@opengsd/gsd-core 1.9.0 → 1.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +2 -3
- package/.opencode/plugins/gsd-core.js +8 -1
- package/agents/gsd-code-fixer.md +131 -34
- package/agents/gsd-debugger.md +12 -246
- package/agents/gsd-executor.md +7 -5
- package/agents/gsd-integration-checker.md +3 -0
- package/agents/gsd-plan-checker.md +9 -0
- package/agents/gsd-planner.md +5 -8
- package/agents/gsd-roadmapper.md +21 -3
- package/agents/gsd-verifier.md +14 -70
- package/bin/install.js +503 -341
- package/commands/gsd/mempalace-capture.md +1 -1
- package/commands/gsd/new-milestone.md +1 -1
- package/commands/gsd/plan-phase.md +1 -1
- package/gsd-core/bin/gsd-tools.cjs +607 -63
- package/gsd-core/bin/lib/active-workstream-store.cjs +25 -0
- package/gsd-core/bin/lib/agent-install-check.cjs +38 -6
- package/gsd-core/bin/lib/api-coverage.cjs +120 -0
- package/gsd-core/bin/lib/audit.cjs +89 -1
- package/gsd-core/bin/lib/broken-windows.cjs +36 -6
- package/gsd-core/bin/lib/capability-registry.cjs +96 -110
- package/gsd-core/bin/lib/capability-validator.cjs +12 -2
- package/gsd-core/bin/lib/check-command-router.cjs +43 -1
- package/gsd-core/bin/lib/command-aliases.cjs +72 -0
- package/gsd-core/bin/lib/commands.cjs +26 -25
- package/gsd-core/bin/lib/commonjs-marker.cjs +136 -0
- package/gsd-core/bin/lib/config-loader.cjs +1 -0
- package/gsd-core/bin/lib/config.cjs +12 -1
- package/gsd-core/bin/lib/context-composer.cjs +278 -0
- package/gsd-core/bin/lib/context-predicates.cjs +506 -0
- package/gsd-core/bin/lib/core-utils.cjs +91 -12
- package/gsd-core/bin/lib/docs.cjs +3 -2
- package/gsd-core/bin/lib/external-job.cjs +19 -4
- package/gsd-core/bin/lib/frontmatter.cjs +84 -12
- package/gsd-core/bin/lib/gate-predicate-evaluator.cjs +57 -6
- package/gsd-core/bin/lib/git-base-branch.cjs +58 -15
- package/gsd-core/bin/lib/graphify.cjs +142 -27
- package/gsd-core/bin/lib/gsd2-import.cjs +27 -4
- package/gsd-core/bin/lib/host-integration.cjs +13 -1
- package/gsd-core/bin/lib/init-command-router.cjs +83 -8
- package/gsd-core/bin/lib/init.cjs +1021 -57
- package/gsd-core/bin/lib/install-engine.cjs +64 -10
- package/gsd-core/bin/lib/install-profiles.cjs +27 -1
- package/gsd-core/bin/lib/installer-migration-authoring.cjs +3 -1
- package/gsd-core/bin/lib/installer-migration-report.cjs +4 -0
- package/gsd-core/bin/lib/installer-migrations/007-retire-config-root-commonjs-marker.cjs +149 -0
- package/gsd-core/bin/lib/installer-migrations/008-cursor-retire-commands-surface.cjs +55 -0
- package/gsd-core/bin/lib/installer-migrations/009-pi-retire-reserved-hooks-dir.cjs +199 -0
- package/gsd-core/bin/lib/installer-migrations.cjs +87 -1
- package/gsd-core/bin/lib/io.cjs +28 -3
- package/gsd-core/bin/lib/markdown-sectionizer.cjs +6 -0
- package/gsd-core/bin/lib/mcp-catalog.cjs +518 -0
- package/gsd-core/bin/lib/mcp-server.cjs +135 -3
- package/gsd-core/bin/lib/milestone.cjs +106 -51
- package/gsd-core/bin/lib/phase-id.cjs +63 -0
- package/gsd-core/bin/lib/phase-locator.cjs +138 -45
- package/gsd-core/bin/lib/phase.cjs +260 -25
- package/gsd-core/bin/lib/plan-dependency-graph.cjs +232 -0
- package/gsd-core/bin/lib/planning-workspace.cjs +4 -0
- package/gsd-core/bin/lib/project-root.cjs +48 -0
- package/gsd-core/bin/lib/prompt-budget.cjs +128 -165
- package/gsd-core/bin/lib/retired-artifact-cleanup.cjs +80 -0
- package/gsd-core/bin/lib/review-lane-descriptor.cjs +99 -0
- package/gsd-core/bin/lib/review-lane-runner.cjs +30 -6
- package/gsd-core/bin/lib/roadmap-command-router.cjs +42 -9
- package/gsd-core/bin/lib/roadmap-parser.cjs +100 -18
- package/gsd-core/bin/lib/roadmap.cjs +37 -7
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +195 -62
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +15 -3
- package/gsd-core/bin/lib/runtime-homes.cjs +154 -41
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +105 -41
- package/gsd-core/bin/lib/section-manifest.cjs +209 -0
- package/gsd-core/bin/lib/shell-command-projection.cjs +113 -27
- package/gsd-core/bin/lib/smart-entry.cjs +12 -0
- package/gsd-core/bin/lib/state-transition.cjs +73 -8
- package/gsd-core/bin/lib/state.cjs +151 -62
- package/gsd-core/bin/lib/surface.cjs +12 -1
- package/gsd-core/bin/lib/uat-predicate.cjs +11 -1
- package/gsd-core/bin/lib/uat.cjs +320 -21
- package/gsd-core/bin/lib/unusable-input.cjs +9 -0
- package/gsd-core/bin/lib/verification.cjs +29 -12
- package/gsd-core/bin/lib/verify.cjs +29 -5
- package/gsd-core/bin/lib/workflow-fragments.cjs +557 -0
- package/gsd-core/bin/lib/workstream-inventory-builder.cjs +181 -18
- package/gsd-core/bin/lib/workstream-inventory.cjs +519 -27
- package/gsd-core/bin/lib/workstream.cjs +6 -0
- package/gsd-core/bin/lib/worktree-base-ref.cjs +50 -6
- package/gsd-core/bin/lib/worktree-safety.cjs +276 -118
- package/gsd-core/bin/shared/config-schema.manifest.json +2 -0
- package/gsd-core/references/artifact-types.md +10 -3
- package/gsd-core/references/autonomous-ui-design-contract.md +42 -0
- package/gsd-core/references/debugger-techniques.md +255 -0
- package/gsd-core/references/research-documentation-lookup.md +5 -3
- package/gsd-core/references/specless-probe-fallback.md +7 -6
- package/gsd-core/references/verifier-wiring-patterns.md +100 -0
- package/gsd-core/references/worktree-branch-check.md +2 -2
- package/gsd-core/templates/summary-complex.md +2 -0
- package/gsd-core/templates/summary-minimal.md +2 -0
- package/gsd-core/templates/summary-standard.md +2 -0
- package/gsd-core/templates/summary.md +2 -0
- package/gsd-core/workflows/audit-milestone.md +3 -0
- package/gsd-core/workflows/autonomous/steps/converge-banner.md +1 -0
- package/gsd-core/workflows/autonomous/steps/converge-dispatch-bg.md +11 -0
- package/gsd-core/workflows/autonomous/steps/converge-dispatch-inline.md +7 -0
- package/gsd-core/workflows/autonomous/steps/converge-fail-fast.md +21 -0
- package/gsd-core/workflows/autonomous/steps/converge-loop.md +7 -0
- package/gsd-core/workflows/autonomous.md +32 -69
- package/gsd-core/workflows/code-review/steps/dispatch-fix.md +39 -0
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +83 -0
- package/gsd-core/workflows/code-review.md +42 -145
- package/gsd-core/workflows/complete-milestone/steps/git-tag.md +29 -0
- package/gsd-core/workflows/complete-milestone.md +23 -81
- package/gsd-core/workflows/debug.md +9 -12
- package/gsd-core/workflows/diagnose-issues.md +22 -0
- package/gsd-core/workflows/discovery-phase.md +4 -4
- package/gsd-core/workflows/discuss-phase-assumptions/steps/auto-advance-dispatch.md +15 -0
- package/gsd-core/workflows/discuss-phase-assumptions.md +5 -16
- package/gsd-core/workflows/docs-update/steps/dispatch-monorepo-packages.md +51 -0
- package/gsd-core/workflows/docs-update.md +8 -51
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +34 -2
- package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +50 -0
- package/gsd-core/workflows/execute-phase/steps/partial-wave.md +31 -0
- package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +19 -0
- package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +42 -0
- package/gsd-core/workflows/execute-phase/steps/regression-gate.md +43 -37
- package/gsd-core/workflows/execute-phase.md +65 -137
- package/gsd-core/workflows/execute-plan.md +1 -1
- package/gsd-core/workflows/help/modes/full.md +6 -1
- package/gsd-core/workflows/ingest-docs.md +2 -1
- package/gsd-core/workflows/new-milestone/steps/project-md-milestone-write.md +16 -0
- package/gsd-core/workflows/new-milestone/steps/reset-phase-safety.md +19 -0
- package/gsd-core/workflows/new-milestone.md +21 -38
- package/gsd-core/workflows/new-project/steps/auto-mode-config.md +176 -0
- package/gsd-core/workflows/new-project/steps/auto-mode-detection.md +32 -0
- package/gsd-core/workflows/new-project/steps/codebase-map-offer.md +18 -0
- package/gsd-core/workflows/new-project.md +13 -226
- package/gsd-core/workflows/plan-phase/steps/adr-ingest-express-path.md +15 -0
- package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +110 -0
- package/gsd-core/workflows/plan-phase/steps/prd-express-gate.md +8 -0
- package/gsd-core/workflows/plan-phase/steps/research-only-early-exit.md +17 -0
- package/gsd-core/workflows/plan-phase/steps/research-only-modifiers.md +16 -0
- package/gsd-core/workflows/plan-phase/steps/reviews-prerequisite.md +17 -0
- package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +149 -0
- package/gsd-core/workflows/plan-phase.md +49 -193
- package/gsd-core/workflows/progress/steps/forensic-audit.md +125 -0
- package/gsd-core/workflows/progress/steps/mvp-display.md +18 -0
- package/gsd-core/workflows/progress.md +11 -153
- package/gsd-core/workflows/quick/steps/discussion-phase.md +124 -0
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +111 -0
- package/gsd-core/workflows/quick/steps/quick-verification.md +46 -0
- package/gsd-core/workflows/quick/steps/research-phase.md +72 -0
- package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +37 -0
- package/gsd-core/workflows/quick.md +20 -390
- package/gsd-core/workflows/resume-project.md +3 -0
- package/gsd-core/workflows/review/steps/reviewer-instances-note-1.md +4 -0
- package/gsd-core/workflows/review/steps/reviewer-instances-note-2.md +3 -0
- package/gsd-core/workflows/review.md +15 -8
- package/gsd-core/workflows/section-manifest.json +219 -0
- package/gsd-core/workflows/sketch.md +1 -1
- package/gsd-core/workflows/spec-phase.md +17 -14
- package/gsd-core/workflows/spike-wrap-up.md +20 -5
- package/gsd-core/workflows/spike.md +50 -16
- package/gsd-core/workflows/sync-skills.md +49 -11
- package/gsd-core/workflows/transition/steps/workstream-collision-check.md +17 -0
- package/gsd-core/workflows/transition.md +8 -21
- package/gsd-core/workflows/ui-phase.md +8 -7
- package/gsd-core/workflows/update/steps/channel-banner.md +7 -0
- package/gsd-core/workflows/update.md +18 -7
- package/gsd-core/workflows/verify-phase.md +4 -7
- package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +36 -0
- package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +21 -0
- package/gsd-core/workflows/verify-work.md +8 -58
- package/hooks/dist/gsd-agent-isolation-guard.js +428 -0
- package/hooks/dist/gsd-check-update-worker.js +14 -5
- package/hooks/dist/gsd-cursor-subagent-start.js +532 -26
- package/hooks/dist/gsd-read-injection-scanner.js +7 -0
- package/hooks/dist/gsd-statusline.js +72 -6
- package/hooks/dist/gsd-worktree-path-guard.js +2 -1
- package/hooks/dist/gsd-write-guard.js +359 -0
- package/hooks/dist/lib/isolation-sentinel.js +268 -0
- package/hooks/dist/managed-hooks-registry.cjs +2 -0
- package/hooks/gsd-agent-isolation-guard.js +428 -0
- package/hooks/gsd-check-update-worker.js +14 -5
- package/hooks/gsd-cursor-subagent-start.js +532 -26
- package/hooks/gsd-read-injection-scanner.js +7 -0
- package/hooks/gsd-statusline.js +72 -6
- package/hooks/gsd-worktree-path-guard.js +2 -1
- package/hooks/gsd-write-guard.js +359 -0
- package/hooks/hooks.json +12 -0
- package/hooks/lib/isolation-sentinel.js +268 -0
- package/hooks/managed-hooks-registry.cjs +2 -0
- package/package.json +14 -5
- package/pi/gsd.cjs +57 -12
- package/scripts/build-hooks.js +9 -0
- package/scripts/changeset/lint.cjs +9 -2
- package/scripts/changeset/serialize.cjs +5 -1
- package/scripts/gen-capability-matrix.cjs +1 -1
- package/scripts/gen-context-index.cjs +448 -0
- package/scripts/gen-inventory-manifest.cjs +101 -1
- package/scripts/gen-prompt-budget-parity-corpus.cjs +645 -0
- package/scripts/gen-registry.cjs +39 -15
- package/scripts/gen-section-manifest.cjs +638 -0
- package/scripts/generate-package-identity.cjs +4 -2
- package/scripts/lint-allow-test-rule-refs.allowlist.json +17 -31
- package/scripts/lint-compiled-artifact-sync.cjs +6 -1
- package/scripts/lint-docs-command-form.cjs +195 -0
- package/scripts/lint-docs-required.cjs +9 -1
- package/scripts/lint-emitted-drift-ack.cjs +215 -20
- package/scripts/lint-example-parser-parity.cjs +395 -0
- package/scripts/lint-test-file-count.allowlist.json +27 -1
- package/scripts/mutation-matrix.cjs +13 -0
- package/scripts/prompt-injection-scan.sh +27 -6
- package/scripts/registry-schema.cjs +323 -94
- package/scripts/run-tests.cjs +3 -2
- package/scripts/validate-registry.cjs +10 -6
- package/skills/gsd-autonomous/SKILL.md +1 -1
- package/skills/gsd-execute-phase/SKILL.md +1 -1
- package/skills/gsd-mempalace-capture/SKILL.md +1 -1
- package/skills/gsd-new-milestone/SKILL.md +1 -1
- package/skills/gsd-plan-phase/SKILL.md +2 -2
- package/vscode/package.json +1 -1
- package/scripts/gen-emitted-baseline.cjs +0 -145
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
[
|
|
2
|
-
"tests/agent-classification-parity.test.cjs ::
|
|
2
|
+
"tests/agent-classification-parity.test.cjs :: source-text-is-the-product",
|
|
3
3
|
"tests/agent-frontmatter.test.cjs :: source-text-is-the-product",
|
|
4
4
|
"tests/agent-required-reading-consistency.test.cjs :: source-text-is-the-product",
|
|
5
5
|
"tests/agent-size-budget.test.cjs :: source-text-is-the-product",
|
|
@@ -15,23 +15,20 @@
|
|
|
15
15
|
"tests/autonomous-interactive.test.cjs :: source-text-is-the-product",
|
|
16
16
|
"tests/autonomous-to-flag.test.cjs :: source-text-is-the-product",
|
|
17
17
|
"tests/chain-flag-plan-phase.test.cjs :: source-text-is-the-product",
|
|
18
|
-
"tests/changeset-cli.test.cjs ::
|
|
18
|
+
"tests/changeset-cli.test.cjs :: source-text-is-the-product",
|
|
19
19
|
"tests/check-update-config-dir.test.cjs :: structural-regression-guard",
|
|
20
|
-
"tests/ci-test-scope.test.cjs :: CLI usage banner presence is a user-facing contract.",
|
|
21
|
-
"tests/ci-test-scope.test.cjs :: CLI usage failure text is user-facing contract for this parser guard.",
|
|
22
20
|
"tests/claude-md.test.cjs :: source-text-is-the-product",
|
|
23
21
|
"tests/claude-skills-migration.test.cjs :: source-text-is-the-product",
|
|
24
22
|
"tests/cleanup-branch-pruning.test.cjs :: source-text-is-the-product",
|
|
25
23
|
"tests/cline-install.test.cjs :: source-text-is-the-product",
|
|
26
24
|
"tests/cline-support.test.cjs :: source-text-is-the-product",
|
|
27
|
-
"tests/clock-seam.test.cjs :: line 159 reads the STATE.md temp file written by readModifyWriteStateMd — this is a runtime output file assertion, not a source-grep; the API returns void so a file read-back is the only way to verify the transform was applied",
|
|
28
25
|
"tests/code-review-agent-skills.test.cjs :: source-text-is-the-product",
|
|
29
26
|
"tests/code-review-command.test.cjs :: source-text-is-the-product",
|
|
30
27
|
"tests/code-review-pipeline-regression.test.cjs :: source-text-is-the-product",
|
|
31
28
|
"tests/code-review.test.cjs :: source-text-is-the-product",
|
|
32
29
|
"tests/codebuddy-install.test.cjs :: source-text-is-the-product",
|
|
33
30
|
"tests/codex-config.test.cjs :: source-text-is-the-product",
|
|
34
|
-
"tests/command-contract.test.cjs :: source-text-is-the-product
|
|
31
|
+
"tests/command-contract.test.cjs :: source-text-is-the-product",
|
|
35
32
|
"tests/commands.test.cjs :: source-text-is-the-product",
|
|
36
33
|
"tests/concurrency-safety.test.cjs :: source-text-is-the-product",
|
|
37
34
|
"tests/config-field-docs.test.cjs :: docs-parity",
|
|
@@ -47,18 +44,15 @@
|
|
|
47
44
|
"tests/discuss-phase-power.test.cjs :: source-text-is-the-product",
|
|
48
45
|
"tests/docs-parity-live-registry.test.cjs :: source-text-is-the-product",
|
|
49
46
|
"tests/drift-detection.test.cjs :: source-text-is-the-product",
|
|
50
|
-
"tests/edge-probe-docs-fixtures.test.cjs ::
|
|
51
|
-
"tests/edge-probe-planner-contract.test.cjs ::
|
|
52
|
-
"tests/edge-probe-spec-phase-contract.test.cjs ::
|
|
47
|
+
"tests/edge-probe-docs-fixtures.test.cjs :: source-text-is-the-product",
|
|
48
|
+
"tests/edge-probe-planner-contract.test.cjs :: source-text-is-the-product",
|
|
49
|
+
"tests/edge-probe-spec-phase-contract.test.cjs :: source-text-is-the-product",
|
|
53
50
|
"tests/edit-phase.test.cjs :: source-text-is-the-product",
|
|
54
51
|
"tests/eslint-rules.test.cjs :: <source-grep reason> must still error",
|
|
55
52
|
"tests/eslint-rules.test.cjs :: pending migration",
|
|
56
53
|
"tests/eslint-rules.test.cjs :: source-text-is-the-product",
|
|
57
54
|
"tests/execute-phase-active-flags.test.cjs :: source-text-is-the-product",
|
|
58
55
|
"tests/execute-phase-step-5-5-deviation-doc.test.cjs :: source-text-is-the-product",
|
|
59
|
-
"tests/execute-phase-wave.test.cjs :: behavioral — calls gsd-tools and asserts structured output",
|
|
60
|
-
"tests/execute-phase-wave.test.cjs :: behavioral — exercises config-set validation, not source text",
|
|
61
|
-
"tests/execute-phase-wave.test.cjs :: behavioral — exercises gsd-tools wave-defaulting logic",
|
|
62
56
|
"tests/execute-phase-wave.test.cjs :: source-text-is-the-product",
|
|
63
57
|
"tests/execute-phase-worktree-artifacts.test.cjs :: source-text-is-the-product",
|
|
64
58
|
"tests/explore-command.test.cjs :: source-text-is-the-product",
|
|
@@ -66,9 +60,8 @@
|
|
|
66
60
|
"tests/forensics.test.cjs :: source-text-is-the-product",
|
|
67
61
|
"tests/frontmatter-cli.test.cjs :: source-text-is-the-product",
|
|
68
62
|
"tests/gates-taxonomy.test.cjs :: source-text-is-the-product",
|
|
69
|
-
"tests/git-base-branch.test.cjs ::
|
|
70
|
-
"tests/
|
|
71
|
-
"tests/gsd-check-update-worker-platform-gate.test.cjs :: structural assertion on spawn-options shape; the behavior",
|
|
63
|
+
"tests/git-base-branch.test.cjs :: source-text-is-the-product",
|
|
64
|
+
"tests/gsd-check-update-worker-platform-gate.test.cjs :: structural-regression-guard",
|
|
72
65
|
"tests/gsd-researcher-app-aware.test.cjs :: source-text-is-the-product",
|
|
73
66
|
"tests/gsd-researcher-flow-diagram.test.cjs :: source-text-is-the-product",
|
|
74
67
|
"tests/gsd-settings-advanced.test.cjs :: source-text-is-the-product",
|
|
@@ -80,21 +73,18 @@
|
|
|
80
73
|
"tests/install-minimal-hooks.test.cjs :: source-text-is-the-product",
|
|
81
74
|
"tests/install-nested-layout.test.cjs :: source-text-is-the-product",
|
|
82
75
|
"tests/install-runtime-artifacts.test.cjs :: source-text-is-the-product",
|
|
83
|
-
"tests/install.test.cjs :: runtime-contract-is-the-product",
|
|
84
76
|
"tests/install.test.cjs :: source-text-is-the-product",
|
|
85
|
-
"tests/intel.test.cjs :: source-text-is-the-product
|
|
86
|
-
"tests/
|
|
87
|
-
"tests/inventory-headings-countfree.test.cjs :: runtime-contract-is-the-product — INVENTORY.md heading format is the shipped doc surface being locked",
|
|
77
|
+
"tests/intel.test.cjs :: source-text-is-the-product",
|
|
78
|
+
"tests/inventory-headings-countfree.test.cjs :: source-text-is-the-product",
|
|
88
79
|
"tests/ios-scaffold-safety.test.cjs :: source-text-is-the-product",
|
|
89
80
|
"tests/issue-2639-codex-toml-neutralization.test.cjs :: source-text-is-the-product",
|
|
90
81
|
"tests/issue-429-comment-text-gate.test.cjs :: source-text-is-the-product",
|
|
91
|
-
"tests/issue-498-update-backup-runtime-dir.test.cjs ::
|
|
92
|
-
"tests/issue-57-runtime-install-no-drift.test.cjs ::
|
|
93
|
-
"tests/issue-57-runtime-install-no-drift.test.cjs :: structural guard over bin/install.js source. Behavioral assertions",
|
|
82
|
+
"tests/issue-498-update-backup-runtime-dir.test.cjs :: source-text-is-the-product",
|
|
83
|
+
"tests/issue-57-runtime-install-no-drift.test.cjs :: structural-regression-guard",
|
|
94
84
|
"tests/issue-607-installer-dry-run.install.test.cjs :: integration-test-input",
|
|
95
85
|
"tests/issue-607-legacy-cleanup.test.cjs :: integration-test-input",
|
|
96
86
|
"tests/issue-787-cline-hooks-agents.test.cjs :: source-text-is-the-product",
|
|
97
|
-
"tests/issue-815-update-next-channel.test.cjs ::
|
|
87
|
+
"tests/issue-815-update-next-channel.test.cjs :: source-text-is-the-product",
|
|
98
88
|
"tests/locking-bugs-1909-1916-1925-1927.test.cjs :: architectural-invariant",
|
|
99
89
|
"tests/mcp-tool-inheritance.test.cjs :: source-text-is-the-product",
|
|
100
90
|
"tests/milestone-summary.test.cjs :: source-text-is-the-product",
|
|
@@ -111,7 +101,6 @@
|
|
|
111
101
|
"tests/path-replacement.test.cjs :: source-text-is-the-product",
|
|
112
102
|
"tests/phase-dependency-levels.test.cjs :: source-text-is-the-product",
|
|
113
103
|
"tests/phase.test.cjs :: source-text-is-the-product",
|
|
114
|
-
"tests/phase.test.cjs :: state-md-is-the-runtime-contract — regression tests for",
|
|
115
104
|
"tests/phase6-capability-docs.test.cjs :: source-text-is-the-product",
|
|
116
105
|
"tests/phase6-capstone-conformance.test.cjs :: source-text-is-the-product",
|
|
117
106
|
"tests/phase6-planning-capabilities.test.cjs :: source-text-is-the-product",
|
|
@@ -127,7 +116,6 @@
|
|
|
127
116
|
"tests/product-name-purity.test.cjs :: source-text-is-the-product",
|
|
128
117
|
"tests/profile-output.test.cjs :: source-text-is-the-product",
|
|
129
118
|
"tests/progress-forensic.test.cjs :: source-text-is-the-product",
|
|
130
|
-
"tests/prompt-budget-cli.test.cjs :: prompt-content-is-the-product",
|
|
131
119
|
"tests/prompt-thinning.test.cjs :: source-text-is-the-product",
|
|
132
120
|
"tests/quick-session-management.test.cjs :: source-text-is-the-product",
|
|
133
121
|
"tests/qwen-skills-migration.test.cjs :: source-text-is-the-product",
|
|
@@ -137,12 +125,11 @@
|
|
|
137
125
|
"tests/release-coverage-scope.test.cjs :: source-text-is-the-product",
|
|
138
126
|
"tests/release-tarball-smoke-workflow.test.cjs :: source-text-is-the-product",
|
|
139
127
|
"tests/release-tarball-smoke.install.test.cjs :: integration-test-input",
|
|
140
|
-
"tests/research-agent-profiles.test.cjs ::
|
|
128
|
+
"tests/research-agent-profiles.test.cjs :: source-text-is-the-product",
|
|
141
129
|
"tests/review-default-reviewers-workflow.test.cjs :: source-text-is-the-product",
|
|
142
130
|
"tests/roadmap.test.cjs :: source-text-is-the-product",
|
|
143
|
-
"tests/
|
|
144
|
-
"tests/runtime-
|
|
145
|
-
"tests/runtime-name-policy.test.cjs :: runtime-contract-is-the-product — FALLBACK_ALIASES source text IS the",
|
|
131
|
+
"tests/runtime-launcher-parity.test.cjs :: structural-regression-guard",
|
|
132
|
+
"tests/runtime-name-policy.test.cjs :: source-text-is-the-product",
|
|
146
133
|
"tests/scan-command.test.cjs :: source-text-is-the-product",
|
|
147
134
|
"tests/secret-scan-lint.security.test.cjs :: source-text-is-the-product",
|
|
148
135
|
"tests/secure-phase.test.cjs :: source-text-is-the-product",
|
|
@@ -153,7 +140,6 @@
|
|
|
153
140
|
"tests/settings-jsonc.test.cjs :: structural-regression-guard",
|
|
154
141
|
"tests/skill-frontmatter-contract.test.cjs :: source-text-is-the-product",
|
|
155
142
|
"tests/spawn-liveness-banner.test.cjs :: source-text-is-the-product",
|
|
156
|
-
"tests/state-acquirestatelock-non-eexist.test.cjs :: architectural-invariant",
|
|
157
143
|
"tests/state.test.cjs :: source-text-is-the-product",
|
|
158
144
|
"tests/subagent-timeout.test.cjs :: source-text-is-the-product",
|
|
159
145
|
"tests/template.test.cjs :: source-text-is-the-product",
|
|
@@ -167,7 +153,7 @@
|
|
|
167
153
|
"tests/workflow-compat.test.cjs :: source-text-is-the-product",
|
|
168
154
|
"tests/workflow-guard-registration.test.cjs :: structural-regression-guard",
|
|
169
155
|
"tests/workflow-maintainer-skip.test.cjs :: source-text-is-the-product",
|
|
170
|
-
"tests/workflow-shell-pinning.test.cjs ::
|
|
156
|
+
"tests/workflow-shell-pinning.test.cjs :: source-text-is-the-product",
|
|
171
157
|
"tests/workflow-size-budget.test.cjs :: source-text-is-the-product",
|
|
172
158
|
"tests/workspace.test.cjs :: source-text-is-the-product",
|
|
173
159
|
"tests/worktree-cleanup.test.cjs :: source-text-is-the-product",
|
|
@@ -43,7 +43,12 @@ const REASON = Object.freeze({
|
|
|
43
43
|
});
|
|
44
44
|
|
|
45
45
|
function git(args) {
|
|
46
|
-
|
|
46
|
+
// -c safe.directory=REPO_ROOT: containerized CI checkouts are frequently
|
|
47
|
+
// owned by a different uid than the one running the test process, and git
|
|
48
|
+
// refuses to operate at all on such a repo ("detected dubious ownership")
|
|
49
|
+
// unless explicitly trusted. Scoped per-invocation (not written to any
|
|
50
|
+
// config file) so this never widens trust beyond this one call.
|
|
51
|
+
return execFileSync('git', ['-c', `safe.directory=${REPO_ROOT}`, ...args], { cwd: REPO_ROOT, encoding: 'utf8' });
|
|
47
52
|
}
|
|
48
53
|
|
|
49
54
|
/**
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* lint-docs-command-form.cjs
|
|
4
|
+
*
|
|
5
|
+
* Enforces the human-facing command form in docs/ (#2903).
|
|
6
|
+
*
|
|
7
|
+
* `/gsd:<cmd>` (and bare `gsd:<cmd>`) is a SOURCE-AUTHORING token: install-time
|
|
8
|
+
* converters (`transformContentToHyphen`, `convertSlashCommandsTo<Runtime>SkillMentions`)
|
|
9
|
+
* rewrite it to `/gsd-<cmd>` per-runtime. It is correct in `commands/gsd/**`,
|
|
10
|
+
* `gsd-core/workflows/**`, and `agents/**` — but docs are never passed through a
|
|
11
|
+
* converter, so a doc telling a reader to type `/gsd:<cmd>` names a command no
|
|
12
|
+
* runtime registers. The real user-facing form is `/gsd-<cmd>`.
|
|
13
|
+
*
|
|
14
|
+
* This guard fails any `docs/**\/*.md` file that still contains `/gsd:<cmd>` or
|
|
15
|
+
* bare `gsd:<cmd>` where `<cmd>` is a real command name (drawn from the
|
|
16
|
+
* `commands/gsd/*.md` roster). It explicitly permits `/gsd-core:<cmd>` (the
|
|
17
|
+
* Claude Code plugin namespace) and any `gsd:<token>` whose `<token>` is not a
|
|
18
|
+
* real command (e.g. the `gsd:section` / `gsd:loop-host` workflow-fragment
|
|
19
|
+
* marker syntax documented in docs/reference/workflow-fragments.md, or
|
|
20
|
+
* `gsd:command-name` used as a placeholder while explaining the Gemini CLI
|
|
21
|
+
* colon-form convention).
|
|
22
|
+
*
|
|
23
|
+
* Exclusions (never checked):
|
|
24
|
+
* - docs/adr/** (historical record)
|
|
25
|
+
* - docs/RELEASE-NOTES-LEGACY.md (maintainer question still open)
|
|
26
|
+
* - commands/gsd/**, gsd-core/workflows/**, agents/** — never touched by this
|
|
27
|
+
* guard at all; the colon form is correct there.
|
|
28
|
+
*
|
|
29
|
+
* Exemption — `name:` frontmatter key citations: source command files
|
|
30
|
+
* (`commands/gsd/*.md`) carry the colon form in their `name:` YAML frontmatter
|
|
31
|
+
* key (e.g. `name: gsd:next`). A doc that quotes that key verbatim — e.g.
|
|
32
|
+
* `` `name: gsd:next` `` or `name: gsd:next` — is citing the real source file,
|
|
33
|
+
* not telling a reader what to type. Rewriting that citation to `gsd-next`
|
|
34
|
+
* would make the doc lie about the source it's quoting, so a `gsd:<cmd>` token
|
|
35
|
+
* immediately preceded by `name:` (optionally with a backtick/whitespace in
|
|
36
|
+
* between) is permitted. This is narrow: it does not exempt `gsd:<cmd>`
|
|
37
|
+
* anywhere else on the line or file, including the reader-facing `/gsd-<cmd>`
|
|
38
|
+
* form that may appear later in the same sentence.
|
|
39
|
+
*
|
|
40
|
+
* Detection is case-insensitive (`/GSD:next`, `Gsd:Next`, etc. are all
|
|
41
|
+
* flagged) since the install-time converters and runtimes treat command names
|
|
42
|
+
* case-insensitively in practice, and a doc typo in casing is still a lie
|
|
43
|
+
* about the real command form.
|
|
44
|
+
*
|
|
45
|
+
* Exit 0 if no violations; exit 1 if any are found (with stderr diagnostics).
|
|
46
|
+
*/
|
|
47
|
+
|
|
48
|
+
'use strict';
|
|
49
|
+
|
|
50
|
+
const { execFileSync } = require('child_process');
|
|
51
|
+
const fs = require('fs');
|
|
52
|
+
const path = require('path');
|
|
53
|
+
const { ExitError, runMain } = require('./lib/cli-exit.cjs');
|
|
54
|
+
|
|
55
|
+
const SELF_PATH = path.resolve(__filename);
|
|
56
|
+
// GSD_LINT_DOCS_COMMAND_FORM_REPO_ROOT is used by tests to redirect the guard to
|
|
57
|
+
// a temporary fixture git repo without touching the real working tree.
|
|
58
|
+
const REPO_ROOT = process.env.GSD_LINT_DOCS_COMMAND_FORM_REPO_ROOT
|
|
59
|
+
? path.resolve(process.env.GSD_LINT_DOCS_COMMAND_FORM_REPO_ROOT)
|
|
60
|
+
: path.resolve(__dirname, '..');
|
|
61
|
+
|
|
62
|
+
const DOCS_PREFIX = 'docs/';
|
|
63
|
+
const ADR_PREFIX = 'docs/adr/';
|
|
64
|
+
const RELEASE_NOTES_LEGACY = 'docs/RELEASE-NOTES-LEGACY.md';
|
|
65
|
+
const COMMANDS_DIR = path.join(REPO_ROOT, 'commands/gsd');
|
|
66
|
+
|
|
67
|
+
// Matches `/gsd:<cmd>` and bare `gsd:<cmd>` (not part of `/gsd-core:<cmd>`,
|
|
68
|
+
// which does not contain the substring `gsd:` — the hyphen breaks it).
|
|
69
|
+
// Case-insensitive so `/GSD:next` / `Gsd:Next` are also caught.
|
|
70
|
+
const COMMAND_FORM_RE = /(^|[^A-Za-z0-9_-])(\/)?gsd:([A-Za-z0-9_-]+)/gi;
|
|
71
|
+
|
|
72
|
+
// A `gsd:<cmd>` token is exempt when it is a citation of a source file's
|
|
73
|
+
// YAML `name:` frontmatter key — i.e. the text immediately before the match
|
|
74
|
+
// (ending exactly where the match begins) is `name:` followed by optional
|
|
75
|
+
// whitespace and/or a backtick. Only applies to the bare (non-`/`) form,
|
|
76
|
+
// since the real frontmatter key never carries a leading slash.
|
|
77
|
+
const NAME_KEY_CITATION_RE = /name:\s*`?\s*$/i;
|
|
78
|
+
|
|
79
|
+
function loadRoster() {
|
|
80
|
+
let entries;
|
|
81
|
+
try {
|
|
82
|
+
entries = fs.readdirSync(COMMANDS_DIR);
|
|
83
|
+
} catch (err) {
|
|
84
|
+
throw new ExitError(1, 'ERROR lint-docs-command-form: could not read commands/gsd: ' + err.message);
|
|
85
|
+
}
|
|
86
|
+
return new Set(
|
|
87
|
+
entries.filter((f) => f.endsWith('.md')).map((f) => f.replace(/\.md$/, '')),
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function isCheckedDocsFile(relPath) {
|
|
92
|
+
if (!relPath.startsWith(DOCS_PREFIX)) return false;
|
|
93
|
+
if (relPath.startsWith(ADR_PREFIX)) return false;
|
|
94
|
+
if (relPath === RELEASE_NOTES_LEGACY) return false;
|
|
95
|
+
return relPath.endsWith('.md');
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Pure scan — no fs, no git. Returns violations for a single file's content.
|
|
100
|
+
*
|
|
101
|
+
* @param {string} relPath file path (used only in violation records)
|
|
102
|
+
* @param {string} content file contents
|
|
103
|
+
* @param {Set<string>} roster valid command names
|
|
104
|
+
* @returns {Array<{file:string, line:number, col:number, text:string}>}
|
|
105
|
+
*/
|
|
106
|
+
function scanContent(relPath, content, roster) {
|
|
107
|
+
const violations = [];
|
|
108
|
+
const lines = content.split('\n');
|
|
109
|
+
for (let i = 0; i < lines.length; i++) {
|
|
110
|
+
const line = lines[i];
|
|
111
|
+
COMMAND_FORM_RE.lastIndex = 0;
|
|
112
|
+
let match;
|
|
113
|
+
while ((match = COMMAND_FORM_RE.exec(line)) !== null) {
|
|
114
|
+
const [, pre, slash, cmd] = match;
|
|
115
|
+
if (!roster.has(cmd.toLowerCase())) continue;
|
|
116
|
+
if (!slash) {
|
|
117
|
+
const preContext = line.slice(0, match.index + pre.length);
|
|
118
|
+
if (NAME_KEY_CITATION_RE.test(preContext)) continue;
|
|
119
|
+
}
|
|
120
|
+
const matchedToken = (slash || '') + 'gsd:' + cmd;
|
|
121
|
+
violations.push({
|
|
122
|
+
file: relPath,
|
|
123
|
+
line: i + 1,
|
|
124
|
+
col: match.index + pre.length + 1,
|
|
125
|
+
text: matchedToken,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return violations;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function main() {
|
|
133
|
+
const roster = loadRoster();
|
|
134
|
+
|
|
135
|
+
let trackedFiles;
|
|
136
|
+
try {
|
|
137
|
+
trackedFiles = execFileSync('git', ['ls-files'], { cwd: REPO_ROOT, encoding: 'utf8' })
|
|
138
|
+
.split('\n')
|
|
139
|
+
.map((f) => f.trim())
|
|
140
|
+
.filter(Boolean);
|
|
141
|
+
} catch (err) {
|
|
142
|
+
throw new ExitError(1, 'ERROR lint-docs-command-form: git ls-files failed: ' + err.message);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const docsFiles = trackedFiles.filter(isCheckedDocsFile);
|
|
146
|
+
const violations = [];
|
|
147
|
+
|
|
148
|
+
for (const relPath of docsFiles) {
|
|
149
|
+
const fullPath = path.join(REPO_ROOT, relPath);
|
|
150
|
+
if (path.resolve(fullPath) === SELF_PATH) continue;
|
|
151
|
+
|
|
152
|
+
let content;
|
|
153
|
+
try {
|
|
154
|
+
content = fs.readFileSync(fullPath, 'utf8');
|
|
155
|
+
} catch {
|
|
156
|
+
// Unreadable/deleted files — skip silently.
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
violations.push(...scanContent(relPath, content, roster));
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (violations.length === 0) {
|
|
164
|
+
process.stdout.write(
|
|
165
|
+
'ok lint-docs-command-form: ' + docsFiles.length + ' file(s) checked, 0 violations\n',
|
|
166
|
+
);
|
|
167
|
+
return 0;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
process.stderr.write('\nERROR lint-docs-command-form: ' + violations.length + ' violation(s) found\n\n');
|
|
171
|
+
for (const v of violations) {
|
|
172
|
+
process.stderr.write(' ' + v.file + ':' + v.line + ':' + v.col + ' — ' + JSON.stringify(v.text) + '\n');
|
|
173
|
+
}
|
|
174
|
+
process.stderr.write('\n');
|
|
175
|
+
process.stderr.write(
|
|
176
|
+
'Fix: docs are never passed through the install-time slash-form converters, so the\n',
|
|
177
|
+
);
|
|
178
|
+
process.stderr.write(
|
|
179
|
+
' colon form names a command no runtime registers. Rewrite to the hyphen form\n',
|
|
180
|
+
);
|
|
181
|
+
process.stderr.write(
|
|
182
|
+
' (`/gsd-<cmd>`), or `/gsd-core:<cmd>` if this is genuinely the Claude Code\n',
|
|
183
|
+
);
|
|
184
|
+
process.stderr.write(' plugin namespace.\n\n');
|
|
185
|
+
return 1;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (require.main === module) runMain(main);
|
|
189
|
+
|
|
190
|
+
module.exports = {
|
|
191
|
+
scanContent,
|
|
192
|
+
isCheckedDocsFile,
|
|
193
|
+
loadRoster,
|
|
194
|
+
COMMAND_FORM_RE,
|
|
195
|
+
};
|
|
@@ -16,6 +16,10 @@
|
|
|
16
16
|
const { parseFragment, FRAGMENT_ERROR } = require('./changeset/parse.cjs');
|
|
17
17
|
const { ExitError, runMain } = require('./lib/cli-exit.cjs');
|
|
18
18
|
|
|
19
|
+
// #2988: the repo's integration/default branch — the base every PR targets.
|
|
20
|
+
// Used as the local fallback when GITHUB_BASE_REF is unset (CI sets it).
|
|
21
|
+
const DEFAULT_BASE = 'next';
|
|
22
|
+
|
|
19
23
|
const LINT_REASON = Object.freeze({
|
|
20
24
|
OK_NO_TRIGGERING_FRAGMENTS: 'ok_no_triggering_fragments',
|
|
21
25
|
OK_DOCS_UPDATED: 'ok_docs_updated',
|
|
@@ -149,7 +153,10 @@ function main() {
|
|
|
149
153
|
} catch { /* fall through */ }
|
|
150
154
|
}
|
|
151
155
|
|
|
152
|
-
|
|
156
|
+
// #2988: local fallback must match the repo's integration branch (`next`),
|
|
157
|
+
// not the release branch (`main`). CI sets GITHUB_BASE_REF explicitly; the
|
|
158
|
+
// fallback only fires locally, where `next` is the base every PR targets.
|
|
159
|
+
const base = process.env.GITHUB_BASE_REF || DEFAULT_BASE;
|
|
153
160
|
let changedFiles = [];
|
|
154
161
|
try {
|
|
155
162
|
// execFileSync with argv — no shell, so a malicious GITHUB_BASE_REF
|
|
@@ -216,6 +223,7 @@ module.exports = {
|
|
|
216
223
|
OPT_OUT_LABEL,
|
|
217
224
|
TRIGGERING_TYPES,
|
|
218
225
|
FRAGMENT_ERROR,
|
|
226
|
+
DEFAULT_BASE,
|
|
219
227
|
isFragmentPath,
|
|
220
228
|
isDocsFile,
|
|
221
229
|
isExemptFragment,
|