@opengsd/gsd-core 1.17.0 → 1.18.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 +1 -1
- package/agents/gsd-advisor-researcher.compact.md +1 -1
- package/agents/gsd-advisor-researcher.md +1 -1
- package/agents/gsd-assumptions-analyzer.compact.md +1 -1
- package/agents/gsd-assumptions-analyzer.md +1 -1
- package/agents/gsd-code-fixer.compact.md +1 -1
- package/agents/gsd-code-fixer.md +1 -1
- package/agents/gsd-code-reviewer.compact.md +1 -1
- package/agents/gsd-code-reviewer.md +1 -1
- package/agents/gsd-codebase-mapper.compact.md +1 -1
- package/agents/gsd-codebase-mapper.md +1 -1
- package/agents/gsd-debugger.md +1 -1
- package/agents/gsd-doc-verifier.compact.md +4 -4
- package/agents/gsd-doc-verifier.md +4 -3
- package/agents/gsd-doc-writer.compact.md +23 -5
- package/agents/gsd-doc-writer.md +19 -6
- package/agents/gsd-eval-auditor.compact.md +1 -1
- package/agents/gsd-eval-auditor.md +1 -1
- package/agents/gsd-executor.md +7 -3
- package/agents/gsd-integration-checker.compact.md +1 -1
- package/agents/gsd-integration-checker.md +1 -1
- package/agents/gsd-nyquist-auditor.compact.md +1 -1
- package/agents/gsd-nyquist-auditor.md +1 -1
- package/agents/gsd-phase-researcher.md +1 -1
- package/agents/gsd-plan-checker.md +2 -1
- package/agents/gsd-planner.md +5 -4
- package/agents/gsd-project-researcher.compact.md +1 -1
- package/agents/gsd-project-researcher.md +1 -1
- package/agents/gsd-research-synthesizer.compact.md +5 -5
- package/agents/gsd-research-synthesizer.md +5 -5
- package/agents/gsd-roadmapper.compact.md +1 -1
- package/agents/gsd-roadmapper.md +1 -1
- package/agents/gsd-security-auditor.compact.md +1 -1
- package/agents/gsd-security-auditor.md +1 -1
- package/agents/gsd-ui-auditor.compact.md +1 -1
- package/agents/gsd-ui-auditor.md +1 -1
- package/agents/gsd-ui-checker.compact.md +1 -1
- package/agents/gsd-ui-checker.md +1 -1
- package/agents/gsd-ui-researcher.compact.md +13 -1
- package/agents/gsd-ui-researcher.md +28 -1
- package/agents/gsd-verifier.md +1 -1
- package/bin/install.js +38 -2
- package/commands/gsd/code-review.md +8 -0
- package/commands/gsd/pause-work.md +1 -1
- package/gsd-core/bin/gsd-tools.cjs +18 -11
- package/gsd-core/bin/lib/capability-ledger.cjs +25 -0
- package/gsd-core/bin/lib/capability-lock.cjs +29 -7
- package/gsd-core/bin/lib/capability-registry.cjs +70 -64
- package/gsd-core/bin/lib/capability-source.cjs +3 -1
- package/gsd-core/bin/lib/capability-state.cjs +6 -3
- package/gsd-core/bin/lib/capability-validator.cjs +6 -4
- package/gsd-core/bin/lib/commands.cjs +5 -1
- package/gsd-core/bin/lib/config-loader.cjs +3 -3
- package/gsd-core/bin/lib/decision-coverage-support.cjs +19 -0
- package/gsd-core/bin/lib/gate-decision-coverage-plan.cjs +15 -0
- package/gsd-core/bin/lib/gate-decision-coverage-verify.cjs +13 -0
- package/gsd-core/bin/lib/gate-predicate-evaluator.cjs +23 -3
- package/gsd-core/bin/lib/gate-predicate.cjs +8 -12
- package/gsd-core/bin/lib/gate-tdd-review-checkpoint.cjs +60 -5
- package/gsd-core/bin/lib/init.cjs +11 -4
- package/gsd-core/bin/lib/install-effort-resolver.cjs +2 -2
- package/gsd-core/bin/lib/install-model-override-resolver.cjs +4 -3
- package/gsd-core/bin/lib/install-profiles.cjs +5 -3
- package/gsd-core/bin/lib/phase.cjs +120 -11
- package/gsd-core/bin/lib/report-parser.cjs +57 -1
- package/gsd-core/bin/lib/review-lane-invocation.cjs +40 -0
- package/gsd-core/bin/lib/review-reviewer-selection.cjs +20 -1
- package/gsd-core/bin/lib/roadmap.cjs +56 -5
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +47 -2
- package/gsd-core/bin/lib/runtime-homes.cjs +18 -0
- package/gsd-core/bin/lib/shell-command-projection.cjs +2 -0
- package/gsd-core/bin/lib/smart-entry.cjs +24 -16
- package/gsd-core/bin/lib/state-document.cjs +37 -3
- package/gsd-core/bin/lib/state-transition.cjs +31 -10
- package/gsd-core/bin/lib/state.cjs +90 -60
- package/gsd-core/bin/lib/task-command-router.cjs +2 -3
- package/gsd-core/bin/lib/tdd-red-evidence.cjs +5 -0
- package/gsd-core/bin/lib/tdd-test-files.cjs +42 -0
- package/gsd-core/bin/lib/verify.cjs +36 -1
- package/gsd-core/references/agent-contracts.md +1 -1
- package/gsd-core/references/agent-skills-bootstrap.md +26 -7
- package/gsd-core/references/git-integration.md +3 -3
- package/gsd-core/references/planner-reversibility.md +18 -4
- package/gsd-core/references/planner-verify-command-grounding.md +18 -0
- package/gsd-core/references/tdd.md +4 -3
- package/gsd-core/references/verifier-phase-gates.md +8 -1
- package/gsd-core/workflows/add-backlog.md +10 -2
- package/gsd-core/workflows/add-phase.md +5 -1
- package/gsd-core/workflows/add-tests.md +5 -1
- package/gsd-core/workflows/add-todo.md +5 -1
- package/gsd-core/workflows/ai-integration-phase.md +5 -1
- package/gsd-core/workflows/audit-milestone.md +21 -9
- package/gsd-core/workflows/autonomous/templates/minimal-context.md +41 -0
- package/gsd-core/workflows/autonomous.md +52 -64
- package/gsd-core/workflows/check-todos.md +5 -1
- package/gsd-core/workflows/code-review-fix.md +5 -1
- package/gsd-core/workflows/code-review.md +5 -1
- package/gsd-core/workflows/complete-milestone/detail/elaboration.md +5 -1
- package/gsd-core/workflows/complete-milestone.md +25 -5
- package/gsd-core/workflows/debug.md +5 -1
- package/gsd-core/workflows/diagnose-issues.md +5 -1
- package/gsd-core/workflows/discuss-phase/modes/chain.md +5 -1
- package/gsd-core/workflows/discuss-phase-assumptions.md +11 -3
- package/gsd-core/workflows/discuss-phase.md +5 -1
- package/gsd-core/workflows/docs-update/detail/elaboration.md +7 -6
- package/gsd-core/workflows/docs-update.md +27 -5
- package/gsd-core/workflows/edit-phase.md +5 -1
- package/gsd-core/workflows/eval-review.md +11 -3
- package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +5 -1
- package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +12 -6
- package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +19 -2
- package/gsd-core/workflows/execute-phase/steps/regression-gate.md +18 -1
- package/gsd-core/workflows/execute-phase/steps/verify-phase-goal.md +5 -1
- package/gsd-core/workflows/execute-phase.md +37 -6
- package/gsd-core/workflows/execute-plan.md +8 -4
- package/gsd-core/workflows/extract-learnings.md +6 -2
- package/gsd-core/workflows/forensics.md +5 -1
- package/gsd-core/workflows/import.md +5 -1
- package/gsd-core/workflows/insert-phase.md +5 -1
- package/gsd-core/workflows/manager.md +10 -2
- package/gsd-core/workflows/map-codebase.md +5 -1
- package/gsd-core/workflows/milestone-summary.md +10 -2
- package/gsd-core/workflows/new-milestone.md +13 -5
- package/gsd-core/workflows/new-project.md +9 -5
- package/gsd-core/workflows/next.md +8 -4
- package/gsd-core/workflows/pause-work.md +3 -3
- package/gsd-core/workflows/plan-phase/steps/auto-advance-check.md +70 -0
- package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +5 -1
- package/gsd-core/workflows/plan-phase/steps/closed-phase-gate.md +6 -2
- package/gsd-core/workflows/plan-phase.md +41 -73
- package/gsd-core/workflows/plan-review-convergence.md +17 -5
- package/gsd-core/workflows/plant-seed.md +8 -4
- package/gsd-core/workflows/progress.md +6 -2
- package/gsd-core/workflows/quick-batch.md +5 -1
- package/gsd-core/workflows/quick.md +22 -7
- package/gsd-core/workflows/remove-phase.md +5 -1
- package/gsd-core/workflows/resume-project.md +5 -1
- package/gsd-core/workflows/review.md +6 -2
- package/gsd-core/workflows/scan.md +5 -1
- package/gsd-core/workflows/secure-phase.md +6 -2
- package/gsd-core/workflows/settings.md +3 -3
- package/gsd-core/workflows/ship.md +13 -10
- package/gsd-core/workflows/thread.md +10 -2
- package/gsd-core/workflows/transition.md +5 -1
- package/gsd-core/workflows/ui-phase.md +5 -1
- package/gsd-core/workflows/ui-review.md +6 -2
- package/gsd-core/workflows/ultraplan-phase.md +5 -1
- package/gsd-core/workflows/update.md +5 -1
- package/gsd-core/workflows/validate-phase.md +6 -2
- package/gsd-core/workflows/verify-work/detail/elaboration.md +1 -1
- package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +5 -1
- package/gsd-core/workflows/verify-work.md +11 -3
- package/hooks/dist/gsd-agent-isolation-guard.js +3 -1
- package/hooks/dist/gsd-cursor-subagent-start.js +2 -1
- package/hooks/dist/gsd-secret-read-guard.js +72 -14
- package/hooks/dist/gsd-validate-commit.sh +27 -5
- package/hooks/gsd-agent-isolation-guard.js +3 -1
- package/hooks/gsd-cursor-subagent-start.js +2 -1
- package/hooks/gsd-secret-read-guard.js +72 -14
- package/hooks/gsd-validate-commit.sh +27 -5
- package/package.json +1 -1
- package/scripts/audit-workflow-script-paths.cjs +1 -1
- package/scripts/diagnose-validate-commit-in-tier.cjs +270 -0
- package/scripts/diagnose-validate-commit-phases.cjs +348 -0
- package/scripts/diagnose-windows-spawn-watcher.cjs +317 -0
- package/scripts/docs-guard-registry.cjs +2 -0
- package/scripts/lib/macos-conformance-tier.generated.cjs +9 -0
- package/scripts/lib/platform-conformance-tier.generated.cjs +16 -0
- package/scripts/lint-phase-arg-assignment.cjs +2 -2
- package/scripts/lint-workflow-shellcheck-baseline.json +16 -16
- package/scripts/release-tarball-smoke.cjs +1 -0
- package/scripts/xtrace-phase-timing.cjs +205 -0
- package/skills/gsd-code-review/SKILL.md +8 -0
- package/skills/gsd-pause-work/SKILL.md +1 -1
- package/vscode/package.json +1 -1
|
@@ -23,7 +23,7 @@ Job: transform requirements into a phase structure that delivers the project. Ev
|
|
|
23
23
|
**Context budget:** load project skills first (lightweight); read implementation files incrementally, only what each check requires.
|
|
24
24
|
|
|
25
25
|
**Project skills:** check `.claude/skills/` or `.agents/skills/`:
|
|
26
|
-
**agent_skills:** self-load per @~/.claude/gsd-core/references/agent-skills-bootstrap.md
|
|
26
|
+
**agent_skills:** self-load per @~/.claude/gsd-core/references/agent-skills-bootstrap.md (agent type: `gsd-roadmapper`)
|
|
27
27
|
1. List available skills (subdirectories)
|
|
28
28
|
2. Read `SKILL.md` per skill (lightweight index ~130 lines)
|
|
29
29
|
3. Load specific `rules/*.md` as needed
|
package/agents/gsd-roadmapper.md
CHANGED
|
@@ -27,7 +27,7 @@ If the prompt contains a `<required_reading>` block, you MUST use the `Read` too
|
|
|
27
27
|
|
|
28
28
|
**Project skills:** Check `.claude/skills/` or `.agents/skills/` directory if either exists:
|
|
29
29
|
|
|
30
|
-
**agent_skills:** self-load per @~/.claude/gsd-core/references/agent-skills-bootstrap.md
|
|
30
|
+
**agent_skills:** self-load per @~/.claude/gsd-core/references/agent-skills-bootstrap.md (agent type: `gsd-roadmapper`)
|
|
31
31
|
1. List available skills (subdirectories)
|
|
32
32
|
2. Read `SKILL.md` for each skill (lightweight index ~130 lines)
|
|
33
33
|
3. Load specific `rules/*.md` files as needed during implementation
|
|
@@ -44,7 +44,7 @@ Read ALL `<required_reading>` files. Extract:
|
|
|
44
44
|
|
|
45
45
|
**Project skills:** check `.claude/skills/` or `.agents/skills/` if either exists.
|
|
46
46
|
|
|
47
|
-
**agent_skills:** self-load per @~/.claude/gsd-core/references/agent-skills-bootstrap.md — list skill subdirs, read each `SKILL.md` (~130-line index), load `rules/*.md` as needed. NEVER load full `AGENTS.md` (100KB+ cost). Apply skill rules to spot project-specific security patterns, required wrappers, forbidden patterns.
|
|
47
|
+
**agent_skills:** self-load per @~/.claude/gsd-core/references/agent-skills-bootstrap.md (agent type: `gsd-security-auditor`) — list skill subdirs, read each `SKILL.md` (~130-line index), load `rules/*.md` as needed. NEVER load full `AGENTS.md` (100KB+ cost). Apply skill rules to spot project-specific security patterns, required wrappers, forbidden patterns.
|
|
48
48
|
</step>
|
|
49
49
|
|
|
50
50
|
<step name="analyze_threats">
|
|
@@ -50,7 +50,7 @@ Read ALL files from `<required_reading>`. Extract:
|
|
|
50
50
|
|
|
51
51
|
**Project skills:** Check `.claude/skills/` or `.agents/skills/` directory if either exists:
|
|
52
52
|
|
|
53
|
-
**agent_skills:** self-load per @~/.claude/gsd-core/references/agent-skills-bootstrap.md
|
|
53
|
+
**agent_skills:** self-load per @~/.claude/gsd-core/references/agent-skills-bootstrap.md (agent type: `gsd-security-auditor`)
|
|
54
54
|
1. List available skills (subdirectories)
|
|
55
55
|
2. Read `SKILL.md` for each skill (lightweight index ~130 lines)
|
|
56
56
|
3. Load specific `rules/*.md` files as needed during implementation
|
|
@@ -48,7 +48,7 @@ Before auditing, discover project context:
|
|
|
48
48
|
**Project instructions:** Read `./CLAUDE.md` if present; follow all project-specific guidelines.
|
|
49
49
|
|
|
50
50
|
**Project skills:** Check `.claude/skills/` or `.agents/skills/`.
|
|
51
|
-
**agent_skills:** self-load per @~/.claude/gsd-core/references/agent-skills-bootstrap.md
|
|
51
|
+
**agent_skills:** self-load per @~/.claude/gsd-core/references/agent-skills-bootstrap.md (agent type: `gsd-ui-auditor`)
|
|
52
52
|
1. List available skills 2. Read `SKILL.md` for each 3. Do NOT load full `AGENTS.md` (100KB+ context cost)
|
|
53
53
|
</project_context>
|
|
54
54
|
|
package/agents/gsd-ui-auditor.md
CHANGED
|
@@ -50,7 +50,7 @@ Before auditing, discover project context:
|
|
|
50
50
|
|
|
51
51
|
**Project skills:** Check `.claude/skills/` or `.agents/skills/` directory if either exists:
|
|
52
52
|
|
|
53
|
-
**agent_skills:** self-load per @~/.claude/gsd-core/references/agent-skills-bootstrap.md
|
|
53
|
+
**agent_skills:** self-load per @~/.claude/gsd-core/references/agent-skills-bootstrap.md (agent type: `gsd-ui-auditor`)
|
|
54
54
|
1. List available skills (subdirectories)
|
|
55
55
|
2. Read `SKILL.md` for each skill
|
|
56
56
|
3. Do NOT load full `AGENTS.md` files (100KB+ context cost)
|
|
@@ -63,7 +63,7 @@ Before verifying: read `./CLAUDE.md` if present, follow project-specific guideli
|
|
|
63
63
|
|
|
64
64
|
Check `.claude/skills/` or `.agents/skills/` if either exists.
|
|
65
65
|
|
|
66
|
-
**agent_skills:** self-load per @~/.claude/gsd-core/references/agent-skills-bootstrap.md — list
|
|
66
|
+
**agent_skills:** self-load per @~/.claude/gsd-core/references/agent-skills-bootstrap.md (agent type: `gsd-ui-checker`) — list
|
|
67
67
|
skills, read each `SKILL.md` (~130 lines), load `rules/*.md` as needed during verification. Do
|
|
68
68
|
NOT load full `AGENTS.md` (100KB+ cost). This ensures verification respects project-specific
|
|
69
69
|
design conventions.
|
package/agents/gsd-ui-checker.md
CHANGED
|
@@ -62,7 +62,7 @@ Before verifying, discover project context:
|
|
|
62
62
|
|
|
63
63
|
**Project skills:** Check `.claude/skills/` or `.agents/skills/` directory if either exists:
|
|
64
64
|
|
|
65
|
-
**agent_skills:** self-load per @~/.claude/gsd-core/references/agent-skills-bootstrap.md
|
|
65
|
+
**agent_skills:** self-load per @~/.claude/gsd-core/references/agent-skills-bootstrap.md (agent type: `gsd-ui-checker`)
|
|
66
66
|
1. List available skills (subdirectories)
|
|
67
67
|
2. Read `SKILL.md` for each skill (lightweight index ~130 lines)
|
|
68
68
|
3. Load specific `rules/*.md` files as needed during verification
|
|
@@ -29,7 +29,7 @@ GSD UI researcher, spawned by `/gsd:ui-phase`. Answer "What visual and interacti
|
|
|
29
29
|
<project_context>
|
|
30
30
|
Before researching: read `./CLAUDE.md` if it exists (follow project guidelines/security/conventions). Check `.claude/skills/` or `.agents/skills/`:
|
|
31
31
|
|
|
32
|
-
**agent_skills:** self-load per @~/.claude/gsd-core/references/agent-skills-bootstrap.md — list skill subdirectories; read each `SKILL.md` (~130 lines); load `rules/*.md` as needed; do NOT load full `AGENTS.md` (100KB+ cost); account for project skill patterns in the design contract.
|
|
32
|
+
**agent_skills:** self-load per @~/.claude/gsd-core/references/agent-skills-bootstrap.md (agent type: `gsd-ui-researcher`) — list skill subdirectories; read each `SKILL.md` (~130 lines); load `rules/*.md` as needed; do NOT load full `AGENTS.md` (100KB+ cost); account for project skill patterns in the design contract.
|
|
33
33
|
</project_context>
|
|
34
34
|
|
|
35
35
|
<upstream_input>
|
|
@@ -99,6 +99,18 @@ node -p "require('<pkg>/package.json').version" # RES
|
|
|
99
99
|
```
|
|
100
100
|
A first-party CLI with a JSON mode, or an MCP tool the design system ships, beats all three. What matters: the command is **recorded and re-runnable**. Take the version from the installed package, not the range in your dependent's `package.json` (a caret range hides staleness).
|
|
101
101
|
|
|
102
|
+
**Cross-check the first answer — always.** A tool's count is a claim: `npx shadcn info` reports "No components installed" on projects with hand-authored or pre-CLI primitives. After the first command answers, count component files on disk as a second source (shadcn: the `aliases.ui` dir in `components.json`, else `components/ui` / `src/components/ui`):
|
|
103
|
+
```bash
|
|
104
|
+
ls <ui-dir>/*.tsx 2>/dev/null | wc -l # filesystem count
|
|
105
|
+
```
|
|
106
|
+
If they disagree (including a tool reporting none while files exist), do not pick silently: record the larger filesystem-backed count with the command that produced it, and add directly under the provenance line `Mismatch: <tool> reported <A>, filesystem has <B>.`
|
|
107
|
+
|
|
108
|
+
**A failed lookup is a failure, never a pass-through.** `2>/dev/null` hides why `node -p` died: treat empty output, a non-zero exit, or the literal `undefined` as that step failing. With `node_modules` absent the `require()` version lookup fails; resolve from the lockfile instead (still not the caret range):
|
|
109
|
+
```bash
|
|
110
|
+
node -p "(require('./package-lock.json').packages['node_modules/<pkg>']||{}).version"
|
|
111
|
+
```
|
|
112
|
+
For `pnpm-lock.yaml` / `yarn.lock`, read `<pkg>`'s resolved version from that file. If the lockfile cannot answer, write `<version unresolved: <reason>>` in the version slot instead of leaving it empty or guessing.
|
|
113
|
+
|
|
102
114
|
Record it as the first line of the section, verbatim:
|
|
103
115
|
```
|
|
104
116
|
Enumerated by `<command>` — <N> components — <package>@<version> — <YYYY-MM-DD>.
|
|
@@ -41,7 +41,7 @@ Before researching, discover project context:
|
|
|
41
41
|
|
|
42
42
|
**Project skills:** Check `.claude/skills/` or `.agents/skills/` directory if either exists:
|
|
43
43
|
|
|
44
|
-
**agent_skills:** self-load per @~/.claude/gsd-core/references/agent-skills-bootstrap.md
|
|
44
|
+
**agent_skills:** self-load per @~/.claude/gsd-core/references/agent-skills-bootstrap.md (agent type: `gsd-ui-researcher`)
|
|
45
45
|
1. List available skills (subdirectories)
|
|
46
46
|
2. Read `SKILL.md` for each skill (lightweight index ~130 lines)
|
|
47
47
|
3. Load specific `rules/*.md` files as needed during research
|
|
@@ -166,6 +166,33 @@ A first-party CLI with a JSON mode, or an MCP tool the design system ships, beat
|
|
|
166
166
|
matters is that the command is **recorded and re-runnable**. Take the version from the installed
|
|
167
167
|
package, not the range in your dependent's `package.json` — a caret range hides staleness.
|
|
168
168
|
|
|
169
|
+
**Cross-check the first answer — always.** A tool's count is a claim, not a fact: `npx shadcn info`
|
|
170
|
+
reports "No components installed" on a project whose primitives were hand-authored or predate the
|
|
171
|
+
CLI's tracking. After the first command answers, count the component files on disk as an independent
|
|
172
|
+
second source (for shadcn, the `aliases.ui` directory in `components.json`, else `components/ui` or
|
|
173
|
+
`src/components/ui`):
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
ls <ui-dir>/*.tsx 2>/dev/null | wc -l # filesystem count
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
If the two disagree — including a tool that reports none while files exist — do not pick one
|
|
180
|
+
silently. Record the larger, filesystem-backed count with the command that produced it, and add a
|
|
181
|
+
line directly under the provenance line: `Mismatch: <tool> reported <A>, filesystem has <B>.`
|
|
182
|
+
|
|
183
|
+
**A failed lookup is a failure, never a pass-through.** `2>/dev/null` hides why a `node -p` call died,
|
|
184
|
+
so treat empty output, a non-zero exit, or the literal `undefined` as that step failing. When
|
|
185
|
+
`node_modules` is absent the `require()` version lookup fails; resolve the version from the lockfile
|
|
186
|
+
instead — still not the caret range:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
node -p "(require('./package-lock.json').packages['node_modules/<pkg>']||{}).version"
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
For `pnpm-lock.yaml` or `yarn.lock`, read the resolved version for `<pkg>` from that file. If the
|
|
193
|
+
lockfile cannot answer either, say `<version unresolved: <reason>>` in the version slot rather than
|
|
194
|
+
leaving it empty or guessing.
|
|
195
|
+
|
|
169
196
|
Record it as the first line of the section, verbatim:
|
|
170
197
|
|
|
171
198
|
```
|
package/agents/gsd-verifier.md
CHANGED
|
@@ -55,7 +55,7 @@ Before verifying, discover project context:
|
|
|
55
55
|
- Load `rules/*.md` as needed during **verification**.
|
|
56
56
|
- Apply skill rules when scanning for anti-patterns and verifying quality.
|
|
57
57
|
|
|
58
|
-
**agent_skills:** self-load per @~/.claude/gsd-core/references/agent-skills-bootstrap.md
|
|
58
|
+
**agent_skills:** self-load per @~/.claude/gsd-core/references/agent-skills-bootstrap.md (agent type: `gsd-verifier`)
|
|
59
59
|
</project_context>
|
|
60
60
|
|
|
61
61
|
<core_principle>
|
package/bin/install.js
CHANGED
|
@@ -35,6 +35,7 @@ const {
|
|
|
35
35
|
getGlobalSkillsBase,
|
|
36
36
|
resolveKimiHooksTomlDir,
|
|
37
37
|
isRegisteredRuntimeId,
|
|
38
|
+
resolveGsdHome,
|
|
38
39
|
} = require('../gsd-core/bin/lib/runtime-homes.cjs');
|
|
39
40
|
// #2870: the Install Scope Module — turns a bare 'global' | 'local' scope id
|
|
40
41
|
// plus a runtime into one resolved value (configHome, settingsFile,
|
|
@@ -7033,7 +7034,7 @@ function recordDefaultsProvenance(gsdDir, runtime, defaults, setNow) {
|
|
|
7033
7034
|
/** @returns {boolean} true when it removed or reverted something */
|
|
7034
7035
|
function revertNonClaudeDefaults(runtime) {
|
|
7035
7036
|
if (hostBehaviorsFor(runtime).nativeModelAliases || process.env.GSD_TEST_MODE) return false;
|
|
7036
|
-
const gsdDir = path.join(
|
|
7037
|
+
const gsdDir = path.join(resolveGsdHome(), '.gsd'); // #5017: GSD_HOME-aware, like the loader
|
|
7037
7038
|
const provPath = path.join(gsdDir, DEFAULTS_PROVENANCE_NAME);
|
|
7038
7039
|
if (!fs.existsSync(provPath)) return false;
|
|
7039
7040
|
let releaseLock = null;
|
|
@@ -7086,7 +7087,7 @@ function revertNonClaudeDefaults(runtime) {
|
|
|
7086
7087
|
*/
|
|
7087
7088
|
function writeNonClaudeDefaults(runtime) {
|
|
7088
7089
|
if (hostBehaviorsFor(runtime).nativeModelAliases || process.env.GSD_TEST_MODE) return;
|
|
7089
|
-
const gsdDir = path.join(
|
|
7090
|
+
const gsdDir = path.join(resolveGsdHome(), '.gsd'); // #5017: GSD_HOME-aware, like the loader
|
|
7090
7091
|
const defaultsPath = path.join(gsdDir, 'defaults.json');
|
|
7091
7092
|
let releaseLock = null;
|
|
7092
7093
|
try {
|
|
@@ -12565,6 +12566,41 @@ function install(isGlobal, runtime = DEFAULT_RUNTIME, options = {}) {
|
|
|
12565
12566
|
}
|
|
12566
12567
|
}
|
|
12567
12568
|
}
|
|
12569
|
+
// #5123: the Copilot and Antigravity converters write their DEFAULT home
|
|
12570
|
+
// into `@` includes and Kimi's prompt converter leaves a prose "GSD core/"
|
|
12571
|
+
// path, none of which exist when the payload lives somewhere else. Point
|
|
12572
|
+
// them at the real install root (the same `$HOME/…` / absolute prefix the
|
|
12573
|
+
// other runtimes use). Global installs only: a local install resolves
|
|
12574
|
+
// against its project, which the converters already handle.
|
|
12575
|
+
const includeRetarget = hostBehaviorsFor(runtime);
|
|
12576
|
+
if (isGlobal && (includeRetarget.defaultHomeIncludeRoot || includeRetarget.retargetsGsdCoreProsePath === true)) {
|
|
12577
|
+
const includePrefix = runtimeArtifactConversion._computePathPrefix({
|
|
12578
|
+
isGlobal: true,
|
|
12579
|
+
isOpencode: false,
|
|
12580
|
+
resolvedTarget: targetDir,
|
|
12581
|
+
homeDir: os.homedir(),
|
|
12582
|
+
});
|
|
12583
|
+
for (const relPath of manifestFiles) {
|
|
12584
|
+
const fileName = path.basename(relPath);
|
|
12585
|
+
if (!(fileName.endsWith('.md') || fileName.endsWith('.toml'))) continue;
|
|
12586
|
+
if (fileName === 'CHANGELOG.md') continue;
|
|
12587
|
+
const retargetPath = path.join(targetDir, relPath);
|
|
12588
|
+
let retargetContent;
|
|
12589
|
+
try {
|
|
12590
|
+
retargetContent = fs.readFileSync(retargetPath, 'utf8');
|
|
12591
|
+
} catch (_retargetReadErr) {
|
|
12592
|
+
continue; // inaccessible or missing — never fail the install over this pass
|
|
12593
|
+
}
|
|
12594
|
+
const retargeted = runtimeArtifactConversion.retargetInstalledIncludes(retargetContent, includeRetarget, includePrefix);
|
|
12595
|
+
if (retargeted !== retargetContent) {
|
|
12596
|
+
try {
|
|
12597
|
+
fs.writeFileSync(retargetPath, retargeted);
|
|
12598
|
+
} catch (_retargetWriteErr) {
|
|
12599
|
+
continue;
|
|
12600
|
+
}
|
|
12601
|
+
}
|
|
12602
|
+
}
|
|
12603
|
+
}
|
|
12568
12604
|
for (const relPath of manifestFiles) {
|
|
12569
12605
|
const fileName = path.basename(relPath);
|
|
12570
12606
|
if (!(fileName.endsWith('.md') || fileName.endsWith('.toml'))) continue;
|
|
@@ -48,6 +48,14 @@ Optional flags parsed from the `<arguments>` block:
|
|
|
48
48
|
- `--files=file1,file2,...` — Explicit file list override. Has highest precedence for file scoping per D-08. When provided, workflow skips SUMMARY.md extraction and git diff fallback entirely.
|
|
49
49
|
|
|
50
50
|
Context files (CLAUDE.md, SUMMARY.md, phase state) are resolved inside the workflow via `gsd-tools query init.phase-op` and delegated to agent via `<required_reading>` blocks.
|
|
51
|
+
|
|
52
|
+
## Outside a phase
|
|
53
|
+
|
|
54
|
+
Reviewer lanes run without a phase (`gsd_run` is defined by the runtime-launcher preamble inside workflow fences; in a plain shell call `node <install>/gsd-core/bin/gsd-tools.cjs` instead): pipe canonical repo-relative file paths (one per line) to stdin of
|
|
55
|
+
`gsd_run review-lane dispatch-step --repo-root <root> --depth <quick|standard|deep> --base-sha <sha> --run-dir "$(mktemp -d)" --cap-id code-review --point execute:post --explicit <slugs> --raw`.
|
|
56
|
+
`review-lane` flags are space-separated (`--depth quick`), never `--flag=value`. `--explicit` (omitted, nothing dispatches yet the call exits ok), `--depth`, `--base-sha` (lane reviews changes relative to it; commit them first) and stdin paths are required; `--run-dir` should be a fresh temp dir (default `.` writes the prompt file into the current directory); read each lane's output path (`results[].reviewPath`) from the JSON before removing it. `--cap-id`/`--point` select the `code-review` capability, which must be enabled (`workflow.code_review`) and active at `--point` — `execute:post`, or `execute:wave:post` when `workflow.code_review_point` selects it; otherwise nothing dispatches.
|
|
57
|
+
`--explicit` takes comma-separated canonical slugs, no spaces (`codex,antigravity`), not flag aliases (`antigravity`, not `agy`); slugs: first column of `gsd_run review-lane sections` (`review-lane flags` lists flags/aliases).
|
|
58
|
+
Each lane declares its own model key, which is not always its slug (antigravity's is `review.models.agy`); see the `review.models.*` table in `docs/CONFIGURATION.md`. Unset = lane default model.
|
|
51
59
|
</context>
|
|
52
60
|
|
|
53
61
|
<process>
|
|
@@ -21,7 +21,7 @@ Routes to the pause-work workflow which handles:
|
|
|
21
21
|
- Current phase detection from recent files
|
|
22
22
|
- Complete state gathering (position, completed work, remaining work, decisions, blockers)
|
|
23
23
|
- Handoff file creation with all context sections
|
|
24
|
-
- Git commit
|
|
24
|
+
- Git commit handoff
|
|
25
25
|
- Resume instructions
|
|
26
26
|
</objective>
|
|
27
27
|
|
|
@@ -312,6 +312,7 @@ try {
|
|
|
312
312
|
} catch { /* advisory — never block */ }
|
|
313
313
|
|
|
314
314
|
const { resolveActiveWorkstream, applyResolvedWorkstreamEnv, peekActiveWorkstream } = require('./lib/active-workstream-store.cjs');
|
|
315
|
+
const { planningDir, planningRoot } = require('./lib/planning-workspace.cjs');
|
|
315
316
|
const state = require('./lib/state.cjs');
|
|
316
317
|
const phase = require('./lib/phase.cjs');
|
|
317
318
|
const roadmap = require('./lib/roadmap.cjs');
|
|
@@ -1445,8 +1446,12 @@ function dispatchOverlayCapabilityCommand({ command, args, cwd, raw, error, load
|
|
|
1445
1446
|
// Silent no-op when the section is absent or the table is already canonical
|
|
1446
1447
|
// — the quick/fast workflows call this before their first append, so the
|
|
1447
1448
|
// migration runs exactly once, on the first quick run, unprompted otherwise.
|
|
1448
|
-
const
|
|
1449
|
+
const planningPath = planningDir(cwd);
|
|
1450
|
+
const statePath = path.join(planningPath, 'STATE.md');
|
|
1449
1451
|
if (!fs.existsSync(statePath)) {
|
|
1452
|
+
if (planningPath !== planningRoot(cwd)) {
|
|
1453
|
+
throw new ExitError(1, `quick-tasks-migrate: STATE.md not found at ${statePath}`);
|
|
1454
|
+
}
|
|
1450
1455
|
output({ ok: true, migrated: false, reason: `STATE.md not found at ${statePath}` }, raw);
|
|
1451
1456
|
return;
|
|
1452
1457
|
}
|
|
@@ -1519,7 +1524,7 @@ function dispatchOverlayCapabilityCommand({ command, args, cwd, raw, error, load
|
|
|
1519
1524
|
|| (qtaQuickId && qtaSlug ? `[${qtaQuickId}-${qtaSlug}](./quick/${qtaQuickId}-${qtaSlug}/)` : undefined);
|
|
1520
1525
|
const qtaStatus = qtaParsed['status'] || undefined;
|
|
1521
1526
|
|
|
1522
|
-
const statePath = path.join(cwd, '
|
|
1527
|
+
const statePath = path.join(planningDir(cwd), 'STATE.md');
|
|
1523
1528
|
if (!fs.existsSync(statePath)) {
|
|
1524
1529
|
error(`quick-tasks-append: STATE.md not found at ${statePath}`, ERROR_REASON.USAGE);
|
|
1525
1530
|
}
|
|
@@ -1593,7 +1598,7 @@ function dispatchOverlayCapabilityCommand({ command, args, cwd, raw, error, load
|
|
|
1593
1598
|
const fsx = require('node:fs');
|
|
1594
1599
|
const os = require('node:os');
|
|
1595
1600
|
const { REVIEWER_LANES, mergeReviewerLanes } = require('./lib/review-lane-descriptor.cjs');
|
|
1596
|
-
const { resolveLanePlan: resolveLanePlanBase, resolveLaneEffort, resolveLaneBudget } = require('./lib/review-lane-invocation.cjs');
|
|
1601
|
+
const { resolveLanePlan: resolveLanePlanBase, resolveLaneEffort, resolveLaneBudget, applyPromptOverride } = require('./lib/review-lane-invocation.cjs');
|
|
1597
1602
|
// OpenCode 2.x argv differs from 1.x (no --variant; effort rides on the model as `#variant`;
|
|
1598
1603
|
// ADR-5331 D5/D8). The generation is probed lazily, only when the opencode lane is resolved.
|
|
1599
1604
|
const resolveLanePlan = (laneInput) => {
|
|
@@ -1945,7 +1950,7 @@ function dispatchOverlayCapabilityCommand({ command, args, cwd, raw, error, load
|
|
|
1945
1950
|
const dispatchResult = await dispatchReviewerLanes(
|
|
1946
1951
|
{
|
|
1947
1952
|
trait,
|
|
1948
|
-
selection: { explicitFlags, detected: rosterSlugs },
|
|
1953
|
+
selection: { explicitFlags, detected: rosterSlugs, lanes: mergedLanes },
|
|
1949
1954
|
repoRoot,
|
|
1950
1955
|
paths,
|
|
1951
1956
|
depth,
|
|
@@ -2097,14 +2102,11 @@ function dispatchOverlayCapabilityCommand({ command, args, cwd, raw, error, load
|
|
|
2097
2102
|
}
|
|
2098
2103
|
|
|
2099
2104
|
// `--prompt-file` lets the caller substitute a budget-trimmed prompt. Applied to whichever
|
|
2100
|
-
// channel this lane actually reads from,
|
|
2105
|
+
// channel this lane actually reads from (stdin, argv, an argv-embedded file reference, or the
|
|
2106
|
+
// http promptPath), so one flag serves every lane (#5049).
|
|
2101
2107
|
const promptOverride = flag('--prompt-file');
|
|
2102
2108
|
if (promptOverride) {
|
|
2103
|
-
|
|
2104
|
-
if (entry.plan.stdin) entry.plan.stdin = promptOverride;
|
|
2105
|
-
} else {
|
|
2106
|
-
entry.plan.promptPath = promptOverride;
|
|
2107
|
-
}
|
|
2109
|
+
entry.plan = applyPromptOverride(entry.plan, promptOverride, repoRoot);
|
|
2108
2110
|
}
|
|
2109
2111
|
|
|
2110
2112
|
// ADR-2782 D5 rule 4: re-resolve the consented destination at INVOCATION. `undefined` (no
|
|
@@ -3022,7 +3024,12 @@ function dispatchOverlayCapabilityCommand({ command, args, cwd, raw, error, load
|
|
|
3022
3024
|
const jsonIdx = args.indexOf('--json');
|
|
3023
3025
|
const agentSkillsJsonMode = jsonIdx !== -1;
|
|
3024
3026
|
if (agentSkillsJsonMode) args.splice(jsonIdx, 1);
|
|
3025
|
-
|
|
3027
|
+
// #5122: the agent's own self-load asks for configured skills only,
|
|
3028
|
+
// never the persona fallback served to orchestrator-side injection.
|
|
3029
|
+
const skillsOnlyIdx = args.indexOf('--skills-only');
|
|
3030
|
+
const agentSkillsOnly = skillsOnlyIdx !== -1;
|
|
3031
|
+
if (agentSkillsOnly) args.splice(skillsOnlyIdx, 1);
|
|
3032
|
+
init.cmdAgentSkills(cwd, args[1], raw, agentSkillsJsonMode, agentSkillsOnly);
|
|
3026
3033
|
}
|
|
3027
3034
|
|
|
3028
3035
|
function routeSkillManifest({ args, cwd, raw, error }) {
|
|
@@ -807,6 +807,28 @@ function reconcile(runtimeDir) {
|
|
|
807
807
|
}
|
|
808
808
|
return result;
|
|
809
809
|
}
|
|
810
|
+
/**
|
|
811
|
+
* #5121: the one bounded read for a SKILL.md found by walking a skill root. A skill file is untrusted
|
|
812
|
+
* repository (or installed-runtime) content: a symlink to /dev/zero exhausts memory and a FIFO blocks
|
|
813
|
+
* the process, because a bare readFileSync does neither a type nor a size check. Reuses the fd protocol
|
|
814
|
+
* of readSmallRegularFile and maps its fail-closed "unreadable" conditions (not a regular file after
|
|
815
|
+
* following symlinks, over the cap) to null, so a caller treats the file as it treats a missing one.
|
|
816
|
+
* Any other IO error still throws, as the unbounded read did.
|
|
817
|
+
*
|
|
818
|
+
* 256 KiB: the largest shipped SKILL.md is ~21 KB, so the cap is >10x headroom while still bounding the
|
|
819
|
+
* allocation a hostile repository can force.
|
|
820
|
+
*/
|
|
821
|
+
const SKILL_FILE_MAX_BYTES = 256 * 1024;
|
|
822
|
+
function readSkillFile(filePath) {
|
|
823
|
+
try {
|
|
824
|
+
return readSmallRegularFile(filePath, SKILL_FILE_MAX_BYTES);
|
|
825
|
+
}
|
|
826
|
+
catch (err) {
|
|
827
|
+
if (err instanceof LedgerIOError && (err.code === 'ENXIO' || err.code === 'EISDIR' || err.code === 'EFBIG'))
|
|
828
|
+
return null;
|
|
829
|
+
throw err;
|
|
830
|
+
}
|
|
831
|
+
}
|
|
810
832
|
module.exports = {
|
|
811
833
|
readLedger,
|
|
812
834
|
readLedgerStrict,
|
|
@@ -822,6 +844,9 @@ module.exports = {
|
|
|
822
844
|
// #1459 finding 1 (HIGH): the RAW-BYTES variant — the SOLE correct reader for the byte-exact,
|
|
823
845
|
// injective consent content-hash binding (a utf8 decode is lossy and could collide binary artifacts).
|
|
824
846
|
readSmallRegularFileBuffer,
|
|
847
|
+
// #5121: bounded SKILL.md read shared by skill discovery, the installed-runtime manifest and capability skills.
|
|
848
|
+
readSkillFile,
|
|
849
|
+
SKILL_FILE_MAX_BYTES,
|
|
825
850
|
// Exported for testing / introspection
|
|
826
851
|
LEDGER_FILE_NAME,
|
|
827
852
|
CorruptLedgerError,
|
|
@@ -176,7 +176,8 @@ function isSameHost(parsed) {
|
|
|
176
176
|
* equality comparison (never parsed as a date). The pair (pid, startTime) uniquely identifies a
|
|
177
177
|
* process instance: even if a crashed holder's pid is REUSED, the new process's start-time differs.
|
|
178
178
|
* Returns null on ANY error / unobtainable value (liveness cannot be VERIFIED → steal-eligible past
|
|
179
|
-
* the deadman).
|
|
179
|
+
* the deadman). Probing ANOTHER pid only happens on the rare STEAL-decision path; this process's own
|
|
180
|
+
* start-time is probed on its first lock acquire (see selfStartTime) — never at module load (#5327).
|
|
180
181
|
*/
|
|
181
182
|
function getProcessStartTime(pid) {
|
|
182
183
|
if (!Number.isInteger(pid) || pid <= 0)
|
|
@@ -208,11 +209,29 @@ function getProcessStartTime(pid) {
|
|
|
208
209
|
return null;
|
|
209
210
|
}
|
|
210
211
|
}
|
|
211
|
-
/**
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
212
|
+
/**
|
|
213
|
+
* THIS process's start-time, probed on the first lock acquire and cached so later acquires never re-shell.
|
|
214
|
+
* Not probed at module load: every config read loads this module, and most never take a lock (#5327).
|
|
215
|
+
* Only a successful probe is cached. A failed one (a PowerShell launch past its 5 s timeout on a loaded
|
|
216
|
+
* Windows host) is retried on the next acquire, up to SELF_PROBE_ATTEMPTS probes in all, so a host whose
|
|
217
|
+
* probe never succeeds pays a bounded cost instead of one launch per acquire.
|
|
218
|
+
* Probed per acquire ATTEMPT, before the O_EXCL create, so a process whose first acquire meets a live
|
|
219
|
+
* holder still pays it: probing after a successful create instead would widen the empty-body window
|
|
220
|
+
* that the steal path's `LOCK_STALE_MS` floor relies on.
|
|
221
|
+
*/
|
|
222
|
+
const SELF_PROBE_ATTEMPTS = 2;
|
|
223
|
+
let _selfStartTime = null;
|
|
224
|
+
let _selfProbeAttempts = 0;
|
|
225
|
+
function selfStartTime() {
|
|
226
|
+
if (_selfStartTime === null && _selfProbeAttempts < SELF_PROBE_ATTEMPTS) {
|
|
227
|
+
_selfProbeAttempts++;
|
|
228
|
+
_selfStartTime = getProcessStartTime(process.pid);
|
|
229
|
+
}
|
|
230
|
+
return _selfStartTime;
|
|
231
|
+
}
|
|
232
|
+
/** Serialize the lockfile body: JSON carrying the owner token, pid, hostname, start-time, ts. */
|
|
233
|
+
function lockFileBody(token, startTime) {
|
|
234
|
+
return JSON.stringify({ token, pid: process.pid, hostname: node_os_1.default.hostname(), startTime, ts: Date.now() });
|
|
216
235
|
}
|
|
217
236
|
// ---------------------------------------------------------------------------
|
|
218
237
|
// Liveness probes (test seam)
|
|
@@ -364,6 +383,9 @@ function acquireLock(lockPath, opts) {
|
|
|
364
383
|
? opts.maxAttempts
|
|
365
384
|
: LOCK_MAX_ATTEMPTS;
|
|
366
385
|
const waitForFresh = !!(opts && opts.waitForFresh);
|
|
386
|
+
// Probe BEFORE the O_EXCL create: the first probe can be a PowerShell launch, and between the create
|
|
387
|
+
// and the body write a racing acquirer sees an empty lockfile. That window must stay sub-ms (#5327).
|
|
388
|
+
const startTime = selfStartTime();
|
|
367
389
|
// A held lock that is NOT steal-eligible: fail-fast (return null) by default, or BACK OFF + RETRY
|
|
368
390
|
// (continue) when waitForFresh and a retry budget remains — so a contended consent writer serializes.
|
|
369
391
|
const blocked = (attempt) => {
|
|
@@ -382,7 +404,7 @@ function acquireLock(lockPath, opts) {
|
|
|
382
404
|
// write/close error, best-effort unlink the file we just created and bail. fs.writeFileSync(fd, …)
|
|
383
405
|
// flushes the WHOLE buffer (no short-write) unlike a bare fs.writeSync.
|
|
384
406
|
try {
|
|
385
|
-
node_fs_1.default.writeFileSync(fd, lockFileBody(token));
|
|
407
|
+
node_fs_1.default.writeFileSync(fd, lockFileBody(token, startTime));
|
|
386
408
|
}
|
|
387
409
|
catch (writeErr) {
|
|
388
410
|
try {
|