@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.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/agents/gsd-advisor-researcher.compact.md +85 -0
- package/agents/gsd-ai-researcher.compact.md +96 -0
- package/agents/gsd-assumptions-analyzer.compact.md +81 -0
- package/agents/gsd-code-fixer.compact.md +458 -0
- package/agents/gsd-code-fixer.md +5 -5
- package/agents/gsd-code-reviewer.compact.md +269 -0
- package/agents/gsd-code-reviewer.md +15 -3
- package/agents/gsd-codebase-mapper.compact.md +760 -0
- package/agents/gsd-debug-session-manager.compact.md +345 -0
- package/agents/gsd-doc-classifier.compact.md +192 -0
- package/agents/gsd-doc-synthesizer.compact.md +200 -0
- package/agents/gsd-doc-verifier.compact.md +143 -0
- package/agents/gsd-doc-writer.compact.md +440 -0
- package/agents/gsd-dom-verifier.compact.md +138 -0
- package/agents/gsd-domain-researcher.compact.md +141 -0
- package/agents/gsd-eval-auditor.compact.md +160 -0
- package/agents/gsd-eval-planner.compact.md +137 -0
- package/agents/gsd-framework-selector.compact.md +82 -0
- package/agents/gsd-integration-checker.compact.md +245 -0
- package/agents/gsd-intel-updater.compact.md +226 -0
- package/agents/gsd-mempalace-curator.compact.md +45 -0
- package/agents/gsd-nyquist-auditor.compact.md +179 -0
- package/agents/gsd-pattern-mapper.compact.md +275 -0
- package/agents/gsd-project-researcher.compact.md +587 -0
- package/agents/gsd-research-synthesizer.compact.md +212 -0
- package/agents/gsd-roadmapper.compact.md +454 -0
- package/agents/gsd-roadmapper.md +13 -0
- package/agents/gsd-security-auditor.compact.md +162 -0
- package/agents/gsd-ui-auditor.compact.md +404 -0
- package/agents/gsd-ui-checker.compact.md +277 -0
- package/agents/gsd-ui-researcher.compact.md +282 -0
- package/agents/gsd-user-profiler.compact.md +108 -0
- package/bin/install.js +206 -68
- package/commands/gsd/cleanup.md +1 -0
- package/commands/gsd/code-review.md +2 -1
- package/commands/gsd/complete-milestone.md +1 -0
- package/commands/gsd/config.md +1 -0
- package/commands/gsd/debug.md +1 -0
- package/commands/gsd/graphify.md +1 -0
- package/commands/gsd/health.md +1 -0
- package/commands/gsd/mempalace-capture.md +1 -0
- package/commands/gsd/mempalace-recall.md +1 -0
- package/commands/gsd/new-milestone.md +1 -0
- package/commands/gsd/new-project.md +1 -0
- package/commands/gsd/next.md +1 -0
- package/commands/gsd/pause-work.md +1 -0
- package/commands/gsd/phase.md +1 -0
- package/commands/gsd/pr-branch.md +1 -0
- package/commands/gsd/resume-work.md +1 -0
- package/commands/gsd/review-backlog.md +1 -0
- package/commands/gsd/settings.md +2 -1
- package/commands/gsd/stats.md +1 -0
- package/commands/gsd/thread.md +1 -0
- package/commands/gsd/workspace.md +1 -0
- package/commands/gsd/workstreams.md +1 -0
- package/gsd-core/bin/check-latest-version.cjs +8 -3
- package/gsd-core/bin/gsd-tools.cjs +338 -125
- package/gsd-core/bin/lib/adr-parser.cjs +1 -1
- package/gsd-core/bin/lib/artifacts.cjs +2 -1
- package/gsd-core/bin/lib/audit.cjs +39 -22
- package/gsd-core/bin/lib/broken-windows.cjs +168 -49
- package/gsd-core/bin/lib/capability-lifecycle.cjs +10 -6
- package/gsd-core/bin/lib/capability-loader.cjs +135 -1
- package/gsd-core/bin/lib/capability-registry.cjs +79 -67
- package/gsd-core/bin/lib/capability-source.cjs +19 -2
- package/gsd-core/bin/lib/capability-validator.cjs +14 -1
- package/gsd-core/bin/lib/check-command-router.cjs +113 -36
- package/gsd-core/bin/lib/code-review-depth.cjs +2 -2
- package/gsd-core/bin/lib/commands.cjs +650 -72
- package/gsd-core/bin/lib/config-loader.cjs +1 -0
- package/gsd-core/bin/lib/config.cjs +153 -38
- package/gsd-core/bin/lib/coverage.cjs +1 -1
- package/gsd-core/bin/lib/decisions.cjs +137 -34
- package/gsd-core/bin/lib/external-descriptor-trust.cjs +29 -14
- package/gsd-core/bin/lib/gsd2-import.cjs +1 -2
- package/gsd-core/bin/lib/health-diagnostic-rules/state-consistency.cjs +12 -1
- package/gsd-core/bin/lib/health-diagnostic-rules/worktree-health.cjs +1 -1
- package/gsd-core/bin/lib/init.cjs +409 -47
- package/gsd-core/bin/lib/install-engine.cjs +16 -3
- package/gsd-core/bin/lib/install-profiles.cjs +14 -0
- package/gsd-core/bin/lib/installer-migrations.cjs +33 -4
- package/gsd-core/bin/lib/loop-resolver.cjs +50 -31
- package/gsd-core/bin/lib/mcp-catalog.cjs +2 -2
- package/gsd-core/bin/lib/milestone.cjs +19 -8
- package/gsd-core/bin/lib/model-resolver.cjs +101 -10
- package/gsd-core/bin/lib/phase-command-router.cjs +7 -1
- package/gsd-core/bin/lib/phase-id.cjs +161 -22
- package/gsd-core/bin/lib/phase-lifecycle.cjs +61 -0
- package/gsd-core/bin/lib/phase.cjs +167 -63
- package/gsd-core/bin/lib/planning-inspect.cjs +34 -18
- package/gsd-core/bin/lib/planning-snapshot.cjs +61 -12
- package/gsd-core/bin/lib/planning-workspace.cjs +50 -1
- package/gsd-core/bin/lib/pristine-baseline.cjs +182 -0
- package/gsd-core/bin/lib/prohibition-enforcement.cjs +91 -4
- package/gsd-core/bin/lib/quick-batch.cjs +1 -1
- package/gsd-core/bin/lib/refactor-trigger-command-router.cjs +61 -2
- package/gsd-core/bin/lib/research-store.cjs +11 -12
- package/gsd-core/bin/lib/review-lane-invocation.cjs +23 -0
- package/gsd-core/bin/lib/reviewer-step-dispatch.cjs +337 -0
- package/gsd-core/bin/lib/roadmap-parser.cjs +56 -15
- package/gsd-core/bin/lib/roadmap.cjs +108 -14
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +27 -10
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +12 -3
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +13 -5
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +193 -4
- package/gsd-core/bin/lib/security.cjs +126 -7
- package/gsd-core/bin/lib/state-document.cjs +130 -28
- package/gsd-core/bin/lib/state-md-schema.cjs +21 -14
- package/gsd-core/bin/lib/state-transition.cjs +142 -28
- package/gsd-core/bin/lib/state.cjs +223 -27
- package/gsd-core/bin/lib/surface.cjs +60 -2
- package/gsd-core/bin/lib/task-command-router.cjs +12 -6
- package/gsd-core/bin/lib/uat.cjs +1 -1
- package/gsd-core/bin/lib/update-context.cjs +30 -24
- package/gsd-core/bin/lib/vendor/js-yaml.cjs +11 -3
- package/gsd-core/bin/lib/verification.cjs +47 -15
- package/gsd-core/bin/lib/verify-command-grounding.cjs +1 -1
- package/gsd-core/bin/lib/verify.cjs +188 -23
- package/gsd-core/bin/lib/workstream-inventory.cjs +1 -0
- package/gsd-core/bin/lib/worktree-safety.cjs +13 -7
- package/gsd-core/bin/shared/config-defaults.manifest.json +1 -0
- package/gsd-core/bin/shared/config-schema.manifest.json +5 -0
- package/gsd-core/bin/verify-reapply-patches.cjs +439 -80
- package/gsd-core/references/compact-content-gate.md +66 -0
- package/gsd-core/references/loop-hook-dispatch.md +18 -0
- package/gsd-core/references/model-profiles.md +12 -3
- package/gsd-core/references/planning-config.md +3 -0
- package/gsd-core/references/tdd.md +5 -2
- package/gsd-core/references/thinking-models-planning.md +18 -2
- package/gsd-core/references/verification-patterns.md +17 -4
- package/gsd-core/references/worktree-path-safety.md +112 -2
- package/gsd-core/templates/README.md +7 -1
- package/gsd-core/templates/state.md +6 -3
- package/gsd-core/templates/summary.compact.md +212 -0
- package/gsd-core/templates/user-setup.compact.md +199 -0
- package/gsd-core/templates/user-setup.md +0 -9
- package/gsd-core/workflows/add-todo.md +3 -2
- package/gsd-core/workflows/autonomous.md +13 -10
- package/gsd-core/workflows/check-todos.md +4 -2
- package/gsd-core/workflows/cleanup.md +3 -1
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +7 -0
- package/gsd-core/workflows/code-review-fix.md +3 -3
- package/gsd-core/workflows/code-review.md +156 -30
- package/gsd-core/workflows/complete-milestone/detail/elaboration.md +274 -0
- package/gsd-core/workflows/complete-milestone.md +39 -262
- package/gsd-core/workflows/docs-update/detail/elaboration.md +179 -0
- package/gsd-core/workflows/docs-update.md +14 -155
- package/gsd-core/workflows/execute-phase/detail/elaboration.md +124 -0
- package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +18 -3
- package/gsd-core/workflows/execute-phase/steps/completion-reconciliation.md +56 -0
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +7 -2
- package/gsd-core/workflows/execute-phase/steps/executor-progress-policy.md +43 -0
- package/gsd-core/workflows/execute-phase/steps/sequential-root-pin.md +35 -0
- package/gsd-core/workflows/execute-phase.md +53 -152
- package/gsd-core/workflows/execute-plan.md +20 -7
- package/gsd-core/workflows/help/modes/full.compact.md +398 -0
- package/gsd-core/workflows/help.md +1 -1
- package/gsd-core/workflows/map-codebase.md +50 -3
- package/gsd-core/workflows/new-milestone.md +54 -12
- package/gsd-core/workflows/new-project/detail/elaboration.md +216 -0
- package/gsd-core/workflows/new-project.md +32 -202
- package/gsd-core/workflows/plan-phase/detail/elaboration.md +209 -0
- package/gsd-core/workflows/plan-phase.md +22 -181
- package/gsd-core/workflows/pr-branch.md +19 -7
- package/gsd-core/workflows/quick.md +8 -1
- package/gsd-core/workflows/reapply-patches.md +77 -3
- package/gsd-core/workflows/settings.md +18 -5
- package/gsd-core/workflows/update.md +7 -5
- package/gsd-core/workflows/verify-work/detail/elaboration.md +230 -0
- package/gsd-core/workflows/verify-work.md +20 -180
- package/hooks/dist/gsd-agent-isolation-guard.js +42 -16
- package/hooks/dist/gsd-context-monitor.js +88 -15
- package/hooks/dist/gsd-cursor-subagent-start.js +34 -14
- package/hooks/dist/gsd-secret-read-guard.js +44 -18
- package/hooks/dist/gsd-statusline.js +11 -7
- package/hooks/dist/gsd-validate-commit.sh +34 -4
- package/hooks/dist/gsd-worktree-path-guard.js +25 -14
- package/hooks/dist/gsd-write-guard.js +46 -1
- package/hooks/dist/lib/dispatch-identity.js +187 -0
- package/hooks/dist/lib/filename-classification.js +64 -0
- package/hooks/dist/lib/isolation-deny-reason.js +53 -1
- package/hooks/dist/lib/isolation-sentinel.js +58 -19
- package/hooks/gsd-agent-isolation-guard.js +42 -16
- package/hooks/gsd-context-monitor.js +88 -15
- package/hooks/gsd-cursor-subagent-start.js +34 -14
- package/hooks/gsd-secret-read-guard.js +44 -18
- package/hooks/gsd-statusline.js +11 -7
- package/hooks/gsd-validate-commit.sh +34 -4
- package/hooks/gsd-worktree-path-guard.js +25 -14
- package/hooks/gsd-write-guard.js +46 -1
- package/hooks/lib/dispatch-identity.js +187 -0
- package/hooks/lib/filename-classification.js +64 -0
- package/hooks/lib/isolation-deny-reason.js +53 -1
- package/hooks/lib/isolation-sentinel.js +58 -19
- package/package.json +10 -6
- package/scripts/benchmark-compact-content-variants.cjs +298 -0
- package/scripts/benchmark-compact-content.cjs +368 -0
- package/scripts/check-contract-drift.cjs +4 -1
- package/scripts/check-env.cjs +36 -8
- package/scripts/check-glossary-refs.cjs +25 -21
- package/scripts/ci-next-health.cjs +271 -0
- package/scripts/ci-prepare-test-scope.cjs +7 -7
- package/scripts/ci-test-scope.cjs +126 -20
- package/scripts/ci-timeout-report.cjs +1 -1
- package/scripts/diff-touches-shipped-paths.cjs +1 -1
- package/scripts/docs-guard-registry.cjs +7 -2
- package/scripts/gen-adr-index.cjs +8 -2
- package/scripts/gen-inventory-manifest.cjs +12 -0
- package/scripts/gen-platform-conformance-tier.cjs +557 -0
- package/scripts/lib/drift-scan.cjs +1 -1
- package/scripts/lib/macos-conformance-tier.generated.cjs +210 -0
- package/scripts/lib/npm-version-check-diagnosis.cjs +59 -0
- package/scripts/lib/platform-conformance-tier.generated.cjs +276 -0
- package/scripts/lib/suite-detection.cjs +32 -0
- package/scripts/lint-allowed-tools-parity.cjs +221 -0
- package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +19 -2
- package/scripts/lint-phase-id-drift.cjs +338 -13
- package/scripts/lint-response-language-coverage.cjs +9 -3
- package/scripts/lint-source-test-name-collision.cjs +1 -1
- package/scripts/lint-test-file-count.allowlist.json +1 -0
- package/scripts/lint-vendored-deps.cjs +128 -17
- package/scripts/lint-workflow-shellcheck-baseline.json +85 -0
- package/scripts/prompt-injection-scan.sh +14 -0
- package/scripts/workflow-size.cjs +139 -0
- package/skills/gsd-cleanup/SKILL.md +1 -0
- package/skills/gsd-code-review/SKILL.md +2 -1
- package/skills/gsd-complete-milestone/SKILL.md +1 -0
- package/skills/gsd-config/SKILL.md +1 -0
- package/skills/gsd-debug/SKILL.md +1 -0
- package/skills/gsd-graphify/SKILL.md +1 -0
- package/skills/gsd-health/SKILL.md +1 -0
- package/skills/gsd-mempalace-capture/SKILL.md +1 -0
- package/skills/gsd-mempalace-recall/SKILL.md +1 -0
- package/skills/gsd-new-milestone/SKILL.md +1 -0
- package/skills/gsd-new-project/SKILL.md +1 -0
- package/skills/gsd-next/SKILL.md +1 -0
- package/skills/gsd-pause-work/SKILL.md +1 -0
- package/skills/gsd-phase/SKILL.md +1 -0
- package/skills/gsd-pr-branch/SKILL.md +1 -0
- package/skills/gsd-resume-work/SKILL.md +1 -0
- package/skills/gsd-review-backlog/SKILL.md +1 -0
- package/skills/gsd-settings/SKILL.md +2 -1
- package/skills/gsd-stats/SKILL.md +1 -0
- package/skills/gsd-thread/SKILL.md +1 -0
- package/skills/gsd-workspace/SKILL.md +1 -0
- package/skills/gsd-workstreams/SKILL.md +1 -0
- package/vscode/package.json +1 -1
- package/gsd-core/templates/claude-md.md +0 -145
- package/gsd-core/templates/codebase/concerns.md +0 -310
- package/gsd-core/templates/codebase/conventions.md +0 -307
- package/gsd-core/templates/codebase/integrations.md +0 -280
- package/gsd-core/templates/codebase/structure.md +0 -285
- package/gsd-core/templates/codebase/testing.md +0 -480
- package/gsd-core/templates/debug-subagent-prompt.md +0 -91
- 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
|
-
*
|
|
1366
|
-
*
|
|
1367
|
-
*
|
|
1368
|
-
*
|
|
1369
|
-
*
|
|
1370
|
-
*
|
|
1371
|
-
*
|
|
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
|
|
10368
|
-
|
|
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
|
-
//
|
|
12407
|
-
//
|
|
12408
|
-
//
|
|
12409
|
-
//
|
|
12410
|
-
//
|
|
12411
|
-
//
|
|
12412
|
-
|
|
12413
|
-
|
|
12414
|
-
//
|
|
12415
|
-
// context-monitor
|
|
12416
|
-
//
|
|
12417
|
-
//
|
|
12418
|
-
//
|
|
12419
|
-
//
|
|
12420
|
-
|
|
12421
|
-
|
|
12422
|
-
|
|
12423
|
-
|
|
12424
|
-
|
|
12425
|
-
|
|
12426
|
-
|
|
12427
|
-
|
|
12428
|
-
|
|
12429
|
-
|
|
12430
|
-
|
|
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
|
-
}
|
|
12434
|
-
|
|
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,
|
package/commands/gsd/cleanup.md
CHANGED
|
@@ -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>
|
package/commands/gsd/config.md
CHANGED
package/commands/gsd/debug.md
CHANGED
package/commands/gsd/graphify.md
CHANGED
package/commands/gsd/health.md
CHANGED