@productbrain/cli 0.1.0-beta.72 → 0.1.0-beta.7204
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/README.md +8 -2
- package/dist/__tests__/adapters.test.js +60 -12
- package/dist/__tests__/adapters.test.js.map +1 -1
- package/dist/__tests__/adminConfig.test.d.ts +18 -0
- package/dist/__tests__/adminConfig.test.d.ts.map +1 -0
- package/dist/__tests__/adminConfig.test.js +221 -0
- package/dist/__tests__/adminConfig.test.js.map +1 -0
- package/dist/__tests__/audit.test.js +86 -28
- package/dist/__tests__/audit.test.js.map +1 -1
- package/dist/__tests__/batch-transformations.test.js +2 -26
- package/dist/__tests__/batch-transformations.test.js.map +1 -1
- package/dist/__tests__/canonicalRefs.vocab.test.d.ts +2 -0
- package/dist/__tests__/canonicalRefs.vocab.test.d.ts.map +1 -0
- package/dist/__tests__/canonicalRefs.vocab.test.js +251 -0
- package/dist/__tests__/canonicalRefs.vocab.test.js.map +1 -0
- package/dist/__tests__/capture-receipt-coaching.test.d.ts +2 -0
- package/dist/__tests__/capture-receipt-coaching.test.d.ts.map +1 -0
- package/dist/__tests__/capture-receipt-coaching.test.js +89 -0
- package/dist/__tests__/capture-receipt-coaching.test.js.map +1 -0
- package/dist/__tests__/capture-receipt-spine-floor.test.d.ts +2 -0
- package/dist/__tests__/capture-receipt-spine-floor.test.d.ts.map +1 -0
- package/dist/__tests__/capture-receipt-spine-floor.test.js +45 -0
- package/dist/__tests__/capture-receipt-spine-floor.test.js.map +1 -0
- package/dist/__tests__/capture.test.js +1272 -73
- package/dist/__tests__/capture.test.js.map +1 -1
- package/dist/__tests__/client-binding-guard.test.d.ts +2 -0
- package/dist/__tests__/client-binding-guard.test.d.ts.map +1 -0
- package/dist/__tests__/client-binding-guard.test.js +84 -0
- package/dist/__tests__/client-binding-guard.test.js.map +1 -0
- package/dist/__tests__/coaching-mirror-drift.test.d.ts +2 -0
- package/dist/__tests__/coaching-mirror-drift.test.d.ts.map +1 -0
- package/dist/__tests__/coaching-mirror-drift.test.js +47 -0
- package/dist/__tests__/coaching-mirror-drift.test.js.map +1 -0
- package/dist/__tests__/codex-prep-parity.test.d.ts +2 -0
- package/dist/__tests__/codex-prep-parity.test.d.ts.map +1 -0
- package/dist/__tests__/codex-prep-parity.test.js +107 -0
- package/dist/__tests__/codex-prep-parity.test.js.map +1 -0
- package/dist/__tests__/collection-registry-seed-drift.test.d.ts +2 -0
- package/dist/__tests__/collection-registry-seed-drift.test.d.ts.map +1 -0
- package/dist/__tests__/collection-registry-seed-drift.test.js +81 -0
- package/dist/__tests__/collection-registry-seed-drift.test.js.map +1 -0
- package/dist/__tests__/config-prod-fallthrough.test.d.ts +2 -0
- package/dist/__tests__/config-prod-fallthrough.test.d.ts.map +1 -0
- package/dist/__tests__/config-prod-fallthrough.test.js +93 -0
- package/dist/__tests__/config-prod-fallthrough.test.js.map +1 -0
- package/dist/__tests__/config.test.d.ts +1 -1
- package/dist/__tests__/config.test.js +845 -18
- package/dist/__tests__/config.test.js.map +1 -1
- package/dist/__tests__/constants.test.js +6 -1
- package/dist/__tests__/constants.test.js.map +1 -1
- package/dist/__tests__/constellation.test.js +26 -14
- package/dist/__tests__/constellation.test.js.map +1 -1
- package/dist/__tests__/conversation.test.d.ts +2 -0
- package/dist/__tests__/conversation.test.d.ts.map +1 -0
- package/dist/__tests__/conversation.test.js +113 -0
- package/dist/__tests__/conversation.test.js.map +1 -0
- package/dist/__tests__/entry-formatter.test.d.ts +2 -0
- package/dist/__tests__/entry-formatter.test.d.ts.map +1 -0
- package/dist/__tests__/entry-formatter.test.js +130 -0
- package/dist/__tests__/entry-formatter.test.js.map +1 -0
- package/dist/__tests__/entry-preflight.test.d.ts +2 -0
- package/dist/__tests__/entry-preflight.test.d.ts.map +1 -0
- package/dist/__tests__/entry-preflight.test.js +58 -0
- package/dist/__tests__/entry-preflight.test.js.map +1 -0
- package/dist/__tests__/entryAccept-batch.test.d.ts +2 -0
- package/dist/__tests__/entryAccept-batch.test.d.ts.map +1 -0
- package/dist/__tests__/entryAccept-batch.test.js +305 -0
- package/dist/__tests__/entryAccept-batch.test.js.map +1 -0
- package/dist/__tests__/entryAccept.test.d.ts +2 -0
- package/dist/__tests__/entryAccept.test.d.ts.map +1 -0
- package/dist/__tests__/entryAccept.test.js +433 -0
- package/dist/__tests__/entryAccept.test.js.map +1 -0
- package/dist/__tests__/entryArchive.test.d.ts +2 -0
- package/dist/__tests__/entryArchive.test.d.ts.map +1 -0
- package/dist/__tests__/entryArchive.test.js +35 -0
- package/dist/__tests__/entryArchive.test.js.map +1 -0
- package/dist/__tests__/entryOwn.test.d.ts +2 -0
- package/dist/__tests__/entryOwn.test.d.ts.map +1 -0
- package/dist/__tests__/entryOwn.test.js +50 -0
- package/dist/__tests__/entryOwn.test.js.map +1 -0
- package/dist/__tests__/envelope-contract.test.d.ts +15 -0
- package/dist/__tests__/envelope-contract.test.d.ts.map +1 -0
- package/dist/__tests__/envelope-contract.test.js +154 -0
- package/dist/__tests__/envelope-contract.test.js.map +1 -0
- package/dist/__tests__/errors.test.js +30 -0
- package/dist/__tests__/errors.test.js.map +1 -1
- package/dist/__tests__/gateway-dry-run-timeout.test.d.ts +2 -0
- package/dist/__tests__/gateway-dry-run-timeout.test.d.ts.map +1 -0
- package/dist/__tests__/gateway-dry-run-timeout.test.js +70 -0
- package/dist/__tests__/gateway-dry-run-timeout.test.js.map +1 -0
- package/dist/__tests__/gateway-timeout-body-phase.test.d.ts +2 -0
- package/dist/__tests__/gateway-timeout-body-phase.test.d.ts.map +1 -0
- package/dist/__tests__/gateway-timeout-body-phase.test.js +121 -0
- package/dist/__tests__/gateway-timeout-body-phase.test.js.map +1 -0
- package/dist/__tests__/handshake-augment.test.d.ts +2 -0
- package/dist/__tests__/handshake-augment.test.d.ts.map +1 -0
- package/dist/__tests__/handshake-augment.test.js +422 -0
- package/dist/__tests__/handshake-augment.test.js.map +1 -0
- package/dist/__tests__/handshake-dormancy.test.d.ts +2 -0
- package/dist/__tests__/handshake-dormancy.test.d.ts.map +1 -0
- package/dist/__tests__/handshake-dormancy.test.js +82 -0
- package/dist/__tests__/handshake-dormancy.test.js.map +1 -0
- package/dist/__tests__/handshake-formatter.test.d.ts +2 -0
- package/dist/__tests__/handshake-formatter.test.d.ts.map +1 -0
- package/dist/__tests__/handshake-formatter.test.js +111 -0
- package/dist/__tests__/handshake-formatter.test.js.map +1 -0
- package/dist/__tests__/handshake-preview.test.d.ts +2 -0
- package/dist/__tests__/handshake-preview.test.d.ts.map +1 -0
- package/dist/__tests__/handshake-preview.test.js +1092 -0
- package/dist/__tests__/handshake-preview.test.js.map +1 -0
- package/dist/__tests__/handshake.e2e.test.d.ts +2 -0
- package/dist/__tests__/handshake.e2e.test.d.ts.map +1 -0
- package/dist/__tests__/handshake.e2e.test.js +485 -0
- package/dist/__tests__/handshake.e2e.test.js.map +1 -0
- package/dist/__tests__/handshake.test.js +828 -4
- package/dist/__tests__/handshake.test.js.map +1 -1
- package/dist/__tests__/health-gap-kinds-drift.test.d.ts +2 -0
- package/dist/__tests__/health-gap-kinds-drift.test.d.ts.map +1 -0
- package/dist/__tests__/health-gap-kinds-drift.test.js +42 -0
- package/dist/__tests__/health-gap-kinds-drift.test.js.map +1 -0
- package/dist/__tests__/hook-intents.test.d.ts +2 -0
- package/dist/__tests__/hook-intents.test.d.ts.map +1 -0
- package/dist/__tests__/hook-intents.test.js +184 -0
- package/dist/__tests__/hook-intents.test.js.map +1 -0
- package/dist/__tests__/ingest.test.js +9 -0
- package/dist/__tests__/ingest.test.js.map +1 -1
- package/dist/__tests__/init.test.js +51 -14
- package/dist/__tests__/init.test.js.map +1 -1
- package/dist/__tests__/kernel-value-sets-drift.test.d.ts +2 -0
- package/dist/__tests__/kernel-value-sets-drift.test.d.ts.map +1 -0
- package/dist/__tests__/kernel-value-sets-drift.test.js +46 -0
- package/dist/__tests__/kernel-value-sets-drift.test.js.map +1 -0
- package/dist/__tests__/kernel-value-sets-generator.test.d.ts +2 -0
- package/dist/__tests__/kernel-value-sets-generator.test.d.ts.map +1 -0
- package/dist/__tests__/kernel-value-sets-generator.test.js +108 -0
- package/dist/__tests__/kernel-value-sets-generator.test.js.map +1 -0
- package/dist/__tests__/manifest.test.d.ts +6 -0
- package/dist/__tests__/manifest.test.d.ts.map +1 -0
- package/dist/__tests__/manifest.test.js +255 -0
- package/dist/__tests__/manifest.test.js.map +1 -0
- package/dist/__tests__/method-publish-coherency.test.d.ts +9 -0
- package/dist/__tests__/method-publish-coherency.test.d.ts.map +1 -0
- package/dist/__tests__/method-publish-coherency.test.js +71 -0
- package/dist/__tests__/method-publish-coherency.test.js.map +1 -0
- package/dist/__tests__/method-registry.integration.test.d.ts +6 -0
- package/dist/__tests__/method-registry.integration.test.d.ts.map +1 -0
- package/dist/__tests__/method-registry.integration.test.js +17 -0
- package/dist/__tests__/method-registry.integration.test.js.map +1 -0
- package/dist/__tests__/method-registry.test.d.ts +12 -0
- package/dist/__tests__/method-registry.test.d.ts.map +1 -0
- package/dist/__tests__/method-registry.test.js +86 -0
- package/dist/__tests__/method-registry.test.js.map +1 -0
- package/dist/__tests__/migrate-setup-session-refusal.test.d.ts +2 -0
- package/dist/__tests__/migrate-setup-session-refusal.test.d.ts.map +1 -0
- package/dist/__tests__/migrate-setup-session-refusal.test.js +65 -0
- package/dist/__tests__/migrate-setup-session-refusal.test.js.map +1 -0
- package/dist/__tests__/missingPin.test.d.ts +11 -0
- package/dist/__tests__/missingPin.test.d.ts.map +1 -0
- package/dist/__tests__/missingPin.test.js +233 -0
- package/dist/__tests__/missingPin.test.js.map +1 -0
- package/dist/__tests__/notice-marker.test.d.ts +2 -0
- package/dist/__tests__/notice-marker.test.d.ts.map +1 -0
- package/dist/__tests__/notice-marker.test.js +176 -0
- package/dist/__tests__/notice-marker.test.js.map +1 -0
- package/dist/__tests__/onboarding-path-b.test.js +4 -4
- package/dist/__tests__/onboarding-path-b.test.js.map +1 -1
- package/dist/__tests__/orient.test.js +489 -11
- package/dist/__tests__/orient.test.js.map +1 -1
- package/dist/__tests__/perimeter.test.d.ts +2 -0
- package/dist/__tests__/perimeter.test.d.ts.map +1 -0
- package/dist/__tests__/perimeter.test.js +165 -0
- package/dist/__tests__/perimeter.test.js.map +1 -0
- package/dist/__tests__/personal-layer.test.d.ts +11 -0
- package/dist/__tests__/personal-layer.test.d.ts.map +1 -0
- package/dist/__tests__/personal-layer.test.js +268 -0
- package/dist/__tests__/personal-layer.test.js.map +1 -0
- package/dist/__tests__/preview-key-refresh.test.d.ts +2 -0
- package/dist/__tests__/preview-key-refresh.test.d.ts.map +1 -0
- package/dist/__tests__/preview-key-refresh.test.js +126 -0
- package/dist/__tests__/preview-key-refresh.test.js.map +1 -0
- package/dist/__tests__/profiles.test.js +613 -5
- package/dist/__tests__/profiles.test.js.map +1 -1
- package/dist/__tests__/proof-run.test.d.ts +2 -0
- package/dist/__tests__/proof-run.test.d.ts.map +1 -0
- package/dist/__tests__/proof-run.test.js +255 -0
- package/dist/__tests__/proof-run.test.js.map +1 -0
- package/dist/__tests__/proposals.test.js +1 -1
- package/dist/__tests__/proposals.test.js.map +1 -1
- package/dist/__tests__/rate-limit-resilience.test.d.ts +7 -0
- package/dist/__tests__/rate-limit-resilience.test.d.ts.map +1 -0
- package/dist/__tests__/rate-limit-resilience.test.js +209 -0
- package/dist/__tests__/rate-limit-resilience.test.js.map +1 -0
- package/dist/__tests__/read-target-notice.test.d.ts +2 -0
- package/dist/__tests__/read-target-notice.test.d.ts.map +1 -0
- package/dist/__tests__/read-target-notice.test.js +129 -0
- package/dist/__tests__/read-target-notice.test.js.map +1 -0
- package/dist/__tests__/relate.test.js +246 -2
- package/dist/__tests__/relate.test.js.map +1 -1
- package/dist/__tests__/repo-detect.test.js +9 -14
- package/dist/__tests__/repo-detect.test.js.map +1 -1
- package/dist/__tests__/reportedProfile.test.d.ts +2 -0
- package/dist/__tests__/reportedProfile.test.d.ts.map +1 -0
- package/dist/__tests__/reportedProfile.test.js +328 -0
- package/dist/__tests__/reportedProfile.test.js.map +1 -0
- package/dist/__tests__/restore.test.d.ts +2 -0
- package/dist/__tests__/restore.test.d.ts.map +1 -0
- package/dist/__tests__/restore.test.js +85 -0
- package/dist/__tests__/restore.test.js.map +1 -0
- package/dist/__tests__/route-latency-budget.test.d.ts +2 -0
- package/dist/__tests__/route-latency-budget.test.d.ts.map +1 -0
- package/dist/__tests__/route-latency-budget.test.js +103 -0
- package/dist/__tests__/route-latency-budget.test.js.map +1 -0
- package/dist/__tests__/runner.test.js +59 -44
- package/dist/__tests__/runner.test.js.map +1 -1
- package/dist/__tests__/session-binding-refusal-tenant.test.d.ts +2 -0
- package/dist/__tests__/session-binding-refusal-tenant.test.d.ts.map +1 -0
- package/dist/__tests__/session-binding-refusal-tenant.test.js +112 -0
- package/dist/__tests__/session-binding-refusal-tenant.test.js.map +1 -0
- package/dist/__tests__/session-close-loop.test.d.ts +2 -0
- package/dist/__tests__/session-close-loop.test.d.ts.map +1 -0
- package/dist/__tests__/session-close-loop.test.js +215 -0
- package/dist/__tests__/session-close-loop.test.js.map +1 -0
- package/dist/__tests__/session-label.test.d.ts +2 -0
- package/dist/__tests__/session-label.test.d.ts.map +1 -0
- package/dist/__tests__/session-label.test.js +46 -0
- package/dist/__tests__/session-label.test.js.map +1 -0
- package/dist/__tests__/session-list-show.test.d.ts +2 -0
- package/dist/__tests__/session-list-show.test.d.ts.map +1 -0
- package/dist/__tests__/session-list-show.test.js +174 -0
- package/dist/__tests__/session-list-show.test.js.map +1 -0
- package/dist/__tests__/session-reset.test.d.ts +2 -0
- package/dist/__tests__/session-reset.test.d.ts.map +1 -0
- package/dist/__tests__/session-reset.test.js +138 -0
- package/dist/__tests__/session-reset.test.js.map +1 -0
- package/dist/__tests__/session-resume-backstop.test.d.ts +2 -0
- package/dist/__tests__/session-resume-backstop.test.d.ts.map +1 -0
- package/dist/__tests__/session-resume-backstop.test.js +107 -0
- package/dist/__tests__/session-resume-backstop.test.js.map +1 -0
- package/dist/__tests__/session-start-key-refresh.test.d.ts +2 -0
- package/dist/__tests__/session-start-key-refresh.test.d.ts.map +1 -0
- package/dist/__tests__/session-start-key-refresh.test.js +191 -0
- package/dist/__tests__/session-start-key-refresh.test.js.map +1 -0
- package/dist/__tests__/session-state-machine.test.js +235 -10
- package/dist/__tests__/session-state-machine.test.js.map +1 -1
- package/dist/__tests__/session-switch.test.d.ts +2 -0
- package/dist/__tests__/session-switch.test.d.ts.map +1 -0
- package/dist/__tests__/session-switch.test.js +267 -0
- package/dist/__tests__/session-switch.test.js.map +1 -0
- package/dist/__tests__/session-touch.test.js +6 -1
- package/dist/__tests__/session-touch.test.js.map +1 -1
- package/dist/__tests__/sessionBinding.test.d.ts +2 -0
- package/dist/__tests__/sessionBinding.test.d.ts.map +1 -0
- package/dist/__tests__/sessionBinding.test.js +118 -0
- package/dist/__tests__/sessionBinding.test.js.map +1 -0
- package/dist/__tests__/sessionByIdLookup.test.d.ts +2 -0
- package/dist/__tests__/sessionByIdLookup.test.d.ts.map +1 -0
- package/dist/__tests__/sessionByIdLookup.test.js +63 -0
- package/dist/__tests__/sessionByIdLookup.test.js.map +1 -0
- package/dist/__tests__/setup-ingest.test.d.ts +2 -0
- package/dist/__tests__/setup-ingest.test.d.ts.map +1 -0
- package/dist/__tests__/setup-ingest.test.js +71 -0
- package/dist/__tests__/setup-ingest.test.js.map +1 -0
- package/dist/__tests__/setup-resolver.test.d.ts +14 -0
- package/dist/__tests__/setup-resolver.test.d.ts.map +1 -0
- package/dist/__tests__/setup-resolver.test.js +228 -0
- package/dist/__tests__/setup-resolver.test.js.map +1 -0
- package/dist/__tests__/setupShFallbackWarning.test.d.ts +2 -0
- package/dist/__tests__/setupShFallbackWarning.test.d.ts.map +1 -0
- package/dist/__tests__/setupShFallbackWarning.test.js +15 -0
- package/dist/__tests__/setupShFallbackWarning.test.js.map +1 -0
- package/dist/__tests__/skill-vocabulary.test.d.ts +21 -0
- package/dist/__tests__/skill-vocabulary.test.d.ts.map +1 -0
- package/dist/__tests__/skill-vocabulary.test.js +192 -0
- package/dist/__tests__/skill-vocabulary.test.js.map +1 -0
- package/dist/__tests__/state.test.d.ts +6 -0
- package/dist/__tests__/state.test.d.ts.map +1 -0
- package/dist/__tests__/state.test.js +117 -0
- package/dist/__tests__/state.test.js.map +1 -0
- package/dist/__tests__/strip.test.js +57 -3
- package/dist/__tests__/strip.test.js.map +1 -1
- package/dist/__tests__/surfaces.test.d.ts +2 -0
- package/dist/__tests__/surfaces.test.d.ts.map +1 -0
- package/dist/__tests__/surfaces.test.js +46 -0
- package/dist/__tests__/surfaces.test.js.map +1 -0
- package/dist/__tests__/tenant-notice-write-path.test.d.ts +2 -0
- package/dist/__tests__/tenant-notice-write-path.test.d.ts.map +1 -0
- package/dist/__tests__/tenant-notice-write-path.test.js +169 -0
- package/dist/__tests__/tenant-notice-write-path.test.js.map +1 -0
- package/dist/__tests__/update-check.test.d.ts +2 -0
- package/dist/__tests__/update-check.test.d.ts.map +1 -0
- package/dist/__tests__/update-check.test.js +215 -0
- package/dist/__tests__/update-check.test.js.map +1 -0
- package/dist/__tests__/update.test.js +443 -5
- package/dist/__tests__/update.test.js.map +1 -1
- package/dist/__tests__/upgrade-runner.test.d.ts +2 -0
- package/dist/__tests__/upgrade-runner.test.d.ts.map +1 -0
- package/dist/__tests__/upgrade-runner.test.js +54 -0
- package/dist/__tests__/upgrade-runner.test.js.map +1 -0
- package/dist/__tests__/upgrade.test.d.ts +2 -0
- package/dist/__tests__/upgrade.test.d.ts.map +1 -0
- package/dist/__tests__/upgrade.test.js +56 -0
- package/dist/__tests__/upgrade.test.js.map +1 -0
- package/dist/__tests__/verify-formatter.test.d.ts +2 -0
- package/dist/__tests__/verify-formatter.test.d.ts.map +1 -0
- package/dist/__tests__/verify-formatter.test.js +85 -0
- package/dist/__tests__/verify-formatter.test.js.map +1 -0
- package/dist/__tests__/vocabulary-leak.test.d.ts +39 -0
- package/dist/__tests__/vocabulary-leak.test.d.ts.map +1 -0
- package/dist/__tests__/vocabulary-leak.test.js +540 -0
- package/dist/__tests__/vocabulary-leak.test.js.map +1 -0
- package/dist/__tests__/workspace.test.js +32 -12
- package/dist/__tests__/workspace.test.js.map +1 -1
- package/dist/__tests__/workspaceNotice.test.d.ts +2 -0
- package/dist/__tests__/workspaceNotice.test.d.ts.map +1 -0
- package/dist/__tests__/workspaceNotice.test.js +571 -0
- package/dist/__tests__/workspaceNotice.test.js.map +1 -0
- package/dist/commands/__tests__/connect-handoff.test.d.ts +11 -0
- package/dist/commands/__tests__/connect-handoff.test.d.ts.map +1 -0
- package/dist/commands/__tests__/connect-handoff.test.js +111 -0
- package/dist/commands/__tests__/connect-handoff.test.js.map +1 -0
- package/dist/commands/__tests__/quality.test.d.ts +2 -0
- package/dist/commands/__tests__/quality.test.d.ts.map +1 -0
- package/dist/commands/__tests__/quality.test.js +156 -0
- package/dist/commands/__tests__/quality.test.js.map +1 -0
- package/dist/commands/__tests__/rework.test.d.ts +2 -0
- package/dist/commands/__tests__/rework.test.d.ts.map +1 -0
- package/dist/commands/__tests__/rework.test.js +149 -0
- package/dist/commands/__tests__/rework.test.js.map +1 -0
- package/dist/commands/__tests__/setup-detect-surfaces.test.d.ts +15 -0
- package/dist/commands/__tests__/setup-detect-surfaces.test.d.ts.map +1 -0
- package/dist/commands/__tests__/setup-detect-surfaces.test.js +149 -0
- package/dist/commands/__tests__/setup-detect-surfaces.test.js.map +1 -0
- package/dist/commands/__tests__/setup-state.test.d.ts +2 -0
- package/dist/commands/__tests__/setup-state.test.d.ts.map +1 -0
- package/dist/commands/__tests__/setup-state.test.js +194 -0
- package/dist/commands/__tests__/setup-state.test.js.map +1 -0
- package/dist/commands/__tests__/tensionsList.test.d.ts +2 -0
- package/dist/commands/__tests__/tensionsList.test.d.ts.map +1 -0
- package/dist/commands/__tests__/tensionsList.test.js +63 -0
- package/dist/commands/__tests__/tensionsList.test.js.map +1 -0
- package/dist/commands/accept-policy.d.ts +10 -0
- package/dist/commands/accept-policy.d.ts.map +1 -0
- package/dist/commands/accept-policy.js +107 -0
- package/dist/commands/accept-policy.js.map +1 -0
- package/dist/commands/accept.d.ts.map +1 -1
- package/dist/commands/accept.js +1 -1
- package/dist/commands/accept.js.map +1 -1
- package/dist/commands/admin/cockpit.d.ts +2 -12
- package/dist/commands/admin/cockpit.d.ts.map +1 -1
- package/dist/commands/admin/cockpit.js +17 -15
- package/dist/commands/admin/cockpit.js.map +1 -1
- package/dist/commands/admin/index.d.ts +49 -0
- package/dist/commands/admin/index.d.ts.map +1 -1
- package/dist/commands/admin/index.js +145 -29
- package/dist/commands/admin/index.js.map +1 -1
- package/dist/commands/admin/index.test.d.ts +2 -0
- package/dist/commands/admin/index.test.d.ts.map +1 -0
- package/dist/commands/admin/index.test.js +84 -0
- package/dist/commands/admin/index.test.js.map +1 -0
- package/dist/commands/admin/inspect.js +1 -1
- package/dist/commands/admin/inspect.js.map +1 -1
- package/dist/commands/admin/manage.d.ts.map +1 -1
- package/dist/commands/admin/manage.js +188 -2
- package/dist/commands/admin/manage.js.map +1 -1
- package/dist/commands/admin/manage.test.d.ts +16 -0
- package/dist/commands/admin/manage.test.d.ts.map +1 -0
- package/dist/commands/admin/manage.test.js +171 -0
- package/dist/commands/admin/manage.test.js.map +1 -0
- package/dist/commands/admin/probe.d.ts +75 -0
- package/dist/commands/admin/probe.d.ts.map +1 -0
- package/dist/commands/admin/probe.js +224 -0
- package/dist/commands/admin/probe.js.map +1 -0
- package/dist/commands/admin/probe.test.d.ts +2 -0
- package/dist/commands/admin/probe.test.d.ts.map +1 -0
- package/dist/commands/admin/probe.test.js +193 -0
- package/dist/commands/admin/probe.test.js.map +1 -0
- package/dist/commands/admin/run.d.ts +43 -0
- package/dist/commands/admin/run.d.ts.map +1 -0
- package/dist/commands/admin/run.js +78 -0
- package/dist/commands/admin/run.js.map +1 -0
- package/dist/commands/admin/run.test.d.ts +18 -0
- package/dist/commands/admin/run.test.d.ts.map +1 -0
- package/dist/commands/admin/run.test.js +168 -0
- package/dist/commands/admin/run.test.js.map +1 -0
- package/dist/commands/admin/seed.d.ts +32 -3
- package/dist/commands/admin/seed.d.ts.map +1 -1
- package/dist/commands/admin/seed.js +312 -83
- package/dist/commands/admin/seed.js.map +1 -1
- package/dist/commands/admin/seed.test.d.ts +4 -0
- package/dist/commands/admin/seed.test.d.ts.map +1 -1
- package/dist/commands/admin/seed.test.js +33 -7
- package/dist/commands/admin/seed.test.js.map +1 -1
- package/dist/commands/admin/seedRegistryEntries.generated.d.ts +14 -0
- package/dist/commands/admin/seedRegistryEntries.generated.d.ts.map +1 -0
- package/dist/commands/admin/seedRegistryEntries.generated.js +126 -0
- package/dist/commands/admin/seedRegistryEntries.generated.js.map +1 -0
- package/dist/commands/admin/seedRegistryEntries.test.d.ts +13 -0
- package/dist/commands/admin/seedRegistryEntries.test.d.ts.map +1 -0
- package/dist/commands/admin/seedRegistryEntries.test.js +93 -0
- package/dist/commands/admin/seedRegistryEntries.test.js.map +1 -0
- package/dist/commands/admin/seedRowType.d.ts +22 -0
- package/dist/commands/admin/seedRowType.d.ts.map +1 -0
- package/dist/commands/admin/seedRowType.js +2 -0
- package/dist/commands/admin/seedRowType.js.map +1 -0
- package/dist/commands/admin/seedStatusColor.d.ts +9 -0
- package/dist/commands/admin/seedStatusColor.d.ts.map +1 -0
- package/dist/commands/admin/seedStatusColor.js +18 -0
- package/dist/commands/admin/seedStatusColor.js.map +1 -0
- package/dist/commands/admin/seedStatusColor.test.d.ts +2 -0
- package/dist/commands/admin/seedStatusColor.test.d.ts.map +1 -0
- package/dist/commands/admin/seedStatusColor.test.js +25 -0
- package/dist/commands/admin/seedStatusColor.test.js.map +1 -0
- package/dist/commands/audit.d.ts +2 -2
- package/dist/commands/audit.d.ts.map +1 -1
- package/dist/commands/audit.js +52 -6
- package/dist/commands/audit.js.map +1 -1
- package/dist/commands/brief.d.ts.map +1 -1
- package/dist/commands/brief.js +24 -2
- package/dist/commands/brief.js.map +1 -1
- package/dist/commands/capture.d.ts +15 -8
- package/dist/commands/capture.d.ts.map +1 -1
- package/dist/commands/capture.js +243 -247
- package/dist/commands/capture.js.map +1 -1
- package/dist/commands/chain-walk.d.ts.map +1 -1
- package/dist/commands/chain-walk.js.map +1 -1
- package/dist/commands/changes.d.ts.map +1 -1
- package/dist/commands/changes.js.map +1 -1
- package/dist/commands/codex-prep.d.ts +12 -1
- package/dist/commands/codex-prep.d.ts.map +1 -1
- package/dist/commands/codex-prep.js +18 -84
- package/dist/commands/codex-prep.js.map +1 -1
- package/dist/commands/collections.d.ts.map +1 -1
- package/dist/commands/collections.js.map +1 -1
- package/dist/commands/conflicts.d.ts +40 -0
- package/dist/commands/conflicts.d.ts.map +1 -0
- package/dist/commands/conflicts.js +267 -0
- package/dist/commands/conflicts.js.map +1 -0
- package/dist/commands/conflicts.test.d.ts +2 -0
- package/dist/commands/conflicts.test.d.ts.map +1 -0
- package/dist/commands/conflicts.test.js +219 -0
- package/dist/commands/conflicts.test.js.map +1 -0
- package/dist/commands/connect-config.test.d.ts +2 -0
- package/dist/commands/connect-config.test.d.ts.map +1 -0
- package/dist/commands/connect-config.test.js +44 -0
- package/dist/commands/connect-config.test.js.map +1 -0
- package/dist/commands/connect-context.d.ts +57 -0
- package/dist/commands/connect-context.d.ts.map +1 -0
- package/dist/commands/connect-context.js +80 -0
- package/dist/commands/connect-context.js.map +1 -0
- package/dist/commands/connect-context.test.d.ts +2 -0
- package/dist/commands/connect-context.test.d.ts.map +1 -0
- package/dist/commands/connect-context.test.js +143 -0
- package/dist/commands/connect-context.test.js.map +1 -0
- package/dist/commands/connect-handoff.d.ts +51 -0
- package/dist/commands/connect-handoff.d.ts.map +1 -0
- package/dist/commands/connect-handoff.js +70 -0
- package/dist/commands/connect-handoff.js.map +1 -0
- package/dist/commands/connect-integration.test.js +58 -35
- package/dist/commands/connect-integration.test.js.map +1 -1
- package/dist/commands/connect-legacy-migration.test.d.ts +2 -0
- package/dist/commands/connect-legacy-migration.test.d.ts.map +1 -0
- package/dist/commands/connect-legacy-migration.test.js +109 -0
- package/dist/commands/connect-legacy-migration.test.js.map +1 -0
- package/dist/commands/connect-screens.d.ts +33 -0
- package/dist/commands/connect-screens.d.ts.map +1 -0
- package/dist/commands/connect-screens.js +143 -0
- package/dist/commands/connect-screens.js.map +1 -0
- package/dist/commands/connect.d.ts +27 -6
- package/dist/commands/connect.d.ts.map +1 -1
- package/dist/commands/connect.js +252 -115
- package/dist/commands/connect.js.map +1 -1
- package/dist/commands/connect.test.js +348 -7
- package/dist/commands/connect.test.js.map +1 -1
- package/dist/commands/constellation.d.ts.map +1 -1
- package/dist/commands/constellation.js.map +1 -1
- package/dist/commands/context.d.ts.map +1 -1
- package/dist/commands/context.js.map +1 -1
- package/dist/commands/cross-cut.d.ts.map +1 -1
- package/dist/commands/cross-cut.js.map +1 -1
- package/dist/commands/direction.d.ts +10 -0
- package/dist/commands/direction.d.ts.map +1 -0
- package/dist/commands/direction.js +79 -0
- package/dist/commands/direction.js.map +1 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +173 -38
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/doctor.test.js +352 -6
- package/dist/commands/doctor.test.js.map +1 -1
- package/dist/commands/entryAccept.d.ts +24 -0
- package/dist/commands/entryAccept.d.ts.map +1 -0
- package/dist/commands/entryAccept.js +282 -0
- package/dist/commands/entryAccept.js.map +1 -0
- package/dist/commands/entryArchive.d.ts +8 -0
- package/dist/commands/entryArchive.d.ts.map +1 -0
- package/dist/commands/entryArchive.js +37 -0
- package/dist/commands/entryArchive.js.map +1 -0
- package/dist/commands/entryOwn.d.ts +5 -0
- package/dist/commands/entryOwn.d.ts.map +1 -0
- package/dist/commands/entryOwn.js +17 -0
- package/dist/commands/entryOwn.js.map +1 -0
- package/dist/commands/entryPreflight.d.ts +8 -0
- package/dist/commands/entryPreflight.d.ts.map +1 -0
- package/dist/commands/entryPreflight.js +48 -0
- package/dist/commands/entryPreflight.js.map +1 -0
- package/dist/commands/feedback.d.ts +36 -0
- package/dist/commands/feedback.d.ts.map +1 -0
- package/dist/commands/feedback.js +193 -0
- package/dist/commands/feedback.js.map +1 -0
- package/dist/commands/feedback.test.d.ts +2 -0
- package/dist/commands/feedback.test.d.ts.map +1 -0
- package/dist/commands/feedback.test.js +125 -0
- package/dist/commands/feedback.test.js.map +1 -0
- package/dist/commands/fields.d.ts.map +1 -1
- package/dist/commands/fields.js +1 -1
- package/dist/commands/fields.js.map +1 -1
- package/dist/commands/files.d.ts +26 -0
- package/dist/commands/files.d.ts.map +1 -0
- package/dist/commands/files.js +160 -0
- package/dist/commands/files.js.map +1 -0
- package/dist/commands/files.test.d.ts +2 -0
- package/dist/commands/files.test.d.ts.map +1 -0
- package/dist/commands/files.test.js +278 -0
- package/dist/commands/files.test.js.map +1 -0
- package/dist/commands/handshake.d.ts +78 -7
- package/dist/commands/handshake.d.ts.map +1 -1
- package/dist/commands/handshake.js +1536 -101
- package/dist/commands/handshake.js.map +1 -1
- package/dist/commands/handshakeCursorSkillCleanup.d.ts +36 -0
- package/dist/commands/handshakeCursorSkillCleanup.d.ts.map +1 -0
- package/dist/commands/handshakeCursorSkillCleanup.js +110 -0
- package/dist/commands/handshakeCursorSkillCleanup.js.map +1 -0
- package/dist/commands/handshakeDriftClassification.d.ts +33 -0
- package/dist/commands/handshakeDriftClassification.d.ts.map +1 -0
- package/dist/commands/handshakeDriftClassification.js +62 -0
- package/dist/commands/handshakeDriftClassification.js.map +1 -0
- package/dist/commands/history.d.ts +30 -0
- package/dist/commands/history.d.ts.map +1 -0
- package/dist/commands/history.js +62 -0
- package/dist/commands/history.js.map +1 -0
- package/dist/commands/history.test.d.ts +2 -0
- package/dist/commands/history.test.d.ts.map +1 -0
- package/dist/commands/history.test.js +106 -0
- package/dist/commands/history.test.js.map +1 -0
- package/dist/commands/ingest.d.ts.map +1 -1
- package/dist/commands/ingest.js +9 -0
- package/dist/commands/ingest.js.map +1 -1
- package/dist/commands/init.d.ts +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +20 -17
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/method.d.ts +97 -0
- package/dist/commands/method.d.ts.map +1 -0
- package/dist/commands/method.js +773 -0
- package/dist/commands/method.js.map +1 -0
- package/dist/commands/migrate-setup.d.ts +18 -0
- package/dist/commands/migrate-setup.d.ts.map +1 -0
- package/dist/commands/migrate-setup.js +162 -0
- package/dist/commands/migrate-setup.js.map +1 -0
- package/dist/commands/organisation.d.ts +17 -0
- package/dist/commands/organisation.d.ts.map +1 -0
- package/dist/commands/organisation.js +201 -0
- package/dist/commands/organisation.js.map +1 -0
- package/dist/commands/organisation.test.d.ts +2 -0
- package/dist/commands/organisation.test.d.ts.map +1 -0
- package/dist/commands/organisation.test.js +204 -0
- package/dist/commands/organisation.test.js.map +1 -0
- package/dist/commands/organisationHierarchy.d.ts +8 -0
- package/dist/commands/organisationHierarchy.d.ts.map +1 -0
- package/dist/commands/organisationHierarchy.js +75 -0
- package/dist/commands/organisationHierarchy.js.map +1 -0
- package/dist/commands/organisationHierarchy.test.d.ts +2 -0
- package/dist/commands/organisationHierarchy.test.d.ts.map +1 -0
- package/dist/commands/organisationHierarchy.test.js +72 -0
- package/dist/commands/organisationHierarchy.test.js.map +1 -0
- package/dist/commands/organisationWrite.d.ts +18 -0
- package/dist/commands/organisationWrite.d.ts.map +1 -0
- package/dist/commands/organisationWrite.js +68 -0
- package/dist/commands/organisationWrite.js.map +1 -0
- package/dist/commands/orient.d.ts +116 -4
- package/dist/commands/orient.d.ts.map +1 -1
- package/dist/commands/orient.js +224 -11
- package/dist/commands/orient.js.map +1 -1
- package/dist/commands/outcome.d.ts +92 -0
- package/dist/commands/outcome.d.ts.map +1 -0
- package/dist/commands/outcome.js +203 -0
- package/dist/commands/outcome.js.map +1 -0
- package/dist/commands/outcome.test.d.ts +2 -0
- package/dist/commands/outcome.test.d.ts.map +1 -0
- package/dist/commands/outcome.test.js +308 -0
- package/dist/commands/outcome.test.js.map +1 -0
- package/dist/commands/profile.d.ts +34 -2
- package/dist/commands/profile.d.ts.map +1 -1
- package/dist/commands/profile.js +294 -41
- package/dist/commands/profile.js.map +1 -1
- package/dist/commands/proof-run.d.ts +51 -0
- package/dist/commands/proof-run.d.ts.map +1 -0
- package/dist/commands/proof-run.js +209 -0
- package/dist/commands/proof-run.js.map +1 -0
- package/dist/commands/proposals.d.ts.map +1 -1
- package/dist/commands/proposals.js.map +1 -1
- package/dist/commands/quality.d.ts +16 -0
- package/dist/commands/quality.d.ts.map +1 -0
- package/dist/commands/quality.js +29 -0
- package/dist/commands/quality.js.map +1 -0
- package/dist/commands/questions.d.ts +34 -0
- package/dist/commands/questions.d.ts.map +1 -0
- package/dist/commands/questions.js +318 -0
- package/dist/commands/questions.js.map +1 -0
- package/dist/commands/questions.test.d.ts +2 -0
- package/dist/commands/questions.test.d.ts.map +1 -0
- package/dist/commands/questions.test.js +186 -0
- package/dist/commands/questions.test.js.map +1 -0
- package/dist/commands/reject.d.ts.map +1 -1
- package/dist/commands/reject.js +3 -2
- package/dist/commands/reject.js.map +1 -1
- package/dist/commands/relate.d.ts +1 -0
- package/dist/commands/relate.d.ts.map +1 -1
- package/dist/commands/relate.js +102 -3
- package/dist/commands/relate.js.map +1 -1
- package/dist/commands/restore.d.ts +2 -0
- package/dist/commands/restore.d.ts.map +1 -0
- package/dist/commands/restore.js +83 -0
- package/dist/commands/restore.js.map +1 -0
- package/dist/commands/rework.d.ts +24 -0
- package/dist/commands/rework.d.ts.map +1 -0
- package/dist/commands/rework.js +97 -0
- package/dist/commands/rework.js.map +1 -0
- package/dist/commands/role.d.ts +49 -0
- package/dist/commands/role.d.ts.map +1 -0
- package/dist/commands/role.js +126 -0
- package/dist/commands/role.js.map +1 -0
- package/dist/commands/role.test.d.ts +2 -0
- package/dist/commands/role.test.d.ts.map +1 -0
- package/dist/commands/role.test.js +195 -0
- package/dist/commands/role.test.js.map +1 -0
- package/dist/commands/scoreboard.d.ts +28 -0
- package/dist/commands/scoreboard.d.ts.map +1 -0
- package/dist/commands/scoreboard.js +40 -0
- package/dist/commands/scoreboard.js.map +1 -0
- package/dist/commands/search.d.ts.map +1 -1
- package/dist/commands/search.js.map +1 -1
- package/dist/commands/session.d.ts +60 -7
- package/dist/commands/session.d.ts.map +1 -1
- package/dist/commands/session.js +422 -58
- package/dist/commands/session.js.map +1 -1
- package/dist/commands/setup-audit.d.ts +59 -0
- package/dist/commands/setup-audit.d.ts.map +1 -0
- package/dist/commands/setup-audit.js +250 -0
- package/dist/commands/setup-audit.js.map +1 -0
- package/dist/commands/setup-detect-surfaces.d.ts +38 -0
- package/dist/commands/setup-detect-surfaces.d.ts.map +1 -0
- package/dist/commands/setup-detect-surfaces.js +76 -0
- package/dist/commands/setup-detect-surfaces.js.map +1 -0
- package/dist/commands/setup-ingest.d.ts +17 -0
- package/dist/commands/setup-ingest.d.ts.map +1 -0
- package/dist/commands/setup-ingest.js +179 -0
- package/dist/commands/setup-ingest.js.map +1 -0
- package/dist/commands/setup-resolver.d.ts +58 -0
- package/dist/commands/setup-resolver.d.ts.map +1 -0
- package/dist/commands/setup-resolver.js +150 -0
- package/dist/commands/setup-resolver.js.map +1 -0
- package/dist/commands/setup-state.d.ts +42 -0
- package/dist/commands/setup-state.d.ts.map +1 -0
- package/dist/commands/setup-state.js +93 -0
- package/dist/commands/setup-state.js.map +1 -0
- package/dist/commands/setup.d.ts +17 -9
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +52 -151
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/shape.d.ts +16 -0
- package/dist/commands/shape.d.ts.map +1 -0
- package/dist/commands/shape.js +149 -0
- package/dist/commands/shape.js.map +1 -0
- package/dist/commands/shape.test.d.ts +2 -0
- package/dist/commands/shape.test.d.ts.map +1 -0
- package/dist/commands/shape.test.js +148 -0
- package/dist/commands/shape.test.js.map +1 -0
- package/dist/commands/status.d.ts +7 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +102 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/status.test.d.ts +2 -0
- package/dist/commands/status.test.d.ts.map +1 -0
- package/dist/commands/status.test.js +75 -0
- package/dist/commands/status.test.js.map +1 -0
- package/dist/commands/tensionsList.d.ts +5 -0
- package/dist/commands/tensionsList.d.ts.map +1 -0
- package/dist/commands/tensionsList.js +27 -0
- package/dist/commands/tensionsList.js.map +1 -0
- package/dist/commands/update.d.ts +20 -0
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +136 -35
- package/dist/commands/update.js.map +1 -1
- package/dist/commands/upgrade.d.ts +5 -0
- package/dist/commands/upgrade.d.ts.map +1 -0
- package/dist/commands/upgrade.js +110 -0
- package/dist/commands/upgrade.js.map +1 -0
- package/dist/commands/usage.d.ts.map +1 -1
- package/dist/commands/usage.js +0 -18
- package/dist/commands/usage.js.map +1 -1
- package/dist/commands/verify.d.ts.map +1 -1
- package/dist/commands/verify.js +7 -1
- package/dist/commands/verify.js.map +1 -1
- package/dist/commands/welcome.d.ts +21 -0
- package/dist/commands/welcome.d.ts.map +1 -0
- package/dist/commands/welcome.js +53 -0
- package/dist/commands/welcome.js.map +1 -0
- package/dist/commands/whoami.d.ts +20 -0
- package/dist/commands/whoami.d.ts.map +1 -0
- package/dist/commands/whoami.js +126 -0
- package/dist/commands/whoami.js.map +1 -0
- package/dist/commands/whoami.test.d.ts +2 -0
- package/dist/commands/whoami.test.d.ts.map +1 -0
- package/dist/commands/whoami.test.js +130 -0
- package/dist/commands/whoami.test.js.map +1 -0
- package/dist/commands/workspace.d.ts +52 -2
- package/dist/commands/workspace.d.ts.map +1 -1
- package/dist/commands/workspace.js +23 -2
- package/dist/commands/workspace.js.map +1 -1
- package/dist/formatters/__tests__/orient-possibleConflict.test.d.ts +2 -0
- package/dist/formatters/__tests__/orient-possibleConflict.test.d.ts.map +1 -0
- package/dist/formatters/__tests__/orient-possibleConflict.test.js +68 -0
- package/dist/formatters/__tests__/orient-possibleConflict.test.js.map +1 -0
- package/dist/formatters/__tests__/orient-provenance.test.d.ts +7 -0
- package/dist/formatters/__tests__/orient-provenance.test.d.ts.map +1 -0
- package/dist/formatters/__tests__/orient-provenance.test.js +549 -0
- package/dist/formatters/__tests__/orient-provenance.test.js.map +1 -0
- package/dist/formatters/__tests__/session-list-show.test.d.ts +2 -0
- package/dist/formatters/__tests__/session-list-show.test.d.ts.map +1 -0
- package/dist/formatters/__tests__/session-list-show.test.js +159 -0
- package/dist/formatters/__tests__/session-list-show.test.js.map +1 -0
- package/dist/formatters/__tests__/session.test.d.ts +2 -0
- package/dist/formatters/__tests__/session.test.d.ts.map +1 -0
- package/dist/formatters/__tests__/session.test.js +192 -0
- package/dist/formatters/__tests__/session.test.js.map +1 -0
- package/dist/formatters/__tests__/tensionsList.test.d.ts +2 -0
- package/dist/formatters/__tests__/tensionsList.test.d.ts.map +1 -0
- package/dist/formatters/__tests__/tensionsList.test.js +30 -0
- package/dist/formatters/__tests__/tensionsList.test.js.map +1 -0
- package/dist/formatters/audit.d.ts +7 -1
- package/dist/formatters/audit.d.ts.map +1 -1
- package/dist/formatters/audit.js +2 -2
- package/dist/formatters/audit.js.map +1 -1
- package/dist/formatters/brief.d.ts +6 -15
- package/dist/formatters/brief.d.ts.map +1 -1
- package/dist/formatters/brief.js +16 -14
- package/dist/formatters/brief.js.map +1 -1
- package/dist/formatters/brief.test.d.ts +2 -0
- package/dist/formatters/brief.test.d.ts.map +1 -0
- package/dist/formatters/brief.test.js +21 -0
- package/dist/formatters/brief.test.js.map +1 -0
- package/dist/formatters/capture.d.ts +13 -0
- package/dist/formatters/capture.d.ts.map +1 -1
- package/dist/formatters/capture.js +20 -1
- package/dist/formatters/capture.js.map +1 -1
- package/dist/formatters/coaching.d.ts +55 -0
- package/dist/formatters/coaching.d.ts.map +1 -0
- package/dist/formatters/coaching.js +46 -0
- package/dist/formatters/coaching.js.map +1 -0
- package/dist/formatters/conflicts.d.ts +69 -0
- package/dist/formatters/conflicts.d.ts.map +1 -0
- package/dist/formatters/conflicts.js +87 -0
- package/dist/formatters/conflicts.js.map +1 -0
- package/dist/formatters/conflicts.test.d.ts +2 -0
- package/dist/formatters/conflicts.test.d.ts.map +1 -0
- package/dist/formatters/conflicts.test.js +136 -0
- package/dist/formatters/conflicts.test.js.map +1 -0
- package/dist/formatters/context.d.ts +1 -1
- package/dist/formatters/context.d.ts.map +1 -1
- package/dist/formatters/context.js.map +1 -1
- package/dist/formatters/direction.d.ts +48 -0
- package/dist/formatters/direction.d.ts.map +1 -0
- package/dist/formatters/direction.js +75 -0
- package/dist/formatters/direction.js.map +1 -0
- package/dist/formatters/direction.test.d.ts +2 -0
- package/dist/formatters/direction.test.d.ts.map +1 -0
- package/dist/formatters/direction.test.js +70 -0
- package/dist/formatters/direction.test.js.map +1 -0
- package/dist/formatters/entry.d.ts +58 -0
- package/dist/formatters/entry.d.ts.map +1 -1
- package/dist/formatters/entry.js +99 -11
- package/dist/formatters/entry.js.map +1 -1
- package/dist/formatters/entryAccept.d.ts +79 -0
- package/dist/formatters/entryAccept.d.ts.map +1 -0
- package/dist/formatters/entryAccept.js +80 -0
- package/dist/formatters/entryAccept.js.map +1 -0
- package/dist/formatters/feedback.d.ts +56 -0
- package/dist/formatters/feedback.d.ts.map +1 -0
- package/dist/formatters/feedback.js +89 -0
- package/dist/formatters/feedback.js.map +1 -0
- package/dist/formatters/feedback.test.d.ts +2 -0
- package/dist/formatters/feedback.test.d.ts.map +1 -0
- package/dist/formatters/feedback.test.js +112 -0
- package/dist/formatters/feedback.test.js.map +1 -0
- package/dist/formatters/handshake.d.ts +61 -0
- package/dist/formatters/handshake.d.ts.map +1 -1
- package/dist/formatters/handshake.js +160 -3
- package/dist/formatters/handshake.js.map +1 -1
- package/dist/formatters/orient.coherencyCheckTag.test.d.ts +2 -0
- package/dist/formatters/orient.coherencyCheckTag.test.d.ts.map +1 -0
- package/dist/formatters/orient.coherencyCheckTag.test.js +22 -0
- package/dist/formatters/orient.coherencyCheckTag.test.js.map +1 -0
- package/dist/formatters/orient.d.ts +223 -10
- package/dist/formatters/orient.d.ts.map +1 -1
- package/dist/formatters/orient.js +249 -40
- package/dist/formatters/orient.js.map +1 -1
- package/dist/formatters/orient.rcrtMiss.test.d.ts +2 -0
- package/dist/formatters/orient.rcrtMiss.test.d.ts.map +1 -0
- package/dist/formatters/orient.rcrtMiss.test.js +83 -0
- package/dist/formatters/orient.rcrtMiss.test.js.map +1 -0
- package/dist/formatters/orient.rituals.test.d.ts +2 -0
- package/dist/formatters/orient.rituals.test.d.ts.map +1 -0
- package/dist/formatters/orient.rituals.test.js +78 -0
- package/dist/formatters/orient.rituals.test.js.map +1 -0
- package/dist/formatters/orient.shapeAdvisorySummary.test.d.ts +2 -0
- package/dist/formatters/orient.shapeAdvisorySummary.test.d.ts.map +1 -0
- package/dist/formatters/orient.shapeAdvisorySummary.test.js +63 -0
- package/dist/formatters/orient.shapeAdvisorySummary.test.js.map +1 -0
- package/dist/formatters/orientDegradation.d.ts +38 -0
- package/dist/formatters/orientDegradation.d.ts.map +1 -0
- package/dist/formatters/orientDegradation.js +50 -0
- package/dist/formatters/orientDegradation.js.map +1 -0
- package/dist/formatters/orientDegradation.test.d.ts +2 -0
- package/dist/formatters/orientDegradation.test.d.ts.map +1 -0
- package/dist/formatters/orientDegradation.test.js +28 -0
- package/dist/formatters/orientDegradation.test.js.map +1 -0
- package/dist/formatters/orientDirection.d.ts +106 -0
- package/dist/formatters/orientDirection.d.ts.map +1 -0
- package/dist/formatters/orientDirection.js +177 -0
- package/dist/formatters/orientDirection.js.map +1 -0
- package/dist/formatters/orientDirection.test.d.ts +2 -0
- package/dist/formatters/orientDirection.test.d.ts.map +1 -0
- package/dist/formatters/orientDirection.test.js +311 -0
- package/dist/formatters/orientDirection.test.js.map +1 -0
- package/dist/formatters/orientRetrievalMiss.d.ts +22 -0
- package/dist/formatters/orientRetrievalMiss.d.ts.map +1 -0
- package/dist/formatters/orientRetrievalMiss.js +17 -0
- package/dist/formatters/orientRetrievalMiss.js.map +1 -0
- package/dist/formatters/proposals.js +2 -2
- package/dist/formatters/proposals.js.map +1 -1
- package/dist/formatters/questions.d.ts +100 -0
- package/dist/formatters/questions.d.ts.map +1 -0
- package/dist/formatters/questions.js +163 -0
- package/dist/formatters/questions.js.map +1 -0
- package/dist/formatters/questions.test.d.ts +2 -0
- package/dist/formatters/questions.test.d.ts.map +1 -0
- package/dist/formatters/questions.test.js +211 -0
- package/dist/formatters/questions.test.js.map +1 -0
- package/dist/formatters/relate.d.ts +14 -1
- package/dist/formatters/relate.d.ts.map +1 -1
- package/dist/formatters/relate.js +12 -3
- package/dist/formatters/relate.js.map +1 -1
- package/dist/formatters/relate.test.d.ts +2 -0
- package/dist/formatters/relate.test.d.ts.map +1 -0
- package/dist/formatters/relate.test.js +81 -0
- package/dist/formatters/relate.test.js.map +1 -0
- package/dist/formatters/scoreboard.d.ts +11 -0
- package/dist/formatters/scoreboard.d.ts.map +1 -0
- package/dist/formatters/scoreboard.js +164 -0
- package/dist/formatters/scoreboard.js.map +1 -0
- package/dist/formatters/scoreboard.test.d.ts +2 -0
- package/dist/formatters/scoreboard.test.d.ts.map +1 -0
- package/dist/formatters/scoreboard.test.js +303 -0
- package/dist/formatters/scoreboard.test.js.map +1 -0
- package/dist/formatters/search.d.ts.map +1 -1
- package/dist/formatters/search.js +17 -1
- package/dist/formatters/search.js.map +1 -1
- package/dist/formatters/search.test.d.ts +2 -0
- package/dist/formatters/search.test.d.ts.map +1 -0
- package/dist/formatters/search.test.js +46 -0
- package/dist/formatters/search.test.js.map +1 -0
- package/dist/formatters/session-feedback.test.d.ts +2 -0
- package/dist/formatters/session-feedback.test.d.ts.map +1 -0
- package/dist/formatters/session-feedback.test.js +61 -0
- package/dist/formatters/session-feedback.test.js.map +1 -0
- package/dist/formatters/session.d.ts +121 -5
- package/dist/formatters/session.d.ts.map +1 -1
- package/dist/formatters/session.js +309 -12
- package/dist/formatters/session.js.map +1 -1
- package/dist/formatters/shape.d.ts +54 -0
- package/dist/formatters/shape.d.ts.map +1 -0
- package/dist/formatters/shape.js +97 -0
- package/dist/formatters/shape.js.map +1 -0
- package/dist/formatters/shape.test.d.ts +2 -0
- package/dist/formatters/shape.test.d.ts.map +1 -0
- package/dist/formatters/shape.test.js +80 -0
- package/dist/formatters/shape.test.js.map +1 -0
- package/dist/formatters/spineCheck.d.ts +14 -0
- package/dist/formatters/spineCheck.d.ts.map +1 -0
- package/dist/formatters/spineCheck.js +113 -0
- package/dist/formatters/spineCheck.js.map +1 -0
- package/dist/formatters/spineCheck.test.d.ts +2 -0
- package/dist/formatters/spineCheck.test.d.ts.map +1 -0
- package/dist/formatters/spineCheck.test.js +76 -0
- package/dist/formatters/spineCheck.test.js.map +1 -0
- package/dist/formatters/tensionsList.d.ts +17 -0
- package/dist/formatters/tensionsList.d.ts.map +1 -0
- package/dist/formatters/tensionsList.js +33 -0
- package/dist/formatters/tensionsList.js.map +1 -0
- package/dist/formatters/update.d.ts +23 -0
- package/dist/formatters/update.d.ts.map +1 -1
- package/dist/formatters/update.js +46 -6
- package/dist/formatters/update.js.map +1 -1
- package/dist/formatters/update.test.d.ts +2 -0
- package/dist/formatters/update.test.d.ts.map +1 -0
- package/dist/formatters/update.test.js +103 -0
- package/dist/formatters/update.test.js.map +1 -0
- package/dist/formatters/verify.d.ts +12 -4
- package/dist/formatters/verify.d.ts.map +1 -1
- package/dist/formatters/verify.js +20 -2
- package/dist/formatters/verify.js.map +1 -1
- package/dist/generated/healthGapKinds.generated.d.ts +12 -0
- package/dist/generated/healthGapKinds.generated.d.ts.map +1 -0
- package/dist/generated/healthGapKinds.generated.js +23 -0
- package/dist/generated/healthGapKinds.generated.js.map +1 -0
- package/dist/generated/organisationalAuthorityRefusalCodes.generated.d.ts +12 -0
- package/dist/generated/organisationalAuthorityRefusalCodes.generated.d.ts.map +1 -0
- package/dist/generated/organisationalAuthorityRefusalCodes.generated.js +11 -0
- package/dist/generated/organisationalAuthorityRefusalCodes.generated.js.map +1 -0
- package/dist/generated/relationTypes.generated.d.ts +12 -0
- package/dist/generated/relationTypes.generated.d.ts.map +1 -0
- package/dist/generated/relationTypes.generated.js +11 -0
- package/dist/generated/relationTypes.generated.js.map +1 -0
- package/dist/generated/routeLatencyBudget.generated.d.ts +55 -0
- package/dist/generated/routeLatencyBudget.generated.d.ts.map +1 -0
- package/dist/generated/routeLatencyBudget.generated.js +312 -0
- package/dist/generated/routeLatencyBudget.generated.js.map +1 -0
- package/dist/generated/sourceSurfaces.generated.d.ts +12 -0
- package/dist/generated/sourceSurfaces.generated.d.ts.map +1 -0
- package/dist/generated/sourceSurfaces.generated.js +11 -0
- package/dist/generated/sourceSurfaces.generated.js.map +1 -0
- package/dist/generators/adapters.d.ts +33 -2
- package/dist/generators/adapters.d.ts.map +1 -1
- package/dist/generators/adapters.js +68 -23
- package/dist/generators/adapters.js.map +1 -1
- package/dist/generators/adapters.test.js +0 -2
- package/dist/generators/adapters.test.js.map +1 -1
- package/dist/generators/archetypes.d.ts.map +1 -1
- package/dist/generators/archetypes.js +46 -9
- package/dist/generators/archetypes.js.map +1 -1
- package/dist/generators/archetypes.test.js +35 -0
- package/dist/generators/archetypes.test.js.map +1 -1
- package/dist/generators/boundary-manifest.d.ts +29 -0
- package/dist/generators/boundary-manifest.d.ts.map +1 -0
- package/dist/generators/boundary-manifest.js +183 -0
- package/dist/generators/boundary-manifest.js.map +1 -0
- package/dist/generators/boundary-manifest.real-file.test.d.ts +2 -0
- package/dist/generators/boundary-manifest.real-file.test.d.ts.map +1 -0
- package/dist/generators/boundary-manifest.real-file.test.js +70 -0
- package/dist/generators/boundary-manifest.real-file.test.js.map +1 -0
- package/dist/generators/boundary-manifest.test.d.ts +2 -0
- package/dist/generators/boundary-manifest.test.d.ts.map +1 -0
- package/dist/generators/boundary-manifest.test.js +91 -0
- package/dist/generators/boundary-manifest.test.js.map +1 -0
- package/dist/generators/chain-classifier-kernel-client-drift.test.d.ts +2 -0
- package/dist/generators/chain-classifier-kernel-client-drift.test.d.ts.map +1 -0
- package/dist/generators/chain-classifier-kernel-client-drift.test.js +41 -0
- package/dist/generators/chain-classifier-kernel-client-drift.test.js.map +1 -0
- package/dist/generators/chain-classifier.d.ts +67 -14
- package/dist/generators/chain-classifier.d.ts.map +1 -1
- package/dist/generators/chain-classifier.js +46 -174
- package/dist/generators/chain-classifier.js.map +1 -1
- package/dist/generators/chain-rules.d.ts.map +1 -1
- package/dist/generators/chain-rules.js +115 -3
- package/dist/generators/chain-rules.js.map +1 -1
- package/dist/generators/chain-rules.test.js +271 -2
- package/dist/generators/chain-rules.test.js.map +1 -1
- package/dist/generators/context-md.js +7 -7
- package/dist/generators/context-md.js.map +1 -1
- package/dist/generators/manifest.d.ts +115 -0
- package/dist/generators/manifest.d.ts.map +1 -0
- package/dist/generators/manifest.js +277 -0
- package/dist/generators/manifest.js.map +1 -0
- package/dist/generators/noProjectionAssets.d.ts +15 -0
- package/dist/generators/noProjectionAssets.d.ts.map +1 -0
- package/dist/generators/noProjectionAssets.js +6 -0
- package/dist/generators/noProjectionAssets.js.map +1 -0
- package/dist/generators/portable-knowledge.d.ts +24 -12
- package/dist/generators/portable-knowledge.d.ts.map +1 -1
- package/dist/generators/portable-knowledge.js +96 -56
- package/dist/generators/portable-knowledge.js.map +1 -1
- package/dist/generators/portable-knowledge.test.js +46 -81
- package/dist/generators/portable-knowledge.test.js.map +1 -1
- package/dist/generators/region-projections.d.ts +17 -0
- package/dist/generators/region-projections.d.ts.map +1 -0
- package/dist/generators/region-projections.js +48 -0
- package/dist/generators/region-projections.js.map +1 -0
- package/dist/generators/region-projections.test.d.ts +2 -0
- package/dist/generators/region-projections.test.d.ts.map +1 -0
- package/dist/generators/region-projections.test.js +63 -0
- package/dist/generators/region-projections.test.js.map +1 -0
- package/dist/generators/region.d.ts +24 -0
- package/dist/generators/region.d.ts.map +1 -0
- package/dist/generators/region.js +87 -0
- package/dist/generators/region.js.map +1 -0
- package/dist/generators/region.test.d.ts +2 -0
- package/dist/generators/region.test.d.ts.map +1 -0
- package/dist/generators/region.test.js +126 -0
- package/dist/generators/region.test.js.map +1 -0
- package/dist/generators/surface-profiles.d.ts +1 -2
- package/dist/generators/surface-profiles.d.ts.map +1 -1
- package/dist/generators/surface-profiles.js.map +1 -1
- package/dist/handleCliError.d.ts +2 -0
- package/dist/handleCliError.d.ts.map +1 -0
- package/dist/handleCliError.js +56 -0
- package/dist/handleCliError.js.map +1 -0
- package/dist/index.d.ts +0 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +305 -251
- package/dist/index.js.map +1 -1
- package/dist/lib/__tests__/legalRelationTypes.test.d.ts +2 -0
- package/dist/lib/__tests__/legalRelationTypes.test.d.ts.map +1 -0
- package/dist/lib/__tests__/legalRelationTypes.test.js +98 -0
- package/dist/lib/__tests__/legalRelationTypes.test.js.map +1 -0
- package/dist/lib/__tests__/parseFields.test.d.ts +2 -0
- package/dist/lib/__tests__/parseFields.test.d.ts.map +1 -0
- package/dist/lib/__tests__/parseFields.test.js +40 -0
- package/dist/lib/__tests__/parseFields.test.js.map +1 -0
- package/dist/lib/activation.d.ts.map +1 -1
- package/dist/lib/activation.js +7 -3
- package/dist/lib/activation.js.map +1 -1
- package/dist/lib/activation.test.js +3 -3
- package/dist/lib/activation.test.js.map +1 -1
- package/dist/lib/adminConfig.d.ts +48 -0
- package/dist/lib/adminConfig.d.ts.map +1 -0
- package/dist/lib/adminConfig.js +130 -0
- package/dist/lib/adminConfig.js.map +1 -0
- package/dist/lib/canonicalRefs.d.ts +160 -0
- package/dist/lib/canonicalRefs.d.ts.map +1 -0
- package/dist/lib/canonicalRefs.js +169 -0
- package/dist/lib/canonicalRefs.js.map +1 -0
- package/dist/lib/captureGrounding.d.ts +43 -0
- package/dist/lib/captureGrounding.d.ts.map +1 -0
- package/dist/lib/captureGrounding.js +99 -0
- package/dist/lib/captureGrounding.js.map +1 -0
- package/dist/lib/captureGrounding.test.d.ts +2 -0
- package/dist/lib/captureGrounding.test.d.ts.map +1 -0
- package/dist/lib/captureGrounding.test.js +116 -0
- package/dist/lib/captureGrounding.test.js.map +1 -0
- package/dist/lib/captureLink.d.ts +26 -0
- package/dist/lib/captureLink.d.ts.map +1 -0
- package/dist/lib/captureLink.js +96 -0
- package/dist/lib/captureLink.js.map +1 -0
- package/dist/lib/captureVersion.d.ts +38 -0
- package/dist/lib/captureVersion.d.ts.map +1 -0
- package/dist/lib/captureVersion.js +73 -0
- package/dist/lib/captureVersion.js.map +1 -0
- package/dist/lib/client.d.ts +46 -19
- package/dist/lib/client.d.ts.map +1 -1
- package/dist/lib/client.js +229 -66
- package/dist/lib/client.js.map +1 -1
- package/dist/lib/collectionRegistry.d.ts +80 -0
- package/dist/lib/collectionRegistry.d.ts.map +1 -0
- package/dist/lib/collectionRegistry.js +170 -0
- package/dist/lib/collectionRegistry.js.map +1 -0
- package/dist/lib/commanderOptions.d.ts +8 -0
- package/dist/lib/commanderOptions.d.ts.map +1 -0
- package/dist/lib/commanderOptions.js +10 -0
- package/dist/lib/commanderOptions.js.map +1 -0
- package/dist/lib/compose-wrapup-view.d.ts +48 -0
- package/dist/lib/compose-wrapup-view.d.ts.map +1 -0
- package/dist/lib/compose-wrapup-view.js +37 -0
- package/dist/lib/compose-wrapup-view.js.map +1 -0
- package/dist/lib/config.d.ts +102 -54
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +252 -156
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/configResult.d.ts +103 -0
- package/dist/lib/configResult.d.ts.map +1 -0
- package/dist/lib/configResult.js +180 -0
- package/dist/lib/configResult.js.map +1 -0
- package/dist/lib/connectKeyLabel.d.ts +9 -0
- package/dist/lib/connectKeyLabel.d.ts.map +1 -0
- package/dist/lib/connectKeyLabel.js +12 -0
- package/dist/lib/connectKeyLabel.js.map +1 -0
- package/dist/lib/constants.d.ts +5 -1
- package/dist/lib/constants.d.ts.map +1 -1
- package/dist/lib/constants.js +8 -1
- package/dist/lib/constants.js.map +1 -1
- package/dist/lib/conversation.d.ts +36 -0
- package/dist/lib/conversation.d.ts.map +1 -0
- package/dist/lib/conversation.js +66 -0
- package/dist/lib/conversation.js.map +1 -0
- package/dist/lib/createEntryResult.d.ts +34 -0
- package/dist/lib/createEntryResult.d.ts.map +1 -0
- package/dist/lib/createEntryResult.js +12 -0
- package/dist/lib/createEntryResult.js.map +1 -0
- package/dist/lib/deployment.test.js +19 -0
- package/dist/lib/deployment.test.js.map +1 -1
- package/dist/lib/envKeySnapshot.d.ts +10 -0
- package/dist/lib/envKeySnapshot.d.ts.map +1 -0
- package/dist/lib/envKeySnapshot.js +30 -0
- package/dist/lib/envKeySnapshot.js.map +1 -0
- package/dist/lib/errors.d.ts +79 -0
- package/dist/lib/errors.d.ts.map +1 -1
- package/dist/lib/errors.js +79 -0
- package/dist/lib/errors.js.map +1 -1
- package/dist/lib/frontmatter.d.ts +55 -0
- package/dist/lib/frontmatter.d.ts.map +1 -0
- package/dist/lib/frontmatter.js +92 -0
- package/dist/lib/frontmatter.js.map +1 -0
- package/dist/lib/frontmatter.test.d.ts +15 -0
- package/dist/lib/frontmatter.test.d.ts.map +1 -0
- package/dist/lib/frontmatter.test.js +98 -0
- package/dist/lib/frontmatter.test.js.map +1 -0
- package/dist/lib/gatewayTimeout.d.ts +88 -0
- package/dist/lib/gatewayTimeout.d.ts.map +1 -0
- package/dist/lib/gatewayTimeout.js +118 -0
- package/dist/lib/gatewayTimeout.js.map +1 -0
- package/dist/lib/gitEnvLeakKeysParity.test.d.ts +2 -0
- package/dist/lib/gitEnvLeakKeysParity.test.d.ts.map +1 -0
- package/dist/lib/gitEnvLeakKeysParity.test.js +73 -0
- package/dist/lib/gitEnvLeakKeysParity.test.js.map +1 -0
- package/dist/lib/glossary.js +1 -1
- package/dist/lib/glossary.js.map +1 -1
- package/dist/lib/hook-intents.d.ts +51 -0
- package/dist/lib/hook-intents.d.ts.map +1 -0
- package/dist/lib/hook-intents.js +84 -0
- package/dist/lib/hook-intents.js.map +1 -0
- package/dist/lib/inferSourceDate.d.ts +12 -0
- package/dist/lib/inferSourceDate.d.ts.map +1 -0
- package/dist/lib/inferSourceDate.js +44 -0
- package/dist/lib/inferSourceDate.js.map +1 -0
- package/dist/lib/kernelEnvelope.d.ts +31 -0
- package/dist/lib/kernelEnvelope.d.ts.map +1 -0
- package/dist/lib/kernelEnvelope.js +52 -0
- package/dist/lib/kernelEnvelope.js.map +1 -0
- package/dist/lib/legalRelationTypes.d.ts +26 -0
- package/dist/lib/legalRelationTypes.d.ts.map +1 -0
- package/dist/lib/legalRelationTypes.js +95 -0
- package/dist/lib/legalRelationTypes.js.map +1 -0
- package/dist/lib/localBinding.d.ts +86 -0
- package/dist/lib/localBinding.d.ts.map +1 -0
- package/dist/lib/localBinding.js +173 -0
- package/dist/lib/localBinding.js.map +1 -0
- package/dist/lib/method-registry.d.ts +37 -0
- package/dist/lib/method-registry.d.ts.map +1 -0
- package/dist/lib/method-registry.js +41 -0
- package/dist/lib/method-registry.js.map +1 -0
- package/dist/lib/normalizeMaterializedFilename.d.ts +28 -0
- package/dist/lib/normalizeMaterializedFilename.d.ts.map +1 -0
- package/dist/lib/normalizeMaterializedFilename.js +56 -0
- package/dist/lib/normalizeMaterializedFilename.js.map +1 -0
- package/dist/lib/normalizeMaterializedFilename.test.d.ts +16 -0
- package/dist/lib/normalizeMaterializedFilename.test.d.ts.map +1 -0
- package/dist/lib/normalizeMaterializedFilename.test.js +90 -0
- package/dist/lib/normalizeMaterializedFilename.test.js.map +1 -0
- package/dist/lib/notice-marker.d.ts +3 -0
- package/dist/lib/notice-marker.d.ts.map +1 -0
- package/dist/lib/notice-marker.js +223 -0
- package/dist/lib/notice-marker.js.map +1 -0
- package/dist/lib/onboarding-path-b.d.ts.map +1 -1
- package/dist/lib/onboarding-path-b.js +35 -6
- package/dist/lib/onboarding-path-b.js.map +1 -1
- package/dist/lib/onboarding-shared.d.ts +4 -4
- package/dist/lib/onboarding-shared.d.ts.map +1 -1
- package/dist/lib/onboarding-shared.js +5 -20
- package/dist/lib/onboarding-shared.js.map +1 -1
- package/dist/lib/onboarding.d.ts.map +1 -1
- package/dist/lib/onboarding.js +8 -0
- package/dist/lib/onboarding.js.map +1 -1
- package/dist/lib/ownerLine.d.ts +62 -0
- package/dist/lib/ownerLine.d.ts.map +1 -0
- package/dist/lib/ownerLine.js +42 -0
- package/dist/lib/ownerLine.js.map +1 -0
- package/dist/lib/parseFields.d.ts +19 -0
- package/dist/lib/parseFields.d.ts.map +1 -0
- package/dist/lib/parseFields.js +49 -0
- package/dist/lib/parseFields.js.map +1 -0
- package/dist/lib/previewBanner.d.ts +9 -0
- package/dist/lib/previewBanner.d.ts.map +1 -0
- package/dist/lib/previewBanner.js +37 -0
- package/dist/lib/previewBanner.js.map +1 -0
- package/dist/lib/productbrain-files.d.ts +94 -0
- package/dist/lib/productbrain-files.d.ts.map +1 -0
- package/dist/lib/productbrain-files.js +214 -0
- package/dist/lib/productbrain-files.js.map +1 -0
- package/dist/lib/productbrain-files.test.d.ts +2 -0
- package/dist/lib/productbrain-files.test.d.ts.map +1 -0
- package/dist/lib/productbrain-files.test.js +293 -0
- package/dist/lib/productbrain-files.test.js.map +1 -0
- package/dist/lib/profiles.d.ts +53 -5
- package/dist/lib/profiles.d.ts.map +1 -1
- package/dist/lib/profiles.js +77 -23
- package/dist/lib/profiles.js.map +1 -1
- package/dist/lib/projectConfig.d.ts +81 -0
- package/dist/lib/projectConfig.d.ts.map +1 -0
- package/dist/lib/projectConfig.js +157 -0
- package/dist/lib/projectConfig.js.map +1 -0
- package/dist/lib/rate-limit.d.ts +38 -0
- package/dist/lib/rate-limit.d.ts.map +1 -0
- package/dist/lib/rate-limit.js +83 -0
- package/dist/lib/rate-limit.js.map +1 -0
- package/dist/lib/readinessNotices.d.ts +15 -0
- package/dist/lib/readinessNotices.d.ts.map +1 -0
- package/dist/lib/readinessNotices.js +15 -0
- package/dist/lib/readinessNotices.js.map +1 -0
- package/dist/lib/repo-detect.d.ts +5 -1
- package/dist/lib/repo-detect.d.ts.map +1 -1
- package/dist/lib/repo-detect.js +10 -3
- package/dist/lib/repo-detect.js.map +1 -1
- package/dist/lib/reportedProfile.d.ts +18 -0
- package/dist/lib/reportedProfile.d.ts.map +1 -0
- package/dist/lib/reportedProfile.js +144 -0
- package/dist/lib/reportedProfile.js.map +1 -0
- package/dist/lib/runner.d.ts +9 -1
- package/dist/lib/runner.d.ts.map +1 -1
- package/dist/lib/runner.js +30 -4
- package/dist/lib/runner.js.map +1 -1
- package/dist/lib/session.d.ts +90 -6
- package/dist/lib/session.d.ts.map +1 -1
- package/dist/lib/session.js +261 -17
- package/dist/lib/session.js.map +1 -1
- package/dist/lib/sessionBinding.d.ts +61 -0
- package/dist/lib/sessionBinding.d.ts.map +1 -0
- package/dist/lib/sessionBinding.js +125 -0
- package/dist/lib/sessionBinding.js.map +1 -0
- package/dist/lib/sessionNotices.d.ts +57 -0
- package/dist/lib/sessionNotices.d.ts.map +1 -0
- package/dist/lib/sessionNotices.js +128 -0
- package/dist/lib/sessionNotices.js.map +1 -0
- package/dist/lib/sessionNotices.test.d.ts +2 -0
- package/dist/lib/sessionNotices.test.d.ts.map +1 -0
- package/dist/lib/sessionNotices.test.js +48 -0
- package/dist/lib/sessionNotices.test.js.map +1 -0
- package/dist/lib/spineVerdictRead.d.ts +70 -0
- package/dist/lib/spineVerdictRead.d.ts.map +1 -0
- package/dist/lib/spineVerdictRead.js +73 -0
- package/dist/lib/spineVerdictRead.js.map +1 -0
- package/dist/lib/spinner.js +2 -2
- package/dist/lib/spinner.js.map +1 -1
- package/dist/lib/startup-resolution-signals.d.ts +34 -0
- package/dist/lib/startup-resolution-signals.d.ts.map +1 -0
- package/dist/lib/startup-resolution-signals.js +116 -0
- package/dist/lib/startup-resolution-signals.js.map +1 -0
- package/dist/lib/startup-resolution-signals.test.d.ts +2 -0
- package/dist/lib/startup-resolution-signals.test.d.ts.map +1 -0
- package/dist/lib/startup-resolution-signals.test.js +113 -0
- package/dist/lib/startup-resolution-signals.test.js.map +1 -0
- package/dist/lib/startup-signals.d.ts +12 -0
- package/dist/lib/startup-signals.d.ts.map +1 -0
- package/dist/lib/startup-signals.js +179 -0
- package/dist/lib/startup-signals.js.map +1 -0
- package/dist/lib/startup-signals.test.d.ts +2 -0
- package/dist/lib/startup-signals.test.d.ts.map +1 -0
- package/dist/lib/startup-signals.test.js +165 -0
- package/dist/lib/startup-signals.test.js.map +1 -0
- package/dist/lib/state.d.ts +60 -0
- package/dist/lib/state.d.ts.map +1 -0
- package/dist/lib/state.js +97 -0
- package/dist/lib/state.js.map +1 -0
- package/dist/lib/strip.d.ts +17 -0
- package/dist/lib/strip.d.ts.map +1 -1
- package/dist/lib/strip.js +48 -1
- package/dist/lib/strip.js.map +1 -1
- package/dist/lib/style.d.ts +10 -2
- package/dist/lib/style.d.ts.map +1 -1
- package/dist/lib/style.js +26 -17
- package/dist/lib/style.js.map +1 -1
- package/dist/lib/tokenConstants.d.ts +2 -0
- package/dist/lib/tokenConstants.d.ts.map +1 -1
- package/dist/lib/tokenConstants.js +2 -0
- package/dist/lib/tokenConstants.js.map +1 -1
- package/dist/lib/update-check.d.ts +42 -7
- package/dist/lib/update-check.d.ts.map +1 -1
- package/dist/lib/update-check.js +213 -61
- package/dist/lib/update-check.js.map +1 -1
- package/dist/lib/upgrade-runner.d.ts +22 -0
- package/dist/lib/upgrade-runner.d.ts.map +1 -0
- package/dist/lib/upgrade-runner.js +110 -0
- package/dist/lib/upgrade-runner.js.map +1 -0
- package/dist/lib/versionWrite.d.ts +65 -0
- package/dist/lib/versionWrite.d.ts.map +1 -0
- package/dist/lib/versionWrite.js +32 -0
- package/dist/lib/versionWrite.js.map +1 -0
- package/dist/lib/workspace-probe.d.ts +3 -0
- package/dist/lib/workspace-probe.d.ts.map +1 -1
- package/dist/lib/workspace-probe.js +7 -13
- package/dist/lib/workspace-probe.js.map +1 -1
- package/dist/lib/workspaceNotice.d.ts +202 -0
- package/dist/lib/workspaceNotice.d.ts.map +1 -0
- package/dist/lib/workspaceNotice.js +345 -0
- package/dist/lib/workspaceNotice.js.map +1 -0
- package/dist/lib/workspaceVocabCache.d.ts +60 -0
- package/dist/lib/workspaceVocabCache.d.ts.map +1 -0
- package/dist/lib/workspaceVocabCache.js +98 -0
- package/dist/lib/workspaceVocabCache.js.map +1 -0
- package/dist/registerEntryCommands.d.ts +17 -0
- package/dist/registerEntryCommands.d.ts.map +1 -0
- package/dist/registerEntryCommands.js +106 -0
- package/dist/registerEntryCommands.js.map +1 -0
- package/dist/registerHistoryCommand.d.ts +8 -0
- package/dist/registerHistoryCommand.d.ts.map +1 -0
- package/dist/registerHistoryCommand.js +14 -0
- package/dist/registerHistoryCommand.js.map +1 -0
- package/dist/registerOutcomeCommands.d.ts +27 -0
- package/dist/registerOutcomeCommands.d.ts.map +1 -0
- package/dist/registerOutcomeCommands.js +27 -0
- package/dist/registerOutcomeCommands.js.map +1 -0
- package/dist/registerProposalCommands.d.ts +13 -0
- package/dist/registerProposalCommands.d.ts.map +1 -0
- package/dist/registerProposalCommands.js +76 -0
- package/dist/registerProposalCommands.js.map +1 -0
- package/dist/registerRoleCommands.d.ts +10 -0
- package/dist/registerRoleCommands.d.ts.map +1 -0
- package/dist/registerRoleCommands.js +14 -0
- package/dist/registerRoleCommands.js.map +1 -0
- package/dist/registerTensionsCommands.d.ts +10 -0
- package/dist/registerTensionsCommands.d.ts.map +1 -0
- package/dist/registerTensionsCommands.js +15 -0
- package/dist/registerTensionsCommands.js.map +1 -0
- package/dist/scoreboard/diagnose.d.ts +226 -0
- package/dist/scoreboard/diagnose.d.ts.map +1 -0
- package/dist/scoreboard/diagnose.js +343 -0
- package/dist/scoreboard/diagnose.js.map +1 -0
- package/dist/scoreboard/diagnose.test.d.ts +15 -0
- package/dist/scoreboard/diagnose.test.d.ts.map +1 -0
- package/dist/scoreboard/diagnose.test.js +355 -0
- package/dist/scoreboard/diagnose.test.js.map +1 -0
- package/dist/scoreboard/floors.d.ts +47 -0
- package/dist/scoreboard/floors.d.ts.map +1 -0
- package/dist/scoreboard/floors.js +33 -0
- package/dist/scoreboard/floors.js.map +1 -0
- package/dist/scoreboard/localDrift.d.ts +23 -0
- package/dist/scoreboard/localDrift.d.ts.map +1 -0
- package/dist/scoreboard/localDrift.js +111 -0
- package/dist/scoreboard/localDrift.js.map +1 -0
- package/dist/scoreboard/localDrift.test.d.ts +9 -0
- package/dist/scoreboard/localDrift.test.d.ts.map +1 -0
- package/dist/scoreboard/localDrift.test.js +82 -0
- package/dist/scoreboard/localDrift.test.js.map +1 -0
- package/dist/setup/__tests__/coach-traces.test.d.ts +2 -0
- package/dist/setup/__tests__/coach-traces.test.d.ts.map +1 -0
- package/dist/setup/__tests__/coach-traces.test.js +189 -0
- package/dist/setup/__tests__/coach-traces.test.js.map +1 -0
- package/dist/setup/__tests__/setup-commands.test.d.ts +2 -0
- package/dist/setup/__tests__/setup-commands.test.d.ts.map +1 -0
- package/dist/setup/__tests__/setup-commands.test.js +177 -0
- package/dist/setup/__tests__/setup-commands.test.js.map +1 -0
- package/dist/setup/__tests__/state-machine.test.d.ts +2 -0
- package/dist/setup/__tests__/state-machine.test.d.ts.map +1 -0
- package/dist/setup/__tests__/state-machine.test.js +341 -0
- package/dist/setup/__tests__/state-machine.test.js.map +1 -0
- package/dist/setup/detect-surfaces.d.ts +21 -0
- package/dist/setup/detect-surfaces.d.ts.map +1 -0
- package/dist/setup/detect-surfaces.js +39 -0
- package/dist/setup/detect-surfaces.js.map +1 -0
- package/dist/setup/manifest-writer.d.ts +17 -0
- package/dist/setup/manifest-writer.d.ts.map +1 -0
- package/dist/setup/manifest-writer.js +153 -0
- package/dist/setup/manifest-writer.js.map +1 -0
- package/dist/setup/perimeter.d.ts +72 -0
- package/dist/setup/perimeter.d.ts.map +1 -0
- package/dist/setup/perimeter.js +128 -0
- package/dist/setup/perimeter.js.map +1 -0
- package/dist/setup/state-machine.d.ts +67 -0
- package/dist/setup/state-machine.d.ts.map +1 -0
- package/dist/setup/state-machine.js +124 -0
- package/dist/setup/state-machine.js.map +1 -0
- package/dist/surfaces/__tests__/adapter.test.d.ts +2 -0
- package/dist/surfaces/__tests__/adapter.test.d.ts.map +1 -0
- package/dist/surfaces/__tests__/adapter.test.js +86 -0
- package/dist/surfaces/__tests__/adapter.test.js.map +1 -0
- package/dist/surfaces/__tests__/claude-skill-pointer-drift.test.d.ts +2 -0
- package/dist/surfaces/__tests__/claude-skill-pointer-drift.test.d.ts.map +1 -0
- package/dist/surfaces/__tests__/claude-skill-pointer-drift.test.js +179 -0
- package/dist/surfaces/__tests__/claude-skill-pointer-drift.test.js.map +1 -0
- package/dist/surfaces/__tests__/pb-setup-passthrough.test.d.ts +2 -0
- package/dist/surfaces/__tests__/pb-setup-passthrough.test.d.ts.map +1 -0
- package/dist/surfaces/__tests__/pb-setup-passthrough.test.js +131 -0
- package/dist/surfaces/__tests__/pb-setup-passthrough.test.js.map +1 -0
- package/dist/surfaces/__tests__/telemetry.test.d.ts +2 -0
- package/dist/surfaces/__tests__/telemetry.test.d.ts.map +1 -0
- package/dist/surfaces/__tests__/telemetry.test.js +55 -0
- package/dist/surfaces/__tests__/telemetry.test.js.map +1 -0
- package/dist/surfaces/adapter.d.ts +70 -0
- package/dist/surfaces/adapter.d.ts.map +1 -0
- package/dist/surfaces/adapter.js +2 -0
- package/dist/surfaces/adapter.js.map +1 -0
- package/dist/surfaces/adapters/claude.d.ts +3 -0
- package/dist/surfaces/adapters/claude.d.ts.map +1 -0
- package/dist/surfaces/adapters/claude.js +72 -0
- package/dist/surfaces/adapters/claude.js.map +1 -0
- package/dist/surfaces/adapters/codex.d.ts +3 -0
- package/dist/surfaces/adapters/codex.d.ts.map +1 -0
- package/dist/surfaces/adapters/codex.js +61 -0
- package/dist/surfaces/adapters/codex.js.map +1 -0
- package/dist/surfaces/adapters/copilot.d.ts +3 -0
- package/dist/surfaces/adapters/copilot.d.ts.map +1 -0
- package/dist/surfaces/adapters/copilot.js +59 -0
- package/dist/surfaces/adapters/copilot.js.map +1 -0
- package/dist/surfaces/adapters/cursor.d.ts +3 -0
- package/dist/surfaces/adapters/cursor.d.ts.map +1 -0
- package/dist/surfaces/adapters/cursor.js +78 -0
- package/dist/surfaces/adapters/cursor.js.map +1 -0
- package/dist/surfaces/registry.d.ts +76 -0
- package/dist/surfaces/registry.d.ts.map +1 -0
- package/dist/surfaces/registry.js +117 -0
- package/dist/surfaces/registry.js.map +1 -0
- package/dist/surfaces/telemetry.d.ts +17 -0
- package/dist/surfaces/telemetry.d.ts.map +1 -0
- package/dist/surfaces/telemetry.js +31 -0
- package/dist/surfaces/telemetry.js.map +1 -0
- package/package.json +9 -5
- package/templates/method-registry.json +16 -0
- package/dist/__tests__/promote.test.d.ts +0 -2
- package/dist/__tests__/promote.test.d.ts.map +0 -1
- package/dist/__tests__/promote.test.js +0 -161
- package/dist/__tests__/promote.test.js.map +0 -1
- package/dist/__tests__/setup.test.d.ts +0 -2
- package/dist/__tests__/setup.test.d.ts.map +0 -1
- package/dist/__tests__/setup.test.js +0 -141
- package/dist/__tests__/setup.test.js.map +0 -1
- package/dist/commands/promote.d.ts +0 -12
- package/dist/commands/promote.d.ts.map +0 -1
- package/dist/commands/promote.js +0 -90
- package/dist/commands/promote.js.map +0 -1
- package/dist/formatters/promote.d.ts +0 -30
- package/dist/formatters/promote.d.ts.map +0 -1
- package/dist/formatters/promote.js +0 -39
- package/dist/formatters/promote.js.map +0 -1
- package/dist/generators/__tests__/surface-profiles.test.d.ts +0 -2
- package/dist/generators/__tests__/surface-profiles.test.d.ts.map +0 -1
- package/dist/generators/__tests__/surface-profiles.test.js +0 -89
- package/dist/generators/__tests__/surface-profiles.test.js.map +0 -1
- package/dist/generators/chain-classifier.test.d.ts +0 -2
- package/dist/generators/chain-classifier.test.d.ts.map +0 -1
- package/dist/generators/chain-classifier.test.js +0 -257
- package/dist/generators/chain-classifier.test.js.map +0 -1
- package/dist/lib/onboarding-phases.d.ts +0 -9
- package/dist/lib/onboarding-phases.d.ts.map +0 -1
- package/dist/lib/onboarding-phases.js +0 -120
- package/dist/lib/onboarding-phases.js.map +0 -1
|
@@ -1,24 +1,49 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* pb handshake — generate context files for AI developer tools.
|
|
3
|
-
*
|
|
3
|
+
* Context export wiring (read-only filesystem bridge; GLO-63, DEC-161) — not a product surface.
|
|
4
4
|
*/
|
|
5
|
-
import { mkdirSync, writeFileSync, existsSync, readFileSync, readdirSync, copyFileSync } from 'fs';
|
|
6
|
-
import { join, dirname, resolve } from 'path';
|
|
5
|
+
import { mkdirSync, writeFileSync, existsSync, readFileSync, readdirSync, copyFileSync, realpathSync } from 'fs';
|
|
6
|
+
import { join, dirname, resolve, basename, relative, sep, isAbsolute } from 'path';
|
|
7
7
|
import { homedir } from 'os';
|
|
8
8
|
import { fileURLToPath } from 'url';
|
|
9
|
+
import { createHash } from 'crypto';
|
|
10
|
+
import { execSync } from 'child_process';
|
|
9
11
|
import { getConfigOrGuide } from '../lib/config.js';
|
|
10
|
-
import { select as promptSelect } from '../lib/prompts.js';
|
|
11
|
-
import {
|
|
12
|
+
import { select as promptSelect, confirm as promptConfirm } from '../lib/prompts.js';
|
|
13
|
+
import { composeHooksFromIntents, getHookStatusForSurface } from '../lib/hook-intents.js';
|
|
14
|
+
import { kernelCall, kernelCallWithSession } from '../lib/client.js';
|
|
15
|
+
import { readSession } from '../lib/session.js';
|
|
12
16
|
import { detectRepo, extractWorkspaceProfile } from '../lib/repo-detect.js';
|
|
13
17
|
import { generateContextMd } from '../generators/context-md.js';
|
|
14
18
|
import { generateBriefingMd } from '../generators/briefing-md.js';
|
|
15
|
-
import { MARKER, generateAgentsMd, generateClaudeMd, generateCursorMdc, generateCopilotMd } from '../generators/adapters.js';
|
|
16
|
-
import { readCanonicalSkills, readCanonicalRules, generateCursorSkill, generateCursorRule, generateCodexSkill, generateCodexSkillIndex,
|
|
19
|
+
import { MARKER, generateAgentsMd, generateClaudeMd, generateCursorMdc, generateCopilotMd, generateCopilotInstructionFiles } from '../generators/adapters.js';
|
|
20
|
+
import { readCanonicalSkills, readCanonicalRules, readPersonalLayer, readPersonalSkillsLayer, generateCursorSkill, generateCursorRule, generateCodexSkill, generateCodexSkillIndex, shouldEmitToTarget, filterByLevel, validateCodexSkills, evaluateConditions, STAGE_TO_MAX_LEVEL, LEVEL_ORDER, } from '../generators/portable-knowledge.js';
|
|
17
21
|
import { generateChainRules } from '../generators/chain-rules.js';
|
|
22
|
+
import { findNoProjectionAssets } from '../generators/noProjectionAssets.js'; // WP-660 S2 combine
|
|
18
23
|
import { saveHandshakeState, loadPreviousState, diffHandshakeState, formatDiff, buildCurrentState, } from '../generators/handshake-diff.js';
|
|
19
24
|
import { resolveSurfaceProfile } from '../generators/surface-profiles.js';
|
|
20
25
|
import { formatHandshakeReport } from '../formatters/handshake.js';
|
|
26
|
+
import { classifyAdapterFile, detectEol, spliceAppend, spliceReplace } from '../generators/region.js';
|
|
27
|
+
import { REGION_PROJECTIONS } from '../generators/region-projections.js';
|
|
28
|
+
import { readManifest, readManifestStatus, filterByAdoptionState } from '../generators/manifest.js';
|
|
29
|
+
import { generateBoundaryManifest, getBoundaryEnforcementMode } from '../generators/boundary-manifest.js';
|
|
30
|
+
import { loadMethodRegistry } from '../lib/method-registry.js';
|
|
21
31
|
import { CLIError, ErrorCode } from '../lib/errors.js';
|
|
32
|
+
import { trackEvent } from '../lib/telemetry.js';
|
|
33
|
+
import { isJsonMode } from '../lib/runner.js';
|
|
34
|
+
import { stripConvexInternals } from '../lib/strip.js';
|
|
35
|
+
import { replaceVocabTokens } from '../lib/canonicalRefs.js';
|
|
36
|
+
// WP-436 S3: vocab projector — resolves {{vocab:...}} tokens before writing to disk.
|
|
37
|
+
import { getOrFetchVocabCtx } from '../lib/workspaceVocabCache.js';
|
|
38
|
+
import { normalizeMaterializedFilename } from '../lib/normalizeMaterializedFilename.js';
|
|
39
|
+
import { findLeftoverCursorSkills, LEFTOVER_FILES_MAX } from './handshakeCursorSkillCleanup.js';
|
|
40
|
+
import { classifyDriftBucket } from './handshakeDriftClassification.js';
|
|
41
|
+
import { parseSetupFrontmatter } from '../lib/frontmatter.js';
|
|
42
|
+
import { sanitizeStartupResolutionSignals } from '../lib/startup-resolution-signals.js';
|
|
43
|
+
import { assertSetupWritePath } from '../setup/perimeter.js';
|
|
44
|
+
// WP-421 S3: SurfaceAdapter reverse-map for tampered prompts (DEC-952, doneWhen #34).
|
|
45
|
+
import { canonicalPathForAnySurface, SURFACE_GOVERN_NO_SURFACES, SURFACE_REGISTRY, validateSurfacesForMode, } from '../surfaces/registry.js';
|
|
46
|
+
import { getReverseMapFallbackMessage, reportReverseMapMissing } from '../surfaces/telemetry.js';
|
|
22
47
|
const LEVELS = {
|
|
23
48
|
guide: {
|
|
24
49
|
label: 'Guide me',
|
|
@@ -47,12 +72,8 @@ const LEVELS = {
|
|
|
47
72
|
};
|
|
48
73
|
// Explicit ordering — determines menu numbering in promptLevel(). Do not reorder.
|
|
49
74
|
const LEVEL_KEYS = ['guide', 'work', 'silent', 'full-trust'];
|
|
50
|
-
// Hook failure contract (TEN-712):
|
|
51
|
-
// so Claude Code always starts even if pb is unavailable. Never remove this suffix.
|
|
75
|
+
// Hook failure contract (TEN-712): every hook command MUST end with '|| true' so Claude Code always starts even if pb is unavailable.
|
|
52
76
|
const INIT_PERMISSION = 'Bash(pb:*)';
|
|
53
|
-
const INIT_SESSION_START_CMD = 'pb session start 2>/dev/null || true';
|
|
54
|
-
const INIT_SESSION_CLOSE_CMD = 'pb session close 2>/dev/null || true';
|
|
55
|
-
const INIT_PRECOMPACT_CMD = 'pb session id > /dev/null 2>&1 && echo \'{"systemMessage": "pb session active — capture decisions/tensions before compacting: pb capture \\"DEC: ...\\""}\' || true';
|
|
56
77
|
function readSettings(filePath) {
|
|
57
78
|
if (!existsSync(filePath))
|
|
58
79
|
return {};
|
|
@@ -64,9 +85,6 @@ function readSettings(filePath) {
|
|
|
64
85
|
return {};
|
|
65
86
|
}
|
|
66
87
|
}
|
|
67
|
-
function hasCommand(groups, cmd) {
|
|
68
|
-
return (groups ?? []).some((g) => g.hooks?.some((h) => h.command === cmd));
|
|
69
|
-
}
|
|
70
88
|
// Team write: hooks + Bash(pb:*) → .claude/settings.json (safe to commit)
|
|
71
89
|
function writeTeamSettings(cwd, dryRun) {
|
|
72
90
|
const claudeDir = join(cwd, '.claude');
|
|
@@ -82,26 +100,10 @@ function writeTeamSettings(cwd, dryRun) {
|
|
|
82
100
|
}
|
|
83
101
|
settings.permissions = permissions;
|
|
84
102
|
const hooks = (settings.hooks ?? {});
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
];
|
|
90
|
-
added.push('SessionStart → pb session start');
|
|
91
|
-
}
|
|
92
|
-
if (!hasCommand(hooks.Stop, INIT_SESSION_CLOSE_CMD)) {
|
|
93
|
-
hooks.Stop = [
|
|
94
|
-
...(hooks.Stop ?? []),
|
|
95
|
-
{ hooks: [{ type: 'command', command: INIT_SESSION_CLOSE_CMD, statusMessage: 'Closing pb session...' }] },
|
|
96
|
-
];
|
|
97
|
-
added.push('Stop → pb session close');
|
|
98
|
-
}
|
|
99
|
-
if (!hasCommand(hooks.PreCompact, INIT_PRECOMPACT_CMD)) {
|
|
100
|
-
hooks.PreCompact = [
|
|
101
|
-
...(hooks.PreCompact ?? []),
|
|
102
|
-
{ hooks: [{ type: 'command', command: INIT_PRECOMPACT_CMD }] },
|
|
103
|
-
];
|
|
104
|
-
added.push('PreCompact → decision capture reminder');
|
|
103
|
+
const hookAdditions = composeHooksFromIntents(['session-start', 'session-close', 'pre-compact'], hooks);
|
|
104
|
+
for (const addition of hookAdditions) {
|
|
105
|
+
hooks[addition.event] = [...(hooks[addition.event] ?? []), addition.entry];
|
|
106
|
+
added.push(addition.label);
|
|
105
107
|
}
|
|
106
108
|
settings.hooks = hooks;
|
|
107
109
|
if (!dryRun) {
|
|
@@ -171,8 +173,7 @@ export async function runHandshakeInit(options = {}) {
|
|
|
171
173
|
for (const item of teamAdded)
|
|
172
174
|
console.log(` + ${item}`);
|
|
173
175
|
}
|
|
174
|
-
// Step 2: Personal config — wizard or --level flag
|
|
175
|
-
// Cast is safe: LEVEL_KEYS.includes() validated above; invalid level already threw CLIError.
|
|
176
|
+
// Step 2: Personal config — wizard or --level flag. Cast is safe: LEVEL_KEYS.includes() validated above.
|
|
176
177
|
const levelKey = options.level ? options.level : await promptLevel();
|
|
177
178
|
const level = LEVELS[levelKey];
|
|
178
179
|
const personalAdded = writePersonalSettings(levelKey, dryRun);
|
|
@@ -194,6 +195,27 @@ export async function runHandshakeInit(options = {}) {
|
|
|
194
195
|
if (!dryRun)
|
|
195
196
|
console.log('Reload /hooks in Claude Code (or restart) to activate.');
|
|
196
197
|
console.log('Run `pb handshake --init --level <guide|work|silent|full-trust>` to change level.');
|
|
198
|
+
// Step 2b: Report multi-surface hook opt-in status (WP-310 E3b) — manifest.hooks.{cursor,copilot}, silence = no manifest/flags (DEC-536).
|
|
199
|
+
const pbDirForManifest = join(cwd, '.productbrain');
|
|
200
|
+
const initManifest = readManifest(pbDirForManifest);
|
|
201
|
+
const multiSurfaceOptIns = [];
|
|
202
|
+
if (initManifest?.hooks?.cursor)
|
|
203
|
+
multiSurfaceOptIns.push('cursor');
|
|
204
|
+
if (initManifest?.hooks?.copilot)
|
|
205
|
+
multiSurfaceOptIns.push('copilot');
|
|
206
|
+
if (multiSurfaceOptIns.length > 0) {
|
|
207
|
+
console.log('');
|
|
208
|
+
for (const surface of multiSurfaceOptIns) {
|
|
209
|
+
const status = getHookStatusForSurface(surface);
|
|
210
|
+
if (status.writable) {
|
|
211
|
+
// Future-proofing path: surface has hook events, would write files.
|
|
212
|
+
console.log(`ℹ ${surface} hooks: opted in — hooks will be written`);
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
console.log(`ℹ ${surface} hooks: opted in — no auto-hooks (${surface} has no session events; run \`pb session start\` manually)`);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
197
219
|
// Step 3: Scaffold starter templates if .productbrain/rules/ is empty
|
|
198
220
|
const rulesDir = join(cwd, '.productbrain', 'rules');
|
|
199
221
|
const hasExistingRules = existsSync(rulesDir) && readdirSync(rulesDir).filter((f) => f.endsWith('.md')).length > 0;
|
|
@@ -242,24 +264,385 @@ export async function runHandshakeInit(options = {}) {
|
|
|
242
264
|
}
|
|
243
265
|
}
|
|
244
266
|
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
267
|
+
const LOCAL_REF_REGEX = /\b(?:WP|TEN|DEC|BET|FEAT|INS|STD|PRI|ARCH)[-\s#]*\d+\b|\bPR\s*#?\s*\d+\b/gi;
|
|
268
|
+
const STARTUP_RESOLUTION_RESOLVER_VERSION = 'startup-resolution-v1';
|
|
269
|
+
// Global cap on collected refs (spec "Contract: StartupResolutionSignals" — arrays are capped).
|
|
270
|
+
const LOCAL_REF_GLOBAL_CAP = 25;
|
|
271
|
+
// Per-source cap so a broad source (context.md) can't starve briefing.md's task-specific refs (Codex@677).
|
|
272
|
+
const LOCAL_REF_PER_SOURCE_CAP = 18;
|
|
273
|
+
// Time-boxed so an unauthed/slow `gh` can't stall session-start (F4).
|
|
274
|
+
const PR_DIFF_TIMEOUT_MS = 4_000;
|
|
275
|
+
// Bounds worst-case `gh` subprocess invocations per handshake.
|
|
276
|
+
const PR_DIFF_MAX_REFS = 5;
|
|
277
|
+
function runGitText(cwd, command) {
|
|
278
|
+
try {
|
|
279
|
+
const value = execSync(command, {
|
|
280
|
+
cwd,
|
|
281
|
+
encoding: 'utf8',
|
|
282
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
283
|
+
}).trim();
|
|
284
|
+
return value.length > 0 ? value : undefined;
|
|
285
|
+
}
|
|
286
|
+
catch {
|
|
287
|
+
return undefined;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
/** Dereference a "PR #N" ref to its changed paths via `gh pr diff <N> --name-only` (F4: server
|
|
291
|
+
* resolver has no git/gh access). Guarded/time-boxed; `run` is injectable for tests. */
|
|
292
|
+
export function dereferencePrRefToPaths(cwd, prNumber, run = runGitTextTimeboxed) {
|
|
293
|
+
if (!Number.isInteger(prNumber) || prNumber <= 0)
|
|
294
|
+
return [];
|
|
295
|
+
const raw = run(cwd, `gh pr diff ${prNumber} --name-only`, PR_DIFF_TIMEOUT_MS);
|
|
296
|
+
if (!raw)
|
|
297
|
+
return [];
|
|
298
|
+
return raw.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
|
|
299
|
+
}
|
|
300
|
+
/** Time-boxed variant of runGitText for the PR-diff dereference (F4). */
|
|
301
|
+
function runGitTextTimeboxed(cwd, command, timeoutMs) {
|
|
302
|
+
try {
|
|
303
|
+
const value = execSync(command, {
|
|
304
|
+
cwd,
|
|
305
|
+
encoding: 'utf8',
|
|
306
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
307
|
+
timeout: timeoutMs,
|
|
308
|
+
}).trim();
|
|
309
|
+
return value.length > 0 ? value : undefined;
|
|
310
|
+
}
|
|
311
|
+
catch {
|
|
312
|
+
return undefined;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
function readOptionalLocalText(cwd, path) {
|
|
316
|
+
const fullPath = join(cwd, path);
|
|
317
|
+
if (!existsSync(fullPath))
|
|
318
|
+
return undefined;
|
|
319
|
+
try {
|
|
320
|
+
return readFileSync(fullPath, 'utf8');
|
|
321
|
+
}
|
|
322
|
+
catch {
|
|
323
|
+
return undefined;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
function normalizeLocalRef(ref) {
|
|
327
|
+
const trimmed = ref.trim().replace(/\s+/g, ' ');
|
|
328
|
+
const pr = trimmed.match(/^PR\s*#?\s*(\d+)$/i);
|
|
329
|
+
if (pr)
|
|
330
|
+
return `PR #${pr[1]}`;
|
|
331
|
+
const entry = trimmed.match(/^([A-Z]+)[-\s#]*(\d+)$/i);
|
|
332
|
+
if (entry)
|
|
333
|
+
return `${entry[1].toUpperCase()}-${entry[2]}`;
|
|
334
|
+
return trimmed;
|
|
335
|
+
}
|
|
336
|
+
/** Collect normalized local refs across several text sources, deduped. Codex@677: a per-source
|
|
337
|
+
* cap alongside the global one, so a broad source (context.md) can't starve a later,
|
|
338
|
+
* task-specific source (briefing.md); already-collected refs dedupe without spending later quota. */
|
|
339
|
+
function collectLocalRefs(texts) {
|
|
340
|
+
const refs = [];
|
|
341
|
+
const seen = new Set();
|
|
342
|
+
for (const text of texts) {
|
|
343
|
+
if (!text)
|
|
344
|
+
continue;
|
|
345
|
+
let fromThisSource = 0;
|
|
346
|
+
for (const match of text.matchAll(LOCAL_REF_REGEX)) {
|
|
347
|
+
const ref = normalizeLocalRef(match[0]);
|
|
348
|
+
const key = ref.toLowerCase();
|
|
349
|
+
if (seen.has(key))
|
|
350
|
+
continue;
|
|
351
|
+
if (fromThisSource >= LOCAL_REF_PER_SOURCE_CAP)
|
|
352
|
+
break;
|
|
353
|
+
seen.add(key);
|
|
354
|
+
refs.push(ref);
|
|
355
|
+
fromThisSource++;
|
|
356
|
+
if (refs.length >= LOCAL_REF_GLOBAL_CAP)
|
|
357
|
+
return refs;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
return refs;
|
|
361
|
+
}
|
|
362
|
+
function deriveHandshakeStartupTask(refs, changedPaths, callerTask) {
|
|
363
|
+
if (callerTask && callerTask.trim())
|
|
364
|
+
return callerTask.trim();
|
|
365
|
+
const parts = [];
|
|
366
|
+
if (refs.length > 0)
|
|
367
|
+
parts.push(refs.join(' '));
|
|
368
|
+
if (changedPaths.length > 0)
|
|
369
|
+
parts.push(`changed paths ${changedPaths.slice(0, 5).join(' ')}`);
|
|
370
|
+
return parts.length > 0 ? parts.join(' ') : undefined;
|
|
371
|
+
}
|
|
372
|
+
const DEFAULT_HANDSHAKE_SIGNAL_DEPS = {
|
|
373
|
+
runGit: runGitText,
|
|
374
|
+
prDiff: (cwd, prNumber) => dereferencePrRefToPaths(cwd, prNumber),
|
|
375
|
+
};
|
|
376
|
+
/** Extract the PR number from a normalized "PR #N" ref, else null. */
|
|
377
|
+
function prNumberFromRef(ref) {
|
|
378
|
+
const m = ref.match(/^PR\s*#?\s*(\d+)$/i);
|
|
379
|
+
if (!m)
|
|
380
|
+
return null;
|
|
381
|
+
const n = Number(m[1]);
|
|
382
|
+
return Number.isInteger(n) && n > 0 ? n : null;
|
|
383
|
+
}
|
|
384
|
+
export function deriveHandshakeStartupSignals(cwd, callerSignals = {}, deps = DEFAULT_HANDSHAKE_SIGNAL_DEPS) {
|
|
385
|
+
const { runGit, prDiff } = deps;
|
|
386
|
+
const branchName = runGit(cwd, 'git branch --show-current');
|
|
387
|
+
const commitSha = runGit(cwd, 'git rev-parse --short HEAD');
|
|
388
|
+
// Changed paths, unioned + deduped: (1) dirty worktree; (2) committed branch delta vs origin/main's
|
|
389
|
+
// merge-base (Codex@665, invisible once the tree is clean); (3) PR-ref dereference (F4), appended later.
|
|
390
|
+
const dirtyChangedPaths = runGit(cwd, 'git diff --name-only HEAD')?.split(/\r?\n/).filter(Boolean) ?? [];
|
|
391
|
+
const mergeBase = runGit(cwd, 'git merge-base HEAD origin/main');
|
|
392
|
+
const branchChangedPaths = mergeBase
|
|
393
|
+
? (runGit(cwd, `git diff --name-only ${mergeBase} HEAD`)?.split(/\r?\n/).filter(Boolean) ?? [])
|
|
394
|
+
: [];
|
|
395
|
+
const worktreeName = basename(cwd);
|
|
396
|
+
const contextText = readOptionalLocalText(cwd, '.productbrain/context.md');
|
|
397
|
+
const briefingText = readOptionalLocalText(cwd, '.productbrain/briefing.md');
|
|
398
|
+
const callerRefs = Array.isArray(callerSignals.reviewedArtifactRefs) ? callerSignals.reviewedArtifactRefs.join('\n') : undefined;
|
|
399
|
+
// Codex@677: briefing.md (task-specific) reads BEFORE context.md (broad) so its refs collect first — with the per-source cap, context.md can't starve briefing.
|
|
400
|
+
const refs = collectLocalRefs([
|
|
401
|
+
callerSignals.taskText ?? undefined,
|
|
402
|
+
callerSignals.explicitScope ?? undefined,
|
|
403
|
+
callerRefs,
|
|
404
|
+
branchName,
|
|
405
|
+
worktreeName,
|
|
406
|
+
briefingText,
|
|
407
|
+
contextText,
|
|
408
|
+
]);
|
|
409
|
+
// F4: dereference "PR #N" refs to diff paths, folded into changedPaths — the only place this can happen (server records dereferenced:false, no git access). Time-boxed; absent/unauthed gh no-ops.
|
|
410
|
+
const prDiffPaths = [];
|
|
411
|
+
if (callerSignals.changedPaths === undefined) {
|
|
412
|
+
let derefed = 0;
|
|
413
|
+
for (const ref of refs) {
|
|
414
|
+
const prNumber = prNumberFromRef(ref);
|
|
415
|
+
if (prNumber === null)
|
|
416
|
+
continue;
|
|
417
|
+
if (derefed >= PR_DIFF_MAX_REFS)
|
|
418
|
+
break;
|
|
419
|
+
derefed++;
|
|
420
|
+
try {
|
|
421
|
+
for (const p of prDiff(cwd, prNumber))
|
|
422
|
+
prDiffPaths.push(p);
|
|
423
|
+
}
|
|
424
|
+
catch {
|
|
425
|
+
// gh absent / unauthed / PR missing — skip gracefully, leave existing behavior.
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
// Caller-supplied changedPaths win (backward compat); otherwise union the
|
|
430
|
+
// three local sources, deduped, order-stable.
|
|
431
|
+
const unionedChangedPaths = callerSignals.changedPaths ??
|
|
432
|
+
Array.from(new Set([...dirtyChangedPaths, ...branchChangedPaths, ...prDiffPaths]));
|
|
433
|
+
const baseSignals = sanitizeStartupResolutionSignals({
|
|
434
|
+
...callerSignals,
|
|
435
|
+
sourceSurface: callerSignals.sourceSurface ?? 'cli',
|
|
436
|
+
resolverVersion: callerSignals.resolverVersion ?? STARTUP_RESOLUTION_RESOLVER_VERSION,
|
|
437
|
+
branchName: callerSignals.branchName ?? branchName,
|
|
438
|
+
worktreeName: callerSignals.worktreeName ?? worktreeName,
|
|
439
|
+
changedPaths: unionedChangedPaths,
|
|
440
|
+
reviewedArtifactRefs: callerSignals.reviewedArtifactRefs ?? refs,
|
|
441
|
+
commitSha: callerSignals.commitSha ?? commitSha,
|
|
442
|
+
});
|
|
443
|
+
const taskText = deriveHandshakeStartupTask(baseSignals.reviewedArtifactRefs ?? [], baseSignals.changedPaths ?? [], baseSignals.taskText);
|
|
444
|
+
const sanitized = sanitizeStartupResolutionSignals({
|
|
445
|
+
...baseSignals,
|
|
446
|
+
taskText,
|
|
447
|
+
});
|
|
448
|
+
const hasMeaningfulEvidence = Boolean(sanitized.taskText) ||
|
|
449
|
+
(sanitized.changedPaths?.length ?? 0) > 0 ||
|
|
450
|
+
(sanitized.reviewedArtifactRefs?.length ?? 0) > 0 ||
|
|
451
|
+
Boolean(sanitized.explicitScope);
|
|
452
|
+
if (hasMeaningfulEvidence)
|
|
453
|
+
return sanitized;
|
|
454
|
+
// Codex@704: even with no evidence, emit a minimal envelope carrying attribution — {} would
|
|
455
|
+
// drop the whole startup block, losing the loud domain-unresolved signal (spec "Loud Unresolved State", AC #4).
|
|
456
|
+
return sanitizeStartupResolutionSignals({
|
|
457
|
+
sourceSurface: sanitized.sourceSurface ?? 'cli',
|
|
458
|
+
resolverVersion: sanitized.resolverVersion ?? STARTUP_RESOLUTION_RESOLVER_VERSION,
|
|
459
|
+
branchName: sanitized.branchName,
|
|
460
|
+
worktreeName: sanitized.worktreeName,
|
|
461
|
+
commitSha: sanitized.commitSha,
|
|
462
|
+
changeId: sanitized.changeId,
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
/** Normalize volatile handshake-only timestamps before comparing generated files — keeps visible
|
|
466
|
+
* timestamps in artifacts while avoiding meaningless rewrites when content is unchanged. */
|
|
250
467
|
export function normalizeHandshakeContentForComparison(content) {
|
|
251
468
|
return content
|
|
252
469
|
.replace(/<!-- auto-generated by pb handshake — [0-9]{4}-[0-9]{2}-[0-9]{2}T[^>]+ -->/g, '<!-- auto-generated by pb handshake — <TIMESTAMP> -->')
|
|
253
470
|
.replace(/^_Generated: [0-9]{4}-[0-9]{2}-[0-9]{2}T.*_$/gm, '_Generated: <TIMESTAMP>_');
|
|
254
471
|
}
|
|
255
472
|
function shouldWriteAdapter(filePath, force) {
|
|
256
|
-
|
|
257
|
-
return true;
|
|
473
|
+
// An absent file at an adapter path is a projection target → materialize it.
|
|
258
474
|
if (!existsSync(filePath))
|
|
259
475
|
return true;
|
|
260
476
|
const content = readFileSync(filePath, 'utf8');
|
|
477
|
+
// No MARKER → user-owned/committed-static (CLAUDE.md, AGENTS.md, Copilot instructions) — never overwritten, not even under --force.
|
|
478
|
+
void force;
|
|
261
479
|
return content.includes(MARKER);
|
|
262
480
|
}
|
|
481
|
+
function normalizeSurfaceName(surface) {
|
|
482
|
+
const stripped = surface.startsWith('.') ? surface.slice(1) : surface;
|
|
483
|
+
const normalized = stripped === 'github' ? 'copilot' : stripped;
|
|
484
|
+
return normalized in SURFACE_REGISTRY ? normalized : null;
|
|
485
|
+
}
|
|
486
|
+
function surfacePerimeterRoots(surface) {
|
|
487
|
+
if (surface === 'codex')
|
|
488
|
+
return ['.codex', SURFACE_REGISTRY.codex.hookFilePath];
|
|
489
|
+
if (surface === 'copilot')
|
|
490
|
+
return ['.github', SURFACE_REGISTRY.copilot.hookFilePath];
|
|
491
|
+
if (surface === 'claude')
|
|
492
|
+
return ['.claude', 'CLAUDE.md'];
|
|
493
|
+
return [`.${surface}`];
|
|
494
|
+
}
|
|
495
|
+
function modeRank(mode) {
|
|
496
|
+
return { off: 0, observe: 1, project: 2, govern: 3 }[mode];
|
|
497
|
+
}
|
|
498
|
+
function normalizeSetupAuthoringBody(body) {
|
|
499
|
+
return body.replace(/\r\n/g, '\n').replace(/\r/g, '\n').trimEnd();
|
|
500
|
+
}
|
|
501
|
+
function setupAuthoringAssetHash(asset) {
|
|
502
|
+
const canonical = {
|
|
503
|
+
entryId: asset.entryId,
|
|
504
|
+
name: asset.name,
|
|
505
|
+
description: asset.description ?? '',
|
|
506
|
+
assetKind: asset.assetKind,
|
|
507
|
+
triggers: asset.triggers ?? [],
|
|
508
|
+
semanticRefs: asset.semanticRefs ?? [],
|
|
509
|
+
body: normalizeSetupAuthoringBody(asset.body),
|
|
510
|
+
};
|
|
511
|
+
return `sha256:${createHash('sha256').update(JSON.stringify(canonical), 'utf8').digest('hex')}`;
|
|
512
|
+
}
|
|
513
|
+
function parseSetupAuthoringFrontmatter(raw) {
|
|
514
|
+
// Shared parser (lib/frontmatter.ts): array-item quotes strip exactly as before, now canonical
|
|
515
|
+
// for migrate-setup/setup-ingest too. `assetKind` ignored (handshake derives kind from dir).
|
|
516
|
+
const parsed = parseSetupFrontmatter(raw);
|
|
517
|
+
return {
|
|
518
|
+
frontmatterId: parsed.frontmatterId,
|
|
519
|
+
name: parsed.name,
|
|
520
|
+
description: parsed.description,
|
|
521
|
+
body: parsed.body,
|
|
522
|
+
triggers: parsed.triggers,
|
|
523
|
+
semanticRefs: parsed.semanticRefs,
|
|
524
|
+
};
|
|
525
|
+
}
|
|
526
|
+
function deriveSetupAuthoringEntryId(filename, kind) {
|
|
527
|
+
const base = basename(filename, '.md');
|
|
528
|
+
const snakeCase = base.toUpperCase().replace(/[^A-Z0-9]+/g, '_');
|
|
529
|
+
return `SETUP-${kind.toUpperCase()}-${snakeCase}`;
|
|
530
|
+
}
|
|
531
|
+
function scanSetupAuthoringFiles(productbrainDir) {
|
|
532
|
+
const dirs = [
|
|
533
|
+
{ dir: 'skills', kind: 'skill' },
|
|
534
|
+
{ dir: 'rules', kind: 'rule' },
|
|
535
|
+
{ dir: 'hooks', kind: 'hook' },
|
|
536
|
+
];
|
|
537
|
+
const items = [];
|
|
538
|
+
for (const { dir, kind } of dirs) {
|
|
539
|
+
const absDir = join(productbrainDir, dir);
|
|
540
|
+
if (!existsSync(absDir))
|
|
541
|
+
continue;
|
|
542
|
+
for (const file of readdirSync(absDir).filter((f) => f.endsWith('.md'))) {
|
|
543
|
+
const filePath = join(absDir, file);
|
|
544
|
+
const parsed = parseSetupAuthoringFrontmatter(readFileSync(filePath, 'utf8'));
|
|
545
|
+
const fallbackName = basename(file, '.md');
|
|
546
|
+
items.push({
|
|
547
|
+
filePath,
|
|
548
|
+
derivedEntryId: deriveSetupAuthoringEntryId(file, kind),
|
|
549
|
+
frontmatterId: parsed.frontmatterId,
|
|
550
|
+
name: parsed.name || fallbackName,
|
|
551
|
+
description: parsed.description,
|
|
552
|
+
body: parsed.body,
|
|
553
|
+
assetKind: kind,
|
|
554
|
+
triggers: parsed.triggers,
|
|
555
|
+
semanticRefs: parsed.semanticRefs,
|
|
556
|
+
});
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
return items.sort((a, b) => a.filePath.localeCompare(b.filePath));
|
|
560
|
+
}
|
|
561
|
+
function setupAuthoringDirForKind(kind) {
|
|
562
|
+
if (kind === 'skill')
|
|
563
|
+
return 'skills';
|
|
564
|
+
if (kind === 'rule')
|
|
565
|
+
return 'rules';
|
|
566
|
+
if (kind === 'hook')
|
|
567
|
+
return 'hooks';
|
|
568
|
+
return null;
|
|
569
|
+
}
|
|
570
|
+
function setupAuthoringFilename(name, entryId) {
|
|
571
|
+
const base = (name || entryId)
|
|
572
|
+
.replace(/[\/\\:*?"<>|]/g, '-')
|
|
573
|
+
.replace(/\s+/g, ' ')
|
|
574
|
+
.trim();
|
|
575
|
+
return `${base || entryId}.md`;
|
|
576
|
+
}
|
|
577
|
+
function setupAuthoringPath(cwd, asset) {
|
|
578
|
+
const dir = setupAuthoringDirForKind(asset.assetKind);
|
|
579
|
+
if (!dir)
|
|
580
|
+
return null;
|
|
581
|
+
// WP-426 E3: recorded authoring source path wins so reprojection lands where the
|
|
582
|
+
// user authored — no duplicate (TEN-1920). Stored relative to .productbrain/.
|
|
583
|
+
if (asset.authoringPath && asset.authoringPath.trim()) {
|
|
584
|
+
// Codex P1/P2: authoringPath is untrusted DB data, probed before any assertSetupWritePath guard runs —
|
|
585
|
+
// constrain to a kind-appropriate markdown file, else fall back to the safe name-derived path.
|
|
586
|
+
const pbDir = join(cwd, '.productbrain');
|
|
587
|
+
const candidate = resolve(pbDir, asset.authoringPath);
|
|
588
|
+
const within = relative(pbDir, candidate);
|
|
589
|
+
const withinPosix = within.split(sep).join('/');
|
|
590
|
+
if (!within.startsWith('..') &&
|
|
591
|
+
!isAbsolute(within) &&
|
|
592
|
+
withinPosix.startsWith(`${dir}/`) &&
|
|
593
|
+
withinPosix.toLowerCase().endsWith('.md')) {
|
|
594
|
+
return candidate;
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
return join(cwd, '.productbrain', dir, setupAuthoringFilename(asset.name, asset.entryId));
|
|
598
|
+
}
|
|
599
|
+
function renderSetupAuthoringFile(asset) {
|
|
600
|
+
const lines = [
|
|
601
|
+
'---',
|
|
602
|
+
`id: ${asset.entryId}`,
|
|
603
|
+
`name: ${JSON.stringify(asset.name)}`,
|
|
604
|
+
`description: ${JSON.stringify(asset.description ?? '')}`,
|
|
605
|
+
`assetKind: ${asset.assetKind}`,
|
|
606
|
+
];
|
|
607
|
+
const pushArray = (key, values) => {
|
|
608
|
+
if (!values || values.length === 0)
|
|
609
|
+
return;
|
|
610
|
+
lines.push(`${key}:`);
|
|
611
|
+
for (const value of values)
|
|
612
|
+
lines.push(` - ${JSON.stringify(value)}`);
|
|
613
|
+
};
|
|
614
|
+
pushArray('triggers', asset.triggers);
|
|
615
|
+
pushArray('semanticRefs', asset.semanticRefs);
|
|
616
|
+
lines.push('---', normalizeSetupAuthoringBody(asset.body), '');
|
|
617
|
+
return lines.join('\n');
|
|
618
|
+
}
|
|
619
|
+
function loadAuthoringSyncState(productbrainDir) {
|
|
620
|
+
const statePath = join(productbrainDir, '.authoring-sync.json');
|
|
621
|
+
if (!existsSync(statePath))
|
|
622
|
+
return { version: 1, assets: {} };
|
|
623
|
+
try {
|
|
624
|
+
const parsed = JSON.parse(readFileSync(statePath, 'utf8'));
|
|
625
|
+
if (parsed.version !== 1 || !parsed.assets || typeof parsed.assets !== 'object') {
|
|
626
|
+
return { version: 1, assets: {} };
|
|
627
|
+
}
|
|
628
|
+
return {
|
|
629
|
+
version: 1,
|
|
630
|
+
assets: parsed.assets,
|
|
631
|
+
};
|
|
632
|
+
}
|
|
633
|
+
catch {
|
|
634
|
+
return { version: 1, assets: {} };
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
function saveAuthoringSyncState(productbrainDir, state) {
|
|
638
|
+
const statePath = join(productbrainDir, '.authoring-sync.json');
|
|
639
|
+
assertSetupWritePath(statePath, { surfaces: [] });
|
|
640
|
+
mkdirSync(productbrainDir, { recursive: true });
|
|
641
|
+
writeFileSync(statePath, JSON.stringify(state, null, 2) + '\n');
|
|
642
|
+
}
|
|
643
|
+
// ── WP-421 S3: Three-bucket drift classification (doneWhen #17) — now its own module (STD-2/DEC-1504
|
|
644
|
+
// shrink-only offset). Re-exported so existing imports `from '../commands/handshake.js'` keep working.
|
|
645
|
+
export { classifyDriftBucket };
|
|
263
646
|
function deduplicateEntries(entries) {
|
|
264
647
|
const seen = new Set();
|
|
265
648
|
const result = [];
|
|
@@ -272,19 +655,128 @@ function deduplicateEntries(entries) {
|
|
|
272
655
|
}
|
|
273
656
|
return result;
|
|
274
657
|
}
|
|
658
|
+
/**
|
|
659
|
+
* findLeftoverProjections — WP-379 S5b
|
|
660
|
+
*
|
|
661
|
+
* Lists marker-bearing files under .cursor/rules/, .claude/rules/, .claude/skills/, .codex/skills/
|
|
662
|
+
* (plus the nested .cursor/skills/<name>/SKILL.md layout) that look stale: orphan (no canonical
|
|
663
|
+
* asset), stale case/punctuation variant, or a leftover `.dormant` copy. User-owned (no MARKER)
|
|
664
|
+
* files and unselected `allowedTargets` are never reported.
|
|
665
|
+
*
|
|
666
|
+
* Round 12: stops once `LEFTOVER_FILES_MAX + 1` matches are found across the flat + merged
|
|
667
|
+
* nested-Cursor scan combined — bounds read/enumerate I/O, not just the reported list.
|
|
668
|
+
* `truncated` says more exist beyond the capped, returned `files`.
|
|
669
|
+
*
|
|
670
|
+
* @param cursorSkillNames Cursor-specific, SKILL-kind-only canon (falls back to `assetNames`).
|
|
671
|
+
* @param exactRelativePaths Round 11: exact write-plan paths (forward-slash), exempted from both
|
|
672
|
+
* checks — covers asset-less generated files and a canonical raw name not already normalized.
|
|
673
|
+
*/
|
|
674
|
+
export function findLeftoverProjections(cwd, assetNames, allowedTargets, cursorSkillNames, exactRelativePaths) {
|
|
675
|
+
const TARGET_DIRS_BY_EXT = [
|
|
676
|
+
{ dir: join(cwd, '.cursor', 'rules'), ext: '.mdc', surface: 'cursor' },
|
|
677
|
+
{ dir: join(cwd, '.claude', 'rules'), ext: '.md', surface: 'claude' },
|
|
678
|
+
{ dir: join(cwd, '.claude', 'skills'), ext: '.md', surface: 'claude' },
|
|
679
|
+
{ dir: join(cwd, '.codex', 'skills'), ext: '.md', surface: 'codex' },
|
|
680
|
+
];
|
|
681
|
+
const canonicalNormalizedStems = new Set(assetNames.map((n) => normalizeMaterializedFilename(n)));
|
|
682
|
+
const exactPaths = exactRelativePaths ?? new Set();
|
|
683
|
+
const leftovers = [];
|
|
684
|
+
let truncated = false;
|
|
685
|
+
scanLoop: for (const { dir, ext, surface } of TARGET_DIRS_BY_EXT) {
|
|
686
|
+
if (!allowedTargets.has(surface))
|
|
687
|
+
continue;
|
|
688
|
+
if (!existsSync(dir))
|
|
689
|
+
continue;
|
|
690
|
+
let files;
|
|
691
|
+
try {
|
|
692
|
+
files = readdirSync(dir);
|
|
693
|
+
}
|
|
694
|
+
catch {
|
|
695
|
+
continue; // unreadable dir — skip
|
|
696
|
+
}
|
|
697
|
+
for (const filename of files) {
|
|
698
|
+
if (!filename.endsWith(ext) && !filename.endsWith(`${ext}.dormant`))
|
|
699
|
+
continue;
|
|
700
|
+
const fullPath = join(dir, filename);
|
|
701
|
+
let content;
|
|
702
|
+
try {
|
|
703
|
+
content = readFileSync(fullPath, 'utf8');
|
|
704
|
+
}
|
|
705
|
+
catch {
|
|
706
|
+
continue; // unreadable file — skip
|
|
707
|
+
}
|
|
708
|
+
if (!content.includes(MARKER))
|
|
709
|
+
continue; // user-owned — never reported
|
|
710
|
+
const isDormant = filename.endsWith('.dormant');
|
|
711
|
+
// A live file the write plan targets by this exact path is canonical by construction.
|
|
712
|
+
if (!isDormant) {
|
|
713
|
+
const relativePath = relative(cwd, fullPath).split(sep).join('/');
|
|
714
|
+
if (exactPaths.has(relativePath))
|
|
715
|
+
continue;
|
|
716
|
+
}
|
|
717
|
+
const stem = basename(isDormant ? filename.slice(0, -'.dormant'.length) : filename, ext);
|
|
718
|
+
const normalizedStem = normalizeMaterializedFilename(stem);
|
|
719
|
+
let entry = null;
|
|
720
|
+
if (!canonicalNormalizedStems.has(normalizedStem)) {
|
|
721
|
+
entry = { path: fullPath, reason: 'orphan — no canonical asset matches this name' };
|
|
722
|
+
}
|
|
723
|
+
else if (isDormant) {
|
|
724
|
+
entry = { path: fullPath, reason: 'leftover .dormant file from an older binary version' };
|
|
725
|
+
}
|
|
726
|
+
else if (stem !== normalizedStem) {
|
|
727
|
+
entry = { path: fullPath, reason: `stale case/punctuation variant — canonical form is "${normalizedStem}${ext}"` };
|
|
728
|
+
}
|
|
729
|
+
if (!entry)
|
|
730
|
+
continue;
|
|
731
|
+
leftovers.push(entry);
|
|
732
|
+
if (leftovers.length > LEFTOVER_FILES_MAX) {
|
|
733
|
+
truncated = true;
|
|
734
|
+
leftovers.pop();
|
|
735
|
+
break scanLoop;
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
// Nested Cursor skills — extracted to its own module (STD-2/DEC-1504 shrink-only offset).
|
|
740
|
+
// Skipped once the flat scan already hit the cap; the remaining budget keeps the combined
|
|
741
|
+
// total across both scans stopping at LEFTOVER_FILES_MAX + 1.
|
|
742
|
+
if (!truncated && allowedTargets.has('cursor')) {
|
|
743
|
+
const nested = findLeftoverCursorSkills(cwd, cursorSkillNames ?? assetNames, LEFTOVER_FILES_MAX - leftovers.length);
|
|
744
|
+
leftovers.push(...nested.files);
|
|
745
|
+
truncated = nested.truncated;
|
|
746
|
+
}
|
|
747
|
+
return { files: leftovers, truncated };
|
|
748
|
+
}
|
|
749
|
+
/** Round 13 (Codex P1, security): strips a `user:token@` userinfo segment from an https remote
|
|
750
|
+
* so a credential never reaches JSON output. SSH remotes (`git@host:...`) are untouched — that
|
|
751
|
+
* `git@` is a fixed public username, not a secret. */
|
|
752
|
+
function redactGitRemote(remote) {
|
|
753
|
+
return remote ? remote.replace(/^(https?:\/\/)[^@/]+@/i, '$1') : remote;
|
|
754
|
+
}
|
|
755
|
+
/** Round 13 (Codex P1, security): `pb --json handshake` serialized the report directly — leaking
|
|
756
|
+
* an HTTPS git-remote credential and raw Convex `_id`/`_creationTime` on `matchedEntries` (never
|
|
757
|
+
* went through the shared runner's `stripConvexInternals`). One public shape, both JSON paths. */
|
|
758
|
+
function toPublicJsonReport(report) {
|
|
759
|
+
return stripConvexInternals({ ...report, repo: { ...report.repo, gitRemote: redactGitRemote(report.repo.gitRemote) } });
|
|
760
|
+
}
|
|
275
761
|
export async function runHandshake(options = {}) {
|
|
276
|
-
const config = await getConfigOrGuide(() => runHandshake(options));
|
|
762
|
+
const config = await getConfigOrGuide(async () => { await runHandshake(options); });
|
|
277
763
|
if (!config)
|
|
278
|
-
return;
|
|
764
|
+
return undefined;
|
|
279
765
|
const cwd = process.cwd();
|
|
280
766
|
const force = options.force ?? false;
|
|
281
767
|
const dryRun = options.dryRun ?? false;
|
|
768
|
+
// Preview mode: default when neither --apply nor --dry-run is passed (--dry-run is a backward-compat alias).
|
|
769
|
+
const preview = !options.apply && !dryRun;
|
|
770
|
+
const applyMode = options.apply === true && !dryRun;
|
|
282
771
|
const level = options.level;
|
|
772
|
+
// `quiet` gates the final report write (`--json` alone still prints). `suppressProgress`
|
|
773
|
+
// also silences stdout log() prose in JSON mode. logErr() stays on `quiet` alone (stderr).
|
|
283
774
|
const quiet = options.quiet ?? false;
|
|
775
|
+
const suppressProgress = quiet || isJsonMode();
|
|
284
776
|
const generate = options.generate ?? false;
|
|
285
777
|
const timestamp = new Date().toISOString();
|
|
286
|
-
// Helper: emit progress line only when not
|
|
287
|
-
const log = (msg) => { if (!
|
|
778
|
+
// Helper: emit progress line only when not suppressed. logErr is gated on `quiet` alone.
|
|
779
|
+
const log = (msg) => { if (!suppressProgress)
|
|
288
780
|
process.stdout.write(msg + '\n'); };
|
|
289
781
|
const logErr = (msg) => { if (!quiet)
|
|
290
782
|
process.stderr.write(msg + '\n'); };
|
|
@@ -303,6 +795,15 @@ export async function runHandshake(options = {}) {
|
|
|
303
795
|
if (repo.detectedStack.length > 0) {
|
|
304
796
|
log(`Stack: ${repo.detectedStack.join(', ')}`);
|
|
305
797
|
}
|
|
798
|
+
const startupSignals = deriveHandshakeStartupSignals(cwd, options.startupSignals ?? {});
|
|
799
|
+
const orientArgs = { tier: 'standard' };
|
|
800
|
+
if (options.invocationPath)
|
|
801
|
+
orientArgs.invocationPath = options.invocationPath;
|
|
802
|
+
if (Object.keys(startupSignals).length > 0) {
|
|
803
|
+
orientArgs.startupSignals = startupSignals;
|
|
804
|
+
if (startupSignals.taskText)
|
|
805
|
+
orientArgs.task = startupSignals.taskText;
|
|
806
|
+
}
|
|
306
807
|
// 2. Fetch orient view + workspace readiness in parallel (budget max +200ms added latency)
|
|
307
808
|
log('Fetching workspace context...');
|
|
308
809
|
let orientView = null;
|
|
@@ -310,7 +811,7 @@ export async function runHandshake(options = {}) {
|
|
|
310
811
|
try {
|
|
311
812
|
const workspaceReadinessPromise = kernelCall('chain.workspaceReadiness', {}).catch(() => null);
|
|
312
813
|
const [orientResult, readinessRaw] = await Promise.all([
|
|
313
|
-
kernelCall('chain.getOrientView',
|
|
814
|
+
kernelCall('chain.getOrientView', orientArgs).catch((err) => {
|
|
314
815
|
logErr(`Warning: could not fetch workspace context — ${err instanceof Error ? err.message : err}`);
|
|
315
816
|
logErr('Continuing with limited context (Chain search + portable knowledge only).');
|
|
316
817
|
return null;
|
|
@@ -325,7 +826,7 @@ export async function runHandshake(options = {}) {
|
|
|
325
826
|
logErr('Continuing with limited context (Chain search + portable knowledge only).');
|
|
326
827
|
}
|
|
327
828
|
if (workspaceProfile) {
|
|
328
|
-
log(`Workspace profile: stage=${workspaceProfile.stage}, entries=${workspaceProfile.totalEntries}
|
|
829
|
+
log(`Workspace profile: stage=${workspaceProfile.stage}, entries=${workspaceProfile.totalEntries}`);
|
|
329
830
|
}
|
|
330
831
|
// 3. Build search queries from repo context
|
|
331
832
|
const searchQueries = [];
|
|
@@ -347,10 +848,319 @@ export async function runHandshake(options = {}) {
|
|
|
347
848
|
const searchResults = await Promise.all(uniqueQueries.map((q) => kernelCall('chain.searchEntries', { query: q }).catch(() => [])));
|
|
348
849
|
matchedEntries = deduplicateEntries(searchResults.flat());
|
|
349
850
|
}
|
|
350
|
-
// 5. Read canonical skills & rules
|
|
851
|
+
// 5. Read canonical skills & rules — DB-first (WP-345 S0c, TEN-1459): query setup.listAssetsForUser, FS fallback.
|
|
351
852
|
const pbDir = join(cwd, '.productbrain');
|
|
352
|
-
const
|
|
353
|
-
const
|
|
853
|
+
const manifestStatus = readManifestStatus(pbDir);
|
|
854
|
+
const manifest = manifestStatus.manifest;
|
|
855
|
+
const surfaceValidation = validateSurfacesForMode(manifestStatus.mode, manifestStatus.surfaces);
|
|
856
|
+
if (applyMode && surfaceValidation.error === SURFACE_GOVERN_NO_SURFACES) {
|
|
857
|
+
throw new CLIError('materialize: govern requires at least one registered manifest surface.', {
|
|
858
|
+
code: ErrorCode.VALIDATION_FAILED,
|
|
859
|
+
category: 'validation',
|
|
860
|
+
guidance: 'Add surfaces such as `.cursor` or `.claude` to .productbrain/manifest.yaml.',
|
|
861
|
+
});
|
|
862
|
+
}
|
|
863
|
+
for (const surface of surfaceValidation.unregisteredSurfaces) {
|
|
864
|
+
logErr(`Warning: manifest surface "${surface}" is not registered; skipping it.`);
|
|
865
|
+
}
|
|
866
|
+
const manifestTargets = new Set(surfaceValidation.registeredSurfaces);
|
|
867
|
+
const cliTargets = new Set();
|
|
868
|
+
const ignoredCliSurfaces = [];
|
|
869
|
+
for (const surface of options.surfaces ?? []) {
|
|
870
|
+
const normalized = normalizeSurfaceName(surface);
|
|
871
|
+
if (normalized && manifestTargets.has(normalized)) {
|
|
872
|
+
cliTargets.add(normalized);
|
|
873
|
+
}
|
|
874
|
+
else {
|
|
875
|
+
ignoredCliSurfaces.push(surface);
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
if (ignoredCliSurfaces.length > 0) {
|
|
879
|
+
logErr(`Warning: --surfaces ignored outside manifest.surfaces: ${ignoredCliSurfaces.join(', ')}`);
|
|
880
|
+
}
|
|
881
|
+
const allowedTargets = options.surfaces && options.surfaces.length > 0
|
|
882
|
+
? cliTargets
|
|
883
|
+
: manifestTargets;
|
|
884
|
+
const perimeterManifest = {
|
|
885
|
+
surfaces: [...manifestTargets].flatMap(surfacePerimeterRoots),
|
|
886
|
+
};
|
|
887
|
+
const authorityCanWrite = manifestStatus.mode === 'project' || manifestStatus.mode === 'govern';
|
|
888
|
+
const authorityPreviewOnly = applyMode && !authorityCanWrite;
|
|
889
|
+
const writeMode = applyMode && authorityCanWrite;
|
|
890
|
+
let dbSkills = [];
|
|
891
|
+
let dbRules = [];
|
|
892
|
+
let usedDbSource = false;
|
|
893
|
+
// Codex P2 (PR #912 round 3): distinct from usedDbSource — true whenever the query succeeded
|
|
894
|
+
// (even empty), gating cleanup regardless of a later body-fetch throw; usedDbSource stays the
|
|
895
|
+
// CONTENT-source flag, only true after full success (a throw falls back to the filesystem).
|
|
896
|
+
let dbQuerySucceeded = false;
|
|
897
|
+
let dbAssetRows = [];
|
|
898
|
+
// WP-428 S2 (Finding #5): entryIds whose body fetch failed — hoisted so both the
|
|
899
|
+
// skills/rules AND authoring-file projection loops can skip them.
|
|
900
|
+
const bodyFetchFailedEntryIds = new Set();
|
|
901
|
+
const dbProjectionHashes = new Map();
|
|
902
|
+
const syncDriftTensToFire = [];
|
|
903
|
+
const deferredAuthoringBaselineEntryIds = new Set();
|
|
904
|
+
if (writeMode) {
|
|
905
|
+
const authoringItems = scanSetupAuthoringFiles(pbDir);
|
|
906
|
+
if (authoringItems.length > 0) {
|
|
907
|
+
// WP-428 S2 (Critical #1): ingestSetupAssetWithBody runs per-asset (batch can't call ctx.storage.store()), losing intra-batch collision detection — checked client-side below (replaces server-side DEC-954).
|
|
908
|
+
const idToPaths = new Map();
|
|
909
|
+
for (const item of authoringItems) {
|
|
910
|
+
const canonicalId = item.frontmatterId?.trim() || item.derivedEntryId;
|
|
911
|
+
const paths = idToPaths.get(canonicalId) ?? [];
|
|
912
|
+
paths.push(item.filePath);
|
|
913
|
+
idToPaths.set(canonicalId, paths);
|
|
914
|
+
}
|
|
915
|
+
const conflictingPaths = new Set();
|
|
916
|
+
for (const [, paths] of idToPaths) {
|
|
917
|
+
if (paths.length > 1) {
|
|
918
|
+
for (const p of paths)
|
|
919
|
+
conflictingPaths.add(p);
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
if (conflictingPaths.size > 0) {
|
|
923
|
+
logErr(`Setup authoring import partial: ${conflictingPaths.size} file(s) refused for duplicate setup id. ` +
|
|
924
|
+
[...conflictingPaths].join(', '));
|
|
925
|
+
}
|
|
926
|
+
const itemsToIngest = authoringItems.filter((item) => !conflictingPaths.has(item.filePath));
|
|
927
|
+
if (itemsToIngest.length > 0) {
|
|
928
|
+
try {
|
|
929
|
+
// Parallel uploads — concurrency limit 10 to avoid overwhelming the gateway.
|
|
930
|
+
const CONCURRENCY = 10;
|
|
931
|
+
const ingestResults = [];
|
|
932
|
+
for (let i = 0; i < itemsToIngest.length; i += CONCURRENCY) {
|
|
933
|
+
const batch = itemsToIngest.slice(i, i + CONCURRENCY);
|
|
934
|
+
const settled = await Promise.allSettled(batch.map(async (item) => {
|
|
935
|
+
const result = await kernelCall('setup.ingestSetupAssetWithBody', {
|
|
936
|
+
entryId: item.derivedEntryId,
|
|
937
|
+
frontmatterId: item.frontmatterId,
|
|
938
|
+
name: item.name,
|
|
939
|
+
description: item.description,
|
|
940
|
+
body: item.body,
|
|
941
|
+
assetKind: item.assetKind,
|
|
942
|
+
triggers: item.triggers,
|
|
943
|
+
semanticRefs: item.semanticRefs,
|
|
944
|
+
authoringPath: relative(pbDir, item.filePath).split(sep).join('/'),
|
|
945
|
+
});
|
|
946
|
+
return { filePath: item.filePath, ...result };
|
|
947
|
+
}));
|
|
948
|
+
for (const r of settled) {
|
|
949
|
+
if (r.status === 'fulfilled') {
|
|
950
|
+
ingestResults.push(r.value);
|
|
951
|
+
if (r.value.conflict === 'repo-wins') {
|
|
952
|
+
syncDriftTensToFire.push(`Repo authoring file won setup sync conflict for ${r.value.entryId} at ${r.value.filePath}.`);
|
|
953
|
+
logErr(`Warning: repo authoring file won sync conflict for ${r.value.entryId}; DB edit was overwritten.`);
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
else {
|
|
957
|
+
trackEvent('setup.authoring_import.item_failed', { error: r.reason instanceof Error ? r.reason.message : String(r.reason) });
|
|
958
|
+
logErr(`Warning: setup authoring import failed for one asset — ${r.reason instanceof Error ? r.reason.message : String(r.reason)}`);
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
if (ingestResults.length > 0) {
|
|
963
|
+
log(`Setup authoring import: ${ingestResults.length} file(s) checked (with bodyStorageId).`);
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
catch (err) {
|
|
967
|
+
trackEvent('setup.authoring_import.failed', { error: err instanceof Error ? err.message : String(err) });
|
|
968
|
+
logErr(`Warning: setup authoring import failed — ${err instanceof Error ? err.message : String(err)}`);
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
try {
|
|
974
|
+
// WP-379 S4: only activeAssets projects (DEC-1690); falls back to [] for the old flat-array server shape.
|
|
975
|
+
const rawResponse = await kernelCall('setup.listAssetsForUser', {}).catch(() => null);
|
|
976
|
+
let dbAssets = [];
|
|
977
|
+
if (rawResponse !== null) {
|
|
978
|
+
if (Array.isArray(rawResponse)) {
|
|
979
|
+
// Pre-S4 server — treat entire response as active assets with no dormant list.
|
|
980
|
+
dbAssets = rawResponse;
|
|
981
|
+
}
|
|
982
|
+
else {
|
|
983
|
+
dbAssets = rawResponse.activeAssets ?? [];
|
|
984
|
+
}
|
|
985
|
+
// Successful (even empty) is authoritative, distinct from "unavailable" (catch below) — an
|
|
986
|
+
// empty active set must still gate cleanup on, or a workspace whose last asset was deleted
|
|
987
|
+
// keeps stale projections forever.
|
|
988
|
+
dbQuerySucceeded = true;
|
|
989
|
+
dbAssetRows = dbAssets;
|
|
990
|
+
}
|
|
991
|
+
if (dbAssets.length > 0) {
|
|
992
|
+
// WP-428 S2: body is no longer inline — fetch from storage per non-disabled skill/rule/hook (bounded, parallel).
|
|
993
|
+
const projectableAssets = dbAssets.filter((a) => !a.disabledByOwner && (a.assetKind === 'skill' || a.assetKind === 'rule' || a.assetKind === 'hook'));
|
|
994
|
+
const assetsNeedingBodyFetch = projectableAssets.filter((a) => a.bodyStorageId);
|
|
995
|
+
const bodyFetchMap = new Map(); // entryId → body
|
|
996
|
+
// WP-428 S2 (Finding #5/#12): fetch-failed entryIds excluded from dbSkills/dbRules below (outer-scope bodyFetchFailedEntryIds).
|
|
997
|
+
if (assetsNeedingBodyFetch.length > 0) {
|
|
998
|
+
log(`Fetching ${assetsNeedingBodyFetch.length} asset body(s) from storage...`);
|
|
999
|
+
const bodyFetchResults = await Promise.allSettled(assetsNeedingBodyFetch.map(async (asset) => {
|
|
1000
|
+
const result = await kernelCall('setup.fetchAssetBody', { bodyStorageId: asset.bodyStorageId });
|
|
1001
|
+
return { entryId: asset.entryId, name: asset.name, body: result.body };
|
|
1002
|
+
}));
|
|
1003
|
+
for (let i = 0; i < bodyFetchResults.length; i++) {
|
|
1004
|
+
const result = bodyFetchResults[i];
|
|
1005
|
+
if (result.status === 'fulfilled') {
|
|
1006
|
+
bodyFetchMap.set(result.value.entryId, result.value.body);
|
|
1007
|
+
}
|
|
1008
|
+
else {
|
|
1009
|
+
// WP-428 S2 (Finding #12): include entryId and name in the warning (Finding #5: skip projection).
|
|
1010
|
+
const asset = assetsNeedingBodyFetch[i];
|
|
1011
|
+
logErr(`Warning: failed to fetch body for ${asset.entryId} (${asset.name}) — ${result.reason instanceof Error ? result.reason.message : String(result.reason)}`);
|
|
1012
|
+
bodyFetchFailedEntryIds.add(asset.entryId);
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
if (bodyFetchFailedEntryIds.size > 0) {
|
|
1016
|
+
// WP-439 S4: strict-by-default — a body-fetch failure is hard unless --lenient.
|
|
1017
|
+
const failedList = [...bodyFetchFailedEntryIds].join(', ');
|
|
1018
|
+
if (options.lenient) {
|
|
1019
|
+
logErr(`Warning: ${bodyFetchFailedEntryIds.size} asset(s) skipped due to body fetch failure (--lenient): ${failedList}`);
|
|
1020
|
+
}
|
|
1021
|
+
else {
|
|
1022
|
+
throw new CLIError(`${bodyFetchFailedEntryIds.size} asset(s) failed body fetch: ${failedList}. ` +
|
|
1023
|
+
`Run \`pb setup-audit\` to diagnose, then \`pb setup-audit --repair\` to reseed. ` +
|
|
1024
|
+
`Pass --lenient to suppress this and continue with affected entries skipped (legacy behaviour).`, { code: ErrorCode.INTERNAL, category: 'internal' });
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
// Map DB assets to CanonicalSkill/CanonicalRule shapes
|
|
1029
|
+
for (const asset of dbAssets) {
|
|
1030
|
+
if (asset.disabledByOwner)
|
|
1031
|
+
continue;
|
|
1032
|
+
// WP-428 S2 (Finding #5): skip fetch-failed assets — no empty body written, no lastProjectedHash update.
|
|
1033
|
+
if (bodyFetchFailedEntryIds.has(asset.entryId))
|
|
1034
|
+
continue;
|
|
1035
|
+
// WP-428 S2: prefer storage-fetched body, fall back to inline body (pre-S2 servers, deletable once all servers are S2+).
|
|
1036
|
+
const resolvedBody = bodyFetchMap.get(asset.entryId) ?? asset.body ?? '';
|
|
1037
|
+
if (asset.assetKind === 'skill') {
|
|
1038
|
+
dbSkills.push({
|
|
1039
|
+
name: asset.name,
|
|
1040
|
+
description: asset.description,
|
|
1041
|
+
triggers: asset.triggers ?? [],
|
|
1042
|
+
body: resolvedBody,
|
|
1043
|
+
sourcePath: `db:${asset.entryId}`,
|
|
1044
|
+
});
|
|
1045
|
+
}
|
|
1046
|
+
else if (asset.assetKind === 'rule' || asset.assetKind === 'hook') {
|
|
1047
|
+
dbRules.push({
|
|
1048
|
+
name: asset.name,
|
|
1049
|
+
description: asset.description,
|
|
1050
|
+
autoApply: false,
|
|
1051
|
+
body: resolvedBody,
|
|
1052
|
+
sourcePath: `db:${asset.entryId}`,
|
|
1053
|
+
});
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
log(`Setup assets: ${dbSkills.length} skills, ${dbRules.length} rules/hooks from DB (WP-345 DB-first path)`);
|
|
1057
|
+
// Reaching here (no throw above) means it's safe to use as the CONTENT source (Codex P2, PR #912 round 3).
|
|
1058
|
+
usedDbSource = true;
|
|
1059
|
+
}
|
|
1060
|
+
else if (dbQuerySucceeded && writeMode) {
|
|
1061
|
+
// Empty DB in WRITE mode is authoritative (ingest already ran); preview never ingests, so FS still forecasts apply.
|
|
1062
|
+
// Round 14: findLeftoverProjections only lists stale files, never removes them — say so.
|
|
1063
|
+
// Round 15: it also skips surfaces outside allowedTargets — scope the claim to those.
|
|
1064
|
+
log('Setup assets: DB query succeeded with zero active assets — any existing projections on the selected surfaces will be listed as leftovers, not removed.');
|
|
1065
|
+
usedDbSource = true;
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
catch {
|
|
1069
|
+
// DB unavailable, or post-query processing failed hard — usedDbSource stays false either way.
|
|
1070
|
+
}
|
|
1071
|
+
const allSkills = usedDbSource ? dbSkills : readCanonicalSkills(pbDir);
|
|
1072
|
+
const manualRules = usedDbSource ? dbRules : readCanonicalRules(pbDir);
|
|
1073
|
+
if (!usedDbSource) {
|
|
1074
|
+
log('Setup assets: reading from filesystem (DB source unavailable, or unauthoritative for this mode)');
|
|
1075
|
+
}
|
|
1076
|
+
// 5a-pre. E4: resolve semantic refs (WP-345, DEC-A/C/K) — replace {{ref:key}} via the Convex
|
|
1077
|
+
// resolver, apply mode only. NG11: PostHog events fire from CLI side only.
|
|
1078
|
+
if (usedDbSource && writeMode) {
|
|
1079
|
+
const projectableDbAssets = dbAssetRows.filter((a) => !a.disabledByOwner && (a.assetKind === 'skill' || a.assetKind === 'rule' || a.assetKind === 'hook'));
|
|
1080
|
+
const assetsWithRefs = projectableDbAssets.filter((a) => a.semanticRefs && a.semanticRefs.length > 0);
|
|
1081
|
+
if (assetsWithRefs.length > 0) {
|
|
1082
|
+
log(`Resolving semantic refs for ${assetsWithRefs.length} asset(s)...`);
|
|
1083
|
+
// Collect unique ref keys across all assets
|
|
1084
|
+
const allRefKeys = [...new Set(assetsWithRefs.flatMap((a) => a.semanticRefs))];
|
|
1085
|
+
// Resolve all refs in a single batch call (DEC-767 / WP-354 Build-Order #6 — kind + status discriminator).
|
|
1086
|
+
let resolvedRefs = [];
|
|
1087
|
+
try {
|
|
1088
|
+
resolvedRefs = await kernelCall('setup.resolveSemanticRefs', { semanticRefs: allRefKeys });
|
|
1089
|
+
}
|
|
1090
|
+
catch (err) {
|
|
1091
|
+
trackEvent('setup.refs.resolve_failed', { error: err instanceof Error ? err.message : String(err) });
|
|
1092
|
+
logErr(`Warning: could not resolve semantic refs — ${err instanceof Error ? err.message : String(err)}`);
|
|
1093
|
+
}
|
|
1094
|
+
// Build resolved map: canonicalKey → display name. Only required refs count as unresolved warnings.
|
|
1095
|
+
const resolvedMap = new Map();
|
|
1096
|
+
let unresolvedCount = 0;
|
|
1097
|
+
for (const result of resolvedRefs) {
|
|
1098
|
+
if (result.status === 'resolved' && result.localEntryId) {
|
|
1099
|
+
resolvedMap.set(result.ref, result.localEntryId);
|
|
1100
|
+
trackEvent('skill.ref.resolved', { ref: result.ref, kind: result.kind });
|
|
1101
|
+
}
|
|
1102
|
+
else if (result.status === 'unsupported-future') {
|
|
1103
|
+
// seed: refs are explicitly future scope per WP-354 Build-Order #6 — not a warning.
|
|
1104
|
+
trackEvent('skill.ref.future', { ref: result.ref, kind: result.kind });
|
|
1105
|
+
}
|
|
1106
|
+
else if (result.required) {
|
|
1107
|
+
unresolvedCount++;
|
|
1108
|
+
trackEvent('skill.ref.unresolved', { ref: result.ref, kind: result.kind, status: result.status });
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
if (unresolvedCount > 0) {
|
|
1112
|
+
logErr(`Warning: ${unresolvedCount} required semantic ref(s) could not be resolved.`);
|
|
1113
|
+
}
|
|
1114
|
+
// Projection preserves ref tokens as portable refs — resolvedMap is validation/telemetry only.
|
|
1115
|
+
}
|
|
1116
|
+
// Compute projection hash per projected DB asset (DEC-K): sha256 of the normalized resolved body.
|
|
1117
|
+
const HASH_TRAILER_REGEX = /^<!--\s*pb-hash:.*-->\s*$/gm;
|
|
1118
|
+
const TIMESTAMP_REGEX = /^<!--\s*pb-generated-at:.*-->\s*$/gm;
|
|
1119
|
+
for (const rawAsset of projectableDbAssets) {
|
|
1120
|
+
const resolvedAsset = [...dbSkills, ...dbRules].find((a) => a.sourcePath === `db:${rawAsset.entryId}`);
|
|
1121
|
+
if (!resolvedAsset)
|
|
1122
|
+
continue;
|
|
1123
|
+
try {
|
|
1124
|
+
// Build the projected body (what will be written to disk)
|
|
1125
|
+
const projectedBody = resolvedAsset.body;
|
|
1126
|
+
// Normalize: strip existing hash/timestamp trailers, convert to LF
|
|
1127
|
+
const normalized = projectedBody
|
|
1128
|
+
.replace(HASH_TRAILER_REGEX, '')
|
|
1129
|
+
.replace(TIMESTAMP_REGEX, '')
|
|
1130
|
+
.replace(/\r\n/g, '\n')
|
|
1131
|
+
.replace(/\r/g, '\n')
|
|
1132
|
+
.trimEnd();
|
|
1133
|
+
// Compute sha256 hash
|
|
1134
|
+
const hash = createHash('sha256').update(normalized, 'utf8').digest('hex');
|
|
1135
|
+
const hashTrailer = `<!-- pb-hash: sha256:${hash} -->`;
|
|
1136
|
+
// Append hash trailer to the projected body
|
|
1137
|
+
resolvedAsset.body = `${normalized}\n${hashTrailer}`;
|
|
1138
|
+
dbProjectionHashes.set(rawAsset.entryId, {
|
|
1139
|
+
hash: `sha256:${hash}`,
|
|
1140
|
+
assetKind: rawAsset.assetKind,
|
|
1141
|
+
});
|
|
1142
|
+
// Drift detection: compare against last known hash
|
|
1143
|
+
if (rawAsset.lastProjectedHash && rawAsset.lastProjectedHash !== `sha256:${hash}`) {
|
|
1144
|
+
trackEvent('skill.drift.detected', {
|
|
1145
|
+
entryId: rawAsset.entryId,
|
|
1146
|
+
assetKind: rawAsset.assetKind,
|
|
1147
|
+
});
|
|
1148
|
+
log(`Drift detected for asset ${rawAsset.entryId} — projecting updated version.`);
|
|
1149
|
+
}
|
|
1150
|
+
trackEvent('skill.projection.succeeded', {
|
|
1151
|
+
entryId: rawAsset.entryId,
|
|
1152
|
+
assetKind: rawAsset.assetKind,
|
|
1153
|
+
});
|
|
1154
|
+
}
|
|
1155
|
+
catch (err) {
|
|
1156
|
+
trackEvent('skill.projection.failed', {
|
|
1157
|
+
entryId: rawAsset.entryId,
|
|
1158
|
+
assetKind: rawAsset.assetKind,
|
|
1159
|
+
});
|
|
1160
|
+
logErr(`Warning: projection failed for ${rawAsset.entryId} — ${err instanceof Error ? err.message : String(err)}`);
|
|
1161
|
+
}
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
354
1164
|
// 5a. Optionally fetch and merge Chain-derived rules (--generate flag)
|
|
355
1165
|
let chainRulesStats = null;
|
|
356
1166
|
let chainGaps = [];
|
|
@@ -382,12 +1192,48 @@ export async function runHandshake(options = {}) {
|
|
|
382
1192
|
log(diffText);
|
|
383
1193
|
}
|
|
384
1194
|
}
|
|
385
|
-
//
|
|
386
|
-
|
|
387
|
-
|
|
1195
|
+
// 5b. Read personal layer (WP-310 E2) — machine-local rules/skills from .productbrain/.local/, [] if absent, all persist: 'local'.
|
|
1196
|
+
const personalRules = readPersonalLayer(pbDir);
|
|
1197
|
+
if (personalRules.length > 0) {
|
|
1198
|
+
// Name collision detection — warn when a personal rule overrides a team rule
|
|
1199
|
+
const teamRuleNames = new Set(allRules.map((r) => r.name));
|
|
1200
|
+
for (const pr of personalRules) {
|
|
1201
|
+
if (teamRuleNames.has(pr.name)) {
|
|
1202
|
+
logErr(`Personal rule "${pr.name}" overrides team rule (local takes precedence).`);
|
|
1203
|
+
}
|
|
1204
|
+
}
|
|
1205
|
+
// Merge: team rules first, personal rules appended (personal takes precedence via name collision above)
|
|
1206
|
+
allRules = [...allRules, ...personalRules];
|
|
1207
|
+
}
|
|
1208
|
+
const personalSkills = readPersonalSkillsLayer(pbDir);
|
|
1209
|
+
if (personalSkills.length > 0) {
|
|
1210
|
+
const teamSkillNames = new Set(allSkills.map((s) => s.name));
|
|
1211
|
+
for (const ps of personalSkills) {
|
|
1212
|
+
if (teamSkillNames.has(ps.name)) {
|
|
1213
|
+
logErr(`Personal skill "${ps.name}" overrides team skill (local takes precedence).`);
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
allSkills.push(...personalSkills);
|
|
1217
|
+
}
|
|
1218
|
+
// 5d. Load method registry (WP-310 E4) — only when manifest is present.
|
|
1219
|
+
let registrySource;
|
|
1220
|
+
let registryStale;
|
|
1221
|
+
if (manifest) {
|
|
1222
|
+
const registryResult = await loadMethodRegistry().catch(() => null);
|
|
1223
|
+
if (registryResult) {
|
|
1224
|
+
registrySource = registryResult.source;
|
|
1225
|
+
registryStale = registryResult.stale;
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
const adoptionFilteredSkills = filterByAdoptionState(allSkills, manifest);
|
|
1229
|
+
const adoptionFilteredRules = filterByAdoptionState(allRules, manifest);
|
|
1230
|
+
// Compute adoption counts for report (only meaningful when manifest is present)
|
|
1231
|
+
const adoptedRulesCount = manifest ? adoptionFilteredRules.length : undefined;
|
|
1232
|
+
const rejectedRulesCount = manifest ? allRules.length - adoptionFilteredRules.length : undefined;
|
|
1233
|
+
// Level filtering with stage-gating: stage caps the effective level (blank→beginner, seed→intermediate, grounded+→expert).
|
|
388
1234
|
const profileStage = workspaceProfile?.stage;
|
|
389
|
-
const levelFilteredSkills = filterByLevel(
|
|
390
|
-
const levelFilteredRules = filterByLevel(
|
|
1235
|
+
const levelFilteredSkills = filterByLevel(adoptionFilteredSkills, level, profileStage);
|
|
1236
|
+
const levelFilteredRules = filterByLevel(adoptionFilteredRules, level, profileStage);
|
|
391
1237
|
// Log when stage gating changes the effective level
|
|
392
1238
|
if (profileStage) {
|
|
393
1239
|
const stageCap = STAGE_TO_MAX_LEVEL[profileStage];
|
|
@@ -420,6 +1266,7 @@ export async function runHandshake(options = {}) {
|
|
|
420
1266
|
if (dryRun && canonicalRules.length > 0) {
|
|
421
1267
|
log(` INCLUDED rules: ${canonicalRules.map((r) => r.name).join(', ')}`);
|
|
422
1268
|
}
|
|
1269
|
+
const noProjectionAssets = findNoProjectionAssets(canonicalSkills, canonicalRules);
|
|
423
1270
|
if (canonicalSkills.length > 0 || canonicalRules.length > 0) {
|
|
424
1271
|
const levelSuffix = level ? ` (level: ${level})` : '';
|
|
425
1272
|
const stageSuffix = profileStage ? `, stage: ${profileStage}` : '';
|
|
@@ -429,16 +1276,15 @@ export async function runHandshake(options = {}) {
|
|
|
429
1276
|
log(`Portable knowledge: ${canonicalSkills.length}/${totalSkills} skills, ${canonicalRules.length}/${totalRules} rules${levelSuffix}${stageSuffix}${stackSuffix}`);
|
|
430
1277
|
}
|
|
431
1278
|
// 6. Generate file contents
|
|
432
|
-
// Build workspace context for AGENTS.md enrichment (stage, focus,
|
|
1279
|
+
// Build workspace context for AGENTS.md enrichment (stage, focus, entry count)
|
|
433
1280
|
const agentsWorkspaceContext = workspaceProfile
|
|
434
1281
|
? {
|
|
435
1282
|
stage: workspaceProfile.stage,
|
|
436
|
-
focus: orientView?.strategicContext?.
|
|
437
|
-
governanceMode: workspaceProfile.governanceMode,
|
|
1283
|
+
focus: orientView?.strategicContext?.currentWorkPackage ?? undefined,
|
|
438
1284
|
totalEntries: workspaceProfile.totalEntries,
|
|
439
1285
|
}
|
|
440
1286
|
: undefined;
|
|
441
|
-
// Collect codex-targeted skills for AGENTS.md skill directory
|
|
1287
|
+
// Collect codex-targeted skills for AGENTS.md skill directory — persist: 'local' entries included (all projections are local-only now).
|
|
442
1288
|
const agentsCodexSkills = canonicalSkills
|
|
443
1289
|
.filter((s) => shouldEmitToTarget(s, 'codex'))
|
|
444
1290
|
.map((s) => ({
|
|
@@ -477,26 +1323,160 @@ export async function runHandshake(options = {}) {
|
|
|
477
1323
|
const claudeContent = generateClaudeMd(timestamp);
|
|
478
1324
|
const cursorContent = generateCursorMdc(timestamp);
|
|
479
1325
|
const copilotContent = generateCopilotMd(timestamp, copilotOptions);
|
|
1326
|
+
// DEC-1343: one committed .github/instructions/<slug>.instructions.md per copilot rule with applyTo; repo-wide rules stay above.
|
|
1327
|
+
const copilotInstructionFiles = generateCopilotInstructionFiles(canonicalRules
|
|
1328
|
+
.filter((r) => shouldEmitToTarget(r, 'copilot'))
|
|
1329
|
+
// `.github/instructions/` is COMMITTED — never project a machine-local (persist: 'local') rule into it.
|
|
1330
|
+
.filter((r) => r.persist !== 'local')
|
|
1331
|
+
.map((r) => ({ name: r.name, body: r.body, applyTo: r.applyTo, sourcePath: r.sourcePath })), timestamp);
|
|
1332
|
+
const boundaryEnforcementMode = getBoundaryEnforcementMode(manifest);
|
|
1333
|
+
const boundaryManifestContent = boundaryEnforcementMode === 'advisory'
|
|
1334
|
+
? null
|
|
1335
|
+
: generateBoundaryManifest(pbDir);
|
|
480
1336
|
// 7. Write files
|
|
481
1337
|
const filesWritten = [];
|
|
482
1338
|
const filesSkipped = [];
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
1339
|
+
const previewPlan = [];
|
|
1340
|
+
if (writeMode && usedDbSource) {
|
|
1341
|
+
const authoringSyncState = loadAuthoringSyncState(pbDir);
|
|
1342
|
+
let authoringSyncStateChanged = false;
|
|
1343
|
+
const personalAssets = dbAssetRows.filter((asset) => asset.scope === 'personal' &&
|
|
1344
|
+
!asset.disabledByOwner &&
|
|
1345
|
+
(asset.assetKind === 'skill' || asset.assetKind === 'rule' || asset.assetKind === 'hook'));
|
|
1346
|
+
for (const asset of personalAssets) {
|
|
1347
|
+
// WP-428 S2 (Finding #5): skip fetch-failed assets — no empty-body authoring file, no lastProjectedHash update.
|
|
1348
|
+
if (bodyFetchFailedEntryIds.has(asset.entryId))
|
|
1349
|
+
continue;
|
|
1350
|
+
const authoringPath = setupAuthoringPath(cwd, asset);
|
|
1351
|
+
if (!authoringPath)
|
|
1352
|
+
continue;
|
|
1353
|
+
// relative() for correct cross-platform path computation (string-replace mis-fires on non-'/' cwd separators).
|
|
1354
|
+
const relativeAuthoringPath = relative(cwd, authoringPath);
|
|
1355
|
+
const bodyHash = setupAuthoringAssetHash(asset);
|
|
1356
|
+
const authoringExists = existsSync(authoringPath);
|
|
1357
|
+
const tracked = authoringSyncState.assets[asset.entryId];
|
|
1358
|
+
const trackedHere = tracked?.path === relativeAuthoringPath;
|
|
1359
|
+
const trackedMatchesServer = Boolean(trackedHere && asset.lastProjectedHash && tracked?.hash === asset.lastProjectedHash);
|
|
1360
|
+
if (!authoringExists && asset.lastProjectedHash && trackedHere && trackedMatchesServer) {
|
|
1361
|
+
try {
|
|
1362
|
+
const dormantResult = await kernelCall('setup.markPersonalSetupAssetDormantFromSync', { entryId: asset.entryId, expectedLastProjectedHash: tracked.hash });
|
|
1363
|
+
if (dormantResult.action === 'conflict') {
|
|
1364
|
+
syncDriftTensToFire.push(`Repo authoring deletion skipped for ${asset.entryId}; server baseline changed during sync, so writeback was deferred until the next DB read.`);
|
|
1365
|
+
logErr(`Warning: authoring deletion for ${asset.entryId} was not applied because the DB baseline changed during sync.`);
|
|
1366
|
+
deferredAuthoringBaselineEntryIds.add(asset.entryId);
|
|
1367
|
+
continue;
|
|
1368
|
+
}
|
|
1369
|
+
else {
|
|
1370
|
+
syncDriftTensToFire.push(`Repo authoring file was deleted for ${asset.entryId}; caller-owned personal setup asset marked dormant.`);
|
|
1371
|
+
log(`Setup authoring deletion: ${asset.entryId} marked dormant.`);
|
|
1372
|
+
delete authoringSyncState.assets[asset.entryId];
|
|
1373
|
+
authoringSyncStateChanged = true;
|
|
1374
|
+
continue;
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1377
|
+
catch (err) {
|
|
1378
|
+
logErr(`Warning: could not mark ${asset.entryId} dormant after authoring deletion — ${err instanceof Error ? err.message : String(err)}`);
|
|
1379
|
+
continue;
|
|
1380
|
+
}
|
|
1381
|
+
}
|
|
1382
|
+
else if (!authoringExists && asset.lastProjectedHash && trackedHere) {
|
|
1383
|
+
syncDriftTensToFire.push(`Repo authoring deletion skipped for ${asset.entryId}; local sync baseline is stale, so DB writeback wins.`);
|
|
1384
|
+
logErr(`Warning: authoring deletion for ${asset.entryId} was not applied because the DB baseline changed.`);
|
|
1385
|
+
}
|
|
1386
|
+
const nextAuthoringContent = renderSetupAuthoringFile(asset);
|
|
1387
|
+
if (authoringExists) {
|
|
1388
|
+
const parsed = parseSetupAuthoringFrontmatter(readFileSync(authoringPath, 'utf8'));
|
|
1389
|
+
const fileHash = setupAuthoringAssetHash({
|
|
1390
|
+
entryId: parsed.frontmatterId?.trim() || asset.entryId,
|
|
1391
|
+
name: parsed.name || asset.name,
|
|
1392
|
+
description: parsed.description,
|
|
1393
|
+
body: parsed.body,
|
|
1394
|
+
assetKind: asset.assetKind,
|
|
1395
|
+
triggers: parsed.triggers,
|
|
1396
|
+
semanticRefs: parsed.semanticRefs,
|
|
1397
|
+
});
|
|
1398
|
+
if (fileHash === bodyHash) {
|
|
1399
|
+
if (asset.lastProjectedHash !== bodyHash) {
|
|
1400
|
+
await kernelCall('setup.updateLastProjectedHash', {
|
|
1401
|
+
entryId: asset.entryId,
|
|
1402
|
+
hash: bodyHash,
|
|
1403
|
+
}).catch(() => null);
|
|
1404
|
+
}
|
|
1405
|
+
authoringSyncState.assets[asset.entryId] = { path: relativeAuthoringPath, hash: bodyHash };
|
|
1406
|
+
authoringSyncStateChanged = true;
|
|
1407
|
+
continue;
|
|
1408
|
+
}
|
|
1409
|
+
if (!asset.lastProjectedHash) {
|
|
1410
|
+
syncDriftTensToFire.push(`Repo authoring file differs from DB for ${asset.entryId} at ${authoringPath} with no shared baseline; DB writeback skipped.`);
|
|
1411
|
+
logErr(`Warning: setup authoring drift for ${asset.entryId}; DB writeback skipped because no shared baseline exists.`);
|
|
1412
|
+
continue;
|
|
1413
|
+
}
|
|
1414
|
+
if (fileHash !== asset.lastProjectedHash &&
|
|
1415
|
+
bodyHash !== asset.lastProjectedHash) {
|
|
1416
|
+
syncDriftTensToFire.push(`Repo authoring file won setup sync conflict for ${asset.entryId} at ${authoringPath}.`);
|
|
1417
|
+
logErr(`Warning: repo authoring file won sync conflict for ${asset.entryId}; DB writeback skipped.`);
|
|
1418
|
+
continue;
|
|
1419
|
+
}
|
|
1420
|
+
if (fileHash !== asset.lastProjectedHash) {
|
|
1421
|
+
syncDriftTensToFire.push(`Repo authoring file differs from DB baseline for ${asset.entryId} at ${authoringPath}; DB writeback skipped.`);
|
|
1422
|
+
logErr(`Warning: setup authoring drift for ${asset.entryId}; DB writeback skipped.`);
|
|
1423
|
+
continue;
|
|
1424
|
+
}
|
|
1425
|
+
}
|
|
1426
|
+
try {
|
|
1427
|
+
assertSetupWritePath(authoringPath, perimeterManifest);
|
|
1428
|
+
mkdirSync(dirname(authoringPath), { recursive: true });
|
|
1429
|
+
writeFileSync(authoringPath, nextAuthoringContent);
|
|
1430
|
+
filesWritten.push(relativeAuthoringPath);
|
|
1431
|
+
await kernelCall('setup.updateLastProjectedHash', {
|
|
1432
|
+
entryId: asset.entryId,
|
|
1433
|
+
hash: bodyHash,
|
|
1434
|
+
}).catch(() => null);
|
|
1435
|
+
authoringSyncState.assets[asset.entryId] = { path: relativeAuthoringPath, hash: bodyHash };
|
|
1436
|
+
authoringSyncStateChanged = true;
|
|
1437
|
+
}
|
|
1438
|
+
catch (err) {
|
|
1439
|
+
logErr(`Warning: could not write setup authoring file for ${asset.entryId} — ${err instanceof Error ? err.message : String(err)}`);
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
if (authoringSyncStateChanged) {
|
|
1443
|
+
try {
|
|
1444
|
+
saveAuthoringSyncState(pbDir, authoringSyncState);
|
|
1445
|
+
}
|
|
1446
|
+
catch (err) {
|
|
1447
|
+
logErr(`Warning: could not persist setup authoring sync state — ${err instanceof Error ? err.message : String(err)}`);
|
|
1448
|
+
}
|
|
1449
|
+
}
|
|
1450
|
+
}
|
|
487
1451
|
const writes = [
|
|
488
1452
|
...(contextContent ? [{ path: join(cwd, '.productbrain', 'context.md'), relative: '.productbrain/context.md', content: contextContent, dirs: join(cwd, '.productbrain'), isAdapter: false }] : []),
|
|
489
1453
|
{ path: join(cwd, '.productbrain', 'briefing.md'), relative: '.productbrain/briefing.md', content: briefingContent, isAdapter: false },
|
|
490
|
-
{ path: join(cwd, 'AGENTS.md'), relative: 'AGENTS.md', content: agentsContent, isAdapter: true, target: 'codex' },
|
|
491
|
-
{ path: join(cwd, 'CLAUDE.md'), relative: 'CLAUDE.md', content: claudeContent, isAdapter: true, target: 'claude' },
|
|
1454
|
+
{ path: join(cwd, 'AGENTS.md'), relative: 'AGENTS.md', content: agentsContent, isAdapter: true, target: 'codex', augmentTarget: true },
|
|
1455
|
+
{ path: join(cwd, 'CLAUDE.md'), relative: 'CLAUDE.md', content: claudeContent, isAdapter: true, target: 'claude', augmentTarget: true },
|
|
492
1456
|
{ path: join(cwd, '.cursor', 'rules', 'chain.mdc'), relative: '.cursor/rules/chain.mdc', content: cursorContent, dirs: join(cwd, '.cursor', 'rules'), isAdapter: true, target: 'cursor' },
|
|
493
1457
|
{ path: join(cwd, '.github', 'copilot-instructions.md'), relative: '.github/copilot-instructions.md', content: copilotContent, dirs: join(cwd, '.github'), isAdapter: true, target: 'copilot' },
|
|
1458
|
+
...copilotInstructionFiles.map((f) => ({
|
|
1459
|
+
path: join(cwd, f.relativePath),
|
|
1460
|
+
relative: f.relativePath,
|
|
1461
|
+
content: f.content,
|
|
1462
|
+
dirs: join(cwd, '.github', 'instructions'),
|
|
1463
|
+
isAdapter: true,
|
|
1464
|
+
target: 'copilot',
|
|
1465
|
+
})),
|
|
1466
|
+
...(boundaryManifestContent ? [{
|
|
1467
|
+
path: join(cwd, '.productbrain', 'generated', 'boundaries.json'),
|
|
1468
|
+
relative: '.productbrain/generated/boundaries.json',
|
|
1469
|
+
content: boundaryManifestContent,
|
|
1470
|
+
dirs: join(cwd, '.productbrain', 'generated'),
|
|
1471
|
+
isAdapter: false,
|
|
1472
|
+
}] : []),
|
|
494
1473
|
];
|
|
495
1474
|
// Add Cursor skill copies (filtered by target)
|
|
496
1475
|
const cursorProfile = resolveSurfaceProfile('cursor');
|
|
497
1476
|
for (const skill of canonicalSkills) {
|
|
498
1477
|
if (!shouldEmitToTarget(skill, 'cursor'))
|
|
499
1478
|
continue;
|
|
1479
|
+
const dbAssetEntryId = skill.sourcePath.startsWith('db:') ? skill.sourcePath.slice(3) : undefined;
|
|
500
1480
|
const skillDir = join(cwd, '.cursor', 'skills', skill.name);
|
|
501
1481
|
writes.push({
|
|
502
1482
|
path: join(skillDir, 'SKILL.md'),
|
|
@@ -505,12 +1485,14 @@ export async function runHandshake(options = {}) {
|
|
|
505
1485
|
dirs: skillDir,
|
|
506
1486
|
isAdapter: true,
|
|
507
1487
|
target: 'cursor',
|
|
1488
|
+
dbAssetEntryId,
|
|
508
1489
|
});
|
|
509
1490
|
}
|
|
510
1491
|
// Add Codex skill copies (projected markdown + index)
|
|
511
1492
|
const codexProfile = resolveSurfaceProfile('codex');
|
|
512
1493
|
const codexSkills = canonicalSkills.filter((s) => shouldEmitToTarget(s, 'codex'));
|
|
513
1494
|
for (const skill of codexSkills) {
|
|
1495
|
+
const dbAssetEntryId = skill.sourcePath.startsWith('db:') ? skill.sourcePath.slice(3) : undefined;
|
|
514
1496
|
writes.push({
|
|
515
1497
|
path: join(cwd, '.codex', 'skills', `${skill.name}.md`),
|
|
516
1498
|
relative: `.codex/skills/${skill.name}.md`,
|
|
@@ -518,6 +1500,7 @@ export async function runHandshake(options = {}) {
|
|
|
518
1500
|
dirs: join(cwd, '.codex', 'skills'),
|
|
519
1501
|
isAdapter: true,
|
|
520
1502
|
target: 'codex',
|
|
1503
|
+
dbAssetEntryId,
|
|
521
1504
|
});
|
|
522
1505
|
}
|
|
523
1506
|
writes.push({
|
|
@@ -534,6 +1517,7 @@ export async function runHandshake(options = {}) {
|
|
|
534
1517
|
for (const rule of canonicalRules) {
|
|
535
1518
|
if (!shouldEmitToTarget(rule, 'cursor'))
|
|
536
1519
|
continue;
|
|
1520
|
+
const dbAssetEntryId = rule.sourcePath.startsWith('db:') ? rule.sourcePath.slice(3) : undefined;
|
|
537
1521
|
writes.push({
|
|
538
1522
|
path: join(cwd, '.cursor', 'rules', `${rule.name}.mdc`),
|
|
539
1523
|
relative: `.cursor/rules/${rule.name}.mdc`,
|
|
@@ -541,64 +1525,492 @@ export async function runHandshake(options = {}) {
|
|
|
541
1525
|
dirs: join(cwd, '.cursor', 'rules'),
|
|
542
1526
|
isAdapter: true,
|
|
543
1527
|
target: 'cursor',
|
|
1528
|
+
dbAssetEntryId,
|
|
544
1529
|
});
|
|
545
1530
|
}
|
|
546
|
-
//
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
1531
|
+
// 7a. WP-379 S5b: find leftover projections (apply mode) — REPORT-ONLY (coordinator ruling, PR
|
|
1532
|
+
// #912 round 10), see findLeftoverProjections's own header. Gated on dbQuerySucceeded, not
|
|
1533
|
+
// usedDbSource — the report only needs dbAssetRows' names, not the write-content source.
|
|
1534
|
+
let leftoverFiles = [];
|
|
1535
|
+
let leftoverFilesTruncated = false;
|
|
1536
|
+
if (writeMode && dbQuerySucceeded) {
|
|
1537
|
+
// Personal-layer names: merged into allSkills/allRules below but absent from dbAssetRows —
|
|
1538
|
+
// without this an already-projected personal asset reads as a false-positive leftover.
|
|
1539
|
+
const activeAssetNames = [
|
|
1540
|
+
...dbAssetRows.filter((a) => !a.disabledByOwner).map((a) => a.name),
|
|
1541
|
+
...personalSkills.map((s) => s.name),
|
|
1542
|
+
...personalRules.map((r) => r.name),
|
|
1543
|
+
];
|
|
1544
|
+
// Nested .cursor/skills scan gets its OWN canon: canonicalSkills is SKILL-kind only and
|
|
1545
|
+
// shouldEmitToTarget(_, 'cursor') respects per-skill target routing.
|
|
1546
|
+
const cursorSkillNames = canonicalSkills.filter((s) => shouldEmitToTarget(s, 'cursor')).map((s) => s.name);
|
|
1547
|
+
// Round 11: exempt exact write-plan paths from the leftover scan (see findLeftoverProjections's own doc).
|
|
1548
|
+
const exactRelativePaths = new Set(writes.map((w) => w.relative));
|
|
1549
|
+
const scanResult = findLeftoverProjections(cwd, activeAssetNames, allowedTargets, cursorSkillNames, exactRelativePaths);
|
|
1550
|
+
leftoverFiles = scanResult.files;
|
|
1551
|
+
leftoverFilesTruncated = scanResult.truncated;
|
|
559
1552
|
}
|
|
560
|
-
//
|
|
561
|
-
|
|
562
|
-
const
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
1553
|
+
// ── WP-436 S3: Vocab projector — fetch workspace vocab context once per handshake. Source-side
|
|
1554
|
+
// stays tokenized; resolves {{vocab:...}} before writing. Fail-open: a failed fetch writes the raw token.
|
|
1555
|
+
const handshakeVocabCtx = await getOrFetchVocabCtx(config.apiKey, async () => {
|
|
1556
|
+
try {
|
|
1557
|
+
const vocab = await kernelCall('chain.getVocabulary', {});
|
|
1558
|
+
if (vocab?.collectionLabels || vocab?.collectionDefaults) {
|
|
1559
|
+
return {
|
|
1560
|
+
...(vocab.collectionLabels ? { collectionLabels: vocab.collectionLabels } : {}),
|
|
1561
|
+
...(vocab.collectionDefaults ? { collectionDefaults: vocab.collectionDefaults } : {}),
|
|
1562
|
+
};
|
|
1563
|
+
}
|
|
1564
|
+
return null;
|
|
1565
|
+
}
|
|
1566
|
+
catch {
|
|
1567
|
+
return null; // fail-open
|
|
1568
|
+
}
|
|
1569
|
+
});
|
|
1570
|
+
const userOwnedSkipped = [];
|
|
1571
|
+
const projectedHashUpdates = new Map();
|
|
1572
|
+
const cleanBucketPaths = [];
|
|
1573
|
+
const tamperedBucket = [];
|
|
1574
|
+
const recordProjectedHash = (entryId) => {
|
|
1575
|
+
if (!applyMode || !entryId)
|
|
1576
|
+
return;
|
|
1577
|
+
if (deferredAuthoringBaselineEntryIds.has(entryId))
|
|
1578
|
+
return;
|
|
1579
|
+
const projection = dbProjectionHashes.get(entryId);
|
|
1580
|
+
if (projection)
|
|
1581
|
+
projectedHashUpdates.set(entryId, projection.hash);
|
|
1582
|
+
};
|
|
1583
|
+
// TEN-2155: region augmentation context + symlink dedupe — codexActive gates the AGENTS.md skills-index pointer.
|
|
1584
|
+
const regionCtx = { codexActive: allowedTargets.has('codex') };
|
|
1585
|
+
const malformedRegionPaths = [];
|
|
1586
|
+
// Same inode for two augment targets (e.g. CLAUDE.md symlinked to AGENTS.md): augment only first-seen.
|
|
1587
|
+
const seenAugmentRealpaths = new Set();
|
|
1588
|
+
const augmentTargetSkip = new Set();
|
|
1589
|
+
for (const w of writes) {
|
|
1590
|
+
if (!w.augmentTarget || !w.target || !allowedTargets.has(w.target) || !existsSync(w.path))
|
|
1591
|
+
continue;
|
|
1592
|
+
let real;
|
|
1593
|
+
try {
|
|
1594
|
+
real = realpathSync(w.path);
|
|
1595
|
+
}
|
|
1596
|
+
catch {
|
|
1597
|
+
real = w.path;
|
|
1598
|
+
}
|
|
1599
|
+
if (seenAugmentRealpaths.has(real))
|
|
1600
|
+
augmentTargetSkip.add(w.path);
|
|
1601
|
+
else
|
|
1602
|
+
seenAugmentRealpaths.add(real);
|
|
572
1603
|
}
|
|
573
1604
|
for (const w of writes) {
|
|
574
1605
|
// Surface filtering: skip adapter writes for targets not in the allowed set
|
|
575
|
-
if (
|
|
1606
|
+
if (w.target && !allowedTargets.has(w.target)) {
|
|
576
1607
|
filesSkipped.push({ path: w.relative, reason: `filtered (surface: ${w.target})` });
|
|
1608
|
+
if (preview)
|
|
1609
|
+
previewPlan.push({ path: w.relative, status: 'filtered' });
|
|
577
1610
|
continue;
|
|
578
1611
|
}
|
|
1612
|
+
// ── TEN-2155: augment user-owned CLAUDE.md / AGENTS.md with a marked PB region — runs ahead
|
|
1613
|
+
// of the legacy MARKER gates; absent/legacy-pb-managed fall through to the legacy path.
|
|
1614
|
+
if (w.augmentTarget) {
|
|
1615
|
+
const projection = REGION_PROJECTIONS[w.target];
|
|
1616
|
+
if (projection && existsSync(w.path)) {
|
|
1617
|
+
if (augmentTargetSkip.has(w.path)) {
|
|
1618
|
+
filesSkipped.push({ path: w.relative, reason: 'symlinked to another augment target — augmented once' });
|
|
1619
|
+
continue;
|
|
1620
|
+
}
|
|
1621
|
+
const disk = readFileSync(w.path, 'utf8');
|
|
1622
|
+
const cls = classifyAdapterFile(disk);
|
|
1623
|
+
if (cls === 'augmentable' || cls === 'region-present') {
|
|
1624
|
+
const eol = detectEol(disk);
|
|
1625
|
+
const region = replaceVocabTokens(projection.build(regionCtx, eol), handshakeVocabCtx);
|
|
1626
|
+
// Defense-in-depth: the composed region (post vocab-token resolution) must itself be a
|
|
1627
|
+
// single well-formed region. v1 content has no vocab tokens so this is a no-op, but it
|
|
1628
|
+
// guards the documented future override/vocab seam from injecting a stray sentinel/MARKER.
|
|
1629
|
+
if (classifyAdapterFile(region) !== 'region-present') {
|
|
1630
|
+
filesSkipped.push({ path: w.relative, reason: 'internal: composed PB region malformed — skipped to protect your file' });
|
|
1631
|
+
if (preview)
|
|
1632
|
+
previewPlan.push({ path: w.relative, status: 'needs-attention' });
|
|
1633
|
+
continue;
|
|
1634
|
+
}
|
|
1635
|
+
const candidate = cls === 'augmentable' ? spliceAppend(disk, region, eol) : spliceReplace(disk, region);
|
|
1636
|
+
if (candidate === disk) {
|
|
1637
|
+
filesSkipped.push({ path: w.relative, reason: 'unchanged' });
|
|
1638
|
+
if (preview)
|
|
1639
|
+
previewPlan.push({ path: w.relative, status: 'unchanged' });
|
|
1640
|
+
continue;
|
|
1641
|
+
}
|
|
1642
|
+
if (preview || dryRun) {
|
|
1643
|
+
filesWritten.push(w.relative + (dryRun ? ' (dry run)' : ''));
|
|
1644
|
+
if (preview)
|
|
1645
|
+
previewPlan.push({ path: w.relative, status: 'would-augment' });
|
|
1646
|
+
continue;
|
|
1647
|
+
}
|
|
1648
|
+
if (authorityPreviewOnly) {
|
|
1649
|
+
// apply + materialize observe/off: honor authority — do NOT write; mirror the legacy
|
|
1650
|
+
// preview-only skip so the report does not falsely list it as written.
|
|
1651
|
+
filesSkipped.push({ path: w.relative, reason: `preview-only (materialize: ${manifestStatus.mode})` });
|
|
1652
|
+
continue;
|
|
1653
|
+
}
|
|
1654
|
+
assertSetupWritePath(w.path, perimeterManifest);
|
|
1655
|
+
writeFileSync(w.path, candidate);
|
|
1656
|
+
filesWritten.push(w.relative);
|
|
1657
|
+
continue;
|
|
1658
|
+
}
|
|
1659
|
+
if (cls === 'malformed') {
|
|
1660
|
+
filesSkipped.push({ path: w.relative, reason: 'malformed PB region — left untouched; fix the pb:region sentinels' });
|
|
1661
|
+
if (preview)
|
|
1662
|
+
previewPlan.push({ path: w.relative, status: 'needs-attention' });
|
|
1663
|
+
malformedRegionPaths.push(w.relative);
|
|
1664
|
+
continue;
|
|
1665
|
+
}
|
|
1666
|
+
// cls 'pb-managed' falls through to legacy re-projection; 'opt-out' (pb:no-augment) falls through to the user-owned skip.
|
|
1667
|
+
}
|
|
1668
|
+
// absent file → fall through to legacy whole-file CREATE.
|
|
1669
|
+
}
|
|
579
1670
|
if (w.isAdapter && !shouldWriteAdapter(w.path, force)) {
|
|
580
|
-
|
|
1671
|
+
// User-owned: a file at an adapter path without our auto-gen MARKER is the
|
|
1672
|
+
// user's own file. Leave it untouched — never overwrite, never treat as drift
|
|
1673
|
+
// or log a TEN (TEN-2150). Relayed to the connect screen via userOwnedSkipped.
|
|
1674
|
+
filesSkipped.push({ path: w.relative, reason: 'user-owned — left untouched (pb won\'t overwrite your file)' });
|
|
1675
|
+
if (preview) {
|
|
1676
|
+
previewPlan.push({ path: w.relative, status: 'user-owned' });
|
|
1677
|
+
}
|
|
1678
|
+
else {
|
|
1679
|
+
userOwnedSkipped.push(w.relative);
|
|
1680
|
+
}
|
|
1681
|
+
continue;
|
|
1682
|
+
}
|
|
1683
|
+
if (authorityPreviewOnly) {
|
|
1684
|
+
filesSkipped.push({
|
|
1685
|
+
path: w.relative,
|
|
1686
|
+
reason: `preview-only (materialize: ${manifestStatus.mode})`,
|
|
1687
|
+
});
|
|
581
1688
|
continue;
|
|
582
1689
|
}
|
|
583
|
-
if (dryRun) {
|
|
584
|
-
|
|
1690
|
+
if (preview || dryRun) {
|
|
1691
|
+
// In preview/dry-run mode: check content to distinguish new/update/unchanged
|
|
1692
|
+
if (existsSync(w.path)) {
|
|
1693
|
+
const current = readFileSync(w.path, 'utf8');
|
|
1694
|
+
const nextNormalized = normalizeHandshakeContentForComparison(w.content);
|
|
1695
|
+
const currentNormalized = normalizeHandshakeContentForComparison(current);
|
|
1696
|
+
if (nextNormalized === currentNormalized) {
|
|
1697
|
+
filesSkipped.push({ path: w.relative, reason: 'unchanged' });
|
|
1698
|
+
if (preview)
|
|
1699
|
+
previewPlan.push({ path: w.relative, status: 'unchanged' });
|
|
1700
|
+
}
|
|
1701
|
+
else {
|
|
1702
|
+
filesWritten.push(w.relative + (dryRun ? ' (dry run)' : ''));
|
|
1703
|
+
if (preview)
|
|
1704
|
+
previewPlan.push({ path: w.relative, status: 'would-update' });
|
|
1705
|
+
}
|
|
1706
|
+
}
|
|
1707
|
+
else {
|
|
1708
|
+
filesWritten.push(w.relative + (dryRun ? ' (dry run)' : ''));
|
|
1709
|
+
if (preview)
|
|
1710
|
+
previewPlan.push({ path: w.relative, status: 'would-write' });
|
|
1711
|
+
}
|
|
585
1712
|
continue;
|
|
586
1713
|
}
|
|
1714
|
+
// ── WP-421 S3: defer tampered adapter writes (doneWhen #17) — classify pb-managed-clean vs
|
|
1715
|
+
// pb-managed-tampered, deferred not overwritten; post-loop resolves. --force bypasses the defer.
|
|
1716
|
+
if (w.isAdapter && !force) {
|
|
1717
|
+
const drift = classifyDriftBucket(w.path);
|
|
1718
|
+
if (drift && drift.bucket === 'pb-managed-tampered') {
|
|
1719
|
+
tamperedBucket.push({
|
|
1720
|
+
path: w.path,
|
|
1721
|
+
relative: w.relative,
|
|
1722
|
+
content: w.content,
|
|
1723
|
+
expectedHash: drift.expectedHash,
|
|
1724
|
+
actualHash: drift.actualHash,
|
|
1725
|
+
dirs: w.dirs,
|
|
1726
|
+
dbAssetEntryId: w.dbAssetEntryId,
|
|
1727
|
+
});
|
|
1728
|
+
// Do NOT write — defer until prompt/refusal resolves the file.
|
|
1729
|
+
continue;
|
|
1730
|
+
}
|
|
1731
|
+
if (drift && drift.bucket === 'pb-managed-clean') {
|
|
1732
|
+
cleanBucketPaths.push(w.relative);
|
|
1733
|
+
}
|
|
1734
|
+
}
|
|
1735
|
+
assertSetupWritePath(w.path, perimeterManifest);
|
|
587
1736
|
if (w.dirs)
|
|
588
1737
|
mkdirSync(w.dirs, { recursive: true });
|
|
1738
|
+
// WP-436 S3: resolve {{vocab:...}} tokens before writing projected adapter files only
|
|
1739
|
+
// (source-side stays tokenized). Fail-open: undefined vocabCtx falls back to canonicalKey literals.
|
|
1740
|
+
const resolvedContent = w.isAdapter
|
|
1741
|
+
? replaceVocabTokens(w.content, handshakeVocabCtx)
|
|
1742
|
+
: w.content;
|
|
589
1743
|
if (existsSync(w.path)) {
|
|
590
1744
|
const current = readFileSync(w.path, 'utf8');
|
|
591
|
-
const nextNormalized = normalizeHandshakeContentForComparison(
|
|
1745
|
+
const nextNormalized = normalizeHandshakeContentForComparison(resolvedContent);
|
|
592
1746
|
const currentNormalized = normalizeHandshakeContentForComparison(current);
|
|
593
1747
|
if (nextNormalized === currentNormalized) {
|
|
594
1748
|
filesSkipped.push({ path: w.relative, reason: 'unchanged' });
|
|
1749
|
+
recordProjectedHash(w.dbAssetEntryId);
|
|
595
1750
|
continue;
|
|
596
1751
|
}
|
|
597
1752
|
}
|
|
598
|
-
writeFileSync(w.path,
|
|
1753
|
+
writeFileSync(w.path, resolvedContent);
|
|
599
1754
|
filesWritten.push(w.relative);
|
|
1755
|
+
recordProjectedHash(w.dbAssetEntryId);
|
|
1756
|
+
}
|
|
1757
|
+
if (projectedHashUpdates.size > 0) {
|
|
1758
|
+
const updates = [...projectedHashUpdates];
|
|
1759
|
+
const results = await Promise.allSettled(updates.map(([entryId, hash]) => kernelCall('setup.updateLastProjectedHash', { entryId, hash })));
|
|
1760
|
+
results.forEach((result, index) => {
|
|
1761
|
+
if (result.status === 'rejected') {
|
|
1762
|
+
const [entryId] = updates[index];
|
|
1763
|
+
trackEvent('skill.projection.failed', {
|
|
1764
|
+
entryId,
|
|
1765
|
+
reason: result.reason instanceof Error ? result.reason.message : String(result.reason),
|
|
1766
|
+
});
|
|
1767
|
+
}
|
|
1768
|
+
});
|
|
1769
|
+
}
|
|
1770
|
+
// Runs AFTER the hash flush (malformed files were never written, nothing to record). TEN-2155:
|
|
1771
|
+
// non-interactive apply refuses on a malformed region — gated on applyMode per STD-263 vi.
|
|
1772
|
+
if (applyMode && malformedRegionPaths.length > 0 && (options.noPrompt || !process.stdout.isTTY)) {
|
|
1773
|
+
throw new CLIError(`Malformed PB region in: ${malformedRegionPaths.join(', ')}`, {
|
|
1774
|
+
code: ErrorCode.VALIDATION_FAILED,
|
|
1775
|
+
category: 'validation',
|
|
1776
|
+
guidance: 'Fix the `<!-- pb:region:start -->` / `<!-- pb:region:end -->` sentinels (one balanced pair), then re-run `pb handshake`.',
|
|
1777
|
+
});
|
|
1778
|
+
}
|
|
1779
|
+
// ── WP-421 S3: tampered-bucket resolution (doneWhen #17), apply mode only — headless (--no-prompt
|
|
1780
|
+
// / non-TTY) refuses (setup_receipt kind='transition', DEC-962, exit non-zero); interactive adopts
|
|
1781
|
+
// (personal draft from tampered content) or reverts (re-project canonical content).
|
|
1782
|
+
const adoptedTamperedPaths = [];
|
|
1783
|
+
const revertedTamperedPaths = [];
|
|
1784
|
+
if (writeMode && tamperedBucket.length > 0) {
|
|
1785
|
+
const headless = options.noPrompt === true || !process.stdout.isTTY;
|
|
1786
|
+
if (headless) {
|
|
1787
|
+
// ── Headless refusal path (doneWhen #17) ────────────────────────────────
|
|
1788
|
+
logErr('');
|
|
1789
|
+
logErr(`pb handshake: ${tamperedBucket.length} PB-managed projection file(s) were edited downstream of the auto-gen marker.`);
|
|
1790
|
+
logErr('Headless mode (--no-prompt or no TTY) cannot resolve adopt-or-revert — refusing.');
|
|
1791
|
+
logErr('');
|
|
1792
|
+
const refusedTamperedFiles = tamperedBucket.map((t) => ({
|
|
1793
|
+
path: t.relative,
|
|
1794
|
+
expectedHash: t.expectedHash,
|
|
1795
|
+
actualHash: t.actualHash,
|
|
1796
|
+
}));
|
|
1797
|
+
for (const refused of refusedTamperedFiles) {
|
|
1798
|
+
// Per #17: stderr enumerates each tampered file as
|
|
1799
|
+
// {path, expectedHash, actualHash, bucket}.
|
|
1800
|
+
logErr(` ${JSON.stringify({ ...refused, bucket: 'pb-managed-tampered' })}`);
|
|
1801
|
+
}
|
|
1802
|
+
logErr('');
|
|
1803
|
+
logErr('Re-run interactively to resolve, or use --force to overwrite (data loss).');
|
|
1804
|
+
// Write the kind='transition' setup_receipt row. Fail-open on the
|
|
1805
|
+
// network/auth side: if the row cannot be written, we still exit non-zero
|
|
1806
|
+
// (the audit trail is best-effort; refusal is mandatory).
|
|
1807
|
+
try {
|
|
1808
|
+
const manifestStatus = readManifestStatus(pbDir);
|
|
1809
|
+
await kernelCall('setup.recordTamperRefusal', {
|
|
1810
|
+
mode: manifestStatus.mode,
|
|
1811
|
+
refusedTamperedFiles,
|
|
1812
|
+
});
|
|
1813
|
+
trackEvent('setup.transition.refused', {
|
|
1814
|
+
fileCount: refusedTamperedFiles.length,
|
|
1815
|
+
mode: manifestStatus.mode,
|
|
1816
|
+
});
|
|
1817
|
+
}
|
|
1818
|
+
catch (err) {
|
|
1819
|
+
trackEvent('setup.transition.refused.write_failed', {
|
|
1820
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1821
|
+
});
|
|
1822
|
+
logErr(`Warning: could not record transition receipt — ${err instanceof Error ? err.message : String(err)}`);
|
|
1823
|
+
}
|
|
1824
|
+
// Surface the report counts before exit (visibility for CI logs).
|
|
1825
|
+
if (!quiet) {
|
|
1826
|
+
const refusalReport = {
|
|
1827
|
+
filesWritten,
|
|
1828
|
+
filesSkipped,
|
|
1829
|
+
matchedEntries,
|
|
1830
|
+
searchQueries: uniqueQueries,
|
|
1831
|
+
repo,
|
|
1832
|
+
codexWarnings: codexWarnings.length > 0 ? codexWarnings : undefined,
|
|
1833
|
+
chainRulesStats: chainRulesStats ?? undefined,
|
|
1834
|
+
chainGaps: chainGaps.length > 0 ? chainGaps : undefined,
|
|
1835
|
+
adoptedCount: adoptedRulesCount,
|
|
1836
|
+
rejectedCount: rejectedRulesCount,
|
|
1837
|
+
personalRuleCount: personalRules.length > 0 ? personalRules.length : undefined,
|
|
1838
|
+
personalSkillCount: personalSkills.length > 0 ? personalSkills.length : undefined,
|
|
1839
|
+
registrySource,
|
|
1840
|
+
registryStale,
|
|
1841
|
+
userOwnedSkipped: userOwnedSkipped.length > 0 ? userOwnedSkipped : undefined,
|
|
1842
|
+
managedCleanCount: cleanBucketPaths.length || undefined,
|
|
1843
|
+
tamperedFiles: refusedTamperedFiles,
|
|
1844
|
+
leftoverFiles: leftoverFiles.length > 0 ? leftoverFiles : undefined,
|
|
1845
|
+
leftoverFilesTruncated: leftoverFilesTruncated || undefined, noProjectionAssets: noProjectionAssets.length > 0 ? noProjectionAssets : undefined, // same-line combine, shrink-only budget
|
|
1846
|
+
};
|
|
1847
|
+
process.stdout.write('\n');
|
|
1848
|
+
process.stdout.write(isJsonMode() ? JSON.stringify(toPublicJsonReport(refusalReport)) + '\n' : formatHandshakeReport(refusalReport) + '\n');
|
|
1849
|
+
}
|
|
1850
|
+
// Exit non-zero per #17.
|
|
1851
|
+
process.exit(1);
|
|
1852
|
+
}
|
|
1853
|
+
// ── Interactive path: prompt adopt-or-revert per file ──────────────────────
|
|
1854
|
+
log('');
|
|
1855
|
+
log(`pb handshake: ${tamperedBucket.length} PB-managed projection file(s) were edited downstream of the auto-gen marker.`);
|
|
1856
|
+
log('You can ADOPT (capture your edits as a personal-scoped draft) or REVERT (overwrite with canonical content).');
|
|
1857
|
+
// Batch yes-to-all / no-to-all when the user has many tampered files.
|
|
1858
|
+
// Threshold: 5 (arbitrary; mirrors the typical handshake projection set).
|
|
1859
|
+
let batchChoice = null;
|
|
1860
|
+
if (tamperedBucket.length >= 5) {
|
|
1861
|
+
const useBatch = await promptConfirm({
|
|
1862
|
+
message: `Apply the same choice to all ${tamperedBucket.length} tampered files?`,
|
|
1863
|
+
initialValue: false,
|
|
1864
|
+
});
|
|
1865
|
+
if (useBatch) {
|
|
1866
|
+
const choice = await promptSelect({
|
|
1867
|
+
message: 'Apply to all:',
|
|
1868
|
+
options: [
|
|
1869
|
+
{ value: 'adopt', label: 'Adopt all — capture each as a personal-scoped draft' },
|
|
1870
|
+
{ value: 'revert', label: 'Revert all — overwrite with canonical content' },
|
|
1871
|
+
],
|
|
1872
|
+
});
|
|
1873
|
+
batchChoice = choice === 'adopt' ? 'adopt-all' : 'revert-all';
|
|
1874
|
+
}
|
|
1875
|
+
}
|
|
1876
|
+
for (const tamper of tamperedBucket) {
|
|
1877
|
+
// Reverse-map the projection path back to the canonical authoring path.
|
|
1878
|
+
const reverse = canonicalPathForAnySurface(tamper.relative);
|
|
1879
|
+
const canonicalHint = reverse
|
|
1880
|
+
? `Canonical authoring path: ${reverse.canonicalPath}`
|
|
1881
|
+
: (() => {
|
|
1882
|
+
// Telemetry + fallback message per surfaces/telemetry.ts.
|
|
1883
|
+
reportReverseMapMissing({ surface: 'unknown', projectionPath: tamper.relative }, logErr);
|
|
1884
|
+
return `Canonical authoring path: ${getReverseMapFallbackMessage()}`;
|
|
1885
|
+
})();
|
|
1886
|
+
log('');
|
|
1887
|
+
log(`Tampered: ${tamper.relative}`);
|
|
1888
|
+
log(` expected: ${tamper.expectedHash}`);
|
|
1889
|
+
log(` actual: ${tamper.actualHash}`);
|
|
1890
|
+
log(` ${canonicalHint}`);
|
|
1891
|
+
let action;
|
|
1892
|
+
if (batchChoice === 'adopt-all')
|
|
1893
|
+
action = 'adopt';
|
|
1894
|
+
else if (batchChoice === 'revert-all')
|
|
1895
|
+
action = 'revert';
|
|
1896
|
+
else {
|
|
1897
|
+
action = await promptSelect({
|
|
1898
|
+
message: 'Adopt or revert?',
|
|
1899
|
+
options: [
|
|
1900
|
+
{ value: 'adopt', label: 'Adopt — capture this as a personal-scoped setup_asset draft' },
|
|
1901
|
+
{ value: 'revert', label: 'Revert — overwrite with canonical content' },
|
|
1902
|
+
],
|
|
1903
|
+
});
|
|
1904
|
+
}
|
|
1905
|
+
if (action === 'revert') {
|
|
1906
|
+
// Re-project canonical content over the tampered file.
|
|
1907
|
+
// WP-436 S3: resolve vocab tokens before writing (all tampered files are adapters).
|
|
1908
|
+
if (tamper.dirs)
|
|
1909
|
+
mkdirSync(tamper.dirs, { recursive: true });
|
|
1910
|
+
assertSetupWritePath(tamper.path, perimeterManifest);
|
|
1911
|
+
writeFileSync(tamper.path, replaceVocabTokens(tamper.content, handshakeVocabCtx));
|
|
1912
|
+
revertedTamperedPaths.push(tamper.relative);
|
|
1913
|
+
recordProjectedHash(tamper.dbAssetEntryId);
|
|
1914
|
+
trackEvent('setup.tampered.reverted', { path: tamper.relative });
|
|
1915
|
+
}
|
|
1916
|
+
else {
|
|
1917
|
+
// Adopt: capture the tampered content as a personal-scoped draft (DEC-953: personal
|
|
1918
|
+
// scope = push, no fork required). Best-effort — on failure the file stays untouched and
|
|
1919
|
+
// a warning is logged. Does NOT revert; preserves the edits AND records them as a draft.
|
|
1920
|
+
const draftName = basename(tamper.relative).replace(/\.(md|mdc)$/, '') + ' (adopted)';
|
|
1921
|
+
try {
|
|
1922
|
+
const tamperedContent = readFileSync(tamper.path, 'utf8');
|
|
1923
|
+
const session = readSession();
|
|
1924
|
+
const caller = session ? kernelCallWithSession : kernelCall;
|
|
1925
|
+
await caller('setup.ingestSetupAsset', {
|
|
1926
|
+
entryId: `SETUP-ADOPTED-${Date.now()}-${draftName.replace(/\s+/g, '-')}`,
|
|
1927
|
+
name: draftName,
|
|
1928
|
+
// WP-421 S3
|
|
1929
|
+
description: `Adopted from tampered projection at ${tamper.relative}.`,
|
|
1930
|
+
body: tamperedContent,
|
|
1931
|
+
assetKind: tamper.relative.includes('/skills/') ? 'skill' : 'rule',
|
|
1932
|
+
triggers: [],
|
|
1933
|
+
semanticRefs: [],
|
|
1934
|
+
});
|
|
1935
|
+
adoptedTamperedPaths.push(tamper.relative);
|
|
1936
|
+
trackEvent('setup.tampered.adopted', { path: tamper.relative });
|
|
1937
|
+
}
|
|
1938
|
+
catch (err) {
|
|
1939
|
+
logErr(`Warning: could not adopt ${tamper.relative} as draft — ${err instanceof Error ? err.message : String(err)}`);
|
|
1940
|
+
trackEvent('setup.tampered.adopt_failed', {
|
|
1941
|
+
path: tamper.relative,
|
|
1942
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1943
|
+
});
|
|
1944
|
+
}
|
|
1945
|
+
}
|
|
1946
|
+
}
|
|
1947
|
+
}
|
|
1948
|
+
// DEC-1690: a dormant (gate-failed) asset is simply not projected — dbAssets already comes
|
|
1949
|
+
// from the server's activeAssets list. The WP-379 S4 / WP-426 E4 on-disk marker/rename/restore
|
|
1950
|
+
// machinery (and its .authoring-sync.json registries) is retired: nothing to reconcile.
|
|
1951
|
+
// 8. User-owned files left untouched are NOT drift (TEN-2150) — a marker-less adapter-path
|
|
1952
|
+
// file is the user's own; handshake never wrote it, so no "sync", no draft TEN, just a benign
|
|
1953
|
+
// "Skipped:" surfaced via report.userOwnedSkipped (the tampered/authoring-sync drift below is unaffected).
|
|
1954
|
+
if (syncDriftTensToFire.length > 0) {
|
|
1955
|
+
const session = readSession();
|
|
1956
|
+
if (session) {
|
|
1957
|
+
for (const driftDescription of syncDriftTensToFire) {
|
|
1958
|
+
kernelCallWithSession('chain.createEntry', {
|
|
1959
|
+
collectionSlug: 'tensions',
|
|
1960
|
+
name: 'TEN: setup authoring sync drift — repo wins',
|
|
1961
|
+
status: 'draft',
|
|
1962
|
+
data: { kind: 'drift', description: driftDescription },
|
|
1963
|
+
sessionId: session.sessionId,
|
|
1964
|
+
createdBy: `agent:${session.sessionId}`,
|
|
1965
|
+
}, { retryOnRateLimit: false }).catch((err) => {
|
|
1966
|
+
// WP-513 round 3 (P2): still fail-open, but surfaced — an unowned rung-2 refusal must not silently drop the drift evidence.
|
|
1967
|
+
logErr(`Warning: could not persist drift TEN (${driftDescription.slice(0, 60)}…) — ${err instanceof Error ? err.message : String(err)}`);
|
|
1968
|
+
});
|
|
1969
|
+
}
|
|
1970
|
+
}
|
|
1971
|
+
}
|
|
1972
|
+
// 8. Case-collision and dormant-drift TENs are gone (coordinator ruling, PR #912 round 10) —
|
|
1973
|
+
// they existed only to audit automated deletions that no longer happen; `report.leftoverFiles`
|
|
1974
|
+
// below is the single reporting surface now.
|
|
1975
|
+
// 8b. Setup receipt — record which assets were materialized (apply mode only)
|
|
1976
|
+
// Fail-open: receipt write is advisory, never blocks the handshake.
|
|
1977
|
+
if (applyMode) {
|
|
1978
|
+
const session = readSession();
|
|
1979
|
+
const caller = session ? kernelCallWithSession : kernelCall;
|
|
1980
|
+
try {
|
|
1981
|
+
const currentState = await caller('setup.getCurrentSetupState', {});
|
|
1982
|
+
const fromMode = currentState?.effectiveMode ?? 'observe';
|
|
1983
|
+
if (fromMode !== manifestStatus.mode) {
|
|
1984
|
+
await caller('setup.recordTransition', {
|
|
1985
|
+
fromMode, toMode: manifestStatus.mode, parseStatus: manifestStatus.parseStatus,
|
|
1986
|
+
surfaces: manifestStatus.surfaces,
|
|
1987
|
+
lock: manifestStatus.lock,
|
|
1988
|
+
});
|
|
1989
|
+
if (modeRank(manifestStatus.mode) < modeRank(fromMode)) {
|
|
1990
|
+
trackEvent('setup.transition.lowered', { fromMode, toMode: manifestStatus.mode });
|
|
1991
|
+
}
|
|
1992
|
+
}
|
|
1993
|
+
}
|
|
1994
|
+
catch (err) {
|
|
1995
|
+
trackEvent('setup.transition.write_failed', { error: err instanceof Error ? err.message : String(err) });
|
|
1996
|
+
logErr(`Warning: could not record setup transition — ${err instanceof Error ? err.message : String(err)}`);
|
|
1997
|
+
}
|
|
1998
|
+
}
|
|
1999
|
+
if (writeMode) {
|
|
2000
|
+
const session = readSession();
|
|
2001
|
+
const caller = session ? kernelCallWithSession : kernelCall;
|
|
2002
|
+
try {
|
|
2003
|
+
const receiptResult = await caller('setup.materializeSetup', {});
|
|
2004
|
+
if (receiptResult?.assetCount > 0) {
|
|
2005
|
+
log(`Setup receipt: ${receiptResult.assetCount} asset(s) recorded.`);
|
|
2006
|
+
}
|
|
2007
|
+
}
|
|
2008
|
+
catch (err) {
|
|
2009
|
+
trackEvent('setup.receipt.write_failed', { error: err instanceof Error ? err.message : String(err) });
|
|
2010
|
+
logErr(`Warning: could not write setup receipt — ${err instanceof Error ? err.message : String(err)}`);
|
|
2011
|
+
}
|
|
600
2012
|
}
|
|
601
|
-
//
|
|
2013
|
+
// 9. Report
|
|
602
2014
|
const report = {
|
|
603
2015
|
filesWritten,
|
|
604
2016
|
filesSkipped,
|
|
@@ -608,10 +2020,33 @@ export async function runHandshake(options = {}) {
|
|
|
608
2020
|
codexWarnings: codexWarnings.length > 0 ? codexWarnings : undefined,
|
|
609
2021
|
chainRulesStats: chainRulesStats ?? undefined,
|
|
610
2022
|
chainGaps: chainGaps.length > 0 ? chainGaps : undefined,
|
|
2023
|
+
adoptedCount: adoptedRulesCount,
|
|
2024
|
+
rejectedCount: rejectedRulesCount,
|
|
2025
|
+
personalRuleCount: personalRules.length > 0 ? personalRules.length : undefined,
|
|
2026
|
+
personalSkillCount: personalSkills.length > 0 ? personalSkills.length : undefined,
|
|
2027
|
+
registrySource,
|
|
2028
|
+
registryStale,
|
|
2029
|
+
preview: preview ? true : undefined,
|
|
2030
|
+
previewPlan: preview && previewPlan.length > 0 ? previewPlan : undefined,
|
|
2031
|
+
userOwnedSkipped: userOwnedSkipped.length > 0 ? userOwnedSkipped : undefined,
|
|
2032
|
+
// WP-421 S3: three-bucket drift report (doneWhen #17). PB-managed-clean is
|
|
2033
|
+
// the count of files whose marker + hash matched. Tampered files were
|
|
2034
|
+
// resolved (adopted/reverted) above and are reported separately.
|
|
2035
|
+
managedCleanCount: cleanBucketPaths.length > 0 ? cleanBucketPaths.length : undefined,
|
|
2036
|
+
adoptedTamperedPaths: adoptedTamperedPaths.length > 0 ? adoptedTamperedPaths : undefined,
|
|
2037
|
+
revertedTamperedPaths: revertedTamperedPaths.length > 0 ? revertedTamperedPaths : undefined,
|
|
2038
|
+
// REPORT-ONLY leftover-file listing (coordinator ruling, PR #912 round 10) — the human removes these.
|
|
2039
|
+
leftoverFiles: leftoverFiles.length > 0 ? leftoverFiles : undefined,
|
|
2040
|
+
leftoverFilesTruncated: leftoverFilesTruncated || undefined, noProjectionAssets: noProjectionAssets.length > 0 ? noProjectionAssets : undefined, // WP-660 S2 combine
|
|
611
2041
|
};
|
|
612
2042
|
if (!quiet) {
|
|
613
2043
|
process.stdout.write('\n');
|
|
614
|
-
process.stdout.write(formatHandshakeReport(report) + '\n');
|
|
2044
|
+
process.stdout.write(isJsonMode() ? JSON.stringify(toPublicJsonReport(report)) + '\n' : formatHandshakeReport(report) + '\n');
|
|
615
2045
|
}
|
|
2046
|
+
// Return the report so non-UI callers (e.g. prepareConnectContext) can surface
|
|
2047
|
+
// skipped/user-owned files without re-deriving the skip logic (TEN-2107).
|
|
2048
|
+
return report;
|
|
616
2049
|
}
|
|
2050
|
+
// WP-426 E3/E4: exported test-only surface (not part of the public CLI API).
|
|
2051
|
+
export const __test = { setupAuthoringPath, loadAuthoringSyncState, MARKER };
|
|
617
2052
|
//# sourceMappingURL=handshake.js.map
|