Follow-up hygiene from the #1507 epic review (release blocker fixed in #1537):
- path-replacement.test.cjs: delete the hand-reimplemented computePathPrefix copy
(ADR-1508 said to); route all cases (incl. Windows + outside-home) through the
real _computePathPrefix so the test can no longer drift from the function.
- enh-1511: add an isWindowsHost no-op tripwire characterization test.
- enh-1511: add a deterministic (fs-method monkeypatch, root/OS-independent)
error-path test for applyRuntimeContentRewritesForCommandsInPlace — asserts the
temp dir is rm'd on a read failure with no orphaned gsd-cmd-rewrites-* leak.
- runtime-artifact-conversion.cts: @internal note on rewriteStagedCommandBodies
(deep-seam companion to rewriteStagedSkillBodies; no production caller today).
- ADR-1508 + CONTEXT.md: qualify the "single owner" claim with the deliberate
opencode/kilo applyOpencodeFamilyPathPrefix pre-conversion carve-out (#784).
No user-facing behavior change (tests + internal docs + one code comment).
Refs #1507.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
walk() collected dirents by extension only, then readFileSync'd each — so a
broken symlink named *.md (e.g. the gitignored CLAUDE.md worktree symlink whose
target is absent in a gsd-test Docker copy) crashed the #1073 guard with ENOENT.
It passed on a developer Mac (the symlink resolves) and in GitHub CI (CLAUDE.md
is gitignored/absent), failing only on the gsd-test-docker-from-worktree path —
a real error hiding behind the local environment, not a flake.
Guard the collection with entry.isFile() so symlinks (and other non-regular
dirents) are skipped deterministically on every platform; gitignored files are
not shipped repo text, so excluding CLAUDE.md is correct. Add a deterministic
regression test (dangling *.md symlink fixture, Windows-symlink-guarded with a
genuine t.skip) asserting walk() excludes the broken symlink and the read loop
never throws ENOENT.
Closes#1545.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
* fix(#1521): resolve own runtime + worktrees-off for all non-Claude installs
Generalizes the Codex-only #1515/#1519 fix to every non-Claude runtime, and
wires it into the real install path (where it was previously dead-on-arrival).
Root causes:
1. The runtime-default stamping lived only in `_applyRuntimeRewrites`, but the
installer emits `gsd-core/workflows/*.md` via `copyWithPathReplacement`, which
never calls it — so a real `--codex`/`--cursor`/etc. install emitted
`--default claude` and worktrees-on. RUNTIME mis-resolved to claude and the
workflow ran executors unisolated against the main checkout. (#1515/#1519 were
also dead-on-arrival in real installs; this repairs them.)
2. Only `case 'codex'` was stamped; every other non-Claude runtime kept the
Claude default.
Fix:
- New `_stampNonClaudeRuntimeDefaults(content, runtime)` (single shared helper)
stamps `--default <runtime>` + `use_worktrees=false` for every `runtime !=
claude`; called from both `_applyRuntimeRewrites` and, crucially,
`copyWithPathReplacement` in bin/install.js (the real workflow emit path).
- Generalize the fail-closed worktree guard `= codex` -> `!= claude` in
execute-phase/quick/diagnose-issues (worktree isolation is Claude-Code-only).
- Flip manager/autonomous inline-vs-background gating to `codex -> background,
everything-else -> inline` (research: only Codex can background-nest the
pipeline's subagents; all others run inline, which they support).
Worktree-capability determination is research-backed (official docs for all 14
non-Claude runtimes: none honor GSD's isolation="worktree" mechanism, only Codex
background-nests). New end-to-end real-install test asserts the EMITTED workflow
is stamped — the regression guard that would have caught the dead-on-arrival bug.
Closes#1521
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013vX5eUtWa2wsZEyeMf5i3r
* chore(#1521): backfill changeset PR number (#1537)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013vX5eUtWa2wsZEyeMf5i3r
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(#1515): make Codex installs resolve their own runtime and fail closed on worktrees
A Codex install with a runtime-neutral .planning/config.json resolved
RUNTIME=claude and enabled git worktree isolation, which Codex's
spawn_agent cannot honor. Two root causes:
1. Workflows read `config-get runtime` / `config-get workflow.use_worktrees`
without `--raw`, so config-get's JSON-quoted output ("codex") was captured
verbatim into the bash var and broke every `[ "$RUNTIME" = ... ]` check —
the Codex fail-closed guard was dead even when runtime:codex was explicit,
and Claude's own worktree degrade-check was dead too. Add `--raw` to those
reads across execute-phase, autonomous, manager, diagnose-issues, quick.
2. The conversion engine emitted `--default claude` for every runtime. Stamp
the codex-emitted workflows to `--default codex` (runtime) and
`--default false` (use_worktrees) in _applyRuntimeRewrites case 'codex', so
a neutral config on a Codex install resolves runtime=codex / worktrees off.
Also extend the Codex fail-closed worktree guard to quick.md and
diagnose-issues.md (they spawned isolation="worktree" with no runtime guard).
Regression test asserts source<->engine parity across all five workflows
(DEFECT.GENERATIVE-FIX) plus fast-check property coverage of the stamping.
Closes#1515
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013vX5eUtWa2wsZEyeMf5i3r
* chore(#1515): backfill changeset PR number (#1519)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013vX5eUtWa2wsZEyeMf5i3r
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The #1279 node-test machine-proof confirmed a known-bad subject drives the
negative test RED, but could not distinguish a genuine content-violation from a
deceptive test that reds merely because GSD_PROHIB_SUBJECT is set. Add an
optional fifth flat scalar `check_clean_fixture` (-> CheckDescriptor.cleanFixture)
threading a KNOWN-CLEAN control subject through projectProhibitions +
descriptorFromProjection. When present, the prover also runs the check against
the clean subject and requires GREEN, so fail-first is proven only when the check
is RED on the violation AND GREEN on the clean subject (content-dependent).
Opt-in and additive: absent a clean fixture the prover behaves exactly as
post-#1314 (no control, documented residual), preserving the zero-authoring
compose path; the lint-rule kind needs no analog (its subject IS the linted
file, no env indirection). Coverage: RED-first deceptive case, positive,
missing-clean fail-closed, round-trip read-back/emit, fast-check property
extended to the 5th scalar, and an end-to-end COMPOSE capstone (honest vs
deceptive). Docs: ADR-550 dated addendum, prohibition-probe reference,
spec-phase + verify-phase workflows.
Closes#1346
Claude-Session: https://claude.ai/code/session_01GsPRb8zvpcT7Eat6vZw8PX
* refactor(#1511): move content-rewrite engine to conversion module, delete the install.js relay
Phase 2 of epic #1507 (ADR-1508). Behavior-preserving: makes the Runtime
Artifact Conversion Module the single owner of per-runtime content rewriting and
removes the last upward .cts -> bin/install.js dependency.
- src/runtime-artifact-conversion.cts now owns the engine (_applyRuntimeRewrites,
5-arg with INJECTED attribution), the staged-content walkers
(applyRuntimeContentRewritesInPlace / ...ForCommandsInPlace), computePathPrefix
(private, exported as _computePathPrefix for tests), and the deep public seam
rewriteStagedSkillBodies / rewriteStagedCommandBodies({runtime, configDir,
scope, homedir?, platform?, resolveAttribution?}).
- src/surface.cts:applySurface calls rewriteStagedSkillBodies directly (no
resolveAttribution -> undefined). Co-Authored-By is absent from ALL rewritten
content, so processAttribution is vacuous there and undefined is provably
behavior-identical. surface no longer imports getInstallExports.
- src/runtime-artifact-layout.cts: deleted getInstallExports / loadInstallExports
/ InstallExports + the GSD_TEST_MODE require('bin/install.js') relay.
- bin/install.js: binds computePathPrefix / the two walkers / _applyRuntimeRewrites
from the conversion module (single implementation, exports preserved for Hyrum);
install callsites pass getCommitAttribution(runtime) as the injected attribution.
getCommitAttribution stays here (impure install-time config I/O).
- DEFECT.GENERATIVE-FIX guard: tests assert install.X === conversion.X reference
identity for computePathPrefix + both walkers (no drift).
New tests/enh-1511-*.test.cjs (engine, attribution injection, deep seam, prefix,
layout-no-relay guard, reference-identity). 316 affected-suite tests green; lint clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0187qgypdy1wkWRpdaf2hRuD
* test(#1511): make rewrite-engine path assertions Windows-robust
The deep seam normalizes paths as path.resolve(configDir).replace(/\\/g,'/')
and compares homedir().replace(/\\/g,'/'). Three assertions in the new test
rebuilt expected paths without that normalization, so they passed on Mac/Linux
but failed on Windows CI (PR #1513):
- two absolute-branch asserts rebuilt resolvedTarget via path.resolve(configDir)
without the backslash→slash replace → mismatch on Windows.
- the $HOME-branch test fed a POSIX-literal /home/testuser, which Windows
path.resolve re-roots onto the cwd drive (D:/home/...), so the
resolvedTarget.startsWith(homeDir) check failed and the $HOME shorthand was
never produced.
Fix is test-only (engine unchanged, still behavior-preserving): mirror the
engine's .replace(/\\/g,'/') in the two absolute-branch asserts, and use a real
absolute path (path.resolve(os.tmpdir(), ...)) + platform: process.platform for
the $HOME-branch test so the comparison holds on all platforms.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0187qgypdy1wkWRpdaf2hRuD
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Phase 1 of epic #1507 (ADR-1508): behavior-preserving relocation of the pure
rewrite-engine helpers out of the hand-authored installer so the conversion
module can own them without importing bin/install.js.
- getDirName -> src/runtime-name-policy.cts (pure runtime->dir-name switch).
- processAttribution -> src/runtime-artifact-conversion.cts (pure Co-Authored-By
content transform).
- bin/install.js imports both back via destructure/binding and re-exports
getDirName unchanged (Hyrum: install.test.cjs + runtime install tests import
getDirName from bin/install.js).
Two refinements to ADR-1508's Phase 1 (verified against the source):
- getCommitAttribution STAYS in bin/install.js: it is impure install-time
config I/O (reads runtime settings.json, uses install-time config-dir state +
attributionCache), not a content transform. Phase 2 will inject the resolved
attribution into the engine rather than move this function.
- The convertClaudeToAugmentMarkdown dedup is deferred to Phase 2's cleanup: the
local copy is entangled with a converter cluster (convertSlashCommandsTo
AugmentSkillMentions is used only by it; the family is partly dead-local via
the ...runtimeArtifactConversion export spread), deduping only augment would be
arbitrary, and it is not required to unblock Phase 2 (the engine will call the
conversion module's own copy when it moves).
New tests/enh-1510-*.test.cjs: getDirName at its new home (all runtimes +
fallback + install.js re-export identity) and processAttribution
(null/undefined/string/$-escape/CRLF/global). 487 affected-suite tests green.
Claude-Session: https://claude.ai/code/session_0187qgypdy1wkWRpdaf2hRuD
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Phase 0 of epic #1507. Records the decision to make the Runtime Artifact
Conversion Module the single owner of per-runtime content rewriting, flip the
dependency direction to installer/layout -> conversion, and close the
surface.cts -> bin/install.js getInstallExports relay. Doc-only.
Resolves ADR-3660 Initial-Scope deferral; distinct from epic #1258.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0187qgypdy1wkWRpdaf2hRuD
Proactive checkpoint guard fires at each wave boundary before spawning agents.
Self-assesses context pressure against context-budget.md degradation tiers and
warns (warn, default) or auto-invokes /gsd:pause-work (auto) when POOR tier
(70%+) is detected. Config key validated; defaults to \"warn\".
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
loadConfig() returns a flattened object with no nested `workflow` key, so
config?.workflow was always undefined, making drift_action permanently 'warn'
and drift_threshold permanently 3 regardless of .planning/config.json. Fixes
by reading the raw config.json directly (matching the pattern in
check-command-router.cts:readWorkflowConfig). Adds two behavioral regression
tests that fail under the old code and pass under the fix.
Closes#1493
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(#1498): regenerate capability-registry.cjs in npm version lifecycle hook
The version npm lifecycle script now runs gen-capability-registry.cjs --write
after sync-manifest-versions.cjs stamps all capability/*.json version fields.
Without this, every npm version X.Y.Z call left capability-registry.cjs stale
(capability JSONs got the new version string, but the registry still embedded
the old ones), causing gen-capability-registry.cjs --check to fail in the RC
test suite.
- package.json version script: add gen-capability-registry --write + git add
- tests/issue-844-manifest-version-sync.test.cjs: regression guard (describe F)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: backfill changeset pr: 1499
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(#1369): refresh wave manifest and re-check base before each wave in execute-phase
Two compounding issues caused wave N+1 worktrees to fork from the stale
pre-wave-N commit, immediately tripping the worktree_branch_check FATAL
guard in every executor:
1. worktree.base-check auto-degrade only ran once at initialize time.
After wave N merges advanced orchestrator HEAD past origin/HEAD, new
worktrees were still forked from origin/HEAD (Claude Code "fresh" base).
2. WAVE_WORKTREE_MANIFEST was never unset between waves, so wave N+1
reused the consumed wave-N manifest file, which would have blocked the
step 5.5 manifest guard (#3384) on subsequent waves.
Fix: add two safeguards in execute-phase.md —
- Step 0.5 (start of each wave): re-runs worktree.base-check; auto-degrades
USE_WORKTREES=false for that wave when HEAD has diverged from origin/HEAD.
- Step 7c (end of each wave): unsets WAVE_WORKTREE_MANIFEST so wave N+1
creates a fresh per-wave manifest; re-asserts worktree.set-baseref
(idempotent) and re-evaluates base degradation after wave merges land.
17 regression tests added in tests/bug-1369-wave-stale-base.test.cjs.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(#1369): rename test to fix-NNN convention; update workflow size baseline
Rename tests/bug-1369-wave-stale-base.test.cjs → tests/fix-1369-wave-stale-base.test.cjs
to satisfy the lint-regression-test-names gate (new files cannot use bug-NNN prefix).
Update tests/workflow-size-baseline.json for execute-phase.md: 93157 → 97393
(LF-normalized byte count after adding step 0.5 inter-wave base re-check and
step 7c between-wave manifest reset).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(#1369): add issue reference to allow-test-rule comment
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(#1369): extract new execute-phase steps to references; satisfy ADR-857 cap
Step 0.5 (inter-wave worktree base re-check) and steps 7b–7c (pre-wave
dependency check + between-wave manifest reset/base refresh) added by this
PR grew execute-phase.md to 97393 bytes, violating the ADR-857 phase-6
architectural mandate that host-loop bodies remain strictly below the
pre-phase-6 baseline of 93166 bytes.
Extract both new blocks into dedicated reference files:
- gsd-core/references/execute-phase-wave-guard.md (step 0.5)
- gsd-core/references/execute-phase-between-wave-reset.md (steps 7b + 7c)
Replace inline prose with @-reference pointers. File now measures 92851
bytes (LF-normalized), satisfying the ADR-857 capstone conformance gate.
Also update tests/workflow-size-baseline.json to 92851 and add both new
reference files to docs/INVENTORY-MANIFEST.json.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(#1369): update regression tests to read from extracted reference files
Steps 0.5 and 7b+7c were moved to reference files to satisfy the ADR-857
size cap on execute-phase.md. Tests now check @-reference pointers in the
workflow for ordering and read content assertions from the reference files.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* test(#1464): add behavioral manifest-validation test for capability tutorial docs
Extracts JSON capability manifests from tutorial/reference docs and validates
them through the real validateCapability — closing the test gap that let
issue #1464's broken tutorial manifest (step missing ref) pass undetected.
Adds fix-1464-docs-manifest-validation.test.cjs with:
- Suite 1: build/install/reference docs' complete manifests pass validateCapability
- Suite 2: adversarial fixtures prove the original #1464 bug shapes are caught
(step without ref → "steps[0].ref must be an object…"; id/folderId mismatch)
- Suite 3: extractManifests helper unit tests (complete vs. partial block filtering)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* test(#1496): allowlist docs module for 3-file test cluster
docs-parity-live-registry, docs-update, and the new
fix-1464-docs-manifest-validation sit on the same docs production
module; add the docs entry to lint-test-file-count.allowlist.json
so the novel-offender CI gate passes.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(#1453): clean up stale get-shit-done paths in Codex skill mirror on upgrade
Extends planLegacyCleanup in gsd-core/bin/lib/legacy-cleanup.cjs to scan
skills/gsd-* subdirectories for .md files that still embed the pre-rename
get-shit-done/ path (e.g. ~/.agents/skills/gsd-docs-update/SKILL.md).
These stale copies are removed by cleanupLegacyGsdCc during the next
install/upgrade so Codex can no longer discover and select them.
Adds 5 regression tests to tests/issue-607-legacy-cleanup.test.cjs covering
the stale path detection, non-flagging of fresh skills and user-owned dirs,
and the end-to-end ~/.agents/skills scenario from the issue.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(#1453): add gsd-allow-legacy-name markers to intentional legacy name references
Comments and test descriptions in legacy-cleanup.cjs and its test file
legitimately cite the old 'get-shit-done' directory name to explain what
the cleanup logic removes. Add the lint-exemption marker to each line so
lint-legacy-dir-name passes.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(#1445,#1446): exclude 999.x backlog phases from milestone totals; allow total_phases downward correction
#1445: deriveProgressFromRoadmap (phase-lifecycle.cts), the roadmapPhaseCount
loop (state.cts), and getMilestonePhaseFilter (roadmap-parser.cts) all now
skip phase tokens matching /^999\b/ — consistent with the existing init.cts
filter. 999.x backlog dirs are consequently excluded from phaseDirs too.
#1446: shouldPreserveExistingProgress (state-document.cts) no longer includes
total_phases in its ratchet check. total_phases always takes the freshly
derived value; only completed_phases, total_plans, and completed_plans retain
ratchet behaviour.
Regression tests added for both bugs.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore: add changeset for #1445/#1446 progress-backlog-exclusion-and-ratchet
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(#1445,#1446): rename test files to fix-NNN convention; fix changeset pr: null
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(#1437): add phase.list-plans to gsd-tools
Register phase.list-plans in PHASE_COMMAND_ALIASES, implement
cmdPhaseListPlans in src/phase.cts (uses findPhaseInternal + scanPhasePlans
to return plan_count/has_plans/plans/phase_dir), and wire the handler in
phase-command-router. Previously every call produced "Unknown phase
subcommand".
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(#1437): register new test file in lint-test-file-count allowlist
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(#1437): rename test to fix-NNN convention; update file-count allowlist
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(#1422): sub_repos config takes precedence over .git in findProjectRoot
When heuristic-3 (.git + parent .planning/) fires, do a lookahead walk
over ancestors above the matching parent to check if any further ancestor
has a sub_repos entry that explicitly claims the starting directory. If
found, return that ancestor instead — explicit config wins over the
implicit .git signal.
Regression tests updated: the heuristic-3 precedence test now asserts the
correct new behavior (sub_repos wins), and two additional coverage cases
added (startDir directly in sub_repo child, and startDir nested 2+ levels
inside the child).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(#1447): guard against uncommitted changes before deleting phase dirs in new-milestone
cmdPhasesClear now runs `git status --porcelain <phasesDir>` before
executing any rmSync. If uncommitted changes are detected it calls
error() and aborts, preventing silent data loss when new-milestone's
§6 "phases.clear --confirm" fires before the operator has archived
or committed outgoing phase work.
A new --force flag is added to bypass the guard for callers that have
already verified archival is done (or explicitly accept the loss).
When git is unavailable or the directory is not inside a git repo the
guard silently skips, preserving the existing behaviour for non-git
projects.
Five new regression tests cover: untracked files abort, staged-but-
uncommitted abort, --force bypasses, committed files pass, non-git
project passes without guard.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore: add changeset for #1422 and #1447
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: correct changeset format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(#1472,#1454): validate health workstream-aware paths; exclude active worktree from W017
#1472: cmdValidateHealth now uses planningRoot(cwd) for shared-root files
(PROJECT.md, config.json, MILESTONES.md) and planningDir(cwd) for
workstream-scoped files (ROADMAP.md, STATE.md, phases/). Previously a
single planningDir() call was used for all paths, causing false
E002/E003/E004/W003 when GSD_WORKSTREAM is set.
#1454: W017 no longer fires for a stale worktree whose path equals or is
an ancestor of process.cwd(), preventing advice to remove the active
session's own worktree.
Regression tests added for both bugs; all 40 existing health tests pass.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: correct changeset format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(#1478,#1479,#1480): prohibit ungrounded baselines, error-suppressing fallbacks, and stale-artifact authority in verify blocks
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore: add changeset for #1478/#1479/#1480 planner verify gate fix
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: correct changeset format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(#1478,#1479,#1480): fix test contract violations from new planner dimensions
gsd-planner.md exceeded both the planner-decomposition 48K char limit and
the reachability-check 50K char limit after the new HARD RULE blocks were
added inline. The full rule details already exist in planner-antipatterns.md
(added in the same PR); replace the verbose inline blocks with a single
@-reference pointer to the antipatterns file, reducing the file from 50981
to 49130 chars (under both limits).
Also regenerate tests/agent-size-baseline.json to reflect the new sizes of
gsd-planner.md and gsd-plan-checker.md.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
#2551/#3182/#2361 are pre-migration get-shit-done-redux issue numbers with no
equivalent in open-gsd/gsd-core; they mislead triage and manufacture phantom
blockers. Repoint to real successors (#717 byte-budget rework, #720) or rewrite
as prose referencing the discuss-phase/modes progressive-disclosure split.
Correct co-located 'line budget'/'<500 lines' framing to the byte-based reality
(#717). Add a CI guard (tests/no-phantom-issue-refs.test.cjs) that fails if a
phantom ref is reintroduced. SSH-key patterns (id_ed25519) left untouched.
No user-facing runtime behavior change.
Closes#1073
Add a worked example to the URL-import how-to showing how to install and
enable the projects-sync ADR-1244 ecosystem capability (published at
The-Artificer-of-Ciphers-LLC/projects-sync-capability). The capability ships
as an external installable repo; GSD Core gains the worked example only.
Closes#1010
Adds davesienkowski (write/maintain collaborator) to the all-paths
reviewer pool so they are auto-requested on PRs.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
* feat(#1435): capability matrix (generated + drift-guarded) + trust-model doc consolidation
ADR-1244 Phase 6. Adds the capability matrix reference, generated FROM the committed registry so it
can never drift from the actual capability set:
- scripts/gen-capability-matrix.cjs (--write / --check); --check is a CI drift guard.
- tests/capability-matrix-sync.test.cjs (4 tests): drift guard, buildMatrix==committed, every cap
present, no placeholders.
- docs/reference/capability-matrix.md regenerated from the registry (release-stable: shows engines.gsd,
omits the lockstep per-cap version that would churn the file every release).
- Consolidated the duplicate trust-model doc: deleted docs/explanation/the-capability-trust-model.md,
merged its content into capability-trust-model.md, redirected ~10 references; no stale links remain.
- Diataxis verification (now that gsd capability is a real command): corrected the matrix's third-party
section — the matrix is the first-party catalogue; the overlay-aware view of installed third-party
capabilities is 'gsd capability list', not this generated file.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* docs(#1435): Added changeset for the capability matrix reference
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix(#1435): address code-review — non-vacuous matrix test + generator polish
- capability-matrix-sync.test.cjs: assert the 'security registers a ship:pre gate' precondition
unconditionally so the extension-point check can never degrade to a vacuous pass on registry drift.
- gen-capability-matrix.cjs: warn (stderr) on an unknown loop point at generation time; rename
enginesOf -> fmtEngines for consistency with the other fmt* helpers (output unchanged).
- capability-trust-model.md: point the two how-to links at the real files
(import-a-capability-from-a-url.md, version-a-capability.md) instead of the bare directory.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* chore(#1435): backfill changeset PR number → #1458
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>