diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f917c9..f1ddb0e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,16 +8,18 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), ## [0.3.4] - 2026-04-24 -This is a patch release that hardens the .NET scaffold guidance around hidden asset recovery, making incomplete `npx skills add` installs easier to diagnose and repair before generation continues. The validator and repo docs now reinforce the same upstream-verification and manual-restore rule so local cache or packaging mismatches do not get mistaken for template defects. +This is a patch release that hardens the .NET scaffold guidance around hidden asset recovery and makes `git-keep-a-changelog` safer in yolo/auto mode. Incomplete `npx skills add` installs now pivot immediately to an upstream restore path driven by the shared asset manifest, while the changelog skill treats yolo/auto as an explicit full-autonomy mode instead of asking for scope confirmation. ### Changed -- Clarified `dotnet-new-app-slnx` and `dotnet-new-lib-slnx` so missing required or dot-prefixed files in an installed skill copy are treated as a local install mismatch first, with explicit upstream verification and manual restoration before continuing, -- Aligned the app and library variant references, `AGENTS.md`, and `README.md` with the same hidden-asset recovery rule so incomplete `npx skills add` copies get repaired consistently across the repo. +- Clarified `dotnet-new-app-slnx` and `dotnet-new-lib-slnx` so missing required or dot-prefixed files in an installed skill copy immediately trigger the manifest-driven restore path from upstream before generation continues, +- Aligned the app and library variant references, `AGENTS.md`, and `README.md` with the same hidden-asset recovery rule so incomplete `npx skills add` copies get repaired consistently across the repo, +- Expanded `git-keep-a-changelog` with an explicit yolo/auto mode that skips the pending-change confirmation gate and folds staged, unstaged, and untracked worktree changes into the draft automatically. ### Fixed -- Tightened `scripts/validate-skill-templates.ps1` so it now asserts the hidden-asset recovery wording in both scaffold references, keeping the validator synchronized with the documented install-fallback behavior. +- Tightened `scripts/validate-skill-templates.ps1` so it now asserts the shared hidden-asset recovery wording in both scaffold references, keeping the validator synchronized with the documented install-fallback behavior, +- Added validator coverage for the new manifest-driven restore guidance and the yolo/auto changelog bypass contract. ## [0.3.3] - 2026-03-25 diff --git a/README.md b/README.md index 11bdac7..963bf71 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,8 @@ npx skills add https://github.com/codebeltnet/agentic --skill skill-creator-agno npx skills add https://github.com/codebeltnet/agentic --skill markdown-illustrator npx skills add https://github.com/codebeltnet/agentic --skill trunk-first-repo npx skills add https://github.com/codebeltnet/agentic --skill dotnet-strong-name-signing +npx skills add https://github.com/codebeltnet/agentic --skill dotnet-new-app-slnx +npx skills add https://github.com/codebeltnet/agentic --skill dotnet-new-lib-slnx # npx skills add https://github.com/codebeltnet/agentic --skill another-skill ``` diff --git a/scripts/validate-skill-templates.ps1 b/scripts/validate-skill-templates.ps1 index 79975db..9282c84 100644 --- a/scripts/validate-skill-templates.ps1 +++ b/scripts/validate-skill-templates.ps1 @@ -389,7 +389,7 @@ Add-ValidationResult -Results $results -Name 'App skill documents web-family App Assert-Contains -Name 'dotnet-new-app-slnx/SKILL.md' -Content $skill -Needle 'expect MinVer to report a placeholder pre-release version such as `0.0.0-alpha.0` until the user initializes git and adds a version tag' Assert-Contains -Name 'dotnet-new-app-slnx/SKILL.md' -Content $skill -Needle 'The solution file must be named `{SOLUTION_NAME}.slnx`, not `{REPO_SLUG}.slnx` and not any lowercased variant.' Assert-Contains -Name 'dotnet-new-app-slnx/SKILL.md' -Content $skill -Needle 'The `.slnx` file is required even for single-host scaffolds.' - Assert-Contains -Name 'dotnet-new-app-slnx/SKILL.md' -Content $skill -Needle 'Every file from `assets/shared/` exists in the generated repo with the same relative path' + Assert-Contains -Name 'dotnet-new-app-slnx/SKILL.md' -Content $skill -Needle 'Every file listed in `assets/shared.manifest.json` exists in the generated repo at its declared relative path' Assert-Contains -Name 'dotnet-new-app-slnx/SKILL.md' -Content $skill -Needle 'No generated app or test `.csproj` file introduces ``' Assert-Contains -Name 'dotnet-new-app-slnx/SKILL.md' -Content $skill -Needle '{AppType} = Web' Assert-Contains -Name 'dotnet-new-app-slnx/SKILL.md' -Content $skill -Needle '{AppType} = Api' diff --git a/skills/dotnet-new-app-slnx/SKILL.md b/skills/dotnet-new-app-slnx/SKILL.md index 8cafea2..29ff373 100644 --- a/skills/dotnet-new-app-slnx/SKILL.md +++ b/skills/dotnet-new-app-slnx/SKILL.md @@ -6,6 +6,18 @@ description: > # .NET Application Solution Setup (Codebelt Conventions) +## Upstream Source + +| Field | Value | +|-------|-------| +| **Repo** | `https://github.com/codebeltnet/agentic` | +| **Branch** | `main` | +| **Shared assets root** | `skills/dotnet-new-app-slnx/assets/shared` | +| **Raw base URL** | `https://raw.githubusercontent.com/codebeltnet/agentic/main/skills/dotnet-new-app-slnx/assets/shared` | +| **Asset manifest** | `assets/shared.manifest.json` | + +This metadata is the single source of truth for restoring any file the installer may have dropped. Use it immediately — do not spend cycles confirming absence multiple ways first. + Scaffold new .NET standalone application solutions following the codebeltnet engineering conventions — the same pattern used across [codebeltnet](https://github.com/codebeltnet). Produces a fully wired solution with CI pipeline, centralized build config, semantic versioning, code quality tooling, and proper folder structure. > **CRITICAL:** All application projects **must** use the `Codebelt.Bootstrapper.*` framework — never vanilla `WebApplication.CreateBuilder()` or raw `Host.CreateDefaultBuilder()`. The bootstrapper provides a uniform, convention-driven `Program.cs` (and `Startup.cs` for classic hosting). The asset templates in `assets/app/` already wire this up correctly — **always copy from templates, never write Program.cs from scratch**. @@ -137,11 +149,11 @@ After writing `Directory.Packages.props`, re-check the generated versions agains Generate files in this order: ### 1. Copy shared templates -Copy every file from `assets/shared/` to the project root, preserving directory structure. Treat the **current working directory** as that project root. Apply placeholder substitution (Step 4) to all file contents during the copy. +Copy every file from `assets/shared/` to the project root, preserving directory structure. Do **not** copy `assets/shared.manifest.json` — it is a skill-internal file used only for asset validation and restoration, and must never appear in a generated solution. Treat the **current working directory** as that project root. Apply placeholder substitution (Step 4) to all file contents during the copy. Do this as a recursive, dotfile-aware copy. Hidden folders and files under `assets/shared/` are part of the scaffold and must not be skipped. In particular, copy `assets/shared/.bot/README.md` as a real file in the generated repo; do not replace it with a synthetic `.gitkeep` or placeholder note. -If the installed skill copy omits any required file or dot-prefixed path during a `npx skills add` copy, do not treat that as success or as a template defect. Verify the generated tree against the upstream repository contents, then manually restore the missing files directly from the repository source tree, preserving the same relative paths, before continuing. That includes hidden assets such as `.bot/`, `.github/`, and any other `.`-prefixed directories under `assets/shared/`. +**Asset mismatch policy — pivot immediately to upstream.** The `npx skills add` installer silently strips dot-prefixed entries (`.bot/`, `.github/`, `.editorconfig`, `.gitattributes`, `.gitignore`). Do not spend time re-proving what is absent. The moment any entry from `assets/shared.manifest.json` is missing from the installed skill copy, run `scripts/restore-missing-shared-assets.ps1` to fetch every missing file directly from the upstream repository in one step, then continue. If PowerShell is unavailable, use the raw base URL in the **Upstream Source** table above to download each missing file manually. If upstream fetch fails, halt and report — do not substitute placeholders. Do not selectively copy only "key" shared files. The intended output includes the complete shared asset inventory, including `.gitignore`, `.gitattributes`, `AGENTS.md`, `CHANGELOG.md`, `.github/`, and `.bot/`, in addition to the build and package-management files. @@ -180,8 +192,8 @@ After generating, verify: - [ ] `.slnx` references all generated src/ and test/ projects - [ ] The generated solution filename is `{SOLUTION_NAME}.slnx` with the original user-facing casing preserved -- [ ] Every file from `assets/shared/` exists in the generated repo with the same relative path, including dotfiles and dotfolders such as `.gitignore`, `.gitattributes`, `.bot/README.md`, and `.github/*` -- [ ] If a `npx skills add` install omitted any dot-prefixed files, manually restore them from the same repository commit before generation continues +- [ ] Every file listed in `assets/shared.manifest.json` exists in the generated repo at its declared relative path (this covers all dotfiles and dotfolders) +- [ ] If any manifest entry was absent from the installed skill copy, `scripts/restore-missing-shared-assets.ps1` was run (or files fetched manually from the upstream raw URL) — not diagnosed iteratively - [ ] `Directory.Packages.props` lists all `` packages used in the solution (including host-type-specific packages) - [ ] `Directory.Packages.props` contains concrete version numbers with no unresolved `*_VERSION` placeholders - [ ] No generated `.csproj` file or `Directory.Build.props` contains ad-hoc inline `Version=` attributes for packages that are supposed to be centrally managed by `Directory.Packages.props` @@ -194,7 +206,7 @@ After generating, verify: - [ ] `.bot/` folder exists and is listed in `.gitignore` - [ ] `.bot/README.md` exists in the generated repo and came from the shared asset template - [ ] `testenvironments.json` uses the major-tag `codebeltnet/ubuntu-testrunner:{major}` convention for the selected target framework -- [ ] If a `npx skills add` install omitted any required files, verify the upstream repository contents and manually restore the missing files directly from the repository source tree before generation continues +- [ ] No manifest entries were silently skipped; if the restore script reported failures, generation was halted rather than continuing with incomplete shared assets - [ ] Correct hosting pattern files generated (`Program.cs` only for Minimal, `Program.cs` + `Startup.cs` for Startup) - [ ] `Web API` is the default `web_variant` when the user asked for a generic `Web` app - [ ] `Empty Web` uses the `Web` suffix, `Web API` uses `Api`, `MVC` uses `Mvc`, and `Web App / Razor` uses `WebApp` diff --git a/skills/dotnet-new-app-slnx/assets/shared.manifest.json b/skills/dotnet-new-app-slnx/assets/shared.manifest.json new file mode 100644 index 0000000..b1ad1df --- /dev/null +++ b/skills/dotnet-new-app-slnx/assets/shared.manifest.json @@ -0,0 +1,25 @@ +{ + "description": "Authoritative inventory of all required shared scaffold assets, including dot-prefixed files and folders. Used to detect installer truncation and drive restoration from upstream.", + "upstream": { + "repo": "https://github.com/codebeltnet/agentic", + "branch": "main", + "root": "skills/dotnet-new-app-slnx/assets/shared" + }, + "files": [ + ".bot/README.md", + ".editorconfig", + ".gitattributes", + ".github/CODE_OF_CONDUCT.md", + ".github/CONTRIBUTING.md", + ".github/copilot-instructions.md", + ".github/dependabot.yml", + ".github/workflows/ci-pipeline.yml", + ".gitignore", + "AGENTS.md", + "CHANGELOG.md", + "Directory.Build.targets", + "Directory.Packages.props", + "README.md", + "testenvironments.json" + ] +} diff --git a/skills/dotnet-new-app-slnx/scripts/restore-missing-shared-assets.ps1 b/skills/dotnet-new-app-slnx/scripts/restore-missing-shared-assets.ps1 new file mode 100644 index 0000000..3f670ac --- /dev/null +++ b/skills/dotnet-new-app-slnx/scripts/restore-missing-shared-assets.ps1 @@ -0,0 +1,105 @@ +<# +.SYNOPSIS + Detects missing shared scaffold assets (including dotfiles) and restores them + directly from the upstream repository. + +.DESCRIPTION + Reads assets/shared.manifest.json, checks each required path relative to the + skill root, and downloads any missing file from the authoritative GitHub source. + Exits with code 1 if upstream fetch fails for any file. + +.PARAMETER SkillRoot + Absolute path to the installed skill directory (parent of assets/). + Defaults to the directory containing this script's parent. + +.PARAMETER DryRun + Report missing files without downloading them. + +.EXAMPLE + # Restore missing files into the installed skill copy + scripts/restore-missing-shared-assets.ps1 + + # Preview what is missing without restoring + scripts/restore-missing-shared-assets.ps1 -DryRun +#> +[CmdletBinding()] +param( + [string] $SkillRoot = (Split-Path -Parent $PSScriptRoot), + [switch] $DryRun +) + +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' + +$manifestPath = Join-Path $SkillRoot 'assets/shared.manifest.json' +if (-not (Test-Path $manifestPath)) { + Write-Error "Manifest not found at: $manifestPath" + exit 1 +} + +$manifest = Get-Content $manifestPath -Raw | ConvertFrom-Json +$repoUrl = $manifest.upstream.repo # e.g. https://github.com/codebeltnet/agentic +$branch = $manifest.upstream.branch # e.g. main +$remoteRoot = $manifest.upstream.root # e.g. skills/dotnet-new-app-slnx/assets/shared +$localRoot = Join-Path $SkillRoot 'assets/shared' + +# Build raw-content base URL +$rawBase = $repoUrl -replace 'https://github.com', 'https://raw.githubusercontent.com' +$rawBase = "$rawBase/$branch/$remoteRoot" + +$missing = [System.Collections.Generic.List[string]]::new() +$restored = [System.Collections.Generic.List[string]]::new() +$failed = [System.Collections.Generic.List[string]]::new() + +foreach ($file in $manifest.files) { + $localPath = Join-Path $localRoot $file + if (-not (Test-Path $localPath)) { + $missing.Add($file) + } +} + +if ($missing.Count -eq 0) { + Write-Host "✅ All shared assets present — nothing to restore." -ForegroundColor Green + exit 0 +} + +Write-Host "⚠️ Missing shared assets ($($missing.Count)):" -ForegroundColor Yellow +$missing | ForEach-Object { Write-Host " - $_" } + +if ($DryRun) { + Write-Host "`n[DryRun] No files downloaded." -ForegroundColor Cyan + exit 0 +} + +Write-Host "`nRestoring from upstream: $repoUrl (branch: $branch)" -ForegroundColor Cyan + +foreach ($file in $missing) { + $url = "$rawBase/$file" + $dest = Join-Path $localRoot $file + $destDir = Split-Path $dest -Parent + + if (-not (Test-Path $destDir)) { + New-Item -ItemType Directory -Path $destDir -Force | Out-Null + } + + try { + Write-Host " ↓ $file" -NoNewline + Invoke-WebRequest -Uri $url -OutFile $dest -UseBasicParsing + $restored.Add($file) + Write-Host " ✓" -ForegroundColor Green + } + catch { + $failed.Add($file) + Write-Host " ✗ ($($_.Exception.Message))" -ForegroundColor Red + } +} + +if ($restored.Count -gt 0) { + Write-Host "`n✅ Restored $($restored.Count) file(s)." -ForegroundColor Green +} + +if ($failed.Count -gt 0) { + Write-Host "❌ Failed to restore $($failed.Count) file(s):" -ForegroundColor Red + $failed | ForEach-Object { Write-Host " - $_" } + exit 1 +} diff --git a/skills/dotnet-new-lib-slnx/SKILL.md b/skills/dotnet-new-lib-slnx/SKILL.md index 630efe6..b2ce853 100644 --- a/skills/dotnet-new-lib-slnx/SKILL.md +++ b/skills/dotnet-new-lib-slnx/SKILL.md @@ -6,6 +6,18 @@ description: > # .NET Library Solution Setup (Codebelt Conventions) +## Upstream Source + +| Field | Value | +|-------|-------| +| **Repo** | `https://github.com/codebeltnet/agentic` | +| **Branch** | `main` | +| **Shared assets root** | `skills/dotnet-new-lib-slnx/assets/shared` | +| **Raw base URL** | `https://raw.githubusercontent.com/codebeltnet/agentic/main/skills/dotnet-new-lib-slnx/assets/shared` | +| **Asset manifest** | `assets/shared.manifest.json` | + +This metadata is the single source of truth for restoring any file the installer may have dropped. Use it immediately — do not spend cycles confirming absence multiple ways first. + Scaffold new .NET NuGet library solutions following the codebeltnet engineering conventions — the same pattern used across [codebeltnet](https://github.com/codebeltnet). Produces a fully wired solution with multi-target framework support, strong-name signing, NuGet packaging, DocFX documentation, CI pipeline, centralized build config, semantic versioning, and code quality tooling. Generate the scaffold **in the user's current working directory**. Do not create an extra top-level `{REPO_SLUG}` or `{SOLUTION_NAME}` folder unless the user explicitly asks for a nested output folder. @@ -86,11 +98,11 @@ When copying template files, replace these placeholders in file contents: Generate files in this order: ### 1. Copy shared templates -Copy every file from `assets/shared/` to the project root, preserving directory structure. Treat the **current working directory** as that project root. Apply placeholder substitution (Step 4) to all file contents during the copy. +Copy every file from `assets/shared/` to the project root, preserving directory structure. Do **not** copy `assets/shared.manifest.json` — it is a skill-internal file used only for asset validation and restoration, and must never appear in a generated solution. Treat the **current working directory** as that project root. Apply placeholder substitution (Step 4) to all file contents during the copy. Do this as a recursive, dotfile-aware copy. Hidden folders and files under `assets/shared/` are part of the scaffold and must not be skipped. In particular, copy `assets/shared/.bot/README.md` as a real file in the generated repo; do not replace it with a synthetic `.gitkeep` or placeholder note. -If the installed skill copy omits any required file or dot-prefixed path during a `npx skills add` copy, do not treat that as success or as a template defect. Verify the generated tree against the upstream repository contents, then manually restore the missing files directly from the repository source tree, preserving the same relative paths, before continuing. That includes hidden assets such as `.bot/`, `.github/`, `.docfx/`, and any other `.`-prefixed directories under `assets/library/` or `assets/shared/`. +**Asset mismatch policy — pivot immediately to upstream.** The `npx skills add` installer silently strips dot-prefixed entries (`.bot/`, `.github/`, `.editorconfig`, `.gitattributes`, `.gitignore`). Do not spend time re-proving what is absent. The moment any entry from `assets/shared.manifest.json` is missing from the installed skill copy, run `scripts/restore-missing-shared-assets.ps1` to fetch every missing file directly from the upstream repository in one step, then continue. If PowerShell is unavailable, use the raw base URL in the **Upstream Source** table above to download each missing file manually. If upstream fetch fails, halt and report — do not substitute placeholders. Preserve UTF-8 when reading, copying, and writing text files. Do not transcode templates to ANSI, OEM, Windows-1252, or any system-default code page during generation. The shared `.editorconfig` in the scaffold declares `charset = utf-8`, and generated text files should match it from the start. @@ -176,7 +188,9 @@ After generating, verify: - [ ] `.github/copilot-instructions.md` has project-specific patterns - [ ] `.bot/` folder exists and is listed in `.gitignore` - [ ] `.bot/README.md` exists in the generated repo and came from the shared asset template, not from a synthetic `.gitkeep` fallback -- [ ] If a `npx skills add` install omitted any required files, verify the upstream repository contents and manually restore the missing files directly from the repository source tree before generation continues +- [ ] Every file listed in `assets/shared.manifest.json` exists in the generated repo at its declared relative path (this covers all dotfiles and dotfolders) +- [ ] If any manifest entry was absent from the installed skill copy, `scripts/restore-missing-shared-assets.ps1` was run (or files fetched manually from the upstream raw URL) — not diagnosed iteratively +- [ ] No manifest entries were silently skipped; if the restore script reported failures, generation was halted rather than continuing with incomplete shared assets - [ ] `.github/dependabot.yml` watches the repo root so central NuGet package management stays current after scaffolding Summarize what was generated and note any manual steps (e.g. registering with SonarCloud, populating `.docfx/images/` with logo/favicon). diff --git a/skills/dotnet-new-lib-slnx/assets/shared.manifest.json b/skills/dotnet-new-lib-slnx/assets/shared.manifest.json new file mode 100644 index 0000000..08f8d17 --- /dev/null +++ b/skills/dotnet-new-lib-slnx/assets/shared.manifest.json @@ -0,0 +1,27 @@ +{ + "description": "Authoritative inventory of all required shared scaffold assets, including dot-prefixed files and folders. Used to detect installer truncation and drive restoration from upstream.", + "upstream": { + "repo": "https://github.com/codebeltnet/agentic", + "branch": "main", + "root": "skills/dotnet-new-lib-slnx/assets/shared" + }, + "files": [ + ".bot/README.md", + ".editorconfig", + ".gitattributes", + ".github/CODE_OF_CONDUCT.md", + ".github/codecov.yml", + ".github/CONTRIBUTING.md", + ".github/copilot-instructions.md", + ".github/dependabot.yml", + ".github/workflows/ci-pipeline.yml", + ".gitignore", + "AGENTS.md", + "CHANGELOG.md", + "Directory.Build.targets", + "Directory.Packages.props", + "LICENSE", + "README.md", + "testenvironments.json" + ] +} diff --git a/skills/dotnet-new-lib-slnx/scripts/restore-missing-shared-assets.ps1 b/skills/dotnet-new-lib-slnx/scripts/restore-missing-shared-assets.ps1 new file mode 100644 index 0000000..c634f40 --- /dev/null +++ b/skills/dotnet-new-lib-slnx/scripts/restore-missing-shared-assets.ps1 @@ -0,0 +1,105 @@ +<# +.SYNOPSIS + Detects missing shared scaffold assets (including dotfiles) and restores them + directly from the upstream repository. + +.DESCRIPTION + Reads assets/shared.manifest.json, checks each required path relative to the + skill root, and downloads any missing file from the authoritative GitHub source. + Exits with code 1 if upstream fetch fails for any file. + +.PARAMETER SkillRoot + Absolute path to the installed skill directory (parent of assets/). + Defaults to the directory containing this script's parent. + +.PARAMETER DryRun + Report missing files without downloading them. + +.EXAMPLE + # Restore missing files into the installed skill copy + scripts/restore-missing-shared-assets.ps1 + + # Preview what is missing without restoring + scripts/restore-missing-shared-assets.ps1 -DryRun +#> +[CmdletBinding()] +param( + [string] $SkillRoot = (Split-Path -Parent $PSScriptRoot), + [switch] $DryRun +) + +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' + +$manifestPath = Join-Path $SkillRoot 'assets/shared.manifest.json' +if (-not (Test-Path $manifestPath)) { + Write-Error "Manifest not found at: $manifestPath" + exit 1 +} + +$manifest = Get-Content $manifestPath -Raw | ConvertFrom-Json +$repoUrl = $manifest.upstream.repo # e.g. https://github.com/codebeltnet/agentic +$branch = $manifest.upstream.branch # e.g. main +$remoteRoot = $manifest.upstream.root # e.g. skills/dotnet-new-lib-slnx/assets/shared +$localRoot = Join-Path $SkillRoot 'assets/shared' + +# Build raw-content base URL +$rawBase = $repoUrl -replace 'https://github.com', 'https://raw.githubusercontent.com' +$rawBase = "$rawBase/$branch/$remoteRoot" + +$missing = [System.Collections.Generic.List[string]]::new() +$restored = [System.Collections.Generic.List[string]]::new() +$failed = [System.Collections.Generic.List[string]]::new() + +foreach ($file in $manifest.files) { + $localPath = Join-Path $localRoot $file + if (-not (Test-Path $localPath)) { + $missing.Add($file) + } +} + +if ($missing.Count -eq 0) { + Write-Host "✅ All shared assets present — nothing to restore." -ForegroundColor Green + exit 0 +} + +Write-Host "⚠️ Missing shared assets ($($missing.Count)):" -ForegroundColor Yellow +$missing | ForEach-Object { Write-Host " - $_" } + +if ($DryRun) { + Write-Host "`n[DryRun] No files downloaded." -ForegroundColor Cyan + exit 0 +} + +Write-Host "`nRestoring from upstream: $repoUrl (branch: $branch)" -ForegroundColor Cyan + +foreach ($file in $missing) { + $url = "$rawBase/$file" + $dest = Join-Path $localRoot $file + $destDir = Split-Path $dest -Parent + + if (-not (Test-Path $destDir)) { + New-Item -ItemType Directory -Path $destDir -Force | Out-Null + } + + try { + Write-Host " ↓ $file" -NoNewline + Invoke-WebRequest -Uri $url -OutFile $dest -UseBasicParsing + $restored.Add($file) + Write-Host " ✓" -ForegroundColor Green + } + catch { + $failed.Add($file) + Write-Host " ✗ ($($_.Exception.Message))" -ForegroundColor Red + } +} + +if ($restored.Count -gt 0) { + Write-Host "`n✅ Restored $($restored.Count) file(s)." -ForegroundColor Green +} + +if ($failed.Count -gt 0) { + Write-Host "❌ Failed to restore $($failed.Count) file(s):" -ForegroundColor Red + $failed | ForEach-Object { Write-Host " - $_" } + exit 1 +} diff --git a/skills/git-keep-a-changelog/FORMS.md b/skills/git-keep-a-changelog/FORMS.md index 58528e2..0b49965 100644 --- a/skills/git-keep-a-changelog/FORMS.md +++ b/skills/git-keep-a-changelog/FORMS.md @@ -1,6 +1,6 @@ # Parameter Form -Use this form only when pending worktree changes are detected and the skill must ask whether they belong in the changelog draft. This is the mandatory Step 3 confirmation gate for concrete releases. Present each field **one at a time** using the host's native structured input controls when available. If native controls are unavailable, use the deterministic plain-text fallback below. Do not use this form when there are no pending changes to confirm. +Use this form only when pending worktree changes are detected and the skill must ask whether they belong in the changelog draft. This is the mandatory Step 3 confirmation gate for concrete releases. Present each field **one at a time** using the host's native structured input controls when available. If native controls are unavailable, use the deterministic plain-text fallback below. Do not use this form when there are no pending changes to confirm. **Do not use this form when yolo/auto mode is active — Step 3 is skipped entirely and all pending changes are included automatically.** ## Fields @@ -58,4 +58,4 @@ Use this form only when pending worktree changes are detected and the skill must Proceed with this changelog scope? ``` -9. Do not skip this gate when the target is a concrete release, even if the user's request says `include everything`, `all changes`, `commit manually`, or `don't ask`. +9. Do not skip this gate when the target is a concrete release, even if the user's request says `include everything`, `all changes`, `commit manually`, or `don't ask`. **Do not use this form at all when the user's request contains `yolo` or `auto` — the gate is bypassed and all pending changes are included automatically.** diff --git a/skills/git-keep-a-changelog/SKILL.md b/skills/git-keep-a-changelog/SKILL.md index 4cc3318..693ba61 100644 --- a/skills/git-keep-a-changelog/SKILL.md +++ b/skills/git-keep-a-changelog/SKILL.md @@ -1,7 +1,7 @@ --- name: git-keep-a-changelog description: > - Create or update CHANGELOG.md from git history using Keep a Changelog 1.1.0 style. Use when the user asks to create/update changelog, draft release notes, or mentions SemVer-aware summaries. Trigger phrases: "finalize", "ready to release", "rtr", "release" (especially with version branches like v0.3.1/...). Reads full commit bodies and diffs, creates compliant structure with required SemVer highlights, infers versions from branches, must ask a mandatory Yes / No / Custom confirmation question before including pending staged, unstaged, or untracked worktree changes in a concrete release draft, edits directly for review, preserves prose wrapping, avoids commit-log dumps. + Create or update CHANGELOG.md from git history using Keep a Changelog 1.1.0 style. Use when the user asks to create/update changelog, draft release notes, or mentions SemVer-aware summaries. Trigger phrases: "finalize", "ready to release", "rtr", "release" (especially with version branches like v0.3.1/...), "yolo", "auto". Reads full commit bodies and diffs, creates compliant structure with required SemVer highlights, infers versions from branches, must ask a mandatory Yes / No / Custom confirmation question before including pending staged, unstaged, or untracked worktree changes in a concrete release draft (bypassed in yolo/auto mode — all changes included automatically), edits directly for review, preserves prose wrapping, avoids commit-log dumps. --- # Git Keep A Changelog @@ -10,7 +10,17 @@ description: > This skill creates or updates `CHANGELOG.md` directly using the Keep a Changelog 1.1.0 structure. It is git-aware, changelog-focused, and optimized for a human-readable release summary rather than generated release-note noise. -Read `FORMS.md` when pending worktree changes require user confirmation and the host supports native structured input controls. If native structured input is unavailable, use the deterministic plain-text fallback defined there. +Read `FORMS.md` when pending worktree changes require user confirmation and the host supports native structured input controls. If native structured input is unavailable, use the deterministic plain-text fallback defined there. `FORMS.md` is not used in yolo/auto mode — see **Yolo / Auto Mode** below. + +## Yolo / Auto Mode + +When the user's request contains `yolo` or `auto` (case-insensitive, anywhere in the message), the skill operates in full-autonomy mode: + +- **Skip Step 3 entirely.** Do not ask the confirmation question. Do not present the `Yes / No / Custom` gate. +- **Include all pending changes automatically.** Staged, unstaged, and untracked files are all treated as part of the release scope without asking. +- **Make all scope decisions independently.** The user has explicitly delegated judgment. Do not pause for input at any point in the workflow. +- All other quality rules remain in force: the release highlight is still required, the SemVer classification is still required, bullet punctuation still applies, and the compare-link footer must still be maintained. +- Yolo/auto is a user signal of full autonomy — not a shortcut past quality. Treat it as deliberate and act on it immediately. ## Non-Negotiable Rules @@ -27,7 +37,7 @@ Read `FORMS.md` when pending worktree changes require user confirmation and the - Always maintain the Keep a Changelog compare-link footer at the bottom of the file. - Preserve natural line breaks and readable prose. Do not apply any fixed column limit or artificial hard wrapping to changelog paragraphs or bullets. - End each bullet with `,` and end the last bullet in each section with `.`. -- If pending worktree changes exist for a concrete release draft, do not silently include or exclude them. Ask the user first with a short `Yes / No / Custom` prompt. +- If pending worktree changes exist for a concrete release draft, do not silently include or exclude them. Ask the user first with a short `Yes / No / Custom` prompt. **Exception: in yolo/auto mode, include all pending changes automatically without asking.** - Do not dump commit subjects verbatim into the changelog. - Do not invent unsupported changes, risks, or migration guidance. @@ -35,7 +45,7 @@ Read `FORMS.md` when pending worktree changes require user confirmation and the These checkpoints cannot be skipped or bypassed, even when the user's opening request sounds like a shortcut. -1. Step 3 confirmation gate: if pending worktree changes exist for a concrete release such as `## [1.2.3]`, present the confirmation question before drafting or writing the changelog entry. +1. Step 3 confirmation gate: if pending worktree changes exist for a concrete release such as `## [1.2.3]`, present the confirmation question before drafting or writing the changelog entry. **Bypassed in yolo/auto mode — all pending changes are included automatically.** 2. Release highlight contract: every concrete release entry must include a release highlight paragraph that explicitly classifies the release as `major`, `minor`, or `patch`. 3. Bullet punctuation: all bullets must end with `,` except the final bullet in each populated section, which must end with `.` Do not finish the edit until this is consistent. @@ -85,6 +95,8 @@ Explicit instructions such as `staged only`, `include unstaged changes`, or `exc The Step 3 confirmation gate exists to prevent silent inclusion of worktree changes in a permanent release entry. It is a required safety checkpoint, not optional friction. +**Exception — yolo/auto bypasses the gate by design.** When the user explicitly passes `yolo` or `auto`, they are granting full autonomy. That is not a vague hint like `include everything` — it is a deliberate, recognized mode. Skip Step 3, include all pending changes, and proceed. + ### Why this matters Silent inclusion of pending changes in a changelog is a production risk. The gate ensures the release scope is intentional, visible, and explicitly confirmed before the draft becomes part of the project's recorded release history. @@ -132,6 +144,8 @@ This is a required checkpoint. Do not proceed to Step 4 until this step is compl After resolving the target heading, check whether the worktree contains changes that are not part of the committed history yet. +**If yolo/auto mode is active: skip this entire step.** Include all pending changes (staged, unstaged, untracked) automatically and proceed to Step 4. + - Count staged, unstaged, and untracked changes separately. - If there are no pending changes, continue normally. - If there are pending changes and the target is a concrete release heading such as `## [1.2.3]`, you must ask a direct confirmation question before drafting the changelog entry. @@ -227,7 +241,7 @@ After updating `CHANGELOG.md`, stop and let the user review the file. Do not com - Includes a required SemVer-aware release highlight. - Creates a compliant `CHANGELOG.md` scaffold when the file is missing. - Reflects the meaning of full commit bodies and the net diff. -- Treats Step 3 as a mandatory confirmation gate for concrete releases and asks the `Yes / No / Custom` question before including pending worktree changes. +- Treats Step 3 as a mandatory confirmation gate for concrete releases and asks the `Yes / No / Custom` question before including pending worktree changes (or skips Step 3 entirely and includes all changes when yolo/auto mode is active). - Maintains or inserts the compare-link footer at the bottom of the file on both create and update paths. - Preserves natural prose wrapping with no fixed column-width target. - Keeps bullets specific, concrete, non-repetitive, and consistently punctuated. @@ -239,7 +253,7 @@ After updating `CHANGELOG.md`, stop and let the user review the file. Do not com - Omitting the release highlight. - Failing to classify the release as major, minor, or patch. - Refusing to proceed just because `CHANGELOG.md` does not exist yet. -- Silently including, silently ignoring, or otherwise bypassing the pending-worktree confirmation gate for a concrete release draft. +- Silently including, silently ignoring, or otherwise bypassing the pending-worktree confirmation gate for a concrete release draft (bypassing via explicit `yolo` or `auto` is intentional, not silent). - Using any artificial fixed-width wrapping for changelog prose. - Mixing bullet punctuation or leaving section bullets without the required trailing `,` / final `.` pattern. - Emitting empty `Added` / `Changed` / `Fixed` headings.