@opengsd/gsd-core 1.6.0-rc.2 → 1.6.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.
Files changed (157) hide show
  1. package/.claude-plugin/plugin.json +2 -1
  2. package/agents/gsd-advisor-researcher.md +2 -0
  3. package/agents/gsd-ai-researcher.md +2 -0
  4. package/agents/gsd-assumptions-analyzer.md +2 -0
  5. package/agents/gsd-doc-classifier.md +2 -0
  6. package/agents/gsd-doc-synthesizer.md +2 -0
  7. package/agents/gsd-domain-researcher.md +2 -0
  8. package/agents/gsd-eval-auditor.md +6 -9
  9. package/agents/gsd-phase-researcher.md +2 -0
  10. package/agents/gsd-planner.md +8 -57
  11. package/agents/gsd-project-researcher.md +2 -0
  12. package/agents/gsd-research-synthesizer.md +2 -0
  13. package/agents/gsd-security-auditor.md +37 -18
  14. package/agents/gsd-ui-researcher.md +2 -0
  15. package/bin/install.js +370 -18
  16. package/gemini-extension.json +1 -1
  17. package/gsd-core/bin/gsd-tools.cjs +46 -4
  18. package/gsd-core/bin/lib/audit-command-router.cjs +52 -14
  19. package/gsd-core/bin/lib/capability-lifecycle.cjs +30 -7
  20. package/gsd-core/bin/lib/capability-registry.cjs +96 -83
  21. package/gsd-core/bin/lib/capability-validator.cjs +22 -0
  22. package/gsd-core/bin/lib/cjs-command-router-adapter.cjs +40 -2
  23. package/gsd-core/bin/lib/command-aliases.cjs +10 -1
  24. package/gsd-core/bin/lib/command-routing-hub.cjs +10 -3
  25. package/gsd-core/bin/lib/config-schema.cjs +1 -0
  26. package/gsd-core/bin/lib/config.cjs +67 -24
  27. package/gsd-core/bin/lib/coverage.cjs +464 -0
  28. package/gsd-core/bin/lib/decisions.cjs +27 -0
  29. package/gsd-core/bin/lib/eval-command-router.cjs +21 -0
  30. package/gsd-core/bin/lib/eval.cjs +60 -0
  31. package/gsd-core/bin/lib/frontmatter.cjs +132 -13
  32. package/gsd-core/bin/lib/graphify-command-router.cjs +53 -36
  33. package/gsd-core/bin/lib/init.cjs +139 -30
  34. package/gsd-core/bin/lib/install-profiles.cjs +6 -3
  35. package/gsd-core/bin/lib/intel-command-router.cjs +79 -60
  36. package/gsd-core/bin/lib/io.cjs +1 -0
  37. package/gsd-core/bin/lib/phase.cjs +16 -2
  38. package/gsd-core/bin/lib/plan-scan.cjs +2 -2
  39. package/gsd-core/bin/lib/planning-workspace.cjs +157 -13
  40. package/gsd-core/bin/lib/profile-output.cjs +18 -6
  41. package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +53 -16
  42. package/gsd-core/bin/lib/runtime-artifact-layout.cjs +21 -3
  43. package/gsd-core/bin/lib/runtime-hooks-surface.cjs +15 -0
  44. package/gsd-core/bin/lib/runtime-name-policy.cjs +47 -2
  45. package/gsd-core/bin/lib/shell-command-projection.cjs +10 -0
  46. package/gsd-core/bin/lib/state.cjs +398 -60
  47. package/gsd-core/bin/lib/surface.cjs +42 -10
  48. package/gsd-core/bin/lib/uat-predicate.cjs +13 -6
  49. package/gsd-core/bin/lib/update-context.cjs +2 -2
  50. package/gsd-core/bin/lib/verification.cjs +67 -6
  51. package/gsd-core/bin/lib/verify.cjs +8 -1
  52. package/gsd-core/bin/shared/config-defaults.manifest.json +3 -0
  53. package/gsd-core/bin/shared/config-schema.manifest.json +2 -1
  54. package/gsd-core/references/planner-guidance.md +66 -0
  55. package/gsd-core/references/planning-config.md +2 -2
  56. package/gsd-core/references/security-asvs-levels.md +27 -0
  57. package/gsd-core/references/untrusted-input-boundary.md +13 -0
  58. package/gsd-core/templates/SECURITY.md +6 -4
  59. package/gsd-core/templates/summary-complex.md +4 -0
  60. package/gsd-core/templates/summary-minimal.md +3 -0
  61. package/gsd-core/templates/summary-standard.md +4 -0
  62. package/gsd-core/templates/summary.md +41 -0
  63. package/gsd-core/workflows/autonomous.md +53 -46
  64. package/gsd-core/workflows/complete-milestone.md +27 -8
  65. package/gsd-core/workflows/execute-phase.md +1 -1
  66. package/gsd-core/workflows/execute-plan.md +5 -0
  67. package/gsd-core/workflows/manager.md +17 -7
  68. package/gsd-core/workflows/new-project.md +82 -16
  69. package/gsd-core/workflows/plan-phase.md +15 -0
  70. package/gsd-core/workflows/profile-user.md +6 -2
  71. package/gsd-core/workflows/progress.md +37 -4
  72. package/gsd-core/workflows/quick.md +3 -1
  73. package/gsd-core/workflows/secure-phase.md +13 -7
  74. package/gsd-core/workflows/ship.md +3 -1
  75. package/gsd-core/workflows/spec-phase.md +3 -1
  76. package/gsd-core/workflows/transition.md +14 -12
  77. package/gsd-core/workflows/ui-review.md +2 -6
  78. package/gsd-core/workflows/verify-work.md +74 -1
  79. package/hooks/dist/gsd-read-injection-scanner.js +49 -25
  80. package/hooks/gsd-read-injection-scanner.js +49 -25
  81. package/hooks/hooks.json +1 -1
  82. package/package.json +4 -2
  83. package/scripts/check-alias-drift.cjs +5 -0
  84. package/scripts/gen-plugin-skills.cjs +117 -0
  85. package/scripts/lint-test-file-count.allowlist.json +2 -1
  86. package/scripts/prompt-injection-scan.sh +9 -0
  87. package/scripts/release-notes/conventional-title.cjs +88 -0
  88. package/scripts/release-notes/format-github-release-notes.cjs +4 -3
  89. package/skills/gsd-add-tests/SKILL.md +38 -0
  90. package/skills/gsd-ai-integration-phase/SKILL.md +37 -0
  91. package/skills/gsd-audit-fix/SKILL.md +33 -0
  92. package/skills/gsd-audit-milestone/SKILL.md +37 -0
  93. package/skills/gsd-audit-uat/SKILL.md +25 -0
  94. package/skills/gsd-autonomous/SKILL.md +51 -0
  95. package/skills/gsd-capture/SKILL.md +67 -0
  96. package/skills/gsd-cleanup/SKILL.md +24 -0
  97. package/skills/gsd-code-review/SKILL.md +59 -0
  98. package/skills/gsd-complete-milestone/SKILL.md +142 -0
  99. package/skills/gsd-config/SKILL.md +56 -0
  100. package/skills/gsd-debug/SKILL.md +53 -0
  101. package/skills/gsd-discuss-phase/SKILL.md +77 -0
  102. package/skills/gsd-docs-update/SKILL.md +49 -0
  103. package/skills/gsd-eval-review/SKILL.md +33 -0
  104. package/skills/gsd-execute-phase/SKILL.md +65 -0
  105. package/skills/gsd-explore/SKILL.md +28 -0
  106. package/skills/gsd-extract-learnings/SKILL.md +22 -0
  107. package/skills/gsd-fast/SKILL.md +31 -0
  108. package/skills/gsd-forensics/SKILL.md +56 -0
  109. package/skills/gsd-graphify/SKILL.md +204 -0
  110. package/skills/gsd-health/SKILL.md +31 -0
  111. package/skills/gsd-help/SKILL.md +29 -0
  112. package/skills/gsd-import/SKILL.md +46 -0
  113. package/skills/gsd-inbox/SKILL.md +39 -0
  114. package/skills/gsd-ingest-docs/SKILL.md +43 -0
  115. package/skills/gsd-manager/SKILL.md +45 -0
  116. package/skills/gsd-map-codebase/SKILL.md +83 -0
  117. package/skills/gsd-mempalace-capture/SKILL.md +71 -0
  118. package/skills/gsd-mempalace-recall/SKILL.md +102 -0
  119. package/skills/gsd-milestone-summary/SKILL.md +51 -0
  120. package/skills/gsd-mvp-phase/SKILL.md +45 -0
  121. package/skills/gsd-new-milestone/SKILL.md +45 -0
  122. package/skills/gsd-new-project/SKILL.md +47 -0
  123. package/skills/gsd-ns-context/SKILL.md +24 -0
  124. package/skills/gsd-ns-ideate/SKILL.md +23 -0
  125. package/skills/gsd-ns-manage/SKILL.md +35 -0
  126. package/skills/gsd-ns-project/SKILL.md +26 -0
  127. package/skills/gsd-ns-review/SKILL.md +28 -0
  128. package/skills/gsd-ns-workflow/SKILL.md +33 -0
  129. package/skills/gsd-pause-work/SKILL.md +43 -0
  130. package/skills/gsd-phase/SKILL.md +57 -0
  131. package/skills/gsd-plan-phase/SKILL.md +63 -0
  132. package/skills/gsd-plan-review-convergence/SKILL.md +60 -0
  133. package/skills/gsd-pr-branch/SKILL.md +26 -0
  134. package/skills/gsd-profile-user/SKILL.md +47 -0
  135. package/skills/gsd-progress/SKILL.md +49 -0
  136. package/skills/gsd-quick/SKILL.md +174 -0
  137. package/skills/gsd-resume-work/SKILL.md +31 -0
  138. package/skills/gsd-review/SKILL.md +42 -0
  139. package/skills/gsd-review-backlog/SKILL.md +63 -0
  140. package/skills/gsd-secure-phase/SKILL.md +36 -0
  141. package/skills/gsd-settings/SKILL.md +29 -0
  142. package/skills/gsd-ship/SKILL.md +24 -0
  143. package/skills/gsd-sketch/SKILL.md +60 -0
  144. package/skills/gsd-spec-phase/SKILL.md +63 -0
  145. package/skills/gsd-spike/SKILL.md +57 -0
  146. package/skills/gsd-stats/SKILL.md +20 -0
  147. package/skills/gsd-surface/SKILL.md +162 -0
  148. package/skills/gsd-thread/SKILL.md +24 -0
  149. package/skills/gsd-ui-phase/SKILL.md +35 -0
  150. package/skills/gsd-ui-review/SKILL.md +33 -0
  151. package/skills/gsd-ultraplan-phase/SKILL.md +34 -0
  152. package/skills/gsd-undo/SKILL.md +35 -0
  153. package/skills/gsd-update/SKILL.md +50 -0
  154. package/skills/gsd-validate-phase/SKILL.md +36 -0
  155. package/skills/gsd-verify-work/SKILL.md +39 -0
  156. package/skills/gsd-workspace/SKILL.md +53 -0
  157. package/skills/gsd-workstreams/SKILL.md +70 -0
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "gsd-core",
3
3
  "displayName": "GSD Core",
4
- "version": "1.6.0-rc.2",
4
+ "version": "1.6.0",
5
5
  "description": "GSD Core is a meta-prompting, context engineering, and spec-driven development system for AI coding agents.",
6
6
  "author": {
7
7
  "name": "open-gsd",
@@ -19,5 +19,6 @@
19
19
  "gsd"
20
20
  ],
21
21
  "commands": "./commands/gsd/",
22
+ "skills": "./skills/",
22
23
  "hooks": "./hooks/hooks.json"
23
24
  }
@@ -17,6 +17,8 @@ Spawned by `discuss-phase` via `Task()`. You do NOT present output directly to t
17
17
  - Return structured markdown output for the main agent to synthesize
18
18
  </role>
19
19
 
20
+ @~/.claude/gsd-core/references/untrusted-input-boundary.md
21
+
20
22
  <documentation_lookup>
21
23
  @~/.claude/gsd-core/references/research-documentation-lookup.md
22
24
  </documentation_lookup>
@@ -16,6 +16,8 @@ You are a GSD AI researcher. Answer: "How do I correctly implement this AI syste
16
16
  Write Sections 3–4b of AI-SPEC.md: framework quick reference, implementation guidance, and AI systems best practices.
17
17
  </role>
18
18
 
19
+ @~/.claude/gsd-core/references/untrusted-input-boundary.md
20
+
19
21
  <documentation_lookup>
20
22
  @~/.claude/gsd-core/references/research-documentation-lookup.md
21
23
  </documentation_lookup>
@@ -18,6 +18,8 @@ Spawned by `discuss-phase-assumptions` via `Task()`. You do NOT present output d
18
18
  - Flag topics where codebase analysis alone is insufficient (needs external research)
19
19
  </role>
20
20
 
21
+ @~/.claude/gsd-core/references/untrusted-input-boundary.md
22
+
21
23
  <input>
22
24
  Agent receives via prompt:
23
25
 
@@ -18,6 +18,8 @@ You are a GSD doc classifier. You read ONE document and write a structured class
18
18
  If the prompt contains a `<required_reading>` block, use the `Read` tool to load every file listed there before doing anything else. That is your primary context.
19
19
  </role>
20
20
 
21
+ @~/.claude/gsd-core/references/untrusted-input-boundary.md
22
+
21
23
  <why_this_matters>
22
24
  Your classification drives extraction. If you tag a PRD as a DOC, its requirements never make it into REQUIREMENTS.md. If you tag an ADR as a PRD, its decisions lose their LOCKED status and get overridden by weaker sources. Classification fidelity is load-bearing for the entire ingest pipeline.
23
25
  </why_this_matters>
@@ -20,6 +20,8 @@ You do NOT prompt the user. You do NOT write PROJECT.md, REQUIREMENTS.md, or ROA
20
20
  If the prompt contains a `<required_reading>` block, load every file listed there first — especially `references/doc-conflict-engine.md` which defines your conflict report format.
21
21
  </role>
22
22
 
23
+ @~/.claude/gsd-core/references/untrusted-input-boundary.md
24
+
23
25
  <why_this_matters>
24
26
  You are the precedence-enforcing layer. Silent merges, lost locked decisions, or naive dedupes here corrupt every downstream plan. When in doubt, surface the conflict rather than pick.
25
27
  </why_this_matters>
@@ -16,6 +16,8 @@ You are a GSD domain researcher. Answer: "What do domain experts actually care a
16
16
  Research the business domain — not the technical framework. Write Section 1b of AI-SPEC.md.
17
17
  </role>
18
18
 
19
+ @~/.claude/gsd-core/references/untrusted-input-boundary.md
20
+
19
21
  <documentation_lookup>
20
22
  @~/.claude/gsd-core/references/research-documentation-lookup.md
21
23
  </documentation_lookup>
@@ -109,17 +109,14 @@ Score 5 components (ok / partial / missing):
109
109
  </step>
110
110
 
111
111
  <step name="calculate_scores">
112
- ```
113
- coverage_score = covered_count / total_dimensions × 100
114
- infra_score = (tooling + dataset + cicd + guardrails + tracing) / 5 × 100
115
- overall_score = (coverage_score × 0.6) + (infra_score × 0.4)
112
+ Do NOT compute scores by hand. Call the deterministic verb with your audited inputs:
113
+
114
+ ```bash
115
+ _GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; if [ -f "$GSD_TOOLS" ]; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif command -v gsd-tools >/dev/null 2>&1; then GSD_TOOLS="$(command -v gsd-tools)"; gsd_run() { "$GSD_TOOLS" "$@"; }; elif [ -f "$HOME/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="$HOME/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and gsd-tools is not on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; if [ -n "${CLAUDE_ENV_FILE:-}" ] && [ -n "${GSD_TOOLS:-}" ]; then printf "export PATH='%s':\"\$PATH\"\n" "${GSD_TOOLS%/*}" >> "$CLAUDE_ENV_FILE" 2>/dev/null || true; fi
116
+ gsd_run query eval.score --covered <covered_count> --total <total_dimensions> --infra <tooling>,<dataset>,<cicd>,<guardrails>,<tracing> --raw
116
117
  ```
117
118
 
118
- Verdict:
119
- - 80-100: **PRODUCTION READY** — deploy with monitoring
120
- - 60-79: **NEEDS WORK** — address CRITICAL gaps before production
121
- - 40-59: **SIGNIFICANT GAPS** — do not deploy
122
- - 0-39: **NOT IMPLEMENTED** — review AI-SPEC.md and implement
119
+ where each infra component is `ok`, `partial`, or `missing` (from the audit_infrastructure step). Parse the JSON result — it returns `coverage_score`, `infra_score`, `overall_score`, and `verdict` (PRODUCTION READY / NEEDS WORK / SIGNIFICANT GAPS / NOT IMPLEMENTED). Use those values verbatim in EVAL-REVIEW.md; never recompute or override them.
123
120
  </step>
124
121
 
125
122
  <step name="write_eval_review">
@@ -35,6 +35,8 @@ Spawned by `/gsd:plan-phase` (integrated) or `/gsd:plan-phase --research-phase <
35
35
  Claims tagged `[ASSUMED]` signal to the planner and discuss-phase that the information needs user confirmation before becoming a locked decision. Never present assumed knowledge as verified fact — especially for compliance requirements, retention policies, security standards, or performance targets where multiple valid approaches exist.
36
36
  </role>
37
37
 
38
+ @~/.claude/gsd-core/references/untrusted-input-boundary.md
39
+
38
40
  <documentation_lookup>
39
41
  @~/.claude/gsd-core/references/research-documentation-lookup.md
40
42
  </documentation_lookup>
@@ -380,11 +380,11 @@ Output: [Artifacts created]
380
380
 
381
381
  ## STRIDE Threat Register
382
382
 
383
- | Threat ID | Category | Component | Disposition | Mitigation Plan |
384
- |-----------|----------|-----------|-------------|-----------------|
385
- | T-{phase}-01 | {S/T/R/I/D/E} | {function/endpoint/file} | mitigate | {specific: e.g., "validate input with zod at route entry"} |
386
- | T-{phase}-02 | {category} | {component} | accept | {rationale: e.g., "no PII, low-value target"} |
387
- | T-{phase}-SC | Tampering | npm/pip/cargo installs | mitigate | slopcheck + blocking human checkpoint for [ASSUMED]/[SUS] |
383
+ | Threat ID | Category | Component | Severity | Disposition | Mitigation Plan |
384
+ |-----------|----------|-----------|----------|-------------|-----------------|
385
+ | T-{phase}-01 | {S/T/R/I/D/E} | {function/endpoint/file} | {critical\|high\|medium\|low} | mitigate | {specific mitigation action} |
386
+ | T-{phase}-02 | {category} | {component} | low | accept | {rationale for acceptance} |
387
+ | T-{phase}-SC | Tampering | npm/pip/cargo installs | high | mitigate | slopcheck + blocking human checkpoint for [ASSUMED]/[SUS] |
388
388
  </threat_model>
389
389
 
390
390
  <verification>
@@ -459,7 +459,7 @@ Only include what Claude literally cannot do.
459
459
  **Step 0: Extract Requirement IDs**
460
460
  Read ROADMAP.md `**Requirements:**` line for this phase. Strip brackets if present (e.g., `[AUTH-01, AUTH-02]` → `AUTH-01, AUTH-02`). Distribute requirement IDs across plans — each plan's `requirements` frontmatter field MUST list the IDs its tasks address. **CRITICAL:** Every requirement ID MUST appear in at least one plan. Plans with an empty `requirements` field are invalid.
461
461
 
462
- **Security (when `security_enforcement` enabled — absent = enabled):** Identify trust boundaries in this phase's scope. Map STRIDE categories to applicable tech stack from RESEARCH.md security domain. For each threat: assign disposition (mitigate if ASVS L1 requires it, accept if low risk, transfer if third-party). Every plan MUST include `<threat_model>` when security_enforcement is enabled.
462
+ **Security (when `security_enforcement` enabled — absent = enabled):** Identify trust boundaries in this phase's scope. Map STRIDE categories to applicable tech stack from RESEARCH.md security domain. For each threat: assign a **severity** (critical|high|medium|low) based on impact × likelihood, and a disposition (`mitigate`/`accept`/`transfer`) per the configured OWASP ASVS level — see @~/.claude/gsd-core/references/security-asvs-levels.md. Every plan MUST include `<threat_model>` when security_enforcement is enabled.
463
463
 
464
464
  **Package legitimacy gate (npm/pip/cargo only):**
465
465
  - Require RESEARCH.md `## Package Legitimacy Audit` before package-manager install tasks.
@@ -477,66 +477,16 @@ Take phase goal from ROADMAP.md. Must be outcome-shaped, not task-shaped.
477
477
  **Step 2: Derive Observable Truths**
478
478
  "What must be TRUE for this goal to be achieved?" List 3-7 truths from USER's perspective.
479
479
 
480
- For "working chat interface":
481
- - User can see existing messages
482
- - User can type a new message
483
- - User can send the message
484
- - Sent message appears in the list
485
- - Messages persist across page refresh
486
-
487
- **Test:** Each truth verifiable by a human using the application.
488
-
489
480
  **Step 3: Derive Required Artifacts**
490
481
  For each truth: "What must EXIST for this to be true?"
491
482
 
492
- "User can see existing messages" requires:
493
- - Message list component (renders Message[])
494
- - Messages state (loaded from somewhere)
495
- - API route or data source (provides messages)
496
- - Message type definition (shapes the data)
497
-
498
- **Test:** Each artifact = a specific file or database object.
499
-
500
483
  **Step 4: Derive Required Wiring**
501
484
  For each artifact: "What must be CONNECTED for this to function?"
502
485
 
503
- Message list component wiring:
504
- - Imports Message type (not using `any`)
505
- - Receives messages prop or fetches from API
506
- - Maps over messages to render (not hardcoded)
507
- - Handles empty state (not just crashes)
508
-
509
486
  **Step 5: Identify Key Links**
510
487
  "Where is this most likely to break?" Key links = critical connections where breakage causes cascading failures.
511
488
 
512
- ## Must-Haves Output Format
513
-
514
- ```yaml
515
- must_haves:
516
- truths:
517
- - "User can see existing messages"
518
- - "User can send a message"
519
- - "Messages persist across refresh"
520
- artifacts:
521
- - path: "src/components/Chat.tsx"
522
- provides: "Message list rendering"
523
- min_lines: 30
524
- - path: "src/app/api/chat/route.ts"
525
- provides: "Message CRUD operations"
526
- exports: ["GET", "POST"]
527
- - path: "prisma/schema.prisma"
528
- provides: "Message model"
529
- contains: "model Message"
530
- key_links:
531
- - from: "src/components/Chat.tsx"
532
- to: "src/app/api/chat/route.ts"
533
- via: "fetch in useEffect — calls /api/chat endpoint"
534
- pattern: "fetch.*api/chat"
535
- - from: "src/app/api/chat/route.ts"
536
- to: "prisma/schema.prisma"
537
- via: "database query via prisma.message"
538
- pattern: "prisma\\.message\\.(find|create)"
539
- ```
489
+ See @~/.claude/gsd-core/references/planner-guidance.md for a worked example and the `must_haves` YAML format.
540
490
 
541
491
  </goal_backward>
542
492
 
@@ -1037,6 +987,7 @@ Phase planning complete when:
1037
987
  - [ ] User knows next steps and wave structure
1038
988
  - [ ] `<threat_model>` present with STRIDE register (when `security_enforcement` enabled)
1039
989
  - [ ] Every threat has a disposition (mitigate / accept / transfer)
990
+ - [ ] Every threat has a Severity (critical|high|medium|low)
1040
991
  - [ ] Mitigations reference specific implementation (not generic advice)
1041
992
 
1042
993
  ## Gap Closure Mode
@@ -32,6 +32,8 @@ Your files feed the roadmap:
32
32
  **Be comprehensive but opinionated.** "Use X because Y" not "Options are X, Y, Z."
33
33
  </role>
34
34
 
35
+ @~/.claude/gsd-core/references/untrusted-input-boundary.md
36
+
35
37
  <documentation_lookup>
36
38
  @~/.claude/gsd-core/references/research-documentation-lookup.md
37
39
  </documentation_lookup>
@@ -32,6 +32,8 @@ If the prompt contains a `<required_reading>` block, you MUST use the `Read` too
32
32
  - Commit ALL research files (researchers write but don't commit — you commit everything)
33
33
  </role>
34
34
 
35
+ @~/.claude/gsd-core/references/untrusted-input-boundary.md
36
+
35
37
  <downstream_consumer>
36
38
  Your SUMMARY.md is consumed by the gsd-roadmapper agent which uses it to:
37
39
 
@@ -33,18 +33,19 @@ Does NOT scan blindly for new vulnerabilities. Verifies each threat in `<threat_
33
33
  - Marking CLOSED based on code structure ("looks like it validates input") without finding the actual validation call
34
34
 
35
35
  **Required finding classification:**
36
- - **BLOCKER** — `OPEN_THREATS`: a declared mitigation is absent in implemented code; phase must not ship
36
+ - **BLOCKER** — `OPEN_THREATS`: a declared mitigation is absent in implemented code AND the threat's severity ≥ `block_on` threshold; phase must not ship until resolved
37
+ - **OPEN — non-blocking** — mitigation absent BUT the threat's severity is below the `block_on` threshold; tracked in SECURITY.md, does NOT count toward `threats_open`, does not block ship
37
38
  - **WARNING** — `unregistered_flag`: new attack surface appeared during implementation with no threat mapping
38
- Every threat must resolve to CLOSED, OPEN (BLOCKER), or documented accepted risk.
39
+ Every threat must resolve to CLOSED, OPEN-blocking (severity ≥ block_on), OPEN-non-blocking (severity below block_on), or documented accepted risk.
39
40
  </adversarial_stance>
40
41
 
41
42
  <execution_flow>
42
43
 
43
44
  <step name="load_context">
44
45
  Read ALL files from `<required_reading>`. Extract:
45
- - PLAN.md `<threat_model>` block: full threat register with IDs, categories, dispositions, mitigation plans
46
+ - PLAN.md `<threat_model>` block: full threat register with IDs, categories, severities, dispositions, mitigation plans
46
47
  - SUMMARY.md `## Threat Flags` section: new attack surface detected by executor during implementation
47
- - `<config>` block: `asvs_level` (1/2/3), `block_on` (open / unregistered / none)
48
+ - `<config>` block: `asvs_level` (1/2/3), `block_on` (critical | high | medium | low | none) — severity ordering: critical > high > medium > low; none = never block
48
49
  - Implementation files: exports, auth patterns, input handling, data flows
49
50
 
50
51
  **Context budget:** Load project skills first (lightweight). Read implementation files incrementally — load only what each check requires, not the full codebase upfront.
@@ -60,7 +61,7 @@ This ensures project-specific patterns, conventions, and best practices are appl
60
61
  </step>
61
62
 
62
63
  <step name="analyze_threats">
63
- For each threat in `<threat_model>`, determine verification method by disposition:
64
+ For each threat in `<threat_model>`, read its `severity` field (critical|high|medium|low). If building the register retroactively (no `<threat_model>` in PLAN.md), assign a severity to each threat you construct based on impact × likelihood. Determine verification method by disposition:
64
65
 
65
66
  | Disposition | Verification Method |
66
67
  |-------------|---------------------|
@@ -69,16 +70,27 @@ For each threat in `<threat_model>`, determine verification method by dispositio
69
70
  | `transfer` | Verify transfer documentation present (insurance, vendor SLA, etc.) |
70
71
 
71
72
  Classify each threat before verification. Record classification for every threat — no threat skipped.
73
+
74
+ **Verification depth scales with `asvs_level`** (see @~/.claude/gsd-core/references/security-asvs-levels.md for full definitions):
75
+ - L1: verify mitigation is PRESENT in the cited file (grep-level — pattern exists).
76
+ - L2: verify the mitigation ADDRESSES the threat vector and is placed at the correct boundary (a check in the wrong layer does not close the threat).
77
+ - L3: deep trace — follow the data flow end-to-end, check edge cases and ordering, confirm no bypass path exists.
72
78
  </step>
73
79
 
74
80
  <step name="verify_and_write">
75
- For each `mitigate` threat: grep for declared mitigation pattern in cited files → found = `CLOSED`, not found = `OPEN`.
81
+ For each `mitigate` threat: grep for declared mitigation pattern in cited files → found = `CLOSED`, not found = `OPEN`. Apply depth per `asvs_level` (see analyze_threats step).
76
82
  For `accept` threats: check SECURITY.md accepted risks log → entry present = `CLOSED`, absent = `OPEN`.
77
83
  For `transfer` threats: check for transfer documentation → present = `CLOSED`, absent = `OPEN`.
78
84
 
79
85
  For each `threat_flag` in SUMMARY.md `## Threat Flags`: if maps to existing threat ID → informational. If no mapping → log as `unregistered_flag` in SECURITY.md (not a blocker).
80
86
 
81
- Write SECURITY.md. Set `threats_open` count. Return structured result.
87
+ **Severity-aware `threats_open` computation (severity order: critical > high > medium > low):**
88
+ `threats_open` (the SECURITY.md frontmatter gate field) = the count of threats whose status is OPEN AND whose severity rank ≥ the `block_on` rank. `block_on: none` ⇒ 0 (nothing ever blocks). `block_on: low` ⇒ all open threats block. `block_on: high` (default) ⇒ only high and critical open threats block.
89
+ Open threats BELOW the block threshold are recorded in SECURITY.md as **open — below {block_on} threshold (non-blocking)** and MUST NOT be counted in `threats_open`.
90
+
91
+ **Fail-closed for missing severity:** if an OPEN threat has no severity or an unparseable severity (e.g. a legacy register predating the Severity column), treat it as `critical` for this computation — it COUNTS toward `threats_open` (blocking). Never silently drop an unranked open threat.
92
+
93
+ Write SECURITY.md. Set `threats_open` to the severity-filtered count. Return structured result.
82
94
  </step>
83
95
 
84
96
  </execution_flow>
@@ -95,9 +107,9 @@ Write SECURITY.md. Set `threats_open` count. Return structured result.
95
107
  **ASVS Level:** {1/2/3}
96
108
 
97
109
  ### Threat Verification
98
- | Threat ID | Category | Disposition | Evidence |
99
- |-----------|----------|-------------|----------|
100
- | {id} | {category} | {mitigate/accept/transfer} | {file:line or doc reference} |
110
+ | Threat ID | Category | Severity | Disposition | Evidence |
111
+ |-----------|----------|----------|-------------|----------|
112
+ | {id} | {category} | {critical\|high\|medium\|low} | {mitigate/accept/transfer} | {file:line or doc reference} |
101
113
 
102
114
  ### Unregistered Flags
103
115
  {none / list from SUMMARY.md ## Threat Flags with no threat mapping}
@@ -115,14 +127,21 @@ SECURITY.md: {path}
115
127
  **ASVS Level:** {1/2/3}
116
128
 
117
129
  ### Closed
118
- | Threat ID | Category | Disposition | Evidence |
119
- |-----------|----------|-------------|----------|
120
- | {id} | {category} | {disposition} | {evidence} |
121
-
122
- ### Open
123
- | Threat ID | Category | Mitigation Expected | Files Searched |
124
- |-----------|----------|---------------------|----------------|
125
- | {id} | {category} | {pattern not found} | {file paths} |
130
+ | Threat ID | Category | Severity | Disposition | Evidence |
131
+ |-----------|----------|----------|-------------|----------|
132
+ | {id} | {category} | {critical\|high\|medium\|low} | {disposition} | {evidence} |
133
+
134
+ ### Open (blocking — severity ≥ block_on threshold)
135
+ | Threat ID | Category | Severity | Mitigation Expected | Files Searched |
136
+ |-----------|----------|----------|---------------------|----------------|
137
+ | {id} | {category} | {critical\|high\|medium\|low} | {pattern not found} | {file paths} |
138
+
139
+ ### Open (non-blocking — severity below block_on threshold)
140
+ | Threat ID | Category | Severity | Mitigation Expected | Files Searched |
141
+ |-----------|----------|----------|---------------------|----------------|
142
+ | {id} | {category} | {critical\|high\|medium\|low} | {pattern not found} | {file paths} |
143
+
144
+ *Only blocking-open threats count toward `threats_open` in SECURITY.md frontmatter.*
126
145
 
127
146
  Next: Implement mitigations or document as accepted in SECURITY.md accepted risks log, then re-run /gsd:secure-phase.
128
147
 
@@ -27,6 +27,8 @@ If the prompt contains a `<required_reading>` block, you MUST use the `Read` too
27
27
  - Return structured result to orchestrator
28
28
  </role>
29
29
 
30
+ @~/.claude/gsd-core/references/untrusted-input-boundary.md
31
+
30
32
  <documentation_lookup>
31
33
  @~/.claude/gsd-core/references/research-documentation-lookup.md
32
34
  </documentation_lookup>