@productbrain/cli 0.1.0-beta.9 → 0.1.0-beta.90
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,6 +2,12 @@
|
|
|
2
2
|
* Portable knowledge — reads canonical skills/rules from .productbrain/
|
|
3
3
|
* and generates tool-specific copies for Cursor, Claude Code, etc.
|
|
4
4
|
*/
|
|
5
|
+
import type { SurfaceProfile } from './surface-profiles.js';
|
|
6
|
+
export interface WhenConditions {
|
|
7
|
+
when_stack?: string;
|
|
8
|
+
when_minStage?: string;
|
|
9
|
+
when_minGovernance?: string;
|
|
10
|
+
}
|
|
5
11
|
export interface CanonicalSkill {
|
|
6
12
|
name: string;
|
|
7
13
|
description: string;
|
|
@@ -10,6 +16,9 @@ export interface CanonicalSkill {
|
|
|
10
16
|
sourcePath: string;
|
|
11
17
|
targets?: string[];
|
|
12
18
|
level?: string;
|
|
19
|
+
conditions?: WhenConditions;
|
|
20
|
+
/** 'team' = default (projected to committed adapter files); 'local' = local surface files only, never committed. */
|
|
21
|
+
persist?: 'local' | 'team';
|
|
13
22
|
}
|
|
14
23
|
export interface CanonicalRule {
|
|
15
24
|
name: string;
|
|
@@ -20,22 +29,69 @@ export interface CanonicalRule {
|
|
|
20
29
|
sourcePath: string;
|
|
21
30
|
targets?: string[];
|
|
22
31
|
level?: string;
|
|
32
|
+
conditions?: WhenConditions;
|
|
33
|
+
/** 'team' = default (projected to committed adapter files); 'local' = local surface files only, never committed. */
|
|
34
|
+
persist?: 'local' | 'team';
|
|
23
35
|
}
|
|
24
|
-
export type TargetName = 'cursor' | 'claude' | 'copilot';
|
|
36
|
+
export type TargetName = 'cursor' | 'claude' | 'copilot' | 'codex';
|
|
37
|
+
/**
|
|
38
|
+
* Returns true if the rule has persist: 'local'.
|
|
39
|
+
* Local rules are written to local surface files (.claude/rules/, .cursor/rules/)
|
|
40
|
+
* but must never be projected to committed adapter files (CLAUDE.md, AGENTS.md, etc.).
|
|
41
|
+
*/
|
|
42
|
+
export declare function isPersistLocal(rule: CanonicalRule): boolean;
|
|
25
43
|
/** Returns true if the entry should be emitted to the given target. */
|
|
26
44
|
export declare function shouldEmitToTarget(entry: CanonicalRule | CanonicalSkill, target: TargetName): boolean;
|
|
27
45
|
export type HandshakeLevel = 'beginner' | 'intermediate' | 'expert';
|
|
28
46
|
/**
|
|
29
|
-
*
|
|
30
|
-
*
|
|
47
|
+
* Maps workspace stage to the maximum allowed HandshakeLevel.
|
|
48
|
+
* Stages not listed here apply no cap (fail-open for unknown stages).
|
|
49
|
+
* Note: 'beginner' level allows only 'core' items; 'intermediate' allows core + intermediate.
|
|
50
|
+
*/
|
|
51
|
+
export declare const STAGE_TO_MAX_LEVEL: Record<string, HandshakeLevel>;
|
|
52
|
+
/** Level ordering used to pick the more restrictive of two levels. */
|
|
53
|
+
export declare const LEVEL_ORDER: HandshakeLevel[];
|
|
54
|
+
/**
|
|
55
|
+
* Filter items by graduated level, with optional workspace stage-gating.
|
|
56
|
+
* - If requestedLevel is undefined/null AND stage provides no cap: return ALL items (backward compat).
|
|
31
57
|
* - Items with no `level` field: always included (backward compat).
|
|
32
|
-
* -
|
|
58
|
+
* - Stage caps the effective level: blank→beginner, seed→intermediate, grounded/connected/critical→expert.
|
|
59
|
+
* - If stage is unknown or null: no cap applied (fail-open).
|
|
60
|
+
* - The effective level is min(requestedLevel, stageCap) — most restrictive wins.
|
|
33
61
|
*/
|
|
34
62
|
export declare function filterByLevel<T extends {
|
|
35
63
|
level?: string;
|
|
36
|
-
}>(items: T[], requestedLevel?: string): T[];
|
|
64
|
+
}>(items: T[], requestedLevel?: string, stage?: string): T[];
|
|
65
|
+
/**
|
|
66
|
+
* Evaluate when_* conditions against the workspace profile and repo context.
|
|
67
|
+
* Returns { included, reasons }.
|
|
68
|
+
*
|
|
69
|
+
* Fail-open: if profile is null and profile-dependent conditions are present,
|
|
70
|
+
* the item is included (preserves current behavior when Chain is unavailable).
|
|
71
|
+
*/
|
|
72
|
+
export declare function evaluateConditions(conditions: WhenConditions, profile: {
|
|
73
|
+
stage: string;
|
|
74
|
+
totalRelations: number;
|
|
75
|
+
} | null, repoContext: {
|
|
76
|
+
detectedStack: string[];
|
|
77
|
+
}): {
|
|
78
|
+
included: boolean;
|
|
79
|
+
reasons: string[];
|
|
80
|
+
};
|
|
37
81
|
export declare function readCanonicalSkills(productbrainDir: string): CanonicalSkill[];
|
|
38
82
|
export declare function readCanonicalRules(productbrainDir: string): CanonicalRule[];
|
|
83
|
+
/**
|
|
84
|
+
* Read machine-local personal rules from .productbrain/.local/rules/.
|
|
85
|
+
* Returns [] when the directory is absent — no-op when personal layer is not set up.
|
|
86
|
+
* Every returned rule has persist: 'local' set, preventing projection to committed adapter files.
|
|
87
|
+
*/
|
|
88
|
+
export declare function readPersonalLayer(productbrainDir: string): CanonicalRule[];
|
|
89
|
+
/**
|
|
90
|
+
* Read machine-local personal skills from .productbrain/.local/skills/.
|
|
91
|
+
* Returns [] when the directory is absent — no-op when personal layer is not set up.
|
|
92
|
+
* Every returned skill has persist: 'local' set, preventing projection to committed adapter files.
|
|
93
|
+
*/
|
|
94
|
+
export declare function readPersonalSkillsLayer(productbrainDir: string): CanonicalSkill[];
|
|
39
95
|
/**
|
|
40
96
|
* Strip transport-conditional sections from a skill body.
|
|
41
97
|
*
|
|
@@ -53,20 +109,57 @@ export declare function stripTransportSections(body: string, target: TargetName)
|
|
|
53
109
|
* Generate a Cursor SKILL.md from a canonical skill.
|
|
54
110
|
* Cursor expects: name, description (with triggers embedded).
|
|
55
111
|
*/
|
|
56
|
-
export declare function generateCursorSkill(skill: CanonicalSkill): string;
|
|
112
|
+
export declare function generateCursorSkill(skill: CanonicalSkill, profile?: SurfaceProfile): string;
|
|
57
113
|
/**
|
|
58
114
|
* Generate a Cursor .mdc rule from a canonical rule.
|
|
59
115
|
* Cursor expects: description, globs, alwaysApply.
|
|
60
116
|
*/
|
|
61
|
-
export declare function generateCursorRule(rule: CanonicalRule): string;
|
|
117
|
+
export declare function generateCursorRule(rule: CanonicalRule, profile?: SurfaceProfile): string;
|
|
118
|
+
/**
|
|
119
|
+
* Apply batch-mode transformations to a skill body (DEC-283).
|
|
120
|
+
*
|
|
121
|
+
* Skills describe WHAT (intent). This generator produces HOW (batch-appropriate
|
|
122
|
+
* instructions). We transform interactive patterns without gutting the skill's
|
|
123
|
+
* logical structure and purpose.
|
|
124
|
+
*
|
|
125
|
+
* Transformations applied:
|
|
126
|
+
* 1. Strip sub-agent spawn patterns → inline steps
|
|
127
|
+
* 2. Strip user confirmation gates → autonomous proceed
|
|
128
|
+
* 3. Strip streaming/interactive references
|
|
129
|
+
* 4. Add batch governance header after first `#` heading
|
|
130
|
+
*/
|
|
131
|
+
export declare function applyBatchTransformations(body: string): string;
|
|
132
|
+
/**
|
|
133
|
+
* Generate a Codex skill projection from a canonical skill.
|
|
134
|
+
* This is a repo-local markdown projection, not a separate authoring source.
|
|
135
|
+
*
|
|
136
|
+
* When profile.executionModel === 'batch', batch transformations are applied
|
|
137
|
+
* AFTER transport stripping and path replacement (DEC-283).
|
|
138
|
+
*/
|
|
139
|
+
export declare function generateCodexSkill(skill: CanonicalSkill, profile?: SurfaceProfile): string;
|
|
140
|
+
/**
|
|
141
|
+
* Generate a Codex skill index/router file.
|
|
142
|
+
* AGENTS.md can point here so Codex has one obvious place to find available workflows.
|
|
143
|
+
*/
|
|
144
|
+
export declare function generateCodexSkillIndex(skills: CanonicalSkill[]): string;
|
|
145
|
+
export interface CodexValidationWarning {
|
|
146
|
+
skillName: string;
|
|
147
|
+
pattern: string;
|
|
148
|
+
line: string;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Validate Codex-projected skills for references to capabilities Codex cannot execute.
|
|
152
|
+
* Scans the transport-stripped body (so claude-only blocks don't false-positive).
|
|
153
|
+
*/
|
|
154
|
+
export declare function validateCodexSkills(skills: CanonicalSkill[]): CodexValidationWarning[];
|
|
62
155
|
/**
|
|
63
156
|
* Generate a Claude Code .md rule from a canonical rule.
|
|
64
157
|
* Claude Code expects: description, optional paths (array).
|
|
65
158
|
*/
|
|
66
|
-
export declare function generateClaudeRule(rule: CanonicalRule): string;
|
|
159
|
+
export declare function generateClaudeRule(rule: CanonicalRule, profile?: SurfaceProfile): string;
|
|
67
160
|
/**
|
|
68
161
|
* Generate a Claude Code skill-router.md — imperative skill activation rule.
|
|
69
162
|
* Loaded automatically by Claude Code via .claude/rules/ with no paths (always active).
|
|
70
163
|
*/
|
|
71
|
-
export declare function generateClaudeSkillRouter(skills: CanonicalSkill[]): string;
|
|
164
|
+
export declare function generateClaudeSkillRouter(skills: CanonicalSkill[], profile?: SurfaceProfile): string;
|
|
72
165
|
//# sourceMappingURL=portable-knowledge.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"portable-knowledge.d.ts","sourceRoot":"","sources":["../../src/generators/portable-knowledge.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"portable-knowledge.d.ts","sourceRoot":"","sources":["../../src/generators/portable-knowledge.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,8 +5,25 @@
|
|
|
5
5
|
import { readdirSync, readFileSync, existsSync } from 'fs';
|
|
6
6
|
import { join, basename } from 'path';
|
|
7
7
|
import { MARKER } from './adapters.js';
|
|
8
|
+
/**
|
|
9
|
+
* Committed adapter targets — these correspond to files that are checked into the repo.
|
|
10
|
+
* Rules with persist: 'local' must never be included in arrays that feed these targets.
|
|
11
|
+
*/
|
|
12
|
+
const COMMITTED_ADAPTER_TARGETS = new Set(['copilot', 'codex']);
|
|
13
|
+
/**
|
|
14
|
+
* Returns true if the rule has persist: 'local'.
|
|
15
|
+
* Local rules are written to local surface files (.claude/rules/, .cursor/rules/)
|
|
16
|
+
* but must never be projected to committed adapter files (CLAUDE.md, AGENTS.md, etc.).
|
|
17
|
+
*/
|
|
18
|
+
export function isPersistLocal(rule) {
|
|
19
|
+
return rule.persist === 'local';
|
|
20
|
+
}
|
|
8
21
|
/** Returns true if the entry should be emitted to the given target. */
|
|
9
22
|
export function shouldEmitToTarget(entry, target) {
|
|
23
|
+
// Local rules must not go to committed adapter targets (copilot, codex)
|
|
24
|
+
if ('persist' in entry && entry.persist === 'local' && COMMITTED_ADAPTER_TARGETS.has(target)) {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
10
27
|
if (!entry.targets)
|
|
11
28
|
return true;
|
|
12
29
|
return entry.targets.includes(target);
|
|
@@ -18,20 +35,120 @@ const LEVEL_HIERARCHY = {
|
|
|
18
35
|
};
|
|
19
36
|
const VALID_LEVELS = new Set(Object.keys(LEVEL_HIERARCHY));
|
|
20
37
|
/**
|
|
21
|
-
*
|
|
22
|
-
*
|
|
38
|
+
* Maps workspace stage to the maximum allowed HandshakeLevel.
|
|
39
|
+
* Stages not listed here apply no cap (fail-open for unknown stages).
|
|
40
|
+
* Note: 'beginner' level allows only 'core' items; 'intermediate' allows core + intermediate.
|
|
41
|
+
*/
|
|
42
|
+
export const STAGE_TO_MAX_LEVEL = {
|
|
43
|
+
blank: 'beginner',
|
|
44
|
+
seed: 'intermediate',
|
|
45
|
+
grounded: 'expert',
|
|
46
|
+
connected: 'expert',
|
|
47
|
+
critical: 'expert',
|
|
48
|
+
};
|
|
49
|
+
/** Level ordering used to pick the more restrictive of two levels. */
|
|
50
|
+
export const LEVEL_ORDER = ['beginner', 'intermediate', 'expert'];
|
|
51
|
+
/**
|
|
52
|
+
* Pick the more restrictive of two levels.
|
|
53
|
+
* If either is undefined, returns the other (or undefined if both are).
|
|
54
|
+
*/
|
|
55
|
+
function capLevel(requested, cap) {
|
|
56
|
+
if (!requested && !cap)
|
|
57
|
+
return undefined;
|
|
58
|
+
if (!requested)
|
|
59
|
+
return cap;
|
|
60
|
+
if (!cap)
|
|
61
|
+
return requested;
|
|
62
|
+
const requestedIdx = LEVEL_ORDER.indexOf(requested);
|
|
63
|
+
const capIdx = LEVEL_ORDER.indexOf(cap);
|
|
64
|
+
return LEVEL_ORDER[Math.min(requestedIdx, capIdx)];
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Filter items by graduated level, with optional workspace stage-gating.
|
|
68
|
+
* - If requestedLevel is undefined/null AND stage provides no cap: return ALL items (backward compat).
|
|
23
69
|
* - Items with no `level` field: always included (backward compat).
|
|
24
|
-
* -
|
|
70
|
+
* - Stage caps the effective level: blank→beginner, seed→intermediate, grounded/connected/critical→expert.
|
|
71
|
+
* - If stage is unknown or null: no cap applied (fail-open).
|
|
72
|
+
* - The effective level is min(requestedLevel, stageCap) — most restrictive wins.
|
|
25
73
|
*/
|
|
26
|
-
export function filterByLevel(items, requestedLevel) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
if
|
|
30
|
-
|
|
74
|
+
export function filterByLevel(items, requestedLevel, stage) {
|
|
75
|
+
// Resolve stage cap (fail-open for unknown/undefined stage)
|
|
76
|
+
const stageCap = stage ? STAGE_TO_MAX_LEVEL[stage] : undefined;
|
|
77
|
+
// Resolve requested level as typed enum (validate if provided)
|
|
78
|
+
let typedRequested;
|
|
79
|
+
if (requestedLevel) {
|
|
80
|
+
if (!VALID_LEVELS.has(requestedLevel)) {
|
|
81
|
+
throw new Error(`Unknown level "${requestedLevel}". Valid levels: ${[...VALID_LEVELS].join(', ')}`);
|
|
82
|
+
}
|
|
83
|
+
typedRequested = requestedLevel;
|
|
31
84
|
}
|
|
32
|
-
|
|
85
|
+
// Determine effective level (most restrictive)
|
|
86
|
+
const effectiveLevel = capLevel(typedRequested, stageCap);
|
|
87
|
+
// No effective level — return all items (backward compat)
|
|
88
|
+
if (!effectiveLevel)
|
|
89
|
+
return items;
|
|
90
|
+
const allowedLevels = LEVEL_HIERARCHY[effectiveLevel];
|
|
33
91
|
return items.filter((item) => !item.level || allowedLevels.includes(item.level));
|
|
34
92
|
}
|
|
93
|
+
// ── Stage ordering ────────────────────────────────────────────────────
|
|
94
|
+
const STAGE_ORDER = ['blank', 'seed', 'grounded', 'connected', 'critical'];
|
|
95
|
+
/**
|
|
96
|
+
* Evaluate when_* conditions against the workspace profile and repo context.
|
|
97
|
+
* Returns { included, reasons }.
|
|
98
|
+
*
|
|
99
|
+
* Fail-open: if profile is null and profile-dependent conditions are present,
|
|
100
|
+
* the item is included (preserves current behavior when Chain is unavailable).
|
|
101
|
+
*/
|
|
102
|
+
export function evaluateConditions(conditions, profile, repoContext) {
|
|
103
|
+
const hasProfileConditions = conditions.when_minStage !== undefined || conditions.when_minGovernance !== undefined;
|
|
104
|
+
const hasStackCondition = conditions.when_stack !== undefined;
|
|
105
|
+
// No when_* keys at all — always include
|
|
106
|
+
if (!hasProfileConditions && !hasStackCondition) {
|
|
107
|
+
return { included: true, reasons: ['no conditions'] };
|
|
108
|
+
}
|
|
109
|
+
// Fail-open: profile unavailable but profile-dependent conditions present
|
|
110
|
+
if (profile === null && hasProfileConditions) {
|
|
111
|
+
return { included: true, reasons: ['no workspace profile — fail-open'] };
|
|
112
|
+
}
|
|
113
|
+
const reasons = [];
|
|
114
|
+
let included = true;
|
|
115
|
+
// when_stack: evaluated against repoContext (not profile)
|
|
116
|
+
if (conditions.when_stack !== undefined) {
|
|
117
|
+
const needle = conditions.when_stack.toLowerCase();
|
|
118
|
+
const match = repoContext.detectedStack.some((s) => s.toLowerCase() === needle);
|
|
119
|
+
if (!match) {
|
|
120
|
+
included = false;
|
|
121
|
+
reasons.push(`when_stack=${conditions.when_stack} not in detected stack [${repoContext.detectedStack.join(', ')}]`);
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
reasons.push(`when_stack=${conditions.when_stack} matched`);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// when_minStage: profile guaranteed non-null here when this condition is present
|
|
128
|
+
if (conditions.when_minStage !== undefined && profile !== null) {
|
|
129
|
+
const profileIdx = STAGE_ORDER.indexOf(profile.stage);
|
|
130
|
+
const thresholdIdx = STAGE_ORDER.indexOf(conditions.when_minStage);
|
|
131
|
+
if (thresholdIdx === -1 || profileIdx === -1 || profileIdx < thresholdIdx) {
|
|
132
|
+
included = false;
|
|
133
|
+
reasons.push(`when_minStage=${conditions.when_minStage} but workspace stage=${profile.stage}`);
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
reasons.push(`when_minStage=${conditions.when_minStage} satisfied (stage=${profile.stage})`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// when_minGovernance: profile guaranteed non-null here when this condition is present
|
|
140
|
+
if (conditions.when_minGovernance !== undefined && profile !== null) {
|
|
141
|
+
const threshold = parseInt(conditions.when_minGovernance, 10);
|
|
142
|
+
if (isNaN(threshold) || profile.totalRelations < threshold) {
|
|
143
|
+
included = false;
|
|
144
|
+
reasons.push(`when_minGovernance=${conditions.when_minGovernance} but totalRelations=${profile.totalRelations}`);
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
reasons.push(`when_minGovernance=${conditions.when_minGovernance} satisfied (totalRelations=${profile.totalRelations})`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return { included, reasons };
|
|
151
|
+
}
|
|
35
152
|
// ── Frontmatter parser ─────────────────────────────────────────────────
|
|
36
153
|
function parseFrontmatter(raw) {
|
|
37
154
|
const match = raw.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/);
|
|
@@ -94,7 +211,18 @@ export function readCanonicalSkills(productbrainDir) {
|
|
|
94
211
|
const triggers = arrayFields.get('triggers') ?? [];
|
|
95
212
|
const targets = arrayFields.get('targets');
|
|
96
213
|
const level = fields.get('level');
|
|
97
|
-
|
|
214
|
+
const conditions = {};
|
|
215
|
+
const whenStack = fields.get('when_stack');
|
|
216
|
+
const whenMinStage = fields.get('when_minStage');
|
|
217
|
+
const whenMinGovernance = fields.get('when_minGovernance');
|
|
218
|
+
if (whenStack)
|
|
219
|
+
conditions.when_stack = whenStack;
|
|
220
|
+
if (whenMinStage)
|
|
221
|
+
conditions.when_minStage = whenMinStage;
|
|
222
|
+
if (whenMinGovernance)
|
|
223
|
+
conditions.when_minGovernance = whenMinGovernance;
|
|
224
|
+
const hasConditions = Object.keys(conditions).length > 0;
|
|
225
|
+
skills.push({ name, description, triggers, body, sourcePath: filePath, targets: targets?.length ? targets : undefined, level: level || undefined, conditions: hasConditions ? conditions : undefined });
|
|
98
226
|
}
|
|
99
227
|
return skills.sort((a, b) => a.name.localeCompare(b.name));
|
|
100
228
|
}
|
|
@@ -114,10 +242,113 @@ export function readCanonicalRules(productbrainDir) {
|
|
|
114
242
|
const autoApply = fields.get('autoApply') === 'true';
|
|
115
243
|
const targets = arrayFields.get('targets');
|
|
116
244
|
const level = fields.get('level');
|
|
117
|
-
|
|
245
|
+
const conditions = {};
|
|
246
|
+
const whenStack = fields.get('when_stack');
|
|
247
|
+
const whenMinStage = fields.get('when_minStage');
|
|
248
|
+
const whenMinGovernance = fields.get('when_minGovernance');
|
|
249
|
+
if (whenStack)
|
|
250
|
+
conditions.when_stack = whenStack;
|
|
251
|
+
if (whenMinStage)
|
|
252
|
+
conditions.when_minStage = whenMinStage;
|
|
253
|
+
if (whenMinGovernance)
|
|
254
|
+
conditions.when_minGovernance = whenMinGovernance;
|
|
255
|
+
const hasConditions = Object.keys(conditions).length > 0;
|
|
256
|
+
rules.push({ name, description, scope, autoApply, body, sourcePath: filePath, targets: targets?.length ? targets : undefined, level: level || undefined, conditions: hasConditions ? conditions : undefined });
|
|
257
|
+
}
|
|
258
|
+
return rules.sort((a, b) => a.name.localeCompare(b.name));
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Read machine-local personal rules from .productbrain/.local/rules/.
|
|
262
|
+
* Returns [] when the directory is absent — no-op when personal layer is not set up.
|
|
263
|
+
* Every returned rule has persist: 'local' set, preventing projection to committed adapter files.
|
|
264
|
+
*/
|
|
265
|
+
export function readPersonalLayer(productbrainDir) {
|
|
266
|
+
const localRulesDir = join(productbrainDir, '.local', 'rules');
|
|
267
|
+
if (!existsSync(localRulesDir))
|
|
268
|
+
return [];
|
|
269
|
+
const files = readdirSync(localRulesDir).filter((f) => f.endsWith('.md'));
|
|
270
|
+
const rules = [];
|
|
271
|
+
for (const file of files) {
|
|
272
|
+
const filePath = join(localRulesDir, file);
|
|
273
|
+
const raw = readFileSync(filePath, 'utf8');
|
|
274
|
+
const { fields, arrayFields, body } = parseFrontmatter(raw);
|
|
275
|
+
const name = fields.get('name') ?? basename(file, '.md');
|
|
276
|
+
const description = fields.get('description') ?? '';
|
|
277
|
+
const scope = fields.get('scope');
|
|
278
|
+
const autoApply = fields.get('autoApply') === 'true';
|
|
279
|
+
const targets = arrayFields.get('targets');
|
|
280
|
+
const level = fields.get('level');
|
|
281
|
+
const conditions = {};
|
|
282
|
+
const whenStack = fields.get('when_stack');
|
|
283
|
+
const whenMinStage = fields.get('when_minStage');
|
|
284
|
+
const whenMinGovernance = fields.get('when_minGovernance');
|
|
285
|
+
if (whenStack)
|
|
286
|
+
conditions.when_stack = whenStack;
|
|
287
|
+
if (whenMinStage)
|
|
288
|
+
conditions.when_minStage = whenMinStage;
|
|
289
|
+
if (whenMinGovernance)
|
|
290
|
+
conditions.when_minGovernance = whenMinGovernance;
|
|
291
|
+
const hasConditions = Object.keys(conditions).length > 0;
|
|
292
|
+
rules.push({
|
|
293
|
+
name,
|
|
294
|
+
description,
|
|
295
|
+
scope,
|
|
296
|
+
autoApply,
|
|
297
|
+
body,
|
|
298
|
+
sourcePath: filePath,
|
|
299
|
+
targets: targets?.length ? targets : undefined,
|
|
300
|
+
level: level || undefined,
|
|
301
|
+
conditions: hasConditions ? conditions : undefined,
|
|
302
|
+
persist: 'local',
|
|
303
|
+
});
|
|
118
304
|
}
|
|
119
305
|
return rules.sort((a, b) => a.name.localeCompare(b.name));
|
|
120
306
|
}
|
|
307
|
+
/**
|
|
308
|
+
* Read machine-local personal skills from .productbrain/.local/skills/.
|
|
309
|
+
* Returns [] when the directory is absent — no-op when personal layer is not set up.
|
|
310
|
+
* Every returned skill has persist: 'local' set, preventing projection to committed adapter files.
|
|
311
|
+
*/
|
|
312
|
+
export function readPersonalSkillsLayer(productbrainDir) {
|
|
313
|
+
const localSkillsDir = join(productbrainDir, '.local', 'skills');
|
|
314
|
+
if (!existsSync(localSkillsDir))
|
|
315
|
+
return [];
|
|
316
|
+
const files = readdirSync(localSkillsDir).filter((f) => f.endsWith('.md'));
|
|
317
|
+
const skills = [];
|
|
318
|
+
for (const file of files) {
|
|
319
|
+
const filePath = join(localSkillsDir, file);
|
|
320
|
+
const raw = readFileSync(filePath, 'utf8');
|
|
321
|
+
const { fields, arrayFields, body } = parseFrontmatter(raw);
|
|
322
|
+
const name = fields.get('name') ?? basename(file, '.md');
|
|
323
|
+
const description = fields.get('description') ?? '';
|
|
324
|
+
const triggers = arrayFields.get('triggers') ?? [];
|
|
325
|
+
const targets = arrayFields.get('targets');
|
|
326
|
+
const level = fields.get('level');
|
|
327
|
+
const conditions = {};
|
|
328
|
+
const whenStack = fields.get('when_stack');
|
|
329
|
+
const whenMinStage = fields.get('when_minStage');
|
|
330
|
+
const whenMinGovernance = fields.get('when_minGovernance');
|
|
331
|
+
if (whenStack)
|
|
332
|
+
conditions.when_stack = whenStack;
|
|
333
|
+
if (whenMinStage)
|
|
334
|
+
conditions.when_minStage = whenMinStage;
|
|
335
|
+
if (whenMinGovernance)
|
|
336
|
+
conditions.when_minGovernance = whenMinGovernance;
|
|
337
|
+
const hasConditions = Object.keys(conditions).length > 0;
|
|
338
|
+
skills.push({
|
|
339
|
+
name,
|
|
340
|
+
description,
|
|
341
|
+
triggers,
|
|
342
|
+
body,
|
|
343
|
+
sourcePath: filePath,
|
|
344
|
+
targets: targets?.length ? targets : undefined,
|
|
345
|
+
level: level || undefined,
|
|
346
|
+
conditions: hasConditions ? conditions : undefined,
|
|
347
|
+
persist: 'local',
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
return skills.sort((a, b) => a.name.localeCompare(b.name));
|
|
351
|
+
}
|
|
121
352
|
// ── Transport section stripping ───────────────────────────────────────
|
|
122
353
|
/**
|
|
123
354
|
* Strip transport-conditional sections from a skill body.
|
|
@@ -149,7 +380,7 @@ export function stripTransportSections(body, target) {
|
|
|
149
380
|
* Generate a Cursor SKILL.md from a canonical skill.
|
|
150
381
|
* Cursor expects: name, description (with triggers embedded).
|
|
151
382
|
*/
|
|
152
|
-
export function generateCursorSkill(skill) {
|
|
383
|
+
export function generateCursorSkill(skill, profile) {
|
|
153
384
|
// Cursor puts trigger phrases in the description field
|
|
154
385
|
const triggerLine = skill.triggers.length > 0
|
|
155
386
|
? ` Use when the user says ${skill.triggers.map((t) => `"${t}"`).join(', ')}.`
|
|
@@ -174,26 +405,162 @@ ${body}`;
|
|
|
174
405
|
* Generate a Cursor .mdc rule from a canonical rule.
|
|
175
406
|
* Cursor expects: description, globs, alwaysApply.
|
|
176
407
|
*/
|
|
177
|
-
export function generateCursorRule(rule) {
|
|
408
|
+
export function generateCursorRule(rule, profile) {
|
|
178
409
|
// Replace canonical paths with Cursor paths in body
|
|
179
410
|
const body = rule.body
|
|
180
411
|
.replace(/\.productbrain\/rules\/(\S+)\.md/g, '.cursor/rules/$1.mdc')
|
|
181
412
|
.replace(/\.productbrain\/skills\/(\S+)\.md/g, '.cursor/skills/$1/SKILL.md');
|
|
182
413
|
return `---
|
|
183
414
|
description: ${rule.description}
|
|
184
|
-
globs: ${rule.scope
|
|
185
|
-
alwaysApply: ${rule.autoApply}
|
|
415
|
+
globs: ${rule.scope || ''}
|
|
416
|
+
alwaysApply: ${!rule.scope && rule.autoApply}
|
|
186
417
|
---
|
|
187
418
|
<!-- ${MARKER} — source: .productbrain/rules/${rule.name}.md -->
|
|
188
419
|
|
|
189
420
|
${body}`;
|
|
190
421
|
}
|
|
422
|
+
// ── Codex generators ───────────────────────────────────────────────────
|
|
423
|
+
/**
|
|
424
|
+
* Apply batch-mode transformations to a skill body (DEC-283).
|
|
425
|
+
*
|
|
426
|
+
* Skills describe WHAT (intent). This generator produces HOW (batch-appropriate
|
|
427
|
+
* instructions). We transform interactive patterns without gutting the skill's
|
|
428
|
+
* logical structure and purpose.
|
|
429
|
+
*
|
|
430
|
+
* Transformations applied:
|
|
431
|
+
* 1. Strip sub-agent spawn patterns → inline steps
|
|
432
|
+
* 2. Strip user confirmation gates → autonomous proceed
|
|
433
|
+
* 3. Strip streaming/interactive references
|
|
434
|
+
* 4. Add batch governance header after first `#` heading
|
|
435
|
+
*/
|
|
436
|
+
export function applyBatchTransformations(body) {
|
|
437
|
+
// Split into fenced code blocks vs prose so transforms only apply to prose.
|
|
438
|
+
// Fenced blocks (``` or ~~~) may contain examples of interactive patterns
|
|
439
|
+
// that must be preserved verbatim.
|
|
440
|
+
const segments = body.split(/(^```[^\n]*\n[\s\S]*?^```\s*$|^~~~[^\n]*\n[\s\S]*?^~~~\s*$)/m);
|
|
441
|
+
let result = segments
|
|
442
|
+
.map((segment, i) => {
|
|
443
|
+
// Odd indices are fenced code blocks — pass through unchanged
|
|
444
|
+
if (i % 2 === 1)
|
|
445
|
+
return segment;
|
|
446
|
+
return applyProseTransformations(segment);
|
|
447
|
+
})
|
|
448
|
+
.join('');
|
|
449
|
+
// 4. Add batch governance header after the first `#` heading line
|
|
450
|
+
const batchHeader = '> Batch execution mode: This skill runs autonomously without interactive gates. Decisions are logged, not prompted.';
|
|
451
|
+
result = result.replace(/^(#\s+[^\n]+)(\n)/m, `$1$2\n${batchHeader}\n`);
|
|
452
|
+
return result;
|
|
453
|
+
}
|
|
454
|
+
/** Apply interactive-pattern transforms to a prose segment (not inside code fences). */
|
|
455
|
+
function applyProseTransformations(text) {
|
|
456
|
+
let result = text;
|
|
457
|
+
// 1. Sub-agent spawn patterns — lines that dispatch to sub-agents or fresh conversations
|
|
458
|
+
result = result.replace(/^.*\b(spawn\s+(a\s+)?(sub-agent|build\s+sub-agent|review\s+sub-agent|judge|system\s+verification\s+agent)|Agent\s+tool\s+dispatch|fresh\s+conversation\s+handoff|open\s+a\s+(new|fresh)\s+(conversation|chat)|start\s+a\s+(new|fresh)\s+(conversation|chat))\b.*$/gim, 'Execute as inline steps within this session.');
|
|
459
|
+
// 2. User confirmation gates — lines that halt for human input
|
|
460
|
+
result = result.replace(/^.*\b(ask\s+the\s+(user|human)|wait\s+for\s+(user\s+)?input|present\s+gate\s+to\s+(the\s+)?user|stop\s+and\s+ask|pause\s+and\s+ask|get\s+user\s+confirmation|awaiting\s+your\s+feedback|wait\s+for\s+(human|user)\s+(sign-?off|approval|input))\b.*$/gim, 'Proceed autonomously. Log decision rationale.');
|
|
461
|
+
// 3. Streaming / persistent-connection references
|
|
462
|
+
result = result.replace(/^.*\b(real-time\s+feedback|streaming\s+output|interactive\s+mcp\s+tool\s+calls?\s+that\s+assume\s+a\s+persistent\s+connection)\b.*$/gim, '');
|
|
463
|
+
return result;
|
|
464
|
+
}
|
|
465
|
+
/**
|
|
466
|
+
* Generate a Codex skill projection from a canonical skill.
|
|
467
|
+
* This is a repo-local markdown projection, not a separate authoring source.
|
|
468
|
+
*
|
|
469
|
+
* When profile.executionModel === 'batch', batch transformations are applied
|
|
470
|
+
* AFTER transport stripping and path replacement (DEC-283).
|
|
471
|
+
*/
|
|
472
|
+
export function generateCodexSkill(skill, profile) {
|
|
473
|
+
const triggerLine = skill.triggers.length > 0
|
|
474
|
+
? `\n\n**Triggers:** ${skill.triggers.map((t) => `\`${t}\``).join(', ')}`
|
|
475
|
+
: '';
|
|
476
|
+
const stripped = stripTransportSections(skill.body, 'codex');
|
|
477
|
+
const pathReplaced = stripped
|
|
478
|
+
.replace(/\.productbrain\/skills\/(\S+)\.md/g, '.codex/skills/$1.md');
|
|
479
|
+
const body = profile?.executionModel === 'batch'
|
|
480
|
+
? applyBatchTransformations(pathReplaced)
|
|
481
|
+
: pathReplaced;
|
|
482
|
+
return `<!-- ${MARKER} — source: .productbrain/skills/${skill.name}.md -->
|
|
483
|
+
|
|
484
|
+
# ${skill.name}
|
|
485
|
+
|
|
486
|
+
${skill.description}${triggerLine}
|
|
487
|
+
|
|
488
|
+
${body}`;
|
|
489
|
+
}
|
|
490
|
+
/**
|
|
491
|
+
* Generate a Codex skill index/router file.
|
|
492
|
+
* AGENTS.md can point here so Codex has one obvious place to find available workflows.
|
|
493
|
+
*/
|
|
494
|
+
export function generateCodexSkillIndex(skills) {
|
|
495
|
+
const primarySkills = skills.filter((skill) => {
|
|
496
|
+
const lower = skill.name.toLowerCase();
|
|
497
|
+
return lower !== 'learnings-template' && !lower.endsWith('-learnings');
|
|
498
|
+
});
|
|
499
|
+
if (primarySkills.length === 0) {
|
|
500
|
+
return `<!-- ${MARKER} — source: generated from .productbrain/skills/*.md -->
|
|
501
|
+
|
|
502
|
+
# Product Brain Skills for Codex
|
|
503
|
+
|
|
504
|
+
No Product Brain skills are currently projected for Codex in this repo.
|
|
505
|
+
`;
|
|
506
|
+
}
|
|
507
|
+
const blocks = primarySkills.map((skill) => {
|
|
508
|
+
const triggerText = skill.triggers.length > 0
|
|
509
|
+
? `Triggers: ${skill.triggers.map((t) => `\`${t}\``).join(', ')}`
|
|
510
|
+
: 'Triggers: none declared';
|
|
511
|
+
return `## ${skill.name}
|
|
512
|
+
|
|
513
|
+
${skill.description}
|
|
514
|
+
|
|
515
|
+
${triggerText}
|
|
516
|
+
|
|
517
|
+
Read: \`.codex/skills/${skill.name}.md\``;
|
|
518
|
+
});
|
|
519
|
+
return `<!-- ${MARKER} — source: generated from .productbrain/skills/*.md -->
|
|
520
|
+
|
|
521
|
+
# Product Brain Skills for Codex
|
|
522
|
+
|
|
523
|
+
When the task matches one of these workflows, read the linked skill file first and follow its protocol.
|
|
524
|
+
Maintenance companions like \`*-learnings\` and \`LEARNINGS-TEMPLATE\` are still projected on disk, but hidden from this index so the primary workflows stay easy to scan.
|
|
525
|
+
|
|
526
|
+
${blocks.join('\n\n')}`;
|
|
527
|
+
}
|
|
528
|
+
const CODEX_DEAD_REFERENCE_PATTERNS = [
|
|
529
|
+
{ pattern: /\bpb\s+(session|orient|get|capture|search|update|handshake|context|constellation)\b/, label: 'pb CLI command' },
|
|
530
|
+
{ pattern: /\bsub-agent\b/i, label: 'sub-agent reference' },
|
|
531
|
+
{ pattern: /\bAgent\s+tool\b/, label: 'Agent tool reference' },
|
|
532
|
+
{ pattern: /\bkernelCall\b/, label: 'kernelCall reference' },
|
|
533
|
+
{ pattern: /\bpb\s+session\s+(start|close)\b/, label: 'pb session lifecycle' },
|
|
534
|
+
];
|
|
535
|
+
/**
|
|
536
|
+
* Validate Codex-projected skills for references to capabilities Codex cannot execute.
|
|
537
|
+
* Scans the transport-stripped body (so claude-only blocks don't false-positive).
|
|
538
|
+
*/
|
|
539
|
+
export function validateCodexSkills(skills) {
|
|
540
|
+
const warnings = [];
|
|
541
|
+
for (const skill of skills) {
|
|
542
|
+
const stripped = stripTransportSections(skill.body, 'codex');
|
|
543
|
+
const lines = stripped.split('\n');
|
|
544
|
+
for (const line of lines) {
|
|
545
|
+
for (const { pattern, label } of CODEX_DEAD_REFERENCE_PATTERNS) {
|
|
546
|
+
if (pattern.test(line)) {
|
|
547
|
+
warnings.push({
|
|
548
|
+
skillName: skill.name,
|
|
549
|
+
pattern: label,
|
|
550
|
+
line: line.trim().slice(0, 80),
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
return warnings;
|
|
557
|
+
}
|
|
191
558
|
// ── Claude Code generators ────────────────────────────────────────────
|
|
192
559
|
/**
|
|
193
560
|
* Generate a Claude Code .md rule from a canonical rule.
|
|
194
561
|
* Claude Code expects: description, optional paths (array).
|
|
195
562
|
*/
|
|
196
|
-
export function generateClaudeRule(rule) {
|
|
563
|
+
export function generateClaudeRule(rule, profile) {
|
|
197
564
|
// Replace canonical paths with Claude Code paths in body
|
|
198
565
|
const body = rule.body
|
|
199
566
|
.replace(/\.productbrain\/rules\/(\S+)\.md/g, '.claude/rules/$1.md')
|
|
@@ -215,7 +582,7 @@ ${body}`;
|
|
|
215
582
|
* Generate a Claude Code skill-router.md — imperative skill activation rule.
|
|
216
583
|
* Loaded automatically by Claude Code via .claude/rules/ with no paths (always active).
|
|
217
584
|
*/
|
|
218
|
-
export function generateClaudeSkillRouter(skills) {
|
|
585
|
+
export function generateClaudeSkillRouter(skills, profile) {
|
|
219
586
|
if (skills.length === 0)
|
|
220
587
|
return '';
|
|
221
588
|
const triggerBlocks = skills.map((skill) => {
|