@opengsd/gsd-core 1.7.0 → 1.9.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 +45 -1
- package/README.md +2 -0
- package/agents/gsd-code-fixer.md +1 -1
- package/agents/gsd-codebase-mapper.md +1 -1
- package/agents/gsd-debug-session-manager.md +78 -4
- package/agents/gsd-debugger.md +87 -29
- package/agents/gsd-executor.md +49 -9
- package/agents/gsd-intel-updater.md +3 -3
- package/agents/gsd-phase-researcher.md +4 -2
- package/agents/gsd-plan-checker.md +20 -0
- package/agents/gsd-planner.md +44 -59
- package/agents/gsd-project-researcher.md +2 -2
- package/agents/gsd-ui-auditor.md +0 -40
- package/agents/gsd-verifier.md +2 -2
- package/bin/install.js +1338 -135
- package/commands/gsd/ai-integration-phase.md +1 -1
- package/commands/gsd/mempalace-capture.md +9 -5
- package/commands/gsd/new-milestone.md +1 -1
- package/commands/gsd/plan-phase.md +5 -3
- package/commands/gsd/plan-review-convergence.md +7 -2
- package/gsd-core/bin/gsd-tools.cjs +2690 -2472
- package/gsd-core/bin/lib/adapter-imperative.cjs +8 -1
- package/gsd-core/bin/lib/agent-command-router.cjs +20 -5
- package/gsd-core/bin/lib/api-coverage.cjs +360 -53
- package/gsd-core/bin/lib/audit.cjs +8 -8
- package/gsd-core/bin/lib/broken-windows.cjs +716 -0
- package/gsd-core/bin/lib/capability-command-router.cjs +733 -0
- package/gsd-core/bin/lib/capability-consent.cjs +40 -1
- package/gsd-core/bin/lib/capability-lifecycle.cjs +58 -0
- package/gsd-core/bin/lib/capability-loader.cjs +23 -1
- package/gsd-core/bin/lib/capability-registry.cjs +1450 -160
- package/gsd-core/bin/lib/capability-trust.cjs +468 -33
- package/gsd-core/bin/lib/capability-validator.cjs +882 -6
- package/gsd-core/bin/lib/capability-writer.cjs +6 -1
- package/gsd-core/bin/lib/check-command-router.cjs +140 -27
- package/gsd-core/bin/lib/cjs-command-router-adapter.cjs +15 -0
- package/gsd-core/bin/lib/claude-orchestration-command-router.cjs +209 -31
- package/gsd-core/bin/lib/claude-orchestration.cjs +203 -25
- package/gsd-core/bin/lib/command-aliases.cjs +14 -0
- package/gsd-core/bin/lib/commands.cjs +326 -21
- package/gsd-core/bin/lib/config-loader.cjs +214 -30
- package/gsd-core/bin/lib/config.cjs +158 -22
- package/gsd-core/bin/lib/core-utils.cjs +6 -1
- package/gsd-core/bin/lib/decisions.cjs +32 -8
- package/gsd-core/bin/lib/docs.cjs +6 -0
- package/gsd-core/bin/lib/estimate-cli.cjs +336 -0
- package/gsd-core/bin/lib/external-descriptor-trust.cjs +14 -2
- package/gsd-core/bin/lib/frontmatter.cjs +125 -15
- package/gsd-core/bin/lib/gap-checker.cjs +17 -2
- package/gsd-core/bin/lib/host-integration.cjs +215 -8
- package/gsd-core/bin/lib/init.cjs +155 -66
- package/gsd-core/bin/lib/install-engine.cjs +299 -23
- package/gsd-core/bin/lib/install-profiles.cjs +239 -1
- package/gsd-core/bin/lib/installer-migrations/005-opencode-baseline-commands-dir.cjs +146 -0
- package/gsd-core/bin/lib/installer-migrations/006-pi-extension-cjs-to-js.cjs +91 -0
- package/gsd-core/bin/lib/installer-migrations.cjs +44 -5
- package/gsd-core/bin/lib/markdown-sectionizer.cjs +107 -0
- package/gsd-core/bin/lib/milestone.cjs +248 -14
- package/gsd-core/bin/lib/model-catalog.cjs +69 -4
- package/gsd-core/bin/lib/model-resolver.cjs +189 -7
- package/gsd-core/bin/lib/observability/logger.cjs +7 -2
- package/gsd-core/bin/lib/onboard-projection.cjs +11 -8
- package/gsd-core/bin/lib/phase-command-router.cjs +10 -1
- package/gsd-core/bin/lib/phase-estimation.cjs +398 -0
- package/gsd-core/bin/lib/phase-id.cjs +304 -9
- package/gsd-core/bin/lib/phase.cjs +258 -17
- package/gsd-core/bin/lib/plan-drift-guard.cjs +1 -1
- package/gsd-core/bin/lib/plan-scan.cjs +70 -2
- package/gsd-core/bin/lib/planning-workspace.cjs +9 -2
- package/gsd-core/bin/lib/profile-output.cjs +34 -8
- package/gsd-core/bin/lib/review-lane-descriptor.cjs +927 -0
- package/gsd-core/bin/lib/review-lane-invocation.cjs +348 -0
- package/gsd-core/bin/lib/review-lane-runner.cjs +594 -0
- package/gsd-core/bin/lib/review-reviewer-selection.cjs +114 -32
- package/gsd-core/bin/lib/roadmap-parser.cjs +61 -10
- package/gsd-core/bin/lib/roadmap.cjs +23 -7
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +38 -5
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +23 -9
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +156 -0
- package/gsd-core/bin/lib/runtime-name-policy.cjs +15 -2
- package/gsd-core/bin/lib/smart-entry.cjs +70 -5
- package/gsd-core/bin/lib/state-document.cjs +171 -24
- package/gsd-core/bin/lib/state-transition.cjs +50 -11
- package/gsd-core/bin/lib/state.cjs +206 -32
- package/gsd-core/bin/lib/surface.cjs +51 -9
- package/gsd-core/bin/lib/uat-predicate.cjs +6 -4
- package/gsd-core/bin/lib/uat.cjs +428 -11
- package/gsd-core/bin/lib/ui-consideration-probe.cjs +2 -2
- package/gsd-core/bin/lib/unusable-input.cjs +216 -0
- package/gsd-core/bin/lib/validate.cjs +44 -8
- package/gsd-core/bin/lib/verification.cjs +163 -31
- package/gsd-core/bin/lib/verify.cjs +348 -42
- package/gsd-core/bin/lib/worktree-safety.cjs +360 -15
- package/gsd-core/bin/shared/config-defaults.manifest.json +1 -0
- package/gsd-core/bin/shared/config-schema.manifest.json +4 -15
- package/gsd-core/bin/shared/model-catalog.json +5 -0
- package/gsd-core/bin/shared/runtime-aliases.manifest.json +5 -0
- package/gsd-core/references/api-coverage.md +37 -7
- package/gsd-core/references/checkpoints.md +1 -1
- package/gsd-core/references/common-bug-patterns.md +13 -0
- package/gsd-core/references/context-budget.md +40 -0
- package/gsd-core/references/debugger-bug-taxonomy.md +111 -0
- package/gsd-core/references/debugger-fix-acceptance.md +157 -0
- package/gsd-core/references/debugger-philosophy.md +1 -0
- package/gsd-core/references/debugger-prevention.md +98 -0
- package/gsd-core/references/debugger-rca-branching.md +98 -0
- package/gsd-core/references/debugger-repro-hardening.md +130 -0
- package/gsd-core/references/debugger-sbfl.md +110 -0
- package/gsd-core/references/debugger-semantic-recall.md +81 -0
- package/gsd-core/references/execute-phase-quota-recovery.md +55 -0
- package/gsd-core/references/execute-phase-requirement-revert.md +8 -0
- package/gsd-core/references/execute-phase-response-language.md +7 -0
- package/gsd-core/references/gate-prompts.md +6 -3
- package/gsd-core/references/model-profile-resolution.md +64 -13
- package/gsd-core/references/offer-next.md +88 -0
- package/gsd-core/references/planner-antipatterns.md +6 -0
- package/gsd-core/references/planner-mvp-mode.md +12 -13
- package/gsd-core/references/planner-preconditions.md +156 -0
- package/gsd-core/references/planner-reversibility.md +132 -0
- package/gsd-core/references/planning-config.md +2 -1
- package/gsd-core/references/reviewer-instances.md +28 -19
- package/gsd-core/references/runtime-aware-dispatch.md +42 -0
- package/gsd-core/references/skeleton-template.md +1 -1
- package/gsd-core/references/thinking-models-planning.md +3 -1
- package/gsd-core/references/ui-consideration-probe.md +2 -2
- package/gsd-core/references/worktree-branch-check.md +4 -4
- package/gsd-core/templates/DEBUG.md +5 -3
- package/gsd-core/templates/summary-minimal.md +4 -0
- package/gsd-core/templates/summary-standard.md +4 -0
- package/gsd-core/templates/summary.md +7 -0
- package/gsd-core/workflows/add-phase.md +2 -0
- package/gsd-core/workflows/add-tests.md +3 -1
- package/gsd-core/workflows/add-todo.md +32 -1
- package/gsd-core/workflows/ai-integration-phase.md +8 -6
- package/gsd-core/workflows/audit-fix.md +6 -2
- package/gsd-core/workflows/audit-milestone.md +8 -0
- package/gsd-core/workflows/autonomous.md +19 -15
- package/gsd-core/workflows/check-todos.md +5 -3
- package/gsd-core/workflows/cleanup.md +7 -1
- package/gsd-core/workflows/code-review-fix.md +14 -6
- package/gsd-core/workflows/code-review.md +93 -24
- package/gsd-core/workflows/complete-milestone.md +3 -0
- package/gsd-core/workflows/debug.md +35 -7
- package/gsd-core/workflows/diagnose-issues.md +5 -1
- package/gsd-core/workflows/discovery-phase.md +7 -0
- package/gsd-core/workflows/discuss-phase/modes/advisor.md +2 -4
- package/gsd-core/workflows/discuss-phase/modes/auto.md +0 -6
- package/gsd-core/workflows/discuss-phase/templates/context.md +16 -2
- package/gsd-core/workflows/discuss-phase-assumptions.md +18 -9
- package/gsd-core/workflows/discuss-phase.md +2 -2
- package/gsd-core/workflows/do.md +7 -1
- package/gsd-core/workflows/docs-update.md +9 -0
- package/gsd-core/workflows/eval-review.md +4 -1
- package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +4 -0
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +160 -0
- package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +4 -4
- package/gsd-core/workflows/execute-phase/steps/regression-gate.md +2 -2
- package/gsd-core/workflows/execute-phase.md +110 -149
- package/gsd-core/workflows/execute-plan.md +20 -8
- package/gsd-core/workflows/explore.md +4 -0
- package/gsd-core/workflows/extract-learnings.md +21 -0
- package/gsd-core/workflows/graduation.md +3 -0
- package/gsd-core/workflows/health.md +7 -1
- package/gsd-core/workflows/help/modes/full.md +9 -5
- package/gsd-core/workflows/import.md +11 -2
- package/gsd-core/workflows/inbox.md +7 -0
- package/gsd-core/workflows/ingest-docs.md +19 -10
- package/gsd-core/workflows/manager.md +3 -1
- package/gsd-core/workflows/map-codebase.md +17 -10
- package/gsd-core/workflows/mvp-phase.md +3 -0
- package/gsd-core/workflows/new-milestone.md +79 -23
- package/gsd-core/workflows/new-project.md +28 -19
- package/gsd-core/workflows/new-workspace.md +3 -1
- package/gsd-core/workflows/next.md +5 -2
- package/gsd-core/workflows/onboard.md +3 -0
- package/gsd-core/workflows/plan-phase.md +56 -51
- package/gsd-core/workflows/plan-review-convergence.md +61 -12
- package/gsd-core/workflows/plant-seed.md +3 -0
- package/gsd-core/workflows/profile-user.md +7 -1
- package/gsd-core/workflows/progress.md +31 -3
- package/gsd-core/workflows/quick.md +33 -10
- package/gsd-core/workflows/remove-workspace.md +3 -0
- package/gsd-core/workflows/review.md +172 -585
- package/gsd-core/workflows/scan.md +10 -2
- package/gsd-core/workflows/secure-phase.md +13 -2
- package/gsd-core/workflows/settings-integrations.md +3 -0
- package/gsd-core/workflows/settings.md +3 -0
- package/gsd-core/workflows/ship.md +88 -11
- package/gsd-core/workflows/sketch.md +3 -0
- package/gsd-core/workflows/smart-entry.md +4 -1
- package/gsd-core/workflows/spike.md +7 -1
- package/gsd-core/workflows/ui-phase.md +11 -2
- package/gsd-core/workflows/ui-review.md +11 -1
- package/gsd-core/workflows/undo.md +7 -0
- package/gsd-core/workflows/update.md +106 -5
- package/gsd-core/workflows/validate-phase.md +13 -2
- package/gsd-core/workflows/verify-phase.md +2 -2
- package/gsd-core/workflows/verify-work.md +15 -4
- package/hooks/dist/gsd-context-monitor.js +27 -9
- package/hooks/dist/gsd-cursor-session-start.js +6 -2
- package/hooks/dist/gsd-cursor-stop.js +6 -2
- package/hooks/dist/gsd-cursor-subagent-start.js +6 -2
- package/hooks/dist/gsd-graphify-update.sh +9 -0
- package/hooks/dist/gsd-phase-boundary.sh +14 -2
- package/hooks/dist/gsd-prompt-guard.js +101 -2
- package/hooks/dist/gsd-read-guard.js +100 -2
- package/hooks/dist/gsd-read-injection-scanner.js +109 -2
- package/hooks/dist/gsd-statusline.js +97 -9
- package/hooks/dist/gsd-workflow-guard.js +110 -6
- package/hooks/dist/gsd-worktree-path-guard.js +132 -8
- package/hooks/dist/lib/cursor-workspace.js +74 -0
- package/hooks/gsd-context-monitor.js +27 -9
- package/hooks/gsd-cursor-session-start.js +6 -2
- package/hooks/gsd-cursor-stop.js +6 -2
- package/hooks/gsd-cursor-subagent-start.js +6 -2
- package/hooks/gsd-graphify-update.sh +9 -0
- package/hooks/gsd-phase-boundary.sh +14 -2
- package/hooks/gsd-prompt-guard.js +101 -2
- package/hooks/gsd-read-guard.js +100 -2
- package/hooks/gsd-read-injection-scanner.js +109 -2
- package/hooks/gsd-statusline.js +97 -9
- package/hooks/gsd-workflow-guard.js +110 -6
- package/hooks/gsd-worktree-path-guard.js +132 -8
- package/hooks/lib/cursor-workspace.js +74 -0
- package/package.json +10 -8
- package/pi/gsd.cjs +34 -3
- package/scripts/changeset/lint.cjs +1 -0
- package/scripts/changeset/parse.cjs +26 -0
- package/scripts/check-coverage-gate.cjs +51 -0
- package/scripts/check-glossary-refs.cjs +244 -0
- package/scripts/ci-rebase-check.cjs +48 -4
- package/scripts/ci-test-scope.cjs +67 -17
- package/scripts/gen-adr-index.cjs +528 -0
- package/scripts/gen-capability-matrix.cjs +26 -2
- package/scripts/gen-capability-registry.cjs +132 -34
- package/scripts/gen-emitted-baseline.cjs +145 -0
- package/scripts/gen-test-timings.cjs +201 -0
- package/scripts/lint-compiled-artifact-sync.cjs +146 -0
- package/scripts/lint-emitted-drift-ack.cjs +149 -0
- package/scripts/lint-fix-has-regression-test.cjs +131 -0
- package/scripts/lint-portable-timeout.cjs +140 -0
- package/scripts/lint-resolution-provenance.cjs +9 -0
- package/scripts/lint-test-file-count.allowlist.json +1 -0
- package/scripts/mutation-matrix.cjs +4 -0
- package/scripts/prompt-injection-scan.sh +6 -0
- package/scripts/registry-schema.cjs +57 -8
- package/scripts/release-notes/conventional-title.cjs +19 -1
- package/scripts/release-notes/format-github-release-notes.cjs +7 -3
- package/scripts/release-tarball-smoke.cjs +18 -11
- package/scripts/run-tests.cjs +420 -58
- package/scripts/workflow-size.cjs +16 -8
- package/skills/gsd-ai-integration-phase/SKILL.md +1 -1
- package/skills/gsd-mempalace-capture/SKILL.md +9 -5
- package/skills/gsd-new-milestone/SKILL.md +1 -1
- package/skills/gsd-plan-phase/SKILL.md +5 -3
- package/skills/gsd-plan-review-convergence/SKILL.md +7 -2
- package/vscode/package.json +1 -1
- package/scripts/gen-golden-install-parity-zcode.cjs +0 -77
- package/scripts/update-size-baseline.cjs +0 -68
|
@@ -399,6 +399,10 @@ function isValidConsentRecord(rec) {
|
|
|
399
399
|
return false;
|
|
400
400
|
if (typeof r['consentedAt'] !== 'string' || !r['consentedAt'])
|
|
401
401
|
return false;
|
|
402
|
+
// Optional (see ConsentRecord.reviewerHost): absent is valid and is the common case. Present but
|
|
403
|
+
// non-string is a corrupt record — reject rather than silently comparing against a non-host.
|
|
404
|
+
if (r['reviewerHost'] !== undefined && typeof r['reviewerHost'] !== 'string')
|
|
405
|
+
return false;
|
|
402
406
|
return true;
|
|
403
407
|
}
|
|
404
408
|
/**
|
|
@@ -645,7 +649,7 @@ function writeConsentStore(gsdHome, store) {
|
|
|
645
649
|
* written. (The OLD code returned a null handle and proceeded unlocked — that is the bug.)
|
|
646
650
|
*/
|
|
647
651
|
function recordProjectConsent(args) {
|
|
648
|
-
const { gsdHome, projectRoot, id, integrity, disclosureSignature, contentHash } = args;
|
|
652
|
+
const { gsdHome, projectRoot, id, integrity, disclosureSignature, contentHash, reviewerHost } = args;
|
|
649
653
|
if (isUnsafeCapabilityId(id)) {
|
|
650
654
|
throw new Error(`Invalid capability id "${String(id)}": must match /^[a-z][a-z0-9-]*$/ (kebab-case, lowercase). ` +
|
|
651
655
|
`Unsafe or non-kebab ids are rejected to keep the consent store prototype-pollution-safe.`);
|
|
@@ -685,6 +689,9 @@ function recordProjectConsent(args) {
|
|
|
685
689
|
disclosureSignature,
|
|
686
690
|
contentHash,
|
|
687
691
|
consentedAt: new Date().toISOString(),
|
|
692
|
+
// Written only when the capability actually declares an egress destination, so a spawn lane
|
|
693
|
+
// or a non-lane capability keeps a byte-identical record shape.
|
|
694
|
+
...(typeof reviewerHost === 'string' && reviewerHost ? { reviewerHost } : {}),
|
|
688
695
|
};
|
|
689
696
|
writeConsentStore(gsdHome, store);
|
|
690
697
|
}
|
|
@@ -730,6 +737,37 @@ function revokeProjectConsent(args) {
|
|
|
730
737
|
releaseConsentLock(lock);
|
|
731
738
|
}
|
|
732
739
|
}
|
|
740
|
+
/**
|
|
741
|
+
* The egress destination a capability's consent was granted against, or `undefined`.
|
|
742
|
+
*
|
|
743
|
+
* ADR-2782 D5 rule 4 (#2799) — read on the INVOCATION path, not only at install, because
|
|
744
|
+
* `hostConfigKey` names a key in `.planning/config.json`: the one consent-bound value that lives
|
|
745
|
+
* outside the SHA-pinned bundle and can be changed by an ordinary pull request with no re-install
|
|
746
|
+
* and no integrity check.
|
|
747
|
+
*
|
|
748
|
+
* `undefined` means "nothing to compare", and the caller MUST treat that as allow, not deny. Two
|
|
749
|
+
* legitimate ways to get it: the capability has no consent record at all (first-party lanes ship
|
|
750
|
+
* inside the SHA-pinned distribution and are never consent-gated), or the record predates this
|
|
751
|
+
* field. Denying on absence would break every existing local-model user on upgrade.
|
|
752
|
+
*
|
|
753
|
+
* Non-throwing: a missing, corrupt, or oversized store yields `undefined` like any other absence.
|
|
754
|
+
*/
|
|
755
|
+
function readConsentedReviewerHost(args) {
|
|
756
|
+
const { gsdHome, projectRoot, id } = args;
|
|
757
|
+
if (isUnsafeCapabilityId(id))
|
|
758
|
+
return undefined;
|
|
759
|
+
try {
|
|
760
|
+
const store = readConsentStore(gsdHome);
|
|
761
|
+
const key = consentKey(realpathProject(projectRoot), id);
|
|
762
|
+
if (!Object.prototype.hasOwnProperty.call(store.records, key))
|
|
763
|
+
return undefined;
|
|
764
|
+
const host = store.records[key].reviewerHost;
|
|
765
|
+
return typeof host === 'string' && host ? host : undefined;
|
|
766
|
+
}
|
|
767
|
+
catch {
|
|
768
|
+
return undefined;
|
|
769
|
+
}
|
|
770
|
+
}
|
|
733
771
|
/**
|
|
734
772
|
* #1459 finding 2 (round 6): TEST-ONLY — override the cumulative bundle entry-count cap and return a
|
|
735
773
|
* restore() that resets it to the production default. Lets a test prove the streaming walk fails closed
|
|
@@ -744,6 +782,7 @@ module.exports = {
|
|
|
744
782
|
consentStorePath,
|
|
745
783
|
bundleContentHash,
|
|
746
784
|
readConsentStore,
|
|
785
|
+
readConsentedReviewerHost,
|
|
747
786
|
hasProjectConsent,
|
|
748
787
|
recordProjectConsent,
|
|
749
788
|
revokeProjectConsent,
|
|
@@ -672,6 +672,59 @@ function warnIfConsentSkipped(opts, id) {
|
|
|
672
672
|
* Best-effort: a consent-store write failure must not turn a successful install/upgrade into a
|
|
673
673
|
* failure (the bundle is already committed) — it is surfaced as a warning, not a throw.
|
|
674
674
|
*/
|
|
675
|
+
/**
|
|
676
|
+
* Resolve an `openai-http` reviewer lane's declared `hostConfigKey` to the destination it currently
|
|
677
|
+
* names, or `undefined` when this capability is not such a lane.
|
|
678
|
+
*
|
|
679
|
+
* Falls back to the lane's declared `defaultHost` when the key is unset, because that is exactly
|
|
680
|
+
* what the invocation path will do — binding the config value while the runtime uses the default
|
|
681
|
+
* would guarantee a mismatch on the very first review.
|
|
682
|
+
*
|
|
683
|
+
* Non-throwing: consent binding is best-effort and must never turn a successful install into a
|
|
684
|
+
* failure. An unresolvable host simply records nothing, which reads as "not bound" and allows.
|
|
685
|
+
*/
|
|
686
|
+
function resolveReviewerEgressHost(opts, manifest) {
|
|
687
|
+
try {
|
|
688
|
+
const reviewer = manifest['reviewer'];
|
|
689
|
+
if (reviewer === null || typeof reviewer !== 'object' || Array.isArray(reviewer))
|
|
690
|
+
return undefined;
|
|
691
|
+
const r = reviewer;
|
|
692
|
+
if (r['transport'] !== 'openai-http')
|
|
693
|
+
return undefined;
|
|
694
|
+
const invoke = r['invoke'];
|
|
695
|
+
if (invoke === null || typeof invoke !== 'object')
|
|
696
|
+
return undefined;
|
|
697
|
+
const inv = invoke;
|
|
698
|
+
const key = typeof inv['hostConfigKey'] === 'string' ? inv['hostConfigKey'] : '';
|
|
699
|
+
const fallback = typeof inv['defaultHost'] === 'string' ? inv['defaultHost'] : '';
|
|
700
|
+
let configured = '';
|
|
701
|
+
if (key) {
|
|
702
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
703
|
+
const cfgLoader = require('./config-loader.cjs');
|
|
704
|
+
const root = projectRootMod.consentProjectRoot(opts.runtimeDir);
|
|
705
|
+
const cfg = cfgLoader.loadConfigResolved ? (cfgLoader.loadConfigResolved(root).config ?? {}) : {};
|
|
706
|
+
let cur = cfg;
|
|
707
|
+
for (const part of key.split('.')) {
|
|
708
|
+
if (cur === null || typeof cur !== 'object') {
|
|
709
|
+
cur = undefined;
|
|
710
|
+
break;
|
|
711
|
+
}
|
|
712
|
+
cur = Object.prototype.hasOwnProperty.call(cur, part)
|
|
713
|
+
? cur[part]
|
|
714
|
+
: undefined;
|
|
715
|
+
}
|
|
716
|
+
if (typeof cur === 'string')
|
|
717
|
+
configured = cur.trim();
|
|
718
|
+
}
|
|
719
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
720
|
+
const { normalizeHost } = require('./review-lane-invocation.cjs');
|
|
721
|
+
const resolved = normalizeHost(configured || fallback);
|
|
722
|
+
return resolved || undefined;
|
|
723
|
+
}
|
|
724
|
+
catch {
|
|
725
|
+
return undefined;
|
|
726
|
+
}
|
|
727
|
+
}
|
|
675
728
|
function bindProjectConsent(opts, id, integrity, manifest) {
|
|
676
729
|
// #1459 IC-07: a project-scope op WITHOUT a consent store cannot bind — warn (then nothing to do).
|
|
677
730
|
if (!shouldBindConsent(opts)) {
|
|
@@ -689,6 +742,11 @@ function bindProjectConsent(opts, id, integrity, manifest) {
|
|
|
689
742
|
integrity,
|
|
690
743
|
disclosureSignature: trustMod.signatureForManifest(manifest),
|
|
691
744
|
contentHash: consentMod.bundleContentHash(capDir(opts.runtimeDir, id)),
|
|
745
|
+
// ADR-2782 D5 rule 1 (#2799): bind the RESOLVED egress destination, not merely the config key
|
|
746
|
+
// that names it. The key lives in `.planning/config.json`, outside the SHA-pinned bundle, so
|
|
747
|
+
// without this the user consents to "wherever that key points" — a promise the bundle hash
|
|
748
|
+
// cannot keep. Phase 5b re-resolves and compares at invocation (rule 4).
|
|
749
|
+
reviewerHost: resolveReviewerEgressHost(opts, manifest),
|
|
692
750
|
});
|
|
693
751
|
}
|
|
694
752
|
catch (err) {
|
|
@@ -426,6 +426,8 @@ function loadRegistry(options = {}) {
|
|
|
426
426
|
// consent the CLI records is the consent the loader checks. The consent store NEVER lives in a repo.
|
|
427
427
|
const gsdHome = options.gsdHome || process.env['GSD_HOME'] || os.homedir();
|
|
428
428
|
const warnings = [];
|
|
429
|
+
// ADR-2782 D4.3 — non-fatal notices for capabilities that are ACCEPTED (see OverlayMeta).
|
|
430
|
+
const diagnostics = [];
|
|
429
431
|
const incompatibleGateCapIds = [];
|
|
430
432
|
const blockedGates = [];
|
|
431
433
|
const commandRoots = {};
|
|
@@ -719,6 +721,26 @@ function loadRegistry(options = {}) {
|
|
|
719
721
|
}
|
|
720
722
|
}
|
|
721
723
|
// Accepted.
|
|
724
|
+
//
|
|
725
|
+
// ADR-2782 D4.3: an unknown field inside a `reviewer` body is IGNORED WITH A
|
|
726
|
+
// WARNING rather than failing validation, so a lane built for a newer GSD
|
|
727
|
+
// degrades to accepted-but-partially-understood instead of being rejected.
|
|
728
|
+
// That case validates cleanly, so without this call it would surface
|
|
729
|
+
// nowhere at runtime — the build-time generator only ever sees first-party
|
|
730
|
+
// in-repo manifests, never an installed third-party overlay. Guarded on
|
|
731
|
+
// presence so an older built validator without the function still loads,
|
|
732
|
+
// and wrapped because the never-crash contract (ADR-1244 D2) outranks a
|
|
733
|
+
// diagnostic: a throwing collector must not cost the user a working lane.
|
|
734
|
+
if (typeof validator.collectReviewerWarnings === 'function') {
|
|
735
|
+
try {
|
|
736
|
+
for (const w of validator.collectReviewerWarnings(cap) || []) {
|
|
737
|
+
diagnostics.push(`${root.scope}:${id}: ${w}`);
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
catch {
|
|
741
|
+
// A diagnostic that cannot be produced is not worth failing an install over.
|
|
742
|
+
}
|
|
743
|
+
}
|
|
722
744
|
overlayCaps.push(cap);
|
|
723
745
|
acceptedIds.add(id);
|
|
724
746
|
for (const s of skills)
|
|
@@ -752,7 +774,7 @@ function loadRegistry(options = {}) {
|
|
|
752
774
|
}
|
|
753
775
|
}
|
|
754
776
|
}
|
|
755
|
-
const meta = { warnings, incompatibleGateCapIds, blockedGates, commandRoots };
|
|
777
|
+
const meta = { warnings, diagnostics, incompatibleGateCapIds, blockedGates, commandRoots };
|
|
756
778
|
if (overlayCaps.length === 0) {
|
|
757
779
|
// Nothing to compose. Return the frozen registry unchanged when there is
|
|
758
780
|
// also nothing to report (identity-stable); otherwise attach diagnostics.
|