@opengsd/gsd-core 1.13.0 → 1.14.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 (257) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/agents/gsd-advisor-researcher.compact.md +85 -0
  4. package/agents/gsd-ai-researcher.compact.md +96 -0
  5. package/agents/gsd-assumptions-analyzer.compact.md +81 -0
  6. package/agents/gsd-code-fixer.compact.md +458 -0
  7. package/agents/gsd-code-fixer.md +5 -5
  8. package/agents/gsd-code-reviewer.compact.md +269 -0
  9. package/agents/gsd-code-reviewer.md +15 -3
  10. package/agents/gsd-codebase-mapper.compact.md +760 -0
  11. package/agents/gsd-debug-session-manager.compact.md +345 -0
  12. package/agents/gsd-doc-classifier.compact.md +192 -0
  13. package/agents/gsd-doc-synthesizer.compact.md +200 -0
  14. package/agents/gsd-doc-verifier.compact.md +143 -0
  15. package/agents/gsd-doc-writer.compact.md +440 -0
  16. package/agents/gsd-dom-verifier.compact.md +138 -0
  17. package/agents/gsd-domain-researcher.compact.md +141 -0
  18. package/agents/gsd-eval-auditor.compact.md +160 -0
  19. package/agents/gsd-eval-planner.compact.md +137 -0
  20. package/agents/gsd-framework-selector.compact.md +82 -0
  21. package/agents/gsd-integration-checker.compact.md +245 -0
  22. package/agents/gsd-intel-updater.compact.md +226 -0
  23. package/agents/gsd-mempalace-curator.compact.md +45 -0
  24. package/agents/gsd-nyquist-auditor.compact.md +179 -0
  25. package/agents/gsd-pattern-mapper.compact.md +275 -0
  26. package/agents/gsd-project-researcher.compact.md +587 -0
  27. package/agents/gsd-research-synthesizer.compact.md +212 -0
  28. package/agents/gsd-roadmapper.compact.md +454 -0
  29. package/agents/gsd-roadmapper.md +13 -0
  30. package/agents/gsd-security-auditor.compact.md +162 -0
  31. package/agents/gsd-ui-auditor.compact.md +404 -0
  32. package/agents/gsd-ui-checker.compact.md +277 -0
  33. package/agents/gsd-ui-researcher.compact.md +282 -0
  34. package/agents/gsd-user-profiler.compact.md +108 -0
  35. package/bin/install.js +206 -68
  36. package/commands/gsd/cleanup.md +1 -0
  37. package/commands/gsd/code-review.md +2 -1
  38. package/commands/gsd/complete-milestone.md +1 -0
  39. package/commands/gsd/config.md +1 -0
  40. package/commands/gsd/debug.md +1 -0
  41. package/commands/gsd/graphify.md +1 -0
  42. package/commands/gsd/health.md +1 -0
  43. package/commands/gsd/mempalace-capture.md +1 -0
  44. package/commands/gsd/mempalace-recall.md +1 -0
  45. package/commands/gsd/new-milestone.md +1 -0
  46. package/commands/gsd/new-project.md +1 -0
  47. package/commands/gsd/next.md +1 -0
  48. package/commands/gsd/pause-work.md +1 -0
  49. package/commands/gsd/phase.md +1 -0
  50. package/commands/gsd/pr-branch.md +1 -0
  51. package/commands/gsd/resume-work.md +1 -0
  52. package/commands/gsd/review-backlog.md +1 -0
  53. package/commands/gsd/settings.md +2 -1
  54. package/commands/gsd/stats.md +1 -0
  55. package/commands/gsd/thread.md +1 -0
  56. package/commands/gsd/workspace.md +1 -0
  57. package/commands/gsd/workstreams.md +1 -0
  58. package/gsd-core/bin/check-latest-version.cjs +8 -3
  59. package/gsd-core/bin/gsd-tools.cjs +338 -125
  60. package/gsd-core/bin/lib/adr-parser.cjs +1 -1
  61. package/gsd-core/bin/lib/artifacts.cjs +2 -1
  62. package/gsd-core/bin/lib/audit.cjs +39 -22
  63. package/gsd-core/bin/lib/broken-windows.cjs +168 -49
  64. package/gsd-core/bin/lib/capability-lifecycle.cjs +10 -6
  65. package/gsd-core/bin/lib/capability-loader.cjs +135 -1
  66. package/gsd-core/bin/lib/capability-registry.cjs +79 -67
  67. package/gsd-core/bin/lib/capability-source.cjs +19 -2
  68. package/gsd-core/bin/lib/capability-validator.cjs +14 -1
  69. package/gsd-core/bin/lib/check-command-router.cjs +113 -36
  70. package/gsd-core/bin/lib/code-review-depth.cjs +2 -2
  71. package/gsd-core/bin/lib/commands.cjs +650 -72
  72. package/gsd-core/bin/lib/config-loader.cjs +1 -0
  73. package/gsd-core/bin/lib/config.cjs +153 -38
  74. package/gsd-core/bin/lib/coverage.cjs +1 -1
  75. package/gsd-core/bin/lib/decisions.cjs +137 -34
  76. package/gsd-core/bin/lib/external-descriptor-trust.cjs +29 -14
  77. package/gsd-core/bin/lib/gsd2-import.cjs +1 -2
  78. package/gsd-core/bin/lib/health-diagnostic-rules/state-consistency.cjs +12 -1
  79. package/gsd-core/bin/lib/health-diagnostic-rules/worktree-health.cjs +1 -1
  80. package/gsd-core/bin/lib/init.cjs +409 -47
  81. package/gsd-core/bin/lib/install-engine.cjs +16 -3
  82. package/gsd-core/bin/lib/install-profiles.cjs +14 -0
  83. package/gsd-core/bin/lib/installer-migrations.cjs +33 -4
  84. package/gsd-core/bin/lib/loop-resolver.cjs +50 -31
  85. package/gsd-core/bin/lib/mcp-catalog.cjs +2 -2
  86. package/gsd-core/bin/lib/milestone.cjs +19 -8
  87. package/gsd-core/bin/lib/model-resolver.cjs +101 -10
  88. package/gsd-core/bin/lib/phase-command-router.cjs +7 -1
  89. package/gsd-core/bin/lib/phase-id.cjs +161 -22
  90. package/gsd-core/bin/lib/phase-lifecycle.cjs +61 -0
  91. package/gsd-core/bin/lib/phase.cjs +167 -63
  92. package/gsd-core/bin/lib/planning-inspect.cjs +34 -18
  93. package/gsd-core/bin/lib/planning-snapshot.cjs +61 -12
  94. package/gsd-core/bin/lib/planning-workspace.cjs +50 -1
  95. package/gsd-core/bin/lib/pristine-baseline.cjs +182 -0
  96. package/gsd-core/bin/lib/prohibition-enforcement.cjs +91 -4
  97. package/gsd-core/bin/lib/quick-batch.cjs +1 -1
  98. package/gsd-core/bin/lib/refactor-trigger-command-router.cjs +61 -2
  99. package/gsd-core/bin/lib/research-store.cjs +11 -12
  100. package/gsd-core/bin/lib/review-lane-invocation.cjs +23 -0
  101. package/gsd-core/bin/lib/reviewer-step-dispatch.cjs +337 -0
  102. package/gsd-core/bin/lib/roadmap-parser.cjs +56 -15
  103. package/gsd-core/bin/lib/roadmap.cjs +108 -14
  104. package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +27 -10
  105. package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +12 -3
  106. package/gsd-core/bin/lib/runtime-artifact-layout.cjs +13 -5
  107. package/gsd-core/bin/lib/runtime-hooks-surface.cjs +193 -4
  108. package/gsd-core/bin/lib/security.cjs +126 -7
  109. package/gsd-core/bin/lib/state-document.cjs +130 -28
  110. package/gsd-core/bin/lib/state-md-schema.cjs +21 -14
  111. package/gsd-core/bin/lib/state-transition.cjs +142 -28
  112. package/gsd-core/bin/lib/state.cjs +223 -27
  113. package/gsd-core/bin/lib/surface.cjs +60 -2
  114. package/gsd-core/bin/lib/task-command-router.cjs +12 -6
  115. package/gsd-core/bin/lib/uat.cjs +1 -1
  116. package/gsd-core/bin/lib/update-context.cjs +30 -24
  117. package/gsd-core/bin/lib/vendor/js-yaml.cjs +11 -3
  118. package/gsd-core/bin/lib/verification.cjs +47 -15
  119. package/gsd-core/bin/lib/verify-command-grounding.cjs +1 -1
  120. package/gsd-core/bin/lib/verify.cjs +188 -23
  121. package/gsd-core/bin/lib/workstream-inventory.cjs +1 -0
  122. package/gsd-core/bin/lib/worktree-safety.cjs +13 -7
  123. package/gsd-core/bin/shared/config-defaults.manifest.json +1 -0
  124. package/gsd-core/bin/shared/config-schema.manifest.json +5 -0
  125. package/gsd-core/bin/verify-reapply-patches.cjs +439 -80
  126. package/gsd-core/references/compact-content-gate.md +66 -0
  127. package/gsd-core/references/loop-hook-dispatch.md +18 -0
  128. package/gsd-core/references/model-profiles.md +12 -3
  129. package/gsd-core/references/planning-config.md +3 -0
  130. package/gsd-core/references/tdd.md +5 -2
  131. package/gsd-core/references/thinking-models-planning.md +18 -2
  132. package/gsd-core/references/verification-patterns.md +17 -4
  133. package/gsd-core/references/worktree-path-safety.md +112 -2
  134. package/gsd-core/templates/README.md +7 -1
  135. package/gsd-core/templates/state.md +6 -3
  136. package/gsd-core/templates/summary.compact.md +212 -0
  137. package/gsd-core/templates/user-setup.compact.md +199 -0
  138. package/gsd-core/templates/user-setup.md +0 -9
  139. package/gsd-core/workflows/add-todo.md +3 -2
  140. package/gsd-core/workflows/autonomous.md +13 -10
  141. package/gsd-core/workflows/check-todos.md +4 -2
  142. package/gsd-core/workflows/cleanup.md +3 -1
  143. package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +7 -0
  144. package/gsd-core/workflows/code-review-fix.md +3 -3
  145. package/gsd-core/workflows/code-review.md +156 -30
  146. package/gsd-core/workflows/complete-milestone/detail/elaboration.md +274 -0
  147. package/gsd-core/workflows/complete-milestone.md +39 -262
  148. package/gsd-core/workflows/docs-update/detail/elaboration.md +179 -0
  149. package/gsd-core/workflows/docs-update.md +14 -155
  150. package/gsd-core/workflows/execute-phase/detail/elaboration.md +124 -0
  151. package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +18 -3
  152. package/gsd-core/workflows/execute-phase/steps/completion-reconciliation.md +56 -0
  153. package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +7 -2
  154. package/gsd-core/workflows/execute-phase/steps/executor-progress-policy.md +43 -0
  155. package/gsd-core/workflows/execute-phase/steps/sequential-root-pin.md +35 -0
  156. package/gsd-core/workflows/execute-phase.md +53 -152
  157. package/gsd-core/workflows/execute-plan.md +20 -7
  158. package/gsd-core/workflows/help/modes/full.compact.md +398 -0
  159. package/gsd-core/workflows/help.md +1 -1
  160. package/gsd-core/workflows/map-codebase.md +50 -3
  161. package/gsd-core/workflows/new-milestone.md +54 -12
  162. package/gsd-core/workflows/new-project/detail/elaboration.md +216 -0
  163. package/gsd-core/workflows/new-project.md +32 -202
  164. package/gsd-core/workflows/plan-phase/detail/elaboration.md +209 -0
  165. package/gsd-core/workflows/plan-phase.md +22 -181
  166. package/gsd-core/workflows/pr-branch.md +19 -7
  167. package/gsd-core/workflows/quick.md +8 -1
  168. package/gsd-core/workflows/reapply-patches.md +77 -3
  169. package/gsd-core/workflows/settings.md +18 -5
  170. package/gsd-core/workflows/update.md +7 -5
  171. package/gsd-core/workflows/verify-work/detail/elaboration.md +230 -0
  172. package/gsd-core/workflows/verify-work.md +20 -180
  173. package/hooks/dist/gsd-agent-isolation-guard.js +42 -16
  174. package/hooks/dist/gsd-context-monitor.js +88 -15
  175. package/hooks/dist/gsd-cursor-subagent-start.js +34 -14
  176. package/hooks/dist/gsd-secret-read-guard.js +44 -18
  177. package/hooks/dist/gsd-statusline.js +11 -7
  178. package/hooks/dist/gsd-validate-commit.sh +34 -4
  179. package/hooks/dist/gsd-worktree-path-guard.js +25 -14
  180. package/hooks/dist/gsd-write-guard.js +46 -1
  181. package/hooks/dist/lib/dispatch-identity.js +187 -0
  182. package/hooks/dist/lib/filename-classification.js +64 -0
  183. package/hooks/dist/lib/isolation-deny-reason.js +53 -1
  184. package/hooks/dist/lib/isolation-sentinel.js +58 -19
  185. package/hooks/gsd-agent-isolation-guard.js +42 -16
  186. package/hooks/gsd-context-monitor.js +88 -15
  187. package/hooks/gsd-cursor-subagent-start.js +34 -14
  188. package/hooks/gsd-secret-read-guard.js +44 -18
  189. package/hooks/gsd-statusline.js +11 -7
  190. package/hooks/gsd-validate-commit.sh +34 -4
  191. package/hooks/gsd-worktree-path-guard.js +25 -14
  192. package/hooks/gsd-write-guard.js +46 -1
  193. package/hooks/lib/dispatch-identity.js +187 -0
  194. package/hooks/lib/filename-classification.js +64 -0
  195. package/hooks/lib/isolation-deny-reason.js +53 -1
  196. package/hooks/lib/isolation-sentinel.js +58 -19
  197. package/package.json +10 -6
  198. package/scripts/benchmark-compact-content-variants.cjs +298 -0
  199. package/scripts/benchmark-compact-content.cjs +368 -0
  200. package/scripts/check-contract-drift.cjs +4 -1
  201. package/scripts/check-env.cjs +36 -8
  202. package/scripts/check-glossary-refs.cjs +25 -21
  203. package/scripts/ci-next-health.cjs +271 -0
  204. package/scripts/ci-prepare-test-scope.cjs +7 -7
  205. package/scripts/ci-test-scope.cjs +126 -20
  206. package/scripts/ci-timeout-report.cjs +1 -1
  207. package/scripts/diff-touches-shipped-paths.cjs +1 -1
  208. package/scripts/docs-guard-registry.cjs +7 -2
  209. package/scripts/gen-adr-index.cjs +8 -2
  210. package/scripts/gen-inventory-manifest.cjs +12 -0
  211. package/scripts/gen-platform-conformance-tier.cjs +557 -0
  212. package/scripts/lib/drift-scan.cjs +1 -1
  213. package/scripts/lib/macos-conformance-tier.generated.cjs +210 -0
  214. package/scripts/lib/npm-version-check-diagnosis.cjs +59 -0
  215. package/scripts/lib/platform-conformance-tier.generated.cjs +276 -0
  216. package/scripts/lib/suite-detection.cjs +32 -0
  217. package/scripts/lint-allowed-tools-parity.cjs +221 -0
  218. package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +19 -2
  219. package/scripts/lint-phase-id-drift.cjs +338 -13
  220. package/scripts/lint-response-language-coverage.cjs +9 -3
  221. package/scripts/lint-source-test-name-collision.cjs +1 -1
  222. package/scripts/lint-test-file-count.allowlist.json +1 -0
  223. package/scripts/lint-vendored-deps.cjs +128 -17
  224. package/scripts/lint-workflow-shellcheck-baseline.json +85 -0
  225. package/scripts/prompt-injection-scan.sh +14 -0
  226. package/scripts/workflow-size.cjs +139 -0
  227. package/skills/gsd-cleanup/SKILL.md +1 -0
  228. package/skills/gsd-code-review/SKILL.md +2 -1
  229. package/skills/gsd-complete-milestone/SKILL.md +1 -0
  230. package/skills/gsd-config/SKILL.md +1 -0
  231. package/skills/gsd-debug/SKILL.md +1 -0
  232. package/skills/gsd-graphify/SKILL.md +1 -0
  233. package/skills/gsd-health/SKILL.md +1 -0
  234. package/skills/gsd-mempalace-capture/SKILL.md +1 -0
  235. package/skills/gsd-mempalace-recall/SKILL.md +1 -0
  236. package/skills/gsd-new-milestone/SKILL.md +1 -0
  237. package/skills/gsd-new-project/SKILL.md +1 -0
  238. package/skills/gsd-next/SKILL.md +1 -0
  239. package/skills/gsd-pause-work/SKILL.md +1 -0
  240. package/skills/gsd-phase/SKILL.md +1 -0
  241. package/skills/gsd-pr-branch/SKILL.md +1 -0
  242. package/skills/gsd-resume-work/SKILL.md +1 -0
  243. package/skills/gsd-review-backlog/SKILL.md +1 -0
  244. package/skills/gsd-settings/SKILL.md +2 -1
  245. package/skills/gsd-stats/SKILL.md +1 -0
  246. package/skills/gsd-thread/SKILL.md +1 -0
  247. package/skills/gsd-workspace/SKILL.md +1 -0
  248. package/skills/gsd-workstreams/SKILL.md +1 -0
  249. package/vscode/package.json +1 -1
  250. package/gsd-core/templates/claude-md.md +0 -145
  251. package/gsd-core/templates/codebase/concerns.md +0 -310
  252. package/gsd-core/templates/codebase/conventions.md +0 -307
  253. package/gsd-core/templates/codebase/integrations.md +0 -280
  254. package/gsd-core/templates/codebase/structure.md +0 -285
  255. package/gsd-core/templates/codebase/testing.md +0 -480
  256. package/gsd-core/templates/debug-subagent-prompt.md +0 -91
  257. package/gsd-core/templates/discovery.md +0 -146
@@ -0,0 +1,108 @@
1
+ ---
2
+ name: gsd-user-profiler
3
+ description: Analyzes extracted session messages across 8 behavioral dimensions to produce a scored developer profile with confidence levels and evidence. Spawned by profile orchestration workflows.
4
+ tools: Read
5
+ color: purple
6
+ ---
7
+
8
+ <role>
9
+ GSD user profiler: analyze a developer's session messages to identify behavioral patterns across 8 dimensions. Spawned by the profile orchestration workflow (Phase 3) or by write-profile during standalone profiling.
10
+
11
+ Apply the heuristics in the user-profiling reference doc to score each dimension with evidence and confidence; return structured JSON.
12
+
13
+ CRITICAL: apply the reference doc's rubric exactly — it is the single source of truth. Do not invent dimensions, scoring rules, or patterns beyond what it specifies.
14
+
15
+ **CRITICAL: Mandatory Initial Read** — if the prompt contains a `<required_reading>` block, Read every listed file before any other action.
16
+ </role>
17
+
18
+ <input>
19
+ You receive extracted session messages as JSONL content (profile-sample output). Each message:
20
+ ```json
21
+ {
22
+ "sessionId": "string",
23
+ "projectPath": "encoded-path-string",
24
+ "projectName": "human-readable-project-name",
25
+ "timestamp": "ISO-8601",
26
+ "content": "message text (max 500 chars for profiling)"
27
+ }
28
+ ```
29
+ Characteristics: already filtered to genuine user messages (no system/tool/Claude-response noise); each truncated to 500 chars; project-proportionally sampled (no single project dominates); recency-weighted during sampling; typically 100-150 messages across all projects.
30
+ </input>
31
+
32
+ <reference>
33
+ @~/.claude/gsd-core/references/user-profiling.md
34
+
35
+ Detection heuristics rubric — read in full before analyzing. Defines: the 8 dimensions and rating spectrums, signal patterns, detection heuristics, confidence scoring thresholds, evidence curation rules, output schema.
36
+ </reference>
37
+
38
+ <process>
39
+
40
+ <step name="load_rubric">
41
+ Read `~/.claude/gsd-core/references/user-profiling.md` to load: all 8 dimension definitions + rating spectrums; signal patterns/heuristics per dimension; confidence thresholds (HIGH: 10+ signals across 2+ projects, MEDIUM: 5-9, LOW: <5, UNSCORED: 0); evidence curation rules (Signal+Example format, 3 quotes/dimension, ~100 char quotes); sensitive-content exclusions; recency weighting; output schema.
42
+ </step>
43
+
44
+ <step name="read_messages">
45
+ Read all provided messages. While reading: group by project (cross-project consistency), note timestamps (recency), flag log pastes/context dumps/large code blocks (deprioritize as evidence), count total genuine messages for threshold mode (full >50, hybrid 20-50, insufficient <20).
46
+ </step>
47
+
48
+ <step name="analyze_dimensions">
49
+ For each of the 8 dimensions:
50
+
51
+ 1. **Scan for signal patterns** from the reference doc's per-dimension list. Count occurrences.
52
+ 2. **Count evidence signals** — messages containing dimension-relevant signals. Recency weighting: signals from the last 30 days count ~3x.
53
+ 3. **Select up to 3 evidence quotes**: format **Signal:** [interpretation] / **Example:** "[~100 char quote]" — project: [name]. Prefer quotes from different projects, recent over older, natural language over log/context dumps. Check each candidate against sensitive-content patterns (Layer 1) before selecting.
54
+ 4. **Assess cross-project consistency** — same rating across 2+ projects → `cross_project_consistent: true`; varies by project → `false`, describe the split in summary.
55
+ 5. **Apply confidence scoring**: HIGH = 10+ weighted signals across 2+ projects; MEDIUM = 5-9 signals OR consistent within 1 project only; LOW = <5 signals OR mixed/contradictory; UNSCORED = 0 relevant signals.
56
+ 6. **Write summary** — 1-2 sentences on the observed pattern, with context-dependent notes if applicable.
57
+ 7. **Write claude_instruction** — an imperative directive for Claude to follow, e.g. "Provide concise explanations with code" not "You tend to prefer brief explanations." For LOW confidence: add a hedging instruction ("Try X — ask if this matches their preference"). For UNSCORED: neutral fallback ("No strong preference detected. Ask the developer when this dimension is relevant.").
58
+ </step>
59
+
60
+ <step name="filter_sensitive">
61
+ After selecting all quotes, final pass for sensitive patterns: `sk-` (API key prefixes), `Bearer ` (auth headers), `password`, `secret`, `token` (as credential value, not concept), `api_key`/`API_KEY`, full absolute paths containing usernames (`/Users/john/`, `/home/john/`).
62
+
63
+ If a selected quote matches: replace with the next-best clean quote; if none exists, reduce that dimension's evidence count; record the exclusion in `sensitive_excluded`.
64
+ </step>
65
+
66
+ <step name="assemble_output">
67
+ Build the analysis JSON matching the reference doc's Output Schema exactly. Verify before returning:
68
+ - All 8 dimensions present, each with all required fields (rating, confidence, evidence_count, cross_project_consistent, evidence_quotes, summary, claude_instruction)
69
+ - Rating values match defined spectrums (no invented ratings)
70
+ - Confidence is one of HIGH/MEDIUM/LOW/UNSCORED
71
+ - claude_instruction fields are imperative directives, not descriptions
72
+ - `sensitive_excluded` populated (empty array if nothing excluded)
73
+ - `message_threshold` reflects the actual message count
74
+
75
+ Wrap the JSON in `<analysis>` tags.
76
+ </step>
77
+
78
+ </process>
79
+
80
+ <output>
81
+ Return the complete analysis JSON wrapped in `<analysis>` tags:
82
+ ```
83
+ <analysis>
84
+ {
85
+ "profile_version": "1.0",
86
+ "analyzed_at": "...",
87
+ ...full JSON matching reference doc schema...
88
+ }
89
+ </analysis>
90
+ ```
91
+
92
+ If data is insufficient for all dimensions, still return the full schema with UNSCORED dimensions noting "insufficient data" and neutral fallback claude_instructions.
93
+
94
+ Do NOT return markdown commentary, explanations, or caveats outside the `<analysis>` tags — the orchestrator parses them programmatically.
95
+ </output>
96
+
97
+ <constraints>
98
+ - Never select quotes containing sensitive patterns (sk-, Bearer, password, secret, token-as-credential, api_key, full paths with usernames)
99
+ - Never invent evidence or fabricate quotes — every quote must come from actual session messages
100
+ - Never rate a dimension HIGH without 10+ weighted signals across 2+ projects
101
+ - Never invent dimensions beyond the 8 defined in the reference document
102
+ - Weight recent messages (last 30 days) ~3x per reference doc guidelines
103
+ - Report context-dependent splits rather than forcing one rating when signals contradict across projects
104
+ - claude_instruction fields must be imperative directives, not descriptions — the profile is an instruction document for Claude's own consumption
105
+ - Deprioritize log pastes, session context dumps, and large code blocks as evidence
106
+ - When evidence is genuinely insufficient, report UNSCORED with "insufficient data" — do not guess
107
+ </constraints>
108
+ </output>
package/bin/install.js CHANGED
@@ -436,7 +436,7 @@ const GSD_CHANGESET_FILES = [
436
436
  'github-release-notes.cjs', 'lint.cjs', 'new.cjs',
437
437
  'README.md', // documentation only — not user-authored
438
438
  ];
439
- const GSD_SCRIPTS_LIB_FILES = ['cli-exit.cjs', 'allowlist-ratchet.cjs', 'drift-scan.cjs', 'alias-drift-families.cjs', 'exit-code-registry.cjs', 'ndjson-reporter.cjs', 'ci-job-timing.cjs', 'shellcheck-fetch.cjs'];
439
+ const GSD_SCRIPTS_LIB_FILES = ['cli-exit.cjs', 'allowlist-ratchet.cjs', 'drift-scan.cjs', 'alias-drift-families.cjs', 'exit-code-registry.cjs', 'ndjson-reporter.cjs', 'ci-job-timing.cjs', 'shellcheck-fetch.cjs', 'npm-version-check-diagnosis.cjs', 'platform-conformance-tier.generated.cjs', 'suite-detection.cjs', 'macos-conformance-tier.generated.cjs'];
440
440
 
441
441
  /**
442
442
  * Resolve a runtime's shared-hooks directory name from its descriptor.
@@ -544,6 +544,13 @@ const {
544
544
  RUNTIME_PROFILE_MAP: GSD_RUNTIME_PROFILE_MAP,
545
545
  isAnthropicFlavoredModel: gsdIsAnthropicFlavoredModel,
546
546
  } = require(path.join(_gsdLibDir, 'model-catalog.cjs'));
547
+ // #4145: shared hash-first recovery for gsd-pristine/ baselines stored at an
548
+ // unexpected path (e.g. without the gsd-core/ prefix an earlier release's
549
+ // writer dropped). Same module the reapply verifier uses, so the two readers
550
+ // cannot drift apart again.
551
+ const {
552
+ findPristineByHash: gsdFindPristineByHash,
553
+ } = require(path.join(_gsdLibDir, 'pristine-baseline.cjs'));
547
554
  // #2875 Part 2: MODEL_PROFILES + resolveTierEntry are now consumed only by
548
555
  // install-model-override-resolver.cjs's readGsdRuntimeProfileResolver
549
556
  // (required below) — this installer no longer needs its own bindings.
@@ -1285,6 +1292,7 @@ const removeKimiHooksToml = hooksSurface.removeKimiHooksToml;
1285
1292
  // callers continue to work and there is a single implementation. (All call
1286
1293
  // sites are below this line, so the const binding has no TDZ hazard.)
1287
1294
  const processAttribution = runtimeArtifactConversion.processAttribution;
1295
+ const filterRuntimeNotesForTarget = runtimeArtifactConversion.filterRuntimeNotesForTarget;
1288
1296
  // computePathPrefix: implementation lives in runtimeArtifactConversion
1289
1297
  // (ADR-1508 / #1511 Phase 2 — single owner). Re-bound here so install.js call
1290
1298
  // sites continue to work. #2876 retired the sibling
@@ -1362,34 +1370,13 @@ function ensureCodexHooksJsonSessionStart(targetDir, opts = {}) {
1362
1370
  }
1363
1371
 
1364
1372
  /**
1365
- * Ensure hooks.json contains exactly one managed GSD hook entry for the given
1366
- * Codex event, wired to gsd-context-monitor.js. Preserves user-owned entries.
1367
- *
1368
- * Used for the new Codex events added in #772:
1369
- * SubagentStart — inject context / GSD_AGENT_NAME awareness at subagent open
1370
- * Stop — post-session context headroom tracking
1371
- * PostToolUse — mirror the Claude Code PostToolUse context monitor
1372
- *
1373
- * All three events are routed through gsd-context-monitor.js — the same hook
1374
- * used for PostToolUse in the Claude Code baseline — so context-headroom
1375
- * warnings surface at these key Codex session lifecycle moments.
1376
- *
1377
- * On Windows (#3426): writes a gsd-context-monitor.cmd shim alongside the .js
1378
- * file and uses the .cmd path as the hook command — exactly the same fix as
1379
- * SessionStart uses for gsd-check-update — to avoid the bash.exe POSIX-exec
1380
- * failure when Codex's hook dispatcher tries to run node.exe through Git Bash.
1381
- *
1382
- * @param {string} targetDir
1383
- * @param {string} eventName - One of 'SubagentStart', 'Stop', 'PostToolUse'.
1384
- * @param {{ absoluteRunner: string|null, platform?: NodeJS.Platform }} opts
1385
- * @returns {{ changed: boolean, wrote: boolean, path: string }}
1386
- */
1387
- function ensureCodexHooksJsonEvent(targetDir, eventName, opts = {}) {
1388
- return hooksSurface.ensureCodexHooksJsonEvent(targetDir, eventName, opts);
1389
- }
1390
-
1391
- /**
1392
- * Remove a GSD-managed event entry from hooks.json. Called during uninstall.
1373
+ * Remove a GSD-managed event entry from hooks.json. Called during uninstall,
1374
+ * and (#2586) unconditionally during install/reinstall to clean up a
1375
+ * pre-#2586 install's stale gsd-context-monitor.js registrations — GSD no
1376
+ * longer ADDS entries for these events (see CODEX_HOOKS_TO_COPY /
1377
+ * cleanupOrphanedCodexContextMonitorScript in bin/install.js's Codex branch),
1378
+ * only removes recognized ones, so the `ensureCodexHooksJsonEvent` wrapper
1379
+ * that used to add them was removed as dead code.
1393
1380
  *
1394
1381
  * @param {string} targetDir
1395
1382
  * @param {string} eventName
@@ -2429,7 +2416,7 @@ function convertClaudeAgentToCopilotAgent(content, isGlobal = false) {
2429
2416
  * @param {boolean} [isGlobal=false] - Whether this is a global install
2430
2417
  */
2431
2418
  function convertClaudeToAntigravityContent(content, isGlobal = false) {
2432
- let c = content;
2419
+ let c = filterRuntimeNotesForTarget(content, 'antigravity');
2433
2420
  if (isGlobal) {
2434
2421
  // #3738: global skills install under ~/.gemini/config/skills (the dir AGY
2435
2422
  // scans for global discovery), so skills-path references must divert there
@@ -2565,7 +2552,7 @@ function convertSlashCommandsToCursorSkillMentions(content) {
2565
2552
  }
2566
2553
 
2567
2554
  function convertClaudeToCursorMarkdown(content) {
2568
- let converted = convertSlashCommandsToCursorSkillMentions(content);
2555
+ let converted = convertSlashCommandsToCursorSkillMentions(filterRuntimeNotesForTarget(content, 'cursor'));
2569
2556
  // Replace tool name references in body text
2570
2557
  converted = converted.replace(/\bBash\(/g, 'Shell(');
2571
2558
  converted = converted.replace(/\bEdit\(/g, 'StrReplace(');
@@ -2686,7 +2673,7 @@ function convertSlashCommandsToTraeSkillMentions(content) {
2686
2673
  }
2687
2674
 
2688
2675
  function convertClaudeToTraeMarkdown(content) {
2689
- let converted = convertSlashCommandsToTraeSkillMentions(content);
2676
+ let converted = convertSlashCommandsToTraeSkillMentions(filterRuntimeNotesForTarget(content, 'trae'));
2690
2677
  converted = converted.replace(/\bBash\(/g, 'Shell(');
2691
2678
  converted = converted.replace(/\bEdit\(/g, 'StrReplace(');
2692
2679
  // Replace general-purpose subagent type with Trae's equivalent "general_purpose_task"
@@ -2812,7 +2799,7 @@ function convertSlashCommandsToCodebuddySkillMentions(content) {
2812
2799
  }
2813
2800
 
2814
2801
  function convertClaudeToCodebuddyMarkdown(content) {
2815
- let converted = convertSlashCommandsToCodebuddySkillMentions(content);
2802
+ let converted = convertSlashCommandsToCodebuddySkillMentions(filterRuntimeNotesForTarget(content, 'codebuddy'));
2816
2803
  // CodeBuddy uses the same tool names as Claude Code (Bash, Edit, Read, Write, etc.)
2817
2804
  // No tool name conversion needed
2818
2805
  converted = converted.replace(/\$ARGUMENTS\b/g, '{{GSD_ARGS}}');
@@ -2904,7 +2891,7 @@ function convertClaudeAgentToCodebuddyAgent(content) {
2904
2891
  // ── Cline converters ────────────────────────────────────────────────────────
2905
2892
 
2906
2893
  function convertClaudeToCliineMarkdown(content) {
2907
- let converted = content;
2894
+ let converted = filterRuntimeNotesForTarget(content, 'cline');
2908
2895
  // Cline uses the same tool names as Claude Code — no tool name conversion needed
2909
2896
  converted = converted.replace(/`\.\/CLAUDE\.md`/g, '`.clinerules`');
2910
2897
  converted = converted.replace(/\.\/CLAUDE\.md/g, '.clinerules');
@@ -3827,7 +3814,7 @@ function rewriteBareGsdToolsCommandsForCodex(content) {
3827
3814
  }
3828
3815
 
3829
3816
  function convertClaudeToCodexMarkdown(content) {
3830
- let converted = convertSlashCommandsToCodexSkillMentions(content);
3817
+ let converted = convertSlashCommandsToCodexSkillMentions(filterRuntimeNotesForTarget(content, 'codex'));
3831
3818
  converted = converted.replace(/\$ARGUMENTS\b/g, '{{GSD_ARGS}}');
3832
3819
  // Remove /clear references — Codex has no equivalent command
3833
3820
  // Handle backtick-wrapped: `\/clear` then: → (removed)
@@ -7208,7 +7195,7 @@ function neutralizeAgentReferences(content, instructionFile) {
7208
7195
 
7209
7196
  function convertClaudeToOpencodeFrontmatter(content, { isAgent = false, modelOverride = null } = {}) {
7210
7197
  // Replace tool name references in content (applies to all files)
7211
- let convertedContent = content;
7198
+ let convertedContent = filterRuntimeNotesForTarget(content, 'opencode');
7212
7199
  convertedContent = convertedContent.replace(/\bAskUserQuestion\b/g, 'question');
7213
7200
  convertedContent = convertedContent.replace(/\bSlashCommand\b/g, 'skill');
7214
7201
  convertedContent = convertedContent.replace(/\bTodoWrite\b/g, 'todowrite');
@@ -7370,7 +7357,7 @@ function convertClaudeToOpencodeFrontmatter(content, { isAgent = false, modelOve
7370
7357
  // tests/runtime-converters.test.cjs (#2093).
7371
7358
  function convertClaudeToKiloFrontmatter(content, { isAgent = false, modelOverride = null } = {}) {
7372
7359
  // Replace tool name references in content (applies to all files)
7373
- let convertedContent = content;
7360
+ let convertedContent = filterRuntimeNotesForTarget(content, 'kilo');
7374
7361
  convertedContent = convertedContent.replace(/\bAskUserQuestion\b/g, 'question');
7375
7362
  convertedContent = convertedContent.replace(/\bSlashCommand\b/g, 'skill');
7376
7363
  convertedContent = convertedContent.replace(/\bTodoWrite\b/g, 'todowrite');
@@ -7924,6 +7911,8 @@ function copyWithPathReplacement(srcDir, destDir, pathPrefix, runtime, isCommand
7924
7911
  content = composeWorkflow(content, { sourcePath: srcPath });
7925
7912
  }
7926
7913
 
7914
+ content = filterRuntimeNotesForTarget(content, runtime);
7915
+
7927
7916
  if (!dispatch.mdSkipGenericRewrite) {
7928
7917
  const globalClaudeRegex = /~\/\.claude\//g;
7929
7918
  const globalClaudeHomeRegex = /\$HOME\/\.claude\//g;
@@ -8478,6 +8467,16 @@ function uninstall(isGlobal, runtime = DEFAULT_RUNTIME) {
8478
8467
  console.log(` ${green}✓${reset} Removed managed Codex ${eventName} hook from hooks.json`);
8479
8468
  }
8480
8469
  }
8470
+ // #2586: uninstall's own symmetric half of the orphaned-script cleanup —
8471
+ // same GSD-owned + unreferenced gate as the install-time call.
8472
+ const uninstallMonitorCleanup = hooksSurface.cleanupOrphanedCodexContextMonitorScript(targetDir);
8473
+ for (const deletedPath of uninstallMonitorCleanup.deleted) {
8474
+ removedCount++;
8475
+ console.log(` ${green}✓${reset} Removed orphaned Codex hook script (${path.basename(deletedPath)})`);
8476
+ }
8477
+ for (const warning of uninstallMonitorCleanup.warnings) {
8478
+ console.warn(` ${yellow}⚠${reset} Could not remove orphaned Codex hook script ${warning.path}: ${warning.reason}`);
8479
+ }
8481
8480
  }
8482
8481
 
8483
8482
  // 1a-kimi. Non-layout Kimi side-effect (#2095 EoS/kimi Upgrade 1): kimi's
@@ -10153,6 +10152,86 @@ function populatePristineDir({ packageSrc, pristineDir, modified, runtime, pathP
10153
10152
  return written;
10154
10153
  }
10155
10154
 
10155
+ /**
10156
+ * #4145: recover a pristine baseline from a hash-matching orphan stored at an
10157
+ * unexpected path under gsd-pristine/ (e.g. without the gsd-core/ prefix an
10158
+ * earlier release's writer dropped).
10159
+ *
10160
+ * The preserve-check's strict join (pristineDir + manifest-keyed relPath)
10161
+ * misses such snapshots, so they were pushed into regeneration from the
10162
+ * incoming release — and when the file changed upstream, the candidate's hash
10163
+ * could never satisfy the recorded outgoing hash, leaving the correct
10164
+ * baseline permanently unconsumed and unpruned (the self-perpetuating state
10165
+ * #4145 reports). Hash equality with pristine_hashes is the same authority
10166
+ * the #3657 drift guard trusts, so an exact match cannot be the wrong
10167
+ * baseline no matter where under gsd-pristine/ it lives.
10168
+ *
10169
+ * Recovery = relocation: copy the orphan to the canonical manifest-keyed path
10170
+ * (hash-verified after the copy) and remove the orphan only once the
10171
+ * canonical copy is verified in place. Returns true when the canonical path
10172
+ * ended up holding recorded-hash bytes. Never deletes anything it cannot
10173
+ * vouch for by hash, and never consumes a path that is the canonical path of
10174
+ * ANY manifest file (see canonicalSkip below) — only genuine orphans, which
10175
+ * no strict-join reader ever consults, are eligible for removal.
10176
+ */
10177
+ function recoverOrphanedPristine(pristineDir, relPath, recordedHash, canonicalSkip) {
10178
+ if (!recordedHash) return false;
10179
+ let orphanRel;
10180
+ try {
10181
+ // canonicalSkip = the normalized manifest keys: a file already sitting at
10182
+ // any canonical path can never be (re-)adopted through the scan. Without
10183
+ // this, two modified files sharing byte-identical outgoing content would
10184
+ // repeatedly "rescue" each other's canonical away (relocate + delete at
10185
+ // its home path) in alternating updates — bytes identical, state unstable.
10186
+ // It also keeps drift (#3657) / stale (#3407) territory with the caller.
10187
+ orphanRel = gsdFindPristineByHash(pristineDir, recordedHash, canonicalSkip);
10188
+ } catch {
10189
+ return false;
10190
+ }
10191
+ if (!orphanRel) return false;
10192
+ const outRef = resolveInstallRelativePath(pristineDir, relPath);
10193
+ if (!outRef) return false;
10194
+ try {
10195
+ fs.mkdirSync(path.dirname(outRef.fullPath), { recursive: true });
10196
+ fs.copyFileSync(path.join(pristineDir, orphanRel), outRef.fullPath);
10197
+ // Verify the relocated copy before removing the orphan — only a
10198
+ // hash-matching canonical counts as recovered.
10199
+ if (fileHash(outRef.fullPath) !== recordedHash) {
10200
+ try { fs.rmSync(outRef.fullPath, { force: true }); } catch { /* best-effort */ }
10201
+ return false;
10202
+ }
10203
+ // Orphan removal is best-effort: the canonical copy is already verified,
10204
+ // so a failed unlink leaves a harmless duplicate, never data loss.
10205
+ try { fs.rmSync(path.join(pristineDir, orphanRel), { force: true }); } catch { /* best-effort */ }
10206
+ return true;
10207
+ } catch {
10208
+ return false;
10209
+ }
10210
+ }
10211
+
10212
+ /**
10213
+ * #4135: honest N-of-M accounting for gsd-pristine/ baselines after an
10214
+ * update. The #3407 promotion rule keeps only hash-validated candidates
10215
+ * (byte-identical across the version span), so a multi-version update
10216
+ * legitimately ends with near-zero baselines — the collapse itself is NOT a
10217
+ * bug to hide; hiding it is. This renders the covered-of-total line the
10218
+ * update output prints either way, so "1 of 13" can never present like a
10219
+ * fully-covered run. Pure function (typed return) so tests lock the exact
10220
+ * contract without matching console prose.
10221
+ */
10222
+ function describeBaselineCoverage(totalModified, covered) {
10223
+ const total = Math.max(0, totalModified);
10224
+ const have = Math.min(Math.max(0, covered), total);
10225
+ const uncovered = total - have;
10226
+ return {
10227
+ complete: uncovered === 0,
10228
+ uncovered,
10229
+ text: uncovered === 0
10230
+ ? `gsd-pristine/ baselines cover ${have} of ${total} modified file(s)`
10231
+ : `gsd-pristine/ baselines cover ${have} of ${total} modified file(s) — ${uncovered} will be reported no_baseline by the reapply verifier`,
10232
+ };
10233
+ }
10234
+
10156
10235
  /**
10157
10236
  * Detect user-modified GSD files by comparing against install manifest.
10158
10237
  * Backs up modified files to gsd-local-patches/ for reapply after update.
@@ -10299,6 +10378,15 @@ function saveLocalPatches(configDir, pristineCtx) {
10299
10378
  const stalePaths = new Set();
10300
10379
  // Track which relPaths were successfully regenerated (from either missing or stale).
10301
10380
  const regeneratedPaths = new Set();
10381
+ // #4145: track which relPaths were recovered by relocating a hash-matching
10382
+ // orphan (stored at an unexpected path, e.g. without the gsd-core/ prefix).
10383
+ const rescuedPaths = new Set();
10384
+ // #4145: the set of paths that are SOME file's canonical pristine path
10385
+ // (every normalized manifest key). The orphan scan must never consume
10386
+ // these — see recoverOrphanedPristine.
10387
+ const canonicalSkip = new Set(
10388
+ Object.keys(manifest.files || {}).map((k) => normalizeInstallRelativePath(k)).filter(Boolean),
10389
+ );
10302
10390
  const missingPaths = [];
10303
10391
  for (const relPath of modified) {
10304
10392
  const outRef = resolveInstallRelativePath(pristineDir, relPath);
@@ -10320,6 +10408,17 @@ function saveLocalPatches(configDir, pristineCtx) {
10320
10408
  stalePaths.add(relPath);
10321
10409
  }
10322
10410
  }
10411
+ // #4145: canonical absent (or just removed as stale) — before falling
10412
+ // into regeneration, try to recover the baseline from a hash-matching
10413
+ // orphan elsewhere under gsd-pristine/ and relocate it to the canonical
10414
+ // path. This is the self-heal for snapshots an earlier release stored
10415
+ // without the gsd-core/ prefix: without it the state repeats forever
10416
+ // (regeneration candidates from the incoming release can never satisfy
10417
+ // the recorded outgoing hash when upstream changed the file).
10418
+ if (recoverOrphanedPristine(pristineDir, relPath, pristineHashes[relPath], canonicalSkip)) {
10419
+ rescuedPaths.add(relPath);
10420
+ continue;
10421
+ }
10323
10422
  // File absent from gsd-pristine/ (or just removed above as stale):
10324
10423
  // attempt hash-validated regeneration from new-release source.
10325
10424
  missingPaths.push(relPath);
@@ -10362,19 +10461,38 @@ function saveLocalPatches(configDir, pristineCtx) {
10362
10461
  }
10363
10462
  // `regenerated` = total files successfully regenerated (from missing OR stale).
10364
10463
  const regenerated = regeneratedPaths.size;
10464
+ // `rescued` = files recovered by relocating a hash-matching orphan to its
10465
+ // canonical path (#4145) — distinct from preservation (canonical already
10466
+ // correct) and regeneration (bytes re-derived from new-release source).
10467
+ const rescued = rescuedPaths.size;
10365
10468
  // `removed` = stale entries that were deleted and NOT subsequently regenerated.
10366
10469
  // Entries that were stale-deleted but then successfully regenerated are counted
10367
- // only in `regenerated` — the counts are non-overlapping.
10368
- const removed = [...stalePaths].filter(p => !regeneratedPaths.has(p)).length;
10470
+ // only in `regenerated`; stale-deleted-then-orphan-rescued entries are counted
10471
+ // only in `rescued` — the counts are non-overlapping.
10472
+ const removed = [...stalePaths].filter(p => !regeneratedPaths.has(p) && !rescuedPaths.has(p)).length;
10369
10473
  if (preserved > 0) {
10370
10474
  console.log(' ' + green + '✓' + reset + ' Preserved ' + cyan + 'gsd-pristine/' + reset + ' (' + preserved + ' file(s)) for three-way merge');
10371
10475
  }
10476
+ if (rescued > 0) {
10477
+ console.log(' ' + green + '✓' + reset + ' Recovered ' + cyan + 'gsd-pristine/' + reset + ' (' + rescued + ' file(s)) by recorded hash from a legacy-path snapshot and relocated them (#4145)');
10478
+ }
10372
10479
  if (regenerated > 0) {
10373
10480
  console.log(' ' + green + '✓' + reset + ' Regenerated ' + cyan + 'gsd-pristine/' + reset + ' (' + regenerated + ' file(s)) via hash-validated new-release source');
10374
10481
  }
10375
10482
  if (removed > 0) {
10376
10483
  console.log(' ' + yellow + 'i' + reset + ' Removed ' + removed + ' stale gsd-pristine/ snapshot(s); regenerated ' + regenerated + ' of those — falls back to over-broad verify heuristic for the rest');
10377
10484
  }
10485
+ // #4135: the honest N-of-M coverage line. Preserved/rescued/regenerated
10486
+ // are disjoint buckets (see their accounting comments above), so their
10487
+ // sum is exactly the files that ended this update with a hash-valid
10488
+ // baseline. A partial result renders as an info line, not an error:
10489
+ // the collapse is legitimate (#3407), hiding it was the bug.
10490
+ const coverage = describeBaselineCoverage(modified.length, preserved + rescued + regenerated);
10491
+ if (coverage.complete) {
10492
+ console.log(' ' + green + '✓' + reset + ' ' + coverage.text);
10493
+ } else {
10494
+ console.log(' ' + yellow + 'i' + reset + ' ' + coverage.text);
10495
+ }
10378
10496
  }
10379
10497
  }
10380
10498
  return modified;
@@ -12197,11 +12315,17 @@ function install(isGlobal, runtime = DEFAULT_RUNTIME, options = {}) {
12197
12315
  // stageTransitiveHookLibs call after the copy loop. The #3579 boundary is
12198
12316
  // preserved: helpers no staged Codex hook requires (graphify tooling among
12199
12317
  // them) are still not shipped.
12318
+ // #2586: gsd-context-monitor.js is deliberately NOT copied for Codex.
12319
+ // It reads the statusline bridge file (${TMPDIR}/claude-ctx-{session_id}.json)
12320
+ // written only by hooks/gsd-statusline.js, which Codex never installs — so
12321
+ // every registered event was a guaranteed silent no-op (readSentinel throws
12322
+ // ENOENT -> allow(undefined), every invocation, every event, no exceptions).
12323
+ // A pre-#2586 install's stale copy + hooks.json registrations are cleaned
12324
+ // up below (see the CODEX_EXTENDED_HOOK_EVENTS loop), not re-added here.
12200
12325
  const CODEX_HOOKS_TO_COPY = [
12201
12326
  'gsd-check-update.js',
12202
12327
  'gsd-check-update-worker.js',
12203
12328
  'managed-hooks-registry.cjs',
12204
- 'gsd-context-monitor.js',
12205
12329
  ];
12206
12330
  const codexHooksSrc = path.join(src, 'hooks', 'dist');
12207
12331
  if (fs.existsSync(codexHooksSrc)) {
@@ -12403,35 +12527,48 @@ function install(isGlobal, runtime = DEFAULT_RUNTIME, options = {}) {
12403
12527
  }
12404
12528
  }
12405
12529
 
12406
- // ── Codex extended hook events (#772, #2088) ─────────────────────────
12407
- // Codex CLI stabilised a full hook-event set in rust-v0.137.0. GSD
12408
- // registers CODEX_EXTENDED_HOOK_EVENTS (#2088 adds the 6 documented
12409
- // events beyond the original #772 three) — all routed through
12410
- // gsd-context-monitor.js so context-headroom warnings surface at each
12411
- // lifecycle point: SubagentStart/SubagentStop (subagent open/close),
12412
- // Stop (final-response), PreToolUse/PostToolUse (tool boundaries),
12413
- // PermissionRequest (approval prompts), Pre/PostCompact (context
12414
- // compaction), and UserPromptSubmit (per-turn context injection). The
12415
- // context-monitor script decides per-payload what to do; unregistered
12416
- // events simply never fire.
12417
- //
12418
- // Guard: only register when the context-monitor file exists and the node
12419
- // runner is available — same guards as the SessionStart path above.
12420
- const contextMonitorFile = path.join(targetDir, 'hooks', 'gsd-context-monitor.js');
12421
- if (codexNodeRunner && fs.existsSync(contextMonitorFile)) {
12422
- for (const codexEvent of CODEX_EXTENDED_HOOK_EVENTS) {
12423
- const eventWrite = ensureCodexHooksJsonEvent(targetDir, codexEvent, {
12424
- absoluteRunner: codexNodeRunner,
12425
- platform: process.platform,
12426
- });
12427
- if (eventWrite.wrote) {
12428
- console.log(` ${green}✓${reset} Configured Codex hooks (${codexEvent} via hooks.json)`);
12429
- } else if (eventWrite.changed) {
12430
- console.log(` ${green}✓${reset} Verified Codex hooks (${codexEvent} via hooks.json)`);
12431
- }
12530
+ // #2586: Codex's hook payload carries no context/token-usage field
12531
+ // (confirmed against codex-rs/hooks/src/schema.rs), so agent-facing
12532
+ // context warnings and GSD phase/lifecycle display cannot be
12533
+ // supported on this runtime — state that plainly during install
12534
+ // rather than silently omitting the capability. Matches
12535
+ // capabilities/codex/capability.json's hostBehaviors.unsupportedFeatures.
12536
+ console.log(` ${dim}↳${reset} Codex: agent-facing context warnings and GSD phase/lifecycle display are unsupported (Codex's hook payload has no context-usage metric)`);
12537
+
12538
+ // ── Codex extended hook events (#772, #2088) — REMOVED by #2586 ──────
12539
+ // gsd-context-monitor.js is no longer copied or registered for Codex
12540
+ // (see the CODEX_HOOKS_TO_COPY comment above): every one of these
12541
+ // events was a guaranteed silent no-op, since the metrics bridge file
12542
+ // it reads is only ever written by Claude's own statusline hook.
12543
+ // Every event in CODEX_EXTENDED_HOOK_EVENTS is unconditionally
12544
+ // reconciled here — not gated on the script existing — so a
12545
+ // pre-#2586 install's stale registrations (exact current shape, or a
12546
+ // recognized legacy shape via isManagedHookCommand's
12547
+ // includeLegacyAliases) are stripped on reinstall. Mirrors the
12548
+ // unconditional uninstall-time loop over the same constant. A
12549
+ // registration whose command does not match the managed shape (a
12550
+ // hand-customized entry) survives untouched — see
12551
+ // reconcileCodexHooksJsonEvent's isManagedHookCommand filter.
12552
+ for (const codexEvent of CODEX_EXTENDED_HOOK_EVENTS) {
12553
+ const eventCleanup = removeCodexHooksJsonEvent(targetDir, codexEvent);
12554
+ if (eventCleanup.changed) {
12555
+ console.log(` ${green}✓${reset} Removed stale Codex ${codexEvent} context-monitor hook from hooks.json`);
12432
12556
  }
12433
- } else if (!codexNodeRunner) {
12434
- console.warn(` ${yellow}⚠${reset} Skipped Codex extended hook-event registration — Node runner unavailable.`);
12557
+ }
12558
+ // Delete the orphaned script (+ Windows .cmd shim) left by a
12559
+ // pre-#2586 install, but ONLY once no surviving hooks.json
12560
+ // registration under any event still references it, and only when
12561
+ // the on-disk file is GSD's own (see design doc's Ownership check —
12562
+ // a content-signature check, not manifest membership, so this works
12563
+ // on the very first reinstall after upgrading, with no bootstrap
12564
+ // gap). A deletion failure never reverts the (already safe,
12565
+ // already-written) hooks.json cleanup above — must-have #8.
12566
+ const monitorCleanup = hooksSurface.cleanupOrphanedCodexContextMonitorScript(targetDir);
12567
+ for (const deletedPath of monitorCleanup.deleted) {
12568
+ console.log(` ${green}✓${reset} Removed orphaned Codex hook script (${path.basename(deletedPath)})`);
12569
+ }
12570
+ for (const warning of monitorCleanup.warnings) {
12571
+ console.warn(` ${yellow}⚠${reset} Could not remove orphaned Codex hook script ${warning.path}: ${warning.reason}`);
12435
12572
  }
12436
12573
  // ── end Codex extended hook events ────────────────────────────────────
12437
12574
  }
@@ -14117,6 +14254,7 @@ module.exports = {
14117
14254
  reportLocalPatches,
14118
14255
  validateHookFields,
14119
14256
  populatePristineDir,
14257
+ describeBaselineCoverage,
14120
14258
  _resolveUserArtifactStagingRoot,
14121
14259
  _tryResolveUserArtifactStagingRoot,
14122
14260
  finishInstall,
@@ -5,6 +5,7 @@ allowed-tools:
5
5
  - Read
6
6
  - Write
7
7
  - Bash
8
+ - Grep
8
9
  - AskUserQuestion
9
10
  requires: [phase]
10
11
  ---
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: gsd:code-review
3
3
  description: Review source files changed during a phase for bugs, security issues, and code quality problems
4
- argument-hint: "<phase-number> [--depth=quick|standard|deep] [--files file1,file2,...] [--fix [--all] [--auto]]"
4
+ argument-hint: "<phase-number> [--depth=quick|standard|deep] [--files file1,file2,...] [--fix [--all] [--auto]] [reviewer-lane flags]"
5
5
  allowed-tools:
6
6
  - Read
7
7
  - Bash
@@ -26,6 +26,7 @@ Arguments:
26
26
  - `--fix` (optional) — after review completes (or if REVIEW.md already exists), auto-apply fixes found. Spawns gsd-code-fixer agent. Accepts sub-flags:
27
27
  - `--all` — include Info findings in fix scope (default: Critical + Warning only)
28
28
  - `--auto` — enable fix + re-review iteration loop, capped at 3 iterations
29
+ - Optional reviewer-lane flags (#4209) — any flag returned by `gsd_run review-lane flags` (the canonical reviewer-lane roster; e.g. `--codex`, `--agy`) requests that lane independently review the same already-resolved scope alongside the internal `gsd-code-reviewer` agent. Its findings are corroborating evidence only — `gsd-code-reviewer` alone verifies each claim against the actual source and writes REVIEW.md; there is exactly one REVIEW.md schema. No reviewer-lane flag (the default) reviews with only the internal agent, byte-for-byte unchanged from before #4209.
29
30
 
30
31
  Output: {padded_phase}-REVIEW.md in phase directory + inline summary of findings
31
32
  </objective>
@@ -7,6 +7,7 @@ allowed-tools:
7
7
  - Read
8
8
  - Write
9
9
  - Bash
10
+ - Grep
10
11
  requires: [audit-milestone, discuss-phase, execute-phase, new-milestone, phase, plan-phase, stats, update]
11
12
  ---
12
13
 
@@ -6,6 +6,7 @@ allowed-tools:
6
6
  - Read
7
7
  - Write
8
8
  - Bash
9
+ - Grep
9
10
  - AskUserQuestion
10
11
  requires: [code-review, review, settings]
11
12
  ---
@@ -6,6 +6,7 @@ allowed-tools:
6
6
  - Read
7
7
  - Write
8
8
  - Bash
9
+ - Grep
9
10
  - Agent
10
11
  - AskUserQuestion
11
12
  ---
@@ -5,6 +5,7 @@ argument-hint: "[build|query <term>|status|diff]"
5
5
  allowed-tools:
6
6
  - Read
7
7
  - Bash
8
+ - Grep
8
9
  requires: [config, fast, phase, update]
9
10
  ---
10
11
 
@@ -5,6 +5,7 @@ argument-hint: "[--repair] [--context]"
5
5
  allowed-tools:
6
6
  - Read
7
7
  - Bash
8
+ - Grep
8
9
  - Write
9
10
  - AskUserQuestion
10
11
  requires: [thread]
@@ -5,6 +5,7 @@ argument-hint: "[CONTEXT.md|PLAN.md|SUMMARY.md]"
5
5
  allowed-tools:
6
6
  - Read
7
7
  - Bash
8
+ - Grep
8
9
  requires: [config]
9
10
  ---
10
11
 
@@ -6,6 +6,7 @@ allowed-tools:
6
6
  - Read
7
7
  - Write
8
8
  - Bash
9
+ - Grep
9
10
  requires: [config]
10
11
  ---
11
12
 
@@ -6,6 +6,7 @@ allowed-tools:
6
6
  - Read
7
7
  - Write
8
8
  - Bash
9
+ - Grep
9
10
  - Agent
10
11
  - AskUserQuestion
11
12
  requires: [new-project, phase, plan-phase]