From 024b9a73186939820957ac394055eb652db37062 Mon Sep 17 00:00:00 2001 From: "aicia[bot]" Date: Mon, 4 May 2026 22:03:34 +0200 Subject: [PATCH 1/4] =?UTF-8?q?=F0=9F=93=9D=20clarify=20git-story-teller?= =?UTF-8?q?=20local=20packing=20architecture=20and=20eval=20contracts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- skills/git-story-teller/SKILL.md | 14 +++++--------- skills/git-story-teller/evals/evals.json | 12 ++++++------ 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/skills/git-story-teller/SKILL.md b/skills/git-story-teller/SKILL.md index 4335205..463df34 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, 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. + Generate source-grounded repository story markdown from deterministic local context bundles. Use when the user asks to create, refresh, or complete repo/package stories, family or project overview pages, .bot/stories output, story workspace workflows, or result/Index.md plus result/{TargetName}.md files for any repository URL. The skill runs its bundled .NET file-based context generator over a git clone, 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 @@ -62,19 +62,15 @@ repo-id Derived from the final repository URL path segment, with .git remov result dir result ``` -The runner requires the .NET 10 SDK or newer and `git`. It prefers Repomix through `npx repomix` for high-fidelity packing, because Repomix provides the canonical XML shape, ignore handling, token-aware metadata, and security checks. If `npx`/Repomix cannot start or npm registry access is unavailable, the runner tries the same public Repomix web API used by `https://repomix.com/` for GitHub HTTPS repository URLs. If both Repomix paths are unavailable, it falls back to its built-in .NET text packer so the workspace can still be generated. +The runner requires the .NET 10 SDK or newer and `git`. It performs one shallow git clone, discovers packable targets from that local clone, and packs context with its bundled C# packer. The packer uses `git ls-files` for deterministic tracked-file membership, applies the runner's include patterns, skips generated or low-signal paths, keeps text files only, and writes a stable XML repository-context block into each generated `*.context.md` file. -Fallback notes: +Packing 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 context packer is local-only. It does not call Node/npm, Repomix, browser automation, or a public packing service. +- The context packer does not emit third-party token counts, compression summaries, or external Secretlint results. Treat source, tests, project files, README files, and generated public API / engineering signal sections as the grounding surface. - 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. - -Do not scrape or drive the browser UI. If a web fallback is needed, call the Repomix API endpoint directly and keep the lower-fidelity .NET fallback available in case the public service changes or is unreachable. ## Expected Workspace diff --git a/skills/git-story-teller/evals/evals.json b/skills/git-story-teller/evals/evals.json index a19f163..45dcb43 100644 --- a/skills/git-story-teller/evals/evals.json +++ b/skills/git-story-teller/evals/evals.json @@ -70,13 +70,13 @@ }, { "id": 6, - "prompt": "Use git-story-teller to generate a story workspace for https://github.com/example/myproject, but local npx/Repomix cannot start while .NET 10 and git are available.", - "expected_output": "Allows the runner to use the Repomix web API fallback for the public GitHub URL, or the built-in .NET packer if the web API is unavailable, then follows the generated manifest instead of treating missing npx as a hard blocker.", + "prompt": "Use git-story-teller to generate a story workspace for https://github.com/example/myproject while .NET 10 and git are available, but Node/npm, Repomix, and public packing services are unavailable.", + "expected_output": "Runs the bundled story.cs runner with the full repository URL and output root, recognizes that context packing is handled locally by the C# packer over the cloned repository's tracked files, and follows the generated manifest instead of treating missing Node/npm or Repomix as relevant dependencies.", "expectations": [ - "Does not stop solely because local npx or local Repomix is unavailable", - "Recognizes that the runner prefers local Repomix, then can try the public Repomix web API for GitHub HTTPS URLs", - "Mentions that the web API fallback sends the repository URL and include patterns to the public Repomix service", - "Recognizes the built-in .NET text packer as the last-resort lower-fidelity fallback", + "Does not stop or request Node/npm solely because local npx or local Repomix is unavailable", + "Recognizes that the runner performs one shallow git clone and packs local tracked files with the bundled C# packer", + "Does not suggest sending the repository URL or include patterns to a public packing service", + "Treats the C# packer as the primary deterministic context packer rather than a lower-fidelity fallback", "Still treats .NET 10 SDK and git failures as blocking dependencies" ] }, From 257806d4e4f83905aee1da37635e10a3a6324402 Mon Sep 17 00:00:00 2001 From: "aicia[bot]" Date: Mon, 4 May 2026 22:03:34 +0200 Subject: [PATCH 2/4] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20consolidate=20git-stor?= =?UTF-8?q?y-teller=20to=20single=20local=20C#=20context=20packer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- skills/git-story-teller/scripts/story.cs | 233 +++++------------------ 1 file changed, 43 insertions(+), 190 deletions(-) diff --git a/skills/git-story-teller/scripts/story.cs b/skills/git-story-teller/scripts/story.cs index d08bb06..5008f30 100644 --- a/skills/git-story-teller/scripts/story.cs +++ b/skills/git-story-teller/scripts/story.cs @@ -4,7 +4,6 @@ #:property PublishAot=false using System.Diagnostics; -using System.Net.Http; using System.Text; using System.Text.Json; using System.Text.RegularExpressions; @@ -351,7 +350,7 @@ private static async Task BuildTargetContextAsync(string repoUrl, string } includeParts.Add(".nuget/**/README.md"); - var repomix = await PackRepositoryContentAsync(repoUrl, cloneDir, string.Join(',', includeParts)); + var packedContent = await PackRepositoryContentAsync(cloneDir, string.Join(',', includeParts)); var sb = new StringBuilder(); AppendHeader(sb, "TARGET IDENTITY"); @@ -384,7 +383,7 @@ private static async Task BuildTargetContextAsync(string repoUrl, string AppendMultiline(sb, BuildPackageStoryPrompt(target.Name)); AppendHeader(sb, "PACKED REPOSITORY CONTENT"); - sb.AppendLine(repomix.Trim()); + sb.AppendLine(packedContent.Trim()); sb.AppendLine(); return sb.ToString(); @@ -393,7 +392,7 @@ private static async Task BuildTargetContextAsync(string repoUrl, string private static async Task BuildOverviewContextAsync(string repoUrl, string cloneDir, string repoId, IReadOnlyList targets) { Console.WriteLine("[story] packing overview context..."); - var repomix = await PackRepositoryContentAsync(repoUrl, cloneDir, "README.md,.nuget/**/README.md,Directory.Build.props,Directory.Build.targets,Directory.Packages.props,src/**/*.csproj"); + var packedContent = await PackRepositoryContentAsync(cloneDir, "README.md,.nuget/**/README.md,Directory.Build.props,Directory.Build.targets,Directory.Packages.props,src/**/*.csproj"); var sb = new StringBuilder(); AppendHeader(sb, "REPOSITORY IDENTITY"); @@ -425,7 +424,7 @@ private static async Task BuildOverviewContextAsync(string repoUrl, stri AppendMultiline(sb, BuildOverviewStoryPrompt(repoId, targets)); AppendHeader(sb, "SUPPLEMENTARY REPOSITORY CONTENT"); - sb.AppendLine(repomix.Trim()); + sb.AppendLine(packedContent.Trim()); sb.AppendLine(); return sb.ToString(); @@ -1193,150 +1192,18 @@ private static string EscapeMarkdownTableCell(string value) => private static Regex PublicMemberRegex() => PublicMemberExpression; - private static async Task PackRepositoryContentAsync(string repoUrl, string cloneDir, string includes) + private static async Task PackRepositoryContentAsync(string cloneDir, string includes) { - try - { - return FilterLowSignalPackedContent(await PackWithRepomixAsync(cloneDir, includes)); - } - catch (Exception ex) when (CanUseDotNetPackerFallback(ex)) - { - Console.WriteLine("[story] local repomix unavailable: " + ex.Message.Split(Environment.NewLine)[0]); - - if (CanUseRepomixWebApi(repoUrl)) - { - try - { - Console.WriteLine("[story] trying Repomix web API fallback."); - return FilterLowSignalPackedContent(await PackWithRepomixWebApiAsync(repoUrl, includes)); - } - catch (Exception webEx) - { - Console.WriteLine("[story] Repomix web API fallback unavailable: " + webEx.Message.Split(Environment.NewLine)[0]); - } - } - - Console.WriteLine("[story] using built-in .NET context packer fallback."); - return FilterLowSignalPackedContent(await PackWithDotNetPackerAsync(cloneDir, includes)); - } - } - - private static async Task PackWithRepomixAsync(string cloneDir, string includes) - { - var outputFile = Path.Combine(Path.GetTempPath(), "repomix-story-" + Guid.NewGuid().ToString("N") + ".xml"); - try - { - var executable = ResolveNpxExecutable(); - await RunProcessAsync(executable, - ["--yes", "repomix", "--include", includes, "--style", "xml", "--output", outputFile, "--no-file-summary", "--quiet"], - cloneDir); - - if (!File.Exists(outputFile)) - { - throw new InvalidOperationException("repomix completed without creating the expected output file."); - } - - return await File.ReadAllTextAsync(outputFile, Encoding.UTF8); - } - finally - { - TryDeleteFile(outputFile); - } - } - - private static bool CanUseDotNetPackerFallback(Exception ex) - { - var message = ex.ToString(); - var fallbackSignals = new[] - { - "Could not start", - "error occurred trying to start process", - "The system cannot find the file specified", - "No such file or directory", - "could not determine executable to run", - "ENOTFOUND", - "EAI_AGAIN", - "ETIMEDOUT", - "ECONNRESET", - "ECONNREFUSED", - "registry.npmjs.org", - "npm ERR! code" - }; - - return fallbackSignals.Any(signal => message.Contains(signal, StringComparison.OrdinalIgnoreCase)); - } - - private static bool CanUseRepomixWebApi(string repoUrl) - { - return Uri.TryCreate(repoUrl, UriKind.Absolute, out var uri) - && uri.Scheme is "http" or "https" - && string.Equals(uri.Host, "github.com", StringComparison.OrdinalIgnoreCase); - } - - private static async Task PackWithRepomixWebApiAsync(string repoUrl, string includes) - { - using var http = new HttpClient(); - using var content = new MultipartFormDataContent - { - { new StringContent(repoUrl, Encoding.UTF8), "url" }, - { new StringContent("xml", Encoding.UTF8), "format" }, - { new StringContent(BuildRepomixWebOptions(includes), Encoding.UTF8), "options" } - }; - - using var response = await http.PostAsync("https://api.repomix.com/api/pack", content); - var body = await response.Content.ReadAsStringAsync(); - if (!response.IsSuccessStatusCode) - { - throw new InvalidOperationException($"Repomix web API returned HTTP {(int)response.StatusCode}."); - } - - foreach (var line in body.Split('\n', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)) - { - using var json = JsonDocument.Parse(line); - var root = json.RootElement; - if (root.TryGetProperty("type", out var type) && string.Equals(type.GetString(), "result", StringComparison.OrdinalIgnoreCase)) - { - return root.GetProperty("data").GetProperty("content").GetString() - ?? throw new InvalidOperationException("Repomix web API returned an empty result."); - } - - if (root.TryGetProperty("type", out var errorType) && string.Equals(errorType.GetString(), "error", StringComparison.OrdinalIgnoreCase)) - { - var message = root.TryGetProperty("message", out var messageElement) - ? messageElement.GetString() - : "Repomix web API returned an error."; - throw new InvalidOperationException(message); - } - } - - throw new InvalidOperationException("Repomix web API did not return a result event."); + return FilterLowSignalPackedContent(await PackWithLocalPackerAsync(cloneDir, includes)); } - private static string BuildRepomixWebOptions(string includes) - { - var options = new - { - removeComments = false, - removeEmptyLines = false, - showLineNumbers = false, - fileSummary = false, - directoryStructure = true, - includePatterns = includes, - outputParsable = false, - compress = false - }; - - return JsonSerializer.Serialize(options); - } - - private static async Task PackWithDotNetPackerAsync(string cloneDir, string includes) + private static async Task PackWithLocalPackerAsync(string cloneDir, string includes) { var includePatterns = includes .Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) .ToList(); - var files = Directory.EnumerateFiles(cloneDir, "*", SearchOption.AllDirectories) - .Select(path => new PackedFile(path, Path.GetRelativePath(cloneDir, path).Replace('\\', '/'))) + var files = (await GetTrackedFilesAsync(cloneDir)) .Where(file => ShouldIncludeFile(file.RelativePath, includePatterns)) .Where(file => !IsUnderSkippedDirectory(file.RelativePath)) .Where(file => !ShouldSkipLowSignalFile(file.RelativePath)) @@ -1354,8 +1221,8 @@ private static async Task PackWithDotNetPackerAsync(string cloneDir, str var doc = new XDocument( new XElement( "repository-context", - new XAttribute("generatedBy", "git-story-teller-dotnet-fallback"), - new XElement("note", "Repomix was unavailable, so this fallback packed selected text files with a simple .NET reader. It does not provide Repomix token counts, Secretlint checks, or exact gitignore semantics."), + new XAttribute("generatedBy", "git-story-teller-local-packer"), + new XElement("note", "Packed by the bundled git-story-teller C# runner from tracked files in the cloned repository. The packer uses git ls-files for deterministic repository membership, applies the runner include patterns, skips known generated or low-signal paths, and includes text files only."), new XElement("includePatterns", includePatterns.Select(pattern => new XElement("pattern", pattern))), new XElement("directoryStructure", BuildDirectoryStructure(files.Select(file => file.RelativePath))), filesElement)); @@ -1363,6 +1230,30 @@ private static async Task PackWithDotNetPackerAsync(string cloneDir, str return doc.ToString(SaveOptions.DisableFormatting); } + private static async Task> GetTrackedFilesAsync(string cloneDir) + { + var output = await RunProcessCaptureAsync("git", ["ls-files", "-z"], cloneDir); + return output + .Split('\0', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) + .Select(path => path.Replace('\\', '/')) + .Select(relativePath => new PackedFile(ResolveRepositoryPath(cloneDir, relativePath), relativePath)) + .OrderBy(file => file.RelativePath, StringComparer.OrdinalIgnoreCase) + .ToList(); + } + + private static string ResolveRepositoryPath(string cloneDir, string relativePath) + { + var fullPath = Path.GetFullPath(Path.Combine(cloneDir, relativePath.Replace('/', Path.DirectorySeparatorChar))); + var root = Path.GetFullPath(cloneDir).TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar) + + Path.DirectorySeparatorChar; + if (!fullPath.StartsWith(root, StringComparison.OrdinalIgnoreCase)) + { + throw new InvalidOperationException($"Git returned a path outside the cloned repository: '{relativePath}'."); + } + + return fullPath; + } + private static bool ShouldIncludeFile(string relativePath, IReadOnlyList includePatterns) => includePatterns.Any(pattern => MatchesIncludePattern(relativePath, pattern)); @@ -1404,7 +1295,7 @@ private static string FilterLowSignalPackedContent(string content) } catch { - // Repomix output is expected to be XML, but keep a text fallback for service changes. + // The packer emits XML; keep a text fallback in case a future shape changes. } var withoutFileBlocks = Regex.Replace( @@ -1485,36 +1376,6 @@ private static string BuildDirectoryStructure(IEnumerable relativePaths) return string.Join(Environment.NewLine, entries); } - private static string ResolveNpxExecutable() - { - if (!OperatingSystem.IsWindows()) - { - return "npx"; - } - - var programFiles = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles); - if (!string.IsNullOrWhiteSpace(programFiles)) - { - var nodeNpx = Path.Combine(programFiles, "nodejs", "npx.cmd"); - if (File.Exists(nodeNpx)) - { - return nodeNpx; - } - } - - var programFilesX86 = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86); - if (!string.IsNullOrWhiteSpace(programFilesX86)) - { - var nodeNpx = Path.Combine(programFilesX86, "nodejs", "npx.cmd"); - if (File.Exists(nodeNpx)) - { - return nodeNpx; - } - } - - return "npx.cmd"; - } - private static async Task WriteManifestAsync( string manifestPath, StoryOptions options, @@ -1570,6 +1431,11 @@ private static async Task WriteManifestAsync( } private static async Task RunProcessAsync(string executable, IReadOnlyList arguments, string workingDirectory, TimeSpan timeout = default) + { + await RunProcessCaptureAsync(executable, arguments, workingDirectory, timeout); + } + + private static async Task RunProcessCaptureAsync(string executable, IReadOnlyList arguments, string workingDirectory, TimeSpan timeout = default) { if (timeout == default) timeout = TimeSpan.FromMinutes(5); @@ -1612,6 +1478,8 @@ private static async Task RunProcessAsync(string executable, IReadOnlyList !string.IsNullOrWhiteSpace(s))); throw new InvalidOperationException($"'{executable}' failed with exit code {process.ExitCode}.{Environment.NewLine}{details}".Trim()); } + + return stdout; } private static void AppendHeader(StringBuilder sb, string value) @@ -1626,21 +1494,6 @@ private static async Task WriteUtf8Async(string path, string content) await File.WriteAllTextAsync(path, content, new UTF8Encoding(false)); } - private static void TryDeleteFile(string path) - { - try - { - if (File.Exists(path)) - { - File.Delete(path); - } - } - catch - { - // Temp cleanup failure should not hide the real result. - } - } - private static void TryDeleteDirectory(string path) { try @@ -1685,7 +1538,7 @@ result dir result - This script writes deterministic context only. - This script does not call an LLM. - Existing result/*.md files are not overwritten. - - Context packing prefers local Repomix, then the Repomix web API for GitHub HTTPS URLs, then the built-in .NET fallback. + - Context packing uses the bundled C# packer over the cloned repository's tracked files. """); } } From 414d9c72a9181ef4b3571210d7c97483482c6a13 Mon Sep 17 00:00:00 2001 From: "aicia[bot]" Date: Mon, 4 May 2026 22:03:34 +0200 Subject: [PATCH 3/4] =?UTF-8?q?=F0=9F=92=AC=20release=200.4.2=20with=20sim?= =?UTF-8?q?plified=20git-story-teller=20architecture?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 25 ++++++++++++++++++++++++- README.md | 7 +++---- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d983b2..5c47194 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,28 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), ## [Unreleased] +## [0.4.2] - 2026-05-04 + +This is a minor release focused on simplifying `git-story-teller` architecture by removing external dependencies and consolidating on a single deterministic local context packing strategy. The skill no longer depends on Node/npm, Repomix, or public packing services; instead, it performs a shallow git clone and uses the bundled C# packer to extract tracked files via `git ls-files`, making the skill fully self-contained and deterministic. + +### Changed + +- Refactored `git-story-teller` to remove Repomix-first architecture with web API and .NET fallback paths in favor of a single local C# packer, +- Updated `story.cs` to perform deterministic tracked-file discovery using `git ls-files -z` instead of filesystem enumeration, eliminating gitignore parsing and directory scanning variance, +- Removed HTTP client dependency and all Repomix integration code (`PackWithRepomixAsync`, `PackWithRepomixWebApiAsync`, `CanUseRepomixWebApi`, `BuildRepomixWebOptions`) from `story.cs`, +- Updated XML repository-context metadata to reflect the new "git-story-teller-local-packer" source and emit deterministic generation notes instead of fallback disclaimers, +- Updated SKILL.md description and runtime notes to document the shift from Repomix-first with fallbacks to single local packing path, +- Updated eval contract (eval 6) to verify that the runner no longer requires Node/npm, Repomix, or public packing services and recognizes the C# packer as the primary deterministic strategy, +- Added `.vs` to `.gitignore` to exclude Visual Studio settings folder, +- Updated README.md to reflect deterministic local file packing with `git ls-files` instead of external packing dependencies. + +### Removed + +- Repomix integration and all fallback-detection logic from `story.cs`, +- HTTP-based communication with the public Repomix web API, +- Node/npm executable resolution and `npx` invocation for `repomix` command execution, +- Optional Repomix token counts, Secretlint checks, and compression features from the packer output. + ## [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, plus clarifying `git-visual-squash-summary` emoji-first output conventions with explicit lowercase-start guidance. The `git-story-teller` 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. The `git-visual-squash-summary` skill clarifies its emoji-first output rule to start descriptions lowercase after the emoji unless a leading technical identifier requires original casing. @@ -190,7 +212,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.1...HEAD +[Unreleased]: https://github.com/codebeltnet/agentic/compare/v0.4.2...HEAD +[0.4.2]: https://github.com/codebeltnet/agentic/compare/v0.4.1...v0.4.2 [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 diff --git a/README.md b/README.md index eb494d9..c3edfbc 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,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 lowercase-start 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, 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. | +| [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/`, performs one shallow git clone, packs local tracked files with the bundled C# packer using `git ls-files` plus runner include patterns, 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. | @@ -287,9 +287,8 @@ Anthropic's `skill-creator` is an excellent base workflow, but the day-to-day fr 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 -- **Web API fallback** - if local Repomix cannot start and the input is a public GitHub HTTPS URL, posts the same pack request shape used by `https://repomix.com/` to the public Repomix API -- **Local fallback path** - if both Repomix paths are unavailable, uses a simple built-in .NET text packer so public/non-sensitive story work can still proceed +- **Single local packing path** - performs one shallow `git clone`, then packs tracked files from that clone with the bundled C# packer instead of calling Node/npm, Repomix, browser automation, or a public packing service +- **Deterministic file membership** - uses `git ls-files`, runner include patterns, text-file detection, generated-directory skips, and low-signal filtering so the context source is transparent and repeatable - **Repository-generic input** - starts from a full repository URL and an explicit output root instead of assuming an owner/slug convention - **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 From 834471b5d774b13a9bdad56c9f28cb6c172467f2 Mon Sep 17 00:00:00 2001 From: "aicia[bot]" Date: Mon, 4 May 2026 22:03:34 +0200 Subject: [PATCH 4/4] =?UTF-8?q?=F0=9F=99=88=20add=20.vs=20to=20gitignore?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index a86de9c..0035e34 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ desktop.ini .idea/ *.swp *.swo +.vs # Skill workspaces and eval artifacts (local only, not for sharing) skills/*-workspace/