From dbefb6fd126c98a9c72d73111f4753e9b69ac12c Mon Sep 17 00:00:00 2001 From: "aicia[bot]" Date: Sun, 3 May 2026 21:59:27 +0200 Subject: [PATCH 01/18] =?UTF-8?q?=F0=9F=92=AC=20Update=20AGENTS.md=20and?= =?UTF-8?q?=20README=20with=20git-story-teller=20and=20Gemini=20Antigravit?= =?UTF-8?q?y=20guidance?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Document 4-way skill sync: repo, Claude install, global agents, Gemini Antigravity - Update git-story-teller description with subagent and complete-read grounding patterns - Clarify package-facing overview and phase-scoped reading in Why section --- AGENTS.md | 12 +++++++----- README.md | 7 +++++-- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 412b412..ef06465 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -47,11 +47,12 @@ Never modify skills maintained by others (e.g. `skill-creator` by Anthropic). If ## Local Install Sync -Repo-managed skills live in three places that must stay in sync: +Repo-managed skills live in four places that must stay in sync: -- `skills//` — source control +- `skills//` — source control (and source of truth for edits) - `~/.claude/skills//` — local Claude install - `~/.agents/skills//` — local global agent install +- `~/.gemini/antigravity/skills//` — local Gemini Antigravity install Changes often start in `~/.claude/skills//`, then get mirrored to the repo and the global install: @@ -67,15 +68,16 @@ Changes often start in `~/.claude/skills//`, then get mirrored to the repo ```powershell Copy-Item "skills//" "$HOME/.claude/skills//" -Force Copy-Item "skills//" "$HOME/.agents/skills//" -Force + Copy-Item "skills//" "$HOME/.gemini/antigravity/skills//" -Force ``` -If you edit the `~/.agents/skills//` copy first, mirror it back to the repo and to `~/.claude/skills//` using the same pattern. +If you edit the `~/.agents/skills//` copy first, mirror it back to the repo and to `~/.claude/skills//` and `~/.gemini/antigravity/skills//` using the same pattern. -When renaming a skill, update **all three** locations — the repo folder, the local Claude install folder, and the local global agent install folder. The folder name and the `name:` field in the SKILL.md frontmatter must match. A mismatch causes the skill to disappear from tooling or show stale instructions. +When renaming a skill, update **all four** locations — the repo folder, the local Claude install folder, the local global agent install folder, and the local Gemini Antigravity install folder. The folder name and the `name:` field in the SKILL.md frontmatter must match. A mismatch causes the skill to disappear from tooling or show stale instructions. A sync mismatch means one side runs a stale version, which leads to confusing eval results and wasted iterations. -After changing any repo-managed skill, sync the touched files across the repo copy, `~/.claude/skills//`, and `~/.agents/skills//` before considering the task done. +After changing any repo-managed skill, sync the touched files across the repo copy, `~/.claude/skills//`, `~/.agents/skills//`, and `~/.gemini/antigravity/skills//` before considering the task done. ## Skill Directory Structure diff --git a/README.md b/README.md index 22e6013..14f35a2 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,7 @@ npx skills add https://github.com/codebeltnet/agentic --skill dotnet-new-lib-sln | [git-visual-squash-summary](skills/git-visual-squash-summary/SKILL.md) | Non-mutating grouped-summary companion to `git-visual-commits`. Turns the full current feature branch into a curated set of compact summary lines for PR or squash-and-merge contexts by default, preserving technical identifiers, merging overlap, dropping low-signal noise, highlighting distinct meaningful efforts, and avoiding changelog-style wording, unsupported claims, needless commit-range questions, or commit-selection UI for ordinary branch-level squash requests. | | [skill-creator-agnostic](skills/skill-creator-agnostic/SKILL.md) | Runner-agnostic overlay for Anthropic `skill-creator`. Adds repo and environment guardrails for skill authoring and benchmarking: temp-workspace isolation, `iteration-N/eval-name/{config}/run-N/` benchmark layout, valid `grading.json` summaries, generated `benchmark.json`, honest `MEASURED` vs `SIMULATED` labeling, and sync/README discipline for repo-managed skills. | | [markdown-illustrator](skills/markdown-illustrator/SKILL.md) | Reads a markdown file and answers directly in chat with one document-wide Visual Brief plus one compiled prompt. Infers a compact visual strategy by default, keeps follow-up questions near zero, and only branches when the user explicitly asks for added specificity. | -| [git-story-teller](skills/git-story-teller/SKILL.md) | Turns any full repository URL into a deterministic story workspace using the bundled .NET file-based runner `scripts/story.cs`. Requires explicit `--repo-url` and `--output-root`, derives `{repo-id}`, fixes `result/`, packs context with local Repomix when available, the public Repomix web API for GitHub URLs when Node/npm is unavailable, or a lower-fidelity built-in .NET fallback as the last resort, writes target contexts plus manifest instructions, then guides the agent to write target stories before `result/Index.md` with a package-facing `## Package selection` overview section. | +| [git-story-teller](skills/git-story-teller/SKILL.md) | Turns any full repository URL into a deterministic story workspace using the bundled .NET file-based runner `scripts/story.cs`. Requires explicit `--repo-url` and `--output-root`, derives `{repo-id}`, fixes `result/`, packs context with local Repomix when available, the public Repomix web API for GitHub URLs when Node/npm is unavailable, or a lower-fidelity built-in .NET fallback as the last resort, writes target contexts plus manifest instructions, then guides the agent to fully read the current phase's required context before writing target stories and `result/Index.md`, optionally using one subagent per independent target context and using completed package stories as the primary source for the package-facing `## Package selection` overview. | | [dotnet-new-lib-slnx](skills/dotnet-new-lib-slnx/SKILL.md) | Scaffold a new .NET NuGet library solution following codebeltnet engineering conventions. Dynamic defaults for TFM/repository metadata, latest-stable NuGet package resolution, tuning projects plus a tooling-based benchmark runner, TFM-aware test environments, strong-name signing, NuGet packaging, DocFX documentation, CI/CD pipeline, and code quality tooling. | | [dotnet-new-app-slnx](skills/dotnet-new-app-slnx/SKILL.md) | Scaffold a new .NET standalone application solution following codebeltnet engineering conventions. Supports Console, Web, and Worker host families with Startup or Minimal hosting patterns; Web expands into Empty Web, Web API, MVC, or Web App / Razor, plus functional tests and a simplified CI pipeline. | | [trunk-first-repo](skills/trunk-first-repo/SKILL.md) | Initialize a git repository following [scaled trunk-based development](https://trunkbaseddevelopment.com/#scaled-trunk-based-development). Seeds an empty `main` branch and creates a versioned feature branch (`v0.1.0/init`), enforcing a PR-first workflow where content only reaches main through peer-reviewed pull requests. | @@ -293,9 +293,12 @@ Repository story generation works best when deterministic context gathering is s - **KISS contract** - only `--repo-url` and `--output-root` are inputs; `{repo-id}` is derived and `result/` is fixed - **Codebelt-flavored default** - recommends `.bot/stories` when the active workspace already contains a `.bot` folder - **Tool output is authoritative** - reads `manifest.json`, `instructions.md`, and one target context at a time instead of reconstructing scope from memory +- **Complete-read grounding** - treats capped or truncated context output as an unfinished read, requiring the agent to continue by chunk or range until the current target context, overview context, and required target stories have been fully inspected +- **Subagent-friendly targets** - when the runtime supports delegation, assigns at most one independent target context to each subagent so large contexts do not compete for the same prompt budget, while the main agent orchestrates, gathers caveats, and authors the final overview - **Target-first workflow** - writes `result/{TargetName}.md` files before synthesizing `result/Index.md` +- **Story-sourced overview** - requires the overview phase to open the completed target story files as the primary source instead of relying on `overview.context.md` alone - **Package-facing overview** - requires `result/Index.md` to use `## Package selection` for the reader-facing selection section -- **Context-budget aware** - processes target contexts separately and uses completed target stories for the overview +- **Phase-scoped reading** - processes target contexts separately and uses completed target stories for the overview without letting token limits justify skipped evidence - **Grounded prose** - forbids invented APIs, relationships, examples, and broad marketing claims unless the generated context supports them - **Publication stays explicit** - leaves staged files in `{output-root}/{repo-id}/result` unless the user asks to sync them into a consuming site ### Why markdown-illustrator? From ff9310e2f82c10926ccfd3b61cb88c50e9c9eeec Mon Sep 17 00:00:00 2001 From: "aicia[bot]" Date: Sun, 3 May 2026 21:59:32 +0200 Subject: [PATCH 02/18] =?UTF-8?q?=F0=9F=93=9D=20Refine=20git-story-teller?= =?UTF-8?q?=20skill=20instructions=20for=20complete-read=20grounding?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Rename 'TARGET STORIES TO READ FIRST' to 'REQUIRED COMPLETED TARGET STORY SOURCES' - Require agent to read completed target stories before overview - Clarify that target stories are primary source, overview context supplementary - Emphasize manifest-ordered reading and result file dependencies - Add grounding rules for overview synthesis from target results --- skills/git-story-teller/SKILL.md | 54 ++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 10 deletions(-) diff --git a/skills/git-story-teller/SKILL.md b/skills/git-story-teller/SKILL.md index 7b934ed..f170d79 100644 --- a/skills/git-story-teller/SKILL.md +++ b/skills/git-story-teller/SKILL.md @@ -1,7 +1,7 @@ --- name: git-story-teller description: > - Generate source-grounded repository story markdown from deterministic ContentSync context bundles. Use when the user asks to create, refresh, or complete repo/package stories, family or project overview pages, .bot/stories output, ContentSync story workflows, or result/Index.md plus result/{TargetName}.md files for any repository URL. The skill runs its bundled .NET file-based context generator, writes target stories first, then writes the overview from completed target stories, and enforces grounding, context-budget, and no-invention rules. + Generate source-grounded repository story markdown from deterministic ContentSync context bundles. Use when the user asks to create, refresh, or complete repo/package stories, family or project overview pages, .bot/stories output, ContentSync story workflows, or result/Index.md plus result/{TargetName}.md files for any repository URL. The skill runs its bundled .NET file-based context generator, writes target stories first, then writes the overview from completed target stories, and enforces complete-read grounding and no-invention rules. --- # Git Story Teller @@ -21,7 +21,11 @@ Use this skill to turn a deterministic story workspace into website-ready or doc - Do not assume GitHub owner, repository host, organization, package prefix, website path, or docs domain from memory. - Do not call an LLM provider from the runner. The calling agent is the brain that writes prose. - Process one target context at a time. Do not load all target contexts into the same prompt unless the generated manifest explicitly requires it. +- When the runtime supports subagents and the manifest has multiple independent target contexts, prefer one subagent per target context. Give each subagent only its assigned target context, `instructions.md`, the relevant manifest entry, and the complete-read contract. Subagents reduce context pressure; they do not reduce grounding requirements. +- Complete reads are mandatory for the files used in the current phase. For a target story, read that target's entire context file before writing. For the overview, read the entire `overview.context.md` and every completed target result file required by the manifest or generated instructions before writing. Chunking is only a way to finish reading a large file; it is not permission to skip sections. +- If a tool caps, truncates, summarizes, or partially displays a required file, continue reading the remaining ranges or use a different file-reading method until the full required file has been inspected. If the full required file cannot be read, stop and report that blocker instead of writing from a subset. - Write target result files before the overview result file. +- For the overview, explicitly read every completed target result file listed by the manifest or `overview.context.md`. Reading only `overview.context.md` is an incomplete overview workflow because the package stories are the primary editorial source. - Do not invent APIs, target relationships, examples, dependencies, support statements, performance claims, or architectural claims not supported by the target context. - If required deterministic files are missing, stale, contradictory, or too large to use safely, stop and report the blocking issue instead of guessing. - Do not copy results into a website or documentation tree unless the user explicitly asks for publication or sync. @@ -139,19 +143,37 @@ If there is no manifest, infer the target list only from `*.context.md` files an For each target in the first phase: 1. Open only that target's context file plus `instructions.md` if needed. -2. Confirm the target result path is `result/{TargetName}.md` or the manifest's declared equivalent. -3. Write the exact required sections from the generated context. -4. Ground API lists and examples in source, tests, project files, README files, or metadata found in the context. -5. Keep examples compact and use real namespaces, type names, method names, and constructor signatures from the context. -6. If the context proves the target is a convenience, aggregate, or metadata-only package with no source of its own, write that honestly instead of inventing APIs. +2. Read the target context file completely before drafting. If the read output is capped or truncated, keep reading the remaining portions until the whole file has been inspected. +3. Confirm the target result path is `result/{TargetName}.md` or the manifest's declared equivalent. +4. Write the exact required sections from the generated context. +5. Ground API lists and examples in source, tests, project files, README files, or metadata found in the context. +6. Keep examples compact and use real namespaces, type names, method names, and constructor signatures from the context. +7. If the context proves the target is a convenience, aggregate, or metadata-only package with no source of its own, write that honestly instead of inventing APIs. Do not use another target's context to fill gaps unless the current context explicitly includes it or the manifest marks that relationship as required. +### Optional Subagent Strategy + +If the agent runtime can delegate work, use subagents to keep each target context isolated and roomy: + +- Spawn at most one subagent per target context from the current target phase. +- Give each subagent a narrow task: completely read its assigned context, follow `instructions.md`, write or draft only its assigned `result/{TargetName}.md`, and report any unreadable or contradictory evidence. +- Do not give one subagent multiple target contexts unless the manifest says those targets are dependent. +- Do not ask a subagent to write `result/Index.md` until all required target result files exist. +- The main agent is the orchestrator and final editor. It gathers each subagent's completed target result file, reported caveats, and validation notes, then authors `result/Index.md` itself from those completed stories plus `overview.context.md`. +- The coordinating agent remains responsible for manifest order, final file placement, overview synthesis, validation, and final reporting. + +Subagent summaries and caveats are useful handoff material for the orchestrator, but they are not a replacement for the completed target result files required by the overview phase. + ### Step 5: Write the Overview Write `result/Index.md` only after target stories exist. -Use the overview context and the completed target result files as the main editorial input. The overview should help readers choose between packages or understand the repository's shape. It should not repeat every target page or amplify unsupported claims. +Open and completely read `overview.context.md` and every completed target result file listed by the manifest or by the generated required target-story source section. Treat the completed target result files as the required package-story source for `result/Index.md`; treat `overview.context.md` as supplementary repository context for relationships, project metadata, README framing, and package inventory. Reading only `overview.context.md` is not sufficient. + +If target stories were produced by subagents, collect their reported caveats and validation notes before drafting the overview. Use those notes to avoid overclaiming, but ground the overview in the completed target result files and `overview.context.md`. + +The overview should help readers choose between packages or understand the repository's shape. It should not repeat every target page or amplify unsupported claims. If any target story is missing, decide from the manifest: @@ -179,12 +201,16 @@ rg -n "robust|seamless|powerful|comprehensive" /result Explain any remaining risk, especially missing tests, ambiguous APIs, oversized context, or targets whose purpose is unclear from source. -## Context Budget Rules +## Complete-Read Rules - Open target contexts one at a time. +- Use subagents for independent target contexts when available so each context can be read completely without competing for the same prompt budget. - Prefer manifest summaries, target result files, and overview context for the overview instead of reopening every target context. -- If a single target context is too large for the active model, split the work by evidence type: project metadata first, public source second, tests third, README last. -- Never silently omit evidence because it is large. State the limitation and use the generated instructions to choose the smallest safe subset. +- For the overview, target result files are compact source material. Read those files directly before writing `Index.md` instead of relying on their path list inside `overview.context.md`. +- Do not treat context limits as permission to sample. The required file set for the current phase must be read completely. +- If a single target context is too large for one tool response, split the read into ranges or sections and continue until the entire file has been inspected. Track where you left off so no section is skipped. +- Use targeted searches only after the complete read, as a validation aid or to revisit specific evidence. Searches do not replace reading the required context. +- If the active model or available tools cannot read the full required file set for the current phase, stop and report the limitation. Do not write a story from a partial context. ## Publication @@ -200,7 +226,10 @@ Do not copy staged results there unless the user asks for website sync, publicat ## Good Output Characteristics - Target pages are concrete, source-backed, and useful to experienced developers. +- Independent target contexts may be handled by separate subagents, with each subagent fully reading one assigned context before drafting. +- Target pages are written only after the full target context has been read, including any portions hidden by capped or truncated tool output. - The overview includes a `## Package selection` section that explains package selection, repository boundaries, and relationships. +- The overview synthesis clearly uses the completed target result files as source material, not just `overview.context.md`. - The writing is restrained and developer-facing, not marketing-heavy. - The agent follows the generated manifest instead of improvising the run order. - The final response names the result files written and any validation gaps. @@ -212,6 +241,11 @@ Do not copy staged results there unless the user asks for website sync, publicat - Passing only a repository slug when the runner requires a full URL. - Assuming a fixed organization such as `codebeltnet` or a fixed repository host such as GitHub. - Loading the entire repository context for every target story. +- Sending multiple unrelated target contexts to the same subagent when they can be processed independently. +- Treating a subagent's summary as a substitute for a completed target result file during overview synthesis. +- Treating capped, truncated, summarized, or partial context output as enough to write from. +- Using context limits, token limits, or "strategic reading" as a reason to skip part of a required target context or overview source file. - Writing `Index.md` before target stories exist. +- Writing `Index.md` after reading only `overview.context.md` and not the completed target result files. - Inventing usage examples from plausible framework patterns rather than supplied source and tests. - Copying staged files into website content without an explicit user request. From 3eaafa6260d5e34a224b18005fd49b2b4ed766df Mon Sep 17 00:00:00 2001 From: "aicia[bot]" Date: Sun, 3 May 2026 21:59:35 +0200 Subject: [PATCH 03/18] =?UTF-8?q?=E2=9C=85=20Add=20evals=20for=20complete-?= =?UTF-8?q?read=20grounding=20and=20subagent-per-target=20patterns?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Refine eval 1-3 expectations: require completed target files as primary source for overview - Add eval 7: test complete-read grounding with capped file output - Add eval 8: test subagent-per-target delegation with independent contexts - Enforce that overview.context.md alone is never sufficient for Index.md - Ensure subagent summaries do not replace completed target result files --- skills/git-story-teller/evals/evals.json | 35 ++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/skills/git-story-teller/evals/evals.json b/skills/git-story-teller/evals/evals.json index 29c02e6..90e5dbe 100644 --- a/skills/git-story-teller/evals/evals.json +++ b/skills/git-story-teller/evals/evals.json @@ -4,12 +4,14 @@ { "id": 1, "prompt": "Use git-story-teller to write target stories and the overview for an existing story workspace at .bot/stories/example-project. The workspace has manifest.json, instructions.md, two target context files, overview.context.md, and an empty result folder.", - "expected_output": "Reads manifest.json and instructions.md first, writes result/{TargetName}.md files before result/Index.md, processes one target context at a time, treats generated output as source of truth, writes the overview with a Package selection section, and reports validation gaps without copying files to a website content tree unless explicitly asked.", + "expected_output": "Reads manifest.json and instructions.md first, writes result/{TargetName}.md files before result/Index.md, processes one target context at a time, treats generated output as source of truth, reads the completed target result files as primary source material for the overview, writes the overview with a Package selection section, and reports validation gaps without copying files to a website content tree unless explicitly asked.", "expectations": [ "Reads manifest.json and instructions.md before writing any result file", "Writes result/{TargetName}.md files before result/Index.md", "Processes one target context file at a time instead of loading all contexts together", + "Reads each required target context completely before writing its result file", "Treats the generated manifest as authoritative for target names, context paths, result paths, and phase order", + "Reads the completed result/{TargetName}.md files before writing result/Index.md instead of relying only on overview.context.md", "Does not invent APIs, namespaces, or capabilities not present in the target context", "Writes result/Index.md with a ## Package selection section and does not use the previous target-oriented heading", "Stops after reporting validation gaps rather than copying result files to a website content tree" @@ -31,11 +33,12 @@ { "id": 3, "prompt": "Use git-story-teller to write result/Index.md from an existing story workspace. The context files and manifest are present but the result folder is empty.", - "expected_output": "Writes all required target result files before writing result/Index.md, using completed target stories as editorial input for the overview and using Package selection as the visible overview section heading.", + "expected_output": "Writes all required target result files before writing result/Index.md, reads those completed target stories as required primary source material for the overview, and uses Package selection as the visible overview section heading.", "expectations": [ "Writes all required target result files before writing result/Index.md", "Does not skip target stories even when the user asks only for the overview", - "Uses the completed target result files as editorial input when writing Index.md", + "Reads each completed target result file as editorial input when writing Index.md", + "Does not treat overview.context.md by itself as sufficient source material for Index.md", "Writes result/Index.md with a ## Package selection section and does not use the previous target-oriented heading", "Names any missing target stories in the response if any cannot be completed before proceeding" ] @@ -74,6 +77,32 @@ "Recognizes the built-in .NET text packer as the last-resort lower-fidelity fallback", "Still treats .NET 10 SDK and git failures as blocking dependencies" ] + }, + { + "id": 7, + "prompt": "Use git-story-teller to write a target story from an existing workspace. The first file-read response for WidgetPack.context.md says the file was capped at 50 KB and only shows the beginning of the context.", + "expected_output": "Continues reading the remaining portions of WidgetPack.context.md until the entire target context has been inspected before writing result/WidgetPack.md. It does not use token limits, context budget, or strategic reading as a reason to skip source sections; if the full file cannot be read, it stops and reports the blocker.", + "expectations": [ + "Treats capped or truncated file output as an incomplete read", + "Continues reading remaining ranges or sections until the whole required target context is inspected", + "Does not write the target story from only the first capped portion of the context file", + "Does not describe strategic source selection as acceptable before the full target context has been read", + "Stops and reports a blocker if the full required target context cannot be read with available tools" + ] + }, + { + "id": 8, + "prompt": "Use git-story-teller to write stories for an existing workspace with manifest.json, instructions.md, and four independent target context files. The agent runtime supports subagents.", + "expected_output": "Uses one subagent per independent target context when practical, gives each subagent only its assigned context plus the relevant instructions and manifest entry, requires each subagent to fully read its assigned context before drafting, writes target result files before result/Index.md, and keeps the main agent responsible as orchestrator and final overview author.", + "expectations": [ + "Prefers one subagent per independent target context when the runtime supports subagents", + "Does not give unrelated target contexts to the same subagent", + "Requires each subagent to completely read its assigned context before drafting the target story", + "Keeps result/Index.md blocked until all required target result files exist", + "Does not treat subagent summaries as a replacement for completed target result files during overview synthesis", + "Requires the main agent to gather completed target stories, subagent caveats, and validation notes before drafting the overview", + "Keeps the coordinating agent responsible for manifest order, overview authorship, validation, and final reporting" + ] } ] } From 09f467d74c0d74a481ba80d4abd9a57453610195 Mon Sep 17 00:00:00 2001 From: "aicia[bot]" Date: Sun, 3 May 2026 21:59:40 +0200 Subject: [PATCH 04/18] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Update=20git-story-t?= =?UTF-8?q?eller=20script=20to=20source=20target=20stories=20in=20overview?= =?UTF-8?q?=20workflow?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add sourceResults list to manifest overview phase entry - Require agent to read all completed target files before Index.md synthesis - Clarify in instructions that target stories are primary source, context file supplementary - Update manifest generation to list target result file paths as required sources - Enforce blocking: overview synthesis requires target results, not context alone --- skills/git-story-teller/scripts/story.cs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/skills/git-story-teller/scripts/story.cs b/skills/git-story-teller/scripts/story.cs index 100f38f..f6f32b7 100644 --- a/skills/git-story-teller/scripts/story.cs +++ b/skills/git-story-teller/scripts/story.cs @@ -371,13 +371,17 @@ private static async Task BuildOverviewContextAsync(string repoUrl, stri sb.AppendLine("Result path: result/Index.md"); sb.AppendLine(); - AppendHeader(sb, "TARGET STORIES TO READ FIRST"); + AppendHeader(sb, "REQUIRED COMPLETED TARGET STORY SOURCES"); if (targets.Count == 0) { sb.AppendLine("No package targets were discovered under src/. Write an overview only if the repository context is sufficient."); } else { + sb.AppendLine("Before writing result/Index.md, open and read every completed target story listed below."); + sb.AppendLine("These completed package stories are the primary source for the overview; this overview context file is only supplementary."); + sb.AppendLine("If your execution log would show only overview.context.md being read for the overview phase, stop and read the target stories first."); + sb.AppendLine(); foreach (var target in targets) { sb.AppendLine($"- {target.Name}: result/{target.Name}.md"); @@ -409,6 +413,8 @@ private static string BuildInstructions(string repoUrl, string repoId) => - Treat `manifest.json` as authoritative for context and result paths. - Process target contexts one at a time. - Write every target result before writing the overview. + - For the overview, read `overview.context.md` and every completed target result file listed by the manifest. + - Treat completed target result files as the primary overview source; `overview.context.md` is supplementary. - Write target stories to `result/{TargetName}.md`. - Write the overview to `result/Index.md`. - Use the generated prompt sections in each `.context.md` file as the task contract. @@ -424,7 +430,7 @@ private static string BuildInstructions(string repoUrl, string repoId) => 1. Read `manifest.json`. 2. Read this file. 3. For each target in the `packages` phase, read its context and write its result file. - 4. Read `overview.context.md` and the completed target result files. + 4. Read `overview.context.md` and every completed target result file listed by the manifest. 5. Write `result/Index.md`. 6. Validate that all manifest result paths exist. """; @@ -582,9 +588,12 @@ private static string BuildOverviewStoryPrompt(string repoId, IReadOnlyList t.result).ToList(), result = "result/Index.md" } }; From 00e25b8a94e383320e03d1d599e2a783d901a3d6 Mon Sep 17 00:00:00 2001 From: "aicia[bot]" Date: Sun, 3 May 2026 22:10:04 +0200 Subject: [PATCH 05/18] =?UTF-8?q?=F0=9F=92=AC=20Enforce=20grounded=20evide?= =?UTF-8?q?nce-based=20language=20in=20git-story-teller?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Clarify that unmeasured frequency claims require explicit context evidence - Add guidance on separating structural evidence from behavioral frequency - Expand checklists to flag 'most common', 'often', 'frequently', 'typical', 'popular' - Provide regex patterns for validating grounded prose in result files - Update README grounded prose rule with concrete examples --- README.md | 2 +- skills/git-story-teller/SKILL.md | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 14f35a2..9b0cdb0 100644 --- a/README.md +++ b/README.md @@ -299,7 +299,7 @@ Repository story generation works best when deterministic context gathering is s - **Story-sourced overview** - requires the overview phase to open the completed target story files as the primary source instead of relying on `overview.context.md` alone - **Package-facing overview** - requires `result/Index.md` to use `## Package selection` for the reader-facing selection section - **Phase-scoped reading** - processes target contexts separately and uses completed target stories for the overview without letting token limits justify skipped evidence -- **Grounded prose** - forbids invented APIs, relationships, examples, and broad marketing claims unless the generated context supports them +- **Grounded prose** - forbids invented APIs, relationships, examples, broad marketing claims, and unmeasured frequency claims such as "most common mistake" unless the generated context supports them with concrete evidence - **Publication stays explicit** - leaves staged files in `{output-root}/{repo-id}/result` unless the user asks to sync them into a consuming site ### Why markdown-illustrator? diff --git a/skills/git-story-teller/SKILL.md b/skills/git-story-teller/SKILL.md index f170d79..c550f19 100644 --- a/skills/git-story-teller/SKILL.md +++ b/skills/git-story-teller/SKILL.md @@ -27,6 +27,7 @@ Use this skill to turn a deterministic story workspace into website-ready or doc - Write target result files before the overview result file. - For the overview, explicitly read every completed target result file listed by the manifest or `overview.context.md`. Reading only `overview.context.md` is an incomplete overview workflow because the package stories are the primary editorial source. - Do not invent APIs, target relationships, examples, dependencies, support statements, performance claims, or architectural claims not supported by the target context. +- Do not turn a source-backed structural risk into an unmeasured behavior claim. Phrases such as "most common mistake", "developers often", "users frequently", "popular choice", "widely used", or "typical failure" require explicit evidence such as package analytics, issue history, docs that say so, telemetry, survey data, or examples in the generated context. Without that evidence, describe the risk conditionally: "If you install X in a project that only needs Y, it adds Z." - If required deterministic files are missing, stale, contradictory, or too large to use safely, stop and report the blocking issue instead of guessing. - Do not copy results into a website or documentation tree unless the user explicitly asks for publication or sync. @@ -175,6 +176,13 @@ If target stories were produced by subagents, collect their reported caveats and The overview should help readers choose between packages or understand the repository's shape. It should not repeat every target page or amplify unsupported claims. +For usage guidance, separate evidence from inference: + +- It is grounded to say a meta-package brings in referenced packages or framework references when the project files show that relationship. +- It is grounded to recommend the smaller package first when the generated instructions ask for "use less" guidance and the package boundaries support that recommendation. +- It is not grounded to call that situation "the most common mistake" or describe actual developer behavior unless the context includes frequency evidence. +- Prefer neutral phrasing such as "Avoid installing the aggregate package when..." or "Choose the aggregate package only when..." over popularity or frequency claims. + If any target story is missing, decide from the manifest: - If the overview depends on all target stories, stop and report the missing files. @@ -191,12 +199,14 @@ Before finishing, verify: - No result file contains analysis notes, citations, XML, JSON, confidence scores, or chat commentary unless the generated prompt explicitly asks for them. - Code examples mention only APIs visible in the relevant context. - Target stories do not make broad claims such as robust, seamless, powerful, or comprehensive unless immediately grounded in concrete evidence. +- Results do not contain unmeasured frequency, popularity, adoption, or mistake-rate claims. Search for wording such as most common, often, frequently, usually, typical, popular, and widely, then keep it only when the context provides evidence for that exact kind of claim. Use targeted searches instead of rereading everything: ```powershell rg -n "TODO|TBD|confidence|citation|analysis notes|I cannot|as an AI" /result rg -n "robust|seamless|powerful|comprehensive" /result +rg -n "most common|often|frequently|usually|typical|popular|widely|many developers|most developers" /result ``` Explain any remaining risk, especially missing tests, ambiguous APIs, oversized context, or targets whose purpose is unclear from source. @@ -230,6 +240,7 @@ Do not copy staged results there unless the user asks for website sync, publicat - Target pages are written only after the full target context has been read, including any portions hidden by capped or truncated tool output. - The overview includes a `## Package selection` section that explains package selection, repository boundaries, and relationships. - The overview synthesis clearly uses the completed target result files as source material, not just `overview.context.md`. +- Tradeoff guidance distinguishes structural evidence from behavioral frequency; it avoids "most common" style claims unless the context includes measurement or explicit source support. - The writing is restrained and developer-facing, not marketing-heavy. - The agent follows the generated manifest instead of improvising the run order. - The final response names the result files written and any validation gaps. @@ -245,6 +256,7 @@ Do not copy staged results there unless the user asks for website sync, publicat - Treating a subagent's summary as a substitute for a completed target result file during overview synthesis. - Treating capped, truncated, summarized, or partial context output as enough to write from. - Using context limits, token limits, or "strategic reading" as a reason to skip part of a required target context or overview source file. +- Claiming a mistake is common, most common, frequent, typical, popular, or widely observed based only on package structure or an inferred best practice. - Writing `Index.md` before target stories exist. - Writing `Index.md` after reading only `overview.context.md` and not the completed target result files. - Inventing usage examples from plausible framework patterns rather than supplied source and tests. From bb1ac58f1c1467a759da6157fc71714fe2385dec Mon Sep 17 00:00:00 2001 From: "aicia[bot]" Date: Sun, 3 May 2026 22:10:07 +0200 Subject: [PATCH 06/18] =?UTF-8?q?=E2=9C=85=20Add=20eval=209=20for=20ground?= =?UTF-8?q?ed=20tradeoff=20guidance=20without=20frequency=20claims?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Test that aggregate package guidance is grounded in dependency structure - Verify no 'most common', 'developers often', 'frequently' claims without evidence - Require neutral language like 'if you only need X, aggregate package adds Y' - Enforce conditional, pragmatic recommendations over inferred behavior --- skills/git-story-teller/evals/evals.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/skills/git-story-teller/evals/evals.json b/skills/git-story-teller/evals/evals.json index 90e5dbe..ab4d40f 100644 --- a/skills/git-story-teller/evals/evals.json +++ b/skills/git-story-teller/evals/evals.json @@ -103,6 +103,18 @@ "Requires the main agent to gather completed target stories, subagent caveats, and validation notes before drafting the overview", "Keeps the coordinating agent responsible for manifest order, overview authorship, validation, and final reporting" ] + }, + { + "id": 9, + "prompt": "Use git-story-teller to write result/Index.md for an existing package workspace. The context proves that an aggregate package transitively references hosting and ASP.NET Core packages, and the overview prompt asks for common mistakes and use-less guidance. The context contains no NuGet analytics, GitHub issue frequency, telemetry, survey data, or docs saying which mistake is most common.", + "expected_output": "Writes grounded use-less guidance without claiming measured developer behavior. It may explain that installing the aggregate package in a project that only needs the base package adds unnecessary references, but it must not call that the most common mistake or say developers often/frequently do it unless the context includes frequency evidence.", + "expectations": [ + "Separates source-backed package dependency evidence from inferred usage guidance", + "Does not use phrases such as most common mistake, developers often, users frequently, typical failure, popular choice, or widely used without explicit frequency evidence", + "Explains the dependency tradeoff conditionally, for example by saying that if a project only needs the base package, the aggregate package adds unnecessary references", + "Does not invent NuGet, GitHub, telemetry, issue, or survey insights", + "Uses neutral recommendation language such as start with the focused package and add layers only when needed" + ] } ] } From 3c5c470a7ddf5253246efb8a96ee2fa70bf4c147 Mon Sep 17 00:00:00 2001 From: "aicia[bot]" Date: Mon, 4 May 2026 00:07:10 +0200 Subject: [PATCH 07/18] =?UTF-8?q?=F0=9F=92=AC=20Update=20README.md=20for?= =?UTF-8?q?=20git-story-teller=20enhancements?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Document full output artifacts including API summaries, engineering signals, chunked context - Expand Why section with public-API-first orientation, signal maps, and complete-read grounding - Highlight improved context navigation for agents with index and chunk files --- README.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 9b0cdb0..cd85d98 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,7 @@ npx skills add https://github.com/codebeltnet/agentic --skill dotnet-new-lib-sln | [git-visual-squash-summary](skills/git-visual-squash-summary/SKILL.md) | Non-mutating grouped-summary companion to `git-visual-commits`. Turns the full current feature branch into a curated set of compact summary lines for PR or squash-and-merge contexts by default, preserving technical identifiers, merging overlap, dropping low-signal noise, highlighting distinct meaningful efforts, and avoiding changelog-style wording, unsupported claims, needless commit-range questions, or commit-selection UI for ordinary branch-level squash requests. | | [skill-creator-agnostic](skills/skill-creator-agnostic/SKILL.md) | Runner-agnostic overlay for Anthropic `skill-creator`. Adds repo and environment guardrails for skill authoring and benchmarking: temp-workspace isolation, `iteration-N/eval-name/{config}/run-N/` benchmark layout, valid `grading.json` summaries, generated `benchmark.json`, honest `MEASURED` vs `SIMULATED` labeling, and sync/README discipline for repo-managed skills. | | [markdown-illustrator](skills/markdown-illustrator/SKILL.md) | Reads a markdown file and answers directly in chat with one document-wide Visual Brief plus one compiled prompt. Infers a compact visual strategy by default, keeps follow-up questions near zero, and only branches when the user explicitly asks for added specificity. | -| [git-story-teller](skills/git-story-teller/SKILL.md) | Turns any full repository URL into a deterministic story workspace using the bundled .NET file-based runner `scripts/story.cs`. Requires explicit `--repo-url` and `--output-root`, derives `{repo-id}`, fixes `result/`, packs context with local Repomix when available, the public Repomix web API for GitHub URLs when Node/npm is unavailable, or a lower-fidelity built-in .NET fallback as the last resort, writes target contexts plus manifest instructions, then guides the agent to fully read the current phase's required context before writing target stories and `result/Index.md`, optionally using one subagent per independent target context and using completed package stories as the primary source for the package-facing `## Package selection` overview. | +| [git-story-teller](skills/git-story-teller/SKILL.md) | Turns any full repository URL into a deterministic story workspace using the bundled .NET file-based runner `scripts/story.cs`. Requires explicit `--repo-url` and `--output-root`, derives `{repo-id}`, fixes `result/`, packs context with local Repomix when available, the public Repomix web API for GitHub URLs when Node/npm is unavailable, or a lower-fidelity built-in .NET fallback as the last resort, writes full contexts plus public API summaries, engineering signals, context indexes, and ordered chunk files, then guides the agent to fully read the current phase's required context before writing target stories and `result/Index.md`, optionally using one subagent per independent target context and using completed package stories as the primary source for the package-facing `## Package selection` overview. | | [dotnet-new-lib-slnx](skills/dotnet-new-lib-slnx/SKILL.md) | Scaffold a new .NET NuGet library solution following codebeltnet engineering conventions. Dynamic defaults for TFM/repository metadata, latest-stable NuGet package resolution, tuning projects plus a tooling-based benchmark runner, TFM-aware test environments, strong-name signing, NuGet packaging, DocFX documentation, CI/CD pipeline, and code quality tooling. | | [dotnet-new-app-slnx](skills/dotnet-new-app-slnx/SKILL.md) | Scaffold a new .NET standalone application solution following codebeltnet engineering conventions. Supports Console, Web, and Worker host families with Startup or Minimal hosting patterns; Web expands into Empty Web, Web API, MVC, or Web App / Razor, plus functional tests and a simplified CI pipeline. | | [trunk-first-repo](skills/trunk-first-repo/SKILL.md) | Initialize a git repository following [scaled trunk-based development](https://trunkbaseddevelopment.com/#scaled-trunk-based-development). Seeds an empty `main` branch and creates a versioned feature branch (`v0.1.0/init`), enforcing a PR-first workflow where content only reaches main through peer-reviewed pull requests. | @@ -283,7 +283,7 @@ Anthropic's `skill-creator` is an excellent base workflow, but the day-to-day fr ### Why git-story-teller? -Repository story generation works best when deterministic context gathering is separated from AI-authored prose. **git-story-teller** owns that split: its bundled .NET file-based runner creates the manifest, instructions, and one context file per target; the agent writes the target stories and overview. +Repository story generation works best when deterministic context gathering is separated from AI-authored prose. **git-story-teller** owns that split: its bundled .NET file-based runner creates the manifest, instructions, full context files, public API summaries, engineering signal maps, context indexes, and ordered chunk files; the agent writes the target stories and overview. - **Bundled C# runner** - ships `scripts/story.cs`, run with `dotnet run --file`, so the skill is self-contained without a full project file - **Repomix-first packing** - uses `npx repomix` for the canonical XML context, ignore handling, token metadata, and security checks when Node/npm access is available @@ -293,7 +293,11 @@ Repository story generation works best when deterministic context gathering is s - **KISS contract** - only `--repo-url` and `--output-root` are inputs; `{repo-id}` is derived and `result/` is fixed - **Codebelt-flavored default** - recommends `.bot/stories` when the active workspace already contains a `.bot` folder - **Tool output is authoritative** - reads `manifest.json`, `instructions.md`, and one target context at a time instead of reconstructing scope from memory -- **Complete-read grounding** - treats capped or truncated context output as an unfinished read, requiring the agent to continue by chunk or range until the current target context, overview context, and required target stories have been fully inspected +- **Public API first** - adds a generated public API summary so agents can orient around consumer-facing types, inheritance chains, and likely key members before reading the raw source +- **Engineering signal map** - highlights source-backed places to inspect for validation guards, lifecycle callbacks, factories, hosting styles, and test evidence so stories can explain the engineering decisions instead of listing APIs mechanically +- **Low-signal filtering** - removes `GlobalSuppressions.cs` from packed context while keeping internals available when they explain public behavior +- **Chunked context navigation** - emits `*.context.index.md` and ordered `*.context.chunks/*.md` files beside each full context so agents can read large evidence sets even when a tool caps single-file output +- **Complete-read grounding** - treats capped or truncated context output as an unfinished read, requiring the agent to use the index and every ordered chunk, or range reads for older workspaces, until the current target context, overview context, and required target stories have been fully inspected - **Subagent-friendly targets** - when the runtime supports delegation, assigns at most one independent target context to each subagent so large contexts do not compete for the same prompt budget, while the main agent orchestrates, gathers caveats, and authors the final overview - **Target-first workflow** - writes `result/{TargetName}.md` files before synthesizing `result/Index.md` - **Story-sourced overview** - requires the overview phase to open the completed target story files as the primary source instead of relying on `overview.context.md` alone From 9d3ac60185fb1bb6209cf0805607095be3a233f4 Mon Sep 17 00:00:00 2001 From: "aicia[bot]" Date: Mon, 4 May 2026 00:07:15 +0200 Subject: [PATCH 08/18] =?UTF-8?q?=F0=9F=93=9D=20Refine=20git-story-teller?= =?UTF-8?q?=20SKILL.md=20for=20complete-read=20grounding?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add complete-read grounding rules with mandatory full-inspection requirements - Document subagent strategy for independent target contexts with strict grounding - Add evidence-based language validation patterns to prevent frequency claims without proof - Expand overview phase rules to require reading all target result files as primary sources - Add regex patterns for detecting unmeasured frequency, popularity, and behavior claims --- skills/git-story-teller/SKILL.md | 52 ++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 13 deletions(-) diff --git a/skills/git-story-teller/SKILL.md b/skills/git-story-teller/SKILL.md index c550f19..e9b72d6 100644 --- a/skills/git-story-teller/SKILL.md +++ b/skills/git-story-teller/SKILL.md @@ -1,7 +1,7 @@ --- name: git-story-teller description: > - Generate source-grounded repository story markdown from deterministic ContentSync context bundles. Use when the user asks to create, refresh, or complete repo/package stories, family or project overview pages, .bot/stories output, ContentSync story workflows, or result/Index.md plus result/{TargetName}.md files for any repository URL. The skill runs its bundled .NET file-based context generator, writes target stories first, then writes the overview from completed target stories, and enforces complete-read grounding and no-invention rules. + Generate source-grounded repository story markdown from deterministic ContentSync context bundles. Use when the user asks to create, refresh, or complete repo/package stories, family or project overview pages, .bot/stories output, ContentSync story workflows, or result/Index.md plus result/{TargetName}.md files for any repository URL. The skill runs its bundled .NET file-based context generator, emits public API and engineering signal summaries plus chunked context indexes, writes target stories first, then writes the overview from completed target stories, and enforces complete-read grounding and no-invention rules even when file output is capped. --- # Git Story Teller @@ -12,7 +12,7 @@ Use this skill to turn a deterministic story workspace into website-ready or doc ## Critical -- Treat generated output as the source of truth. If `manifest.json`, `instructions.md`, or `*.context.md` files disagree with this skill, follow the generated files unless they are internally inconsistent. +- Treat generated output as the source of truth. If `manifest.json`, `instructions.md`, `*.context.md`, `*.context.index.md`, or `*.context.chunks/*.md` files disagree with this skill, follow the generated files unless they are internally inconsistent. - Keep the workflow generic. The runner input is a full repository URL, not an implied owner/slug convention. - Require both `--repo-url` and `--output-root`. Do not invent defaults silently. - If a `.bot` folder exists in the workspace the agent is working from, recommend `/.bot/stories` as the output root. @@ -22,8 +22,11 @@ Use this skill to turn a deterministic story workspace into website-ready or doc - Do not call an LLM provider from the runner. The calling agent is the brain that writes prose. - Process one target context at a time. Do not load all target contexts into the same prompt unless the generated manifest explicitly requires it. - When the runtime supports subagents and the manifest has multiple independent target contexts, prefer one subagent per target context. Give each subagent only its assigned target context, `instructions.md`, the relevant manifest entry, and the complete-read contract. Subagents reduce context pressure; they do not reduce grounding requirements. -- Complete reads are mandatory for the files used in the current phase. For a target story, read that target's entire context file before writing. For the overview, read the entire `overview.context.md` and every completed target result file required by the manifest or generated instructions before writing. Chunking is only a way to finish reading a large file; it is not permission to skip sections. -- If a tool caps, truncates, summarizes, or partially displays a required file, continue reading the remaining ranges or use a different file-reading method until the full required file has been inspected. If the full required file cannot be read, stop and report that blocker instead of writing from a subset. +- Complete reads are mandatory for the files used in the current phase. For a target story, read that target's entire context before writing. For the overview, read the entire overview context and every completed target result file required by the manifest or generated instructions before writing. The generated index and chunks are a safer way to finish reading a large context; they are not permission to skip sections. +- Each generated context has three forms: the full `*.context.md` file, a deterministic `*.context.index.md` navigation file, and ordered raw-evidence chunks under `*.context.chunks/*.md`. +- If a tool caps, truncates, summarizes, or partially displays a required full context file, read its `*.context.index.md` file and then read every chunk listed in numeric order. If the chunk reads are also capped or incomplete, continue by ranges or stop and report the blocker instead of writing from a subset. +- Do not use a context index as evidence for story claims. It is a navigation aid; the full context file or all ordered chunks are the source evidence. +- Target contexts may include generated `PUBLIC API SUMMARY` and `ENGINEERING SIGNALS` sections. Use them to focus attention on likely public types, lifecycle contracts, validation guards, factories, callbacks, and package-boundary clues, but verify every claim against the raw source and tests. - Write target result files before the overview result file. - For the overview, explicitly read every completed target result file listed by the manifest or `overview.context.md`. Reading only `overview.context.md` is an incomplete overview workflow because the package stories are the primary editorial source. - Do not invent APIs, target relationships, examples, dependencies, support statements, performance claims, or architectural claims not supported by the target context. @@ -66,6 +69,7 @@ Fallback notes: - The Repomix web API fallback posts the repository URL, output format, and include patterns to `https://api.repomix.com/api/pack`; use it only for public GitHub repositories or repositories the user is comfortable sending to that service. - The built-in .NET fallback is local-only and packs only files matching the runner's include patterns. - The built-in .NET fallback does not provide Repomix token counts, Secretlint checks, compression, or exact gitignore semantics. +- The runner filters known low-signal files such as `GlobalSuppressions.cs` from packed context. Do not recreate or infer story claims from those files. - If `.NET 10` or `git` is unavailable, stop and report the missing dependency. - If Repomix runs and rejects content, do not bypass that result manually with a fallback unless the user explicitly accepts the lower-fidelity path. @@ -86,13 +90,21 @@ Generated shape: manifest.json instructions.md overview.context.md + overview.context.index.md + overview.context.chunks/ + 0001.md + 0002.md {TargetName}.context.md + {TargetName}.context.index.md + {TargetName}.context.chunks/ + 0001.md + 0002.md result/ Index.md {TargetName}.md ``` -The manifest is authoritative after generation. Always follow the manifest for concrete target names, context paths, result paths, and phase order. +The manifest is authoritative after generation. Always follow the manifest for concrete target names, full context paths, context index paths, context chunk paths, result paths, and phase order. ## Workflow @@ -134,6 +146,8 @@ From `manifest.json`, identify: - target phase entries - overview phase entry - each context file path +- each context index path +- each ordered context chunk path - each result file path - dependency order @@ -143,13 +157,15 @@ If there is no manifest, infer the target list only from `*.context.md` files an For each target in the first phase: -1. Open only that target's context file plus `instructions.md` if needed. -2. Read the target context file completely before drafting. If the read output is capped or truncated, keep reading the remaining portions until the whole file has been inspected. +1. Open only that target's context artifacts plus `instructions.md` if needed. +2. Try to read the target context file completely. If the read output is capped or truncated, open the manifest-declared context index and then read every manifest-declared chunk in numeric order until the whole context has been inspected. 3. Confirm the target result path is `result/{TargetName}.md` or the manifest's declared equivalent. 4. Write the exact required sections from the generated context. 5. Ground API lists and examples in source, tests, project files, README files, or metadata found in the context. -6. Keep examples compact and use real namespaces, type names, method names, and constructor signatures from the context. -7. If the context proves the target is a convenience, aggregate, or metadata-only package with no source of its own, write that honestly instead of inventing APIs. +6. Use generated summaries and engineering signals to revisit likely design invariants, lifecycle contracts, callback wiring, factory boundaries, generic type constraints, exception guards, and package-boundary decisions in the raw source. +7. Do not document non-public members as APIs, but do inspect internal implementation when it explains public lifecycle behavior, validation, callback flow, or package boundaries. +8. Keep examples compact and use real namespaces, type names, method names, and constructor signatures from the context. +9. If the context proves the target is a convenience, aggregate, or metadata-only package with no source of its own, write that honestly instead of inventing APIs. Do not use another target's context to fill gaps unless the current context explicitly includes it or the manifest marks that relationship as required. @@ -158,7 +174,7 @@ Do not use another target's context to fill gaps unless the current context expl If the agent runtime can delegate work, use subagents to keep each target context isolated and roomy: - Spawn at most one subagent per target context from the current target phase. -- Give each subagent a narrow task: completely read its assigned context, follow `instructions.md`, write or draft only its assigned `result/{TargetName}.md`, and report any unreadable or contradictory evidence. +- Give each subagent a narrow task: completely read its assigned context, using the context index and ordered chunks if the full file is capped, follow `instructions.md`, write or draft only its assigned `result/{TargetName}.md`, and report any unreadable or contradictory evidence. - Do not give one subagent multiple target contexts unless the manifest says those targets are dependent. - Do not ask a subagent to write `result/Index.md` until all required target result files exist. - The main agent is the orchestrator and final editor. It gathers each subagent's completed target result file, reported caveats, and validation notes, then authors `result/Index.md` itself from those completed stories plus `overview.context.md`. @@ -170,7 +186,7 @@ Subagent summaries and caveats are useful handoff material for the orchestrator, Write `result/Index.md` only after target stories exist. -Open and completely read `overview.context.md` and every completed target result file listed by the manifest or by the generated required target-story source section. Treat the completed target result files as the required package-story source for `result/Index.md`; treat `overview.context.md` as supplementary repository context for relationships, project metadata, README framing, and package inventory. Reading only `overview.context.md` is not sufficient. +Open and completely read `overview.context.md`, or the overview context index plus every ordered overview chunk if the full file is capped, and every completed target result file listed by the manifest or by the generated required target-story source section. Treat the completed target result files as the required package-story source for `result/Index.md`; treat `overview.context.md` or its chunks as supplementary repository context for relationships, project metadata, README framing, and package inventory. Reading only `overview.context.md` is not sufficient when target result files exist. If target stories were produced by subagents, collect their reported caveats and validation notes before drafting the overview. Use those notes to avoid overclaiming, but ground the overview in the completed target result files and `overview.context.md`. @@ -195,9 +211,11 @@ Before finishing, verify: - Every manifest target has a corresponding result file. - `result/Index.md` exists when the manifest includes an overview target. - Result filenames match manifest paths. +- Context index and chunk paths in the manifest exist for every generated context. - Required headings from the generated context are present verbatim. - No result file contains analysis notes, citations, XML, JSON, confidence scores, or chat commentary unless the generated prompt explicitly asks for them. - Code examples mention only APIs visible in the relevant context. +- Public API and engineering-depth claims are verified against source or tests, not copied from generated summaries alone. - Target stories do not make broad claims such as robust, seamless, powerful, or comprehensive unless immediately grounded in concrete evidence. - Results do not contain unmeasured frequency, popularity, adoption, or mistake-rate claims. Search for wording such as most common, often, frequently, usually, typical, popular, and widely, then keep it only when the context provides evidence for that exact kind of claim. @@ -218,7 +236,9 @@ Explain any remaining risk, especially missing tests, ambiguous APIs, oversized - Prefer manifest summaries, target result files, and overview context for the overview instead of reopening every target context. - For the overview, target result files are compact source material. Read those files directly before writing `Index.md` instead of relying on their path list inside `overview.context.md`. - Do not treat context limits as permission to sample. The required file set for the current phase must be read completely. -- If a single target context is too large for one tool response, split the read into ranges or sections and continue until the entire file has been inspected. Track where you left off so no section is skipped. +- If a single target context is too large for one tool response, prefer the manifest-declared `*.context.index.md` file plus every ordered file under `*.context.chunks/`. If chunks are unavailable in an older workspace, split the full context read into ranges or sections and continue until the entire file has been inspected. Track where you left off so no section is skipped. +- Treat `*.context.index.md` as a table of contents, not as source evidence. It can tell you which chunks and packed files exist, but story claims must come from the full context file or the complete ordered chunk set. +- Treat generated public API summaries and engineering signals the same way: they identify where to look, but they do not replace source, tests, project files, README files, or metadata as grounding. - Use targeted searches only after the complete read, as a validation aid or to revisit specific evidence. Searches do not replace reading the required context. - If the active model or available tools cannot read the full required file set for the current phase, stop and report the limitation. Do not write a story from a partial context. @@ -237,7 +257,10 @@ Do not copy staged results there unless the user asks for website sync, publicat - Target pages are concrete, source-backed, and useful to experienced developers. - Independent target contexts may be handled by separate subagents, with each subagent fully reading one assigned context before drafting. -- Target pages are written only after the full target context has been read, including any portions hidden by capped or truncated tool output. +- Target pages are written only after the full target context has been read, either directly or through the complete ordered chunk set, including any portions hidden by capped or truncated tool output. +- Context indexes are used to plan reading and verify chunk coverage, not as a replacement for source evidence. +- Public API summaries and engineering signals help the agent notice fine-grained library design, but every final claim is still backed by raw context. +- Non-public implementation details are used only to explain public behavior, not listed as consumer APIs. - The overview includes a `## Package selection` section that explains package selection, repository boundaries, and relationships. - The overview synthesis clearly uses the completed target result files as source material, not just `overview.context.md`. - Tradeoff guidance distinguishes structural evidence from behavioral frequency; it avoids "most common" style claims unless the context includes measurement or explicit source support. @@ -255,6 +278,9 @@ Do not copy staged results there unless the user asks for website sync, publicat - Sending multiple unrelated target contexts to the same subagent when they can be processed independently. - Treating a subagent's summary as a substitute for a completed target result file during overview synthesis. - Treating capped, truncated, summarized, or partial context output as enough to write from. +- Treating `*.context.index.md` as a summary that can replace reading the full context or every chunk. +- Treating generated public API summaries or engineering signals as final evidence instead of prompts for source-backed inspection. +- Reading only the first few chunks because the index looked sufficient. - Using context limits, token limits, or "strategic reading" as a reason to skip part of a required target context or overview source file. - Claiming a mistake is common, most common, frequent, typical, popular, or widely observed based only on package structure or an inferred best practice. - Writing `Index.md` before target stories exist. From bd8afd8ecc28a582cc7439e0383893e0461c6209 Mon Sep 17 00:00:00 2001 From: "aicia[bot]" Date: Mon, 4 May 2026 00:07:21 +0200 Subject: [PATCH 09/18] =?UTF-8?q?=E2=9C=85=20Enhance=20evals=20for=20compl?= =?UTF-8?q?ete-read=20grounding=20patterns?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Refine evals 1-3 to require completed target files as primary source for overview - Add eval 7 testing complete-read grounding with capped file output - Add eval 8 testing subagent-per-target delegation with independent contexts - Add eval 9 for grounded tradeoff guidance without unmeasured frequency claims - Enforce that overview synthesis requires target results, not context alone --- skills/git-story-teller/evals/evals.json | 28 +++++++++++++++++++----- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/skills/git-story-teller/evals/evals.json b/skills/git-story-teller/evals/evals.json index ab4d40f..1805d76 100644 --- a/skills/git-story-teller/evals/evals.json +++ b/skills/git-story-teller/evals/evals.json @@ -3,13 +3,14 @@ "evals": [ { "id": 1, - "prompt": "Use git-story-teller to write target stories and the overview for an existing story workspace at .bot/stories/example-project. The workspace has manifest.json, instructions.md, two target context files, overview.context.md, and an empty result folder.", - "expected_output": "Reads manifest.json and instructions.md first, writes result/{TargetName}.md files before result/Index.md, processes one target context at a time, treats generated output as source of truth, reads the completed target result files as primary source material for the overview, writes the overview with a Package selection section, and reports validation gaps without copying files to a website content tree unless explicitly asked.", + "prompt": "Use git-story-teller to write target stories and the overview for an existing story workspace at .bot/stories/example-project. The workspace has manifest.json, instructions.md, two target context files with context indexes and chunk directories, overview.context.md, and an empty result folder.", + "expected_output": "Reads manifest.json and instructions.md first, writes result/{TargetName}.md files before result/Index.md, processes one target context at a time, treats generated output as source of truth, uses manifest-declared context indexes and chunks when a full context read is capped, reads the completed target result files as primary source material for the overview, writes the overview with a Package selection section, and reports validation gaps without copying files to a website content tree unless explicitly asked.", "expectations": [ "Reads manifest.json and instructions.md before writing any result file", "Writes result/{TargetName}.md files before result/Index.md", "Processes one target context file at a time instead of loading all contexts together", "Reads each required target context completely before writing its result file", + "Uses the manifest-declared context index and ordered context chunks when a full context file cannot be read completely", "Treats the generated manifest as authoritative for target names, context paths, result paths, and phase order", "Reads the completed result/{TargetName}.md files before writing result/Index.md instead of relying only on overview.context.md", "Does not invent APIs, namespaces, or capabilities not present in the target context", @@ -20,13 +21,14 @@ { "id": 2, "prompt": "Use git-story-teller to generate a story workspace for https://github.com/example/myproject and then write the resulting stories. The active workspace contains a .bot folder.", - "expected_output": "Recommends .bot/stories as the output root, runs dotnet run --file with --repo-url and the full URL and --output-root, does not ask for repo-id or result directory, avoids LLM options, then follows the generated manifest to write target stories before result/Index.md.", + "expected_output": "Recommends .bot/stories as the output root, runs dotnet run --file with --repo-url and the full URL and --output-root, does not ask for repo-id or result directory, avoids LLM options, then follows the generated manifest, including contextIndex and contextChunks entries, to write target stories before result/Index.md.", "expectations": [ "Recommends .bot/stories as the output root because a .bot folder exists in the workspace", "Runs dotnet run --file /scripts/story.cs with --repo-url and --output-root", "Passes the full repository URL, not a slug or partial reference", "Does not ask the user for repo-id or result directory", "Does not pass provider, model, or LLM flags to the runner", + "Recognizes that the generated manifest can include contextIndex and contextChunks entries for capped context reads", "Follows the generated manifest after the runner completes to write target stories before Index.md" ] }, @@ -81,13 +83,15 @@ { "id": 7, "prompt": "Use git-story-teller to write a target story from an existing workspace. The first file-read response for WidgetPack.context.md says the file was capped at 50 KB and only shows the beginning of the context.", - "expected_output": "Continues reading the remaining portions of WidgetPack.context.md until the entire target context has been inspected before writing result/WidgetPack.md. It does not use token limits, context budget, or strategic reading as a reason to skip source sections; if the full file cannot be read, it stops and reports the blocker.", + "expected_output": "Uses the manifest-declared WidgetPack.context.index.md and every ordered file under WidgetPack.context.chunks/ to inspect the full target context before writing result/WidgetPack.md. It does not treat the index as source evidence, and it does not use token limits, context budget, or strategic reading as a reason to skip source sections; if the chunks cannot be read completely, it stops and reports the blocker.", "expectations": [ "Treats capped or truncated file output as an incomplete read", - "Continues reading remaining ranges or sections until the whole required target context is inspected", + "Reads the manifest-declared context index to find the ordered chunk list", + "Reads every context chunk in numeric order until the whole required target context is inspected", + "Does not treat the context index as a substitute for raw source evidence", "Does not write the target story from only the first capped portion of the context file", "Does not describe strategic source selection as acceptable before the full target context has been read", - "Stops and reports a blocker if the full required target context cannot be read with available tools" + "Stops and reports a blocker if the full required target context cannot be read from the full file or complete chunk set" ] }, { @@ -115,6 +119,18 @@ "Does not invent NuGet, GitHub, telemetry, issue, or survey insights", "Uses neutral recommendation language such as start with the focused package and add layers only when needed" ] + }, + { + "id": 10, + "prompt": "Use git-story-teller to generate and write stories for a library workspace whose source contains public classes, internal helper classes, callback-based lifecycle wiring, tests for exception guards, and a GlobalSuppressions.cs file.", + "expected_output": "Uses generated public API summaries and engineering signals to focus source inspection, filters GlobalSuppressions.cs from packed context, does not list internal helpers as consumer APIs, but uses internal implementation details only when they explain public lifecycle behavior, validation guards, callback flow, or package boundaries.", + "expectations": [ + "Recognizes PUBLIC API SUMMARY and ENGINEERING SIGNALS sections as navigation aids rather than final evidence", + "Verifies public API and engineering-depth claims against raw source or tests before writing", + "Does not document internal helper classes as public consumer APIs", + "Uses internal implementation details only to explain public behavior such as lifecycle, validation, callback flow, or package boundaries", + "Excludes GlobalSuppressions.cs from packed context instead of spending story budget on suppression metadata" + ] } ] } From 0a933c72e150b32890ed5079c1bfe918d26f2ecb Mon Sep 17 00:00:00 2001 From: "aicia[bot]" Date: Mon, 4 May 2026 00:07:26 +0200 Subject: [PATCH 10/18] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Update=20story.cs=20?= =?UTF-8?q?to=20emit=20enhanced=20output=20artifacts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add public API summary generation for consumer-facing types and inheritance chains - Implement engineering signal map highlighting validation guards, factories, and test evidence - Add low-signal filtering to remove GlobalSuppressions.cs from context - Generate *.context.index.md and ordered *.context.chunks/*.md files for robust navigation - Support chunked context reading when tools cap single-file output - Refine manifest generation with sourceResults for overview phase dependencies --- skills/git-story-teller/scripts/story.cs | 613 ++++++++++++++++++++++- 1 file changed, 597 insertions(+), 16 deletions(-) diff --git a/skills/git-story-teller/scripts/story.cs b/skills/git-story-teller/scripts/story.cs index f6f32b7..3af7713 100644 --- a/skills/git-story-teller/scripts/story.cs +++ b/skills/git-story-teller/scripts/story.cs @@ -15,6 +15,7 @@ internal static class StoryScript { private const string ResultDirectoryName = "result"; + private const int MaxContextChunkBodyBytes = 36 * 1024; public static async Task RunAsync(string[] args) { @@ -56,18 +57,20 @@ public static async Task RunAsync(string[] args) var contextFileName = target.Name + ".context.md"; var resultPath = Path.Combine(ResultDirectoryName, target.Name + ".md").Replace('\\', '/'); var context = await BuildTargetContextAsync(options.RepoUrl, cloneDir, target); - await WriteUtf8Async(Path.Combine(workspace, contextFileName), context); + var contextArtifacts = await WriteContextArtifactsAsync(workspace, contextFileName, context); targetEntries.Add(new TargetManifestEntry( "package", target.Name, - contextFileName, + contextArtifacts.ContextPath, + contextArtifacts.IndexPath, + contextArtifacts.ChunkPaths, resultPath)); } var overviewContextName = "overview.context.md"; var overviewContext = await BuildOverviewContextAsync(options.RepoUrl, cloneDir, repoId, targets); - await WriteUtf8Async(Path.Combine(workspace, overviewContextName), overviewContext); + var overviewArtifacts = await WriteContextArtifactsAsync(workspace, overviewContextName, overviewContext); await WriteUtf8Async(Path.Combine(workspace, "instructions.md"), BuildInstructions(options.RepoUrl, repoId)); await WriteManifestAsync( @@ -76,7 +79,7 @@ await WriteManifestAsync( repoId, workspace, targetEntries, - overviewContextName); + overviewArtifacts); Console.WriteLine(); Console.WriteLine("[story] deterministic workspace written:"); @@ -348,6 +351,12 @@ private static async Task BuildTargetContextAsync(string repoUrl, string sb.AppendLine(); } + AppendHeader(sb, "PUBLIC API SUMMARY (GENERATED)"); + AppendMultiline(sb, BuildPublicApiSummary(cloneDir, target)); + + AppendHeader(sb, "ENGINEERING SIGNALS (GENERATED)"); + AppendMultiline(sb, BuildEngineeringSignals(cloneDir, target)); + AppendHeader(sb, "PACKAGE STORY PROMPT"); AppendMultiline(sb, BuildPackageStoryPrompt(target.Name)); @@ -399,6 +408,257 @@ private static async Task BuildOverviewContextAsync(string repoUrl, stri return sb.ToString(); } + private static string BuildPublicApiSummary(string cloneDir, TargetInfo target) + { + var discoveredApiTypes = DiscoverPublicApiTypes(cloneDir, target); + var apiTypes = discoveredApiTypes.Take(20).ToList(); + if (apiTypes.Count == 0) + { + return "No public or protected API candidates were discovered by the lightweight source scanner. Treat the packed source context as authoritative."; + } + + var sb = new StringBuilder(); + sb.AppendLine("This section is a deterministic navigation aid extracted from source text. Use it to focus the complete read, but treat the packed source context below as authoritative."); + sb.AppendLine(); + sb.AppendLine("| Type | Kind | Inherits / implements | Public or protected member candidates | Source |"); + sb.AppendLine("|---|---|---|---|---|"); + foreach (var apiType in apiTypes) + { + var members = apiType.Members.Count == 0 + ? "(none discovered)" + : string.Join("
", apiType.Members.Take(6).Select(EscapeMarkdownTableCell)); + + sb.AppendLine($"| `{EscapeMarkdownTableCell(apiType.Name)}` | {EscapeMarkdownTableCell(apiType.Kind)} | {EscapeMarkdownTableCell(apiType.BaseTypes)} | {members} | `{EscapeMarkdownTableCell(apiType.SourcePath)}` |"); + } + + if (discoveredApiTypes.Count > apiTypes.Count) + { + sb.AppendLine(); + sb.AppendLine($"Only the first {apiTypes.Count} of {discoveredApiTypes.Count} API candidates are shown. Read the packed source context for the full surface."); + } + + return sb.ToString(); + } + + private static IReadOnlyList DiscoverPublicApiTypes(string cloneDir, TargetInfo target) + { + var sourceDir = Path.Combine(cloneDir, target.SourcePath.Replace('/', Path.DirectorySeparatorChar)); + if (!Directory.Exists(sourceDir)) + { + return []; + } + + var sourceFiles = Directory.EnumerateFiles(sourceDir, "*.cs", SearchOption.AllDirectories) + .Where(p => !IsUnderDirectoryName(p, "bin") && !IsUnderDirectoryName(p, "obj")) + .Where(p => !ShouldSkipLowSignalFile(Path.GetRelativePath(cloneDir, p).Replace('\\', '/'))) + .OrderBy(p => Path.GetRelativePath(cloneDir, p), StringComparer.OrdinalIgnoreCase) + .ToList(); + + var summaries = new List(); + foreach (var sourceFile in sourceFiles) + { + var text = File.ReadAllText(sourceFile, Encoding.UTF8); + var relativePath = Path.GetRelativePath(cloneDir, sourceFile).Replace('\\', '/'); + foreach (Match match in PublicTypeRegex().Matches(text)) + { + var name = NormalizeDeclaration(match.Groups["name"].Value); + var kind = NormalizeDeclaration(match.Groups["kind"].Value); + var baseTypes = NormalizeDeclaration(match.Groups["base"].Success ? match.Groups["base"].Value : string.Empty); + if (string.IsNullOrWhiteSpace(baseTypes)) + { + baseTypes = "(none declared)"; + } + + var body = TryExtractTypeBody(text, match.Index); + var members = body is null + ? Array.Empty() + : ExtractPublicMemberCandidates(body, GetSimpleTypeName(name)).Take(8).ToArray(); + + summaries.Add(new ApiTypeSummary(name, kind, baseTypes, members, relativePath)); + } + } + + return summaries + .OrderBy(s => s.SourcePath, StringComparer.OrdinalIgnoreCase) + .ThenBy(s => s.Name, StringComparer.OrdinalIgnoreCase) + .ToList(); + } + + private static string BuildEngineeringSignals(string cloneDir, TargetInfo target) + { + var files = EnumerateSignalFiles(cloneDir, target).ToList(); + var exceptionSignals = FindSignals(files, @"(?:throw\s+new|Assert\.Throws(?:Async)?)\s* IsProbablyTestFile(f.RelativePath)) + .Select(f => f.RelativePath) + .Distinct(StringComparer.OrdinalIgnoreCase) + .OrderBy(p => p, StringComparer.OrdinalIgnoreCase) + .Take(12) + .ToList(); + + var sb = new StringBuilder(); + sb.AppendLine("This section is a deterministic signal map. It highlights places where the code may reveal design invariants, lifecycle contracts, package boundaries, or test-backed behavior. Validate every claim against the raw source context before writing."); + sb.AppendLine(); + + AppendSignalGroup(sb, "Exception guards and validation evidence", exceptionSignals); + AppendSignalGroup(sb, "Lifecycle, callback, factory, and composition names", lifecycleSignals); + AppendSignalGroup(sb, "Hosting model markers", hostingSignals); + + sb.AppendLine("### Test evidence files"); + if (testSignals.Count == 0) + { + sb.AppendLine("- No test files were discovered for this target."); + } + else + { + foreach (var path in testSignals) + { + sb.AppendLine("- `" + path + "`"); + } + } + + return sb.ToString(); + } + + private static IEnumerable EnumerateSignalFiles(string cloneDir, TargetInfo target) + { + var roots = new[] { target.SourcePath, target.TestPath } + .Where(p => !string.IsNullOrWhiteSpace(p)) + .Select(p => Path.Combine(cloneDir, p!.Replace('/', Path.DirectorySeparatorChar))) + .Where(Directory.Exists) + .Distinct(StringComparer.OrdinalIgnoreCase); + + foreach (var root in roots) + { + foreach (var file in Directory.EnumerateFiles(root, "*.cs", SearchOption.AllDirectories) + .Where(p => !IsUnderDirectoryName(p, "bin") && !IsUnderDirectoryName(p, "obj")) + .Where(p => !ShouldSkipLowSignalFile(Path.GetRelativePath(cloneDir, p).Replace('\\', '/'))) + .OrderBy(p => Path.GetRelativePath(cloneDir, p), StringComparer.OrdinalIgnoreCase)) + { + yield return new SignalFile( + Path.GetRelativePath(cloneDir, file).Replace('\\', '/'), + File.ReadAllText(file, Encoding.UTF8)); + } + } + } + + private static IEnumerable FindSignals(IEnumerable files, string pattern, string kind) + { + var seen = new HashSet(StringComparer.OrdinalIgnoreCase); + foreach (var file in files) + { + foreach (Match match in Regex.Matches(file.Content, pattern, RegexOptions.Multiline)) + { + var value = match.Groups.Count > 1 && match.Groups[1].Success + ? match.Groups[1].Value + : match.Value; + value = NormalizeDeclaration(value); + if (string.IsNullOrWhiteSpace(value)) + { + continue; + } + + var key = file.RelativePath + "|" + value; + if (!seen.Add(key)) + { + continue; + } + + yield return new EngineeringSignal(kind, value, file.RelativePath); + } + } + } + + private static void AppendSignalGroup(StringBuilder sb, string heading, IReadOnlyList signals) + { + sb.AppendLine("### " + heading); + if (signals.Count == 0) + { + sb.AppendLine("- None discovered by the lightweight scanner."); + sb.AppendLine(); + return; + } + + foreach (var signal in signals) + { + sb.AppendLine($"- `{signal.Value}` in `{signal.SourcePath}`"); + } + sb.AppendLine(); + } + + private static string? TryExtractTypeBody(string text, int typeStartIndex) + { + var openBrace = text.IndexOf('{', typeStartIndex); + if (openBrace < 0) + { + return null; + } + + var depth = 0; + for (var i = openBrace; i < text.Length; i++) + { + if (text[i] == '{') + { + depth++; + } + else if (text[i] == '}') + { + depth--; + if (depth == 0) + { + return text[(openBrace + 1)..i]; + } + } + } + + return null; + } + + private static IEnumerable ExtractPublicMemberCandidates(string body, string simpleTypeName) + { + var members = new List(); + foreach (Match match in PublicMemberRegex().Matches(body)) + { + var declaration = NormalizeDeclaration(match.Groups["decl"].Value); + if (string.IsNullOrWhiteSpace(declaration)) + { + continue; + } + + if (declaration.Contains(" class ", StringComparison.Ordinal) + || declaration.Contains(" interface ", StringComparison.Ordinal) + || declaration.Contains(" struct ", StringComparison.Ordinal) + || declaration.Contains(" record ", StringComparison.Ordinal)) + { + continue; + } + + members.Add(declaration); + } + + return members + .Distinct(StringComparer.OrdinalIgnoreCase) + .OrderByDescending(m => m.Contains(simpleTypeName + "(", StringComparison.Ordinal)) + .ThenBy(m => m, StringComparer.OrdinalIgnoreCase); + } + + private static string NormalizeDeclaration(string value) => + Regex.Replace(value.ReplaceLineEndings(" "), @"\s+", " ").Trim().TrimEnd('{', ';').Trim(); + + private static string GetSimpleTypeName(string name) + { + var index = name.IndexOf('<', StringComparison.Ordinal); + return index >= 0 ? name[..index] : name; + } + + private static bool IsProbablyTestFile(string relativePath) => + relativePath.Contains(".Tests/", StringComparison.OrdinalIgnoreCase) + || relativePath.Contains("/Tests/", StringComparison.OrdinalIgnoreCase) + || relativePath.EndsWith("Test.cs", StringComparison.OrdinalIgnoreCase) + || relativePath.EndsWith("Tests.cs", StringComparison.OrdinalIgnoreCase); + private static string BuildInstructions(string repoUrl, string repoId) => $$""" # Story Writing Instructions @@ -413,11 +673,15 @@ private static string BuildInstructions(string repoUrl, string repoId) => - Treat `manifest.json` as authoritative for context and result paths. - Process target contexts one at a time. - Write every target result before writing the overview. - - For the overview, read `overview.context.md` and every completed target result file listed by the manifest. + - Each context has a full `*.context.md` file, a `*.context.index.md` navigation file, and ordered `*.context.chunks/*.md` raw-evidence chunks. + - If the full context file is capped, truncated, summarized, or too large to read safely, read the index and then every listed chunk in numeric order. + - Do not treat an index file as source evidence. It helps navigation only. + - Do not treat generated public API summaries or engineering signals as standalone evidence. They help you decide what to inspect in the raw context. + - For the overview, read `overview.context.md` or every overview chunk, then read every completed target result file listed by the manifest. - Treat completed target result files as the primary overview source; `overview.context.md` is supplementary. - Write target stories to `result/{TargetName}.md`. - Write the overview to `result/Index.md`. - - Use the generated prompt sections in each `.context.md` file as the task contract. + - Use the generated prompt sections in each `.context.md` file or its ordered chunks as the task contract. - Do not invent APIs, package relationships, examples, dependencies, support statements, performance claims, or architectural claims. - If context is missing, stale, contradictory, or too large to use safely, stop and report the blocker. @@ -429,10 +693,11 @@ private static string BuildInstructions(string repoUrl, string repoId) => 1. Read `manifest.json`. 2. Read this file. - 3. For each target in the `packages` phase, read its context and write its result file. - 4. Read `overview.context.md` and every completed target result file listed by the manifest. - 5. Write `result/Index.md`. - 6. Validate that all manifest result paths exist. + 3. For each target in the `packages` phase, read its context directly if possible; otherwise read its context index and then all chunks in order. + 4. Write each target result file only after its full raw context has been inspected. + 5. Read `overview.context.md` or every overview chunk, then read every completed target result file listed by the manifest. + 6. Write `result/Index.md`. + 7. Validate that all manifest result paths exist. """; private static string BuildSharedEditorialRules() => @@ -502,12 +767,21 @@ Ignore internal implementation details unless they explain the public API. Prefer public types, extension methods, options/configuration types, factories, abstractions, and test-visible usage patterns. If the package has obsolete or deprecated APIs, do not present them as the recommended path. If the package is metadata-only, aggregate, or convenience-only, say that clearly and do not invent public APIs. + The generated public API summary and engineering signals are reading aids, not final evidence. Validate them against the packed source and tests before turning them into claims. + + Engineering depth requirements: + Look for design invariants, lifecycle contracts, callback wiring, factory boundaries, generic type constraints, exception guards, and test-backed edge cases. + Explain a non-obvious design choice only when the source or tests make it visible. + For each important API, prefer the useful engineering detail over a generic description: inheritance chain, why a generic parameter exists, what lifecycle it participates in, or what contract a consumer must respect. + Name what the package deliberately does not solve when package boundaries, dependencies, or sibling packages make that clear. + If generated context appears to pair the target with surprising or weak test evidence, report that as a confidence risk instead of smoothing it over. Before writing the final page, internally identify: - the package's specific responsibility inside the repository - the primary developer scenario - the 3-5 public types that matter most to consumers - the most representative usage pattern found in tests + - the design invariants, lifecycle contracts, or guardrails that matter to consumers - what this package deliberately does not solve - any confidence risks caused by missing tests or unclear source @@ -615,6 +889,7 @@ Keep the overview focused on how developers should understand and choose between - convenience or meta packages, if any exist - the recommended starting point - scenarios where installing or using less is better + - recurring engineering patterns across packages, such as classic versus minimal hosting styles, shared fixture lifecycles, or layered package boundaries, when visible in the evidence - the one non-obvious insight developers should understand Write exactly these three sections. @@ -679,11 +954,233 @@ private static void AppendMultiline(StringBuilder sb, string value) sb.AppendLine(); } + private static async Task WriteContextArtifactsAsync(string workspace, string contextFileName, string context) + { + await WriteUtf8Async(Path.Combine(workspace, contextFileName), context); + + var chunkDirectoryName = Path.GetFileNameWithoutExtension(contextFileName) + ".chunks"; + var chunkDirectory = Path.Combine(workspace, chunkDirectoryName); + if (Directory.Exists(chunkDirectory)) + { + Directory.Delete(chunkDirectory, recursive: true); + } + + Directory.CreateDirectory(chunkDirectory); + + var chunks = SplitContextIntoChunks(context).ToList(); + var chunkPaths = new List(chunks.Count); + for (var i = 0; i < chunks.Count; i++) + { + var chunkNumber = i + 1; + var chunkFileName = chunkNumber.ToString("D4") + ".md"; + var chunkPath = (chunkDirectoryName + "/" + chunkFileName).Replace('\\', '/'); + chunkPaths.Add(chunkPath); + + var chunkContent = BuildChunkFile(contextFileName, chunkNumber, chunks.Count, chunks[i]); + await WriteUtf8Async(Path.Combine(workspace, chunkPath), chunkContent); + } + + var indexPath = Path.GetFileNameWithoutExtension(contextFileName) + ".index.md"; + var index = BuildContextIndex(contextFileName, indexPath, chunkPaths, chunks, context); + await WriteUtf8Async(Path.Combine(workspace, indexPath), index); + + return new ContextArtifacts(contextFileName, indexPath, chunkPaths); + } + + private static IEnumerable SplitContextIntoChunks(string context) + { + var normalized = context.Replace("\r\n", "\n", StringComparison.Ordinal).Replace('\r', '\n'); + var lines = normalized.Split('\n'); + var sb = new StringBuilder(); + var currentBytes = 0; + + foreach (var line in lines) + { + var lineWithNewline = line + Environment.NewLine; + var lineBytes = Encoding.UTF8.GetByteCount(lineWithNewline); + if (lineBytes > MaxContextChunkBodyBytes) + { + if (sb.Length > 0) + { + yield return sb.ToString(); + sb.Clear(); + currentBytes = 0; + } + + foreach (var part in SplitOversizedLine(lineWithNewline)) + { + yield return part; + } + + continue; + } + + if (sb.Length > 0 && currentBytes + lineBytes > MaxContextChunkBodyBytes) + { + yield return sb.ToString(); + sb.Clear(); + currentBytes = 0; + } + + sb.Append(lineWithNewline); + currentBytes += lineBytes; + } + + if (sb.Length > 0) + { + yield return sb.ToString(); + } + } + + private static IEnumerable SplitOversizedLine(string line) + { + var sb = new StringBuilder(); + var currentBytes = 0; + foreach (var rune in line.EnumerateRunes()) + { + var next = rune.ToString(); + var nextBytes = Encoding.UTF8.GetByteCount(next); + if (sb.Length > 0 && currentBytes + nextBytes > MaxContextChunkBodyBytes) + { + yield return sb.ToString(); + sb.Clear(); + currentBytes = 0; + } + + sb.Append(next); + currentBytes += nextBytes; + } + + if (sb.Length > 0) + { + yield return sb.ToString(); + } + } + + private static string BuildChunkFile(string contextFileName, int chunkNumber, int chunkCount, string chunkBody) + { + var sb = new StringBuilder(); + sb.AppendLine("# Context Chunk " + chunkNumber.ToString("D4")); + sb.AppendLine(); + sb.AppendLine("Source context: `" + contextFileName + "`"); + sb.AppendLine("Chunk: " + chunkNumber + " of " + chunkCount); + sb.AppendLine(); + sb.AppendLine("Read this chunk as raw evidence. The index file is only a navigation aid."); + sb.AppendLine(); + sb.AppendLine("---"); + sb.AppendLine(); + sb.Append(chunkBody); + return sb.ToString(); + } + + private static string BuildContextIndex( + string contextFileName, + string indexPath, + IReadOnlyList chunkPaths, + IReadOnlyList chunks, + string context) + { + var sb = new StringBuilder(); + sb.AppendLine("# Context Index"); + sb.AppendLine(); + sb.AppendLine("Source context: `" + contextFileName + "`"); + sb.AppendLine("Index path: `" + indexPath + "`"); + sb.AppendLine("Chunk count: " + chunkPaths.Count); + sb.AppendLine("Full context bytes: " + Encoding.UTF8.GetByteCount(context)); + sb.AppendLine(); + sb.AppendLine("This file is a deterministic navigation aid. Do not use it as a substitute for reading the raw context or every chunk listed below."); + sb.AppendLine(); + + sb.AppendLine("## Read Order"); + sb.AppendLine(); + sb.AppendLine("1. Read this index to understand the context layout."); + sb.AppendLine("2. Read each chunk in numeric order before writing from this context."); + sb.AppendLine("3. Use the full source context only when your tools can read it completely without truncation."); + sb.AppendLine(); + + sb.AppendLine("## Chunks"); + sb.AppendLine(); + sb.AppendLine("| Chunk | Path | Body bytes | Headings |"); + sb.AppendLine("|---|---|---:|---|"); + for (var i = 0; i < chunks.Count; i++) + { + var headings = ExtractHeadings(chunks[i]).ToList(); + var headingText = headings.Count == 0 + ? "(none)" + : string.Join("; ", headings.Take(4)); + if (headings.Count > 4) + { + headingText += "; ..."; + } + + sb.AppendLine($"| {i + 1} | `{chunkPaths[i]}` | {Encoding.UTF8.GetByteCount(chunks[i])} | {EscapeMarkdownTableCell(headingText)} |"); + } + sb.AppendLine(); + + var contextHeadings = ExtractHeadings(context).ToList(); + if (contextHeadings.Count > 0) + { + sb.AppendLine("## Context Sections"); + sb.AppendLine(); + foreach (var heading in contextHeadings) + { + sb.AppendLine("- " + heading); + } + sb.AppendLine(); + } + + var packedPaths = ExtractPackedFilePaths(context).Take(200).ToList(); + if (packedPaths.Count > 0) + { + sb.AppendLine("## Packed File Inventory"); + sb.AppendLine(); + foreach (var path in packedPaths) + { + sb.AppendLine("- `" + path + "`"); + } + sb.AppendLine(); + } + + return sb.ToString(); + } + + private static IEnumerable ExtractHeadings(string markdown) + { + foreach (Match match in Regex.Matches(markdown, @"^##\s+(.+)$", RegexOptions.Multiline)) + { + yield return match.Groups[1].Value.Trim(); + } + } + + private static IEnumerable ExtractPackedFilePaths(string context) + { + var paths = new SortedSet(StringComparer.OrdinalIgnoreCase); + foreach (Match match in Regex.Matches(context, @" + value.Replace("|", "\\|", StringComparison.Ordinal); + + private static Regex PublicTypeRegex() => + new( + @"(?m)^\s*(?:\[[^\]]+\]\s*)*(?:public|protected\s+internal|internal\s+protected)\s+(?:(?:static|abstract|sealed|partial|readonly|unsafe)\s+)*(?record\s+class|record\s+struct|class|interface|struct|record|enum)\s+(?[A-Za-z_][A-Za-z0-9_]*(?:<[^>{};]+>)?)\s*(?::\s*(?[^{]+))?", + RegexOptions.Compiled); + + private static Regex PublicMemberRegex() => + new( + @"(?m)^\s*(?:\[[^\]]+\]\s*)*(?:public|protected(?:\s+internal)?|internal\s+protected)\s+(?[^\r\n{;]+(?:\([^\r\n;{}]*\))?)", + RegexOptions.Compiled); + private static async Task PackRepositoryContentAsync(string repoUrl, string cloneDir, string includes) { try { - return await PackWithRepomixAsync(cloneDir, includes); + return FilterLowSignalPackedContent(await PackWithRepomixAsync(cloneDir, includes)); } catch (Exception ex) when (CanUseDotNetPackerFallback(ex)) { @@ -694,7 +1191,7 @@ private static async Task PackRepositoryContentAsync(string repoUrl, str try { Console.WriteLine("[story] trying Repomix web API fallback."); - return await PackWithRepomixWebApiAsync(repoUrl, includes); + return FilterLowSignalPackedContent(await PackWithRepomixWebApiAsync(repoUrl, includes)); } catch (Exception webEx) { @@ -703,7 +1200,7 @@ private static async Task PackRepositoryContentAsync(string repoUrl, str } Console.WriteLine("[story] using built-in .NET context packer fallback."); - return await PackWithDotNetPackerAsync(cloneDir, includes); + return FilterLowSignalPackedContent(await PackWithDotNetPackerAsync(cloneDir, includes)); } } @@ -825,6 +1322,7 @@ private static async Task PackWithDotNetPackerAsync(string cloneDir, str .Select(path => new PackedFile(path, Path.GetRelativePath(cloneDir, path).Replace('\\', '/'))) .Where(file => ShouldIncludeFile(file.RelativePath, includePatterns)) .Where(file => !IsUnderSkippedDirectory(file.RelativePath)) + .Where(file => !ShouldSkipLowSignalFile(file.RelativePath)) .Where(file => IsTextFile(file.FullPath)) .OrderBy(file => file.RelativePath, StringComparer.OrdinalIgnoreCase) .ToList(); @@ -851,6 +1349,62 @@ private static async Task PackWithDotNetPackerAsync(string cloneDir, str private static bool ShouldIncludeFile(string relativePath, IReadOnlyList includePatterns) => includePatterns.Any(pattern => MatchesIncludePattern(relativePath, pattern)); + private static string FilterLowSignalPackedContent(string content) + { + try + { + var doc = XDocument.Parse(content, LoadOptions.PreserveWhitespace); + var removedAny = false; + foreach (var file in doc.Descendants().Where(e => e.Name.LocalName == "file").ToList()) + { + var path = file.Attribute("path")?.Value; + if (path is not null && ShouldSkipLowSignalFile(path)) + { + file.Remove(); + removedAny = true; + } + } + + foreach (var directoryStructure in doc.Descendants().Where(e => e.Name.LocalName == "directoryStructure").ToList()) + { + var filtered = string.Join( + Environment.NewLine, + directoryStructure.Value.Split('\n', StringSplitOptions.None) + .Select(line => line.TrimEnd('\r')) + .Where(line => !ShouldSkipLowSignalFile(line.Trim()))); + + if (!string.Equals(filtered, directoryStructure.Value, StringComparison.Ordinal)) + { + directoryStructure.Value = filtered; + removedAny = true; + } + } + + if (removedAny) + { + return doc.ToString(SaveOptions.DisableFormatting); + } + } + catch + { + // Repomix output is expected to be XML, but keep a text fallback for service changes. + } + + var withoutFileBlocks = Regex.Replace( + content, + @"(?s)]*>.*?
\s*", + string.Empty, + RegexOptions.IgnoreCase); + + return Regex.Replace( + withoutFileBlocks, + @"(?im)^[^\r\n]*GlobalSuppressions\.cs[^\r\n]*(?:\r?\n)?", + string.Empty); + } + + private static bool ShouldSkipLowSignalFile(string relativePath) => + string.Equals(Path.GetFileName(relativePath), "GlobalSuppressions.cs", StringComparison.OrdinalIgnoreCase); + private static bool MatchesIncludePattern(string relativePath, string pattern) { var normalizedPattern = pattern.Replace('\\', '/').TrimStart('/'); @@ -950,12 +1504,12 @@ private static async Task WriteManifestAsync( string repoId, string workspace, IReadOnlyList targets, - string overviewContextName) + ContextArtifacts overviewArtifacts) { var packagesPhase = new { name = "packages", - targets = targets.Select(t => new { t.kind, t.name, t.context, t.result }).ToList() + targets = targets.Select(t => new { t.kind, t.name, t.context, t.contextIndex, t.contextChunks, t.result }).ToList() }; var overviewPhase = new @@ -966,7 +1520,9 @@ private static async Task WriteManifestAsync( { kind = "overview", name = "Index", - context = overviewContextName, + context = overviewArtifacts.ContextPath, + contextIndex = overviewArtifacts.IndexPath, + contextChunks = overviewArtifacts.ChunkPaths, sourceResults = targets.Select(t => t.result).ToList(), result = "result/Index.md" } @@ -1104,6 +1660,8 @@ result dir result {output-root}/{repo-id}/manifest.json {output-root}/{repo-id}/instructions.md {output-root}/{repo-id}/*.context.md + {output-root}/{repo-id}/*.context.index.md + {output-root}/{repo-id}/*.context.chunks/*.md {output-root}/{repo-id}/result/ Notes: @@ -1130,10 +1688,33 @@ internal sealed record TargetInfo( bool IsConveniencePackage, IReadOnlyList BundledPackages); +internal sealed record ContextArtifacts( + string ContextPath, + string IndexPath, + IReadOnlyList ChunkPaths); + +internal sealed record ApiTypeSummary( + string Name, + string Kind, + string BaseTypes, + IReadOnlyList Members, + string SourcePath); + +internal sealed record SignalFile( + string RelativePath, + string Content); + +internal sealed record EngineeringSignal( + string Kind, + string Value, + string SourcePath); + internal sealed record TargetManifestEntry( string kind, string name, string context, + string contextIndex, + IReadOnlyList contextChunks, string result); internal sealed record PackedFile(string FullPath, string RelativePath); From 43b19028f2f2e77fca3fce55a1a1fad36bf6e97e Mon Sep 17 00:00:00 2001 From: "aicia[bot]" Date: Mon, 4 May 2026 00:07:32 +0200 Subject: [PATCH 11/18] =?UTF-8?q?=F0=9F=92=AC=20Update=20CHANGELOG.md=20fo?= =?UTF-8?q?r=20v0.4.1=20release?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Document complete-read grounding rules and mandatory target-story sourcing - Highlight optional subagent delegation for independent target contexts - Explain evidence-based language validation to prevent unmeasured claims - Document public API summaries and engineering signal maps - Add chunked context navigation for robust file reading - Update compare links for v0.4.1 release --- CHANGELOG.md | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d4d7198..7d53bb1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,31 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), ## [Unreleased] +## [0.4.1] - 2026-05-04 + +This is a minor release focused on strengthening `git-story-teller` with complete-read grounding rules, optional subagent delegation, evidence-based language validation, and enhanced deterministic output artifacts. The skill now enforces that agents read full context and target stories as primary sources, supports delegation of independent target contexts to subagents, and provides tooling to detect and prevent unmeasured frequency or behavior claims without source evidence. + +### Added + +- Complete-read grounding rules in `git-story-teller` requiring agents to fully inspect target contexts and overview sources, with explicit guidance on using chunk indices and range reads to handle truncated output, +- Optional subagent strategy in `git-story-teller` for delegating independent target contexts to isolated subagents, reducing prompt budget contention while maintaining strict grounding requirements, +- Evidence-based language validation patterns and regex detection in `git-story-teller` to distinguish structural facts from unmeasured behavior claims, with explicit guidance on conditional language like "if you only need X, aggregate adds Y" instead of "most common" or "developers often" without evidence, +- Public API summary generation in `story.cs` to help agents orient around consumer-facing types, inheritance chains, and key members before reading raw source, +- Engineering signal map in `story.cs` highlighting source-backed validation guards, lifecycle callbacks, factories, hosting styles, and test evidence for narrative-driven explanations instead of mechanical API lists, +- Chunked context navigation in `story.cs` with `*.context.index.md` and ordered `*.context.chunks/*.md` files alongside full contexts for robust reading even when tools cap single-file output. + +### Changed + +- Refined `git-story-teller` SKILL.md with explicit complete-read contract, mandatory target-story sourcing for overview phase, and subagent orchestration patterns for large independent contexts, +- Enhanced `story.cs` to emit complete context files, public API summaries, engineering signal maps, context indexes, and ordered chunk files for improved agent navigation and grounding, +- Updated README description and "Why git-story-teller?" section to document full output artifacts, public-API-first orientation, engineering signals, chunked navigation, and complete-read grounding, +- Expanded AGENTS.md with four-way skill sync guidance including Gemini Antigravity install location and folder-name requirements, +- Refined eval contracts for complete-read patterns, subagent coordination, evidence-based prose, and target-story-sourced overview synthesis. + +### Fixed + +- Clarified validator and documentation alignment to enforce complete-read requirements, evidence-based language rules, and target-story sourcing for overview workflows. + ## [0.4.0] - 2026-05-03 This is a minor release focused on deterministic repository story generation and foundational agent guidelines. It introduces a new `git-story-teller` skill with a bundled .NET context extractor, enhanced bot workspace management, and Karpathy programming principles for LLM agents. @@ -157,7 +182,8 @@ This is a minor release that introduces two complementary git workflow skills, e - Improved scaffold fidelity with hidden `.bot` asset preservation, explicit UTF-8 and BOM handling, and checks aimed at preventing mojibake or incomplete generated output. -[Unreleased]: https://github.com/codebeltnet/agentic/compare/v0.4.0...HEAD +[Unreleased]: https://github.com/codebeltnet/agentic/compare/v0.4.1...HEAD +[0.4.1]: https://github.com/codebeltnet/agentic/compare/v0.4.0...v0.4.1 [0.4.0]: https://github.com/codebeltnet/agentic/compare/v0.3.4...v0.4.0 [0.3.4]: https://github.com/codebeltnet/agentic/compare/v0.3.3...v0.3.4 [0.3.3]: https://github.com/codebeltnet/agentic/compare/v0.3.2...v0.3.3 From 67147f5f5f12f77822fbc080f5085c0276e9b029 Mon Sep 17 00:00:00 2001 From: "aicia[bot]" Date: Mon, 4 May 2026 00:16:09 +0200 Subject: [PATCH 12/18] =?UTF-8?q?=F0=9F=92=AC=20Document=20conservative=20?= =?UTF-8?q?test=20ownership=20in=20release=20notes=20and=20README?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Update v0.4.1 CHANGELOG entry with conservative test mapping feature - Add conservative test ownership line to README 'Why git-story-teller?' section - Clarify that runner prefers dedicated test projects over downstream package tests --- CHANGELOG.md | 9 +++++---- README.md | 3 ++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d53bb1..3b37c07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,15 +17,16 @@ This is a minor release focused on strengthening `git-story-teller` with complet - Evidence-based language validation patterns and regex detection in `git-story-teller` to distinguish structural facts from unmeasured behavior claims, with explicit guidance on conditional language like "if you only need X, aggregate adds Y" instead of "most common" or "developers often" without evidence, - Public API summary generation in `story.cs` to help agents orient around consumer-facing types, inheritance chains, and key members before reading raw source, - Engineering signal map in `story.cs` highlighting source-backed validation guards, lifecycle callbacks, factories, hosting styles, and test evidence for narrative-driven explanations instead of mechanical API lists, +- Conservative test ownership mapping in `story.cs` preferring dedicated test projects with matching names over downstream package tests, only using direct references as fallback, and leaving Test path undiscovered when no unambiguous match exists, - Chunked context navigation in `story.cs` with `*.context.index.md` and ordered `*.context.chunks/*.md` files alongside full contexts for robust reading even when tools cap single-file output. ### Changed -- Refined `git-story-teller` SKILL.md with explicit complete-read contract, mandatory target-story sourcing for overview phase, and subagent orchestration patterns for large independent contexts, -- Enhanced `story.cs` to emit complete context files, public API summaries, engineering signal maps, context indexes, and ordered chunk files for improved agent navigation and grounding, -- Updated README description and "Why git-story-teller?" section to document full output artifacts, public-API-first orientation, engineering signals, chunked navigation, and complete-read grounding, +- Refined `git-story-teller` SKILL.md with explicit complete-read contract, mandatory target-story sourcing for overview phase, subagent orchestration patterns, and conservative test mapping rules, +- Enhanced `story.cs` to emit complete context files, public API summaries, engineering signal maps, conservative test ownership logic, context indexes, and ordered chunk files for improved agent navigation and grounding, +- Updated README description and "Why git-story-teller?" section to document full output artifacts, public-API-first orientation, engineering signals, conservative test mapping, chunked navigation, and complete-read grounding, - Expanded AGENTS.md with four-way skill sync guidance including Gemini Antigravity install location and folder-name requirements, -- Refined eval contracts for complete-read patterns, subagent coordination, evidence-based prose, and target-story-sourced overview synthesis. +- Refined eval contracts for complete-read patterns, subagent coordination, evidence-based prose, target-story-sourced overview synthesis, and conservative test ownership mapping. ### Fixed diff --git a/README.md b/README.md index cd85d98..6614e77 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,7 @@ npx skills add https://github.com/codebeltnet/agentic --skill dotnet-new-lib-sln | [git-visual-squash-summary](skills/git-visual-squash-summary/SKILL.md) | Non-mutating grouped-summary companion to `git-visual-commits`. Turns the full current feature branch into a curated set of compact summary lines for PR or squash-and-merge contexts by default, preserving technical identifiers, merging overlap, dropping low-signal noise, highlighting distinct meaningful efforts, and avoiding changelog-style wording, unsupported claims, needless commit-range questions, or commit-selection UI for ordinary branch-level squash requests. | | [skill-creator-agnostic](skills/skill-creator-agnostic/SKILL.md) | Runner-agnostic overlay for Anthropic `skill-creator`. Adds repo and environment guardrails for skill authoring and benchmarking: temp-workspace isolation, `iteration-N/eval-name/{config}/run-N/` benchmark layout, valid `grading.json` summaries, generated `benchmark.json`, honest `MEASURED` vs `SIMULATED` labeling, and sync/README discipline for repo-managed skills. | | [markdown-illustrator](skills/markdown-illustrator/SKILL.md) | Reads a markdown file and answers directly in chat with one document-wide Visual Brief plus one compiled prompt. Infers a compact visual strategy by default, keeps follow-up questions near zero, and only branches when the user explicitly asks for added specificity. | -| [git-story-teller](skills/git-story-teller/SKILL.md) | Turns any full repository URL into a deterministic story workspace using the bundled .NET file-based runner `scripts/story.cs`. Requires explicit `--repo-url` and `--output-root`, derives `{repo-id}`, fixes `result/`, packs context with local Repomix when available, the public Repomix web API for GitHub URLs when Node/npm is unavailable, or a lower-fidelity built-in .NET fallback as the last resort, writes full contexts plus public API summaries, engineering signals, context indexes, and ordered chunk files, then guides the agent to fully read the current phase's required context before writing target stories and `result/Index.md`, optionally using one subagent per independent target context and using completed package stories as the primary source for the package-facing `## Package selection` overview. | +| [git-story-teller](skills/git-story-teller/SKILL.md) | Turns any full repository URL into a deterministic story workspace using the bundled .NET file-based runner `scripts/story.cs`. Requires explicit `--repo-url` and `--output-root`, derives `{repo-id}`, fixes `result/`, packs context with local Repomix when available, the public Repomix web API for GitHub URLs when Node/npm is unavailable, or a lower-fidelity built-in .NET fallback as the last resort, writes full contexts plus public API summaries, engineering signals, conservative package-owned test paths, context indexes, and ordered chunk files, then guides the agent to fully read the current phase's required context before writing target stories and `result/Index.md`, optionally using one subagent per independent target context and using completed package stories as the primary source for the package-facing `## Package selection` overview. | | [dotnet-new-lib-slnx](skills/dotnet-new-lib-slnx/SKILL.md) | Scaffold a new .NET NuGet library solution following codebeltnet engineering conventions. Dynamic defaults for TFM/repository metadata, latest-stable NuGet package resolution, tuning projects plus a tooling-based benchmark runner, TFM-aware test environments, strong-name signing, NuGet packaging, DocFX documentation, CI/CD pipeline, and code quality tooling. | | [dotnet-new-app-slnx](skills/dotnet-new-app-slnx/SKILL.md) | Scaffold a new .NET standalone application solution following codebeltnet engineering conventions. Supports Console, Web, and Worker host families with Startup or Minimal hosting patterns; Web expands into Empty Web, Web API, MVC, or Web App / Razor, plus functional tests and a simplified CI pipeline. | | [trunk-first-repo](skills/trunk-first-repo/SKILL.md) | Initialize a git repository following [scaled trunk-based development](https://trunkbaseddevelopment.com/#scaled-trunk-based-development). Seeds an empty `main` branch and creates a versioned feature branch (`v0.1.0/init`), enforcing a PR-first workflow where content only reaches main through peer-reviewed pull requests. | @@ -295,6 +295,7 @@ Repository story generation works best when deterministic context gathering is s - **Tool output is authoritative** - reads `manifest.json`, `instructions.md`, and one target context at a time instead of reconstructing scope from memory - **Public API first** - adds a generated public API summary so agents can orient around consumer-facing types, inheritance chains, and likely key members before reading the raw source - **Engineering signal map** - highlights source-backed places to inspect for validation guards, lifecycle callbacks, factories, hosting styles, and test evidence so stories can explain the engineering decisions instead of listing APIs mechanically +- **Conservative test ownership** - maps a package to a dedicated test project with the same package name plus a test suffix, or to a single unambiguous direct reference, instead of assigning downstream package tests that merely share a base package prefix - **Low-signal filtering** - removes `GlobalSuppressions.cs` from packed context while keeping internals available when they explain public behavior - **Chunked context navigation** - emits `*.context.index.md` and ordered `*.context.chunks/*.md` files beside each full context so agents can read large evidence sets even when a tool caps single-file output - **Complete-read grounding** - treats capped or truncated context output as an unfinished read, requiring the agent to use the index and every ordered chunk, or range reads for older workspaces, until the current target context, overview context, and required target stories have been fully inspected From 70bd2451ae963891c8d9daffd86c97b5d7a7c528 Mon Sep 17 00:00:00 2001 From: "aicia[bot]" Date: Mon, 4 May 2026 00:16:15 +0200 Subject: [PATCH 13/18] =?UTF-8?q?=F0=9F=93=9D=20Add=20conservative=20test?= =?UTF-8?q?=20mapping=20guidance=20to=20git-story-teller=20skill?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Document test project filtering rules in SKILL.md Fallback notes - Add eval 11 testing conservative test ownership with shared base packages - Validate that runner prefers dedicated test projects over downstream tests - Ensure Test path is left undiscovered when only ambiguous matches exist --- skills/git-story-teller/SKILL.md | 1 + skills/git-story-teller/evals/evals.json | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/skills/git-story-teller/SKILL.md b/skills/git-story-teller/SKILL.md index e9b72d6..4335205 100644 --- a/skills/git-story-teller/SKILL.md +++ b/skills/git-story-teller/SKILL.md @@ -70,6 +70,7 @@ Fallback notes: - The built-in .NET fallback is local-only and packs only files matching the runner's include patterns. - The built-in .NET fallback does not provide Repomix token counts, Secretlint checks, compression, or exact gitignore semantics. - The runner filters known low-signal files such as `GlobalSuppressions.cs` from packed context. Do not recreate or infer story claims from those files. +- The runner maps test projects conservatively. It prefers a dedicated test project whose name matches the package plus a test suffix, then a single unambiguous direct project reference. If only downstream package tests match a shared base package prefix, the runner leaves `Test path` undiscovered instead of assigning another package's tests. - If `.NET 10` or `git` is unavailable, stop and report the missing dependency. - If Repomix runs and rejects content, do not bypass that result manually with a fallback unless the user explicitly accepts the lower-fidelity path. diff --git a/skills/git-story-teller/evals/evals.json b/skills/git-story-teller/evals/evals.json index 1805d76..0b66dbd 100644 --- a/skills/git-story-teller/evals/evals.json +++ b/skills/git-story-teller/evals/evals.json @@ -131,6 +131,18 @@ "Uses internal implementation details only to explain public behavior such as lifecycle, validation, callback flow, or package boundaries", "Excludes GlobalSuppressions.cs from packed context instead of spending story budget on suppression metadata" ] + }, + { + "id": 11, + "prompt": "Use git-story-teller to generate a story workspace for a repository where Codebelt.Extensions.Xunit is a shared base package, Directory.Build.props adds it to test projects, and downstream test projects such as Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests exist but there is no dedicated Codebelt.Extensions.Xunit.Tests project.", + "expected_output": "The generated Codebelt.Extensions.Xunit target context does not assign a downstream hosting test directory as its Test path. It either uses a dedicated exact-name test project when present or leaves Test path undiscovered when only downstream package test projects match the base package prefix.", + "expectations": [ + "Prefers a dedicated test project named after the target package plus a test suffix over downstream package test projects", + "Does not treat Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests as the owned test project for Codebelt.Extensions.Xunit", + "Leaves Test path as not discovered when no dedicated test project or single unambiguous direct project reference exists", + "Still allows Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests to map to the Codebelt.Extensions.Xunit.Hosting.AspNetCore target", + "Reports missing dedicated tests as a confidence risk instead of smoothing it over with another package's tests" + ] } ] } From b1bee8502512c45bed7e5a50727af468cf757977 Mon Sep 17 00:00:00 2001 From: "aicia[bot]" Date: Mon, 4 May 2026 00:16:21 +0200 Subject: [PATCH 14/18] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Implement=20conserva?= =?UTF-8?q?tive=20test=20project=20discovery=20in=20story.cs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Prefer dedicated test projects matching target package name plus test suffix - Only use direct project references when dedicated test project unavailable - Leave Test path undiscovered when multiple downstream tests share base package prefix - Add TestProjectMatch record for ordered evaluation of test ownership - Strip known suffixes (Tests, Test, UnitTests, FunctionalTests, IntegrationTests) for matching - Sort candidates by ownership priority and name for deterministic selection --- skills/git-story-teller/scripts/story.cs | 49 +++++++++++++++++++----- 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/skills/git-story-teller/scripts/story.cs b/skills/git-story-teller/scripts/story.cs index 3af7713..2f2024b 100644 --- a/skills/git-story-teller/scripts/story.cs +++ b/skills/git-story-teller/scripts/story.cs @@ -251,6 +251,8 @@ private static string FirstNonEmpty(params string[] values) => .Where(Directory.Exists) .ToList(); + var normalizedTarget = NormalizeForMatch(targetName); + var candidates = new List(); foreach (var root in testRoots) { var testProjects = Directory.EnumerateFiles(root, "*.csproj", SearchOption.AllDirectories) @@ -259,21 +261,45 @@ private static string FirstNonEmpty(params string[] values) => foreach (var testProject in testProjects) { - if (ReferencesProject(testProject, sourceProjectFile)) - { - return Path.GetDirectoryName(testProject); - } + candidates.Add(new TestProjectMatch( + testProject, + IsOwnTestProjectName(testProject, normalizedTarget), + ReferencesProject(testProject, sourceProjectFile))); } + } + + var ownMatch = candidates + .Where(c => c.IsOwnTestProjectName) + .OrderByDescending(c => c.ReferencesProject) + .ThenBy(c => c.ProjectFile, StringComparer.OrdinalIgnoreCase) + .FirstOrDefault(); + if (ownMatch is not null) + { + return Path.GetDirectoryName(ownMatch.ProjectFile); + } + + var directMatches = candidates + .Where(c => c.ReferencesProject) + .OrderBy(c => c.ProjectFile, StringComparer.OrdinalIgnoreCase) + .ToList(); + return directMatches.Count == 1 ? Path.GetDirectoryName(directMatches[0].ProjectFile) : null; + } - var normalizedTarget = NormalizeForMatch(targetName); - var byName = testProjects.FirstOrDefault(p => NormalizeForMatch(Path.GetFileNameWithoutExtension(p)).Contains(normalizedTarget, StringComparison.OrdinalIgnoreCase)); - if (byName is not null) + private static bool IsOwnTestProjectName(string testProjectFile, string normalizedTarget) => + StripKnownTestSuffix(NormalizeForMatch(Path.GetFileNameWithoutExtension(testProjectFile))) == normalizedTarget; + + private static string StripKnownTestSuffix(string normalizedProjectName) + { + var suffixes = new[] { "integrationtests", "functionaltests", "unittests", "tests", "test" }; + foreach (var suffix in suffixes) + { + if (normalizedProjectName.EndsWith(suffix, StringComparison.OrdinalIgnoreCase)) { - return Path.GetDirectoryName(byName); + return normalizedProjectName[..^suffix.Length]; } } - return null; + return normalizedProjectName; } private static bool ReferencesProject(string testProjectFile, string sourceProjectFile) @@ -1688,6 +1714,11 @@ internal sealed record TargetInfo( bool IsConveniencePackage, IReadOnlyList BundledPackages); +internal sealed record TestProjectMatch( + string ProjectFile, + bool IsOwnTestProjectName, + bool ReferencesProject); + internal sealed record ContextArtifacts( string ContextPath, string IndexPath, From 99ef8a1d7e57091bed50d226f2fd07b019affa68 Mon Sep 17 00:00:00 2001 From: "aicia[bot]" Date: Mon, 4 May 2026 00:37:09 +0200 Subject: [PATCH 15/18] =?UTF-8?q?=F0=9F=92=AC=20Document=20test=20project?= =?UTF-8?q?=20matching=20refinements=20in=20CHANGELOG=20and=20evals?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add Fixed section bullets documenting exact suffix matching for test discovery - Clarify eval 11 expectations for dedicated test project patterns - Prevent false positives from partial test-suffix overlaps in project names --- CHANGELOG.md | 4 +++- skills/git-story-teller/evals/evals.json | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b37c07..b2abb2c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,7 +30,9 @@ This is a minor release focused on strengthening `git-story-teller` with complet ### Fixed -- Clarified validator and documentation alignment to enforce complete-read requirements, evidence-based language rules, and target-story sourcing for overview workflows. +- Clarified validator and documentation alignment to enforce complete-read requirements, evidence-based language rules, and target-story sourcing for overview workflows, +- Refined conservative test project matching to use exact suffix matching instead of stripping, preventing false positives when project names contain partial test-suffix overlap, +- Updated eval 11 expectations to clarify handling of dedicated test projects with explicit "Tests" suffix patterns. ## [0.4.0] - 2026-05-03 diff --git a/skills/git-story-teller/evals/evals.json b/skills/git-story-teller/evals/evals.json index 0b66dbd..a19f163 100644 --- a/skills/git-story-teller/evals/evals.json +++ b/skills/git-story-teller/evals/evals.json @@ -137,6 +137,8 @@ "prompt": "Use git-story-teller to generate a story workspace for a repository where Codebelt.Extensions.Xunit is a shared base package, Directory.Build.props adds it to test projects, and downstream test projects such as Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests exist but there is no dedicated Codebelt.Extensions.Xunit.Tests project.", "expected_output": "The generated Codebelt.Extensions.Xunit target context does not assign a downstream hosting test directory as its Test path. It either uses a dedicated exact-name test project when present or leaves Test path undiscovered when only downstream package test projects match the base package prefix.", "expectations": [ + "Recognizes Codebelt.Extensions.Xunit.Tests as the dedicated test project for Codebelt.Extensions.Xunit", + "Does not confuse the Xunit.Tests suffix with a UnitTests suffix and strip too much of the target name", "Prefers a dedicated test project named after the target package plus a test suffix over downstream package test projects", "Does not treat Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests as the owned test project for Codebelt.Extensions.Xunit", "Leaves Test path as not discovered when no dedicated test project or single unambiguous direct project reference exists", From cb37049841ca4b09a2a208922e60c4354b0bf8cb Mon Sep 17 00:00:00 2001 From: "aicia[bot]" Date: Mon, 4 May 2026 00:37:15 +0200 Subject: [PATCH 16/18] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Refine=20test=20proj?= =?UTF-8?q?ect=20matching=20to=20use=20exact=20suffix=20comparison?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Replace suffix-stripping logic with exact suffix matching on target + suffix - Check if normalized project name equals target plus known test suffix pattern - Prevent false positives like confusing 'Xunit.Tests' with 'Xunit' + 'UnitTests' - Support multiple suffix patterns: Tests, Test, UnitTests, UnitTest, etc. --- skills/git-story-teller/scripts/story.cs | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/skills/git-story-teller/scripts/story.cs b/skills/git-story-teller/scripts/story.cs index 2f2024b..9da88be 100644 --- a/skills/git-story-teller/scripts/story.cs +++ b/skills/git-story-teller/scripts/story.cs @@ -285,21 +285,11 @@ private static string FirstNonEmpty(params string[] values) => return directMatches.Count == 1 ? Path.GetDirectoryName(directMatches[0].ProjectFile) : null; } - private static bool IsOwnTestProjectName(string testProjectFile, string normalizedTarget) => - StripKnownTestSuffix(NormalizeForMatch(Path.GetFileNameWithoutExtension(testProjectFile))) == normalizedTarget; - - private static string StripKnownTestSuffix(string normalizedProjectName) + private static bool IsOwnTestProjectName(string testProjectFile, string normalizedTarget) { - var suffixes = new[] { "integrationtests", "functionaltests", "unittests", "tests", "test" }; - foreach (var suffix in suffixes) - { - if (normalizedProjectName.EndsWith(suffix, StringComparison.OrdinalIgnoreCase)) - { - return normalizedProjectName[..^suffix.Length]; - } - } - - return normalizedProjectName; + var normalizedProjectName = NormalizeForMatch(Path.GetFileNameWithoutExtension(testProjectFile)); + var suffixes = new[] { "tests", "test", "unittests", "unittest", "integrationtests", "integrationtest", "functionaltests", "functionaltest" }; + return suffixes.Any(suffix => string.Equals(normalizedProjectName, normalizedTarget + suffix, StringComparison.OrdinalIgnoreCase)); } private static bool ReferencesProject(string testProjectFile, string sourceProjectFile) From a6fef40ba7b20f33919a4def9b45ee21ac05ad05 Mon Sep 17 00:00:00 2001 From: "aicia[bot]" Date: Mon, 4 May 2026 00:42:46 +0200 Subject: [PATCH 17/18] =?UTF-8?q?=F0=9F=92=AC=20Document=20Gemini=20Antigr?= =?UTF-8?q?avity=20in=20skill=20sync=20and=20installation=20guidance?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Update AGENTS.md Local Install Sync to include Gemini Antigravity folder - Clarify that changes mirror to repo, Claude, agents, and Gemini installs - Add Gemini Antigravity to README skill folder table - Update skill installation tips to support multiple personal skill folders --- AGENTS.md | 13 +++++++------ README.md | 5 +++-- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index ef06465..f0d7ced 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -54,17 +54,18 @@ Repo-managed skills live in four places that must stay in sync: - `~/.agents/skills//` — local global agent install - `~/.gemini/antigravity/skills//` — local Gemini Antigravity install -Changes often start in `~/.claude/skills//`, then get mirrored to the repo and the global install: +Changes often start in `~/.claude/skills//`, then get mirrored to the repo and the other local installs: - **Claude local → repo** (persist changes to source control): ```powershell Copy-Item "$HOME/.claude/skills//" "skills//" -Force ``` -- **Claude local → global agent install** (keep `~/.agents` current): - ```powershell - Copy-Item "$HOME/.claude/skills//" "$HOME/.agents/skills//" -Force - ``` -- **Repo → both local installs** (after pulling changes or cloning fresh): +- **Claude local → agent installs** (keep `~/.agents` and Gemini current): + ```powershell + Copy-Item "$HOME/.claude/skills//" "$HOME/.agents/skills//" -Force + Copy-Item "$HOME/.claude/skills//" "$HOME/.gemini/antigravity/skills//" -Force + ``` +- **Repo → local installs** (after pulling changes or cloning fresh): ```powershell Copy-Item "skills//" "$HOME/.claude/skills//" -Force Copy-Item "skills//" "$HOME/.agents/skills//" -Force diff --git a/README.md b/README.md index 6614e77..dfda0d1 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ Use the skill tool to invoke the "" skill. ## Always-on skills -Depending on the agent runtime, skills installed via `npx skills add` may live in `~/.claude/skills/` and/or `~/.agents/skills/`. Treat both as personal global skill folders: if you use both toolchains, keep repo-authored skills mirrored between them so each agent sees the same version. Either way, installed skills are **automatically loaded in every session** — no manual invocation needed. The agent reads the skill's description and activates it when relevant (e.g. you say "commit this" and the `git-visual-commits` skill kicks in). +Depending on the agent runtime, skills installed via `npx skills add` may live in `~/.claude/skills/`, `~/.agents/skills/`, and/or `~/.gemini/antigravity/skills/`. Treat these as personal global skill folders: if you use multiple toolchains, keep repo-authored skills mirrored between them so each agent sees the same version. Either way, installed skills are **automatically loaded in every session** — no manual invocation needed. The agent reads the skill's description and activates it when relevant (e.g. you say "commit this" and the `git-visual-commits` skill kicks in). If you want a bundle of skills always available, just install them all: @@ -68,10 +68,11 @@ npx skills add https://github.com/codebeltnet/agentic --skill dotnet-new-lib-sln |----------|-------|-------------| | `~/.agents/skills/` | All sessions, all projects | Global skills for agents that read the shared `~/.agents` install | | `~/.claude/skills/` | All sessions, all projects | Your personal defaults — always on everywhere | +| `~/.gemini/antigravity/skills/` | All sessions, all projects | Gemini Antigravity skills kept in sync with repo-authored skill copies | | `.claude/skills/` (in a repo) | Project-scoped | Shared team conventions for a specific codebase | | `.github/skills/` (in a repo) | GitHub Copilot / VS Code | When your team uses Copilot agent mode in the IDE | -> **Tip:** You can mix scopes. Install your personal favorites globally, and add project-specific skills to the repo so your whole team gets them. If you use both `~/.claude/skills/` and `~/.agents/skills/`, mirror repo-authored skills to both so sessions stay consistent. +> **Tip:** You can mix scopes. Install your personal favorites globally, and add project-specific skills to the repo so your whole team gets them. If you use multiple personal skill folders, mirror repo-authored skills to each one so sessions stay consistent. ## Available Skills From 3c4edfbc33f1546fa1812f7d52fbd920a3cfa603 Mon Sep 17 00:00:00 2001 From: "aicia[bot]" Date: Mon, 4 May 2026 00:42:52 +0200 Subject: [PATCH 18/18] =?UTF-8?q?=E2=9A=A1=20Optimize=20regex=20compilatio?= =?UTF-8?q?n=20in=20story.cs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Move PublicTypeExpression and PublicMemberExpression to static readonly fields - Compile regexes once at class initialization instead of recreating per method call - Improve performance of public API extraction and engineering signal detection --- skills/git-story-teller/scripts/story.cs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/skills/git-story-teller/scripts/story.cs b/skills/git-story-teller/scripts/story.cs index 9da88be..d08bb06 100644 --- a/skills/git-story-teller/scripts/story.cs +++ b/skills/git-story-teller/scripts/story.cs @@ -16,6 +16,13 @@ internal static class StoryScript { private const string ResultDirectoryName = "result"; private const int MaxContextChunkBodyBytes = 36 * 1024; + private static readonly Regex PublicTypeExpression = new( + @"(?m)^\s*(?:\[[^\]]+\]\s*)*(?:public|protected\s+internal|internal\s+protected)\s+(?:(?:static|abstract|sealed|partial|readonly|unsafe)\s+)*(?record\s+class|record\s+struct|class|interface|struct|record|enum)\s+(?[A-Za-z_][A-Za-z0-9_]*(?:<[^>{};]+>)?)\s*(?::\s*(?[^{]+))?", + RegexOptions.Compiled); + + private static readonly Regex PublicMemberExpression = new( + @"(?m)^\s*(?:\[[^\]]+\]\s*)*(?:public|protected(?:\s+internal)?|internal\s+protected)\s+(?[^\r\n{;]+(?:\([^\r\n;{}]*\))?)", + RegexOptions.Compiled); public static async Task RunAsync(string[] args) { @@ -1182,15 +1189,9 @@ private static IEnumerable ExtractPackedFilePaths(string context) private static string EscapeMarkdownTableCell(string value) => value.Replace("|", "\\|", StringComparison.Ordinal); - private static Regex PublicTypeRegex() => - new( - @"(?m)^\s*(?:\[[^\]]+\]\s*)*(?:public|protected\s+internal|internal\s+protected)\s+(?:(?:static|abstract|sealed|partial|readonly|unsafe)\s+)*(?record\s+class|record\s+struct|class|interface|struct|record|enum)\s+(?[A-Za-z_][A-Za-z0-9_]*(?:<[^>{};]+>)?)\s*(?::\s*(?[^{]+))?", - RegexOptions.Compiled); + private static Regex PublicTypeRegex() => PublicTypeExpression; - private static Regex PublicMemberRegex() => - new( - @"(?m)^\s*(?:\[[^\]]+\]\s*)*(?:public|protected(?:\s+internal)?|internal\s+protected)\s+(?[^\r\n{;]+(?:\([^\r\n;{}]*\))?)", - RegexOptions.Compiled); + private static Regex PublicMemberRegex() => PublicMemberExpression; private static async Task PackRepositoryContentAsync(string repoUrl, string cloneDir, string includes) {