@opengsd/gsd-core 1.10.0 → 1.11.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-debug-session-manager.md +11 -0
- package/agents/gsd-doc-synthesizer.md +2 -4
- package/agents/gsd-executor.md +5 -5
- package/agents/gsd-mempalace-curator.md +5 -2
- package/agents/gsd-phase-researcher.md +20 -1
- package/agents/gsd-plan-checker.md +37 -0
- package/agents/gsd-planner.md +44 -46
- package/agents/gsd-user-profiler.md +3 -0
- package/agents/gsd-verifier.md +12 -3
- package/bin/install.js +841 -971
- package/bin/lib/ui-safety-gate.cjs +2 -0
- package/commands/gsd/code-review.md +1 -1
- package/commands/gsd/execute-phase.md +1 -1
- package/commands/gsd/map-codebase.md +1 -1
- package/commands/gsd/mempalace-capture.md +1 -1
- package/commands/gsd/mempalace-recall.md +1 -1
- package/commands/gsd/new-milestone.md +1 -1
- package/commands/gsd/quick.md +1 -1
- package/commands/gsd/review-backlog.md +2 -1
- package/commands/gsd/verify-work.md +1 -1
- package/gsd-core/bin/gsd-tools.cjs +469 -88
- package/gsd-core/bin/lib/active-workstream-store.cjs +138 -22
- package/gsd-core/bin/lib/agent-install-check.cjs +230 -32
- package/gsd-core/bin/lib/api-coverage.cjs +3 -5
- package/gsd-core/bin/lib/artifacts.cjs +3 -0
- package/gsd-core/bin/lib/assumption-delta.cjs +2 -4
- package/gsd-core/bin/lib/audit-command-router.cjs +9 -2
- package/gsd-core/bin/lib/audit.cjs +876 -240
- package/gsd-core/bin/lib/broken-windows.cjs +1 -1
- package/gsd-core/bin/lib/capability-consent.cjs +149 -15
- package/gsd-core/bin/lib/capability-lifecycle.cjs +45 -0
- package/gsd-core/bin/lib/capability-registry.cjs +575 -101
- package/gsd-core/bin/lib/capability-source.cjs +92 -0
- package/gsd-core/bin/lib/capability-trust.cjs +444 -25
- package/gsd-core/bin/lib/capability-validator.cjs +495 -22
- package/gsd-core/bin/lib/capability-writer.cjs +3 -2
- package/gsd-core/bin/lib/check-command-router.cjs +71 -37
- package/gsd-core/bin/lib/claude-orchestration.cjs +56 -3
- package/gsd-core/bin/lib/codex-agent-toml.cjs +329 -0
- package/gsd-core/bin/lib/command-aliases.cjs +22 -0
- package/gsd-core/bin/lib/command-roster.cjs +44 -1
- package/gsd-core/bin/lib/commands.cjs +651 -86
- package/gsd-core/bin/lib/commonjs-marker.cjs +12 -6
- package/gsd-core/bin/lib/complexity-trigger.cjs +1172 -0
- package/gsd-core/bin/lib/config-loader.cjs +75 -0
- package/gsd-core/bin/lib/config.cjs +10 -1
- package/gsd-core/bin/lib/core-utils.cjs +127 -29
- package/gsd-core/bin/lib/decisions.cjs +23 -0
- package/gsd-core/bin/lib/fallow-runner.cjs +20 -44
- package/gsd-core/bin/lib/frontmatter.cjs +155 -20
- package/gsd-core/bin/lib/gap-checker.cjs +68 -7
- package/gsd-core/bin/lib/git-base-branch.cjs +102 -0
- package/gsd-core/bin/lib/gsd2-import.cjs +10 -1
- package/gsd-core/bin/lib/health-diagnostic-rules/agent-install.cjs +101 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/config-validation.cjs +348 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/consistency.cjs +145 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/install-surface-shadowing.cjs +98 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/milestone-archive-hygiene.cjs +100 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +222 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/roadmap-disk-consistency.cjs +265 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/root-existence.cjs +161 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/state-consistency.cjs +303 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/worktree-health.cjs +173 -0
- package/gsd-core/bin/lib/health-diagnostic-types.cjs +68 -0
- package/gsd-core/bin/lib/health-diagnostic.cjs +431 -0
- package/gsd-core/bin/lib/host-runtime-detection.cjs +134 -0
- package/gsd-core/bin/lib/init.cjs +321 -129
- package/gsd-core/bin/lib/install-effort-resolver.cjs +73 -30
- package/gsd-core/bin/lib/install-engine.cjs +745 -258
- package/gsd-core/bin/lib/install-fs-adapter.cjs +262 -0
- package/gsd-core/bin/lib/install-model-override-resolver.cjs +203 -0
- package/gsd-core/bin/lib/install-profiles.cjs +134 -57
- package/gsd-core/bin/lib/install-scope.cjs +270 -0
- package/gsd-core/bin/lib/install-shadow-report.cjs +385 -0
- package/gsd-core/bin/lib/installed-surface-resolver.cjs +381 -0
- package/gsd-core/bin/lib/installer-migrations.cjs +138 -31
- package/gsd-core/bin/lib/io.cjs +10 -0
- package/gsd-core/bin/lib/markdown-sectionizer.cjs +2 -1
- package/gsd-core/bin/lib/markdown-table.cjs +133 -20
- package/gsd-core/bin/lib/milestone-lock.cjs +248 -0
- package/gsd-core/bin/lib/milestone.cjs +754 -70
- package/gsd-core/bin/lib/model-catalog.cjs +59 -1
- package/gsd-core/bin/lib/model-resolver.cjs +183 -40
- package/gsd-core/bin/lib/normalize-test-command.cjs +1 -1
- package/gsd-core/bin/lib/pattern.cjs +122 -0
- package/gsd-core/bin/lib/phase-estimation.cjs +1 -1
- package/gsd-core/bin/lib/phase-id.cjs +444 -36
- package/gsd-core/bin/lib/phase-lifecycle.cjs +28 -3
- package/gsd-core/bin/lib/phase-locator.cjs +125 -18
- package/gsd-core/bin/lib/phase.cjs +646 -143
- package/gsd-core/bin/lib/plan-dependency-graph.cjs +72 -1
- package/gsd-core/bin/lib/plan-drift-guard.cjs +120 -0
- package/gsd-core/bin/lib/plan-scan.cjs +86 -2
- package/gsd-core/bin/lib/planning-scope.cjs +31 -0
- package/gsd-core/bin/lib/planning-snapshot.cjs +890 -0
- package/gsd-core/bin/lib/planning-workspace.cjs +56 -6
- package/gsd-core/bin/lib/probe-core.cjs +1 -1
- package/gsd-core/bin/lib/profile-output.cjs +1 -1
- package/gsd-core/bin/lib/refactor-trigger-command-router.cjs +740 -0
- package/gsd-core/bin/lib/retired-artifact-cleanup.cjs +11 -6
- package/gsd-core/bin/lib/review-lane-descriptor.cjs +13 -4
- package/gsd-core/bin/lib/review-lane-invocation.cjs +30 -0
- package/gsd-core/bin/lib/review-lane-runner.cjs +421 -66
- package/gsd-core/bin/lib/review-reviewer-selection.cjs +13 -18
- package/gsd-core/bin/lib/roadmap-command-router.cjs +34 -0
- package/gsd-core/bin/lib/roadmap-parser.cjs +943 -184
- package/gsd-core/bin/lib/roadmap-upgrade.cjs +37 -10
- package/gsd-core/bin/lib/roadmap.cjs +385 -94
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +608 -46
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +14 -2
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +426 -55
- package/gsd-core/bin/lib/runtime-config-adapter-registry.cjs +3 -2
- package/gsd-core/bin/lib/runtime-homes.cjs +69 -3
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +115 -3
- package/gsd-core/bin/lib/runtime-name-policy.cjs +3 -1
- package/gsd-core/bin/lib/runtime-slash.cjs +27 -9
- package/gsd-core/bin/lib/security.cjs +104 -5
- package/gsd-core/bin/lib/shell-command-projection.cjs +275 -3
- package/gsd-core/bin/lib/smart-entry.cjs +142 -22
- package/gsd-core/bin/lib/state-command-router.cjs +5 -1
- package/gsd-core/bin/lib/state-document.cjs +152 -8
- package/gsd-core/bin/lib/state-transition.cjs +371 -117
- package/gsd-core/bin/lib/state.cjs +1794 -357
- package/gsd-core/bin/lib/surface.cjs +23 -9
- package/gsd-core/bin/lib/text-lines.cjs +80 -0
- package/gsd-core/bin/lib/token-scanner.cjs +76 -0
- package/gsd-core/bin/lib/uat-predicate.cjs +9 -3
- package/gsd-core/bin/lib/uat.cjs +399 -56
- package/gsd-core/bin/lib/ui-frontend-evidence.cjs +157 -0
- package/gsd-core/bin/lib/ui-safety-gate.cjs +14 -5
- package/gsd-core/bin/lib/unusable-input.cjs +24 -0
- package/gsd-core/bin/lib/update-context.cjs +8 -2
- package/gsd-core/bin/lib/user-artifact-staging.cjs +705 -0
- package/gsd-core/bin/lib/validate.cjs +20 -6
- package/gsd-core/bin/lib/vendor/README.md +37 -0
- package/gsd-core/bin/lib/vendor/re2js.cjs +6480 -0
- package/gsd-core/bin/lib/vendor/re2js.d.cts +938 -0
- package/gsd-core/bin/lib/verification-command-router.cjs +2 -1
- package/gsd-core/bin/lib/verification.cjs +258 -8
- package/gsd-core/bin/lib/verify.cjs +368 -888
- package/gsd-core/bin/lib/workstream-inventory-builder.cjs +53 -32
- package/gsd-core/bin/lib/workstream-inventory.cjs +63 -10
- package/gsd-core/bin/lib/workstream.cjs +2 -2
- package/gsd-core/bin/lib/worktree-safety.cjs +176 -9
- package/gsd-core/bin/shared/config-defaults.manifest.json +1 -0
- package/gsd-core/bin/shared/config-schema.manifest.json +7 -1
- package/gsd-core/references/agent-contracts.md +43 -26
- package/gsd-core/references/checkpoints.md +2 -2
- package/gsd-core/references/context-budget.md +1 -1
- package/gsd-core/references/dispatch-isolation-gate.md +138 -0
- package/gsd-core/references/doc-conflict-engine.md +1 -1
- package/gsd-core/references/execute-mvp-tdd.md +3 -3
- package/gsd-core/references/execute-phase-between-wave-reset.md +6 -2
- package/gsd-core/references/execute-phase-context-guard.md +1 -1
- package/gsd-core/references/execute-phase-response-language.md +1 -1
- package/gsd-core/references/execute-phase-wave-guard.md +6 -2
- package/gsd-core/references/gate-prompts.md +1 -1
- package/gsd-core/references/git-planning-commit.md +2 -1
- package/gsd-core/references/loop-hook-dispatch.md +39 -2
- package/gsd-core/references/model-profiles.md +12 -4
- package/gsd-core/references/mvp-concepts.md +9 -9
- package/gsd-core/references/planner-guidance.md +3 -9
- package/gsd-core/references/planner-preconditions.md +1 -1
- package/gsd-core/references/planner-reviews.md +1 -1
- package/gsd-core/references/planning-config.md +8 -6
- package/gsd-core/references/revision-loop.md +1 -1
- package/gsd-core/references/specless-probe-fallback.md +1 -1
- package/gsd-core/references/universal-anti-patterns.md +3 -3
- package/gsd-core/references/verifier-phase-gates.md +192 -0
- package/gsd-core/references/verify-mvp-mode.md +1 -1
- package/gsd-core/references/workstream-flag.md +22 -6
- package/gsd-core/templates/discussion-log.md +1 -1
- package/gsd-core/templates/phase-prompt.md +2 -4
- package/gsd-core/templates/state.md +4 -4
- package/gsd-core/templates/verification-report.md +9 -1
- package/gsd-core/workflows/ai-integration-phase.md +9 -11
- package/gsd-core/workflows/autonomous.md +1 -1
- package/gsd-core/workflows/cleanup.md +62 -3
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +13 -3
- package/gsd-core/workflows/code-review-fix.md +37 -10
- package/gsd-core/workflows/code-review.md +38 -12
- package/gsd-core/workflows/complete-milestone.md +141 -18
- package/gsd-core/workflows/debug.md +7 -5
- package/gsd-core/workflows/diagnose-issues.md +35 -9
- package/gsd-core/workflows/discuss-phase/modes/chain.md +2 -1
- package/gsd-core/workflows/discuss-phase/modes/default.md +1 -1
- package/gsd-core/workflows/discuss-phase-assumptions.md +2 -1
- package/gsd-core/workflows/edit-phase.md +26 -1
- package/gsd-core/workflows/eval-review.md +3 -5
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +31 -6
- package/gsd-core/workflows/execute-phase/steps/per-plan-executor-routing.md +77 -0
- package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +2 -0
- package/gsd-core/workflows/execute-phase.md +38 -50
- package/gsd-core/workflows/execute-plan.md +36 -4
- package/gsd-core/workflows/explore.md +131 -4
- package/gsd-core/workflows/fast.md +10 -2
- package/gsd-core/workflows/health.md +73 -4
- package/gsd-core/workflows/import.md +4 -4
- package/gsd-core/workflows/ingest-docs.md +5 -5
- package/gsd-core/workflows/mvp-phase.md +6 -3
- package/gsd-core/workflows/new-milestone.md +14 -9
- package/gsd-core/workflows/new-project.md +14 -14
- package/gsd-core/workflows/next.md +12 -0
- package/gsd-core/workflows/plan-phase.md +41 -17
- package/gsd-core/workflows/plan-review-convergence.md +50 -2
- package/gsd-core/workflows/progress.md +34 -6
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +4 -4
- package/gsd-core/workflows/quick/steps/quick-verification.md +27 -6
- package/gsd-core/workflows/quick/steps/research-phase.md +2 -2
- package/gsd-core/workflows/quick.md +35 -15
- package/gsd-core/workflows/review.md +26 -5
- package/gsd-core/workflows/secure-phase.md +1 -1
- package/gsd-core/workflows/session-report.md +2 -1
- package/gsd-core/workflows/settings.md +66 -2
- package/gsd-core/workflows/ship.md +104 -44
- package/gsd-core/workflows/spec-phase.md +30 -12
- package/gsd-core/workflows/sync-skills.md +63 -8
- package/gsd-core/workflows/transition.md +46 -11
- package/gsd-core/workflows/ui-phase.md +5 -5
- package/gsd-core/workflows/ui-review.md +2 -2
- package/gsd-core/workflows/update.md +1 -1
- package/gsd-core/workflows/validate-phase.md +1 -1
- package/gsd-core/workflows/verify-work.md +9 -7
- package/hooks/dist/gsd-agent-isolation-guard.js +103 -14
- package/hooks/dist/gsd-check-update-worker.js +56 -13
- package/hooks/dist/gsd-check-update.js +19 -1
- package/hooks/dist/gsd-cursor-pre-tool.js +0 -3
- package/hooks/dist/gsd-cursor-subagent-start.js +77 -2
- package/hooks/dist/gsd-cursor-subagent-stop.js +3 -2
- package/hooks/dist/gsd-prompt-guard.js +21 -20
- package/hooks/dist/gsd-read-injection-scanner.js +38 -24
- package/hooks/dist/gsd-statusline.js +18 -0
- package/hooks/dist/gsd-update-banner.js +22 -1
- package/hooks/dist/gsd-workflow-guard.js +134 -36
- package/hooks/dist/lib/git-cmd.js +92 -59
- package/hooks/dist/lib/injection-patterns.js +45 -0
- package/hooks/dist/lib/isolation-deny-reason.js +39 -0
- package/hooks/dist/lib/isolation-sentinel.js +9 -0
- package/hooks/gsd-agent-isolation-guard.js +103 -14
- package/hooks/gsd-check-update-worker.js +56 -13
- package/hooks/gsd-check-update.js +19 -1
- package/hooks/gsd-cursor-pre-tool.js +0 -3
- package/hooks/gsd-cursor-subagent-start.js +77 -2
- package/hooks/gsd-cursor-subagent-stop.js +3 -2
- package/hooks/gsd-prompt-guard.js +21 -20
- package/hooks/gsd-read-injection-scanner.js +38 -24
- package/hooks/gsd-statusline.js +18 -0
- package/hooks/gsd-update-banner.js +22 -1
- package/hooks/gsd-workflow-guard.js +134 -36
- package/hooks/lib/git-cmd.js +92 -59
- package/hooks/lib/injection-patterns.js +45 -0
- package/hooks/lib/isolation-deny-reason.js +39 -0
- package/hooks/lib/isolation-sentinel.js +9 -0
- package/package.json +21 -9
- package/pi/gsd.cjs +19 -5
- package/scripts/baselines/planning-prompt-drift-baseline.json +4 -0
- package/scripts/baselines/planning-snapshot-bypass-baseline.json +12 -0
- package/scripts/baselines/unreachable-guard-drift-baseline.json +4 -0
- package/scripts/changeset/lint.cjs +60 -5
- package/scripts/check-alias-drift.cjs +7 -43
- package/scripts/check-contract-drift.cjs +297 -0
- package/scripts/ci-test-scope.cjs +19 -2
- package/scripts/command-contract-helpers.cjs +903 -1
- package/scripts/gen-adr-index.cjs +728 -38
- package/scripts/gen-capability-registry.cjs +3 -15
- package/scripts/gen-context-index.cjs +2 -11
- package/scripts/gen-health-docs.cjs +390 -0
- package/scripts/gen-inventory-manifest.cjs +50 -4
- package/scripts/gen-loop-host-contract.cjs +4 -24
- package/scripts/gen-registry.cjs +3 -14
- package/scripts/lib/alias-drift-families.cjs +46 -0
- package/scripts/lib/drift-scan.cjs +278 -0
- package/scripts/lint-allow-test-rule-refs.allowlist.json +1 -26
- package/scripts/lint-allow-test-rule-refs.effective-ceiling.json +4 -0
- package/scripts/lint-allow-test-rule-refs.unverified-ceiling.json +3 -0
- package/scripts/lint-canary-version-leak.cjs +73 -0
- package/scripts/lint-command-contract.cjs +96 -13
- package/scripts/lint-completion-predicate-drift.cjs +933 -0
- package/scripts/lint-completion-ratio-drift.cjs +214 -0
- package/scripts/lint-default-flip-documentation.cjs +193 -0
- package/scripts/lint-eslint-glob-coverage.allowlist.json +34 -0
- package/scripts/lint-eslint-glob-coverage.cjs +340 -0
- package/scripts/lint-frontmatter-scalar-broad-grep.cjs +237 -0
- package/scripts/lint-health-diagnostic-rule-table.cjs +404 -0
- package/scripts/lint-hooks-runtime-build-seam.cjs +262 -0
- package/scripts/lint-milestone-window-drift.cjs +468 -0
- package/scripts/lint-phase-enumeration-drift.cjs +479 -0
- package/scripts/lint-plan-count-drift.cjs +318 -0
- package/scripts/lint-planning-artifact-writer-drift.cjs +398 -0
- package/scripts/lint-planning-prompt-drift.cjs +434 -0
- package/scripts/lint-planning-snapshot-bypass-drift.cjs +544 -0
- package/scripts/lint-regression-test-names.cjs +15 -13
- package/scripts/lint-removed-but-needed.cjs +320 -0
- package/scripts/lint-state-field-drift.cjs +805 -0
- package/scripts/lint-state-write-path-drift.cjs +1045 -0
- package/scripts/lint-test-file-count.allowlist.json +21 -10
- package/scripts/lint-unreachable-guard-drift.cjs +843 -0
- package/scripts/lint-vendored-deps.cjs +124 -0
- package/scripts/pr-changed-files.cjs +63 -0
- package/scripts/pr-template-policy.cjs +14 -4
- package/scripts/prompt-injection-scan.sh +25 -0
- package/scripts/require-issue-link-policy.cjs +192 -0
- package/scripts/state-write-path-drift-baseline.json +19 -0
- package/scripts/sync-runtime-launcher.cjs +2 -4
- package/skills/gsd-autonomous/SKILL.md +0 -1
- package/skills/gsd-code-review/SKILL.md +1 -1
- package/skills/gsd-execute-phase/SKILL.md +1 -2
- package/skills/gsd-map-codebase/SKILL.md +1 -1
- package/skills/gsd-mempalace-capture/SKILL.md +1 -1
- package/skills/gsd-mempalace-recall/SKILL.md +1 -1
- package/skills/gsd-new-milestone/SKILL.md +1 -1
- package/skills/gsd-next/SKILL.md +0 -1
- package/skills/gsd-plan-phase/SKILL.md +0 -1
- package/skills/gsd-progress/SKILL.md +0 -1
- package/skills/gsd-quick/SKILL.md +1 -1
- package/skills/gsd-review-backlog/SKILL.md +2 -1
- package/skills/gsd-stats/SKILL.md +0 -1
- package/skills/gsd-verify-work/SKILL.md +1 -1
- package/vscode/package.json +1 -1
- package/gsd-core/workflows/discovery-phase.md +0 -298
- package/gsd-core/workflows/plan-milestone-gaps.md +0 -281
- package/gsd-core/workflows/verify-phase.md +0 -574
- package/scripts/affected-tests-lib.cjs +0 -554
- package/scripts/lint-allow-test-rule-refs.cjs +0 -162
- package/scripts/run-affected-tests.cjs +0 -7
- package/scripts/run-tests.cjs +0 -1051
|
@@ -8,7 +8,25 @@ const path = require('path');
|
|
|
8
8
|
const os = require('os');
|
|
9
9
|
const { spawn } = require('child_process');
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
// #3582: gsd-core/bin/lib/package-identity.cjs is a tsc build artifact
|
|
12
|
+
// (ADR-457), gitignored and absent on a raw plugin-marketplace / git-clone
|
|
13
|
+
// install that never ran `npm run build:lib`. This SessionStart hook must
|
|
14
|
+
// DEGRADE (fall back to a generic cache filename) rather than crash session
|
|
15
|
+
// start. gsd-check-update-worker.js — the process this hook spawns — degrades
|
|
16
|
+
// identically and independently, so the shared fallback literal keeps the
|
|
17
|
+
// cache path consistent between writer and reader even in the (rare)
|
|
18
|
+
// doubly-degraded case. This try/require/ensureRuntimeBuild/require/catch
|
|
19
|
+
// shape is deliberately duplicated (not extracted to hooks/lib/) — see
|
|
20
|
+
// gsd-check-update-worker.js's identical #3582 comment for why.
|
|
21
|
+
let updateCacheFileName = 'gsd-update-check.json';
|
|
22
|
+
try {
|
|
23
|
+
const { ensureRuntimeBuild } = require('../gsd-core/bin/ensure-runtime-build.cjs');
|
|
24
|
+
ensureRuntimeBuild();
|
|
25
|
+
({ updateCacheFileName } = require('../gsd-core/bin/lib/package-identity.cjs'));
|
|
26
|
+
} catch (e) {
|
|
27
|
+
// Runtime library missing/broken and could not self-build — degrade to the
|
|
28
|
+
// fallback filename above rather than crash the SessionStart hook.
|
|
29
|
+
}
|
|
12
30
|
|
|
13
31
|
const homeDir = os.homedir();
|
|
14
32
|
const cwd = process.cwd();
|
|
@@ -22,9 +22,6 @@
|
|
|
22
22
|
|
|
23
23
|
'use strict';
|
|
24
24
|
|
|
25
|
-
const fs = require('fs');
|
|
26
|
-
const path = require('path');
|
|
27
|
-
|
|
28
25
|
const WRITE_TOOL_RE = /write|edit|replace|create|delete|remove|append|apply|patch|insert|mkdir/i;
|
|
29
26
|
const PATH_KEY_RE = /^(path|file|file_?path|filepath|target_?path|target|dir|directory|uri|filename)$/i;
|
|
30
27
|
const PLANNING_PATH_RE = /(^|[\\/])\.planning([\\/]|$)/;
|
|
@@ -62,6 +62,15 @@ const os = require('os');
|
|
|
62
62
|
// writeCursorHooksJson so the require always resolves post-install.
|
|
63
63
|
const { resolveStatePath } = require('./lib/cursor-workspace.js');
|
|
64
64
|
const { readSentinel, VALID_ISOLATION, extractDispatchIdentifiers, sentinelAppliesToDispatch } = require('./lib/isolation-sentinel.js');
|
|
65
|
+
const { REASON_CODE } = require('./lib/isolation-deny-reason.js');
|
|
66
|
+
// #3582: gsd-core/bin/lib/*.cjs (runtime-homes.cjs, worktree-safety.cjs,
|
|
67
|
+
// runtime-name-policy.cjs, capability-registry.cjs — required below, inside
|
|
68
|
+
// resolveIsolationEvidence and resolveFallbackIsolation) are tsc build
|
|
69
|
+
// artifacts (ADR-457), gitignored and absent on a raw plugin-marketplace /
|
|
70
|
+
// git-clone install that never ran `npm run build:lib`. Self-heal once, in
|
|
71
|
+
// evaluateRootIsolation, before any of those four requires run — see the
|
|
72
|
+
// call site below. This module itself depends on nothing under ./lib.
|
|
73
|
+
const { ensureRuntimeBuild, RuntimeBuildError } = require('../gsd-core/bin/ensure-runtime-build.cjs');
|
|
65
74
|
|
|
66
75
|
const MSG_PRESENT =
|
|
67
76
|
'GSD: Subagent session started — review .planning/STATE.md for the current phase and any blockers before acting.';
|
|
@@ -333,6 +342,37 @@ function resolveIsolationDecision(data, { clock = Date, realpath = fs.realpathSy
|
|
|
333
342
|
return { action: 'allow' };
|
|
334
343
|
}
|
|
335
344
|
|
|
345
|
+
// ─── #3566: per-install runtime marker ────────────────────────────────────────
|
|
346
|
+
// Same contract as hooks/gsd-agent-isolation-guard.js's readInstallRuntimeMarker
|
|
347
|
+
// (mirroring src/model-resolver.cts #2297): bin/install.js writes
|
|
348
|
+
// `<install>/gsd-core/.gsd-runtime` beside VERSION for every runtime install;
|
|
349
|
+
// this hook ships at `<install>/hooks/`, so the marker is the `gsd-core` sibling
|
|
350
|
+
// of this file's own directory — the same sibling-layout assumption the
|
|
351
|
+
// require('../gsd-core/bin/lib/…') calls below already make. Epic #3473 B3 owns
|
|
352
|
+
// consolidating every marker reader into one shared seam.
|
|
353
|
+
let _installMarkerCache; // undefined = unread; null = known absent; string = value
|
|
354
|
+
|
|
355
|
+
function readInstallRuntimeMarker() {
|
|
356
|
+
if (_installMarkerCache !== undefined) return _installMarkerCache;
|
|
357
|
+
try {
|
|
358
|
+
const markerPath = path.join(__dirname, '..', 'gsd-core', '.gsd-runtime');
|
|
359
|
+
const raw = fs.readFileSync(markerPath, 'utf-8').trim();
|
|
360
|
+
_installMarkerCache = raw || null;
|
|
361
|
+
} catch {
|
|
362
|
+
// No marker: dev/source tree, or an install predating #2297 — "no signal
|
|
363
|
+
// from this rung", never a resolution failure.
|
|
364
|
+
_installMarkerCache = null;
|
|
365
|
+
}
|
|
366
|
+
return _installMarkerCache;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// Test seam — same contract as model-resolver.cts's #2297 seam; the dev/source
|
|
370
|
+
// tree has no marker file, so spawned-hook tests (fresh process, no marker)
|
|
371
|
+
// are unaffected.
|
|
372
|
+
function _setInstallRuntimeMarkerForTests(value) {
|
|
373
|
+
_installMarkerCache = value;
|
|
374
|
+
}
|
|
375
|
+
|
|
336
376
|
/**
|
|
337
377
|
* Conservative fallback resolution used when the #3045 sentinel is absent or
|
|
338
378
|
* stale for `root`: re-derive isolation from the registry CAPABILITY, gated
|
|
@@ -355,7 +395,8 @@ function resolveIsolationDecision(data, { clock = Date, realpath = fs.realpathSy
|
|
|
355
395
|
* otherwise legitimate dispatches, unlike `hooks/gsd-agent-isolation-guard.js`,
|
|
356
396
|
* which degrades an undeterminable runtime to inert (#3045 MAJOR 2). Aligned
|
|
357
397
|
* here: an explicit signal is now required — `GSD_RUNTIME` > config.json
|
|
358
|
-
* `runtime` key >
|
|
398
|
+
* `runtime` key > the per-install `.gsd-runtime` marker (#3566) >
|
|
399
|
+
* `~/.gsd/defaults.json` `runtime` (mirrors the Claude hook's
|
|
359
400
|
* `resolveRuntimeIdentity`; `bin/install.js`'s `writeNonClaudeDefaults`
|
|
360
401
|
* persists the installed runtime there for every non-Claude install,
|
|
361
402
|
* including Cursor, so a REAL Cursor+GSD install still resolves confidently
|
|
@@ -372,6 +413,13 @@ function resolveFallbackIsolation(root, configPath) {
|
|
|
372
413
|
if (!runtimeId && parsedConfig && typeof parsedConfig === 'object' && 'runtime' in parsedConfig) {
|
|
373
414
|
runtimeId = resolveRuntimeNameFromCandidates(parsedConfig.runtime) || null;
|
|
374
415
|
}
|
|
416
|
+
if (!runtimeId) {
|
|
417
|
+
// #3566: the per-install marker, above the host-wide defaults — same fix as
|
|
418
|
+
// hooks/gsd-agent-isolation-guard.js's resolveRuntimeIdentity. defaults.json
|
|
419
|
+
// is host-wide and names whichever runtime installed LAST (#2840's poison);
|
|
420
|
+
// the marker describes THIS install (written for every runtime since #2297).
|
|
421
|
+
runtimeId = resolveRuntimeNameFromCandidates(readInstallRuntimeMarker()) || null;
|
|
422
|
+
}
|
|
375
423
|
if (!runtimeId) {
|
|
376
424
|
try {
|
|
377
425
|
const defaultsPath = path.join(os.homedir(), '.gsd', 'defaults.json');
|
|
@@ -419,6 +467,28 @@ function evaluateRootIsolation(root, subagentType, { clock = Date, dispatchIds =
|
|
|
419
467
|
}
|
|
420
468
|
if (!isGsdProject) return { action: 'allow' };
|
|
421
469
|
|
|
470
|
+
// #3582: self-heal the compiled runtime library BEFORE any of its four
|
|
471
|
+
// downstream requires (resolveFallbackIsolation's two, resolveIsolationEvidence's
|
|
472
|
+
// two — reached only below this point). Checked separately from the
|
|
473
|
+
// sentinel/fallback try block below so a build failure surfaces its own
|
|
474
|
+
// actionable RuntimeBuildError message rather than being folded into the
|
|
475
|
+
// generic "could not read or resolve ... configuration" deny reason (the
|
|
476
|
+
// #3050 misreport this issue exists to fix). Still fails closed either way.
|
|
477
|
+
try {
|
|
478
|
+
ensureRuntimeBuild();
|
|
479
|
+
} catch (err) {
|
|
480
|
+
return {
|
|
481
|
+
action: 'deny',
|
|
482
|
+
reason:
|
|
483
|
+
`GSD subagent isolation guard: cannot resolve this project's dispatch-isolation ` +
|
|
484
|
+
`configuration because the GSD runtime library failed to self-build. ` +
|
|
485
|
+
`${err instanceof RuntimeBuildError ? err.message : String(err && err.message || err)} ` +
|
|
486
|
+
`Refusing to allow this subagent to spawn until the runtime library is built — a guard ` +
|
|
487
|
+
`that cannot verify must not answer "safe" (#3050).`,
|
|
488
|
+
reasonCode: REASON_CODE.RUNTIME_BUILD_FAILED,
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
|
|
422
492
|
let declaredIsolation;
|
|
423
493
|
try {
|
|
424
494
|
// #3045 BLOCKER fix: a fresh sentinel is authoritative for THIS
|
|
@@ -439,6 +509,7 @@ function evaluateRootIsolation(root, subagentType, { clock = Date, dispatchIds =
|
|
|
439
509
|
`Refusing to allow this subagent to spawn without being able to verify whether ` +
|
|
440
510
|
`isolation is required — a guard that cannot verify must not answer "safe" (#3050). ` +
|
|
441
511
|
`Retry once the project configuration is readable.`,
|
|
512
|
+
reasonCode: REASON_CODE.CONFIG_UNREADABLE,
|
|
442
513
|
};
|
|
443
514
|
}
|
|
444
515
|
|
|
@@ -455,6 +526,7 @@ function evaluateRootIsolation(root, subagentType, { clock = Date, dispatchIds =
|
|
|
455
526
|
`"harness-worktree", but the subagentStart payload for this dispatch carries no usable ` +
|
|
456
527
|
`subagent_type. Refusing to allow it to spawn without being able to confirm whether it ` +
|
|
457
528
|
`is a GSD executor — a guard that cannot verify must not answer "safe" (#3050).`,
|
|
529
|
+
reasonCode: REASON_CODE.NO_SUBAGENT_TYPE,
|
|
458
530
|
};
|
|
459
531
|
}
|
|
460
532
|
|
|
@@ -471,6 +543,7 @@ function evaluateRootIsolation(root, subagentType, { clock = Date, dispatchIds =
|
|
|
471
543
|
`could not be determined (git did not respond). Refusing to allow subagent_type=` +
|
|
472
544
|
`"${subagentType}" to spawn without being able to verify isolation — a guard that ` +
|
|
473
545
|
`cannot verify must not answer "safe" (#3050). Retry once git is responsive.`,
|
|
546
|
+
reasonCode: REASON_CODE.CANNOT_DETERMINE_ISOLATION,
|
|
474
547
|
};
|
|
475
548
|
}
|
|
476
549
|
|
|
@@ -483,6 +556,7 @@ function evaluateRootIsolation(root, subagentType, { clock = Date, dispatchIds =
|
|
|
483
556
|
`directly, with no consent and no warning. Start an isolated session first (the ` +
|
|
484
557
|
`"--worktree" CLI flag or the "/worktree" chat command; Cursor manages these worktrees ` +
|
|
485
558
|
`under "~/.cursor/worktrees/") and retry.`,
|
|
559
|
+
reasonCode: REASON_CODE.NOT_ISOLATED_WORKTREE,
|
|
486
560
|
};
|
|
487
561
|
}
|
|
488
562
|
|
|
@@ -532,7 +606,7 @@ function main() {
|
|
|
532
606
|
decision = { action: 'allow' };
|
|
533
607
|
}
|
|
534
608
|
if (decision.action === 'deny') {
|
|
535
|
-
const out = { permission: 'deny', user_message: decision.reason };
|
|
609
|
+
const out = { permission: 'deny', user_message: decision.reason, reason_code: decision.reasonCode };
|
|
536
610
|
if (additionalContext !== null) out.additional_context = additionalContext;
|
|
537
611
|
process.stdout.write(JSON.stringify(out));
|
|
538
612
|
return;
|
|
@@ -557,4 +631,5 @@ module.exports = {
|
|
|
557
631
|
resolveFallbackIsolation,
|
|
558
632
|
resolveIsolationEvidence,
|
|
559
633
|
getWorkspaceRoots,
|
|
634
|
+
_setInstallRuntimeMarkerForTests,
|
|
560
635
|
};
|
|
@@ -20,13 +20,14 @@
|
|
|
20
20
|
|
|
21
21
|
'use strict';
|
|
22
22
|
|
|
23
|
-
let raw = '';
|
|
24
23
|
const stdinTimeout = setTimeout(() => {
|
|
25
24
|
process.exit(0);
|
|
26
25
|
}, 10000);
|
|
27
26
|
|
|
28
27
|
process.stdin.setEncoding('utf8');
|
|
29
|
-
|
|
28
|
+
// Drain stdin (puts the stream into flowing mode so 'end' fires); the
|
|
29
|
+
// payload itself is unused — this hook responds unconditionally.
|
|
30
|
+
process.stdin.on('data', () => {});
|
|
30
31
|
process.stdin.on('end', () => {
|
|
31
32
|
clearTimeout(stdinTimeout);
|
|
32
33
|
try {
|
|
@@ -11,26 +11,14 @@
|
|
|
11
11
|
// The goal is to surface suspicious content so the orchestrator can inspect it,
|
|
12
12
|
// not to create false-positive deadlocks.
|
|
13
13
|
|
|
14
|
-
const fs = require('fs');
|
|
15
14
|
const path = require('path');
|
|
16
15
|
|
|
17
|
-
// Prompt injection patterns
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
/override\s+(system|previous)\s+(prompt|instructions)/i,
|
|
24
|
-
/you\s+are\s+now\s+(?:a|an|the)\s+/i,
|
|
25
|
-
/act\s+as\s+(?:a|an|the)\s+(?!plan|phase|wave)/i,
|
|
26
|
-
/pretend\s+(?:you(?:'re| are)\s+|to\s+be\s+)/i,
|
|
27
|
-
/from\s+now\s+on,?\s+you\s+(?:are|will|should|must)/i,
|
|
28
|
-
/(?:print|output|reveal|show|display|repeat)\s+(?:your\s+)?(?:system\s+)?(?:prompt|instructions)/i,
|
|
29
|
-
/<\/?(?:system|assistant|human)>/i,
|
|
30
|
-
/\[SYSTEM\]/i,
|
|
31
|
-
/\[INST\]/i,
|
|
32
|
-
/<<\s*SYS\s*>>/i,
|
|
33
|
-
];
|
|
16
|
+
// Prompt injection patterns — shared with gsd-read-injection-scanner.js via
|
|
17
|
+
// hooks/lib/injection-patterns.js so the two surfaces cannot drift (#3504).
|
|
18
|
+
// Deliberately a subset of security.cjs's set: hooks stay loadable without the
|
|
19
|
+
// compiled lib tree. Staging of the lib helper is allowlisted in
|
|
20
|
+
// GSD_HOOK_LIB_FILES (bin/install.js).
|
|
21
|
+
const { INJECTION_PATTERNS } = require('./lib/injection-patterns.js');
|
|
34
22
|
|
|
35
23
|
// #2304: Kimi's native hook bus delivers Kimi's tool vocabulary in the payload
|
|
36
24
|
// (Write → WriteFile, Edit/MultiEdit → StrReplaceFile) while the [[hooks]]
|
|
@@ -153,8 +141,21 @@ process.stdin.on('end', () => {
|
|
|
153
141
|
process.exit(0);
|
|
154
142
|
}
|
|
155
143
|
|
|
156
|
-
// Get the content being written
|
|
157
|
-
|
|
144
|
+
// Get the content being written. #3504 (isolated review finding 3): the
|
|
145
|
+
// bare `||` chain handed a NON-STRING truthy `content` straight to
|
|
146
|
+
// pattern.test(), where ToString can throw ("Cannot convert object to a
|
|
147
|
+
// primitive value" for `{"toString": null}`) into the outer catch — the
|
|
148
|
+
// exact crash-to-allow class #2547/#2595 hardened inside
|
|
149
|
+
// normalizeKimiPayload, unreached on this read. Guarded selection: take
|
|
150
|
+
// the first field that is a string, or String-coerces without throwing,
|
|
151
|
+
// so a poisoned `content` no longer shadows a real `new_string`.
|
|
152
|
+
let content = '';
|
|
153
|
+
for (const candidate of [data.tool_input?.content, data.tool_input?.new_string]) {
|
|
154
|
+
if (typeof candidate === 'string' && candidate) { content = candidate; break; }
|
|
155
|
+
if (candidate && typeof candidate !== 'string') {
|
|
156
|
+
try { const s = String(candidate); if (s) { content = s; break; } } catch { /* keep looking */ }
|
|
157
|
+
}
|
|
158
|
+
}
|
|
158
159
|
if (!content) {
|
|
159
160
|
process.exit(0);
|
|
160
161
|
}
|
|
@@ -72,23 +72,10 @@ const MARKDOWN_LINK_PATTERNS = [
|
|
|
72
72
|
},
|
|
73
73
|
];
|
|
74
74
|
|
|
75
|
-
// Standard injection patterns —
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
/disregard\s+(all\s+)?previous/i,
|
|
80
|
-
/forget\s+(all\s+)?(your\s+)?instructions/i,
|
|
81
|
-
/override\s+(system|previous)\s+(prompt|instructions)/i,
|
|
82
|
-
/you\s+are\s+now\s+(?:a|an|the)\s+/i,
|
|
83
|
-
/act\s+as\s+(?:a|an|the)\s+(?!plan|phase|wave)/i,
|
|
84
|
-
/pretend\s+(?:you(?:'re| are)\s+|to\s+be\s+)/i,
|
|
85
|
-
/from\s+now\s+on,?\s+you\s+(?:are|will|should|must)/i,
|
|
86
|
-
/(?:print|output|reveal|show|display|repeat)\s+(?:your\s+)?(?:system\s+)?(?:prompt|instructions)/i,
|
|
87
|
-
/<\/?(?:system|assistant|human)>/i,
|
|
88
|
-
/\[SYSTEM\]/i,
|
|
89
|
-
/\[INST\]/i,
|
|
90
|
-
/<<\s*SYS\s*>>/i,
|
|
91
|
-
];
|
|
75
|
+
// Standard injection patterns — shared with gsd-prompt-guard.js via
|
|
76
|
+
// hooks/lib/injection-patterns.js so the two surfaces cannot drift (#3504).
|
|
77
|
+
// Staging of the lib helper is allowlisted in GSD_HOOK_LIB_FILES (bin/install.js).
|
|
78
|
+
const { INJECTION_PATTERNS } = require('./lib/injection-patterns.js');
|
|
92
79
|
|
|
93
80
|
const ALL_PATTERNS = [...INJECTION_PATTERNS, ...SUMMARISATION_PATTERNS];
|
|
94
81
|
|
|
@@ -98,6 +85,16 @@ const ALL_PATTERNS = [...INJECTION_PATTERNS, ...SUMMARISATION_PATTERNS];
|
|
|
98
85
|
// construction. Normalized to forward slashes to match `p` below.
|
|
99
86
|
const OWN_BUNDLE_PREFIX = __dirname.replace(/\\/g, '/').replace(/\/+$/, '') + '/';
|
|
100
87
|
|
|
88
|
+
// Synthetic rule ids for the finding classes that have no entry in
|
|
89
|
+
// MARKDOWN_LINK_PATTERNS. Frozen and referenced from BOTH the push sites and
|
|
90
|
+
// renderFinding so the two can never drift — a bare literal repeated at each
|
|
91
|
+
// site is how a rename silently falls through to the generic render branch.
|
|
92
|
+
const RULE_IDS = Object.freeze({
|
|
93
|
+
INJECTION_PATTERN: 'INJECTION-PATTERN',
|
|
94
|
+
INVISIBLE_UNICODE: 'INVISIBLE-UNICODE',
|
|
95
|
+
UNICODE_TAG_BLOCK: 'UNICODE-TAG-BLOCK',
|
|
96
|
+
});
|
|
97
|
+
|
|
101
98
|
function isExcludedPath(filePath) {
|
|
102
99
|
const p = filePath.replace(/\\/g, '/');
|
|
103
100
|
return (
|
|
@@ -267,12 +264,19 @@ process.stdin.on('end', () => {
|
|
|
267
264
|
process.exit(0);
|
|
268
265
|
}
|
|
269
266
|
|
|
267
|
+
// Typed findings IR — single source of truth for both the machine-readable
|
|
268
|
+
// `findings` array and the rendered advisory prose. Never build these as two
|
|
269
|
+
// parallel arrays: that invites the generative-fix-divergence defect class
|
|
270
|
+
// where the rendered text and the structured data silently drift apart.
|
|
270
271
|
const findings = [];
|
|
271
272
|
|
|
272
273
|
for (const pattern of ALL_PATTERNS) {
|
|
273
274
|
if (pattern.test(content)) {
|
|
274
275
|
// Trim pattern source for readable output
|
|
275
|
-
findings.push(
|
|
276
|
+
findings.push({
|
|
277
|
+
ruleId: RULE_IDS.INJECTION_PATTERN,
|
|
278
|
+
match: pattern.source.replace(/\\s\+/g, '-').replace(/[()\\]/g, '').substring(0, 50),
|
|
279
|
+
});
|
|
276
280
|
}
|
|
277
281
|
}
|
|
278
282
|
|
|
@@ -284,19 +288,19 @@ process.stdin.on('end', () => {
|
|
|
284
288
|
const m = line.match(entry.pattern);
|
|
285
289
|
if (!m) continue;
|
|
286
290
|
if (entry.safePredicate && entry.safePredicate(line)) continue;
|
|
287
|
-
findings.push(
|
|
291
|
+
findings.push({ ruleId: entry.ruleId, match: m[0].substring(0, 40) });
|
|
288
292
|
}
|
|
289
293
|
}
|
|
290
294
|
|
|
291
295
|
// Invisible Unicode (zero-width, RTL override, soft hyphen, BOM)
|
|
292
296
|
if (/[\u200B-\u200F\u2028-\u202F\uFEFF\u00AD\u2060-\u2069]/.test(content)) {
|
|
293
|
-
findings.push(
|
|
297
|
+
findings.push({ ruleId: RULE_IDS.INVISIBLE_UNICODE, match: null });
|
|
294
298
|
}
|
|
295
299
|
|
|
296
300
|
// Unicode tag block U+E0000–E007F (invisible instruction injection vector)
|
|
297
301
|
try {
|
|
298
302
|
if (/[\u{E0000}-\u{E007F}]/u.test(content)) {
|
|
299
|
-
findings.push(
|
|
303
|
+
findings.push({ ruleId: RULE_IDS.UNICODE_TAG_BLOCK, match: null });
|
|
300
304
|
}
|
|
301
305
|
} catch {
|
|
302
306
|
// Engine does not support Unicode property escapes — skip this check
|
|
@@ -306,6 +310,16 @@ process.stdin.on('end', () => {
|
|
|
306
310
|
process.exit(0);
|
|
307
311
|
}
|
|
308
312
|
|
|
313
|
+
// Renders one finding back into the exact prose fragment the advisory has
|
|
314
|
+
// always embedded. Kept as the ONLY place that maps IR -> text, so the
|
|
315
|
+
// `additionalContext` string and the `findings` array can never diverge.
|
|
316
|
+
function renderFinding(f) {
|
|
317
|
+
if (f.ruleId === RULE_IDS.INVISIBLE_UNICODE) return 'invisible-unicode';
|
|
318
|
+
if (f.ruleId === RULE_IDS.UNICODE_TAG_BLOCK) return 'unicode-tag-block';
|
|
319
|
+
if (f.ruleId === RULE_IDS.INJECTION_PATTERN) return f.match;
|
|
320
|
+
return `${f.ruleId}:${f.match}`;
|
|
321
|
+
}
|
|
322
|
+
|
|
309
323
|
const severity = findings.length >= 3 ? 'HIGH' : 'LOW';
|
|
310
324
|
const label = toolName === 'Read' ? path.basename(source) : source;
|
|
311
325
|
const detail = severity === 'HIGH'
|
|
@@ -313,7 +327,7 @@ process.stdin.on('end', () => {
|
|
|
313
327
|
: 'Single pattern match may be a false positive (e.g., documentation). Proceed with awareness.';
|
|
314
328
|
const advisory =
|
|
315
329
|
`\u26a0\ufe0f INJECTION SCAN [${severity}] (${toolName}): "${label}" triggered ` +
|
|
316
|
-
`${findings.length} pattern(s): ${findings.join(', ')}. ` +
|
|
330
|
+
`${findings.length} pattern(s): ${findings.map(renderFinding).join(', ')}. ` +
|
|
317
331
|
`This content is now in your conversation context. ${detail} Source: ${source}`;
|
|
318
332
|
|
|
319
333
|
// Opt-in blocking: only when configured AND high-confidence
|
|
@@ -330,8 +344,8 @@ process.stdin.on('end', () => {
|
|
|
330
344
|
const output = blocking
|
|
331
345
|
? { decision: 'block',
|
|
332
346
|
reason: `Prompt-injection blocked (${toolName}). ${advisory}`,
|
|
333
|
-
hookSpecificOutput: { hookEventName: 'PostToolUse', additionalContext: advisory } }
|
|
334
|
-
: { hookSpecificOutput: { hookEventName: 'PostToolUse', additionalContext: advisory } };
|
|
347
|
+
hookSpecificOutput: { hookEventName: 'PostToolUse', additionalContext: advisory, findings } }
|
|
348
|
+
: { hookSpecificOutput: { hookEventName: 'PostToolUse', additionalContext: advisory, findings } };
|
|
335
349
|
|
|
336
350
|
process.stdout.write(JSON.stringify(output));
|
|
337
351
|
} catch {
|
|
@@ -9,6 +9,24 @@ const os = require('os');
|
|
|
9
9
|
// Namespace (not destructured) so tests can inject spawn failures by
|
|
10
10
|
// monkeypatching childProcess.execFileSync.
|
|
11
11
|
const childProcess = require('child_process');
|
|
12
|
+
// #3582: gsd-core/bin/lib/*.cjs (semver-compare.cjs, state-document.cjs,
|
|
13
|
+
// active-workstream-store.cjs, planning-workspace.cjs — required below) and
|
|
14
|
+
// package-identity.cjs are tsc build artifacts (ADR-457), gitignored and
|
|
15
|
+
// absent on a raw plugin-marketplace / git-clone install that never ran
|
|
16
|
+
// `npm run build:lib`. The statusline renders on EVERY prompt, so a build
|
|
17
|
+
// failure here must DEGRADE (print nothing, exit 0) rather than crash
|
|
18
|
+
// Claude Code's per-render statusline hook. Scoped to the spawned-as-a-script
|
|
19
|
+
// path (`require.main === module`) — a test `require()` of this module for
|
|
20
|
+
// its pure helpers assumes a built tree, same as every other hook test.
|
|
21
|
+
if (require.main === module) {
|
|
22
|
+
try {
|
|
23
|
+
const { ensureRuntimeBuild } = require('../gsd-core/bin/ensure-runtime-build.cjs');
|
|
24
|
+
ensureRuntimeBuild();
|
|
25
|
+
} catch (e) {
|
|
26
|
+
process.stdout.write('');
|
|
27
|
+
process.exit(0);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
12
30
|
const { isSemverNewer } = require('../gsd-core/bin/lib/semver-compare.cjs');
|
|
13
31
|
const { PACKAGE_NAME, updateCacheFileName } = require('../gsd-core/bin/lib/package-identity.cjs');
|
|
14
32
|
const { normalizeStateStatus } = require('../gsd-core/bin/lib/state-document.cjs');
|
|
@@ -15,7 +15,28 @@
|
|
|
15
15
|
const fs = require('fs');
|
|
16
16
|
const path = require('path');
|
|
17
17
|
const os = require('os');
|
|
18
|
-
|
|
18
|
+
|
|
19
|
+
// #3582: gsd-core/bin/lib/package-identity.cjs is a tsc build artifact
|
|
20
|
+
// (ADR-457), gitignored and absent on a raw plugin-marketplace / git-clone
|
|
21
|
+
// install that never ran `npm run build:lib`. This is an opt-in SessionStart
|
|
22
|
+
// hook — a build failure here must DEGRADE, not crash session start. With
|
|
23
|
+
// PACKAGE_NAME left null, buildBannerOutput's own lineage guard
|
|
24
|
+
// (`!cache.package_name || cache.package_name !== PACKAGE_NAME`) always
|
|
25
|
+
// treats the cache as untrusted, so main() falls through to its existing
|
|
26
|
+
// silent "print nothing" path below — no separate degrade branch needed.
|
|
27
|
+
// This try/require/ensureRuntimeBuild/require/catch shape is deliberately
|
|
28
|
+
// duplicated (not extracted to hooks/lib/) — see
|
|
29
|
+
// gsd-check-update-worker.js's identical #3582 comment for why.
|
|
30
|
+
let PACKAGE_NAME = null;
|
|
31
|
+
let updateCacheFileName = 'gsd-update-check.json';
|
|
32
|
+
try {
|
|
33
|
+
const { ensureRuntimeBuild } = require('../gsd-core/bin/ensure-runtime-build.cjs');
|
|
34
|
+
ensureRuntimeBuild();
|
|
35
|
+
({ PACKAGE_NAME, updateCacheFileName } = require('../gsd-core/bin/lib/package-identity.cjs'));
|
|
36
|
+
} catch (e) {
|
|
37
|
+
// Runtime library missing/broken and could not self-build — degrade to the
|
|
38
|
+
// fallbacks above rather than crash the SessionStart hook.
|
|
39
|
+
}
|
|
19
40
|
|
|
20
41
|
// Suppress repeat parse-error banners for 24 hours so a genuinely broken
|
|
21
42
|
// cache file doesn't nag the user every session.
|