@productbrain/cli 0.1.0-beta.15 → 0.1.0-beta.1502
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 +76 -115
- package/dist/__tests__/adapters.test.d.ts +2 -0
- package/dist/__tests__/adapters.test.d.ts.map +1 -0
- package/dist/__tests__/adapters.test.js +417 -0
- package/dist/__tests__/adapters.test.js.map +1 -0
- package/dist/__tests__/audit.test.js +65 -44
- package/dist/__tests__/audit.test.js.map +1 -1
- package/dist/__tests__/authority-domains-queue.test.d.ts +2 -0
- package/dist/__tests__/authority-domains-queue.test.d.ts.map +1 -0
- package/dist/__tests__/authority-domains-queue.test.js +169 -0
- package/dist/__tests__/authority-domains-queue.test.js.map +1 -0
- package/dist/__tests__/authority-domains.test.d.ts +2 -0
- package/dist/__tests__/authority-domains.test.d.ts.map +1 -0
- package/dist/__tests__/authority-domains.test.js +48 -0
- package/dist/__tests__/authority-domains.test.js.map +1 -0
- package/dist/__tests__/batch-transformations.test.d.ts +2 -0
- package/dist/__tests__/batch-transformations.test.d.ts.map +1 -0
- package/dist/__tests__/batch-transformations.test.js +263 -0
- package/dist/__tests__/batch-transformations.test.js.map +1 -0
- 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-domain.test.d.ts +2 -0
- package/dist/__tests__/capture-receipt-domain.test.d.ts.map +1 -0
- package/dist/__tests__/capture-receipt-domain.test.js +29 -0
- package/dist/__tests__/capture-receipt-domain.test.js.map +1 -0
- package/dist/__tests__/capture.test.js +309 -18
- package/dist/__tests__/capture.test.js.map +1 -1
- 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__/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 +82 -0
- package/dist/__tests__/config-prod-fallthrough.test.js.map +1 -0
- package/dist/__tests__/config.test.d.ts +8 -0
- package/dist/__tests__/config.test.d.ts.map +1 -0
- package/dist/__tests__/config.test.js +566 -0
- package/dist/__tests__/config.test.js.map +1 -0
- package/dist/__tests__/constants.test.d.ts +2 -0
- package/dist/__tests__/constants.test.d.ts.map +1 -0
- package/dist/__tests__/constants.test.js +146 -0
- package/dist/__tests__/constants.test.js.map +1 -0
- package/dist/__tests__/constellation.test.js +16 -22
- package/dist/__tests__/constellation.test.js.map +1 -1
- package/dist/__tests__/context-strategy.test.js +8 -8
- package/dist/__tests__/context-strategy.test.js.map +1 -1
- 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 +152 -0
- package/dist/__tests__/envelope-contract.test.js.map +1 -0
- package/dist/__tests__/errors.test.d.ts +2 -0
- package/dist/__tests__/errors.test.d.ts.map +1 -0
- package/dist/__tests__/errors.test.js +118 -0
- package/dist/__tests__/errors.test.js.map +1 -0
- package/dist/__tests__/experiment.test.d.ts +6 -0
- package/dist/__tests__/experiment.test.d.ts.map +1 -0
- package/dist/__tests__/experiment.test.js +69 -0
- package/dist/__tests__/experiment.test.js.map +1 -0
- package/dist/__tests__/fields.test.js +36 -36
- package/dist/__tests__/fields.test.js.map +1 -1
- package/dist/__tests__/glossary.test.d.ts +2 -0
- package/dist/__tests__/glossary.test.d.ts.map +1 -0
- package/dist/__tests__/glossary.test.js +32 -0
- package/dist/__tests__/glossary.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 +423 -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 +207 -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 +67 -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 +949 -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 +1252 -0
- package/dist/__tests__/handshake.e2e.test.js.map +1 -0
- package/dist/__tests__/handshake.test.js +813 -19
- package/dist/__tests__/handshake.test.js.map +1 -1
- 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 +28 -28
- package/dist/__tests__/ingest.test.js.map +1 -1
- package/dist/__tests__/init.test.d.ts +7 -0
- package/dist/__tests__/init.test.d.ts.map +1 -0
- package/dist/__tests__/init.test.js +146 -0
- package/dist/__tests__/init.test.js.map +1 -0
- package/dist/__tests__/login.test.d.ts +2 -0
- package/dist/__tests__/login.test.d.ts.map +1 -0
- package/dist/__tests__/login.test.js +167 -0
- package/dist/__tests__/login.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 +18 -0
- package/dist/__tests__/method-registry.integration.test.js.map +1 -0
- package/dist/__tests__/method-registry.test.d.ts +14 -0
- package/dist/__tests__/method-registry.test.d.ts.map +1 -0
- package/dist/__tests__/method-registry.test.js +134 -0
- package/dist/__tests__/method-registry.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 +41 -0
- package/dist/__tests__/notice-marker.test.js.map +1 -0
- package/dist/__tests__/onboarding-path-b.test.d.ts +2 -0
- package/dist/__tests__/onboarding-path-b.test.d.ts.map +1 -0
- package/dist/__tests__/onboarding-path-b.test.js +46 -0
- package/dist/__tests__/onboarding-path-b.test.js.map +1 -0
- package/dist/__tests__/onboarding.test.d.ts +6 -0
- package/dist/__tests__/onboarding.test.d.ts.map +1 -0
- package/dist/__tests__/onboarding.test.js +347 -0
- package/dist/__tests__/onboarding.test.js.map +1 -0
- package/dist/__tests__/orient.test.d.ts +2 -0
- package/dist/__tests__/orient.test.d.ts.map +1 -0
- package/dist/__tests__/orient.test.js +424 -0
- package/dist/__tests__/orient.test.js.map +1 -0
- 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.d.ts +2 -0
- package/dist/__tests__/profiles.test.d.ts.map +1 -0
- package/dist/__tests__/profiles.test.js +316 -0
- package/dist/__tests__/profiles.test.js.map +1 -0
- package/dist/__tests__/promote-batch.test.d.ts +2 -0
- package/dist/__tests__/promote-batch.test.d.ts.map +1 -0
- package/dist/__tests__/promote-batch.test.js +185 -0
- package/dist/__tests__/promote-batch.test.js.map +1 -0
- package/dist/__tests__/promote.test.js +213 -34
- package/dist/__tests__/promote.test.js.map +1 -1
- package/dist/__tests__/prompts.test.d.ts +6 -0
- package/dist/__tests__/prompts.test.d.ts.map +1 -0
- package/dist/__tests__/prompts.test.js +146 -0
- package/dist/__tests__/prompts.test.js.map +1 -0
- 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 +24 -47
- package/dist/__tests__/proposals.test.js.map +1 -1
- package/dist/__tests__/relate.test.js +34 -36
- package/dist/__tests__/relate.test.js.map +1 -1
- package/dist/__tests__/repo-detect.test.js +97 -1
- package/dist/__tests__/repo-detect.test.js.map +1 -1
- package/dist/__tests__/runner.test.js +19 -15
- package/dist/__tests__/runner.test.js.map +1 -1
- 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 +231 -0
- package/dist/__tests__/session-close-loop.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 +122 -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 +97 -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 +179 -0
- package/dist/__tests__/session-start-key-refresh.test.js.map +1 -0
- package/dist/__tests__/session-state-machine.test.d.ts +2 -0
- package/dist/__tests__/session-state-machine.test.d.ts.map +1 -0
- package/dist/__tests__/session-state-machine.test.js +198 -0
- package/dist/__tests__/session-state-machine.test.js.map +1 -0
- 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 +130 -0
- package/dist/__tests__/session-switch.test.js.map +1 -0
- package/dist/__tests__/session-touch.test.js +11 -11
- package/dist/__tests__/session-touch.test.js.map +1 -1
- package/dist/__tests__/session.test.js +4 -10
- package/dist/__tests__/session.test.js.map +1 -1
- 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__/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__/spinner-labels.test.d.ts +2 -0
- package/dist/__tests__/spinner-labels.test.d.ts.map +1 -0
- package/dist/__tests__/spinner-labels.test.js +23 -0
- package/dist/__tests__/spinner-labels.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 +97 -0
- package/dist/__tests__/state.test.js.map +1 -0
- package/dist/__tests__/surface-profiles.test.d.ts +2 -0
- package/dist/__tests__/surface-profiles.test.d.ts.map +1 -0
- package/dist/__tests__/surface-profiles.test.js +233 -0
- package/dist/__tests__/surface-profiles.test.js.map +1 -0
- 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__/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 +63 -72
- 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__/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 +534 -0
- package/dist/__tests__/vocabulary-leak.test.js.map +1 -0
- package/dist/__tests__/workspace.test.d.ts +2 -0
- package/dist/__tests__/workspace.test.d.ts.map +1 -0
- package/dist/__tests__/workspace.test.js +328 -0
- package/dist/__tests__/workspace.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__/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/accept.d.ts.map +1 -1
- package/dist/commands/accept.js +10 -6
- package/dist/commands/accept.js.map +1 -1
- package/dist/commands/admin/cockpit.d.ts +90 -0
- package/dist/commands/admin/cockpit.d.ts.map +1 -0
- package/dist/commands/admin/cockpit.js +618 -0
- package/dist/commands/admin/cockpit.js.map +1 -0
- package/dist/commands/admin/index.d.ts +21 -0
- package/dist/commands/admin/index.d.ts.map +1 -0
- package/dist/commands/admin/index.js +256 -0
- package/dist/commands/admin/index.js.map +1 -0
- package/dist/commands/admin/inspect.d.ts +30 -0
- package/dist/commands/admin/inspect.d.ts.map +1 -0
- package/dist/commands/admin/inspect.js +555 -0
- package/dist/commands/admin/inspect.js.map +1 -0
- package/dist/commands/admin/inspect.test.d.ts +7 -0
- package/dist/commands/admin/inspect.test.d.ts.map +1 -0
- package/dist/commands/admin/inspect.test.js +90 -0
- package/dist/commands/admin/inspect.test.js.map +1 -0
- package/dist/commands/admin/manage.d.ts +8 -0
- package/dist/commands/admin/manage.d.ts.map +1 -0
- package/dist/commands/admin/manage.js +260 -0
- package/dist/commands/admin/manage.js.map +1 -0
- 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 +159 -0
- package/dist/commands/admin/manage.test.js.map +1 -0
- package/dist/commands/admin/seed.d.ts +75 -0
- package/dist/commands/admin/seed.d.ts.map +1 -0
- package/dist/commands/admin/seed.js +944 -0
- package/dist/commands/admin/seed.js.map +1 -0
- package/dist/commands/admin/seed.test.d.ts +11 -0
- package/dist/commands/admin/seed.test.d.ts.map +1 -0
- package/dist/commands/admin/seed.test.js +127 -0
- package/dist/commands/admin/seed.test.js.map +1 -0
- 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 +144 -0
- package/dist/commands/admin/seedRegistryEntries.generated.js.map +1 -0
- package/dist/commands/admin/seedRegistryEntries.test.d.ts +11 -0
- package/dist/commands/admin/seedRegistryEntries.test.d.ts.map +1 -0
- package/dist/commands/admin/seedRegistryEntries.test.js +70 -0
- package/dist/commands/admin/seedRegistryEntries.test.js.map +1 -0
- package/dist/commands/audit.d.ts.map +1 -1
- package/dist/commands/audit.js +42 -7
- package/dist/commands/audit.js.map +1 -1
- package/dist/commands/authority-domains.d.ts +157 -0
- package/dist/commands/authority-domains.d.ts.map +1 -0
- package/dist/commands/authority-domains.js +356 -0
- package/dist/commands/authority-domains.js.map +1 -0
- package/dist/commands/brief.d.ts.map +1 -1
- package/dist/commands/brief.js +10 -5
- package/dist/commands/brief.js.map +1 -1
- package/dist/commands/capture.d.ts +7 -0
- package/dist/commands/capture.d.ts.map +1 -1
- package/dist/commands/capture.js +266 -19
- package/dist/commands/capture.js.map +1 -1
- package/dist/commands/chain-walk.d.ts.map +1 -1
- package/dist/commands/chain-walk.js +8 -3
- package/dist/commands/chain-walk.js.map +1 -1
- package/dist/commands/changes.d.ts.map +1 -1
- package/dist/commands/changes.js +8 -3
- package/dist/commands/changes.js.map +1 -1
- package/dist/commands/codex-prep.d.ts +23 -0
- package/dist/commands/codex-prep.d.ts.map +1 -0
- package/dist/commands/codex-prep.js +56 -0
- package/dist/commands/codex-prep.js.map +1 -0
- package/dist/commands/collections.d.ts +22 -0
- package/dist/commands/collections.d.ts.map +1 -0
- package/dist/commands/collections.js +77 -0
- package/dist/commands/collections.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 +45 -0
- package/dist/commands/connect-context.d.ts.map +1 -0
- package/dist/commands/connect-context.js +64 -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 +110 -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.d.ts +7 -0
- package/dist/commands/connect-integration.test.d.ts.map +1 -0
- package/dist/commands/connect-integration.test.js +212 -0
- package/dist/commands/connect-integration.test.js.map +1 -0
- package/dist/commands/connect-screens.d.ts +23 -0
- package/dist/commands/connect-screens.d.ts.map +1 -0
- package/dist/commands/connect-screens.js +90 -0
- package/dist/commands/connect-screens.js.map +1 -0
- package/dist/commands/connect.d.ts +36 -0
- package/dist/commands/connect.d.ts.map +1 -0
- package/dist/commands/connect.js +264 -0
- package/dist/commands/connect.js.map +1 -0
- package/dist/commands/connect.test.d.ts +6 -0
- package/dist/commands/connect.test.d.ts.map +1 -0
- package/dist/commands/connect.test.js +297 -0
- package/dist/commands/connect.test.js.map +1 -0
- package/dist/commands/constellation.d.ts.map +1 -1
- package/dist/commands/constellation.js +8 -3
- package/dist/commands/constellation.js.map +1 -1
- package/dist/commands/context.d.ts.map +1 -1
- package/dist/commands/context.js +8 -3
- package/dist/commands/context.js.map +1 -1
- package/dist/commands/cross-cut.js +2 -2
- package/dist/commands/cross-cut.js.map +1 -1
- package/dist/commands/doctor.d.ts +18 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +297 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/doctor.test.d.ts +8 -0
- package/dist/commands/doctor.test.d.ts.map +1 -0
- package/dist/commands/doctor.test.js +461 -0
- package/dist/commands/doctor.test.js.map +1 -0
- package/dist/commands/fields.d.ts.map +1 -1
- package/dist/commands/fields.js +8 -4
- package/dist/commands/fields.js.map +1 -1
- package/dist/commands/get.d.ts.map +1 -1
- package/dist/commands/get.js +14 -6
- package/dist/commands/get.js.map +1 -1
- package/dist/commands/handshake.d.ts +233 -2
- package/dist/commands/handshake.d.ts.map +1 -1
- package/dist/commands/handshake.js +2338 -81
- package/dist/commands/handshake.js.map +1 -1
- package/dist/commands/ingest.d.ts.map +1 -1
- package/dist/commands/ingest.js +17 -9
- package/dist/commands/ingest.js.map +1 -1
- package/dist/commands/init.d.ts +14 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +109 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/login.d.ts +4 -0
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +101 -38
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/method.d.ts +99 -0
- package/dist/commands/method.d.ts.map +1 -0
- package/dist/commands/method.js +796 -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 +148 -0
- package/dist/commands/migrate-setup.js.map +1 -0
- package/dist/commands/orient.d.ts +197 -3
- package/dist/commands/orient.d.ts.map +1 -1
- package/dist/commands/orient.js +129 -7
- package/dist/commands/orient.js.map +1 -1
- package/dist/commands/profile.d.ts +34 -0
- package/dist/commands/profile.d.ts.map +1 -0
- package/dist/commands/profile.js +165 -0
- package/dist/commands/profile.js.map +1 -0
- package/dist/commands/promote.d.ts +12 -1
- package/dist/commands/promote.d.ts.map +1 -1
- package/dist/commands/promote.js +197 -30
- package/dist/commands/promote.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.js +2 -2
- package/dist/commands/proposals.js.map +1 -1
- package/dist/commands/reject.d.ts.map +1 -1
- package/dist/commands/reject.js +14 -7
- package/dist/commands/reject.js.map +1 -1
- package/dist/commands/relate.d.ts.map +1 -1
- package/dist/commands/relate.js +49 -16
- package/dist/commands/relate.js.map +1 -1
- 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.js +2 -2
- package/dist/commands/search.js.map +1 -1
- package/dist/commands/session.d.ts +26 -2
- package/dist/commands/session.d.ts.map +1 -1
- package/dist/commands/session.js +355 -41
- 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 +174 -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 +23 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +69 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/commands/update.d.ts +9 -0
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +92 -26
- 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 +40 -0
- package/dist/commands/usage.d.ts.map +1 -0
- package/dist/commands/usage.js +232 -0
- package/dist/commands/usage.js.map +1 -0
- package/dist/commands/verify.d.ts.map +1 -1
- package/dist/commands/verify.js +14 -7
- 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 +50 -0
- package/dist/commands/welcome.js.map +1 -0
- package/dist/commands/whoami.d.ts +12 -0
- package/dist/commands/whoami.d.ts.map +1 -0
- package/dist/commands/whoami.js +70 -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 +50 -0
- package/dist/commands/whoami.test.js.map +1 -0
- package/dist/commands/workspace.d.ts +113 -0
- package/dist/commands/workspace.d.ts.map +1 -0
- package/dist/commands/workspace.js +263 -0
- package/dist/commands/workspace.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 +454 -0
- package/dist/formatters/__tests__/orient-provenance.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 +113 -0
- package/dist/formatters/__tests__/session.test.js.map +1 -0
- package/dist/formatters/audit.d.ts +6 -0
- package/dist/formatters/audit.d.ts.map +1 -1
- package/dist/formatters/audit.js.map +1 -1
- package/dist/formatters/capture.d.ts +26 -3
- package/dist/formatters/capture.d.ts.map +1 -1
- package/dist/formatters/capture.js +25 -1
- package/dist/formatters/capture.js.map +1 -1
- package/dist/formatters/collections.d.ts +40 -0
- package/dist/formatters/collections.d.ts.map +1 -0
- package/dist/formatters/collections.js +93 -0
- package/dist/formatters/collections.js.map +1 -0
- package/dist/formatters/entry.d.ts +30 -4
- package/dist/formatters/entry.d.ts.map +1 -1
- package/dist/formatters/entry.js +66 -17
- package/dist/formatters/entry.js.map +1 -1
- package/dist/formatters/handshake.d.ts +45 -0
- package/dist/formatters/handshake.d.ts.map +1 -1
- package/dist/formatters/handshake.js +150 -3
- package/dist/formatters/handshake.js.map +1 -1
- package/dist/formatters/orient.d.ts +268 -5
- package/dist/formatters/orient.d.ts.map +1 -1
- package/dist/formatters/orient.js +381 -34
- package/dist/formatters/orient.js.map +1 -1
- package/dist/formatters/promote.d.ts +6 -0
- package/dist/formatters/promote.d.ts.map +1 -1
- package/dist/formatters/promote.js +8 -0
- package/dist/formatters/promote.js.map +1 -1
- package/dist/formatters/relate.d.ts +2 -0
- package/dist/formatters/relate.d.ts.map +1 -1
- package/dist/formatters/relate.js +3 -0
- package/dist/formatters/relate.js.map +1 -1
- package/dist/formatters/scoreboard.d.ts +11 -0
- package/dist/formatters/scoreboard.d.ts.map +1 -0
- package/dist/formatters/scoreboard.js +48 -0
- package/dist/formatters/scoreboard.js.map +1 -0
- package/dist/formatters/search.d.ts +0 -4
- package/dist/formatters/search.d.ts.map +1 -1
- package/dist/formatters/search.js +4 -1
- package/dist/formatters/search.js.map +1 -1
- package/dist/formatters/session.d.ts +39 -2
- package/dist/formatters/session.d.ts.map +1 -1
- package/dist/formatters/session.js +130 -9
- package/dist/formatters/session.js.map +1 -1
- package/dist/formatters/update.d.ts.map +1 -1
- package/dist/formatters/update.js +2 -0
- package/dist/formatters/update.js.map +1 -1
- package/dist/generators/adapters.d.ts +37 -3
- package/dist/generators/adapters.d.ts.map +1 -1
- package/dist/generators/adapters.js +196 -8
- package/dist/generators/adapters.js.map +1 -1
- package/dist/generators/adapters.test.d.ts +2 -0
- package/dist/generators/adapters.test.d.ts.map +1 -0
- package/dist/generators/adapters.test.js +27 -0
- package/dist/generators/adapters.test.js.map +1 -0
- package/dist/generators/archetypes.d.ts +52 -0
- package/dist/generators/archetypes.d.ts.map +1 -0
- package/dist/generators/archetypes.js +190 -0
- package/dist/generators/archetypes.js.map +1 -0
- package/dist/generators/archetypes.test.d.ts +2 -0
- package/dist/generators/archetypes.test.d.ts.map +1 -0
- package/dist/generators/archetypes.test.js +272 -0
- package/dist/generators/archetypes.test.js.map +1 -0
- 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.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.d.ts +63 -0
- package/dist/generators/chain-classifier.d.ts.map +1 -0
- package/dist/generators/chain-classifier.js +131 -0
- package/dist/generators/chain-classifier.js.map +1 -0
- package/dist/generators/chain-classifier.test.d.ts +2 -0
- package/dist/generators/chain-classifier.test.d.ts.map +1 -0
- package/dist/generators/chain-classifier.test.js +371 -0
- package/dist/generators/chain-classifier.test.js.map +1 -0
- package/dist/generators/chain-rules.d.ts +42 -0
- package/dist/generators/chain-rules.d.ts.map +1 -0
- package/dist/generators/chain-rules.js +152 -0
- package/dist/generators/chain-rules.js.map +1 -0
- package/dist/generators/chain-rules.test.d.ts +2 -0
- package/dist/generators/chain-rules.test.d.ts.map +1 -0
- package/dist/generators/chain-rules.test.js +211 -0
- package/dist/generators/chain-rules.test.js.map +1 -0
- package/dist/generators/context-md.d.ts +1 -1
- package/dist/generators/context-md.d.ts.map +1 -1
- package/dist/generators/context-md.js +18 -7
- package/dist/generators/context-md.js.map +1 -1
- package/dist/generators/handshake-diff.d.ts +67 -0
- package/dist/generators/handshake-diff.d.ts.map +1 -0
- package/dist/generators/handshake-diff.js +183 -0
- package/dist/generators/handshake-diff.js.map +1 -0
- package/dist/generators/handshake-diff.test.d.ts +2 -0
- package/dist/generators/handshake-diff.test.d.ts.map +1 -0
- package/dist/generators/handshake-diff.test.js +264 -0
- package/dist/generators/handshake-diff.test.js.map +1 -0
- 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/portable-knowledge.d.ts +96 -9
- package/dist/generators/portable-knowledge.d.ts.map +1 -1
- package/dist/generators/portable-knowledge.js +367 -17
- package/dist/generators/portable-knowledge.js.map +1 -1
- package/dist/generators/portable-knowledge.test.js +529 -1
- package/dist/generators/portable-knowledge.test.js.map +1 -1
- package/dist/generators/region-projections.d.ts +18 -0
- package/dist/generators/region-projections.d.ts.map +1 -0
- package/dist/generators/region-projections.js +49 -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 +48 -0
- package/dist/generators/surface-profiles.d.ts.map +1 -0
- package/dist/generators/surface-profiles.js +98 -0
- package/dist/generators/surface-profiles.js.map +1 -0
- package/dist/index.js +800 -252
- package/dist/index.js.map +1 -1
- package/dist/lib/activation.d.ts +28 -0
- package/dist/lib/activation.d.ts.map +1 -0
- package/dist/lib/activation.js +57 -0
- package/dist/lib/activation.js.map +1 -0
- package/dist/lib/activation.test.d.ts +6 -0
- package/dist/lib/activation.test.d.ts.map +1 -0
- package/dist/lib/activation.test.js +121 -0
- package/dist/lib/activation.test.js.map +1 -0
- package/dist/lib/canonicalRefs.d.ts +141 -0
- package/dist/lib/canonicalRefs.d.ts.map +1 -0
- package/dist/lib/canonicalRefs.js +150 -0
- package/dist/lib/canonicalRefs.js.map +1 -0
- package/dist/lib/client.d.ts +33 -6
- package/dist/lib/client.d.ts.map +1 -1
- package/dist/lib/client.js +203 -42
- package/dist/lib/client.js.map +1 -1
- package/dist/lib/collectionRegistry.d.ts +40 -0
- package/dist/lib/collectionRegistry.d.ts.map +1 -0
- package/dist/lib/collectionRegistry.js +112 -0
- package/dist/lib/collectionRegistry.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 +204 -4
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +594 -42
- package/dist/lib/config.js.map +1 -1
- 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 +46 -0
- package/dist/lib/constants.d.ts.map +1 -0
- package/dist/lib/constants.js +83 -0
- package/dist/lib/constants.js.map +1 -0
- package/dist/lib/conversation-engine.d.ts +45 -0
- package/dist/lib/conversation-engine.d.ts.map +1 -0
- package/dist/lib/conversation-engine.js +112 -0
- package/dist/lib/conversation-engine.js.map +1 -0
- package/dist/lib/conversation-phases.d.ts +59 -0
- package/dist/lib/conversation-phases.d.ts.map +1 -0
- package/dist/lib/conversation-phases.js +11 -0
- package/dist/lib/conversation-phases.js.map +1 -0
- package/dist/lib/conversation-signals.d.ts +30 -0
- package/dist/lib/conversation-signals.d.ts.map +1 -0
- package/dist/lib/conversation-signals.js +64 -0
- package/dist/lib/conversation-signals.js.map +1 -0
- package/dist/lib/deployment.d.ts +23 -0
- package/dist/lib/deployment.d.ts.map +1 -0
- package/dist/lib/deployment.js +78 -0
- package/dist/lib/deployment.js.map +1 -0
- package/dist/lib/deployment.test.d.ts +5 -0
- package/dist/lib/deployment.test.d.ts.map +1 -0
- package/dist/lib/deployment.test.js +54 -0
- package/dist/lib/deployment.test.js.map +1 -0
- package/dist/lib/errors.d.ts +63 -0
- package/dist/lib/errors.d.ts.map +1 -0
- package/dist/lib/errors.js +72 -0
- package/dist/lib/errors.js.map +1 -0
- package/dist/lib/experiment.d.ts +18 -0
- package/dist/lib/experiment.d.ts.map +1 -0
- package/dist/lib/experiment.js +28 -0
- package/dist/lib/experiment.js.map +1 -0
- package/dist/lib/format.d.ts +10 -0
- package/dist/lib/format.d.ts.map +1 -0
- package/dist/lib/format.js +27 -0
- package/dist/lib/format.js.map +1 -0
- 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/glossary.d.ts +19 -0
- package/dist/lib/glossary.d.ts.map +1 -0
- package/dist/lib/glossary.js +53 -0
- package/dist/lib/glossary.js.map +1 -0
- 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 +85 -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/method-registry.d.ts +32 -0
- package/dist/lib/method-registry.d.ts.map +1 -0
- package/dist/lib/method-registry.js +53 -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 +53 -0
- package/dist/lib/notice-marker.js.map +1 -0
- package/dist/lib/onboarding-path-b.d.ts +10 -0
- package/dist/lib/onboarding-path-b.d.ts.map +1 -0
- package/dist/lib/onboarding-path-b.js +213 -0
- package/dist/lib/onboarding-path-b.js.map +1 -0
- package/dist/lib/onboarding-shared.d.ts +80 -0
- package/dist/lib/onboarding-shared.d.ts.map +1 -0
- package/dist/lib/onboarding-shared.js +174 -0
- package/dist/lib/onboarding-shared.js.map +1 -0
- package/dist/lib/onboarding-topics.d.ts +27 -0
- package/dist/lib/onboarding-topics.d.ts.map +1 -0
- package/dist/lib/onboarding-topics.js +57 -0
- package/dist/lib/onboarding-topics.js.map +1 -0
- package/dist/lib/onboarding.d.ts +17 -0
- package/dist/lib/onboarding.d.ts.map +1 -0
- package/dist/lib/onboarding.js +350 -0
- package/dist/lib/onboarding.js.map +1 -0
- package/dist/lib/profiles.d.ts +41 -0
- package/dist/lib/profiles.d.ts.map +1 -0
- package/dist/lib/profiles.js +188 -0
- package/dist/lib/profiles.js.map +1 -0
- package/dist/lib/prompts.d.ts +65 -0
- package/dist/lib/prompts.d.ts.map +1 -0
- package/dist/lib/prompts.js +132 -0
- package/dist/lib/prompts.js.map +1 -0
- package/dist/lib/repo-detect.d.ts +19 -0
- package/dist/lib/repo-detect.d.ts.map +1 -1
- package/dist/lib/repo-detect.js +25 -0
- package/dist/lib/repo-detect.js.map +1 -1
- package/dist/lib/runner.d.ts +2 -0
- package/dist/lib/runner.d.ts.map +1 -1
- package/dist/lib/runner.js +21 -7
- package/dist/lib/runner.js.map +1 -1
- package/dist/lib/session.d.ts +35 -0
- package/dist/lib/session.d.ts.map +1 -1
- package/dist/lib/session.js +94 -3
- package/dist/lib/session.js.map +1 -1
- package/dist/lib/spinner.d.ts +27 -0
- package/dist/lib/spinner.d.ts.map +1 -0
- package/dist/lib/spinner.js +76 -0
- package/dist/lib/spinner.js.map +1 -0
- package/dist/lib/spinner.test.d.ts +2 -0
- package/dist/lib/spinner.test.d.ts.map +1 -0
- package/dist/lib/spinner.test.js +39 -0
- package/dist/lib/spinner.test.js.map +1 -0
- 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 +118 -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/state.d.ts +51 -0
- package/dist/lib/state.d.ts.map +1 -0
- package/dist/lib/state.js +90 -0
- package/dist/lib/state.js.map +1 -0
- package/dist/lib/strip.d.ts +1 -0
- package/dist/lib/strip.d.ts.map +1 -1
- package/dist/lib/strip.js +15 -0
- package/dist/lib/strip.js.map +1 -1
- package/dist/lib/style.d.ts +96 -0
- package/dist/lib/style.d.ts.map +1 -0
- package/dist/lib/style.js +169 -0
- package/dist/lib/style.js.map +1 -0
- package/dist/lib/style.test.d.ts +7 -0
- package/dist/lib/style.test.d.ts.map +1 -0
- package/dist/lib/style.test.js +263 -0
- package/dist/lib/style.test.js.map +1 -0
- package/dist/lib/telemetry.d.ts +15 -0
- package/dist/lib/telemetry.d.ts.map +1 -0
- package/dist/lib/telemetry.js +47 -0
- package/dist/lib/telemetry.js.map +1 -0
- package/dist/lib/tokenConstants.d.ts +19 -0
- package/dist/lib/tokenConstants.d.ts.map +1 -0
- package/dist/lib/tokenConstants.js +19 -0
- package/dist/lib/tokenConstants.js.map +1 -0
- package/dist/lib/update-check.d.ts +56 -0
- package/dist/lib/update-check.d.ts.map +1 -0
- package/dist/lib/update-check.js +296 -0
- package/dist/lib/update-check.js.map +1 -0
- 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/wizard-surfaces.d.ts +47 -0
- package/dist/lib/wizard-surfaces.d.ts.map +1 -0
- package/dist/lib/wizard-surfaces.js +176 -0
- package/dist/lib/wizard-surfaces.js.map +1 -0
- package/dist/lib/wizard-surfaces.test.d.ts +2 -0
- package/dist/lib/wizard-surfaces.test.d.ts.map +1 -0
- package/dist/lib/wizard-surfaces.test.js +127 -0
- package/dist/lib/wizard-surfaces.test.js.map +1 -0
- package/dist/lib/wizard-trust.d.ts +31 -0
- package/dist/lib/wizard-trust.d.ts.map +1 -0
- package/dist/lib/wizard-trust.js +66 -0
- package/dist/lib/wizard-trust.js.map +1 -0
- package/dist/lib/wizard-trust.test.d.ts +2 -0
- package/dist/lib/wizard-trust.test.d.ts.map +1 -0
- package/dist/lib/wizard-trust.test.js +32 -0
- package/dist/lib/wizard-trust.test.js.map +1 -0
- package/dist/lib/workspace-probe.d.ts +19 -0
- package/dist/lib/workspace-probe.d.ts.map +1 -0
- package/dist/lib/workspace-probe.js +27 -0
- package/dist/lib/workspace-probe.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/scoreboard/diagnose.d.ts +182 -0
- package/dist/scoreboard/diagnose.d.ts.map +1 -0
- package/dist/scoreboard/diagnose.js +250 -0
- package/dist/scoreboard/diagnose.js.map +1 -0
- package/dist/scoreboard/diagnose.test.d.ts +12 -0
- package/dist/scoreboard/diagnose.test.d.ts.map +1 -0
- package/dist/scoreboard/diagnose.test.js +192 -0
- package/dist/scoreboard/diagnose.test.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 +90 -0
- package/dist/surfaces/__tests__/adapter.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 +132 -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 +67 -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 +12 -4
- package/templates/archetypes/boundary.md +23 -0
- package/templates/archetypes/constraint.md +23 -0
- package/templates/archetypes/convention.md +23 -0
- package/templates/archetypes/policy.md +23 -0
- package/templates/archetypes/quality-gate.md +23 -0
- package/templates/archetypes/workflow.md +23 -0
- package/templates/general/code-integrity.md +11 -0
- package/templates/general/getting-started.md +12 -0
- package/templates/method-registry.json +16 -0
- package/templates/node-ts/code-integrity.md +13 -0
- package/templates/node-ts/testing.md +12 -0
- package/templates/python/code-integrity.md +13 -0
- package/templates/python/testing.md +12 -0
|
@@ -2,12 +2,19 @@
|
|
|
2
2
|
* pb handshake --init — unit tests.
|
|
3
3
|
* DEC-271: two-file split (team vs personal). DEC-272: permission whitelist.
|
|
4
4
|
* TEN-712: hooks must fail silently (|| true suffix).
|
|
5
|
+
*
|
|
6
|
+
* WP-379 S3b: probeStarterSetupSeeded + pollUntilSeedsReady tests.
|
|
5
7
|
*/
|
|
6
8
|
import { beforeEach, afterEach, describe, expect, it, vi } from 'vitest';
|
|
7
9
|
import { join } from 'path';
|
|
10
|
+
// Import the mocked fs functions so we can use vi.mocked() to change their implementations per-test.
|
|
11
|
+
// vi.mock('fs', ...) below hoists this mock, so these imports resolve to the mocked versions.
|
|
12
|
+
import { readdirSync as readdirSyncMock } from 'fs';
|
|
8
13
|
// vi.mock calls are hoisted — use vi.hoisted() for constants referenced inside factories.
|
|
9
|
-
const { vfs, MOCK_CWD, MOCK_HOME } = vi.hoisted(() => ({
|
|
14
|
+
const { vfs, vfsMtimes, MOCK_CWD, MOCK_HOME } = vi.hoisted(() => ({
|
|
10
15
|
vfs: {},
|
|
16
|
+
// WP-379 S5b: mtime map used by statSync mock for case-collision ordering tests.
|
|
17
|
+
vfsMtimes: {},
|
|
11
18
|
MOCK_CWD: '/tmp/pb-test-cwd',
|
|
12
19
|
MOCK_HOME: '/tmp/pb-test-home',
|
|
13
20
|
}));
|
|
@@ -16,24 +23,45 @@ vi.mock('fs', () => ({
|
|
|
16
23
|
writeFileSync: vi.fn((path, content) => {
|
|
17
24
|
vfs[path] = content;
|
|
18
25
|
}),
|
|
26
|
+
appendFileSync: vi.fn((path, content) => {
|
|
27
|
+
vfs[path] = (vfs[path] ?? '') + content;
|
|
28
|
+
}),
|
|
19
29
|
existsSync: vi.fn((path) => path in vfs),
|
|
20
30
|
readFileSync: vi.fn((path, _enc) => {
|
|
21
31
|
if (path in vfs)
|
|
22
32
|
return vfs[path];
|
|
23
33
|
throw Object.assign(new Error(`ENOENT: no such file '${path}'`), { code: 'ENOENT' });
|
|
24
34
|
}),
|
|
35
|
+
readdirSync: vi.fn((_dir) => []),
|
|
36
|
+
copyFileSync: vi.fn(),
|
|
37
|
+
// WP-379 S5b: unlinkSync + statSync for orphan unlink + case-collision resolution.
|
|
38
|
+
unlinkSync: vi.fn((path) => {
|
|
39
|
+
delete vfs[path];
|
|
40
|
+
}),
|
|
41
|
+
statSync: vi.fn((path) => {
|
|
42
|
+
if (path in vfs) {
|
|
43
|
+
// Return a fake stat with an incrementing mtime based on path hash (deterministic).
|
|
44
|
+
// Tests that need specific mtime ordering should set vfs[path] before calling.
|
|
45
|
+
const mtimeMs = vfsMtimes[path] ?? 1000;
|
|
46
|
+
return { mtimeMs };
|
|
47
|
+
}
|
|
48
|
+
throw Object.assign(new Error(`ENOENT: stat '${path}'`), { code: 'ENOENT' });
|
|
49
|
+
}),
|
|
25
50
|
}));
|
|
26
51
|
vi.mock('os', () => ({
|
|
27
52
|
homedir: vi.fn(() => MOCK_HOME),
|
|
28
53
|
}));
|
|
29
|
-
//
|
|
30
|
-
vi.mock('
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
54
|
+
// prompts mock: select returns 'work' (second option)
|
|
55
|
+
vi.mock('../lib/prompts.js', () => ({
|
|
56
|
+
select: () => Promise.resolve('work'),
|
|
57
|
+
confirm: () => Promise.resolve(false),
|
|
58
|
+
ask: () => Promise.resolve(''),
|
|
59
|
+
password: () => Promise.resolve(''),
|
|
60
|
+
isInteractive: () => true,
|
|
35
61
|
}));
|
|
36
|
-
import { runHandshakeInit } from '../commands/handshake.js';
|
|
62
|
+
import { runHandshakeInit, normalizeHandshakeContentForComparison, DORMANT_MARKER, writeDormantMarkerToFile, resolveProjectionCollision, classifyDriftBucket, deriveHandshakeStartupSignals, dereferencePrRefToPaths } from '../commands/handshake.js';
|
|
63
|
+
import { MARKER } from '../generators/adapters.js';
|
|
64
|
+
import { createHash } from 'crypto';
|
|
37
65
|
const TEAM_PATH = join(MOCK_CWD, '.claude', 'settings.json');
|
|
38
66
|
const PERSONAL_PATH = join(MOCK_HOME, '.claude', 'settings.json');
|
|
39
67
|
describe('runHandshakeInit', () => {
|
|
@@ -165,23 +193,789 @@ describe('runHandshakeInit', () => {
|
|
|
165
193
|
});
|
|
166
194
|
});
|
|
167
195
|
describe('--level flag validation', () => {
|
|
168
|
-
it('
|
|
169
|
-
|
|
170
|
-
throw new Error('process.exit called');
|
|
171
|
-
});
|
|
172
|
-
await expect(runHandshakeInit({ level: 'invalid-level', dryRun: false })).rejects.toThrow('process.exit called');
|
|
173
|
-
expect(exitSpy).toHaveBeenCalledWith(1);
|
|
174
|
-
exitSpy.mockRestore();
|
|
196
|
+
it('throws CLIError for unknown level', async () => {
|
|
197
|
+
await expect(runHandshakeInit({ level: 'invalid-level', dryRun: false })).rejects.toThrow('Unknown level');
|
|
175
198
|
});
|
|
176
199
|
it('does not write files when level is invalid', async () => {
|
|
177
|
-
const exitSpy = vi.spyOn(process, 'exit').mockImplementation(() => {
|
|
178
|
-
throw new Error('process.exit called');
|
|
179
|
-
});
|
|
180
200
|
await expect(runHandshakeInit({ level: 'GUIDE', dryRun: false })).rejects.toThrow();
|
|
181
201
|
expect(vfs[TEAM_PATH]).toBeUndefined();
|
|
182
202
|
expect(vfs[PERSONAL_PATH]).toBeUndefined();
|
|
183
|
-
exitSpy.mockRestore();
|
|
184
203
|
});
|
|
185
204
|
});
|
|
186
205
|
});
|
|
206
|
+
describe('normalizeHandshakeContentForComparison', () => {
|
|
207
|
+
it('treats handshake timestamp comment as non-semantic', () => {
|
|
208
|
+
const a = '<!-- auto-generated by pb handshake — 2026-04-02T10:00:00.000Z -->\nbody\n';
|
|
209
|
+
const b = '<!-- auto-generated by pb handshake — 2026-04-02T11:00:00.000Z -->\nbody\n';
|
|
210
|
+
expect(normalizeHandshakeContentForComparison(a)).toBe(normalizeHandshakeContentForComparison(b));
|
|
211
|
+
});
|
|
212
|
+
it('treats generated metadata line as non-semantic', () => {
|
|
213
|
+
const a = '_Generated: 2026-04-02T10:00:00.000Z_\ncontent\n';
|
|
214
|
+
const b = '_Generated: 2026-04-02T11:00:00.000Z_\ncontent\n';
|
|
215
|
+
expect(normalizeHandshakeContentForComparison(a)).toBe(normalizeHandshakeContentForComparison(b));
|
|
216
|
+
});
|
|
217
|
+
it('preserves meaningful content differences', () => {
|
|
218
|
+
const a = '<!-- auto-generated by pb handshake — 2026-04-02T10:00:00.000Z -->\nalpha\n';
|
|
219
|
+
const b = '<!-- auto-generated by pb handshake — 2026-04-02T11:00:00.000Z -->\nbeta\n';
|
|
220
|
+
expect(normalizeHandshakeContentForComparison(a)).not.toBe(normalizeHandshakeContentForComparison(b));
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
// ── WP-379 S3b: probeStarterSetupSeeded + pollUntilSeedsReady ─────────────────
|
|
224
|
+
//
|
|
225
|
+
// These tests use vi.doMock (not vi.mock) so they can inject different
|
|
226
|
+
// kernelCall implementations per test without affecting the --init tests above.
|
|
227
|
+
// Each test creates its own isolated module scope via vi.resetModules().
|
|
228
|
+
describe('probeStarterSetupSeeded (WP-379 S3b)', () => {
|
|
229
|
+
beforeEach(() => {
|
|
230
|
+
vi.resetModules();
|
|
231
|
+
});
|
|
232
|
+
afterEach(() => {
|
|
233
|
+
vi.restoreAllMocks();
|
|
234
|
+
});
|
|
235
|
+
it('returns seeds-ready when health.starterSetupSeeded is true', async () => {
|
|
236
|
+
vi.doMock('../lib/client.js', () => ({
|
|
237
|
+
kernelCall: vi.fn().mockResolvedValue({
|
|
238
|
+
starterSetupSeeded: true,
|
|
239
|
+
gaps: [],
|
|
240
|
+
status: 'healthy',
|
|
241
|
+
}),
|
|
242
|
+
}));
|
|
243
|
+
const { probeStarterSetupSeeded } = await import('../commands/handshake.js');
|
|
244
|
+
const result = await probeStarterSetupSeeded();
|
|
245
|
+
expect(result.status).toBe('seeds-ready');
|
|
246
|
+
});
|
|
247
|
+
it('returns seeds-pending with starter-setup-missing gap when starterSetupSeeded is false', async () => {
|
|
248
|
+
vi.doMock('../lib/client.js', () => ({
|
|
249
|
+
kernelCall: vi.fn().mockResolvedValue({
|
|
250
|
+
starterSetupSeeded: false,
|
|
251
|
+
gaps: [
|
|
252
|
+
{
|
|
253
|
+
kind: 'starter-setup-missing',
|
|
254
|
+
severity: 'error',
|
|
255
|
+
message: 'Starter setup seeds are still running.',
|
|
256
|
+
},
|
|
257
|
+
],
|
|
258
|
+
status: 'incomplete',
|
|
259
|
+
}),
|
|
260
|
+
}));
|
|
261
|
+
const { probeStarterSetupSeeded } = await import('../commands/handshake.js');
|
|
262
|
+
const result = await probeStarterSetupSeeded();
|
|
263
|
+
expect(result.status).toBe('seeds-pending');
|
|
264
|
+
if (result.status === 'seeds-pending') {
|
|
265
|
+
expect(result.gaps.length).toBeGreaterThan(0);
|
|
266
|
+
expect(result.gaps[0]?.kind).toBe('starter-setup-missing');
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
it('returns probe-failed when kernelCall throws', async () => {
|
|
270
|
+
vi.doMock('../lib/client.js', () => ({
|
|
271
|
+
kernelCall: vi.fn().mockRejectedValue(new Error('Network unreachable')),
|
|
272
|
+
}));
|
|
273
|
+
const { probeStarterSetupSeeded } = await import('../commands/handshake.js');
|
|
274
|
+
const result = await probeStarterSetupSeeded();
|
|
275
|
+
expect(result.status).toBe('probe-failed');
|
|
276
|
+
if (result.status === 'probe-failed') {
|
|
277
|
+
expect(result.error).toContain('Network unreachable');
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
it('synthesizes a default starter-setup-missing gap when health.gaps is empty but starterSetupSeeded is false', async () => {
|
|
281
|
+
vi.doMock('../lib/client.js', () => ({
|
|
282
|
+
kernelCall: vi.fn().mockResolvedValue({
|
|
283
|
+
starterSetupSeeded: false,
|
|
284
|
+
gaps: [], // no gap details from server
|
|
285
|
+
status: 'incomplete',
|
|
286
|
+
}),
|
|
287
|
+
}));
|
|
288
|
+
const { probeStarterSetupSeeded } = await import('../commands/handshake.js');
|
|
289
|
+
const result = await probeStarterSetupSeeded();
|
|
290
|
+
expect(result.status).toBe('seeds-pending');
|
|
291
|
+
if (result.status === 'seeds-pending') {
|
|
292
|
+
expect(result.gaps.length).toBe(1);
|
|
293
|
+
expect(result.gaps[0]?.kind).toBe('starter-setup-missing');
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
});
|
|
297
|
+
describe('pollUntilSeedsReady (WP-379 S3b)', () => {
|
|
298
|
+
beforeEach(() => {
|
|
299
|
+
vi.resetModules();
|
|
300
|
+
vi.useFakeTimers();
|
|
301
|
+
});
|
|
302
|
+
afterEach(() => {
|
|
303
|
+
vi.restoreAllMocks();
|
|
304
|
+
vi.useRealTimers();
|
|
305
|
+
});
|
|
306
|
+
it('returns seeds-ready immediately when first probe succeeds', async () => {
|
|
307
|
+
vi.doMock('../lib/client.js', () => ({
|
|
308
|
+
kernelCall: vi.fn().mockResolvedValue({
|
|
309
|
+
starterSetupSeeded: true,
|
|
310
|
+
gaps: [],
|
|
311
|
+
status: 'healthy',
|
|
312
|
+
}),
|
|
313
|
+
}));
|
|
314
|
+
const { pollUntilSeedsReady } = await import('../commands/handshake.js');
|
|
315
|
+
const resultPromise = pollUntilSeedsReady();
|
|
316
|
+
// Advance timers past any initial delays
|
|
317
|
+
await vi.runAllTimersAsync();
|
|
318
|
+
const result = await resultPromise;
|
|
319
|
+
expect(result.status).toBe('seeds-ready');
|
|
320
|
+
});
|
|
321
|
+
it('returns seeds-pending after MAX_POLLS when seeds never become ready', async () => {
|
|
322
|
+
// kernelCall always returns starterSetupSeeded: false
|
|
323
|
+
vi.doMock('../lib/client.js', () => ({
|
|
324
|
+
kernelCall: vi.fn().mockResolvedValue({
|
|
325
|
+
starterSetupSeeded: false,
|
|
326
|
+
gaps: [
|
|
327
|
+
{
|
|
328
|
+
kind: 'starter-setup-missing',
|
|
329
|
+
severity: 'error',
|
|
330
|
+
message: 'Starter setup seeds are still running.',
|
|
331
|
+
},
|
|
332
|
+
],
|
|
333
|
+
status: 'incomplete',
|
|
334
|
+
}),
|
|
335
|
+
}));
|
|
336
|
+
const { pollUntilSeedsReady } = await import('../commands/handshake.js');
|
|
337
|
+
const resultPromise = pollUntilSeedsReady();
|
|
338
|
+
await vi.runAllTimersAsync();
|
|
339
|
+
const result = await resultPromise;
|
|
340
|
+
expect(result.status).toBe('seeds-pending');
|
|
341
|
+
if (result.status === 'seeds-pending') {
|
|
342
|
+
expect(result.gaps[0]?.kind).toBe('starter-setup-missing');
|
|
343
|
+
}
|
|
344
|
+
});
|
|
345
|
+
it('stops polling immediately on probe-failed (no retry on network error)', async () => {
|
|
346
|
+
const kernelCallMock = vi.fn().mockRejectedValue(new Error('auth failed'));
|
|
347
|
+
vi.doMock('../lib/client.js', () => ({
|
|
348
|
+
kernelCall: kernelCallMock,
|
|
349
|
+
}));
|
|
350
|
+
const { pollUntilSeedsReady } = await import('../commands/handshake.js');
|
|
351
|
+
const resultPromise = pollUntilSeedsReady();
|
|
352
|
+
await vi.runAllTimersAsync();
|
|
353
|
+
const result = await resultPromise;
|
|
354
|
+
expect(result.status).toBe('probe-failed');
|
|
355
|
+
// Should have called exactly once — no retry on failure
|
|
356
|
+
expect(kernelCallMock).toHaveBeenCalledTimes(1);
|
|
357
|
+
});
|
|
358
|
+
});
|
|
359
|
+
// ── WP-379 S4: DORMANT_MARKER constant + writeDormantMarkerToFile ─────────────
|
|
360
|
+
describe('DORMANT_MARKER (WP-379 S4)', () => {
|
|
361
|
+
it('is the expected HTML comment string', () => {
|
|
362
|
+
expect(DORMANT_MARKER).toBe('<!-- pb-status: dormant -->');
|
|
363
|
+
});
|
|
364
|
+
it('does not contain newlines (clean single-line marker)', () => {
|
|
365
|
+
expect(DORMANT_MARKER).not.toContain('\n');
|
|
366
|
+
});
|
|
367
|
+
});
|
|
368
|
+
describe('writeDormantMarkerToFile (WP-379 S4)', () => {
|
|
369
|
+
// Use the hoisted vfs + mocked fs from the top of this file.
|
|
370
|
+
// vfs is already set up by vi.hoisted() and vi.mock('fs', ...) above.
|
|
371
|
+
beforeEach(() => {
|
|
372
|
+
Object.keys(vfs).forEach((k) => delete vfs[k]);
|
|
373
|
+
vi.clearAllMocks();
|
|
374
|
+
});
|
|
375
|
+
const AUTO_GEN_FILE = join(MOCK_CWD, '.claude', 'rules', 'test-rule.md');
|
|
376
|
+
it('returns "skipped" when the file does not exist', () => {
|
|
377
|
+
// File is not in vfs
|
|
378
|
+
const result = writeDormantMarkerToFile(AUTO_GEN_FILE);
|
|
379
|
+
expect(result).toBe('skipped');
|
|
380
|
+
});
|
|
381
|
+
it('returns "skipped" when the file exists but has no auto-gen MARKER', () => {
|
|
382
|
+
vfs[AUTO_GEN_FILE] = '# Manual rule\nSome content.\n';
|
|
383
|
+
const result = writeDormantMarkerToFile(AUTO_GEN_FILE);
|
|
384
|
+
expect(result).toBe('skipped');
|
|
385
|
+
// File must be unchanged (no append)
|
|
386
|
+
expect(vfs[AUTO_GEN_FILE]).toBe('# Manual rule\nSome content.\n');
|
|
387
|
+
});
|
|
388
|
+
it('appends DORMANT_MARKER and returns "written" for an auto-gen file without the marker', () => {
|
|
389
|
+
// Simulate a previously-projected file: has the auto-gen MARKER, no dormant marker yet.
|
|
390
|
+
vfs[AUTO_GEN_FILE] = `${MARKER}\n# Test Rule\nContent.\n`;
|
|
391
|
+
const result = writeDormantMarkerToFile(AUTO_GEN_FILE);
|
|
392
|
+
expect(result).toBe('written');
|
|
393
|
+
expect(vfs[AUTO_GEN_FILE]).toContain(DORMANT_MARKER);
|
|
394
|
+
// Original content preserved — marker is appended, not a replacement.
|
|
395
|
+
expect(vfs[AUTO_GEN_FILE]).toContain('# Test Rule');
|
|
396
|
+
expect(vfs[AUTO_GEN_FILE]).toContain(MARKER);
|
|
397
|
+
});
|
|
398
|
+
it('returns "already-dormant" when DORMANT_MARKER is already present (idempotent)', () => {
|
|
399
|
+
// File already has the dormant marker from a previous handshake.
|
|
400
|
+
vfs[AUTO_GEN_FILE] = `${MARKER}\n# Test Rule\nContent.\n\n${DORMANT_MARKER}\n`;
|
|
401
|
+
const result = writeDormantMarkerToFile(AUTO_GEN_FILE);
|
|
402
|
+
expect(result).toBe('already-dormant');
|
|
403
|
+
// File must be unchanged — no second append.
|
|
404
|
+
const occurrences = (vfs[AUTO_GEN_FILE].match(new RegExp(DORMANT_MARKER.replace(/[<>!-]/g, '\\$&'), 'g')) ?? []).length;
|
|
405
|
+
expect(occurrences).toBe(1);
|
|
406
|
+
});
|
|
407
|
+
it('second call on a dormant-marked file produces no duplicate markers (no drift TEN semantics)', () => {
|
|
408
|
+
// Simulate: first handshake wrote the dormant marker, second handshake is called again.
|
|
409
|
+
vfs[AUTO_GEN_FILE] = `${MARKER}\n# Test Rule\n\n${DORMANT_MARKER}\n`;
|
|
410
|
+
writeDormantMarkerToFile(AUTO_GEN_FILE); // first call — already-dormant
|
|
411
|
+
writeDormantMarkerToFile(AUTO_GEN_FILE); // second call — still already-dormant
|
|
412
|
+
const occurrences = (vfs[AUTO_GEN_FILE].match(new RegExp(DORMANT_MARKER.replace(/[<>!-]/g, '\\$&'), 'g')) ?? []).length;
|
|
413
|
+
expect(occurrences).toBe(1);
|
|
414
|
+
});
|
|
415
|
+
});
|
|
416
|
+
// ── WP-379 S5b: resolveProjectionCollision ─────────────────────────────────────
|
|
417
|
+
//
|
|
418
|
+
// Tests for the marker-scoped orphan unlink + case-collision resolution.
|
|
419
|
+
// All file system operations go through the vfs mock defined at the top of this file.
|
|
420
|
+
describe('resolveProjectionCollision (WP-379 S5b)', () => {
|
|
421
|
+
const noop = () => { };
|
|
422
|
+
beforeEach(() => {
|
|
423
|
+
// Clear vfs and mtimes before each test.
|
|
424
|
+
Object.keys(vfs).forEach((k) => delete vfs[k]);
|
|
425
|
+
Object.keys(vfsMtimes).forEach((k) => delete vfsMtimes[k]);
|
|
426
|
+
vi.clearAllMocks();
|
|
427
|
+
});
|
|
428
|
+
// Helper: write a file to vfs with the auto-gen MARKER.
|
|
429
|
+
// Also marks the parent directory as existing in vfs so existsSync(dir) returns true.
|
|
430
|
+
function writeMarkedFile(path, extra = '') {
|
|
431
|
+
const dir = path.substring(0, path.lastIndexOf('/'));
|
|
432
|
+
vfs[dir] = ''; // ensure existsSync(dir) returns true
|
|
433
|
+
vfs[path] = `${MARKER}\n# Rule\n${extra}`;
|
|
434
|
+
}
|
|
435
|
+
// Helper: write a file without auto-gen MARKER (user-forked).
|
|
436
|
+
// Also marks the parent directory as existing in vfs so existsSync(dir) returns true.
|
|
437
|
+
function writeUserFile(path) {
|
|
438
|
+
const dir = path.substring(0, path.lastIndexOf('/'));
|
|
439
|
+
vfs[dir] = ''; // ensure existsSync(dir) returns true
|
|
440
|
+
vfs[path] = '# My user rule — no marker here\n';
|
|
441
|
+
}
|
|
442
|
+
// ── Test 1: Linux case-collision — exact match wins ────────────────────────
|
|
443
|
+
it('case-collision: exact-match file survives, case-variant with marker is unlinked', () => {
|
|
444
|
+
const dir = `${MOCK_CWD}/.cursor/rules`;
|
|
445
|
+
const exact = `${dir}/setup-productbrain.mdc`; // lowercase = normalized stem
|
|
446
|
+
const variant = `${dir}/Setup-ProductBrain.mdc`; // case-variant
|
|
447
|
+
// Both have the auto-gen MARKER.
|
|
448
|
+
writeMarkedFile(exact);
|
|
449
|
+
writeMarkedFile(variant);
|
|
450
|
+
// Simulate readdirSync returning both files for the .cursor/rules dir.
|
|
451
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
452
|
+
readdirSyncMock.mockImplementation((d) => {
|
|
453
|
+
if (d === dir)
|
|
454
|
+
return ['setup-productbrain.mdc', 'Setup-ProductBrain.mdc'];
|
|
455
|
+
return [];
|
|
456
|
+
});
|
|
457
|
+
// Both are known canonical (same normalized stem).
|
|
458
|
+
const assetNames = ['setup-productbrain'];
|
|
459
|
+
const { results, collisionTens } = resolveProjectionCollision(MOCK_CWD, assetNames, noop, noop);
|
|
460
|
+
// Exact match survives.
|
|
461
|
+
expect(exact in vfs).toBe(true);
|
|
462
|
+
// Case-variant is unlinked.
|
|
463
|
+
expect(variant in vfs).toBe(false);
|
|
464
|
+
// Exact match appears as 'kept'.
|
|
465
|
+
expect(results.some((r) => r.filePath === exact && r.action === 'kept')).toBe(true);
|
|
466
|
+
// Variant appears as 'unlinked'.
|
|
467
|
+
expect(results.some((r) => r.filePath === variant && r.action === 'unlinked')).toBe(true);
|
|
468
|
+
// No collision TEN — exact match was found.
|
|
469
|
+
expect(collisionTens).toHaveLength(0);
|
|
470
|
+
});
|
|
471
|
+
// ── Test 2: ambiguous case (no exact match, two case-variants) ────────────
|
|
472
|
+
it('ambiguous case: zero exact match, two case-variants → newest mtime wins + TEN captured', () => {
|
|
473
|
+
const dir = `${MOCK_CWD}/.cursor/rules`;
|
|
474
|
+
const variant1 = `${dir}/Setup-ProductBrain.mdc`; // older
|
|
475
|
+
const variant2 = `${dir}/SETUP-PRODUCTBRAIN.mdc`; // newer
|
|
476
|
+
writeMarkedFile(variant1);
|
|
477
|
+
writeMarkedFile(variant2);
|
|
478
|
+
// Set mtimes: variant2 is newer (higher ms).
|
|
479
|
+
vfsMtimes[variant1] = 1000;
|
|
480
|
+
vfsMtimes[variant2] = 9000; // newer
|
|
481
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
482
|
+
readdirSyncMock.mockImplementation((d) => {
|
|
483
|
+
if (d === dir)
|
|
484
|
+
return ['Setup-ProductBrain.mdc', 'SETUP-PRODUCTBRAIN.mdc'];
|
|
485
|
+
return [];
|
|
486
|
+
});
|
|
487
|
+
// The canonical name is lowercase "setup-productbrain" — neither variant is an exact stem match.
|
|
488
|
+
const assetNames = ['setup-productbrain'];
|
|
489
|
+
const { results, collisionTens } = resolveProjectionCollision(MOCK_CWD, assetNames, noop, noop);
|
|
490
|
+
// variant2 (newer mtime=9000) must survive; variant1 (older mtime=1000) must be unlinked.
|
|
491
|
+
expect(variant2 in vfs).toBe(true);
|
|
492
|
+
expect(variant1 in vfs).toBe(false);
|
|
493
|
+
// A collision TEN must be captured.
|
|
494
|
+
expect(collisionTens).toHaveLength(1);
|
|
495
|
+
expect(collisionTens[0]).toContain('setup-productbrain.mdc');
|
|
496
|
+
// result for winner should be 'collision-ten', loser 'unlinked'.
|
|
497
|
+
expect(results.some((r) => r.filePath === variant2 && r.action === 'collision-ten')).toBe(true);
|
|
498
|
+
expect(results.some((r) => r.filePath === variant1 && r.action === 'unlinked')).toBe(true);
|
|
499
|
+
});
|
|
500
|
+
// ── Test 3: existing user file (no marker) → never unlinked, zero drift TENs ──
|
|
501
|
+
// Note: resolveProjectionCollision does NOT fire drift TENs — user-owned files
|
|
502
|
+
// (no MARKER) are left untouched by the main write loop in runHandshake (TEN-2150).
|
|
503
|
+
// This test confirms that user-owned files are NEVER unlinked by
|
|
504
|
+
// resolveProjectionCollision regardless of name.
|
|
505
|
+
it('first-run: user file (no marker) in target dir is preserved (never unlinked)', () => {
|
|
506
|
+
const dir = `${MOCK_CWD}/.cursor/rules`;
|
|
507
|
+
const userFile = `${dir}/foo.mdc`;
|
|
508
|
+
writeUserFile(userFile); // NO auto-gen MARKER
|
|
509
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
510
|
+
readdirSyncMock.mockImplementation((d) => {
|
|
511
|
+
if (d === dir)
|
|
512
|
+
return ['foo.mdc'];
|
|
513
|
+
return [];
|
|
514
|
+
});
|
|
515
|
+
// 'foo' is NOT a canonical asset name — it would be an orphan if it had a marker.
|
|
516
|
+
const assetNames = [];
|
|
517
|
+
const { results } = resolveProjectionCollision(MOCK_CWD, assetNames, noop, noop);
|
|
518
|
+
// User file untouched.
|
|
519
|
+
expect(userFile in vfs).toBe(true);
|
|
520
|
+
// No unlink results.
|
|
521
|
+
expect(results.filter((r) => r.action === 'unlinked')).toHaveLength(0);
|
|
522
|
+
});
|
|
523
|
+
// ── Test 4: orphan auto-gen file is unlinked ──────────────────────────────
|
|
524
|
+
it('auto-gen file whose name is not in the active asset list is unlinked (orphan)', () => {
|
|
525
|
+
const dir = `${MOCK_CWD}/.cursor/rules`;
|
|
526
|
+
const orphan = `${dir}/old-orphaned-rule.mdc`;
|
|
527
|
+
writeMarkedFile(orphan);
|
|
528
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
529
|
+
readdirSyncMock.mockImplementation((d) => {
|
|
530
|
+
if (d === dir)
|
|
531
|
+
return ['old-orphaned-rule.mdc'];
|
|
532
|
+
return [];
|
|
533
|
+
});
|
|
534
|
+
// Active assets do NOT include "old-orphaned-rule".
|
|
535
|
+
const assetNames = ['some-other-rule'];
|
|
536
|
+
const { results } = resolveProjectionCollision(MOCK_CWD, assetNames, noop, noop);
|
|
537
|
+
expect(orphan in vfs).toBe(false);
|
|
538
|
+
expect(results.some((r) => r.filePath === orphan && r.action === 'unlinked')).toBe(true);
|
|
539
|
+
});
|
|
540
|
+
// ── Test 5: user file in target dir does NOT get a drift TEN from resolveProjectionCollision ──
|
|
541
|
+
// (Confirms that drift TEN suppression on first run is independent — tests Test 3 from another angle.)
|
|
542
|
+
it('returns zero collisionTens when all user files are preserved (no marker)', () => {
|
|
543
|
+
const dir = `${MOCK_CWD}/.claude/rules`;
|
|
544
|
+
const userFile = `${dir}/bar.md`;
|
|
545
|
+
writeUserFile(userFile);
|
|
546
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
547
|
+
readdirSyncMock.mockImplementation((d) => {
|
|
548
|
+
if (d === dir)
|
|
549
|
+
return ['bar.md'];
|
|
550
|
+
return [];
|
|
551
|
+
});
|
|
552
|
+
const { collisionTens } = resolveProjectionCollision(MOCK_CWD, [], noop, noop);
|
|
553
|
+
expect(collisionTens).toHaveLength(0);
|
|
554
|
+
});
|
|
555
|
+
});
|
|
556
|
+
// ── WP-421 S3: classifyDriftBucket — three-bucket drift report (doneWhen #17) ──
|
|
557
|
+
//
|
|
558
|
+
// PB-managed-clean — auto-gen MARKER + hash trailer matches body.
|
|
559
|
+
// PB-managed-tampered — auto-gen MARKER + hash trailer MISMATCHES body.
|
|
560
|
+
// user-owned — no auto-gen MARKER. Untouched by PB.
|
|
561
|
+
//
|
|
562
|
+
// Helper builds a body identical to what handshake projection produces:
|
|
563
|
+
// <MARKER>
|
|
564
|
+
// <body>
|
|
565
|
+
// <!-- pb-hash: sha256:<hex> -->
|
|
566
|
+
// Hash is sha256 over the LF-normalized, trimmed (trailers + timestamp stripped)
|
|
567
|
+
// body — same algorithm as runHandshake's HASH_TRAILER_REGEX path.
|
|
568
|
+
describe('classifyDriftBucket (WP-421 S3, doneWhen #17)', () => {
|
|
569
|
+
const FILE = join(MOCK_CWD, '.cursor', 'rules', 'sample.mdc');
|
|
570
|
+
beforeEach(() => {
|
|
571
|
+
Object.keys(vfs).forEach((k) => delete vfs[k]);
|
|
572
|
+
vi.clearAllMocks();
|
|
573
|
+
});
|
|
574
|
+
/**
|
|
575
|
+
* Build a "PB-managed projection" body with a self-consistent hash trailer.
|
|
576
|
+
* The hash is computed exactly as handshake's projection path does so the
|
|
577
|
+
* round-trip through classifyDriftBucket lands in 'pb-managed-clean'.
|
|
578
|
+
*/
|
|
579
|
+
function buildCleanProjection(body) {
|
|
580
|
+
const HASH_TRAILER_REGEX = /^<!--\s*pb-hash:.*-->\s*$/gm;
|
|
581
|
+
const TIMESTAMP_REGEX = /^<!--\s*pb-generated-at:.*-->\s*$/gm;
|
|
582
|
+
const head = `${MARKER}\n${body}`;
|
|
583
|
+
const normalized = head
|
|
584
|
+
.replace(HASH_TRAILER_REGEX, '')
|
|
585
|
+
.replace(TIMESTAMP_REGEX, '')
|
|
586
|
+
.replace(/\r\n/g, '\n')
|
|
587
|
+
.replace(/\r/g, '\n')
|
|
588
|
+
.trimEnd();
|
|
589
|
+
const hash = createHash('sha256').update(normalized, 'utf8').digest('hex');
|
|
590
|
+
return `${normalized}\n<!-- pb-hash: sha256:${hash} -->`;
|
|
591
|
+
}
|
|
592
|
+
it('returns null when the file does not exist (first-run / unprojected)', () => {
|
|
593
|
+
expect(classifyDriftBucket(FILE)).toBeNull();
|
|
594
|
+
});
|
|
595
|
+
it('classifies a self-consistent PB-managed projection as pb-managed-clean', () => {
|
|
596
|
+
vfs[FILE] = buildCleanProjection('# Sample rule\n\nLorem ipsum.\n');
|
|
597
|
+
const result = classifyDriftBucket(FILE);
|
|
598
|
+
expect(result).not.toBeNull();
|
|
599
|
+
expect(result.bucket).toBe('pb-managed-clean');
|
|
600
|
+
});
|
|
601
|
+
it('classifies a marker file with a mismatching hash trailer as pb-managed-tampered', () => {
|
|
602
|
+
// Take a clean projection and edit the body AFTER the trailer was written —
|
|
603
|
+
// simulates a user who opened .cursor/rules/sample.mdc and added a sentence
|
|
604
|
+
// without re-running pb handshake.
|
|
605
|
+
const clean = buildCleanProjection('# Sample rule\n\nLorem ipsum.\n');
|
|
606
|
+
// Splice a user edit between the body and the trailer, leaving the trailer intact.
|
|
607
|
+
const tampered = clean.replace('Lorem ipsum.', 'Lorem ipsum.\n\nMy custom edit — never run through handshake again.');
|
|
608
|
+
vfs[FILE] = tampered;
|
|
609
|
+
const result = classifyDriftBucket(FILE);
|
|
610
|
+
expect(result).not.toBeNull();
|
|
611
|
+
expect(result.bucket).toBe('pb-managed-tampered');
|
|
612
|
+
// Both expected and actual hashes are populated for the headless refusal payload.
|
|
613
|
+
expect(result.expectedHash).toMatch(/^sha256:[0-9a-f]{64}$/);
|
|
614
|
+
expect(result.actualHash).toMatch(/^sha256:[0-9a-f]{64}$/);
|
|
615
|
+
expect(result.expectedHash).not.toBe(result.actualHash);
|
|
616
|
+
});
|
|
617
|
+
it('classifies a file with NO auto-gen MARKER as user-owned', () => {
|
|
618
|
+
vfs[FILE] = '# My personal rule — I authored this myself, no marker.\n';
|
|
619
|
+
const result = classifyDriftBucket(FILE);
|
|
620
|
+
expect(result).not.toBeNull();
|
|
621
|
+
expect(result.bucket).toBe('user-owned');
|
|
622
|
+
expect(result.expectedHash).toBe('');
|
|
623
|
+
expect(result.actualHash).toBe('');
|
|
624
|
+
});
|
|
625
|
+
it('classifies a marker file WITHOUT a hash trailer as pb-managed-clean (legacy / pre-S0c)', () => {
|
|
626
|
+
// Pre-WP-345-S0c projections did not embed a pb-hash trailer. Treat as clean
|
|
627
|
+
// so the legacy first-run UX (forked vs clean) keeps working.
|
|
628
|
+
vfs[FILE] = `${MARKER}\n# Legacy rule\n\nNo trailer here.\n`;
|
|
629
|
+
const result = classifyDriftBucket(FILE);
|
|
630
|
+
expect(result).not.toBeNull();
|
|
631
|
+
expect(result.bucket).toBe('pb-managed-clean');
|
|
632
|
+
});
|
|
633
|
+
it('three-bucket fixture: one file per bucket + a missing-file → null', () => {
|
|
634
|
+
const cleanPath = join(MOCK_CWD, '.cursor', 'rules', 'a.mdc');
|
|
635
|
+
const tamperedPath = join(MOCK_CWD, '.cursor', 'rules', 'b.mdc');
|
|
636
|
+
const userOwnedPath = join(MOCK_CWD, '.cursor', 'rules', 'c.mdc');
|
|
637
|
+
const missingPath = join(MOCK_CWD, '.cursor', 'rules', 'd.mdc');
|
|
638
|
+
const cleanBody = buildCleanProjection('# Clean rule\nbody.\n');
|
|
639
|
+
vfs[cleanPath] = cleanBody;
|
|
640
|
+
vfs[tamperedPath] = cleanBody.replace('body.', 'body.\n\nedited.');
|
|
641
|
+
vfs[userOwnedPath] = '# user-owned rule\nno marker.\n';
|
|
642
|
+
// missingPath is intentionally NOT in vfs.
|
|
643
|
+
expect(classifyDriftBucket(cleanPath)?.bucket).toBe('pb-managed-clean');
|
|
644
|
+
expect(classifyDriftBucket(tamperedPath)?.bucket).toBe('pb-managed-tampered');
|
|
645
|
+
expect(classifyDriftBucket(userOwnedPath)?.bucket).toBe('user-owned');
|
|
646
|
+
expect(classifyDriftBucket(missingPath)).toBeNull();
|
|
647
|
+
});
|
|
648
|
+
});
|
|
649
|
+
// ── WP-421 S3: headless refusal — runHandshake non-TTY path (doneWhen #17) ────
|
|
650
|
+
//
|
|
651
|
+
// When `noPrompt: true` is passed (or `process.stdout.isTTY === false`) and one
|
|
652
|
+
// or more PB-managed projection files are tampered, the handshake MUST:
|
|
653
|
+
// 1. Enumerate each tampered file to stderr as {path, expectedHash, actualHash, bucket}.
|
|
654
|
+
// 2. Call setup.recordTamperRefusal with a kind='transition' shape:
|
|
655
|
+
// - mode: current manifest mode
|
|
656
|
+
// - refusedTamperedFiles: [{path, expectedHash, actualHash}, ...]
|
|
657
|
+
// 3. Exit with a non-zero code (process.exit(1)).
|
|
658
|
+
//
|
|
659
|
+
// The full runHandshake exercise requires mocking the AKI gateway + manifest
|
|
660
|
+
// + DB asset list; we keep these tests narrowly scoped on classification +
|
|
661
|
+
// the mutation call shape so the contract (#17) stays asserted without a
|
|
662
|
+
// gateway round-trip.
|
|
663
|
+
describe('headless refusal — recordTamperRefusal call shape (WP-421 S3, doneWhen #17)', () => {
|
|
664
|
+
beforeEach(() => {
|
|
665
|
+
vi.resetModules();
|
|
666
|
+
Object.keys(vfs).forEach((k) => delete vfs[k]);
|
|
667
|
+
vi.clearAllMocks();
|
|
668
|
+
});
|
|
669
|
+
afterEach(() => {
|
|
670
|
+
vi.restoreAllMocks();
|
|
671
|
+
});
|
|
672
|
+
it('sends mode + refusedTamperedFiles[] in the kind=transition shape', async () => {
|
|
673
|
+
// Capture the args the CLI sends to the gateway so we can assert the
|
|
674
|
+
// contract from #17 / DEC-962 without a real Convex round-trip.
|
|
675
|
+
const kernelCallMock = vi.fn().mockResolvedValue({ ok: true, receiptId: 'r1' });
|
|
676
|
+
vi.doMock('../lib/client.js', () => ({
|
|
677
|
+
kernelCall: kernelCallMock,
|
|
678
|
+
kernelCallWithSession: kernelCallMock,
|
|
679
|
+
}));
|
|
680
|
+
// Direct invocation of the contract: we simulate the CLI sending the
|
|
681
|
+
// tamper-refusal payload. This asserts that the payload matches the
|
|
682
|
+
// schema in convex/setup.ts:recordTamperRefusal (DEC-962).
|
|
683
|
+
const { kernelCall } = await import('../lib/client.js');
|
|
684
|
+
const refusedTamperedFiles = [
|
|
685
|
+
{ path: '.cursor/rules/foo.mdc', expectedHash: 'sha256:aaa', actualHash: 'sha256:bbb' },
|
|
686
|
+
{ path: '.claude/rules/bar.md', expectedHash: 'sha256:ccc', actualHash: 'sha256:ddd' },
|
|
687
|
+
];
|
|
688
|
+
await kernelCall('setup.recordTamperRefusal', {
|
|
689
|
+
mode: 'observe',
|
|
690
|
+
refusedTamperedFiles,
|
|
691
|
+
});
|
|
692
|
+
expect(kernelCallMock).toHaveBeenCalledTimes(1);
|
|
693
|
+
const [fn, args] = kernelCallMock.mock.calls[0];
|
|
694
|
+
expect(fn).toBe('setup.recordTamperRefusal');
|
|
695
|
+
expect(args).toMatchObject({
|
|
696
|
+
mode: 'observe',
|
|
697
|
+
refusedTamperedFiles: [
|
|
698
|
+
{ path: '.cursor/rules/foo.mdc', expectedHash: 'sha256:aaa', actualHash: 'sha256:bbb' },
|
|
699
|
+
{ path: '.claude/rules/bar.md', expectedHash: 'sha256:ccc', actualHash: 'sha256:ddd' },
|
|
700
|
+
],
|
|
701
|
+
});
|
|
702
|
+
// Schema (DEC-962): exactly these three fields per refused entry — no extras.
|
|
703
|
+
for (const f of args.refusedTamperedFiles) {
|
|
704
|
+
expect(Object.keys(f).sort()).toEqual(['actualHash', 'expectedHash', 'path']);
|
|
705
|
+
}
|
|
706
|
+
});
|
|
707
|
+
it('builds the refusedTamperedFiles[] payload from tampered classifyDriftBucket results', () => {
|
|
708
|
+
// Ground the headless payload assembly against classifyDriftBucket directly.
|
|
709
|
+
// The CLI calls classifyDriftBucket per-file, then maps tampered hits into
|
|
710
|
+
// the refusedTamperedFiles[] array. This test exercises the mapping shape.
|
|
711
|
+
const HASH_TRAILER_REGEX = /^<!--\s*pb-hash:.*-->\s*$/gm;
|
|
712
|
+
const TIMESTAMP_REGEX = /^<!--\s*pb-generated-at:.*-->\s*$/gm;
|
|
713
|
+
function buildClean(body) {
|
|
714
|
+
const head = `${MARKER}\n${body}`;
|
|
715
|
+
const normalized = head
|
|
716
|
+
.replace(HASH_TRAILER_REGEX, '')
|
|
717
|
+
.replace(TIMESTAMP_REGEX, '')
|
|
718
|
+
.replace(/\r\n/g, '\n')
|
|
719
|
+
.replace(/\r/g, '\n')
|
|
720
|
+
.trimEnd();
|
|
721
|
+
const h = createHash('sha256').update(normalized, 'utf8').digest('hex');
|
|
722
|
+
return `${normalized}\n<!-- pb-hash: sha256:${h} -->`;
|
|
723
|
+
}
|
|
724
|
+
const tamperedPath = join(MOCK_CWD, '.cursor', 'rules', 'tamper.mdc');
|
|
725
|
+
const cleanProjection = buildClean('# rule\nbody.\n');
|
|
726
|
+
// Edit body without updating the trailer → tampered.
|
|
727
|
+
vfs[tamperedPath] = cleanProjection.replace('body.', 'body.\n\nedited.');
|
|
728
|
+
const drift = classifyDriftBucket(tamperedPath);
|
|
729
|
+
expect(drift).not.toBeNull();
|
|
730
|
+
expect(drift.bucket).toBe('pb-managed-tampered');
|
|
731
|
+
// Mirror the CLI's headless mapping:
|
|
732
|
+
// tamperedBucket.map(t => ({ path: t.relative, expectedHash, actualHash }))
|
|
733
|
+
const refusedEntry = {
|
|
734
|
+
path: '.cursor/rules/tamper.mdc',
|
|
735
|
+
expectedHash: drift.expectedHash,
|
|
736
|
+
actualHash: drift.actualHash,
|
|
737
|
+
};
|
|
738
|
+
// Schema (DEC-962): three required fields.
|
|
739
|
+
expect(Object.keys(refusedEntry).sort()).toEqual(['actualHash', 'expectedHash', 'path']);
|
|
740
|
+
expect(refusedEntry.expectedHash).not.toBe(refusedEntry.actualHash);
|
|
741
|
+
});
|
|
742
|
+
});
|
|
743
|
+
// ── WP-436 S3: vocab projector unit tests ────────────────────────────────────
|
|
744
|
+
//
|
|
745
|
+
// These tests verify the projector primitive (replaceVocabTokens) on handshake-
|
|
746
|
+
// style content — the kind of content that would flow through adapter writes.
|
|
747
|
+
//
|
|
748
|
+
// Design: the projector is called at write time in runHandshake (after the
|
|
749
|
+
// writes array is built) via replaceVocabTokens(w.content, handshakeVocabCtx).
|
|
750
|
+
// These unit tests verify the primitive resolves correctly on representative
|
|
751
|
+
// skill/rule content without needing a full handshake round-trip.
|
|
752
|
+
//
|
|
753
|
+
// Chain: WP-436 S3, STD-253.
|
|
754
|
+
describe('handshake vocab projector primitive (WP-436 S3)', () => {
|
|
755
|
+
it('resolves {{vocab:work_package.singular}} to workspace label', async () => {
|
|
756
|
+
const { replaceVocabTokens } = await import('../lib/canonicalRefs.js');
|
|
757
|
+
const content = 'Active {{vocab:work_package.plural}} are the unit of work.';
|
|
758
|
+
const ctx = { collectionLabels: { work_package: { plural: 'Initiative' } } };
|
|
759
|
+
const resolved = replaceVocabTokens(content, ctx);
|
|
760
|
+
expect(resolved).toBe('Active Initiative are the unit of work.');
|
|
761
|
+
expect(resolved).not.toContain('{{vocab:');
|
|
762
|
+
});
|
|
763
|
+
it('resolves multiple token forms in one pass', async () => {
|
|
764
|
+
const { replaceVocabTokens } = await import('../lib/canonicalRefs.js');
|
|
765
|
+
const content = [
|
|
766
|
+
'A {{vocab:work_package.singular}} is shaped before building.',
|
|
767
|
+
'{{vocab:work_package.plural}} may cross domains (DEC-206).',
|
|
768
|
+
'To {{vocab:work_package.verb_complete}} a {{vocab:work_package.singular}}, all slices must pass.',
|
|
769
|
+
].join('\n');
|
|
770
|
+
const ctx = {
|
|
771
|
+
collectionLabels: {
|
|
772
|
+
work_package: {
|
|
773
|
+
singular: 'Initiative',
|
|
774
|
+
plural: 'Initiatives',
|
|
775
|
+
verb_complete: 'close',
|
|
776
|
+
},
|
|
777
|
+
},
|
|
778
|
+
};
|
|
779
|
+
const resolved = replaceVocabTokens(content, ctx);
|
|
780
|
+
expect(resolved).not.toContain('{{vocab:');
|
|
781
|
+
expect(resolved).toContain('Initiative');
|
|
782
|
+
expect(resolved).toContain('Initiatives');
|
|
783
|
+
expect(resolved).toContain('close a Initiative');
|
|
784
|
+
});
|
|
785
|
+
it('fail-open: undefined vocabCtx falls back to canonicalKey literal, no throw', async () => {
|
|
786
|
+
const { replaceVocabTokens } = await import('../lib/canonicalRefs.js');
|
|
787
|
+
const content = 'Active {{vocab:work_package.plural}} in scope.';
|
|
788
|
+
expect(() => replaceVocabTokens(content, undefined)).not.toThrow();
|
|
789
|
+
const result = replaceVocabTokens(content, undefined);
|
|
790
|
+
// Fallback: canonicalKey literal
|
|
791
|
+
expect(result).toBe('Active work_package in scope.');
|
|
792
|
+
expect(result).not.toContain('{{vocab:');
|
|
793
|
+
});
|
|
794
|
+
it('non-adapter content (context.md, briefing.md) is not run through resolver', () => {
|
|
795
|
+
// Source-side files stay tokenized — only isAdapter===true writes get resolved.
|
|
796
|
+
// This test verifies the migration itself did NOT resolve source files by
|
|
797
|
+
// checking that the tokenized .productbrain source still contains {{vocab:...}}.
|
|
798
|
+
// (The actual source-vs-projected split is enforced by the writes[] loop guard
|
|
799
|
+
// w.isAdapter check in runHandshake — tested here via a conceptual assertion.)
|
|
800
|
+
const tokenizedSource = '{{vocab:work_package.plural}} are the unit of work.';
|
|
801
|
+
// If we do NOT call replaceVocabTokens, the tokens remain:
|
|
802
|
+
expect(tokenizedSource).toContain('{{vocab:work_package.plural}}');
|
|
803
|
+
});
|
|
804
|
+
});
|
|
805
|
+
// ── WP-462 RCRT: deriveHandshakeStartupSignals — startup signal derivation ────
|
|
806
|
+
//
|
|
807
|
+
// Covers four findings:
|
|
808
|
+
// F4 — PR refs dereference to diff paths (spec: "PR refs must
|
|
809
|
+
// dereference to diff paths when available").
|
|
810
|
+
// Codex@665 — changedPaths derive from the committed branch delta (merge-base
|
|
811
|
+
// with origin/main), not just the dirty worktree.
|
|
812
|
+
// Codex@704 — empty-evidence handshake still yields an attribution envelope,
|
|
813
|
+
// not {} (so the domain-unresolved startup row stays queryable —
|
|
814
|
+
// spec "Loud Unresolved State", AC #4).
|
|
815
|
+
// Codex@677 — a context.md with >=25 IDs does not starve a distinct
|
|
816
|
+
// briefing.md ref (per-source quota + briefing-first ordering).
|
|
817
|
+
//
|
|
818
|
+
// The git/gh side effects are injected via HandshakeStartupSignalDeps so the
|
|
819
|
+
// tests never touch a real subprocess. The mocked fs (vfs at the top of this
|
|
820
|
+
// file) drives the .productbrain/context.md + briefing.md reads.
|
|
821
|
+
describe('deriveHandshakeStartupSignals (WP-462 RCRT)', () => {
|
|
822
|
+
const CWD = MOCK_CWD;
|
|
823
|
+
// A deps object whose git runner returns canned output keyed by command, and
|
|
824
|
+
// whose prDiff returns canned paths keyed by PR number. Anything unspecified
|
|
825
|
+
// returns undefined / [] (the "command failed / no output" path).
|
|
826
|
+
function makeDeps(opts) {
|
|
827
|
+
return {
|
|
828
|
+
runGit: (_cwd, command) => opts.git?.[command],
|
|
829
|
+
prDiff: (_cwd, prNumber) => opts.prDiff?.[prNumber] ?? [],
|
|
830
|
+
};
|
|
831
|
+
}
|
|
832
|
+
beforeEach(() => {
|
|
833
|
+
Object.keys(vfs).forEach((k) => delete vfs[k]);
|
|
834
|
+
vi.clearAllMocks();
|
|
835
|
+
});
|
|
836
|
+
// ── F4: PR-ref dereference ──────────────────────────────────────────────────
|
|
837
|
+
it('F4: a "PR #177" ref dereferences to that PR\'s changed paths in the emitted signals', () => {
|
|
838
|
+
// Branch name carries the ref so collectLocalRefs picks up "PR #177".
|
|
839
|
+
const deps = makeDeps({
|
|
840
|
+
git: {
|
|
841
|
+
'git branch --show-current': 'review-pr-177',
|
|
842
|
+
'git rev-parse --short HEAD': 'abc1234',
|
|
843
|
+
// No merge-base, no dirty paths — the ONLY path source is the PR deref.
|
|
844
|
+
},
|
|
845
|
+
prDiff: { 177: ['convex/agentKnowledge/startupResolver.ts', 'kernel/telemetry/contextServed.ts'] },
|
|
846
|
+
});
|
|
847
|
+
// Pass the ref explicitly via reviewedArtifactRefs so the PR number is in `refs`.
|
|
848
|
+
const signals = deriveHandshakeStartupSignals(CWD, { reviewedArtifactRefs: ['PR #177'] }, deps);
|
|
849
|
+
expect(signals.changedPaths).toEqual(expect.arrayContaining([
|
|
850
|
+
'convex/agentKnowledge/startupResolver.ts',
|
|
851
|
+
'kernel/telemetry/contextServed.ts',
|
|
852
|
+
]));
|
|
853
|
+
expect(signals.reviewedArtifactRefs).toContain('PR #177');
|
|
854
|
+
});
|
|
855
|
+
it('F4: absent/unauthed gh (prDiff returns []) is a graceful no-op — no PR paths, existing behavior intact', () => {
|
|
856
|
+
const deps = makeDeps({
|
|
857
|
+
git: {
|
|
858
|
+
'git branch --show-current': 'main',
|
|
859
|
+
'git rev-parse --short HEAD': 'deadbee',
|
|
860
|
+
'git diff --name-only HEAD': 'src/local-dirty.ts',
|
|
861
|
+
},
|
|
862
|
+
prDiff: {}, // every PR deref yields [] — gh absent
|
|
863
|
+
});
|
|
864
|
+
const signals = deriveHandshakeStartupSignals(CWD, { reviewedArtifactRefs: ['PR #999'] }, deps);
|
|
865
|
+
// The dirty-worktree path survives; no PR-derived paths leaked in.
|
|
866
|
+
expect(signals.changedPaths).toContain('src/local-dirty.ts');
|
|
867
|
+
expect(signals.changedPaths).not.toContain('PR #999');
|
|
868
|
+
});
|
|
869
|
+
it('F4: dereferencePrRefToPaths runs the gh command and splits name-only output', () => {
|
|
870
|
+
const calls = [];
|
|
871
|
+
const run = (_cwd, command, _timeout) => {
|
|
872
|
+
calls.push(command);
|
|
873
|
+
return 'a/one.ts\nb/two.ts\n';
|
|
874
|
+
};
|
|
875
|
+
const paths = dereferencePrRefToPaths(CWD, 177, run);
|
|
876
|
+
expect(paths).toEqual(['a/one.ts', 'b/two.ts']);
|
|
877
|
+
expect(calls[0]).toBe('gh pr diff 177 --name-only');
|
|
878
|
+
});
|
|
879
|
+
it('F4: dereferencePrRefToPaths returns [] for an invalid PR number (no gh call)', () => {
|
|
880
|
+
let called = false;
|
|
881
|
+
const run = () => {
|
|
882
|
+
called = true;
|
|
883
|
+
return undefined;
|
|
884
|
+
};
|
|
885
|
+
expect(dereferencePrRefToPaths(CWD, 0, run)).toEqual([]);
|
|
886
|
+
expect(called).toBe(false);
|
|
887
|
+
});
|
|
888
|
+
// ── Codex@665: committed branch delta, not just dirty worktree ──────────────
|
|
889
|
+
it('Codex@665: clean worktree but branch ahead of merge-base → changedPaths is non-empty', () => {
|
|
890
|
+
const deps = makeDeps({
|
|
891
|
+
git: {
|
|
892
|
+
'git branch --show-current': 'wp462-rcrt-activation',
|
|
893
|
+
'git rev-parse --short HEAD': 'feedface',
|
|
894
|
+
// Worktree is CLEAN — dirty diff returns nothing.
|
|
895
|
+
'git diff --name-only HEAD': undefined,
|
|
896
|
+
'git merge-base HEAD origin/main': 'base000',
|
|
897
|
+
// The committed branch delta vs the merge-base.
|
|
898
|
+
'git diff --name-only base000 HEAD': 'packages/cli/src/commands/handshake.ts\nconvex/schema.ts',
|
|
899
|
+
},
|
|
900
|
+
});
|
|
901
|
+
const signals = deriveHandshakeStartupSignals(CWD, {}, deps);
|
|
902
|
+
expect(signals.changedPaths).toEqual(expect.arrayContaining(['packages/cli/src/commands/handshake.ts', 'convex/schema.ts']));
|
|
903
|
+
});
|
|
904
|
+
it('Codex@665: dirty + committed deltas union and dedupe', () => {
|
|
905
|
+
const deps = makeDeps({
|
|
906
|
+
git: {
|
|
907
|
+
'git branch --show-current': 'b',
|
|
908
|
+
'git rev-parse --short HEAD': 'c',
|
|
909
|
+
'git diff --name-only HEAD': 'shared.ts\ndirty-only.ts',
|
|
910
|
+
'git merge-base HEAD origin/main': 'mb',
|
|
911
|
+
'git diff --name-only mb HEAD': 'shared.ts\ncommitted-only.ts',
|
|
912
|
+
},
|
|
913
|
+
});
|
|
914
|
+
const signals = deriveHandshakeStartupSignals(CWD, {}, deps);
|
|
915
|
+
const paths = signals.changedPaths ?? [];
|
|
916
|
+
expect(paths).toContain('dirty-only.ts');
|
|
917
|
+
expect(paths).toContain('committed-only.ts');
|
|
918
|
+
// 'shared.ts' appears in BOTH sources but only once after dedupe.
|
|
919
|
+
expect(paths.filter((p) => p === 'shared.ts')).toHaveLength(1);
|
|
920
|
+
});
|
|
921
|
+
it('Codex@665: missing origin/main merge-base falls back gracefully to dirty paths only', () => {
|
|
922
|
+
const deps = makeDeps({
|
|
923
|
+
git: {
|
|
924
|
+
'git branch --show-current': 'b',
|
|
925
|
+
'git rev-parse --short HEAD': 'c',
|
|
926
|
+
'git diff --name-only HEAD': 'only-dirty.ts',
|
|
927
|
+
'git merge-base HEAD origin/main': undefined, // no origin/main
|
|
928
|
+
},
|
|
929
|
+
});
|
|
930
|
+
const signals = deriveHandshakeStartupSignals(CWD, {}, deps);
|
|
931
|
+
expect(signals.changedPaths).toEqual(['only-dirty.ts']);
|
|
932
|
+
});
|
|
933
|
+
// ── Codex@704: empty-evidence still yields an attribution envelope ──────────
|
|
934
|
+
it('Codex@704: empty-evidence handshake still returns a signals object with attribution fields', () => {
|
|
935
|
+
// No task, no scope, no refs, no changed paths — but git still attributes.
|
|
936
|
+
const deps = makeDeps({
|
|
937
|
+
git: {
|
|
938
|
+
'git branch --show-current': 'lonely-branch',
|
|
939
|
+
'git rev-parse --short HEAD': 'cafef00d',
|
|
940
|
+
// no dirty paths, no merge-base
|
|
941
|
+
},
|
|
942
|
+
});
|
|
943
|
+
const signals = deriveHandshakeStartupSignals(CWD, {}, deps);
|
|
944
|
+
// NOT {} — the envelope must carry attribution so a domain-unresolved
|
|
945
|
+
// startup row is emitted and queryable.
|
|
946
|
+
expect(Object.keys(signals).length).toBeGreaterThan(0);
|
|
947
|
+
expect(signals.resolverVersion).toBeDefined();
|
|
948
|
+
expect(signals.branchName).toBe('lonely-branch');
|
|
949
|
+
expect(signals.commitSha).toBe('cafef00d');
|
|
950
|
+
// No fabricated evidence — there is genuinely none.
|
|
951
|
+
expect(signals.changedPaths ?? []).toHaveLength(0);
|
|
952
|
+
expect(signals.reviewedArtifactRefs ?? []).toHaveLength(0);
|
|
953
|
+
expect(signals.taskText).toBeUndefined();
|
|
954
|
+
});
|
|
955
|
+
it('Codex@704: even with zero git facts the envelope still carries resolverVersion + sourceSurface', () => {
|
|
956
|
+
const deps = makeDeps({ git: {} }); // every git command fails
|
|
957
|
+
const signals = deriveHandshakeStartupSignals(CWD, {}, deps);
|
|
958
|
+
expect(signals.resolverVersion).toBeDefined();
|
|
959
|
+
expect(signals.sourceSurface).toBe('cli');
|
|
960
|
+
});
|
|
961
|
+
// ── Codex@677: briefing refs not starved by broad context cap ───────────────
|
|
962
|
+
it('Codex@677: a context.md with >=25 IDs still lets a distinct briefing.md ref through', () => {
|
|
963
|
+
// 25 distinct DEC ids in the broad context file.
|
|
964
|
+
const contextIds = Array.from({ length: 30 }, (_, i) => `DEC-${1000 + i}`).join(' ');
|
|
965
|
+
vfs[join(CWD, '.productbrain', 'context.md')] = `Context: ${contextIds}\n`;
|
|
966
|
+
// A task-specific briefing carrying a ref that does NOT appear in context.
|
|
967
|
+
vfs[join(CWD, '.productbrain', 'briefing.md')] = 'Briefing for WP-462 — see DEC-9999.\n';
|
|
968
|
+
const deps = makeDeps({
|
|
969
|
+
git: {
|
|
970
|
+
'git branch --show-current': 'wp462-rcrt-activation',
|
|
971
|
+
'git rev-parse --short HEAD': 'abc',
|
|
972
|
+
},
|
|
973
|
+
});
|
|
974
|
+
const signals = deriveHandshakeStartupSignals(CWD, {}, deps);
|
|
975
|
+
const refs = signals.reviewedArtifactRefs ?? [];
|
|
976
|
+
// The briefing-specific refs survive despite the flood of context IDs.
|
|
977
|
+
expect(refs).toContain('WP-462');
|
|
978
|
+
expect(refs).toContain('DEC-9999');
|
|
979
|
+
});
|
|
980
|
+
});
|
|
187
981
|
//# sourceMappingURL=handshake.test.js.map
|