@productbrain/cli 0.1.0-beta.9 → 0.1.0-beta.91
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 +77 -92
- 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.d.ts +2 -0
- package/dist/__tests__/audit.test.d.ts.map +1 -0
- package/dist/__tests__/audit.test.js +394 -0
- package/dist/__tests__/audit.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__/capture.test.js +309 -18
- package/dist/__tests__/capture.test.js.map +1 -1
- 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 +166 -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 +141 -0
- package/dist/__tests__/constants.test.js.map +1 -0
- package/dist/__tests__/constellation.test.js +20 -26
- package/dist/__tests__/constellation.test.js.map +1 -1
- package/dist/__tests__/context-strategy.test.d.ts +2 -0
- package/dist/__tests__/context-strategy.test.d.ts.map +1 -0
- package/dist/__tests__/context-strategy.test.js +79 -0
- package/dist/__tests__/context-strategy.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 +117 -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 +68 -68
- 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-preview.test.d.ts +2 -0
- package/dist/__tests__/handshake-preview.test.d.ts.map +1 -0
- package/dist/__tests__/handshake-preview.test.js +156 -0
- package/dist/__tests__/handshake-preview.test.js.map +1 -0
- package/dist/__tests__/handshake.test.js +27 -18
- 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 +110 -12
- 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 +138 -0
- package/dist/__tests__/manifest.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__/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 +143 -0
- package/dist/__tests__/orient.test.js.map +1 -0
- package/dist/__tests__/personal-layer.test.d.ts +12 -0
- package/dist/__tests__/personal-layer.test.d.ts.map +1 -0
- package/dist/__tests__/personal-layer.test.js +304 -0
- package/dist/__tests__/personal-layer.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 +168 -0
- package/dist/__tests__/profiles.test.js.map +1 -0
- package/dist/__tests__/promote.test.d.ts +2 -0
- package/dist/__tests__/promote.test.d.ts.map +1 -0
- package/dist/__tests__/promote.test.js +161 -0
- package/dist/__tests__/promote.test.js.map +1 -0
- 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__/proposals.test.d.ts +2 -0
- package/dist/__tests__/proposals.test.d.ts.map +1 -0
- package/dist/__tests__/proposals.test.js +167 -0
- package/dist/__tests__/proposals.test.js.map +1 -0
- package/dist/__tests__/relate.test.js +57 -33
- 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-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 +154 -0
- package/dist/__tests__/session-state-machine.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.test.d.ts +2 -0
- package/dist/__tests__/setup.test.d.ts.map +1 -0
- package/dist/__tests__/setup.test.js +141 -0
- package/dist/__tests__/setup.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__/strip.test.js +2 -2
- package/dist/__tests__/strip.test.js.map +1 -1
- 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.test.js +123 -43
- package/dist/__tests__/update.test.js.map +1 -1
- 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 +308 -0
- package/dist/__tests__/workspace.test.js.map +1 -0
- package/dist/commands/accept.d.ts +18 -0
- package/dist/commands/accept.d.ts.map +1 -0
- package/dist/commands/accept.js +76 -0
- package/dist/commands/accept.js.map +1 -0
- 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 +76 -0
- package/dist/commands/admin/manage.js.map +1 -0
- package/dist/commands/admin/seed.d.ts +32 -0
- package/dist/commands/admin/seed.d.ts.map +1 -0
- package/dist/commands/admin/seed.js +533 -0
- package/dist/commands/admin/seed.js.map +1 -0
- package/dist/commands/admin/seed.test.d.ts +6 -0
- package/dist/commands/admin/seed.test.d.ts.map +1 -0
- package/dist/commands/admin/seed.test.js +65 -0
- package/dist/commands/admin/seed.test.js.map +1 -0
- package/dist/commands/audit.d.ts +25 -0
- package/dist/commands/audit.d.ts.map +1 -0
- package/dist/commands/audit.js +188 -0
- package/dist/commands/audit.js.map +1 -0
- package/dist/commands/brand-pack.d.ts +2 -0
- package/dist/commands/brand-pack.d.ts.map +1 -0
- package/dist/commands/brand-pack.js +25 -0
- package/dist/commands/brand-pack.js.map +1 -0
- package/dist/commands/brief.d.ts +28 -0
- package/dist/commands/brief.d.ts.map +1 -0
- package/dist/commands/brief.js +75 -0
- package/dist/commands/brief.js.map +1 -0
- package/dist/commands/capture.d.ts +9 -0
- package/dist/commands/capture.d.ts.map +1 -1
- package/dist/commands/capture.js +256 -17
- package/dist/commands/capture.js.map +1 -1
- package/dist/commands/chain-walk.d.ts +14 -0
- package/dist/commands/chain-walk.d.ts.map +1 -0
- package/dist/commands/chain-walk.js +38 -0
- package/dist/commands/chain-walk.js.map +1 -0
- package/dist/commands/changes.d.ts +11 -0
- package/dist/commands/changes.d.ts.map +1 -0
- package/dist/commands/changes.js +46 -0
- package/dist/commands/changes.js.map +1 -0
- package/dist/commands/codex-prep.d.ts +12 -0
- package/dist/commands/codex-prep.d.ts.map +1 -0
- package/dist/commands/codex-prep.js +122 -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-integration.test.d.ts +7 -0
- package/dist/commands/connect-integration.test.d.ts.map +1 -0
- package/dist/commands/connect-integration.test.js +195 -0
- package/dist/commands/connect-integration.test.js.map +1 -0
- package/dist/commands/connect-screens.d.ts +21 -0
- package/dist/commands/connect-screens.d.ts.map +1 -0
- package/dist/commands/connect-screens.js +79 -0
- package/dist/commands/connect-screens.js.map +1 -0
- package/dist/commands/connect.d.ts +21 -0
- package/dist/commands/connect.d.ts.map +1 -0
- package/dist/commands/connect.js +237 -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 +234 -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.d.ts +11 -0
- package/dist/commands/cross-cut.d.ts.map +1 -0
- package/dist/commands/cross-cut.js +23 -0
- package/dist/commands/cross-cut.js.map +1 -0
- package/dist/commands/doctor.d.ts +18 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +232 -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 +311 -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 +12 -0
- package/dist/commands/handshake.d.ts.map +1 -1
- package/dist/commands/handshake.js +422 -74
- package/dist/commands/handshake.js.map +1 -1
- package/dist/commands/ingest.d.ts +7 -2
- package/dist/commands/ingest.d.ts.map +1 -1
- package/dist/commands/ingest.js +137 -31
- 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 +781 -0
- package/dist/commands/method.js.map +1 -0
- package/dist/commands/orient.d.ts +106 -1
- package/dist/commands/orient.d.ts.map +1 -1
- package/dist/commands/orient.js +13 -2
- package/dist/commands/orient.js.map +1 -1
- package/dist/commands/profile.d.ts +24 -0
- package/dist/commands/profile.d.ts.map +1 -0
- package/dist/commands/profile.js +82 -0
- package/dist/commands/profile.js.map +1 -0
- package/dist/commands/promote.d.ts +12 -0
- package/dist/commands/promote.d.ts.map +1 -0
- package/dist/commands/promote.js +90 -0
- package/dist/commands/promote.js.map +1 -0
- package/dist/commands/proposals.d.ts +9 -0
- package/dist/commands/proposals.d.ts.map +1 -0
- package/dist/commands/proposals.js +24 -0
- package/dist/commands/proposals.js.map +1 -0
- package/dist/commands/reject.d.ts +14 -0
- package/dist/commands/reject.d.ts.map +1 -0
- package/dist/commands/reject.js +43 -0
- package/dist/commands/reject.js.map +1 -0
- package/dist/commands/relate.d.ts +1 -0
- package/dist/commands/relate.d.ts.map +1 -1
- package/dist/commands/relate.js +41 -15
- package/dist/commands/relate.js.map +1 -1
- package/dist/commands/search.js +2 -2
- package/dist/commands/search.js.map +1 -1
- package/dist/commands/session.d.ts.map +1 -1
- package/dist/commands/session.js +85 -16
- package/dist/commands/session.js.map +1 -1
- package/dist/commands/setup.d.ts +15 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +148 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/commands/update.d.ts +1 -0
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +102 -13
- package/dist/commands/update.js.map +1 -1
- 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 +13 -0
- package/dist/commands/verify.d.ts.map +1 -0
- package/dist/commands/verify.js +49 -0
- package/dist/commands/verify.js.map +1 -0
- 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/workspace.d.ts +41 -0
- package/dist/commands/workspace.d.ts.map +1 -0
- package/dist/commands/workspace.js +239 -0
- package/dist/commands/workspace.js.map +1 -0
- package/dist/formatters/audit.d.ts +46 -0
- package/dist/formatters/audit.d.ts.map +1 -0
- package/dist/formatters/audit.js +81 -0
- package/dist/formatters/audit.js.map +1 -0
- package/dist/formatters/brief.d.ts +112 -0
- package/dist/formatters/brief.d.ts.map +1 -0
- package/dist/formatters/brief.js +179 -0
- package/dist/formatters/brief.js.map +1 -0
- package/dist/formatters/capture.d.ts +21 -3
- package/dist/formatters/capture.d.ts.map +1 -1
- package/dist/formatters/capture.js +20 -1
- package/dist/formatters/capture.js.map +1 -1
- package/dist/formatters/chain-walk.d.ts +33 -0
- package/dist/formatters/chain-walk.d.ts.map +1 -0
- package/dist/formatters/chain-walk.js +54 -0
- package/dist/formatters/chain-walk.js.map +1 -0
- package/dist/formatters/changes.d.ts +25 -0
- package/dist/formatters/changes.d.ts.map +1 -0
- package/dist/formatters/changes.js +60 -0
- package/dist/formatters/changes.js.map +1 -0
- 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/cross-cut.d.ts +21 -0
- package/dist/formatters/cross-cut.d.ts.map +1 -0
- package/dist/formatters/cross-cut.js +32 -0
- package/dist/formatters/cross-cut.js.map +1 -0
- package/dist/formatters/entry.d.ts +11 -4
- package/dist/formatters/entry.d.ts.map +1 -1
- package/dist/formatters/entry.js +24 -8
- package/dist/formatters/entry.js.map +1 -1
- package/dist/formatters/handshake.d.ts +29 -0
- package/dist/formatters/handshake.d.ts.map +1 -1
- package/dist/formatters/handshake.js +115 -3
- package/dist/formatters/handshake.js.map +1 -1
- package/dist/formatters/orient.d.ts +104 -1
- package/dist/formatters/orient.d.ts.map +1 -1
- package/dist/formatters/orient.js +140 -17
- package/dist/formatters/orient.js.map +1 -1
- package/dist/formatters/promote.d.ts +30 -0
- package/dist/formatters/promote.d.ts.map +1 -0
- package/dist/formatters/promote.js +39 -0
- package/dist/formatters/promote.js.map +1 -0
- package/dist/formatters/proposals.d.ts +45 -0
- package/dist/formatters/proposals.d.ts.map +1 -0
- package/dist/formatters/proposals.js +62 -0
- package/dist/formatters/proposals.js.map +1 -0
- package/dist/formatters/relate.d.ts +3 -0
- package/dist/formatters/relate.d.ts.map +1 -1
- package/dist/formatters/relate.js +6 -0
- package/dist/formatters/relate.js.map +1 -1
- 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 +1 -1
- package/dist/formatters/session.d.ts.map +1 -1
- package/dist/formatters/session.js +3 -1
- 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/formatters/verify.d.ts +11 -0
- package/dist/formatters/verify.d.ts.map +1 -0
- package/dist/formatters/verify.js +11 -0
- package/dist/formatters/verify.js.map +1 -0
- package/dist/generators/__tests__/surface-profiles.test.d.ts +2 -0
- package/dist/generators/__tests__/surface-profiles.test.d.ts.map +1 -0
- package/dist/generators/__tests__/surface-profiles.test.js +89 -0
- package/dist/generators/__tests__/surface-profiles.test.js.map +1 -0
- package/dist/generators/adapters.d.ts +37 -3
- package/dist/generators/adapters.d.ts.map +1 -1
- package/dist/generators/adapters.js +193 -5
- 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 +153 -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 +237 -0
- package/dist/generators/archetypes.test.js.map +1 -0
- package/dist/generators/chain-classifier.d.ts +49 -0
- package/dist/generators/chain-classifier.d.ts.map +1 -0
- package/dist/generators/chain-classifier.js +180 -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 +257 -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 +144 -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 +179 -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 +12 -1
- 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 +37 -0
- package/dist/generators/manifest.d.ts.map +1 -0
- package/dist/generators/manifest.js +166 -0
- package/dist/generators/manifest.js.map +1 -0
- package/dist/generators/portable-knowledge.d.ts +102 -9
- package/dist/generators/portable-knowledge.d.ts.map +1 -1
- package/dist/generators/portable-knowledge.js +384 -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/surface-profiles.d.ts +49 -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 +618 -138
- 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/client.d.ts +45 -3
- package/dist/lib/client.d.ts.map +1 -1
- package/dist/lib/client.js +188 -36
- package/dist/lib/client.js.map +1 -1
- package/dist/lib/collectionRegistry.d.ts +38 -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/config.d.ts +84 -4
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +322 -42
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/constants.d.ts +42 -0
- package/dist/lib/constants.d.ts.map +1 -0
- package/dist/lib/constants.js +76 -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 +58 -0
- package/dist/lib/errors.d.ts.map +1 -0
- package/dist/lib/errors.js +67 -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/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/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 +214 -0
- package/dist/lib/onboarding-path-b.js.map +1 -0
- package/dist/lib/onboarding-phases.d.ts +9 -0
- package/dist/lib/onboarding-phases.d.ts.map +1 -0
- package/dist/lib/onboarding-phases.js +120 -0
- package/dist/lib/onboarding-phases.js.map +1 -0
- package/dist/lib/onboarding-shared.d.ts +81 -0
- package/dist/lib/onboarding-shared.d.ts.map +1 -0
- package/dist/lib/onboarding-shared.js +190 -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 +39 -0
- package/dist/lib/profiles.d.ts.map +1 -0
- package/dist/lib/profiles.js +185 -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 +25 -0
- package/dist/lib/session.d.ts.map +1 -1
- package/dist/lib/session.js +70 -4
- 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/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 +17 -0
- package/dist/lib/tokenConstants.d.ts.map +1 -0
- package/dist/lib/tokenConstants.js +17 -0
- package/dist/lib/tokenConstants.js.map +1 -0
- package/dist/lib/update-check.d.ts +21 -0
- package/dist/lib/update-check.d.ts.map +1 -0
- package/dist/lib/update-check.js +145 -0
- package/dist/lib/update-check.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/surfaces/registry.d.ts +20 -0
- package/dist/surfaces/registry.d.ts.map +1 -0
- package/dist/surfaces/registry.js +42 -0
- package/dist/surfaces/registry.js.map +1 -0
- package/package.json +9 -3
- 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,18 +2,27 @@
|
|
|
2
2
|
* pb handshake — generate context files for AI developer tools.
|
|
3
3
|
* The fourth delivery surface: context export (GLO-63, DEC-161).
|
|
4
4
|
*/
|
|
5
|
-
import { mkdirSync, writeFileSync, existsSync, readFileSync } from 'fs';
|
|
6
|
-
import { join } from 'path';
|
|
5
|
+
import { mkdirSync, writeFileSync, existsSync, readFileSync, readdirSync, copyFileSync } from 'fs';
|
|
6
|
+
import { join, dirname, resolve } from 'path';
|
|
7
7
|
import { homedir } from 'os';
|
|
8
|
-
import {
|
|
8
|
+
import { fileURLToPath } from 'url';
|
|
9
9
|
import { getConfigOrGuide } from '../lib/config.js';
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
10
|
+
import { select as promptSelect } from '../lib/prompts.js';
|
|
11
|
+
import { composeHooksFromIntents, getHookStatusForSurface } from '../lib/hook-intents.js';
|
|
12
|
+
import { kernelCall, kernelCallWithSession } from '../lib/client.js';
|
|
13
|
+
import { readSession } from '../lib/session.js';
|
|
14
|
+
import { detectRepo, extractWorkspaceProfile } from '../lib/repo-detect.js';
|
|
12
15
|
import { generateContextMd } from '../generators/context-md.js';
|
|
13
16
|
import { generateBriefingMd } from '../generators/briefing-md.js';
|
|
14
|
-
import { MARKER, generateClaudeMd, generateCursorMdc, generateCopilotMd } from '../generators/adapters.js';
|
|
15
|
-
import { readCanonicalSkills, readCanonicalRules, generateCursorSkill, generateCursorRule, generateClaudeRule, generateClaudeSkillRouter, shouldEmitToTarget, filterByLevel, } from '../generators/portable-knowledge.js';
|
|
17
|
+
import { MARKER, generateAgentsMd, generateClaudeMd, generateCursorMdc, generateCopilotMd } from '../generators/adapters.js';
|
|
18
|
+
import { readCanonicalSkills, readCanonicalRules, readPersonalLayer, readPersonalSkillsLayer, generateCursorSkill, generateCursorRule, generateCodexSkill, generateCodexSkillIndex, generateClaudeRule, generateClaudeSkillRouter, shouldEmitToTarget, filterByLevel, validateCodexSkills, evaluateConditions, STAGE_TO_MAX_LEVEL, LEVEL_ORDER, } from '../generators/portable-knowledge.js';
|
|
19
|
+
import { generateChainRules } from '../generators/chain-rules.js';
|
|
20
|
+
import { saveHandshakeState, loadPreviousState, diffHandshakeState, formatDiff, buildCurrentState, } from '../generators/handshake-diff.js';
|
|
21
|
+
import { resolveSurfaceProfile } from '../generators/surface-profiles.js';
|
|
16
22
|
import { formatHandshakeReport } from '../formatters/handshake.js';
|
|
23
|
+
import { readManifest, filterByAdoptionState } from '../generators/manifest.js';
|
|
24
|
+
import { loadMethodRegistry } from '../lib/method-registry.js';
|
|
25
|
+
import { CLIError, ErrorCode } from '../lib/errors.js';
|
|
17
26
|
const LEVELS = {
|
|
18
27
|
guide: {
|
|
19
28
|
label: 'Guide me',
|
|
@@ -45,9 +54,6 @@ const LEVEL_KEYS = ['guide', 'work', 'silent', 'full-trust'];
|
|
|
45
54
|
// Hook failure contract (TEN-712): all hook commands MUST end with '2>/dev/null || true'
|
|
46
55
|
// so Claude Code always starts even if pb is unavailable. Never remove this suffix.
|
|
47
56
|
const INIT_PERMISSION = 'Bash(pb:*)';
|
|
48
|
-
const INIT_SESSION_START_CMD = 'pb session start 2>/dev/null || true';
|
|
49
|
-
const INIT_SESSION_CLOSE_CMD = 'pb session close 2>/dev/null || true';
|
|
50
|
-
const INIT_PRECOMPACT_CMD = 'pb session id > /dev/null 2>&1 && echo \'{"systemMessage": "pb session active — capture decisions/tensions before compacting: pb capture \\"DEC: ...\\""}\' || true';
|
|
51
57
|
function readSettings(filePath) {
|
|
52
58
|
if (!existsSync(filePath))
|
|
53
59
|
return {};
|
|
@@ -59,9 +65,6 @@ function readSettings(filePath) {
|
|
|
59
65
|
return {};
|
|
60
66
|
}
|
|
61
67
|
}
|
|
62
|
-
function hasCommand(groups, cmd) {
|
|
63
|
-
return (groups ?? []).some((g) => g.hooks?.some((h) => h.command === cmd));
|
|
64
|
-
}
|
|
65
68
|
// Team write: hooks + Bash(pb:*) → .claude/settings.json (safe to commit)
|
|
66
69
|
function writeTeamSettings(cwd, dryRun) {
|
|
67
70
|
const claudeDir = join(cwd, '.claude');
|
|
@@ -77,26 +80,10 @@ function writeTeamSettings(cwd, dryRun) {
|
|
|
77
80
|
}
|
|
78
81
|
settings.permissions = permissions;
|
|
79
82
|
const hooks = (settings.hooks ?? {});
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
];
|
|
85
|
-
added.push('SessionStart → pb session start');
|
|
86
|
-
}
|
|
87
|
-
if (!hasCommand(hooks.Stop, INIT_SESSION_CLOSE_CMD)) {
|
|
88
|
-
hooks.Stop = [
|
|
89
|
-
...(hooks.Stop ?? []),
|
|
90
|
-
{ hooks: [{ type: 'command', command: INIT_SESSION_CLOSE_CMD, statusMessage: 'Closing pb session...' }] },
|
|
91
|
-
];
|
|
92
|
-
added.push('Stop → pb session close');
|
|
93
|
-
}
|
|
94
|
-
if (!hasCommand(hooks.PreCompact, INIT_PRECOMPACT_CMD)) {
|
|
95
|
-
hooks.PreCompact = [
|
|
96
|
-
...(hooks.PreCompact ?? []),
|
|
97
|
-
{ hooks: [{ type: 'command', command: INIT_PRECOMPACT_CMD }] },
|
|
98
|
-
];
|
|
99
|
-
added.push('PreCompact → decision capture reminder');
|
|
83
|
+
const hookAdditions = composeHooksFromIntents(['session-start', 'session-close', 'pre-compact'], hooks);
|
|
84
|
+
for (const addition of hookAdditions) {
|
|
85
|
+
hooks[addition.event] = [...(hooks[addition.event] ?? []), addition.entry];
|
|
86
|
+
added.push(addition.label);
|
|
100
87
|
}
|
|
101
88
|
settings.hooks = hooks;
|
|
102
89
|
if (!dryRun) {
|
|
@@ -133,31 +120,26 @@ function writePersonalSettings(levelKey, dryRun) {
|
|
|
133
120
|
return added;
|
|
134
121
|
}
|
|
135
122
|
async function promptLevel() {
|
|
136
|
-
const
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
return new Promise((resolve) => {
|
|
144
|
-
rl.question('> ', (answer) => {
|
|
145
|
-
rl.close();
|
|
146
|
-
const n = parseInt(answer.trim(), 10);
|
|
147
|
-
if (!(n >= 1 && n <= LEVEL_KEYS.length)) {
|
|
148
|
-
console.log(' (Invalid choice — defaulting to "Just work")');
|
|
149
|
-
}
|
|
150
|
-
resolve(n >= 1 && n <= LEVEL_KEYS.length ? LEVEL_KEYS[n - 1] : 'work');
|
|
151
|
-
});
|
|
123
|
+
const result = await promptSelect({
|
|
124
|
+
message: 'How much should Claude explain before acting?',
|
|
125
|
+
options: LEVEL_KEYS.map((key) => ({
|
|
126
|
+
value: key,
|
|
127
|
+
label: LEVELS[key].label,
|
|
128
|
+
hint: LEVELS[key].description,
|
|
129
|
+
})),
|
|
152
130
|
});
|
|
131
|
+
return result;
|
|
153
132
|
}
|
|
154
133
|
export async function runHandshakeInit(options = {}) {
|
|
155
134
|
const cwd = process.cwd();
|
|
156
135
|
const dryRun = options.dryRun ?? false;
|
|
157
136
|
const suffix = dryRun ? ' (dry run)' : '';
|
|
158
137
|
if (options.level && !LEVEL_KEYS.includes(options.level)) {
|
|
159
|
-
|
|
160
|
-
|
|
138
|
+
throw new CLIError(`Unknown level "${options.level}".`, {
|
|
139
|
+
code: ErrorCode.VALIDATION_FAILED,
|
|
140
|
+
category: 'validation',
|
|
141
|
+
guidance: `Valid levels: ${LEVEL_KEYS.join(', ')}`,
|
|
142
|
+
});
|
|
161
143
|
}
|
|
162
144
|
console.log('Setting up Claude Code integration...\n');
|
|
163
145
|
// Step 1: Team config — always, no prompt
|
|
@@ -172,7 +154,7 @@ export async function runHandshakeInit(options = {}) {
|
|
|
172
154
|
console.log(` + ${item}`);
|
|
173
155
|
}
|
|
174
156
|
// Step 2: Personal config — wizard or --level flag
|
|
175
|
-
// Cast is safe: LEVEL_KEYS.includes() validated above; invalid level already
|
|
157
|
+
// Cast is safe: LEVEL_KEYS.includes() validated above; invalid level already threw CLIError.
|
|
176
158
|
const levelKey = options.level ? options.level : await promptLevel();
|
|
177
159
|
const level = LEVELS[levelKey];
|
|
178
160
|
const personalAdded = writePersonalSettings(levelKey, dryRun);
|
|
@@ -194,6 +176,88 @@ export async function runHandshakeInit(options = {}) {
|
|
|
194
176
|
if (!dryRun)
|
|
195
177
|
console.log('Reload /hooks in Claude Code (or restart) to activate.');
|
|
196
178
|
console.log('Run `pb handshake --init --level <guide|work|silent|full-trust>` to change level.');
|
|
179
|
+
// Step 2b: Report multi-surface hook opt-in status (WP-310 E3b)
|
|
180
|
+
// Reads manifest.hooks.{cursor,copilot} and prints an informational note for
|
|
181
|
+
// each opted-in surface. Silence = no manifest or no hooks flags set.
|
|
182
|
+
// DEC-536: Claude-native default is already wired above; this block only fires
|
|
183
|
+
// when the user has explicitly opted in via manifest.
|
|
184
|
+
const pbDirForManifest = join(cwd, '.productbrain');
|
|
185
|
+
const initManifest = readManifest(pbDirForManifest);
|
|
186
|
+
const multiSurfaceOptIns = [];
|
|
187
|
+
if (initManifest?.hooks?.cursor)
|
|
188
|
+
multiSurfaceOptIns.push('cursor');
|
|
189
|
+
if (initManifest?.hooks?.copilot)
|
|
190
|
+
multiSurfaceOptIns.push('copilot');
|
|
191
|
+
if (multiSurfaceOptIns.length > 0) {
|
|
192
|
+
console.log('');
|
|
193
|
+
for (const surface of multiSurfaceOptIns) {
|
|
194
|
+
const status = getHookStatusForSurface(surface);
|
|
195
|
+
if (status.writable) {
|
|
196
|
+
// Future-proofing path: surface has hook events, would write files.
|
|
197
|
+
console.log(`ℹ ${surface} hooks: opted in — hooks will be written`);
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
console.log(`ℹ ${surface} hooks: opted in — no auto-hooks (${surface} has no session events; run \`pb session start\` manually)`);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
// Step 3: Scaffold starter templates if .productbrain/rules/ is empty
|
|
205
|
+
const rulesDir = join(cwd, '.productbrain', 'rules');
|
|
206
|
+
const hasExistingRules = existsSync(rulesDir) && readdirSync(rulesDir).filter((f) => f.endsWith('.md')).length > 0;
|
|
207
|
+
if (!hasExistingRules) {
|
|
208
|
+
// Detect stack from repo to pick template set
|
|
209
|
+
const repo = detectRepo(cwd);
|
|
210
|
+
const stack = repo.detectedStack.map((s) => s.toLowerCase());
|
|
211
|
+
let templateSet;
|
|
212
|
+
if (stack.some((s) => ['typescript', 'sveltekit', 'nextjs', 'react'].includes(s))) {
|
|
213
|
+
templateSet = 'node-ts';
|
|
214
|
+
}
|
|
215
|
+
else if (stack.includes('python')) {
|
|
216
|
+
templateSet = 'python';
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
templateSet = 'general';
|
|
220
|
+
}
|
|
221
|
+
// Resolve templates directory relative to this file
|
|
222
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
223
|
+
const __dirname = dirname(__filename);
|
|
224
|
+
// From dist/commands/handshake.js → ../../templates/
|
|
225
|
+
const templatesRoot = resolve(__dirname, '..', '..', 'templates');
|
|
226
|
+
const templateDir = join(templatesRoot, templateSet);
|
|
227
|
+
if (existsSync(templateDir)) {
|
|
228
|
+
const templateFiles = readdirSync(templateDir).filter((f) => f.endsWith('.md'));
|
|
229
|
+
if (templateFiles.length > 0) {
|
|
230
|
+
console.log('');
|
|
231
|
+
console.log(`Scaffolding starter rules from ${templateSet} template...`);
|
|
232
|
+
if (!dryRun) {
|
|
233
|
+
mkdirSync(rulesDir, { recursive: true });
|
|
234
|
+
for (const file of templateFiles) {
|
|
235
|
+
const src = join(templateDir, file);
|
|
236
|
+
const dest = join(rulesDir, file);
|
|
237
|
+
copyFileSync(src, dest);
|
|
238
|
+
console.log(` + .productbrain/rules/${file}`);
|
|
239
|
+
}
|
|
240
|
+
console.log('');
|
|
241
|
+
console.log('Run `pb handshake` to sync the scaffolded rules to your AI tools.');
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
244
|
+
for (const file of templateFiles) {
|
|
245
|
+
console.log(` + .productbrain/rules/${file} (dry run)`);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Normalize volatile handshake-only timestamps before comparing generated files.
|
|
254
|
+
* This keeps the visible timestamps in generated artifacts while avoiding
|
|
255
|
+
* meaningless rewrites when semantic content is unchanged.
|
|
256
|
+
*/
|
|
257
|
+
export function normalizeHandshakeContentForComparison(content) {
|
|
258
|
+
return content
|
|
259
|
+
.replace(/<!-- auto-generated by pb handshake — [0-9]{4}-[0-9]{2}-[0-9]{2}T[^>]+ -->/g, '<!-- auto-generated by pb handshake — <TIMESTAMP> -->')
|
|
260
|
+
.replace(/^_Generated: [0-9]{4}-[0-9]{2}-[0-9]{2}T.*_$/gm, '_Generated: <TIMESTAMP>_');
|
|
197
261
|
}
|
|
198
262
|
function shouldWriteAdapter(filePath, force) {
|
|
199
263
|
if (force)
|
|
@@ -222,8 +286,12 @@ export async function runHandshake(options = {}) {
|
|
|
222
286
|
const cwd = process.cwd();
|
|
223
287
|
const force = options.force ?? false;
|
|
224
288
|
const dryRun = options.dryRun ?? false;
|
|
289
|
+
// Preview mode: default when neither --apply nor --dry-run is passed.
|
|
290
|
+
// --dry-run is kept as a backward-compat alias for preview (same behavior).
|
|
291
|
+
const preview = !options.apply && !dryRun;
|
|
225
292
|
const level = options.level;
|
|
226
293
|
const quiet = options.quiet ?? false;
|
|
294
|
+
const generate = options.generate ?? false;
|
|
227
295
|
const timestamp = new Date().toISOString();
|
|
228
296
|
// Helper: emit progress line only when not quiet (used when handshake is a sub-step)
|
|
229
297
|
const log = (msg) => { if (!quiet)
|
|
@@ -233,8 +301,11 @@ export async function runHandshake(options = {}) {
|
|
|
233
301
|
// Validate --level if provided (for handshake content filtering, not --init trust level)
|
|
234
302
|
const VALID_HANDSHAKE_LEVELS = ['beginner', 'intermediate', 'expert'];
|
|
235
303
|
if (level && !VALID_HANDSHAKE_LEVELS.includes(level)) {
|
|
236
|
-
|
|
237
|
-
|
|
304
|
+
throw new CLIError(`Unknown level "${level}".`, {
|
|
305
|
+
code: ErrorCode.VALIDATION_FAILED,
|
|
306
|
+
category: 'validation',
|
|
307
|
+
guidance: `Valid levels: ${VALID_HANDSHAKE_LEVELS.join(', ')}`,
|
|
308
|
+
});
|
|
238
309
|
}
|
|
239
310
|
// 1. Detect repo
|
|
240
311
|
const repo = detectRepo(cwd);
|
|
@@ -242,16 +313,30 @@ export async function runHandshake(options = {}) {
|
|
|
242
313
|
if (repo.detectedStack.length > 0) {
|
|
243
314
|
log(`Stack: ${repo.detectedStack.join(', ')}`);
|
|
244
315
|
}
|
|
245
|
-
// 2. Fetch orient view
|
|
316
|
+
// 2. Fetch orient view + workspace readiness in parallel (budget max +200ms added latency)
|
|
246
317
|
log('Fetching workspace context...');
|
|
247
318
|
let orientView = null;
|
|
319
|
+
let workspaceProfile = null;
|
|
248
320
|
try {
|
|
249
|
-
|
|
321
|
+
const workspaceReadinessPromise = kernelCall('chain.workspaceReadiness', {}).catch(() => null);
|
|
322
|
+
const [orientResult, readinessRaw] = await Promise.all([
|
|
323
|
+
kernelCall('chain.getOrientView', {}).catch((err) => {
|
|
324
|
+
logErr(`Warning: could not fetch workspace context — ${err instanceof Error ? err.message : err}`);
|
|
325
|
+
logErr('Continuing with limited context (Chain search + portable knowledge only).');
|
|
326
|
+
return null;
|
|
327
|
+
}),
|
|
328
|
+
workspaceReadinessPromise,
|
|
329
|
+
]);
|
|
330
|
+
orientView = orientResult;
|
|
331
|
+
workspaceProfile = extractWorkspaceProfile(readinessRaw);
|
|
250
332
|
}
|
|
251
333
|
catch (err) {
|
|
252
334
|
logErr(`Warning: could not fetch workspace context — ${err instanceof Error ? err.message : err}`);
|
|
253
335
|
logErr('Continuing with limited context (Chain search + portable knowledge only).');
|
|
254
336
|
}
|
|
337
|
+
if (workspaceProfile) {
|
|
338
|
+
log(`Workspace profile: stage=${workspaceProfile.stage}, entries=${workspaceProfile.totalEntries}, governance=${workspaceProfile.governanceMode}`);
|
|
339
|
+
}
|
|
255
340
|
// 3. Build search queries from repo context
|
|
256
341
|
const searchQueries = [];
|
|
257
342
|
if (repo.name && repo.name.length >= 2)
|
|
@@ -269,37 +354,200 @@ export async function runHandshake(options = {}) {
|
|
|
269
354
|
let matchedEntries = [];
|
|
270
355
|
if (uniqueQueries.length > 0) {
|
|
271
356
|
log(`Searching Chain for: ${uniqueQueries.join(', ')}...`);
|
|
272
|
-
const searchResults = await Promise.all(uniqueQueries.map((q) =>
|
|
357
|
+
const searchResults = await Promise.all(uniqueQueries.map((q) => kernelCall('chain.searchEntries', { query: q }).catch(() => [])));
|
|
273
358
|
matchedEntries = deduplicateEntries(searchResults.flat());
|
|
274
359
|
}
|
|
275
360
|
// 5. Read canonical skills & rules from .productbrain/
|
|
276
361
|
const pbDir = join(cwd, '.productbrain');
|
|
277
362
|
const allSkills = readCanonicalSkills(pbDir);
|
|
278
|
-
const
|
|
279
|
-
//
|
|
280
|
-
|
|
281
|
-
|
|
363
|
+
const manualRules = readCanonicalRules(pbDir);
|
|
364
|
+
// 5a. Optionally fetch and merge Chain-derived rules (--generate flag)
|
|
365
|
+
let chainRulesStats = null;
|
|
366
|
+
let chainGaps = [];
|
|
367
|
+
let allRules = manualRules;
|
|
368
|
+
if (generate) {
|
|
369
|
+
log('Generating Chain-derived rules...');
|
|
370
|
+
const chainResult = await generateChainRules(kernelCall, manualRules);
|
|
371
|
+
if (chainResult.sentinel) {
|
|
372
|
+
// MCP unavailable — inject sentinel rule and warn
|
|
373
|
+
allRules = [...manualRules, chainResult.sentinel];
|
|
374
|
+
logErr('Warning: Chain MCP unavailable — generated rules are disabled. Sentinel rule injected.');
|
|
375
|
+
}
|
|
376
|
+
else {
|
|
377
|
+
// Merge generated rules after manual rules (manual takes precedence on dedup)
|
|
378
|
+
allRules = [...manualRules, ...chainResult.rules];
|
|
379
|
+
chainRulesStats = chainResult.stats;
|
|
380
|
+
chainGaps = chainResult.gaps;
|
|
381
|
+
const { generatedRules, suppressedByManual, suppressedByZeroEntries } = chainResult.stats;
|
|
382
|
+
log(`Chain-derived rules: ${generatedRules} generated, ${suppressedByManual} suppressed by manual, ${suppressedByZeroEntries} gaps`);
|
|
383
|
+
if (chainGaps.length > 0) {
|
|
384
|
+
log(`Gaps (no matching governance entries): ${chainGaps.join(', ')}`);
|
|
385
|
+
}
|
|
386
|
+
// Diff: compare current state against previous run
|
|
387
|
+
const previousState = loadPreviousState(pbDir);
|
|
388
|
+
const currentState = buildCurrentState(chainResult.rules, chainResult.classified);
|
|
389
|
+
saveHandshakeState(pbDir, chainResult.rules, chainResult.classified);
|
|
390
|
+
const diff = diffHandshakeState(currentState, previousState);
|
|
391
|
+
const diffText = formatDiff(diff);
|
|
392
|
+
log(diffText);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
// 5b. Read personal layer (WP-310 E2) — machine-local rules/skills from .productbrain/.local/
|
|
396
|
+
// Returns [] when the directory is absent. All returned entries have persist: 'local'.
|
|
397
|
+
const personalRules = readPersonalLayer(pbDir);
|
|
398
|
+
if (personalRules.length > 0) {
|
|
399
|
+
// Name collision detection — warn when a personal rule overrides a team rule
|
|
400
|
+
const teamRuleNames = new Set(allRules.map((r) => r.name));
|
|
401
|
+
for (const pr of personalRules) {
|
|
402
|
+
if (teamRuleNames.has(pr.name)) {
|
|
403
|
+
logErr(`Personal rule "${pr.name}" overrides team rule (local takes precedence).`);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
// Merge: team rules first, personal rules appended (personal takes precedence via name collision above)
|
|
407
|
+
allRules = [...allRules, ...personalRules];
|
|
408
|
+
}
|
|
409
|
+
const personalSkills = readPersonalSkillsLayer(pbDir);
|
|
410
|
+
if (personalSkills.length > 0) {
|
|
411
|
+
const teamSkillNames = new Set(allSkills.map((s) => s.name));
|
|
412
|
+
for (const ps of personalSkills) {
|
|
413
|
+
if (teamSkillNames.has(ps.name)) {
|
|
414
|
+
logErr(`Personal skill "${ps.name}" overrides team skill (local takes precedence).`);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
allSkills.push(...personalSkills);
|
|
418
|
+
}
|
|
419
|
+
// 5c. Apply manifest-based adoption filter (WP-310 E1)
|
|
420
|
+
// readManifest returns null when manifest.yaml is absent → filterByAdoptionState is a no-op.
|
|
421
|
+
const manifest = readManifest(pbDir);
|
|
422
|
+
// 5d. Load method registry (WP-310 E4) — only when manifest is present.
|
|
423
|
+
let registrySource;
|
|
424
|
+
let registryStale;
|
|
425
|
+
if (manifest) {
|
|
426
|
+
const registryResult = await loadMethodRegistry(manifest.method_source, kernelCall).catch(() => null);
|
|
427
|
+
if (registryResult) {
|
|
428
|
+
registrySource = registryResult.source;
|
|
429
|
+
registryStale = registryResult.stale;
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
const adoptionFilteredSkills = filterByAdoptionState(allSkills, manifest);
|
|
433
|
+
const adoptionFilteredRules = filterByAdoptionState(allRules, manifest);
|
|
434
|
+
// Compute adoption counts for report (only meaningful when manifest is present)
|
|
435
|
+
const adoptedRulesCount = manifest ? adoptionFilteredRules.length : undefined;
|
|
436
|
+
const rejectedRulesCount = manifest ? allRules.length - adoptionFilteredRules.length : undefined;
|
|
437
|
+
// Apply level filtering with stage-gating (after adoption filter, before target filtering in write loop)
|
|
438
|
+
// Stage caps the effective level: blank→beginner, seed→intermediate, grounded+→expert.
|
|
439
|
+
// If stage caps below the requested level, log it so the user knows why items were dropped.
|
|
440
|
+
const profileStage = workspaceProfile?.stage;
|
|
441
|
+
const levelFilteredSkills = filterByLevel(adoptionFilteredSkills, level, profileStage);
|
|
442
|
+
const levelFilteredRules = filterByLevel(adoptionFilteredRules, level, profileStage);
|
|
443
|
+
// Log when stage gating changes the effective level
|
|
444
|
+
if (profileStage) {
|
|
445
|
+
const stageCap = STAGE_TO_MAX_LEVEL[profileStage];
|
|
446
|
+
if (stageCap) {
|
|
447
|
+
const requestedIdx = level ? LEVEL_ORDER.indexOf(level) : LEVEL_ORDER.length - 1;
|
|
448
|
+
const capIdx = LEVEL_ORDER.indexOf(stageCap);
|
|
449
|
+
if (capIdx < requestedIdx) {
|
|
450
|
+
log(`Stage "${profileStage}" caps level from ${level || 'expert'} to ${stageCap}`);
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
// Apply when-condition filtering (stage-aware, workspace profile + repo context)
|
|
455
|
+
const canonicalSkills = levelFilteredSkills.filter((skill) => {
|
|
456
|
+
const result = evaluateConditions(skill.conditions ?? {}, workspaceProfile, repo);
|
|
457
|
+
if (dryRun && !result.included) {
|
|
458
|
+
log(` EXCLUDED skill ${skill.name}: ${result.reasons.join(', ')}`);
|
|
459
|
+
}
|
|
460
|
+
return result.included;
|
|
461
|
+
});
|
|
462
|
+
const canonicalRules = levelFilteredRules.filter((rule) => {
|
|
463
|
+
const result = evaluateConditions(rule.conditions ?? {}, workspaceProfile, repo);
|
|
464
|
+
if (dryRun && !result.included) {
|
|
465
|
+
log(` EXCLUDED rule ${rule.name}: ${result.reasons.join(', ')}`);
|
|
466
|
+
}
|
|
467
|
+
return result.included;
|
|
468
|
+
});
|
|
469
|
+
if (dryRun && canonicalSkills.length > 0) {
|
|
470
|
+
log(` INCLUDED skills: ${canonicalSkills.map((s) => s.name).join(', ')}`);
|
|
471
|
+
}
|
|
472
|
+
if (dryRun && canonicalRules.length > 0) {
|
|
473
|
+
log(` INCLUDED rules: ${canonicalRules.map((r) => r.name).join(', ')}`);
|
|
474
|
+
}
|
|
282
475
|
if (canonicalSkills.length > 0 || canonicalRules.length > 0) {
|
|
283
476
|
const levelSuffix = level ? ` (level: ${level})` : '';
|
|
284
|
-
|
|
477
|
+
const stageSuffix = profileStage ? `, stage: ${profileStage}` : '';
|
|
478
|
+
const stackSuffix = repo.detectedStack.length > 0 ? `, stack: [${repo.detectedStack.join(', ')}]` : '';
|
|
479
|
+
const totalSkills = allSkills.length;
|
|
480
|
+
const totalRules = allRules.length;
|
|
481
|
+
log(`Portable knowledge: ${canonicalSkills.length}/${totalSkills} skills, ${canonicalRules.length}/${totalRules} rules${levelSuffix}${stageSuffix}${stackSuffix}`);
|
|
285
482
|
}
|
|
286
483
|
// 6. Generate file contents
|
|
287
|
-
|
|
484
|
+
// Build workspace context for AGENTS.md enrichment (stage, focus, governance, entry count)
|
|
485
|
+
const agentsWorkspaceContext = workspaceProfile
|
|
486
|
+
? {
|
|
487
|
+
stage: workspaceProfile.stage,
|
|
488
|
+
focus: orientView?.strategicContext?.currentBet ?? undefined,
|
|
489
|
+
governanceMode: workspaceProfile.governanceMode,
|
|
490
|
+
totalEntries: workspaceProfile.totalEntries,
|
|
491
|
+
}
|
|
492
|
+
: undefined;
|
|
493
|
+
// Collect codex-targeted skills for AGENTS.md skill directory
|
|
494
|
+
// Exclude persist: 'local' rules — committed adapter files must never include local-only rules.
|
|
495
|
+
const agentsCodexSkills = canonicalSkills
|
|
496
|
+
.filter((s) => shouldEmitToTarget(s, 'codex'))
|
|
497
|
+
.map((s) => ({
|
|
498
|
+
name: s.name,
|
|
499
|
+
description: s.description,
|
|
500
|
+
triggers: s.triggers,
|
|
501
|
+
}));
|
|
502
|
+
// Collect copilot-targeted skills for copilot-instructions.md skill summaries
|
|
503
|
+
const copilotSkills = canonicalSkills
|
|
504
|
+
.filter((s) => shouldEmitToTarget(s, 'copilot'))
|
|
505
|
+
.map((s) => ({
|
|
506
|
+
name: s.name,
|
|
507
|
+
description: s.description,
|
|
508
|
+
triggers: s.triggers,
|
|
509
|
+
}));
|
|
510
|
+
// Collect copilot-targeted rules for copilot-instructions.md rule summaries
|
|
511
|
+
const copilotRules = canonicalRules
|
|
512
|
+
.filter((r) => shouldEmitToTarget(r, 'copilot'))
|
|
513
|
+
.map((r) => ({
|
|
514
|
+
name: r.name,
|
|
515
|
+
description: r.description,
|
|
516
|
+
}));
|
|
517
|
+
const copilotProfile = resolveSurfaceProfile('copilot');
|
|
518
|
+
const copilotOptions = {
|
|
519
|
+
profile: copilotProfile,
|
|
520
|
+
workspaceContext: agentsWorkspaceContext,
|
|
521
|
+
skills: copilotSkills.length > 0 ? copilotSkills : undefined,
|
|
522
|
+
rules: copilotRules.length > 0 ? copilotRules : undefined,
|
|
523
|
+
};
|
|
524
|
+
const contextContent = orientView ? generateContextMd(orientView, repo, timestamp, workspaceProfile?.stage) : null;
|
|
288
525
|
const briefingContent = generateBriefingMd(matchedEntries, repo, uniqueQueries, timestamp);
|
|
526
|
+
const agentsContent = generateAgentsMd(timestamp, {
|
|
527
|
+
workspaceContext: agentsWorkspaceContext,
|
|
528
|
+
skills: agentsCodexSkills.length > 0 ? agentsCodexSkills : undefined,
|
|
529
|
+
});
|
|
289
530
|
const claudeContent = generateClaudeMd(timestamp);
|
|
290
531
|
const cursorContent = generateCursorMdc(timestamp);
|
|
291
|
-
const copilotContent = generateCopilotMd(timestamp);
|
|
532
|
+
const copilotContent = generateCopilotMd(timestamp, copilotOptions);
|
|
292
533
|
// 7. Write files
|
|
293
534
|
const filesWritten = [];
|
|
294
535
|
const filesSkipped = [];
|
|
536
|
+
const previewPlan = [];
|
|
537
|
+
// Surface filtering: skip adapter writes for targets not in the allowed set
|
|
538
|
+
const allowedTargets = options.surfaces && options.surfaces.length > 0
|
|
539
|
+
? new Set(options.surfaces)
|
|
540
|
+
: null; // null = write all
|
|
295
541
|
const writes = [
|
|
296
542
|
...(contextContent ? [{ path: join(cwd, '.productbrain', 'context.md'), relative: '.productbrain/context.md', content: contextContent, dirs: join(cwd, '.productbrain'), isAdapter: false }] : []),
|
|
297
543
|
{ path: join(cwd, '.productbrain', 'briefing.md'), relative: '.productbrain/briefing.md', content: briefingContent, isAdapter: false },
|
|
298
|
-
{ path: join(cwd, '
|
|
299
|
-
{ path: join(cwd, '.
|
|
300
|
-
{ path: join(cwd, '.
|
|
544
|
+
{ path: join(cwd, 'AGENTS.md'), relative: 'AGENTS.md', content: agentsContent, isAdapter: true, target: 'codex' },
|
|
545
|
+
{ path: join(cwd, 'CLAUDE.md'), relative: 'CLAUDE.md', content: claudeContent, isAdapter: true, target: 'claude' },
|
|
546
|
+
{ path: join(cwd, '.cursor', 'rules', 'chain.mdc'), relative: '.cursor/rules/chain.mdc', content: cursorContent, dirs: join(cwd, '.cursor', 'rules'), isAdapter: true, target: 'cursor' },
|
|
547
|
+
{ path: join(cwd, '.github', 'copilot-instructions.md'), relative: '.github/copilot-instructions.md', content: copilotContent, dirs: join(cwd, '.github'), isAdapter: true, target: 'copilot' },
|
|
301
548
|
];
|
|
302
549
|
// Add Cursor skill copies (filtered by target)
|
|
550
|
+
const cursorProfile = resolveSurfaceProfile('cursor');
|
|
303
551
|
for (const skill of canonicalSkills) {
|
|
304
552
|
if (!shouldEmitToTarget(skill, 'cursor'))
|
|
305
553
|
continue;
|
|
@@ -307,11 +555,35 @@ export async function runHandshake(options = {}) {
|
|
|
307
555
|
writes.push({
|
|
308
556
|
path: join(skillDir, 'SKILL.md'),
|
|
309
557
|
relative: `.cursor/skills/${skill.name}/SKILL.md`,
|
|
310
|
-
content: generateCursorSkill(skill),
|
|
558
|
+
content: generateCursorSkill(skill, cursorProfile),
|
|
311
559
|
dirs: skillDir,
|
|
312
560
|
isAdapter: true,
|
|
561
|
+
target: 'cursor',
|
|
313
562
|
});
|
|
314
563
|
}
|
|
564
|
+
// Add Codex skill copies (projected markdown + index)
|
|
565
|
+
const codexProfile = resolveSurfaceProfile('codex');
|
|
566
|
+
const codexSkills = canonicalSkills.filter((s) => shouldEmitToTarget(s, 'codex'));
|
|
567
|
+
for (const skill of codexSkills) {
|
|
568
|
+
writes.push({
|
|
569
|
+
path: join(cwd, '.codex', 'skills', `${skill.name}.md`),
|
|
570
|
+
relative: `.codex/skills/${skill.name}.md`,
|
|
571
|
+
content: generateCodexSkill(skill, codexProfile),
|
|
572
|
+
dirs: join(cwd, '.codex', 'skills'),
|
|
573
|
+
isAdapter: true,
|
|
574
|
+
target: 'codex',
|
|
575
|
+
});
|
|
576
|
+
}
|
|
577
|
+
writes.push({
|
|
578
|
+
path: join(cwd, '.codex', 'skills', 'README.md'),
|
|
579
|
+
relative: '.codex/skills/README.md',
|
|
580
|
+
content: generateCodexSkillIndex(codexSkills),
|
|
581
|
+
dirs: join(cwd, '.codex', 'skills'),
|
|
582
|
+
isAdapter: true,
|
|
583
|
+
target: 'codex',
|
|
584
|
+
});
|
|
585
|
+
// Validate Codex-projected skills for dead references
|
|
586
|
+
const codexWarnings = validateCodexSkills(codexSkills);
|
|
315
587
|
// Add Cursor rule copies (filtered by target)
|
|
316
588
|
for (const rule of canonicalRules) {
|
|
317
589
|
if (!shouldEmitToTarget(rule, 'cursor'))
|
|
@@ -319,26 +591,29 @@ export async function runHandshake(options = {}) {
|
|
|
319
591
|
writes.push({
|
|
320
592
|
path: join(cwd, '.cursor', 'rules', `${rule.name}.mdc`),
|
|
321
593
|
relative: `.cursor/rules/${rule.name}.mdc`,
|
|
322
|
-
content: generateCursorRule(rule),
|
|
594
|
+
content: generateCursorRule(rule, cursorProfile),
|
|
323
595
|
dirs: join(cwd, '.cursor', 'rules'),
|
|
324
596
|
isAdapter: true,
|
|
597
|
+
target: 'cursor',
|
|
325
598
|
});
|
|
326
599
|
}
|
|
327
600
|
// Add Claude Code rule copies (filtered by target)
|
|
601
|
+
const claudeProfile = resolveSurfaceProfile('claude');
|
|
328
602
|
for (const rule of canonicalRules) {
|
|
329
603
|
if (!shouldEmitToTarget(rule, 'claude'))
|
|
330
604
|
continue;
|
|
331
605
|
writes.push({
|
|
332
606
|
path: join(cwd, '.claude', 'rules', `${rule.name}.md`),
|
|
333
607
|
relative: `.claude/rules/${rule.name}.md`,
|
|
334
|
-
content: generateClaudeRule(rule),
|
|
608
|
+
content: generateClaudeRule(rule, claudeProfile),
|
|
335
609
|
dirs: join(cwd, '.claude', 'rules'),
|
|
336
610
|
isAdapter: true,
|
|
611
|
+
target: 'claude',
|
|
337
612
|
});
|
|
338
613
|
}
|
|
339
614
|
// Add Claude Code skill router (filtered by target)
|
|
340
615
|
const claudeSkills = canonicalSkills.filter((s) => shouldEmitToTarget(s, 'claude'));
|
|
341
|
-
const skillRouterContent = generateClaudeSkillRouter(claudeSkills);
|
|
616
|
+
const skillRouterContent = generateClaudeSkillRouter(claudeSkills, claudeProfile);
|
|
342
617
|
if (skillRouterContent) {
|
|
343
618
|
writes.push({
|
|
344
619
|
path: join(cwd, '.claude', 'rules', 'skill-router.md'),
|
|
@@ -346,29 +621,102 @@ export async function runHandshake(options = {}) {
|
|
|
346
621
|
content: skillRouterContent,
|
|
347
622
|
dirs: join(cwd, '.claude', 'rules'),
|
|
348
623
|
isAdapter: true,
|
|
624
|
+
target: 'claude',
|
|
349
625
|
});
|
|
350
626
|
}
|
|
627
|
+
const forkedPaths = [];
|
|
351
628
|
for (const w of writes) {
|
|
629
|
+
// Surface filtering: skip adapter writes for targets not in the allowed set
|
|
630
|
+
if (allowedTargets && w.target && !allowedTargets.has(w.target)) {
|
|
631
|
+
filesSkipped.push({ path: w.relative, reason: `filtered (surface: ${w.target})` });
|
|
632
|
+
if (preview)
|
|
633
|
+
previewPlan.push({ path: w.relative, status: 'filtered' });
|
|
634
|
+
continue;
|
|
635
|
+
}
|
|
352
636
|
if (w.isAdapter && !shouldWriteAdapter(w.path, force)) {
|
|
353
637
|
filesSkipped.push({ path: w.relative, reason: 'exists without auto-generated marker (use --force to overwrite)' });
|
|
638
|
+
if (preview) {
|
|
639
|
+
previewPlan.push({ path: w.relative, status: 'forked' });
|
|
640
|
+
}
|
|
641
|
+
else {
|
|
642
|
+
forkedPaths.push(w.relative);
|
|
643
|
+
}
|
|
354
644
|
continue;
|
|
355
645
|
}
|
|
356
|
-
if (dryRun) {
|
|
357
|
-
|
|
646
|
+
if (preview || dryRun) {
|
|
647
|
+
// In preview/dry-run mode: check content to distinguish new/update/unchanged
|
|
648
|
+
if (existsSync(w.path)) {
|
|
649
|
+
const current = readFileSync(w.path, 'utf8');
|
|
650
|
+
const nextNormalized = normalizeHandshakeContentForComparison(w.content);
|
|
651
|
+
const currentNormalized = normalizeHandshakeContentForComparison(current);
|
|
652
|
+
if (nextNormalized === currentNormalized) {
|
|
653
|
+
filesSkipped.push({ path: w.relative, reason: 'unchanged' });
|
|
654
|
+
if (preview)
|
|
655
|
+
previewPlan.push({ path: w.relative, status: 'unchanged' });
|
|
656
|
+
}
|
|
657
|
+
else {
|
|
658
|
+
filesWritten.push(w.relative + (dryRun ? ' (dry run)' : ''));
|
|
659
|
+
if (preview)
|
|
660
|
+
previewPlan.push({ path: w.relative, status: 'would-update' });
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
else {
|
|
664
|
+
filesWritten.push(w.relative + (dryRun ? ' (dry run)' : ''));
|
|
665
|
+
if (preview)
|
|
666
|
+
previewPlan.push({ path: w.relative, status: 'would-write' });
|
|
667
|
+
}
|
|
358
668
|
continue;
|
|
359
669
|
}
|
|
360
670
|
if (w.dirs)
|
|
361
671
|
mkdirSync(w.dirs, { recursive: true });
|
|
672
|
+
if (existsSync(w.path)) {
|
|
673
|
+
const current = readFileSync(w.path, 'utf8');
|
|
674
|
+
const nextNormalized = normalizeHandshakeContentForComparison(w.content);
|
|
675
|
+
const currentNormalized = normalizeHandshakeContentForComparison(current);
|
|
676
|
+
if (nextNormalized === currentNormalized) {
|
|
677
|
+
filesSkipped.push({ path: w.relative, reason: 'unchanged' });
|
|
678
|
+
continue;
|
|
679
|
+
}
|
|
680
|
+
}
|
|
362
681
|
writeFileSync(w.path, w.content);
|
|
363
682
|
filesWritten.push(w.relative);
|
|
364
683
|
}
|
|
365
|
-
// 8.
|
|
684
|
+
// 8. Drift logging — if apply mode encountered forked adapters and a session is active, log a draft TEN
|
|
685
|
+
if (forkedPaths.length > 0) {
|
|
686
|
+
const session = readSession();
|
|
687
|
+
if (session) {
|
|
688
|
+
const names = forkedPaths.join(', ');
|
|
689
|
+
kernelCallWithSession('chain.createEntry', {
|
|
690
|
+
collectionSlug: 'tensions',
|
|
691
|
+
name: `TEN: handshake drift — ${forkedPaths.length} adapter(s) forked, sync blocked`,
|
|
692
|
+
status: 'draft',
|
|
693
|
+
data: {
|
|
694
|
+
description: `pb handshake --apply encountered forked adapters that blocked sync. Files: ${names}. Use --force to overwrite or resolve drift manually.`,
|
|
695
|
+
},
|
|
696
|
+
sessionId: session.sessionId,
|
|
697
|
+
createdBy: `agent:${session.sessionId}`,
|
|
698
|
+
}).catch(() => { });
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
// 9. Report
|
|
366
702
|
const report = {
|
|
367
703
|
filesWritten,
|
|
368
704
|
filesSkipped,
|
|
369
705
|
matchedEntries,
|
|
370
706
|
searchQueries: uniqueQueries,
|
|
371
707
|
repo,
|
|
708
|
+
codexWarnings: codexWarnings.length > 0 ? codexWarnings : undefined,
|
|
709
|
+
chainRulesStats: chainRulesStats ?? undefined,
|
|
710
|
+
chainGaps: chainGaps.length > 0 ? chainGaps : undefined,
|
|
711
|
+
adoptedCount: adoptedRulesCount,
|
|
712
|
+
rejectedCount: rejectedRulesCount,
|
|
713
|
+
personalRuleCount: personalRules.length > 0 ? personalRules.length : undefined,
|
|
714
|
+
personalSkillCount: personalSkills.length > 0 ? personalSkills.length : undefined,
|
|
715
|
+
registrySource,
|
|
716
|
+
registryStale,
|
|
717
|
+
preview: preview ? true : undefined,
|
|
718
|
+
previewPlan: preview && previewPlan.length > 0 ? previewPlan : undefined,
|
|
719
|
+
driftConflicts: forkedPaths.length > 0 ? forkedPaths : undefined,
|
|
372
720
|
};
|
|
373
721
|
if (!quiet) {
|
|
374
722
|
process.stdout.write('\n');
|