@productbrain/cli 0.1.0-beta.7 → 0.1.0-beta.70
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 +98 -30
- 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.d.ts +2 -0
- package/dist/__tests__/capture.test.d.ts.map +1 -0
- package/dist/__tests__/capture.test.js +377 -0
- package/dist/__tests__/capture.test.js.map +1 -0
- package/dist/__tests__/config.test.d.ts +8 -0
- package/dist/__tests__/config.test.d.ts.map +1 -0
- package/dist/__tests__/config.test.js +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.d.ts +2 -0
- package/dist/__tests__/constellation.test.d.ts.map +1 -0
- package/dist/__tests__/constellation.test.js +254 -0
- package/dist/__tests__/constellation.test.js.map +1 -0
- 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.d.ts +2 -0
- package/dist/__tests__/fields.test.d.ts.map +1 -0
- package/dist/__tests__/fields.test.js +238 -0
- package/dist/__tests__/fields.test.js.map +1 -0
- 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.test.d.ts +2 -0
- package/dist/__tests__/handshake.test.d.ts.map +1 -0
- package/dist/__tests__/handshake.test.js +196 -0
- package/dist/__tests__/handshake.test.js.map +1 -0
- package/dist/__tests__/ingest.test.js +98 -0
- 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__/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__/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.d.ts +2 -0
- package/dist/__tests__/relate.test.d.ts.map +1 -0
- package/dist/__tests__/relate.test.js +103 -0
- package/dist/__tests__/relate.test.js.map +1 -0
- package/dist/__tests__/repo-detect.test.d.ts +2 -0
- package/dist/__tests__/repo-detect.test.d.ts.map +1 -0
- package/dist/__tests__/repo-detect.test.js +215 -0
- package/dist/__tests__/repo-detect.test.js.map +1 -0
- package/dist/__tests__/runner.test.d.ts +2 -0
- package/dist/__tests__/runner.test.d.ts.map +1 -0
- package/dist/__tests__/runner.test.js +219 -0
- package/dist/__tests__/runner.test.js.map +1 -0
- package/dist/__tests__/session-touch.test.d.ts +2 -0
- package/dist/__tests__/session-touch.test.d.ts.map +1 -0
- package/dist/__tests__/session-touch.test.js +134 -0
- package/dist/__tests__/session-touch.test.js.map +1 -0
- package/dist/__tests__/session.test.d.ts +2 -0
- package/dist/__tests__/session.test.d.ts.map +1 -0
- package/dist/__tests__/session.test.js +46 -0
- package/dist/__tests__/session.test.js.map +1 -0
- 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__/strip.test.d.ts +2 -0
- package/dist/__tests__/strip.test.d.ts.map +1 -0
- package/dist/__tests__/strip.test.js +136 -0
- package/dist/__tests__/strip.test.js.map +1 -0
- package/dist/__tests__/surface-profiles.test.d.ts +2 -0
- package/dist/__tests__/surface-profiles.test.d.ts.map +1 -0
- package/dist/__tests__/surface-profiles.test.js +233 -0
- package/dist/__tests__/surface-profiles.test.js.map +1 -0
- package/dist/__tests__/update.test.d.ts +2 -0
- package/dist/__tests__/update.test.d.ts.map +1 -0
- package/dist/__tests__/update.test.js +228 -0
- package/dist/__tests__/update.test.js.map +1 -0
- package/dist/__tests__/workspace.test.d.ts +2 -0
- package/dist/__tests__/workspace.test.d.ts.map +1 -0
- package/dist/__tests__/workspace.test.js +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 +88 -0
- package/dist/commands/admin/cockpit.d.ts.map +1 -0
- package/dist/commands/admin/cockpit.js +409 -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 +254 -0
- package/dist/commands/admin/index.js.map +1 -0
- package/dist/commands/admin/inspect.d.ts +21 -0
- package/dist/commands/admin/inspect.d.ts.map +1 -0
- package/dist/commands/admin/inspect.js +536 -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 +71 -0
- package/dist/commands/admin/inspect.test.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 +527 -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 +30 -0
- package/dist/commands/capture.d.ts.map +1 -0
- package/dist/commands/capture.js +385 -0
- package/dist/commands/capture.js.map +1 -0
- 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 +200 -0
- package/dist/commands/connect-integration.test.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 +279 -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 +230 -0
- package/dist/commands/connect.test.js.map +1 -0
- package/dist/commands/constellation.d.ts +11 -0
- package/dist/commands/constellation.d.ts.map +1 -0
- package/dist/commands/constellation.js +33 -0
- package/dist/commands/constellation.js.map +1 -0
- package/dist/commands/context.d.ts +2 -1
- package/dist/commands/context.d.ts.map +1 -1
- package/dist/commands/context.js +20 -9
- 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 +9 -0
- package/dist/commands/fields.d.ts.map +1 -0
- package/dist/commands/fields.js +30 -0
- package/dist/commands/fields.js.map +1 -0
- package/dist/commands/get.d.ts +8 -1
- package/dist/commands/get.d.ts.map +1 -1
- package/dist/commands/get.js +60 -7
- package/dist/commands/get.js.map +1 -1
- package/dist/commands/handshake.d.ts +28 -0
- package/dist/commands/handshake.d.ts.map +1 -0
- package/dist/commands/handshake.js +617 -0
- package/dist/commands/handshake.js.map +1 -0
- package/dist/commands/ingest.d.ts +8 -2
- package/dist/commands/ingest.d.ts.map +1 -1
- package/dist/commands/ingest.js +148 -25
- 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 +117 -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/orient.d.ts +107 -1
- package/dist/commands/orient.d.ts.map +1 -1
- package/dist/commands/orient.js +24 -8
- 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 +16 -0
- package/dist/commands/relate.d.ts.map +1 -0
- package/dist/commands/relate.js +98 -0
- package/dist/commands/relate.js.map +1 -0
- package/dist/commands/search.d.ts +1 -0
- package/dist/commands/search.d.ts.map +1 -1
- package/dist/commands/search.js +5 -3
- package/dist/commands/search.js.map +1 -1
- package/dist/commands/session.d.ts +20 -0
- package/dist/commands/session.d.ts.map +1 -0
- package/dist/commands/session.js +148 -0
- package/dist/commands/session.js.map +1 -0
- package/dist/commands/setup.d.ts +15 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +168 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/commands/update.d.ts +17 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +178 -0
- package/dist/commands/update.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/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 +48 -0
- package/dist/formatters/capture.d.ts.map +1 -0
- package/dist/formatters/capture.js +77 -0
- package/dist/formatters/capture.js.map +1 -0
- 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/constellation.d.ts +34 -0
- package/dist/formatters/constellation.d.ts.map +1 -0
- package/dist/formatters/constellation.js +38 -0
- package/dist/formatters/constellation.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/fields.d.ts +32 -0
- package/dist/formatters/fields.d.ts.map +1 -0
- package/dist/formatters/fields.js +49 -0
- package/dist/formatters/fields.js.map +1 -0
- package/dist/formatters/handshake.d.ts +24 -0
- package/dist/formatters/handshake.d.ts.map +1 -0
- package/dist/formatters/handshake.js +69 -0
- package/dist/formatters/handshake.js.map +1 -0
- 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 +14 -0
- package/dist/formatters/relate.d.ts.map +1 -0
- package/dist/formatters/relate.js +16 -0
- package/dist/formatters/relate.js.map +1 -0
- package/dist/formatters/search.d.ts +0 -4
- package/dist/formatters/search.d.ts.map +1 -1
- package/dist/formatters/search.js +4 -1
- package/dist/formatters/search.js.map +1 -1
- package/dist/formatters/session.d.ts +11 -0
- package/dist/formatters/session.d.ts.map +1 -0
- package/dist/formatters/session.js +53 -0
- package/dist/formatters/session.js.map +1 -0
- package/dist/formatters/update.d.ts +17 -0
- package/dist/formatters/update.d.ts.map +1 -0
- package/dist/formatters/update.js +45 -0
- package/dist/formatters/update.js.map +1 -0
- 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 +44 -0
- package/dist/generators/adapters.d.ts.map +1 -0
- package/dist/generators/adapters.js +290 -0
- package/dist/generators/adapters.js.map +1 -0
- 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/briefing-md.d.ts +8 -0
- package/dist/generators/briefing-md.d.ts.map +1 -0
- package/dist/generators/briefing-md.js +51 -0
- package/dist/generators/briefing-md.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 +8 -0
- package/dist/generators/context-md.d.ts.map +1 -0
- package/dist/generators/context-md.js +134 -0
- package/dist/generators/context-md.js.map +1 -0
- 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/portable-knowledge.d.ts +143 -0
- package/dist/generators/portable-knowledge.d.ts.map +1 -0
- package/dist/generators/portable-knowledge.js +504 -0
- package/dist/generators/portable-knowledge.js.map +1 -0
- package/dist/generators/portable-knowledge.test.d.ts +2 -0
- package/dist/generators/portable-knowledge.test.d.ts.map +1 -0
- package/dist/generators/portable-knowledge.test.js +927 -0
- package/dist/generators/portable-knowledge.test.js.map +1 -0
- 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.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +642 -37
- 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 +61 -0
- package/dist/lib/client.d.ts.map +1 -1
- package/dist/lib/client.js +258 -12
- package/dist/lib/client.js.map +1 -1
- 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/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 +33 -0
- package/dist/lib/repo-detect.d.ts.map +1 -0
- package/dist/lib/repo-detect.js +83 -0
- package/dist/lib/repo-detect.js.map +1 -0
- package/dist/lib/runner.d.ts +33 -0
- package/dist/lib/runner.d.ts.map +1 -0
- package/dist/lib/runner.js +79 -0
- package/dist/lib/runner.js.map +1 -0
- package/dist/lib/session.d.ts +17 -0
- package/dist/lib/session.d.ts.map +1 -0
- package/dist/lib/session.js +43 -0
- package/dist/lib/session.js.map +1 -0
- 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/strip.d.ts +12 -0
- package/dist/lib/strip.d.ts.map +1 -0
- package/dist/lib/strip.js +41 -0
- package/dist/lib/strip.js.map +1 -0
- package/dist/lib/style.d.ts +94 -0
- package/dist/lib/style.d.ts.map +1 -0
- package/dist/lib/style.js +167 -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/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 +16 -0
- package/dist/lib/workspace-probe.d.ts.map +1 -0
- package/dist/lib/workspace-probe.js +33 -0
- package/dist/lib/workspace-probe.js.map +1 -0
- package/package.json +13 -4
- package/templates/archetypes/boundary.md +23 -0
- package/templates/archetypes/constraint.md +23 -0
- package/templates/archetypes/convention.md +23 -0
- package/templates/archetypes/policy.md +23 -0
- package/templates/archetypes/quality-gate.md +23 -0
- package/templates/archetypes/workflow.md +23 -0
- package/templates/general/code-integrity.md +11 -0
- package/templates/general/getting-started.md +12 -0
- package/templates/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
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* chain-classifier — unit tests.
|
|
3
|
+
* BET-286 Slice 1: relation-aware governance function classifier.
|
|
4
|
+
*/
|
|
5
|
+
import { describe, expect, it } from 'vitest';
|
|
6
|
+
import { classifyGovernance, } from './chain-classifier.js';
|
|
7
|
+
// ── Helpers ────────────────────────────────────────────────────────────
|
|
8
|
+
function makeEntry(overrides) {
|
|
9
|
+
return {
|
|
10
|
+
status: 'committed',
|
|
11
|
+
verificationStatus: null,
|
|
12
|
+
data: null,
|
|
13
|
+
relations: [],
|
|
14
|
+
...overrides,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
function makeRelation(overrides) {
|
|
18
|
+
return {
|
|
19
|
+
direction: 'outgoing',
|
|
20
|
+
otherEntryId: null,
|
|
21
|
+
otherName: 'other entry',
|
|
22
|
+
otherCollectionSlug: null,
|
|
23
|
+
...overrides,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
// ── Test cases ─────────────────────────────────────────────────────────
|
|
27
|
+
describe('classifyGovernance — collection signal', () => {
|
|
28
|
+
it('STD entry with constrains relation → constraint with high confidence (>=0.6)', () => {
|
|
29
|
+
const entry = makeEntry({
|
|
30
|
+
entryId: 'STD-1',
|
|
31
|
+
name: 'Trunk-based development standard',
|
|
32
|
+
collectionSlug: 'standards',
|
|
33
|
+
relations: [makeRelation({ type: 'constrains', otherCollectionSlug: 'bets' })],
|
|
34
|
+
});
|
|
35
|
+
const results = classifyGovernance([entry]);
|
|
36
|
+
expect(results).toHaveLength(1);
|
|
37
|
+
expect(results[0].governanceFunction).toBe('constraint');
|
|
38
|
+
expect(results[0].confidence).toBeGreaterThanOrEqual(0.6);
|
|
39
|
+
});
|
|
40
|
+
it('ARCH entry → boundary with medium confidence (>=0.4)', () => {
|
|
41
|
+
const entry = makeEntry({
|
|
42
|
+
entryId: 'ARCH-1',
|
|
43
|
+
name: 'Seven system domains',
|
|
44
|
+
collectionSlug: 'architecture',
|
|
45
|
+
});
|
|
46
|
+
const results = classifyGovernance([entry]);
|
|
47
|
+
expect(results).toHaveLength(1);
|
|
48
|
+
expect(results[0].governanceFunction).toBe('boundary');
|
|
49
|
+
expect(results[0].confidence).toBeGreaterThanOrEqual(0.4);
|
|
50
|
+
});
|
|
51
|
+
it('DEC entry with deployment in name → convention with boosted confidence', () => {
|
|
52
|
+
const entry = makeEntry({
|
|
53
|
+
entryId: 'DEC-1',
|
|
54
|
+
name: 'deployment ordering for Convex and Railway',
|
|
55
|
+
collectionSlug: 'decisions',
|
|
56
|
+
});
|
|
57
|
+
const noNameEntry = makeEntry({
|
|
58
|
+
entryId: 'DEC-2',
|
|
59
|
+
name: 'some decision',
|
|
60
|
+
collectionSlug: 'decisions',
|
|
61
|
+
});
|
|
62
|
+
const withName = classifyGovernance([entry]);
|
|
63
|
+
const withoutName = classifyGovernance([noNameEntry]);
|
|
64
|
+
expect(withName[0].governanceFunction).toBe('convention');
|
|
65
|
+
expect(withName[0].confidence).toBeGreaterThan(withoutName[0].confidence);
|
|
66
|
+
});
|
|
67
|
+
it('FLOW entry → workflow', () => {
|
|
68
|
+
const entry = makeEntry({
|
|
69
|
+
entryId: 'FLOW-1',
|
|
70
|
+
name: 'Feature flag lifecycle flow',
|
|
71
|
+
collectionSlug: 'flows',
|
|
72
|
+
});
|
|
73
|
+
const results = classifyGovernance([entry]);
|
|
74
|
+
expect(results).toHaveLength(1);
|
|
75
|
+
expect(results[0].governanceFunction).toBe('workflow');
|
|
76
|
+
});
|
|
77
|
+
it('POL entry with governs relation → policy with high confidence', () => {
|
|
78
|
+
const entry = makeEntry({
|
|
79
|
+
entryId: 'POL-1',
|
|
80
|
+
name: 'Access control policy',
|
|
81
|
+
collectionSlug: 'policies',
|
|
82
|
+
relations: [makeRelation({ type: 'governs', otherCollectionSlug: 'bets' })],
|
|
83
|
+
});
|
|
84
|
+
const results = classifyGovernance([entry]);
|
|
85
|
+
expect(results).toHaveLength(1);
|
|
86
|
+
expect(results[0].governanceFunction).toBe('policy');
|
|
87
|
+
expect(results[0].confidence).toBeGreaterThanOrEqual(0.6);
|
|
88
|
+
});
|
|
89
|
+
it('STD entry with test in name → quality-gate with boosted confidence', () => {
|
|
90
|
+
const entry = makeEntry({
|
|
91
|
+
entryId: 'STD-2',
|
|
92
|
+
name: 'Test coverage quality gate for all slices',
|
|
93
|
+
collectionSlug: 'standards',
|
|
94
|
+
});
|
|
95
|
+
const results = classifyGovernance([entry]);
|
|
96
|
+
expect(results).toHaveLength(1);
|
|
97
|
+
expect(results[0].governanceFunction).toBe('quality-gate');
|
|
98
|
+
expect(results[0].confidence).toBeGreaterThanOrEqual(0.5);
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
describe('classifyGovernance — null entryId safety', () => {
|
|
102
|
+
it('entry with null entryId is excluded from output', () => {
|
|
103
|
+
const entry = makeEntry({
|
|
104
|
+
entryId: null,
|
|
105
|
+
name: 'Draft entry without ID',
|
|
106
|
+
collectionSlug: 'standards',
|
|
107
|
+
});
|
|
108
|
+
const results = classifyGovernance([entry]);
|
|
109
|
+
expect(results).toHaveLength(0);
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
describe('classifyGovernance — empty input', () => {
|
|
113
|
+
it('empty input → empty output', () => {
|
|
114
|
+
const results = classifyGovernance([]);
|
|
115
|
+
expect(results).toHaveLength(0);
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
describe('classifyGovernance — unclassified', () => {
|
|
119
|
+
it('glossary entry → unclassified regardless of signals', () => {
|
|
120
|
+
const entry = makeEntry({
|
|
121
|
+
entryId: 'GLO-1',
|
|
122
|
+
name: 'Trunk-based development',
|
|
123
|
+
collectionSlug: 'glossary',
|
|
124
|
+
relations: [makeRelation({ type: 'constrains' })],
|
|
125
|
+
});
|
|
126
|
+
const results = classifyGovernance([entry]);
|
|
127
|
+
expect(results).toHaveLength(1);
|
|
128
|
+
expect(results[0].governanceFunction).toBe('unclassified');
|
|
129
|
+
expect(results[0].confidence).toBe(0);
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
describe('classifyGovernance — multiple signal matches', () => {
|
|
133
|
+
it('entry with multiple signals → highest confidence function wins', () => {
|
|
134
|
+
// BR entry with both constrains AND governs relations.
|
|
135
|
+
// constrains boosts 'constraint', governs boosts 'policy'.
|
|
136
|
+
// business-rules base maps to 'constraint', so constraint should win.
|
|
137
|
+
const entry = makeEntry({
|
|
138
|
+
entryId: 'BR-1',
|
|
139
|
+
name: 'Entry creation must use createEntry gate',
|
|
140
|
+
collectionSlug: 'business-rules',
|
|
141
|
+
relations: [
|
|
142
|
+
makeRelation({ type: 'constrains' }),
|
|
143
|
+
makeRelation({ type: 'constrains' }),
|
|
144
|
+
makeRelation({ type: 'governs' }),
|
|
145
|
+
],
|
|
146
|
+
});
|
|
147
|
+
const results = classifyGovernance([entry]);
|
|
148
|
+
expect(results).toHaveLength(1);
|
|
149
|
+
// Both constraint and policy are plausible; the function with the highest score wins.
|
|
150
|
+
// With 2x constrains boosts, constraint should dominate.
|
|
151
|
+
expect(results[0].governanceFunction).toBe('constraint');
|
|
152
|
+
expect(results[0].confidence).toBeGreaterThanOrEqual(0.6);
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
describe('classifyGovernance — passthrough fields', () => {
|
|
156
|
+
it('passes data and relations through to result', () => {
|
|
157
|
+
const data = { someField: 'someValue' };
|
|
158
|
+
const relation = makeRelation({ type: 'constrains' });
|
|
159
|
+
const entry = makeEntry({
|
|
160
|
+
entryId: 'STD-99',
|
|
161
|
+
name: 'Some standard',
|
|
162
|
+
collectionSlug: 'standards',
|
|
163
|
+
data,
|
|
164
|
+
relations: [relation],
|
|
165
|
+
});
|
|
166
|
+
const results = classifyGovernance([entry]);
|
|
167
|
+
expect(results[0].data).toBe(data);
|
|
168
|
+
expect(results[0].relations).toEqual([relation]);
|
|
169
|
+
});
|
|
170
|
+
it('returns entryId, name, and collectionSlug unchanged', () => {
|
|
171
|
+
const entry = makeEntry({
|
|
172
|
+
entryId: 'ARCH-42',
|
|
173
|
+
name: 'My architecture entry',
|
|
174
|
+
collectionSlug: 'architecture',
|
|
175
|
+
});
|
|
176
|
+
const results = classifyGovernance([entry]);
|
|
177
|
+
expect(results[0].entryId).toBe('ARCH-42');
|
|
178
|
+
expect(results[0].name).toBe('My architecture entry');
|
|
179
|
+
expect(results[0].collectionSlug).toBe('architecture');
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
describe('classifyGovernance — name signal boosts', () => {
|
|
183
|
+
it('security keyword boosts policy for business-rules collection', () => {
|
|
184
|
+
const withKeyword = makeEntry({
|
|
185
|
+
entryId: 'BR-2',
|
|
186
|
+
name: 'Auth security check before MCP tool execution',
|
|
187
|
+
collectionSlug: 'business-rules',
|
|
188
|
+
});
|
|
189
|
+
const withoutKeyword = makeEntry({
|
|
190
|
+
entryId: 'BR-3',
|
|
191
|
+
name: 'Some business rule',
|
|
192
|
+
collectionSlug: 'business-rules',
|
|
193
|
+
});
|
|
194
|
+
const [withResult] = classifyGovernance([withKeyword]);
|
|
195
|
+
const [withoutResult] = classifyGovernance([withoutKeyword]);
|
|
196
|
+
// Security keyword → policy wins over default constraint
|
|
197
|
+
expect(withResult.governanceFunction).toBe('policy');
|
|
198
|
+
// Without keyword, default constraint wins
|
|
199
|
+
expect(withoutResult.governanceFunction).toBe('constraint');
|
|
200
|
+
});
|
|
201
|
+
it('matchedSignals contains human-readable explanations', () => {
|
|
202
|
+
const entry = makeEntry({
|
|
203
|
+
entryId: 'STD-5',
|
|
204
|
+
name: 'Quality gate for test coverage',
|
|
205
|
+
collectionSlug: 'standards',
|
|
206
|
+
relations: [makeRelation({ type: 'constrains' })],
|
|
207
|
+
});
|
|
208
|
+
const [result] = classifyGovernance([entry]);
|
|
209
|
+
expect(result.matchedSignals.length).toBeGreaterThan(0);
|
|
210
|
+
expect(result.matchedSignals.some((s) => s.includes('standards'))).toBe(true);
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
describe('classifyGovernance — mixed null/non-null entryIds', () => {
|
|
214
|
+
it('only entries with non-null entryIds are returned', () => {
|
|
215
|
+
const entries = [
|
|
216
|
+
makeEntry({ entryId: 'STD-1', name: 'Valid standard', collectionSlug: 'standards' }),
|
|
217
|
+
makeEntry({ entryId: null, name: 'Draft entry', collectionSlug: 'standards' }),
|
|
218
|
+
makeEntry({ entryId: 'ARCH-2', name: 'Architecture entry', collectionSlug: 'architecture' }),
|
|
219
|
+
];
|
|
220
|
+
const results = classifyGovernance(entries);
|
|
221
|
+
expect(results).toHaveLength(2);
|
|
222
|
+
expect(results.map((r) => r.entryId)).toEqual(['STD-1', 'ARCH-2']);
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
describe('classifyGovernance — patterns collection', () => {
|
|
226
|
+
it('PAT entry → convention', () => {
|
|
227
|
+
const entry = makeEntry({
|
|
228
|
+
entryId: 'PAT-1',
|
|
229
|
+
name: 'Additive wrapping pattern for feature flags',
|
|
230
|
+
collectionSlug: 'patterns',
|
|
231
|
+
});
|
|
232
|
+
const results = classifyGovernance([entry]);
|
|
233
|
+
expect(results[0].governanceFunction).toBe('convention');
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
describe('classifyGovernance — informed_by ARCH relation boosts boundary', () => {
|
|
237
|
+
it('DEC informed_by an architecture entry → boundary wins over convention', () => {
|
|
238
|
+
const entry = makeEntry({
|
|
239
|
+
entryId: 'DEC-5',
|
|
240
|
+
name: 'Domain boundaries for the seven layers',
|
|
241
|
+
collectionSlug: 'decisions',
|
|
242
|
+
relations: [
|
|
243
|
+
makeRelation({
|
|
244
|
+
type: 'informed_by',
|
|
245
|
+
direction: 'outgoing',
|
|
246
|
+
otherCollectionSlug: 'architecture',
|
|
247
|
+
otherName: 'Seven system domains',
|
|
248
|
+
otherEntryId: 'ARCH-26',
|
|
249
|
+
}),
|
|
250
|
+
],
|
|
251
|
+
});
|
|
252
|
+
// Also include 'domain' keyword in the name → double boundary boost
|
|
253
|
+
const results = classifyGovernance([entry]);
|
|
254
|
+
expect(results[0].governanceFunction).toBe('boundary');
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
//# sourceMappingURL=chain-classifier.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chain-classifier.test.js","sourceRoot":"","sources":["../../src/generators/chain-classifier.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chain Rules Assembler — BET-286 Slice 3
|
|
3
|
+
*
|
|
4
|
+
* Fetches governance entries via MCP, classifies them, resolves archetype
|
|
5
|
+
* templates, and returns CanonicalRule objects ready to merge into the
|
|
6
|
+
* canonical rules array in runHandshake().
|
|
7
|
+
*
|
|
8
|
+
* Chain: BET-286 (Chain-Derived Agent Configuration)
|
|
9
|
+
*/
|
|
10
|
+
import type { CanonicalRule } from './portable-knowledge.js';
|
|
11
|
+
import type { mcpCall as McpCallFn } from '../lib/client.js';
|
|
12
|
+
/** Statistics from a generateChainRules() call. */
|
|
13
|
+
export interface ChainRulesStats {
|
|
14
|
+
totalEntries: number;
|
|
15
|
+
classifiedEntries: number;
|
|
16
|
+
generatedRules: number;
|
|
17
|
+
suppressedByManual: number;
|
|
18
|
+
suppressedByZeroEntries: number;
|
|
19
|
+
}
|
|
20
|
+
/** Result returned by generateChainRules(). */
|
|
21
|
+
export interface ChainRulesResult {
|
|
22
|
+
/** Generated rules ready to merge into canonical rules array. */
|
|
23
|
+
rules: CanonicalRule[];
|
|
24
|
+
/** Function keys with no matching governance entries. */
|
|
25
|
+
gaps: string[];
|
|
26
|
+
/** Sentinel rule when MCP is unreachable — null on success. */
|
|
27
|
+
sentinel: CanonicalRule | null;
|
|
28
|
+
stats: ChainRulesStats;
|
|
29
|
+
/** Classified governance entries — passed through for diff engine confidence data. */
|
|
30
|
+
classified: import('./chain-classifier.js').ClassifiedGovernance[];
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Fetch governance entries, classify them, resolve archetypes, and produce
|
|
34
|
+
* CanonicalRule objects ready to merge into the handshake pipeline.
|
|
35
|
+
*
|
|
36
|
+
* @param mcpCallFn - Injected mcpCall function for testability.
|
|
37
|
+
* @param manualRules - Existing manual rules from .productbrain/rules/.
|
|
38
|
+
* Used to suppress generated rules when a manual rule
|
|
39
|
+
* with the same name already exists.
|
|
40
|
+
*/
|
|
41
|
+
export declare function generateChainRules(mcpCallFn: typeof McpCallFn, manualRules: CanonicalRule[]): Promise<ChainRulesResult>;
|
|
42
|
+
//# sourceMappingURL=chain-rules.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chain-rules.d.ts","sourceRoot":"","sources":["../../src/generators/chain-rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAI7D,OAAO,KAAK,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAI7D,mDAAmD;AACnD,MAAM,WAAW,eAAe;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,uBAAuB,EAAE,MAAM,CAAC;CACjC;AAED,+CAA+C;AAC/C,MAAM,WAAW,gBAAgB;IAC/B,iEAAiE;IACjE,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,yDAAyD;IACzD,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,+DAA+D;IAC/D,QAAQ,EAAE,aAAa,GAAG,IAAI,CAAC;IAC/B,KAAK,EAAE,eAAe,CAAC;IACvB,sFAAsF;IACtF,UAAU,EAAE,OAAO,uBAAuB,EAAE,oBAAoB,EAAE,CAAC;CACpE;AAkCD;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,OAAO,SAAS,EAC3B,WAAW,EAAE,aAAa,EAAE,GAC3B,OAAO,CAAC,gBAAgB,CAAC,CAoF3B"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chain Rules Assembler — BET-286 Slice 3
|
|
3
|
+
*
|
|
4
|
+
* Fetches governance entries via MCP, classifies them, resolves archetype
|
|
5
|
+
* templates, and returns CanonicalRule objects ready to merge into the
|
|
6
|
+
* canonical rules array in runHandshake().
|
|
7
|
+
*
|
|
8
|
+
* Chain: BET-286 (Chain-Derived Agent Configuration)
|
|
9
|
+
*/
|
|
10
|
+
import { classifyGovernance } from './chain-classifier.js';
|
|
11
|
+
import { resolveArchetype } from './archetypes.js';
|
|
12
|
+
// ── Sentinel ──────────────────────────────────────────────────────────
|
|
13
|
+
/** Produced when chain.getGovernanceWithRelations is unreachable. */
|
|
14
|
+
const CHAIN_DEGRADED_SENTINEL = {
|
|
15
|
+
name: '_chain_degraded',
|
|
16
|
+
description: 'Chain governance unavailable — agent operating with manual rules only',
|
|
17
|
+
body: 'WARNING: The Chain MCP endpoint is unreachable. Generated governance rules are unavailable. Agent is operating with manual rules only. Exercise extra caution on governance decisions — check with the human before proceeding.',
|
|
18
|
+
sourcePath: 'chain://_sentinel',
|
|
19
|
+
autoApply: true,
|
|
20
|
+
level: 'core',
|
|
21
|
+
scope: undefined,
|
|
22
|
+
targets: undefined,
|
|
23
|
+
};
|
|
24
|
+
// ── Governance functions to attempt (excluding 'unclassified') ────────
|
|
25
|
+
const GOVERNANCE_FUNCTIONS = [
|
|
26
|
+
'constraint',
|
|
27
|
+
'boundary',
|
|
28
|
+
'convention',
|
|
29
|
+
'policy',
|
|
30
|
+
'workflow',
|
|
31
|
+
'quality-gate',
|
|
32
|
+
];
|
|
33
|
+
/** Maximum number of generated rules (ranked by relation density). */
|
|
34
|
+
const MAX_GENERATED_RULES = 8;
|
|
35
|
+
// ── Assembler ─────────────────────────────────────────────────────────
|
|
36
|
+
/**
|
|
37
|
+
* Fetch governance entries, classify them, resolve archetypes, and produce
|
|
38
|
+
* CanonicalRule objects ready to merge into the handshake pipeline.
|
|
39
|
+
*
|
|
40
|
+
* @param mcpCallFn - Injected mcpCall function for testability.
|
|
41
|
+
* @param manualRules - Existing manual rules from .productbrain/rules/.
|
|
42
|
+
* Used to suppress generated rules when a manual rule
|
|
43
|
+
* with the same name already exists.
|
|
44
|
+
*/
|
|
45
|
+
export async function generateChainRules(mcpCallFn, manualRules) {
|
|
46
|
+
const emptyStats = {
|
|
47
|
+
totalEntries: 0,
|
|
48
|
+
classifiedEntries: 0,
|
|
49
|
+
generatedRules: 0,
|
|
50
|
+
suppressedByManual: 0,
|
|
51
|
+
suppressedByZeroEntries: 0,
|
|
52
|
+
};
|
|
53
|
+
// Step 1: Fetch governance entries — return sentinel on failure
|
|
54
|
+
// The Convex query returns { entries: [...], total: N } — unwrap the array.
|
|
55
|
+
let entries;
|
|
56
|
+
try {
|
|
57
|
+
const result = await mcpCallFn('chain.getGovernanceWithRelations', {});
|
|
58
|
+
if (!Array.isArray(result?.entries)) {
|
|
59
|
+
return { rules: [], gaps: [], sentinel: CHAIN_DEGRADED_SENTINEL, stats: emptyStats, classified: [] };
|
|
60
|
+
}
|
|
61
|
+
entries = result.entries;
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return {
|
|
65
|
+
rules: [],
|
|
66
|
+
gaps: [],
|
|
67
|
+
sentinel: CHAIN_DEGRADED_SENTINEL,
|
|
68
|
+
stats: emptyStats,
|
|
69
|
+
classified: [],
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
// Step 2: Classify entries
|
|
73
|
+
const classified = classifyGovernance(entries);
|
|
74
|
+
// Step 3: Build manual rule name set for suppression check
|
|
75
|
+
const manualRuleNames = new Set(manualRules.map((r) => r.name));
|
|
76
|
+
// Step 4: Resolve an archetype per governance function
|
|
77
|
+
const resolvedRules = [];
|
|
78
|
+
const gaps = [];
|
|
79
|
+
let suppressedByManual = 0;
|
|
80
|
+
let suppressedByZeroEntries = 0;
|
|
81
|
+
for (const fn of GOVERNANCE_FUNCTIONS) {
|
|
82
|
+
const matching = classified.filter((e) => e.governanceFunction === fn);
|
|
83
|
+
if (matching.length === 0) {
|
|
84
|
+
// Zero entries for this function — add to gaps
|
|
85
|
+
gaps.push(fn);
|
|
86
|
+
suppressedByZeroEntries++;
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
const result = resolveArchetype(fn, classified, manualRuleNames);
|
|
90
|
+
if ('skipped' in result) {
|
|
91
|
+
if (result.skipped === 'manual-suppression') {
|
|
92
|
+
suppressedByManual++;
|
|
93
|
+
}
|
|
94
|
+
// 'no-template' and 'zero-entries' are not counted as manual suppression.
|
|
95
|
+
// Zero-entries is already handled above; no-template is a missing file (not a user action).
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
resolvedRules.push(result.resolved.rule);
|
|
99
|
+
}
|
|
100
|
+
// Step 5: Cap at MAX_GENERATED_RULES — rank by relation density
|
|
101
|
+
// Relation density = total relations across all classified entries matching this function
|
|
102
|
+
const ranked = rankByRelationDensity(resolvedRules, classified);
|
|
103
|
+
const cappedRules = ranked.slice(0, MAX_GENERATED_RULES);
|
|
104
|
+
const stats = {
|
|
105
|
+
totalEntries: entries.length,
|
|
106
|
+
classifiedEntries: classified.length,
|
|
107
|
+
generatedRules: cappedRules.length,
|
|
108
|
+
suppressedByManual,
|
|
109
|
+
suppressedByZeroEntries,
|
|
110
|
+
};
|
|
111
|
+
return {
|
|
112
|
+
rules: cappedRules,
|
|
113
|
+
gaps,
|
|
114
|
+
sentinel: null,
|
|
115
|
+
stats,
|
|
116
|
+
classified,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
// ── Ranking ───────────────────────────────────────────────────────────
|
|
120
|
+
/**
|
|
121
|
+
* Rank generated rules by the total number of relations across classified
|
|
122
|
+
* entries that contributed to each rule. Higher relation density → ranked first.
|
|
123
|
+
*
|
|
124
|
+
* Falls back to name-based sort for ties to ensure stable output.
|
|
125
|
+
*/
|
|
126
|
+
function rankByRelationDensity(rules, classified) {
|
|
127
|
+
// Build a density score per sourcePath (chain://<functionKey>)
|
|
128
|
+
const densityMap = new Map();
|
|
129
|
+
for (const rule of rules) {
|
|
130
|
+
// sourcePath is 'chain://<functionKey>'
|
|
131
|
+
const functionKey = rule.sourcePath.replace('chain://', '');
|
|
132
|
+
const matching = classified.filter((e) => e.governanceFunction === functionKey);
|
|
133
|
+
const density = matching.reduce((sum, e) => sum + e.relations.length, 0);
|
|
134
|
+
densityMap.set(rule.sourcePath, density);
|
|
135
|
+
}
|
|
136
|
+
return [...rules].sort((a, b) => {
|
|
137
|
+
const densityA = densityMap.get(a.sourcePath) ?? 0;
|
|
138
|
+
const densityB = densityMap.get(b.sourcePath) ?? 0;
|
|
139
|
+
if (densityB !== densityA)
|
|
140
|
+
return densityB - densityA;
|
|
141
|
+
return a.name.localeCompare(b.name);
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=chain-rules.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chain-rules.js","sourceRoot":"","sources":["../../src/generators/chain-rules.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chain-rules.test.d.ts","sourceRoot":"","sources":["../../src/generators/chain-rules.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* chain-rules — unit tests.
|
|
3
|
+
* BET-286 Slice 3: chain rules assembler.
|
|
4
|
+
*/
|
|
5
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
6
|
+
import { generateChainRules } from './chain-rules.js';
|
|
7
|
+
// ── Helpers ────────────────────────────────────────────────────────────
|
|
8
|
+
function makeEntry(overrides) {
|
|
9
|
+
return {
|
|
10
|
+
status: 'active',
|
|
11
|
+
verificationStatus: 'verified',
|
|
12
|
+
data: null,
|
|
13
|
+
relations: [],
|
|
14
|
+
...overrides,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
function makeManualRule(name) {
|
|
18
|
+
return {
|
|
19
|
+
name,
|
|
20
|
+
description: 'Manual rule',
|
|
21
|
+
body: 'Manual rule body',
|
|
22
|
+
sourcePath: `.productbrain/rules/${name}.md`,
|
|
23
|
+
autoApply: true,
|
|
24
|
+
level: 'core',
|
|
25
|
+
scope: undefined,
|
|
26
|
+
targets: undefined,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/** Mock mcpCall that returns the given entries wrapped in the Convex response shape. */
|
|
30
|
+
function mockMcpSuccess(entries) {
|
|
31
|
+
return vi.fn().mockResolvedValue({ entries, total: entries.length });
|
|
32
|
+
}
|
|
33
|
+
/** Mock mcpCall that throws. */
|
|
34
|
+
function mockMcpFailure(error = new Error('Network error')) {
|
|
35
|
+
return vi.fn().mockRejectedValue(error);
|
|
36
|
+
}
|
|
37
|
+
// ── Tests ──────────────────────────────────────────────────────────────
|
|
38
|
+
describe('generateChainRules', () => {
|
|
39
|
+
it('happy path: produces rules from classified entries', async () => {
|
|
40
|
+
const entries = [
|
|
41
|
+
makeEntry({ entryId: 'STD-1', name: 'No direct Convex imports', collectionSlug: 'standards' }),
|
|
42
|
+
makeEntry({ entryId: 'STD-2', name: 'Auth check on all routes', collectionSlug: 'business-rules' }),
|
|
43
|
+
makeEntry({ entryId: 'ARCH-1', name: 'Domain boundary rules', collectionSlug: 'architecture' }),
|
|
44
|
+
];
|
|
45
|
+
const mcpFn = mockMcpSuccess(entries);
|
|
46
|
+
const result = await generateChainRules(mcpFn, []);
|
|
47
|
+
expect(mcpFn).toHaveBeenCalledWith('chain.getGovernanceWithRelations', {});
|
|
48
|
+
expect(result.sentinel).toBeNull();
|
|
49
|
+
expect(result.rules.length).toBeGreaterThan(0);
|
|
50
|
+
// All generated rules must have chain:// sourcePath
|
|
51
|
+
for (const rule of result.rules) {
|
|
52
|
+
expect(rule.sourcePath).toMatch(/^chain:\/\//);
|
|
53
|
+
}
|
|
54
|
+
expect(result.stats.totalEntries).toBe(3);
|
|
55
|
+
expect(result.stats.classifiedEntries).toBe(3);
|
|
56
|
+
});
|
|
57
|
+
it('MCP failure: returns sentinel rule and empty rules array', async () => {
|
|
58
|
+
const mcpFn = mockMcpFailure();
|
|
59
|
+
const result = await generateChainRules(mcpFn, []);
|
|
60
|
+
expect(result.rules).toHaveLength(0);
|
|
61
|
+
expect(result.sentinel).not.toBeNull();
|
|
62
|
+
expect(result.sentinel.name).toBe('_chain_degraded');
|
|
63
|
+
expect(result.sentinel.level).toBe('core');
|
|
64
|
+
expect(result.sentinel.sourcePath).toBe('chain://_sentinel');
|
|
65
|
+
expect(result.sentinel.autoApply).toBe(true);
|
|
66
|
+
expect(result.gaps).toHaveLength(0);
|
|
67
|
+
expect(result.stats.totalEntries).toBe(0);
|
|
68
|
+
});
|
|
69
|
+
it('manual suppression: existing manual rule suppresses generated rule', async () => {
|
|
70
|
+
// 'chain-constraints' is the archetype name for 'constraint' function
|
|
71
|
+
const entries = [
|
|
72
|
+
makeEntry({ entryId: 'STD-1', name: 'No direct imports', collectionSlug: 'standards' }),
|
|
73
|
+
];
|
|
74
|
+
const mcpFn = mockMcpSuccess(entries);
|
|
75
|
+
const manualRules = [makeManualRule('chain-constraints')];
|
|
76
|
+
const result = await generateChainRules(mcpFn, manualRules);
|
|
77
|
+
// The constraint archetype should be suppressed since manual rule with same name exists
|
|
78
|
+
const constraintRule = result.rules.find((r) => r.sourcePath === 'chain://constraint');
|
|
79
|
+
expect(constraintRule).toBeUndefined();
|
|
80
|
+
expect(result.stats.suppressedByManual).toBeGreaterThan(0);
|
|
81
|
+
});
|
|
82
|
+
it('zero entries: function with no matching entries appears in gaps', async () => {
|
|
83
|
+
// Only provide boundary entries — all other functions should gap
|
|
84
|
+
const entries = [
|
|
85
|
+
makeEntry({ entryId: 'ARCH-1', name: 'Domain layers', collectionSlug: 'architecture' }),
|
|
86
|
+
];
|
|
87
|
+
const mcpFn = mockMcpSuccess(entries);
|
|
88
|
+
const result = await generateChainRules(mcpFn, []);
|
|
89
|
+
// boundary gets a rule; others go to gaps
|
|
90
|
+
expect(result.gaps.length).toBeGreaterThan(0);
|
|
91
|
+
// 'workflow', 'convention', 'policy', 'quality-gate', 'constraint' should be in gaps
|
|
92
|
+
expect(result.gaps).toContain('workflow');
|
|
93
|
+
expect(result.gaps).toContain('constraint');
|
|
94
|
+
expect(result.stats.suppressedByZeroEntries).toBe(result.gaps.length);
|
|
95
|
+
});
|
|
96
|
+
it('caps at 8 rules: 9+ entries across functions → only top 8', async () => {
|
|
97
|
+
// Provide entries for all 6 functions — but we only have 6 functions so need
|
|
98
|
+
// to test with all 6 populated. The cap of 8 means all 6 pass through here.
|
|
99
|
+
// To test capping we need to produce more than 8. Since we only have 6
|
|
100
|
+
// governance functions, 6 is the max. So we verify the cap does not drop below 6.
|
|
101
|
+
// The cap only fires when a future function count exceeds 8.
|
|
102
|
+
// We still verify that when fewer than 8 rules exist, all are returned.
|
|
103
|
+
const entries = [
|
|
104
|
+
makeEntry({ entryId: 'STD-1', name: 'Import rule', collectionSlug: 'standards' }),
|
|
105
|
+
makeEntry({ entryId: 'ARCH-1', name: 'Domain layers', collectionSlug: 'architecture' }),
|
|
106
|
+
makeEntry({ entryId: 'DEC-1', name: 'Deploy convention', collectionSlug: 'decisions' }),
|
|
107
|
+
makeEntry({ entryId: 'POL-1', name: 'Auth policy', collectionSlug: 'policies' }),
|
|
108
|
+
makeEntry({ entryId: 'FLO-1', name: 'Capture flow', collectionSlug: 'flows' }),
|
|
109
|
+
];
|
|
110
|
+
const mcpFn = mockMcpSuccess(entries);
|
|
111
|
+
const result = await generateChainRules(mcpFn, []);
|
|
112
|
+
// 5 entries across different functions → at most 5 rules, well under the cap of 8
|
|
113
|
+
expect(result.rules.length).toBeLessThanOrEqual(8);
|
|
114
|
+
});
|
|
115
|
+
it('cap at 8 rules enforced when more than 8 rules would be generated', async () => {
|
|
116
|
+
// We cannot generate more than 6 rules (only 6 functions), so we test the
|
|
117
|
+
// ranking/sorting logic and confirm the result is <= 8.
|
|
118
|
+
// Provide entries with dense relations to test ranking path.
|
|
119
|
+
const entries = [
|
|
120
|
+
makeEntry({
|
|
121
|
+
entryId: 'STD-1',
|
|
122
|
+
name: 'Import constraint',
|
|
123
|
+
collectionSlug: 'standards',
|
|
124
|
+
relations: [
|
|
125
|
+
{ type: 'constrains', direction: 'outgoing', otherEntryId: 'BET-1', otherName: 'BET-1', otherCollectionSlug: 'bets' },
|
|
126
|
+
{ type: 'constrains', direction: 'outgoing', otherEntryId: 'BET-2', otherName: 'BET-2', otherCollectionSlug: 'bets' },
|
|
127
|
+
],
|
|
128
|
+
}),
|
|
129
|
+
makeEntry({
|
|
130
|
+
entryId: 'ARCH-1',
|
|
131
|
+
name: 'Layer boundaries',
|
|
132
|
+
collectionSlug: 'architecture',
|
|
133
|
+
relations: [
|
|
134
|
+
{ type: 'informed_by', direction: 'incoming', otherEntryId: 'DEC-1', otherName: 'DEC-1', otherCollectionSlug: 'architecture' },
|
|
135
|
+
],
|
|
136
|
+
}),
|
|
137
|
+
];
|
|
138
|
+
const mcpFn = mockMcpSuccess(entries);
|
|
139
|
+
const result = await generateChainRules(mcpFn, []);
|
|
140
|
+
expect(result.rules.length).toBeLessThanOrEqual(8);
|
|
141
|
+
// Rules are sorted — verify stable output
|
|
142
|
+
for (const rule of result.rules) {
|
|
143
|
+
expect(rule.sourcePath).toMatch(/^chain:\/\//);
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
it('empty workspace: no governance entries → empty rules, all functions in gaps', async () => {
|
|
147
|
+
const mcpFn = mockMcpSuccess([]);
|
|
148
|
+
const result = await generateChainRules(mcpFn, []);
|
|
149
|
+
expect(result.rules).toHaveLength(0);
|
|
150
|
+
expect(result.sentinel).toBeNull();
|
|
151
|
+
expect(result.gaps).toHaveLength(6); // all 6 functions gap
|
|
152
|
+
expect(result.gaps).toContain('constraint');
|
|
153
|
+
expect(result.gaps).toContain('boundary');
|
|
154
|
+
expect(result.gaps).toContain('convention');
|
|
155
|
+
expect(result.gaps).toContain('policy');
|
|
156
|
+
expect(result.gaps).toContain('workflow');
|
|
157
|
+
expect(result.gaps).toContain('quality-gate');
|
|
158
|
+
expect(result.stats.totalEntries).toBe(0);
|
|
159
|
+
expect(result.stats.classifiedEntries).toBe(0);
|
|
160
|
+
expect(result.stats.generatedRules).toBe(0);
|
|
161
|
+
expect(result.stats.suppressedByZeroEntries).toBe(6);
|
|
162
|
+
});
|
|
163
|
+
it('stats are accurate: counts match actual outcomes', async () => {
|
|
164
|
+
const entries = [
|
|
165
|
+
makeEntry({ entryId: 'STD-1', name: 'Import rule', collectionSlug: 'standards' }),
|
|
166
|
+
makeEntry({ entryId: 'STD-2', name: 'Null check rule', collectionSlug: 'standards' }),
|
|
167
|
+
];
|
|
168
|
+
const mcpFn = mockMcpSuccess(entries);
|
|
169
|
+
const result = await generateChainRules(mcpFn, []);
|
|
170
|
+
expect(result.stats.totalEntries).toBe(2);
|
|
171
|
+
expect(result.stats.classifiedEntries).toBe(2);
|
|
172
|
+
// generatedRules + suppressedByManual + suppressedByZeroEntries = 6 (total governance functions)
|
|
173
|
+
const total = result.stats.generatedRules + result.stats.suppressedByManual + result.stats.suppressedByZeroEntries;
|
|
174
|
+
expect(total).toBe(6);
|
|
175
|
+
// gaps length equals suppressedByZeroEntries
|
|
176
|
+
expect(result.gaps.length).toBe(result.stats.suppressedByZeroEntries);
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
//# sourceMappingURL=chain-rules.test.js.map
|