@opengsd/gsd-core 1.12.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/.opencode/plugins/gsd-core.js +12 -0
- 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-executor.md +63 -35
- 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-plan-checker.md +76 -57
- package/agents/gsd-planner.md +14 -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-checker.md +19 -3
- package/agents/gsd-ui-researcher.compact.md +282 -0
- package/agents/gsd-ui-researcher.md +29 -0
- package/agents/gsd-user-profiler.compact.md +108 -0
- package/agents/gsd-verifier.md +23 -1
- package/bin/install.js +444 -134
- 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/execute-phase.md +1 -1
- 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/ns-workflow.md +2 -1
- package/commands/gsd/pause-work.md +1 -0
- package/commands/gsd/phase.md +2 -1
- package/commands/gsd/pr-branch.md +1 -0
- package/commands/gsd/quick-batch.md +105 -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/surface.md +18 -8
- 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 +532 -174
- 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-activation.cjs +27 -0
- 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 +528 -116
- package/gsd-core/bin/lib/capability-source.cjs +19 -2
- package/gsd-core/bin/lib/capability-state.cjs +7 -1
- package/gsd-core/bin/lib/capability-validator.cjs +134 -5
- package/gsd-core/bin/lib/capability-writer.cjs +14 -4
- package/gsd-core/bin/lib/check-command-router.cjs +198 -38
- package/gsd-core/bin/lib/claude-orchestration.cjs +10 -25
- package/gsd-core/bin/lib/clusters.cjs +1 -0
- package/gsd-core/bin/lib/code-review-depth.cjs +2 -2
- package/gsd-core/bin/lib/command-aliases.cjs +16 -0
- package/gsd-core/bin/lib/commands.cjs +981 -79
- package/gsd-core/bin/lib/config-loader.cjs +4 -0
- package/gsd-core/bin/lib/config.cjs +153 -38
- package/gsd-core/bin/lib/core-utils.cjs +34 -7
- package/gsd-core/bin/lib/coverage.cjs +1 -1
- package/gsd-core/bin/lib/decisions.cjs +343 -28
- package/gsd-core/bin/lib/edge-probe.cjs +14 -1
- package/gsd-core/bin/lib/external-descriptor-trust.cjs +29 -14
- package/gsd-core/bin/lib/file-overlap-partitioner.cjs +74 -0
- package/gsd-core/bin/lib/frontmatter.cjs +137 -23
- package/gsd-core/bin/lib/gap-checker.cjs +22 -13
- package/gsd-core/bin/lib/git-base-branch.cjs +10 -2
- package/gsd-core/bin/lib/gsd2-import.cjs +1 -2
- package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +8 -2
- package/gsd-core/bin/lib/health-diagnostic-rules/roadmap-disk-consistency.cjs +54 -11
- package/gsd-core/bin/lib/health-diagnostic-rules/state-consistency.cjs +87 -23
- package/gsd-core/bin/lib/health-diagnostic-rules/worktree-health.cjs +1 -1
- package/gsd-core/bin/lib/host-integration.cjs +57 -5
- package/gsd-core/bin/lib/init-command-router.cjs +14 -0
- package/gsd-core/bin/lib/init.cjs +539 -60
- package/gsd-core/bin/lib/install-engine.cjs +199 -14
- package/gsd-core/bin/lib/install-model-override-resolver.cjs +45 -0
- package/gsd-core/bin/lib/install-profiles.cjs +36 -14
- package/gsd-core/bin/lib/installer-migration-report.cjs +1 -0
- package/gsd-core/bin/lib/installer-migrations.cjs +33 -4
- package/gsd-core/bin/lib/io.cjs +35 -0
- package/gsd-core/bin/lib/loop-resolver.cjs +64 -39
- package/gsd-core/bin/lib/markdown-table.cjs +123 -0
- package/gsd-core/bin/lib/mcp-catalog.cjs +2 -2
- package/gsd-core/bin/lib/milestone.cjs +41 -10
- package/gsd-core/bin/lib/model-resolver.cjs +101 -10
- package/gsd-core/bin/lib/phase-command-router.cjs +20 -7
- package/gsd-core/bin/lib/phase-id.cjs +412 -31
- package/gsd-core/bin/lib/phase-lifecycle.cjs +61 -0
- package/gsd-core/bin/lib/phase.cjs +941 -98
- package/gsd-core/bin/lib/plan-document.cjs +10 -0
- package/gsd-core/bin/lib/planning-inspect.cjs +34 -18
- package/gsd-core/bin/lib/planning-snapshot.cjs +206 -30
- package/gsd-core/bin/lib/planning-workspace.cjs +153 -29
- 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-command-router.cjs +285 -0
- package/gsd-core/bin/lib/quick-batch-dispatch.cjs +250 -0
- package/gsd-core/bin/lib/quick-batch.cjs +840 -0
- 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-descriptor.cjs +53 -5
- package/gsd-core/bin/lib/review-lane-invocation.cjs +96 -1
- package/gsd-core/bin/lib/review-lane-runner.cjs +136 -10
- package/gsd-core/bin/lib/reviewer-step-dispatch.cjs +337 -0
- package/gsd-core/bin/lib/roadmap-parser.cjs +555 -41
- package/gsd-core/bin/lib/roadmap.cjs +292 -69
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +260 -43
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +28 -20
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +294 -108
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +408 -47
- package/gsd-core/bin/lib/security.cjs +126 -7
- package/gsd-core/bin/lib/shell-command-projection.cjs +4 -0
- package/gsd-core/bin/lib/smart-entry.cjs +7 -9
- package/gsd-core/bin/lib/state-document.cjs +159 -32
- package/gsd-core/bin/lib/state-md-schema.cjs +44 -27
- package/gsd-core/bin/lib/state-transition.cjs +465 -62
- package/gsd-core/bin/lib/state.cjs +906 -151
- package/gsd-core/bin/lib/surface.cjs +83 -10
- package/gsd-core/bin/lib/task-command-router.cjs +12 -6
- package/gsd-core/bin/lib/tdd-red-evidence.cjs +133 -0
- package/gsd-core/bin/lib/uat.cjs +1420 -516
- package/gsd-core/bin/lib/update-context.cjs +36 -26
- package/gsd-core/bin/lib/validate.cjs +230 -12
- package/gsd-core/bin/lib/vendor/js-yaml.cjs +11 -3
- package/gsd-core/bin/lib/verification-command-router.cjs +2 -1
- package/gsd-core/bin/lib/verification.cjs +316 -23
- package/gsd-core/bin/lib/verify-command-grounding.cjs +1 -1
- package/gsd-core/bin/lib/verify-command-router.cjs +1 -0
- package/gsd-core/bin/lib/verify.cjs +531 -36
- package/gsd-core/bin/lib/workstream-inventory.cjs +21 -2
- package/gsd-core/bin/lib/worktree-safety.cjs +21 -7
- package/gsd-core/bin/shared/config-defaults.manifest.json +1 -0
- package/gsd-core/bin/shared/config-schema.manifest.json +13 -0
- package/gsd-core/bin/verify-reapply-patches.cjs +507 -81
- package/gsd-core/references/agent-contracts.md +3 -3
- package/gsd-core/references/compact-content-gate.md +66 -0
- package/gsd-core/references/edge-probe.md +17 -13
- package/gsd-core/references/execute-mvp-tdd.md +18 -16
- package/gsd-core/references/execute-phase-response-language.md +6 -0
- package/gsd-core/references/executor-examples.md +42 -0
- package/gsd-core/references/few-shot-examples/plan-checker.md +15 -15
- package/gsd-core/references/loop-hook-dispatch.md +18 -0
- package/gsd-core/references/model-profiles.md +12 -3
- package/gsd-core/references/mvp-concepts.md +2 -2
- package/gsd-core/references/plan-checker-examples.md +41 -0
- package/gsd-core/references/planner-antipatterns.md +25 -0
- package/gsd-core/references/planner-chunked.md +5 -1
- package/gsd-core/references/planner-coupling.md +42 -0
- package/gsd-core/references/planner-quick-batch.md +71 -0
- package/gsd-core/references/planner-reviews.md +47 -0
- package/gsd-core/references/planner-revision.md +75 -2
- package/gsd-core/references/planning-config.md +5 -1
- package/gsd-core/references/response-language-directive.md +9 -0
- package/gsd-core/references/revision-loop.md +118 -11
- package/gsd-core/references/tdd.md +17 -9
- package/gsd-core/references/thinking-models-planning.md +18 -2
- package/gsd-core/references/verification-patterns.md +17 -4
- package/gsd-core/references/verifier-evidence-gate.md +160 -0
- package/gsd-core/references/worktree-path-safety.md +112 -2
- package/gsd-core/templates/README.md +7 -1
- package/gsd-core/templates/phase-prompt.md +4 -0
- 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/templates/verification-report.md +5 -0
- package/gsd-core/workflows/add-backlog.md +2 -0
- package/gsd-core/workflows/add-phase.md +2 -0
- package/gsd-core/workflows/add-tests.md +1 -1
- package/gsd-core/workflows/add-todo.md +4 -3
- package/gsd-core/workflows/ai-integration-phase.md +1 -1
- package/gsd-core/workflows/analyze-dependencies.md +2 -0
- package/gsd-core/workflows/audit-fix.md +2 -0
- package/gsd-core/workflows/audit-milestone.md +2 -0
- package/gsd-core/workflows/audit-uat.md +2 -0
- package/gsd-core/workflows/autonomous.md +15 -10
- package/gsd-core/workflows/check-todos.md +5 -3
- package/gsd-core/workflows/cleanup.md +4 -2
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +22 -13
- package/gsd-core/workflows/code-review-fix.md +5 -3
- package/gsd-core/workflows/code-review.md +211 -43
- package/gsd-core/workflows/complete-milestone/detail/elaboration.md +274 -0
- package/gsd-core/workflows/complete-milestone.md +40 -254
- package/gsd-core/workflows/debug.md +1 -1
- package/gsd-core/workflows/diagnose-issues.md +5 -1
- package/gsd-core/workflows/discuss-phase/modes/advisor.md +2 -0
- package/gsd-core/workflows/discuss-phase/modes/all.md +2 -0
- package/gsd-core/workflows/discuss-phase/modes/analyze.md +2 -0
- package/gsd-core/workflows/discuss-phase/modes/auto.md +2 -0
- package/gsd-core/workflows/discuss-phase/modes/batch.md +2 -0
- package/gsd-core/workflows/discuss-phase/modes/chain.md +2 -0
- package/gsd-core/workflows/discuss-phase/modes/default.md +2 -0
- package/gsd-core/workflows/discuss-phase/modes/power.md +2 -0
- package/gsd-core/workflows/discuss-phase/modes/text.md +2 -0
- package/gsd-core/workflows/discuss-phase/templates/context.md +2 -0
- package/gsd-core/workflows/discuss-phase/templates/discussion-log.md +2 -0
- package/gsd-core/workflows/discuss-phase-assumptions.md +1 -1
- package/gsd-core/workflows/discuss-phase-power.md +2 -0
- package/gsd-core/workflows/discuss-phase.md +1 -1
- package/gsd-core/workflows/do.md +43 -13
- package/gsd-core/workflows/docs-update/detail/elaboration.md +179 -0
- package/gsd-core/workflows/docs-update.md +15 -156
- package/gsd-core/workflows/edit-phase.md +2 -0
- package/gsd-core/workflows/eval-review.md +1 -1
- package/gsd-core/workflows/execute-phase/detail/elaboration.md +124 -0
- package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +20 -3
- package/gsd-core/workflows/execute-phase/steps/completion-reconciliation.md +56 -0
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +24 -3
- package/gsd-core/workflows/execute-phase/steps/executor-progress-policy.md +43 -0
- package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +8 -2
- package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +2 -0
- package/gsd-core/workflows/execute-phase/steps/sequential-root-pin.md +35 -0
- package/gsd-core/workflows/execute-phase/steps/tdd-applicability-resolution.md +25 -0
- package/gsd-core/workflows/execute-phase/steps/worktree-recovery-policy.md +2 -0
- package/gsd-core/workflows/execute-phase.md +78 -159
- package/gsd-core/workflows/execute-plan.md +28 -15
- package/gsd-core/workflows/explore.md +2 -0
- package/gsd-core/workflows/extract-learnings.md +2 -0
- package/gsd-core/workflows/fast.md +6 -0
- package/gsd-core/workflows/forensics.md +2 -0
- package/gsd-core/workflows/graduation.md +1 -1
- package/gsd-core/workflows/health.md +1 -1
- package/gsd-core/workflows/help/modes/brief.md +2 -0
- package/gsd-core/workflows/help/modes/default.md +2 -0
- package/gsd-core/workflows/help/modes/full.compact.md +398 -0
- package/gsd-core/workflows/help/modes/full.md +12 -0
- package/gsd-core/workflows/help/modes/topic.md +2 -0
- package/gsd-core/workflows/help.md +3 -1
- package/gsd-core/workflows/import.md +3 -3
- package/gsd-core/workflows/inbox.md +1 -1
- package/gsd-core/workflows/ingest-docs.md +1 -1
- package/gsd-core/workflows/insert-phase.md +2 -0
- package/gsd-core/workflows/list-phase-assumptions.md +2 -0
- package/gsd-core/workflows/list-seeds.md +2 -0
- package/gsd-core/workflows/list-workspaces.md +2 -0
- package/gsd-core/workflows/manager.md +3 -3
- package/gsd-core/workflows/map-codebase.md +52 -3
- package/gsd-core/workflows/milestone-summary.md +2 -0
- package/gsd-core/workflows/mvp-phase.md +1 -1
- package/gsd-core/workflows/new-milestone.md +55 -13
- package/gsd-core/workflows/new-project/detail/elaboration.md +216 -0
- package/gsd-core/workflows/new-project.md +37 -205
- package/gsd-core/workflows/new-workspace.md +1 -1
- package/gsd-core/workflows/next.md +2 -0
- package/gsd-core/workflows/node-repair.md +2 -0
- package/gsd-core/workflows/note.md +2 -0
- package/gsd-core/workflows/onboard.md +1 -1
- package/gsd-core/workflows/pause-work.md +19 -4
- package/gsd-core/workflows/plan-phase/detail/elaboration.md +209 -0
- package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +100 -18
- package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +2 -0
- package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +9 -0
- package/gsd-core/workflows/plan-phase.md +144 -185
- package/gsd-core/workflows/plan-review-convergence.md +102 -10
- package/gsd-core/workflows/plant-seed.md +1 -1
- package/gsd-core/workflows/pr-branch.md +30 -10
- package/gsd-core/workflows/profile-user.md +1 -1
- package/gsd-core/workflows/progress/steps/forensic-audit.md +1 -1
- package/gsd-core/workflows/progress.md +25 -3
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +37 -2
- package/gsd-core/workflows/quick/steps/research-phase.md +3 -3
- package/gsd-core/workflows/quick-batch/steps/batch-init.md +55 -0
- package/gsd-core/workflows/quick-batch/steps/completion.md +65 -0
- package/gsd-core/workflows/quick-batch/steps/merge-wave.md +100 -0
- package/gsd-core/workflows/quick-batch/steps/plan-checker-loop.md +147 -0
- package/gsd-core/workflows/quick-batch/steps/planner-wave.md +158 -0
- package/gsd-core/workflows/quick-batch/steps/research-phase.md +95 -0
- package/gsd-core/workflows/quick-batch/steps/resume-mode.md +49 -0
- package/gsd-core/workflows/quick-batch/steps/verification-wave.md +73 -0
- package/gsd-core/workflows/quick-batch/steps/worktree-dispatch.md +169 -0
- package/gsd-core/workflows/quick-batch.md +203 -0
- package/gsd-core/workflows/quick.md +21 -4
- package/gsd-core/workflows/reapply-patches.md +79 -3
- package/gsd-core/workflows/remove-phase.md +2 -0
- package/gsd-core/workflows/remove-workspace.md +1 -1
- package/gsd-core/workflows/resume-project.md +6 -2
- package/gsd-core/workflows/review.md +215 -10
- package/gsd-core/workflows/scan.md +2 -0
- package/gsd-core/workflows/section-manifest.json +12 -0
- package/gsd-core/workflows/secure-phase.md +1 -1
- package/gsd-core/workflows/session-report.md +2 -0
- package/gsd-core/workflows/settings-advanced.md +2 -0
- package/gsd-core/workflows/settings-integrations.md +9 -8
- package/gsd-core/workflows/settings.md +19 -6
- package/gsd-core/workflows/ship.md +10 -10
- package/gsd-core/workflows/sketch-wrap-up.md +2 -0
- package/gsd-core/workflows/sketch.md +1 -1
- package/gsd-core/workflows/smart-entry.md +1 -1
- package/gsd-core/workflows/spec-phase.md +24 -19
- package/gsd-core/workflows/spike-wrap-up.md +2 -0
- package/gsd-core/workflows/spike.md +1 -1
- package/gsd-core/workflows/stats.md +2 -0
- package/gsd-core/workflows/sync-skills.md +12 -4
- package/gsd-core/workflows/thread.md +2 -0
- package/gsd-core/workflows/transition.md +2 -0
- package/gsd-core/workflows/ui-phase.md +26 -5
- package/gsd-core/workflows/ui-review.md +1 -1
- package/gsd-core/workflows/ultraplan-phase.md +2 -0
- package/gsd-core/workflows/undo.md +1 -1
- package/gsd-core/workflows/update.md +48 -43
- package/gsd-core/workflows/validate-phase.md +1 -1
- package/gsd-core/workflows/verify-work/detail/elaboration.md +230 -0
- package/gsd-core/workflows/verify-work.md +68 -182
- package/hooks/dist/gsd-agent-isolation-guard.js +42 -16
- package/hooks/dist/gsd-check-update-worker.js +19 -2
- package/hooks/dist/gsd-context-monitor.js +371 -27
- package/hooks/dist/gsd-cursor-subagent-start.js +34 -14
- package/hooks/dist/gsd-node-runner.sh +1 -0
- package/hooks/dist/gsd-prompt-guard.js +30 -5
- package/hooks/dist/gsd-read-guard.js +2 -0
- package/hooks/dist/gsd-read-injection-scanner.js +5 -5
- package/hooks/dist/gsd-secret-read-guard.js +1105 -0
- package/hooks/dist/gsd-statusline.js +18 -10
- package/hooks/dist/gsd-validate-commit.sh +474 -7
- package/hooks/dist/gsd-workflow-guard.js +2 -1
- 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/git-cmd.js +210 -1
- package/hooks/dist/lib/injection-patterns.js +36 -6
- package/hooks/dist/lib/isolation-deny-reason.js +53 -1
- package/hooks/dist/lib/isolation-sentinel.js +58 -19
- package/hooks/dist/managed-hooks-registry.cjs +1 -0
- package/hooks/gsd-agent-isolation-guard.js +42 -16
- package/hooks/gsd-check-update-worker.js +19 -2
- package/hooks/gsd-context-monitor.js +371 -27
- package/hooks/gsd-cursor-subagent-start.js +34 -14
- package/hooks/gsd-node-runner.sh +1 -0
- package/hooks/gsd-prompt-guard.js +30 -5
- package/hooks/gsd-read-guard.js +2 -0
- package/hooks/gsd-read-injection-scanner.js +5 -5
- package/hooks/gsd-secret-read-guard.js +1105 -0
- package/hooks/gsd-statusline.js +18 -10
- package/hooks/gsd-validate-commit.sh +474 -7
- package/hooks/gsd-workflow-guard.js +2 -1
- package/hooks/gsd-worktree-path-guard.js +25 -14
- package/hooks/gsd-write-guard.js +46 -1
- package/hooks/hooks.json +6 -0
- package/hooks/lib/dispatch-identity.js +187 -0
- package/hooks/lib/filename-classification.js +64 -0
- package/hooks/lib/git-cmd.js +210 -1
- package/hooks/lib/injection-patterns.js +36 -6
- package/hooks/lib/isolation-deny-reason.js +53 -1
- package/hooks/lib/isolation-sentinel.js +58 -19
- package/hooks/managed-hooks-registry.cjs +1 -0
- package/package.json +13 -9
- package/scripts/benchmark-compact-content-variants.cjs +298 -0
- package/scripts/benchmark-compact-content.cjs +368 -0
- package/scripts/build-hooks.js +11 -4
- 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 +133 -20
- package/scripts/ci-timeout-report.cjs +1 -1
- package/scripts/diff-touches-shipped-paths.cjs +1 -1
- package/scripts/docs-guard-registry.cjs +17 -2
- package/scripts/gen-adr-index.cjs +8 -2
- package/scripts/gen-inventory-manifest.cjs +12 -0
- package/scripts/gen-loop-host-contract.cjs +67 -15
- 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/shellcheck-fetch.cjs +247 -0
- package/scripts/lib/suite-detection.cjs +32 -0
- package/scripts/lint-allow-test-rule-refs.allowlist.json +0 -6
- package/scripts/lint-allow-test-rule-refs.effective-ceiling.json +1 -1
- package/scripts/lint-allow-test-rule-refs.unverified-ceiling.json +1 -1
- package/scripts/lint-allowed-tools-parity.cjs +221 -0
- package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +24 -2
- package/scripts/lint-phase-enumeration-drift.cjs +24 -6
- package/scripts/lint-phase-id-drift.cjs +465 -15
- package/scripts/lint-portable-grep.cjs +176 -0
- package/scripts/lint-response-language-coverage.cjs +530 -0
- package/scripts/lint-source-test-name-collision.cjs +1 -1
- package/scripts/lint-test-file-count.allowlist.json +4 -1
- package/scripts/lint-vendored-deps.cjs +128 -17
- package/scripts/lint-workflow-shellcheck-baseline.json +1112 -0
- package/scripts/lint-workflow-shellcheck.cjs +614 -0
- package/scripts/npm-audit-baseline.cjs +376 -0
- package/scripts/prompt-injection-scan.sh +22 -0
- package/scripts/require-issue-link-policy.cjs +16 -1
- 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-execute-phase/SKILL.md +1 -1
- 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-ns-workflow/SKILL.md +1 -0
- package/skills/gsd-pause-work/SKILL.md +1 -0
- package/skills/gsd-phase/SKILL.md +2 -1
- package/skills/gsd-pr-branch/SKILL.md +1 -0
- package/skills/gsd-quick-batch/SKILL.md +105 -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-surface/SKILL.md +18 -8
- 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
|
@@ -677,8 +677,25 @@ function stageValidated(opts) {
|
|
|
677
677
|
throw new Error(`Hook fragment validation failed: ${fragErrs.join('; ')}`);
|
|
678
678
|
}
|
|
679
679
|
// Cross-capability validations (contract, consumes, cross-capability).
|
|
680
|
-
|
|
681
|
-
|
|
680
|
+
//
|
|
681
|
+
// #3929: seed the validation set the way the loader builds its accepted
|
|
682
|
+
// map — frozen first-party registry, then each committed overlay of the
|
|
683
|
+
// TARGET (global) install scope accepted incrementally (structural +
|
|
684
|
+
// engines + full-suite-clean), then the candidate LAST (mirroring
|
|
685
|
+
// `acceptedMap.set(id, cap)`). The singleton seed
|
|
686
|
+
// `new Map([[id, cap]])` this replaced made every non-empty `requires`
|
|
687
|
+
// unsatisfiable (membership is checked against the map) and left cycles,
|
|
688
|
+
// tier-monotone and central config-key exclusivity vacuous at install.
|
|
689
|
+
// The seed builder lives in capability-loader so the overlay semantics
|
|
690
|
+
// have one owner and are clean by construction — pre-existing junk in the
|
|
691
|
+
// install scope is skipped, never attributed to the candidate. No swallow:
|
|
692
|
+
// if the loader cannot build the seed the install fails loudly — silently
|
|
693
|
+
// degrading to the singleton map would re-hide #3929.
|
|
694
|
+
/* eslint-disable @typescript-eslint/no-require-imports */
|
|
695
|
+
const seedLoader = require('./capability-loader.cjs');
|
|
696
|
+
/* eslint-enable @typescript-eslint/no-require-imports */
|
|
697
|
+
const { capMap, centralKeys } = seedLoader.crossValidationSeed(process.cwd(), gsdHome, hostVersion, capValidator, semverMod);
|
|
698
|
+
capMap.set(id, cap);
|
|
682
699
|
const crossErrs = [
|
|
683
700
|
...capValidator.validateAgainstContract(cap, id),
|
|
684
701
|
...capValidator.validateConsumesGlobal(capMap),
|
|
@@ -39,7 +39,7 @@ const ioMod = require("./io.cjs");
|
|
|
39
39
|
const { output: coreOutput, error: coreError } = ioMod;
|
|
40
40
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
41
41
|
const activationMod = require("./capability-activation.cjs");
|
|
42
|
-
const { _resolveActivationValue } = activationMod;
|
|
42
|
+
const { _resolveActivationValue, _resolvePointGate } = activationMod;
|
|
43
43
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
44
44
|
const configLoaderMod = require("./config-loader.cjs");
|
|
45
45
|
const { loadConfig } = configLoaderMod;
|
|
@@ -179,6 +179,12 @@ function resolveCapabilityState(input) {
|
|
|
179
179
|
// (mirrors loop-resolver.isActive: `typeof when !== 'string' || when.length === 0` → false)
|
|
180
180
|
configured = false;
|
|
181
181
|
}
|
|
182
|
+
// #3661: optional point-selection gate, ANDed in — mirrors loop-resolver.isActive
|
|
183
|
+
// EXACTLY (see capability-activation.cts's _resolvePointGate doc comment; this
|
|
184
|
+
// parity is load-bearing, see tests/capability-precedence-parity.test.cjs).
|
|
185
|
+
if (configured) {
|
|
186
|
+
configured = _resolvePointGate(h['pointFrom'], point, config, cwd, registry);
|
|
187
|
+
}
|
|
182
188
|
// Hook active = capability-level active AND hook's own config gate.
|
|
183
189
|
// The capability's `active` constant (= enabled && configActivation) is
|
|
184
190
|
// used here so that a config-disabled capability (active=false) cannot
|
|
@@ -1643,6 +1643,28 @@ function validateRuntimeBody(cap) {
|
|
|
1643
1643
|
' (or "undocumented") (got: ' + JSON.stringify(d.isolation) + ')',
|
|
1644
1644
|
);
|
|
1645
1645
|
}
|
|
1646
|
+
|
|
1647
|
+
// maxConcurrency — ADR-1239 Phase 1 (#3673). A numeric dispatch
|
|
1648
|
+
// sub-field (not a closed-vocabulary enum member — same numeric
|
|
1649
|
+
// dispatch sub-field treatment as maxDepth above; unlike maxDepth,
|
|
1650
|
+
// 0 and negative values are invalid — 1 is the fail-closed floor, not
|
|
1651
|
+
// a legitimate "no concurrency" declaration).
|
|
1652
|
+
// OPTIONAL, like isolation: added after existing descriptors, so an
|
|
1653
|
+
// omitted maxConcurrency is legitimate — negotiateHostCapabilities
|
|
1654
|
+
// degrades it to 1 (the safe floor) and warns, exactly as for any
|
|
1655
|
+
// other undeclared dispatch sub-field. Only a PRESENT value is
|
|
1656
|
+
// checked against the positive-safe-integer contract.
|
|
1657
|
+
if (d.maxConcurrency === undefined) {
|
|
1658
|
+
// absent — nothing to validate; negotiateHostCapabilities fails it closed.
|
|
1659
|
+
} else if (
|
|
1660
|
+
d.maxConcurrency !== 'undocumented' &&
|
|
1661
|
+
(!Number.isSafeInteger(d.maxConcurrency) || d.maxConcurrency < 1)
|
|
1662
|
+
) {
|
|
1663
|
+
errors.push(
|
|
1664
|
+
'runtime.hostIntegration.dispatch.maxConcurrency must be a positive safe integer or "undocumented" ' +
|
|
1665
|
+
'(got: ' + JSON.stringify(d.maxConcurrency) + ')',
|
|
1666
|
+
);
|
|
1667
|
+
}
|
|
1646
1668
|
}
|
|
1647
1669
|
}
|
|
1648
1670
|
|
|
@@ -1824,9 +1846,29 @@ const KNOWN_REVIEWER_FIELDS = new Set([
|
|
|
1824
1846
|
// missed a configured model and silently disabled the pinned-model escape hatch
|
|
1825
1847
|
// #2073 added. A convention one shipped lane already violates is not a contract.
|
|
1826
1848
|
'modelConfigKey',
|
|
1849
|
+
// `timeoutConfigKey` added by #3274, same optional/backward-compatible shape as
|
|
1850
|
+
// `modelConfigKey` above: a manifest authored before this field existed must keep validating.
|
|
1851
|
+
'timeoutConfigKey',
|
|
1852
|
+
// `effortConfigKey` / `defaultEffort` added by #4255, same optional/backward-compatible shape
|
|
1853
|
+
// as the two above. Lane effort used to be resolved by querying the `gsd-plan-checker` AGENT
|
|
1854
|
+
// through a hardcoded id, so every prompt-fed lane ran at that verifier's frontmatter effort;
|
|
1855
|
+
// it is a property of the review, so the lane declares it. A manifest authored before these
|
|
1856
|
+
// fields existed must keep validating — absent is read as "this lane declares no review
|
|
1857
|
+
// effort", which emits no effort argument at all.
|
|
1858
|
+
'effortConfigKey',
|
|
1859
|
+
'defaultEffort',
|
|
1827
1860
|
'handler',
|
|
1828
1861
|
]);
|
|
1829
1862
|
|
|
1863
|
+
/**
|
|
1864
|
+
* The effort levels a lane may declare as its review default (#4255, #3533 vocabulary).
|
|
1865
|
+
*
|
|
1866
|
+
* `inherit` is deliberately NOT a member. It is a legitimate CONFIGURED value — it selects "emit
|
|
1867
|
+
* no argument, the CLI's own configuration decides" — but as a DECLARED default it would be a
|
|
1868
|
+
* second spelling of `null` and split one behaviour across two shapes.
|
|
1869
|
+
*/
|
|
1870
|
+
const REVIEWER_EFFORT_LEVELS = new Set(['minimal', 'low', 'medium', 'high', 'xhigh', 'max']);
|
|
1871
|
+
|
|
1830
1872
|
/**
|
|
1831
1873
|
* The closed `runtime.hostBehaviors` vocabulary (ADR-1016, closed via #2801).
|
|
1832
1874
|
*
|
|
@@ -1914,6 +1956,11 @@ const KNOWN_HOST_BEHAVIORS = new Set([
|
|
|
1914
1956
|
'sourceMarkerFile',
|
|
1915
1957
|
'tomlConfigInstall',
|
|
1916
1958
|
'trackCategoryDescription',
|
|
1959
|
+
// #2586: declares runtime-level feature axes GSD does not/cannot support on
|
|
1960
|
+
// this host (e.g. Codex's `["context-warnings","phase-lifecycle-display"]`)
|
|
1961
|
+
// — present-and-populated / absent-is-unsupported-empty convention, so
|
|
1962
|
+
// omitting the key on every other runtime carries no inverted meaning.
|
|
1963
|
+
'unsupportedFeatures',
|
|
1917
1964
|
'verificationStyle',
|
|
1918
1965
|
'writeCategoryDescription',
|
|
1919
1966
|
]);
|
|
@@ -2371,6 +2418,50 @@ function validateReviewerBodyFields(cap) {
|
|
|
2371
2418
|
);
|
|
2372
2419
|
}
|
|
2373
2420
|
|
|
2421
|
+
// OPTIONAL, mirroring modelConfigKey's D4 forward/backward-compat treatment (#3274): a manifest
|
|
2422
|
+
// authored before this field existed must keep validating. Absent/null means "no override for
|
|
2423
|
+
// this lane, use timeoutFloorMs". An empty string is neither absent nor a key, and is rejected.
|
|
2424
|
+
if (r.timeoutConfigKey !== undefined && r.timeoutConfigKey !== null &&
|
|
2425
|
+
(typeof r.timeoutConfigKey !== 'string' || r.timeoutConfigKey.length === 0)) {
|
|
2426
|
+
errors.push(
|
|
2427
|
+
ctx + ' reviewer.timeoutConfigKey must be a dotted config key or null ' +
|
|
2428
|
+
'(got: ' + describeValue(r.timeoutConfigKey) + ')',
|
|
2429
|
+
);
|
|
2430
|
+
}
|
|
2431
|
+
|
|
2432
|
+
// OPTIONAL, mirroring the two keys above (#4255). Absent/null means "this lane declares no
|
|
2433
|
+
// review effort", which is the shape that emits no effort argument at all — the correct state
|
|
2434
|
+
// for the nine lanes with no effort channel to feed. An empty string is neither.
|
|
2435
|
+
if (r.effortConfigKey !== undefined && r.effortConfigKey !== null &&
|
|
2436
|
+
(typeof r.effortConfigKey !== 'string' || r.effortConfigKey.length === 0)) {
|
|
2437
|
+
errors.push(
|
|
2438
|
+
ctx + ' reviewer.effortConfigKey must be a dotted config key or null ' +
|
|
2439
|
+
'(got: ' + describeValue(r.effortConfigKey) + ')',
|
|
2440
|
+
);
|
|
2441
|
+
}
|
|
2442
|
+
|
|
2443
|
+
// A declared default must be a level the effort axis knows, or the lane would render an
|
|
2444
|
+
// argument the reviewer CLI rejects and kill itself on every run. Closed vocabulary, checked
|
|
2445
|
+
// here rather than at resolution time so a malformed manifest fails at the trust boundary.
|
|
2446
|
+
if (r.defaultEffort !== undefined && r.defaultEffort !== null
|
|
2447
|
+
&& !(typeof r.defaultEffort === 'string' && REVIEWER_EFFORT_LEVELS.has(r.defaultEffort))) {
|
|
2448
|
+
errors.push(
|
|
2449
|
+
ctx + ' reviewer.defaultEffort must be one of ' +
|
|
2450
|
+
Array.from(REVIEWER_EFFORT_LEVELS).join('/') + ' or null ' +
|
|
2451
|
+
'(got: ' + describeValue(r.defaultEffort) + ')',
|
|
2452
|
+
);
|
|
2453
|
+
}
|
|
2454
|
+
|
|
2455
|
+
// A default with nothing to configure it through is a value the operator cannot change — the
|
|
2456
|
+
// shape #4255 exists to end. Declared together or not at all.
|
|
2457
|
+
if ((r.defaultEffort !== undefined && r.defaultEffort !== null)
|
|
2458
|
+
&& (r.effortConfigKey === undefined || r.effortConfigKey === null)) {
|
|
2459
|
+
errors.push(
|
|
2460
|
+
ctx + ' reviewer.defaultEffort is declared without an effortConfigKey, so the level ' +
|
|
2461
|
+
'could never be overridden',
|
|
2462
|
+
);
|
|
2463
|
+
}
|
|
2464
|
+
|
|
2374
2465
|
// `null` is the declared "no per-lane budget"; an empty string is not.
|
|
2375
2466
|
if (r.promptBudgetKey !== null && (typeof r.promptBudgetKey !== 'string' || r.promptBudgetKey.length === 0)) {
|
|
2376
2467
|
errors.push(
|
|
@@ -2710,7 +2801,7 @@ function materializeHookFragments(cap, capDir) {
|
|
|
2710
2801
|
|
|
2711
2802
|
const abs = path.resolve(capDir, fragment.path);
|
|
2712
2803
|
const capRoot = path.resolve(capDir);
|
|
2713
|
-
if (abs !== capRoot && !abs.startsWith(capRoot + path.sep)) {
|
|
2804
|
+
if (abs !== capRoot && !abs.startsWith(capRoot + path.sep)) { // allow-handrolled-containment: committed pre-build .cjs; compiled security.cjs is untracked build output
|
|
2714
2805
|
errors.push(
|
|
2715
2806
|
cap.id + '/' + groupName + '[' + i + '].fragment.path escapes capability directory: ' +
|
|
2716
2807
|
fragment.path,
|
|
@@ -2858,6 +2949,18 @@ function validateStep(step, prefix, declaredSkills, declaredAgents) {
|
|
|
2858
2949
|
errors.push(prefix + '.when must be a string if present');
|
|
2859
2950
|
}
|
|
2860
2951
|
|
|
2952
|
+
if (step.pointFrom !== undefined && typeof step.pointFrom !== 'string') {
|
|
2953
|
+
errors.push(prefix + '.pointFrom must be a string if present');
|
|
2954
|
+
}
|
|
2955
|
+
|
|
2956
|
+
// #4209 DISP-02: strict optional boolean opt-in trait. Absent or false is
|
|
2957
|
+
// inert; only a literal `true` reaches the projected active hook. Reject
|
|
2958
|
+
// every other type (including truthy non-boolean values) so a typo can
|
|
2959
|
+
// never silently opt a step into reviewer-lane dispatch.
|
|
2960
|
+
if (step.supportsReviewerLanes !== undefined && typeof step.supportsReviewerLanes !== 'boolean') {
|
|
2961
|
+
errors.push(prefix + '.supportsReviewerLanes must be a boolean if present');
|
|
2962
|
+
}
|
|
2963
|
+
|
|
2861
2964
|
if (step.fragment !== undefined) {
|
|
2862
2965
|
errors.push(...validateFragment(step.fragment, prefix + '.fragment'));
|
|
2863
2966
|
}
|
|
@@ -2997,6 +3100,31 @@ function validateAgainstContract(cap, capId) {
|
|
|
2997
3100
|
}
|
|
2998
3101
|
}
|
|
2999
3102
|
|
|
3103
|
+
// pointFrom (#3661): selects which of possibly several same-capability steps is
|
|
3104
|
+
// active for its own `point`, based on an enum config key. Require it references
|
|
3105
|
+
// an enum key in cap.config whose values include THIS step's own point — otherwise
|
|
3106
|
+
// the step could never activate (a silently-dead step).
|
|
3107
|
+
for (const step of cap.steps) {
|
|
3108
|
+
if (step.pointFrom !== undefined) {
|
|
3109
|
+
if (typeof step.pointFrom !== 'string') continue; // already reported above
|
|
3110
|
+
const slice = typeof cap.config === 'object' && cap.config !== null ? cap.config[step.pointFrom] : undefined;
|
|
3111
|
+
if (!slice || typeof slice !== 'object') {
|
|
3112
|
+
errors.push(
|
|
3113
|
+
prefix + ' step.pointFrom "' + step.pointFrom + '" is not defined in capability config keys',
|
|
3114
|
+
);
|
|
3115
|
+
} else if (slice.type !== 'enum') {
|
|
3116
|
+
errors.push(
|
|
3117
|
+
prefix + ' step.pointFrom "' + step.pointFrom + '" must reference an enum config key (got type: ' + slice.type + ')',
|
|
3118
|
+
);
|
|
3119
|
+
} else if (!Array.isArray(slice.values) || !slice.values.includes(step.point)) {
|
|
3120
|
+
errors.push(
|
|
3121
|
+
prefix + ' step.pointFrom "' + step.pointFrom + '" enum values do not include this step\'s own point "' +
|
|
3122
|
+
step.point + '" — the step could never activate',
|
|
3123
|
+
);
|
|
3124
|
+
}
|
|
3125
|
+
}
|
|
3126
|
+
}
|
|
3127
|
+
|
|
3000
3128
|
for (const contrib of cap.contributions) {
|
|
3001
3129
|
if (contrib.when !== undefined) {
|
|
3002
3130
|
if (typeof contrib.when !== 'string') continue;
|
|
@@ -3605,11 +3733,12 @@ const HOOK_GROUP_KINDS = Object.freeze({
|
|
|
3605
3733
|
* double-report.
|
|
3606
3734
|
*
|
|
3607
3735
|
* KNOWN LIMITATION (#3606): coverage is the UNION across all call sites for a
|
|
3608
|
-
* point in
|
|
3609
|
-
*
|
|
3736
|
+
* point in HOST_LOOP_FILES. Quick's plan:pre planner contribution seam has an
|
|
3737
|
+
* additional generator-owned per-file check. Other consumers outside that
|
|
3738
|
+
* universe (autonomous.md, code-review*.md, audit-milestone.md,
|
|
3610
3739
|
* secure-phase.md, validate-phase.md) are not per-file checked — a narrowed
|
|
3611
|
-
* consumer there passes as long as one host file covers the point.
|
|
3612
|
-
* coverage maps are the tightening path.
|
|
3740
|
+
* consumer there passes as long as one host file covers the point. More
|
|
3741
|
+
* per-file coverage maps are the tightening path.
|
|
3613
3742
|
*
|
|
3614
3743
|
* @param {object} cap Validated capability object.
|
|
3615
3744
|
* @param {Map<string, Set<string>>} wiredKinds Per point, the hook kinds the
|
|
@@ -184,6 +184,7 @@ function setCapabilityState(cwd, runtimeConfigDir, desired, opts) {
|
|
|
184
184
|
};
|
|
185
185
|
}
|
|
186
186
|
// ── Step 4: APPLY PASS ────────────────────────────────────────────────────
|
|
187
|
+
let pendingSurfaceForCommit;
|
|
187
188
|
// ── Surface writes ────────────────────────────────────────────────────────
|
|
188
189
|
if (needsSurface && (idsToDisable.length > 0 || idsToEnable.length > 0)) {
|
|
189
190
|
const existing = readSurface(resolvedConfigDir);
|
|
@@ -242,13 +243,19 @@ function setCapabilityState(cwd, runtimeConfigDir, desired, opts) {
|
|
|
242
243
|
}
|
|
243
244
|
}
|
|
244
245
|
if (surfaceChanged) {
|
|
245
|
-
|
|
246
|
+
pendingSurfaceForCommit = pendingSurface;
|
|
246
247
|
}
|
|
247
248
|
}
|
|
248
249
|
// ── Config writes (once, batched) ─────────────────────────────────────────
|
|
249
250
|
if (pendingGateWrites.length > 0) {
|
|
250
251
|
setConfigValues(cwd, pendingGateWrites);
|
|
251
252
|
}
|
|
253
|
+
// State-only callers preserve the existing direct-write behavior. A caller
|
|
254
|
+
// that requests materialization lets applySurface publish the candidate only
|
|
255
|
+
// after every artifact kind has staged and synchronized successfully.
|
|
256
|
+
if (pendingSurfaceForCommit && !opts?.materialize) {
|
|
257
|
+
writeSurface(resolvedConfigDir, pendingSurfaceForCommit);
|
|
258
|
+
}
|
|
252
259
|
// ── Materialize (optional) ────────────────────────────────────────────────
|
|
253
260
|
if (opts?.materialize) {
|
|
254
261
|
const { runtime, scope } = opts.materialize;
|
|
@@ -274,9 +281,12 @@ function setCapabilityState(cwd, runtimeConfigDir, desired, opts) {
|
|
|
274
281
|
// folded:issue-1575-agent-descriptor-parity describe block in
|
|
275
282
|
// tests/golden-parity-single-source.test.cjs).
|
|
276
283
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
277
|
-
applySurface(resolvedConfigDir, layout, manifest, undefined, registry,
|
|
278
|
-
? {
|
|
279
|
-
|
|
284
|
+
applySurface(resolvedConfigDir, layout, manifest, undefined, registry, {
|
|
285
|
+
...(pendingSurfaceForCommit ? { surfaceState: pendingSurfaceForCommit } : {}),
|
|
286
|
+
...(opts.materialize.resolveAttribution
|
|
287
|
+
? { resolveAttribution: opts.materialize.resolveAttribution }
|
|
288
|
+
: {}),
|
|
289
|
+
});
|
|
280
290
|
}
|
|
281
291
|
catch (err) {
|
|
282
292
|
const msg = err instanceof Error ? err.message : String(err);
|