@soleri/core 9.0.4 → 9.2.0
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/dist/brain/intelligence.d.ts +27 -0
- package/dist/brain/intelligence.d.ts.map +1 -1
- package/dist/brain/intelligence.js +160 -14
- package/dist/brain/intelligence.js.map +1 -1
- package/dist/brain/learning-radar.d.ts +4 -0
- package/dist/brain/learning-radar.d.ts.map +1 -1
- package/dist/brain/learning-radar.js +20 -1
- package/dist/brain/learning-radar.js.map +1 -1
- package/dist/brain/strength-scorer.d.ts +31 -0
- package/dist/brain/strength-scorer.d.ts.map +1 -0
- package/dist/brain/strength-scorer.js +264 -0
- package/dist/brain/strength-scorer.js.map +1 -0
- package/dist/chat/agent-loop.d.ts.map +1 -1
- package/dist/chat/agent-loop.js +2 -0
- package/dist/chat/agent-loop.js.map +1 -1
- package/dist/chat/notifications.d.ts.map +1 -1
- package/dist/chat/notifications.js +2 -0
- package/dist/chat/notifications.js.map +1 -1
- package/dist/claudemd/compose.js +1 -1
- package/dist/claudemd/compose.js.map +1 -1
- package/dist/control/intent-router.d.ts.map +1 -1
- package/dist/control/intent-router.js +12 -4
- package/dist/control/intent-router.js.map +1 -1
- package/dist/curator/contradiction-detector.d.ts +27 -0
- package/dist/curator/contradiction-detector.d.ts.map +1 -0
- package/dist/curator/contradiction-detector.js +62 -0
- package/dist/curator/contradiction-detector.js.map +1 -0
- package/dist/curator/curator.d.ts +3 -4
- package/dist/curator/curator.d.ts.map +1 -1
- package/dist/curator/curator.js +90 -525
- package/dist/curator/curator.js.map +1 -1
- package/dist/curator/duplicate-detector.d.ts +14 -0
- package/dist/curator/duplicate-detector.d.ts.map +1 -0
- package/dist/curator/duplicate-detector.js +77 -0
- package/dist/curator/duplicate-detector.js.map +1 -0
- package/dist/curator/health-audit.d.ts +15 -0
- package/dist/curator/health-audit.d.ts.map +1 -0
- package/dist/curator/health-audit.js +97 -0
- package/dist/curator/health-audit.js.map +1 -0
- package/dist/curator/metadata-enricher.d.ts +17 -0
- package/dist/curator/metadata-enricher.d.ts.map +1 -0
- package/dist/curator/metadata-enricher.js +60 -0
- package/dist/curator/metadata-enricher.js.map +1 -0
- package/dist/curator/schema.d.ts +7 -0
- package/dist/curator/schema.d.ts.map +1 -0
- package/dist/curator/schema.js +62 -0
- package/dist/curator/schema.js.map +1 -0
- package/dist/curator/tag-manager.d.ts +36 -0
- package/dist/curator/tag-manager.d.ts.map +1 -0
- package/dist/curator/tag-manager.js +78 -0
- package/dist/curator/tag-manager.js.map +1 -0
- package/dist/engine/bin/soleri-engine.js +24 -3
- package/dist/engine/bin/soleri-engine.js.map +1 -1
- package/dist/engine/core-ops.d.ts.map +1 -1
- package/dist/engine/core-ops.js +23 -8
- package/dist/engine/core-ops.js.map +1 -1
- package/dist/engine/module-manifest.d.ts.map +1 -1
- package/dist/engine/module-manifest.js +22 -2
- package/dist/engine/module-manifest.js.map +1 -1
- package/dist/engine/register-engine.d.ts.map +1 -1
- package/dist/engine/register-engine.js +26 -2
- package/dist/engine/register-engine.js.map +1 -1
- package/dist/errors/retry.d.ts.map +1 -1
- package/dist/errors/retry.js +2 -0
- package/dist/errors/retry.js.map +1 -1
- package/dist/facades/types.d.ts +1 -1
- package/dist/flows/chain-types.d.ts +18 -18
- package/dist/flows/gate-evaluator.d.ts.map +1 -1
- package/dist/flows/gate-evaluator.js +22 -0
- package/dist/flows/gate-evaluator.js.map +1 -1
- package/dist/flows/types.d.ts +157 -28
- package/dist/flows/types.d.ts.map +1 -1
- package/dist/flows/types.js +4 -0
- package/dist/flows/types.js.map +1 -1
- package/dist/index.d.ts +10 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -1
- package/dist/index.js.map +1 -1
- package/dist/intake/intake-pipeline.d.ts.map +1 -1
- package/dist/intake/intake-pipeline.js +1 -0
- package/dist/intake/intake-pipeline.js.map +1 -1
- package/dist/intake/text-ingester.d.ts.map +1 -1
- package/dist/intake/text-ingester.js +2 -0
- package/dist/intake/text-ingester.js.map +1 -1
- package/dist/llm/key-pool.d.ts +1 -1
- package/dist/llm/key-pool.d.ts.map +1 -1
- package/dist/llm/key-pool.js +3 -4
- package/dist/llm/key-pool.js.map +1 -1
- package/dist/llm/utils.d.ts.map +1 -1
- package/dist/llm/utils.js +2 -0
- package/dist/llm/utils.js.map +1 -1
- package/dist/migrations/migration-runner.test-helpers.d.ts +13 -0
- package/dist/migrations/migration-runner.test-helpers.d.ts.map +1 -0
- package/dist/migrations/migration-runner.test-helpers.js +47 -0
- package/dist/migrations/migration-runner.test-helpers.js.map +1 -0
- package/dist/operator/operator-profile.d.ts +44 -0
- package/dist/operator/operator-profile.d.ts.map +1 -0
- package/dist/operator/operator-profile.js +377 -0
- package/dist/operator/operator-profile.js.map +1 -0
- package/dist/operator/operator-signals.d.ts +45 -0
- package/dist/operator/operator-signals.d.ts.map +1 -0
- package/dist/operator/operator-signals.js +228 -0
- package/dist/operator/operator-signals.js.map +1 -0
- package/dist/operator/operator-types.d.ts +360 -0
- package/dist/operator/operator-types.d.ts.map +1 -0
- package/dist/operator/operator-types.js +24 -0
- package/dist/operator/operator-types.js.map +1 -0
- package/dist/packs/types.d.ts +27 -27
- package/dist/paths.d.ts +40 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +98 -0
- package/dist/paths.js.map +1 -0
- package/dist/persistence/index.d.ts +1 -1
- package/dist/persistence/index.d.ts.map +1 -1
- package/dist/persistence/index.js +1 -1
- package/dist/persistence/index.js.map +1 -1
- package/dist/persistence/sqlite-provider.d.ts +2 -0
- package/dist/persistence/sqlite-provider.d.ts.map +1 -1
- package/dist/persistence/sqlite-provider.js +8 -5
- package/dist/persistence/sqlite-provider.js.map +1 -1
- package/dist/planning/evidence-collector.d.ts +13 -1
- package/dist/planning/evidence-collector.d.ts.map +1 -1
- package/dist/planning/evidence-collector.js +33 -0
- package/dist/planning/evidence-collector.js.map +1 -1
- package/dist/planning/gap-analysis.d.ts +5 -4
- package/dist/planning/gap-analysis.d.ts.map +1 -1
- package/dist/planning/gap-analysis.js +7 -341
- package/dist/planning/gap-analysis.js.map +1 -1
- package/dist/planning/gap-passes.d.ts +19 -0
- package/dist/planning/gap-passes.d.ts.map +1 -0
- package/dist/planning/gap-passes.js +157 -0
- package/dist/planning/gap-passes.js.map +1 -0
- package/dist/planning/gap-patterns.d.ts +29 -0
- package/dist/planning/gap-patterns.d.ts.map +1 -0
- package/dist/planning/gap-patterns.js +129 -0
- package/dist/planning/gap-patterns.js.map +1 -0
- package/dist/planning/gap-types.d.ts +1 -1
- package/dist/planning/gap-types.d.ts.map +1 -1
- package/dist/planning/gap-types.js +1 -0
- package/dist/planning/gap-types.js.map +1 -1
- package/dist/planning/github-projection.d.ts +122 -0
- package/dist/planning/github-projection.d.ts.map +1 -0
- package/dist/planning/github-projection.js +294 -0
- package/dist/planning/github-projection.js.map +1 -0
- package/dist/planning/impact-analyzer.d.ts +26 -0
- package/dist/planning/impact-analyzer.d.ts.map +1 -0
- package/dist/planning/impact-analyzer.js +199 -0
- package/dist/planning/impact-analyzer.js.map +1 -0
- package/dist/planning/plan-lifecycle.d.ts +136 -0
- package/dist/planning/plan-lifecycle.d.ts.map +1 -0
- package/dist/planning/plan-lifecycle.js +296 -0
- package/dist/planning/plan-lifecycle.js.map +1 -0
- package/dist/planning/planner-types.d.ts +202 -0
- package/dist/planning/planner-types.d.ts.map +1 -0
- package/dist/planning/planner-types.js +6 -0
- package/dist/planning/planner-types.js.map +1 -0
- package/dist/planning/planner.d.ts +31 -383
- package/dist/planning/planner.d.ts.map +1 -1
- package/dist/planning/planner.js +154 -878
- package/dist/planning/planner.js.map +1 -1
- package/dist/planning/rationalization-detector.d.ts +32 -0
- package/dist/planning/rationalization-detector.d.ts.map +1 -0
- package/dist/planning/rationalization-detector.js +89 -0
- package/dist/planning/rationalization-detector.js.map +1 -0
- package/dist/planning/reconciliation-engine.d.ts +47 -0
- package/dist/planning/reconciliation-engine.d.ts.map +1 -0
- package/dist/planning/reconciliation-engine.js +128 -0
- package/dist/planning/reconciliation-engine.js.map +1 -0
- package/dist/planning/task-verifier.d.ts +85 -0
- package/dist/planning/task-verifier.d.ts.map +1 -0
- package/dist/planning/task-verifier.js +227 -0
- package/dist/planning/task-verifier.js.map +1 -0
- package/dist/plugins/types.d.ts +4 -4
- package/dist/runtime/admin-ops.d.ts +2 -2
- package/dist/runtime/admin-ops.d.ts.map +1 -1
- package/dist/runtime/admin-ops.js +44 -17
- package/dist/runtime/admin-ops.js.map +1 -1
- package/dist/runtime/admin-setup-ops.d.ts.map +1 -1
- package/dist/runtime/admin-setup-ops.js +21 -46
- package/dist/runtime/admin-setup-ops.js.map +1 -1
- package/dist/runtime/archive-ops.d.ts +10 -0
- package/dist/runtime/archive-ops.d.ts.map +1 -0
- package/dist/runtime/archive-ops.js +310 -0
- package/dist/runtime/archive-ops.js.map +1 -0
- package/dist/runtime/capture-ops.d.ts.map +1 -1
- package/dist/runtime/capture-ops.js +42 -7
- package/dist/runtime/capture-ops.js.map +1 -1
- package/dist/runtime/claude-md-helpers.js +1 -1
- package/dist/runtime/claude-md-helpers.js.map +1 -1
- package/dist/runtime/context-health.d.ts +31 -0
- package/dist/runtime/context-health.d.ts.map +1 -0
- package/dist/runtime/context-health.js +57 -0
- package/dist/runtime/context-health.js.map +1 -0
- package/dist/runtime/facades/archive-facade.d.ts +10 -0
- package/dist/runtime/facades/archive-facade.d.ts.map +1 -0
- package/dist/runtime/facades/archive-facade.js +11 -0
- package/dist/runtime/facades/archive-facade.js.map +1 -0
- package/dist/runtime/facades/brain-facade.d.ts.map +1 -1
- package/dist/runtime/facades/brain-facade.js +2 -0
- package/dist/runtime/facades/brain-facade.js.map +1 -1
- package/dist/runtime/facades/chat-facade.d.ts +7 -0
- package/dist/runtime/facades/chat-facade.d.ts.map +1 -1
- package/dist/runtime/facades/chat-facade.js +15 -800
- package/dist/runtime/facades/chat-facade.js.map +1 -1
- package/dist/runtime/facades/chat-service-ops.d.ts +9 -0
- package/dist/runtime/facades/chat-service-ops.d.ts.map +1 -0
- package/dist/runtime/facades/chat-service-ops.js +330 -0
- package/dist/runtime/facades/chat-service-ops.js.map +1 -0
- package/dist/runtime/facades/chat-session-ops.d.ts +8 -0
- package/dist/runtime/facades/chat-session-ops.d.ts.map +1 -0
- package/dist/runtime/facades/chat-session-ops.js +136 -0
- package/dist/runtime/facades/chat-session-ops.js.map +1 -0
- package/dist/runtime/facades/chat-state.d.ts +31 -0
- package/dist/runtime/facades/chat-state.d.ts.map +1 -0
- package/dist/runtime/facades/chat-state.js +32 -0
- package/dist/runtime/facades/chat-state.js.map +1 -0
- package/dist/runtime/facades/chat-transport-ops.d.ts +9 -0
- package/dist/runtime/facades/chat-transport-ops.d.ts.map +1 -0
- package/dist/runtime/facades/chat-transport-ops.js +337 -0
- package/dist/runtime/facades/chat-transport-ops.js.map +1 -0
- package/dist/runtime/facades/control-facade.d.ts.map +1 -1
- package/dist/runtime/facades/control-facade.js +4 -1
- package/dist/runtime/facades/control-facade.js.map +1 -1
- package/dist/runtime/facades/index.d.ts.map +1 -1
- package/dist/runtime/facades/index.js +6 -0
- package/dist/runtime/facades/index.js.map +1 -1
- package/dist/runtime/facades/memory-facade.d.ts.map +1 -1
- package/dist/runtime/facades/memory-facade.js +75 -6
- package/dist/runtime/facades/memory-facade.js.map +1 -1
- package/dist/runtime/facades/operator-facade.d.ts +8 -0
- package/dist/runtime/facades/operator-facade.d.ts.map +1 -0
- package/dist/runtime/facades/operator-facade.js +220 -0
- package/dist/runtime/facades/operator-facade.js.map +1 -0
- package/dist/runtime/facades/orchestrate-facade.js +3 -3
- package/dist/runtime/facades/orchestrate-facade.js.map +1 -1
- package/dist/runtime/facades/plan-facade.d.ts.map +1 -1
- package/dist/runtime/facades/plan-facade.js +39 -6
- package/dist/runtime/facades/plan-facade.js.map +1 -1
- package/dist/runtime/facades/review-facade.d.ts +7 -0
- package/dist/runtime/facades/review-facade.d.ts.map +1 -0
- package/dist/runtime/facades/review-facade.js +8 -0
- package/dist/runtime/facades/review-facade.js.map +1 -0
- package/dist/runtime/facades/sync-facade.d.ts +7 -0
- package/dist/runtime/facades/sync-facade.d.ts.map +1 -0
- package/dist/runtime/facades/sync-facade.js +8 -0
- package/dist/runtime/facades/sync-facade.js.map +1 -0
- package/dist/runtime/facades/vault-facade.d.ts +4 -1
- package/dist/runtime/facades/vault-facade.d.ts.map +1 -1
- package/dist/runtime/facades/vault-facade.js +13 -66
- package/dist/runtime/facades/vault-facade.js.map +1 -1
- package/dist/runtime/github-integration.d.ts +49 -0
- package/dist/runtime/github-integration.d.ts.map +1 -0
- package/dist/runtime/github-integration.js +113 -0
- package/dist/runtime/github-integration.js.map +1 -0
- package/dist/runtime/grading-ops.js +1 -1
- package/dist/runtime/grading-ops.js.map +1 -1
- package/dist/runtime/memory-extra-ops.d.ts.map +1 -1
- package/dist/runtime/memory-extra-ops.js +6 -2
- package/dist/runtime/memory-extra-ops.js.map +1 -1
- package/dist/runtime/orchestrate-ops.d.ts.map +1 -1
- package/dist/runtime/orchestrate-ops.js +367 -40
- package/dist/runtime/orchestrate-ops.js.map +1 -1
- package/dist/runtime/planning-extra-ops.d.ts.map +1 -1
- package/dist/runtime/planning-extra-ops.js +69 -4
- package/dist/runtime/planning-extra-ops.js.map +1 -1
- package/dist/runtime/review-ops.d.ts +10 -0
- package/dist/runtime/review-ops.d.ts.map +1 -0
- package/dist/runtime/review-ops.js +97 -0
- package/dist/runtime/review-ops.js.map +1 -0
- package/dist/runtime/runtime.d.ts.map +1 -1
- package/dist/runtime/runtime.js +27 -12
- package/dist/runtime/runtime.js.map +1 -1
- package/dist/runtime/session-briefing.d.ts +3 -0
- package/dist/runtime/session-briefing.d.ts.map +1 -1
- package/dist/runtime/session-briefing.js +68 -1
- package/dist/runtime/session-briefing.js.map +1 -1
- package/dist/runtime/sync-ops.d.ts +12 -0
- package/dist/runtime/sync-ops.d.ts.map +1 -0
- package/dist/runtime/sync-ops.js +288 -0
- package/dist/runtime/sync-ops.js.map +1 -0
- package/dist/runtime/types.d.ts +10 -4
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/runtime/vault-extra-ops.d.ts +5 -4
- package/dist/runtime/vault-extra-ops.d.ts.map +1 -1
- package/dist/runtime/vault-extra-ops.js +5 -300
- package/dist/runtime/vault-extra-ops.js.map +1 -1
- package/dist/runtime/vault-sharing-ops.d.ts +4 -4
- package/dist/runtime/vault-sharing-ops.d.ts.map +1 -1
- package/dist/runtime/vault-sharing-ops.js +5 -300
- package/dist/runtime/vault-sharing-ops.js.map +1 -1
- package/dist/skills/sync-skills.d.ts +27 -0
- package/dist/skills/sync-skills.d.ts.map +1 -0
- package/dist/skills/sync-skills.js +81 -0
- package/dist/skills/sync-skills.js.map +1 -0
- package/dist/update-check.d.ts +14 -0
- package/dist/update-check.d.ts.map +1 -0
- package/dist/update-check.js +96 -0
- package/dist/update-check.js.map +1 -0
- package/dist/vault/linking.d.ts +10 -12
- package/dist/vault/linking.d.ts.map +1 -1
- package/dist/vault/linking.js +104 -161
- package/dist/vault/linking.js.map +1 -1
- package/dist/vault/vault-entries.d.ts +69 -0
- package/dist/vault/vault-entries.d.ts.map +1 -0
- package/dist/vault/vault-entries.js +257 -0
- package/dist/vault/vault-entries.js.map +1 -0
- package/dist/vault/vault-interfaces.d.ts +153 -0
- package/dist/vault/vault-interfaces.d.ts.map +1 -0
- package/dist/vault/vault-interfaces.js +2 -0
- package/dist/vault/vault-interfaces.js.map +1 -0
- package/dist/vault/vault-maintenance.d.ts +40 -0
- package/dist/vault/vault-maintenance.d.ts.map +1 -0
- package/dist/vault/vault-maintenance.js +142 -0
- package/dist/vault/vault-maintenance.js.map +1 -0
- package/dist/vault/vault-markdown-sync.d.ts +22 -0
- package/dist/vault/vault-markdown-sync.d.ts.map +1 -0
- package/dist/vault/vault-markdown-sync.js +143 -0
- package/dist/vault/vault-markdown-sync.js.map +1 -0
- package/dist/vault/vault-memories.d.ts +61 -0
- package/dist/vault/vault-memories.d.ts.map +1 -0
- package/dist/vault/vault-memories.js +240 -0
- package/dist/vault/vault-memories.js.map +1 -0
- package/dist/vault/vault-schema.d.ts +9 -0
- package/dist/vault/vault-schema.d.ts.map +1 -0
- package/dist/vault/vault-schema.js +179 -0
- package/dist/vault/vault-schema.js.map +1 -0
- package/dist/vault/vault.d.ts +29 -81
- package/dist/vault/vault.d.ts.map +1 -1
- package/dist/vault/vault.js +78 -931
- package/dist/vault/vault.js.map +1 -1
- package/package.json +1 -1
- package/src/agency/agency-manager.test.ts +600 -0
- package/src/agency/default-rules.test.ts +228 -0
- package/src/{__tests__ → brain}/brain-intelligence.test.ts +37 -14
- package/src/{__tests__ → brain}/brain.test.ts +1 -1
- package/src/brain/intelligence.ts +196 -15
- package/src/brain/learning-radar.ts +22 -1
- package/src/{__tests__ → brain}/second-brain-features.test.ts +4 -4
- package/src/{__tests__ → brain}/session-lifecycle.test.ts +2 -2
- package/src/brain/strength-scorer.ts +404 -0
- package/src/capabilities/chain-mapping.test.ts +66 -0
- package/src/capabilities/registry.test.ts +369 -0
- package/src/chat/agent-loop.test.ts +394 -0
- package/src/chat/agent-loop.ts +2 -0
- package/src/{__tests__ → chat}/chat-differentiators.test.ts +3 -3
- package/src/{__tests__ → chat}/chat-enhanced.test.ts +4 -4
- package/src/{__tests__ → chat}/chat-transport.test.ts +6 -6
- package/src/chat/mcp-bridge.test.ts +173 -0
- package/src/chat/notifications.ts +2 -0
- package/src/chat/output-compressor.test.ts +164 -0
- package/src/claudemd/compose.test.ts +178 -0
- package/src/claudemd/compose.ts +1 -1
- package/src/claudemd/inject.test.ts +211 -0
- package/src/context/context-engine.test.ts +461 -0
- package/src/control/identity-manager.test.ts +305 -0
- package/src/control/intent-router.test.ts +360 -0
- package/src/control/intent-router.ts +13 -4
- package/src/curator/classifier.test.ts +104 -0
- package/src/curator/contradiction-detector.test.ts +180 -0
- package/src/curator/contradiction-detector.ts +87 -0
- package/src/{__tests__ → curator}/curator-pipeline-e2e.test.ts +10 -10
- package/src/{__tests__ → curator}/curator.test.ts +77 -1
- package/src/curator/curator.ts +115 -777
- package/src/curator/duplicate-detector.test.ts +183 -0
- package/src/curator/duplicate-detector.ts +103 -0
- package/src/curator/health-audit.ts +126 -0
- package/src/curator/metadata-enricher.ts +84 -0
- package/src/curator/quality-gate.test.ts +135 -0
- package/src/curator/schema.ts +65 -0
- package/src/curator/tag-manager.test.ts +165 -0
- package/src/curator/tag-manager.ts +109 -0
- package/src/domain-packs/inject-rules.test.ts +117 -0
- package/src/domain-packs/knowledge-installer.test.ts +171 -0
- package/src/domain-packs/loader.test.ts +86 -0
- package/src/domain-packs/pack-runtime.test.ts +140 -0
- package/src/domain-packs/skills-installer.test.ts +135 -0
- package/src/domain-packs/token-resolver.test.ts +150 -0
- package/src/domain-packs/types.test.ts +130 -0
- package/src/enforcement/adapters/claude-code.test.ts +216 -0
- package/src/enforcement/registry.test.ts +264 -0
- package/src/engine/bin/soleri-engine.ts +28 -4
- package/src/engine/core-ops.test.ts +254 -0
- package/src/engine/core-ops.ts +25 -8
- package/src/engine/module-manifest.test.ts +124 -0
- package/src/engine/module-manifest.ts +22 -2
- package/src/engine/register-engine.test.ts +230 -0
- package/src/engine/register-engine.ts +26 -2
- package/src/errors/classify.test.ts +199 -0
- package/src/errors/retry.test.ts +156 -0
- package/src/errors/retry.ts +2 -0
- package/src/errors/types.test.ts +108 -0
- package/src/events/event-bus.test.ts +149 -0
- package/src/extensions/middleware.test.ts +234 -0
- package/src/facades/facade-factory.test.ts +424 -0
- package/src/flows/chain-runner.test.ts +273 -0
- package/src/flows/context-router.test.ts +52 -0
- package/src/flows/dispatch-registry.test.ts +128 -0
- package/src/flows/epilogue.test.ts +107 -0
- package/src/flows/executor.test.ts +263 -0
- package/src/flows/gate-evaluator.test.ts +194 -0
- package/src/flows/gate-evaluator.ts +25 -0
- package/src/flows/types.ts +4 -0
- package/src/governance/governance.test.ts +726 -0
- package/src/health/health-registry.test.ts +186 -0
- package/src/health/vault-integrity.test.ts +110 -0
- package/src/index.ts +92 -0
- package/src/intake/content-classifier.test.ts +209 -0
- package/src/intake/dedup-gate.test.ts +131 -0
- package/src/intake/intake-pipeline.test.ts +506 -0
- package/src/intake/intake-pipeline.ts +1 -0
- package/src/intake/text-ingester.test.ts +194 -0
- package/src/intake/text-ingester.ts +2 -0
- package/src/llm/key-pool.test.ts +236 -0
- package/src/llm/key-pool.ts +3 -4
- package/src/llm/llm-client.test.ts +345 -0
- package/src/llm/oauth-discovery.test.ts +180 -0
- package/src/llm/utils.test.ts +327 -0
- package/src/llm/utils.ts +2 -0
- package/src/{__tests__ → logging}/logger.test.ts +41 -62
- package/src/loop/loop-manager.test.ts +519 -0
- package/src/migrations/migration-runner.edge-cases.test.ts +319 -0
- package/src/migrations/migration-runner.test-helpers.ts +64 -0
- package/src/migrations/migration-runner.test.ts +385 -0
- package/src/operator/auto-signal-pipeline.test.ts +207 -0
- package/src/operator/operator-profile-extended.test.ts +320 -0
- package/src/operator/operator-profile.test.ts +314 -0
- package/src/operator/operator-profile.ts +469 -0
- package/src/operator/operator-signals-extended.test.ts +245 -0
- package/src/operator/operator-signals.test.ts +281 -0
- package/src/operator/operator-signals.ts +261 -0
- package/src/operator/operator-types.ts +444 -0
- package/src/operator/prompts/hook-precompact-operator-dispatch.md +94 -0
- package/src/operator/prompts/subagent-soft-signal-extractor.md +125 -0
- package/src/operator/prompts/subagent-synthesis-cognition.md +181 -0
- package/src/operator/prompts/subagent-synthesis-communication.md +140 -0
- package/src/operator/prompts/subagent-synthesis-technical.md +160 -0
- package/src/operator/prompts/subagent-synthesis-trust.md +143 -0
- package/src/{__tests__ → packs}/pack-lockfile.test.ts +3 -3
- package/src/{__tests__ → packs}/pack-system.test.ts +2 -2
- package/src/paths.ts +115 -0
- package/src/persistence/index.ts +1 -1
- package/src/persistence/sqlite-provider.test.ts +540 -0
- package/src/persistence/sqlite-provider.ts +8 -5
- package/src/persona/defaults.test.ts +59 -0
- package/src/persona/loader.test.ts +67 -0
- package/src/persona/prompt-generator.test.ts +127 -0
- package/src/planning/evidence-collector.test.ts +406 -0
- package/src/planning/evidence-collector.ts +50 -0
- package/src/planning/gap-analysis-alternatives.test.ts +169 -0
- package/src/planning/gap-analysis.ts +21 -636
- package/src/planning/gap-passes.test.ts +372 -0
- package/src/planning/gap-passes.ts +298 -0
- package/src/planning/gap-patterns.test.ts +320 -0
- package/src/planning/gap-patterns.ts +234 -0
- package/src/planning/gap-types.ts +4 -1
- package/src/planning/github-projection.test.ts +177 -0
- package/src/planning/github-projection.ts +425 -0
- package/src/planning/impact-analyzer.test.ts +180 -0
- package/src/planning/impact-analyzer.ts +264 -0
- package/src/planning/plan-lifecycle.test.ts +312 -0
- package/src/planning/plan-lifecycle.ts +346 -0
- package/src/planning/planner-types.ts +215 -0
- package/src/{__tests__ → planning}/planner.test.ts +169 -15
- package/src/planning/planner.ts +197 -1228
- package/src/planning/rationalization-detector.test.ts +171 -0
- package/src/planning/rationalization-detector.ts +138 -0
- package/src/planning/reconciliation-engine.test.ts +141 -0
- package/src/planning/reconciliation-engine.ts +162 -0
- package/src/planning/task-verifier.test.ts +235 -0
- package/src/planning/task-verifier.ts +303 -0
- package/src/planning/verification-protocol.test.ts +201 -0
- package/src/playbooks/generic/generic-playbooks.test.ts +438 -0
- package/src/playbooks/index.test.ts +77 -0
- package/src/playbooks/playbook-executor.test.ts +255 -0
- package/src/playbooks/playbook-registry.test.ts +232 -0
- package/src/playbooks/playbook-seeder.test.ts +153 -0
- package/src/plugins/plugin-loader.test.ts +212 -0
- package/src/plugins/plugin-registry.test.ts +272 -0
- package/src/project/project-registry.test.ts +428 -0
- package/src/prompts/parser.test.ts +100 -0
- package/src/prompts/template-manager.test.ts +109 -0
- package/src/{__tests__ → queue}/async-infrastructure.test.ts +3 -3
- package/src/queue/job-queue.test.ts +331 -0
- package/src/queue/pipeline-runner.test.ts +209 -0
- package/src/runtime/admin-extra-ops.test.ts +527 -0
- package/src/runtime/admin-ops.test.ts +257 -0
- package/src/runtime/admin-ops.ts +45 -17
- package/src/runtime/admin-setup-ops.test.ts +328 -0
- package/src/runtime/admin-setup-ops.ts +20 -43
- package/src/runtime/archive-ops.test.ts +269 -0
- package/src/runtime/archive-ops.ts +347 -0
- package/src/runtime/capture-ops.test.ts +433 -0
- package/src/runtime/capture-ops.ts +50 -8
- package/src/runtime/chain-ops.test.ts +149 -0
- package/src/runtime/claude-md-helpers.test.ts +191 -0
- package/src/runtime/claude-md-helpers.ts +1 -1
- package/src/runtime/context-health.test.ts +78 -0
- package/src/runtime/context-health.ts +85 -0
- package/src/runtime/curator-extra-ops.test.ts +202 -0
- package/src/runtime/deprecation.test.ts +98 -0
- package/src/runtime/domain-ops.test.ts +268 -0
- package/src/runtime/facades/admin-facade.test.ts +333 -0
- package/src/runtime/facades/agency-facade.test.ts +278 -0
- package/src/runtime/facades/archive-facade.test.ts +294 -0
- package/src/runtime/facades/archive-facade.ts +14 -0
- package/src/runtime/facades/brain-facade.test.ts +714 -0
- package/src/runtime/facades/brain-facade.ts +2 -0
- package/src/runtime/facades/chat-facade.test.ts +166 -0
- package/src/runtime/facades/chat-facade.ts +15 -906
- package/src/runtime/facades/chat-service-ops.test.ts +276 -0
- package/src/runtime/facades/chat-service-ops.ts +374 -0
- package/src/runtime/facades/chat-session-ops.test.ts +197 -0
- package/src/runtime/facades/chat-session-ops.ts +146 -0
- package/src/runtime/facades/chat-state.ts +60 -0
- package/src/runtime/facades/chat-transport-ops.test.ts +269 -0
- package/src/runtime/facades/chat-transport-ops.ts +380 -0
- package/src/runtime/facades/context-facade.test.ts +108 -0
- package/src/runtime/facades/control-facade.test.ts +436 -0
- package/src/runtime/facades/control-facade.ts +6 -1
- package/src/runtime/facades/curator-facade.test.ts +303 -0
- package/src/runtime/facades/index.ts +6 -0
- package/src/runtime/facades/loop-facade.test.ts +245 -0
- package/src/runtime/facades/memory-facade.test.ts +269 -0
- package/src/runtime/facades/memory-facade.ts +78 -6
- package/src/runtime/facades/operator-facade.test.ts +208 -0
- package/src/runtime/facades/operator-facade.ts +236 -0
- package/src/runtime/facades/orchestrate-facade.test.ts +185 -0
- package/src/runtime/facades/orchestrate-facade.ts +3 -3
- package/src/runtime/facades/plan-facade.test.ts +266 -0
- package/src/runtime/facades/plan-facade.ts +42 -6
- package/src/runtime/facades/review-facade.test.ts +82 -0
- package/src/runtime/facades/review-facade.ts +11 -0
- package/src/runtime/facades/sync-facade.test.ts +113 -0
- package/src/runtime/facades/sync-facade.ts +11 -0
- package/src/runtime/facades/vault-facade.test.ts +631 -0
- package/src/runtime/facades/vault-facade.ts +15 -70
- package/src/runtime/feature-flags.test.ts +140 -0
- package/src/runtime/github-integration.test.ts +89 -0
- package/src/runtime/github-integration.ts +159 -0
- package/src/runtime/grading-ops.test.ts +141 -0
- package/src/runtime/grading-ops.ts +1 -1
- package/src/runtime/intake-ops.test.ts +208 -0
- package/src/runtime/loop-ops.test.ts +238 -0
- package/src/runtime/memory-cross-project-ops.test.ts +177 -0
- package/src/runtime/memory-extra-ops.test.ts +453 -0
- package/src/runtime/memory-extra-ops.ts +6 -2
- package/src/runtime/orchestrate-ops.test.ts +302 -0
- package/src/runtime/orchestrate-ops.ts +435 -46
- package/src/runtime/pack-ops.test.ts +158 -0
- package/src/runtime/planning-extra-ops.test.ts +583 -0
- package/src/runtime/planning-extra-ops.ts +72 -4
- package/src/{__tests__ → runtime}/playbook-ops-execution.test.ts +3 -3
- package/src/runtime/playbook-ops.test.ts +262 -0
- package/src/runtime/plugin-ops.test.ts +201 -0
- package/src/runtime/project-ops.test.ts +235 -0
- package/src/runtime/review-ops.test.ts +142 -0
- package/src/runtime/review-ops.ts +99 -0
- package/src/runtime/runtime.test.ts +363 -0
- package/src/runtime/runtime.ts +39 -12
- package/src/runtime/session-briefing.test.ts +302 -0
- package/src/runtime/session-briefing.ts +80 -1
- package/src/runtime/sync-ops.test.ts +221 -0
- package/src/runtime/sync-ops.ts +325 -0
- package/src/runtime/telemetry-ops.test.ts +132 -0
- package/src/runtime/types.ts +10 -4
- package/src/runtime/vault-extra-ops.test.ts +246 -0
- package/src/runtime/vault-extra-ops.ts +5 -332
- package/src/runtime/vault-linking-ops.test.ts +237 -0
- package/src/runtime/vault-sharing-ops.test.ts +130 -0
- package/src/runtime/vault-sharing-ops.ts +5 -329
- package/src/skills/sync-skills.ts +108 -0
- package/src/streams/normalize.test.ts +95 -0
- package/src/streams/replayable-stream.test.ts +166 -0
- package/src/telemetry/telemetry.test.ts +143 -0
- package/src/transport/http-server.test.ts +394 -0
- package/src/transport/lsp-server.test.ts +458 -0
- package/src/transport/rate-limiter.test.ts +126 -0
- package/src/transport/session-manager.test.ts +133 -0
- package/src/transport/token-auth.test.ts +136 -0
- package/src/transport/ws-server.test.ts +294 -0
- package/src/update-check.ts +111 -0
- package/src/vault/__tests__/vault-characterization.test.ts +168 -0
- package/src/vault/content-hash.test.ts +78 -0
- package/src/vault/git-vault-sync.test.ts +234 -0
- package/src/vault/knowledge-review.test.ts +269 -0
- package/src/vault/linking.test.ts +358 -0
- package/src/vault/linking.ts +149 -183
- package/src/vault/obsidian-sync.test.ts +342 -0
- package/src/vault/playbook.test.ts +152 -0
- package/src/vault/scope-detector.test.ts +187 -0
- package/src/vault/vault-branching.test.ts +250 -0
- package/src/{__tests__ → vault}/vault-connect.test.ts +1 -1
- package/src/vault/vault-entries.ts +282 -0
- package/src/vault/vault-interfaces.ts +56 -0
- package/src/vault/vault-maintenance.ts +205 -0
- package/src/vault/vault-manager.test.ts +206 -0
- package/src/vault/vault-markdown-sync.test.ts +203 -0
- package/src/vault/vault-markdown-sync.ts +160 -0
- package/src/vault/vault-memories.ts +339 -0
- package/src/{__tests__ → vault}/vault-scaling.test.ts +1 -1
- package/src/vault/vault-schema.ts +181 -0
- package/src/{__tests__ → vault}/vault-sharing.test.ts +4 -4
- package/src/{__tests__ → vault}/vault.test.ts +2 -2
- package/src/vault/vault.ts +89 -1171
- package/dist/cognee/client.d.ts +0 -43
- package/dist/cognee/client.d.ts.map +0 -1
- package/dist/cognee/client.js +0 -375
- package/dist/cognee/client.js.map +0 -1
- package/dist/cognee/sync-manager.d.ts +0 -153
- package/dist/cognee/sync-manager.d.ts.map +0 -1
- package/dist/cognee/sync-manager.js +0 -390
- package/dist/cognee/sync-manager.js.map +0 -1
- package/dist/cognee/types.d.ts +0 -62
- package/dist/cognee/types.d.ts.map +0 -1
- package/dist/cognee/types.js +0 -3
- package/dist/cognee/types.js.map +0 -1
- package/dist/governance/index.d.ts +0 -3
- package/dist/governance/index.d.ts.map +0 -1
- package/dist/governance/index.js +0 -2
- package/dist/governance/index.js.map +0 -1
- package/dist/health/doctor-checks.d.ts +0 -15
- package/dist/health/doctor-checks.d.ts.map +0 -1
- package/dist/health/doctor-checks.js +0 -98
- package/dist/health/doctor-checks.js.map +0 -1
- package/dist/persistence/postgres-provider.d.ts +0 -81
- package/dist/persistence/postgres-provider.d.ts.map +0 -1
- package/dist/persistence/postgres-provider.js +0 -256
- package/dist/persistence/postgres-provider.js.map +0 -1
- package/dist/runtime/cognee-sync-ops.d.ts +0 -12
- package/dist/runtime/cognee-sync-ops.d.ts.map +0 -1
- package/dist/runtime/cognee-sync-ops.js +0 -93
- package/dist/runtime/cognee-sync-ops.js.map +0 -1
- package/dist/runtime/core-ops.d.ts +0 -23
- package/dist/runtime/core-ops.d.ts.map +0 -1
- package/dist/runtime/core-ops.js +0 -1296
- package/dist/runtime/core-ops.js.map +0 -1
- package/dist/runtime/facades/cognee-facade.d.ts +0 -8
- package/dist/runtime/facades/cognee-facade.d.ts.map +0 -1
- package/dist/runtime/facades/cognee-facade.js +0 -156
- package/dist/runtime/facades/cognee-facade.js.map +0 -1
- package/src/__tests__/admin-extra-ops.test.ts +0 -484
- package/src/__tests__/admin-ops.test.ts +0 -268
- package/src/__tests__/admin-setup-ops.test.ts +0 -355
- package/src/__tests__/agency-manager.test.ts +0 -374
- package/src/__tests__/agent-loop.test.ts +0 -256
- package/src/__tests__/capture-ops.test.ts +0 -784
- package/src/__tests__/claudemd.test.ts +0 -282
- package/src/__tests__/content-hash.test.ts +0 -60
- package/src/__tests__/context-engine.test.ts +0 -251
- package/src/__tests__/core-ops.test.ts +0 -550
- package/src/__tests__/curator-extra-ops.test.ts +0 -383
- package/src/__tests__/deprecation.test.ts +0 -78
- package/src/__tests__/domain-ops.test.ts +0 -226
- package/src/__tests__/domain-packs.test.ts +0 -421
- package/src/__tests__/enforcement.test.ts +0 -153
- package/src/__tests__/errors.test.ts +0 -388
- package/src/__tests__/extensions.test.ts +0 -233
- package/src/__tests__/facade-factory.test.ts +0 -271
- package/src/__tests__/feature-flags.test.ts +0 -137
- package/src/__tests__/flows.test.ts +0 -604
- package/src/__tests__/git-vault-sync.test.ts +0 -230
- package/src/__tests__/governance.test.ts +0 -522
- package/src/__tests__/grading-ops.test.ts +0 -361
- package/src/__tests__/health-registry.test.ts +0 -173
- package/src/__tests__/identity-manager.test.ts +0 -243
- package/src/__tests__/intake-pipeline.test.ts +0 -162
- package/src/__tests__/intent-router.test.ts +0 -222
- package/src/__tests__/knowledge-review.test.ts +0 -104
- package/src/__tests__/llm-client.test.ts +0 -69
- package/src/__tests__/llm.test.ts +0 -556
- package/src/__tests__/loader.test.ts +0 -176
- package/src/__tests__/loop-ops.test.ts +0 -469
- package/src/__tests__/lsp-transport.test.ts +0 -442
- package/src/__tests__/memory-cross-project-ops.test.ts +0 -248
- package/src/__tests__/memory-extra-ops.test.ts +0 -352
- package/src/__tests__/migration-runner.test.ts +0 -170
- package/src/__tests__/module-manifest-drift.test.ts +0 -59
- package/src/__tests__/normalize.test.ts +0 -85
- package/src/__tests__/obsidian-sync.test.ts +0 -354
- package/src/__tests__/orchestrate-ops.test.ts +0 -289
- package/src/__tests__/pack-ops.test.ts +0 -146
- package/src/__tests__/persistence.test.ts +0 -291
- package/src/__tests__/planning-extra-ops.test.ts +0 -706
- package/src/__tests__/playbook-executor.test.ts +0 -249
- package/src/__tests__/playbook-registry.test.ts +0 -326
- package/src/__tests__/playbook-seeder.test.ts +0 -163
- package/src/__tests__/playbook.test.ts +0 -389
- package/src/__tests__/plugin-ops.test.ts +0 -411
- package/src/__tests__/plugin-system.test.ts +0 -509
- package/src/__tests__/project-ops.test.ts +0 -381
- package/src/__tests__/replayable-stream.test.ts +0 -177
- package/src/__tests__/runtime.test.ts +0 -95
- package/src/__tests__/scope-detector.test.ts +0 -121
- package/src/__tests__/template-manager.test.ts +0 -222
- package/src/__tests__/token-resolver.test.ts +0 -79
- package/src/__tests__/transport.test.ts +0 -758
- package/src/__tests__/vault-branching.test.ts +0 -274
- package/src/__tests__/vault-extra-ops.test.ts +0 -482
- package/src/__tests__/vault-integrity.test.ts +0 -71
- package/src/__tests__/vault-manager.test.ts +0 -238
- package/src/__tests__/ws-transport.test.ts +0 -479
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for gap-passes.ts — passes 5-8 (clarity, semantic quality,
|
|
3
|
+
* knowledge depth, alternative analysis).
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { describe, it, expect } from 'vitest';
|
|
7
|
+
import type { Plan, PlanAlternative } from './planner.js';
|
|
8
|
+
import {
|
|
9
|
+
analyzeClarity,
|
|
10
|
+
analyzeSemanticQuality,
|
|
11
|
+
analyzeKnowledgeDepth,
|
|
12
|
+
analyzeAlternatives,
|
|
13
|
+
AMBIGUOUS_WORDS,
|
|
14
|
+
GENERIC_OBJECTIVE_PATTERNS,
|
|
15
|
+
RATIONALE_INDICATORS,
|
|
16
|
+
SHALLOW_INDICATORS,
|
|
17
|
+
KNOWLEDGE_INDICATORS,
|
|
18
|
+
NAMED_PATTERN_REGEX,
|
|
19
|
+
} from './gap-passes.js';
|
|
20
|
+
|
|
21
|
+
function makePlan(overrides: Partial<Plan> = {}): Plan {
|
|
22
|
+
return {
|
|
23
|
+
id: 'plan-test',
|
|
24
|
+
objective: 'Implement user authentication with JWT tokens and session management',
|
|
25
|
+
scope: 'Auth module, middleware, and user service. Does not include OAuth providers.',
|
|
26
|
+
status: 'draft',
|
|
27
|
+
decisions: [
|
|
28
|
+
{ decision: 'Use JWT for stateless auth', rationale: 'Because it scales horizontally without shared session store' },
|
|
29
|
+
],
|
|
30
|
+
tasks: [
|
|
31
|
+
{ id: 'task-1', title: 'Add JWT signing', description: 'Implement JWT sign/verify using built-in crypto module', status: 'pending', updatedAt: Date.now() },
|
|
32
|
+
{ id: 'task-2', title: 'Add auth middleware', description: 'Create Express middleware that validates JWT from Authorization header', status: 'pending', updatedAt: Date.now() },
|
|
33
|
+
{ id: 'task-3', title: 'Add login endpoint', description: 'POST /auth/login returns JWT after verifying credentials', status: 'pending', updatedAt: Date.now() },
|
|
34
|
+
{ id: 'task-4', title: 'Add test coverage', description: 'Test JWT signing, middleware rejection, and login flow end-to-end', status: 'pending', updatedAt: Date.now() },
|
|
35
|
+
],
|
|
36
|
+
checks: [],
|
|
37
|
+
createdAt: Date.now(),
|
|
38
|
+
updatedAt: Date.now(),
|
|
39
|
+
...overrides,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function makeAlternative(overrides: Partial<PlanAlternative> = {}): PlanAlternative {
|
|
44
|
+
return {
|
|
45
|
+
approach: 'Use session cookies instead of JWT',
|
|
46
|
+
pros: ['Simpler implementation'],
|
|
47
|
+
cons: ['Requires shared session store'],
|
|
48
|
+
rejected_reason: 'JWT is stateless and scales better for our architecture',
|
|
49
|
+
...overrides,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
describe('Pattern constants (passes 5-8)', () => {
|
|
54
|
+
it('AMBIGUOUS_WORDS contains common vague terms', () => {
|
|
55
|
+
expect(AMBIGUOUS_WORDS).toContain('maybe');
|
|
56
|
+
expect(AMBIGUOUS_WORDS).toContain('probably');
|
|
57
|
+
expect(AMBIGUOUS_WORDS).toContain('etc');
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('GENERIC_OBJECTIVE_PATTERNS matches simple verb-noun objectives', () => {
|
|
61
|
+
expect(GENERIC_OBJECTIVE_PATTERNS.some((p) => p.test('Create something'))).toBe(true);
|
|
62
|
+
expect(GENERIC_OBJECTIVE_PATTERNS.some((p) => p.test('Fix bug'))).toBe(true);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('GENERIC_OBJECTIVE_PATTERNS does not match detailed objectives', () => {
|
|
66
|
+
expect(GENERIC_OBJECTIVE_PATTERNS.some((p) => p.test('Create a user auth module with JWT'))).toBe(false);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('RATIONALE_INDICATORS contains reasoning words', () => {
|
|
70
|
+
expect(RATIONALE_INDICATORS).toContain('because');
|
|
71
|
+
expect(RATIONALE_INDICATORS).toContain('due to');
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('SHALLOW_INDICATORS contains subjective words', () => {
|
|
75
|
+
expect(SHALLOW_INDICATORS).toContain('better');
|
|
76
|
+
expect(SHALLOW_INDICATORS).toContain('good');
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('KNOWLEDGE_INDICATORS match domain patterns', () => {
|
|
80
|
+
expect(KNOWLEDGE_INDICATORS.some((p) => p.test('vault pattern'))).toBe(true);
|
|
81
|
+
expect(KNOWLEDGE_INDICATORS.some((p) => p.test('WCAG 2.1'))).toBe(true);
|
|
82
|
+
expect(KNOWLEDGE_INDICATORS.some((p) => p.test('aria-label'))).toBe(true);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('NAMED_PATTERN_REGEX matches hyphenated identifiers', () => {
|
|
86
|
+
expect(NAMED_PATTERN_REGEX.test('zod-form-validation')).toBe(true);
|
|
87
|
+
expect(NAMED_PATTERN_REGEX.test('simple')).toBe(false);
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
describe('Pass 5: Clarity', () => {
|
|
92
|
+
it('flags ambiguous language in objective', () => {
|
|
93
|
+
const plan = makePlan({
|
|
94
|
+
objective: 'Maybe implement some authentication features probably with JWT',
|
|
95
|
+
scope: 'Auth module. Not including OAuth.',
|
|
96
|
+
});
|
|
97
|
+
const gaps = analyzeClarity(plan);
|
|
98
|
+
expect(gaps.some((g) => g._trigger?.startsWith('ambiguous_words:'))).toBe(true);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('does not flag clear language', () => {
|
|
102
|
+
const plan = makePlan();
|
|
103
|
+
const gaps = analyzeClarity(plan);
|
|
104
|
+
expect(gaps.some((g) => g._trigger?.startsWith('ambiguous_words:'))).toBe(false);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it('flags tasks with very short descriptions', () => {
|
|
108
|
+
const plan = makePlan({
|
|
109
|
+
tasks: [
|
|
110
|
+
{ id: 't1', title: 'Do thing', description: 'Short', status: 'pending', updatedAt: Date.now() },
|
|
111
|
+
{ id: 't2', title: 'Do other', description: '', status: 'pending', updatedAt: Date.now() },
|
|
112
|
+
],
|
|
113
|
+
});
|
|
114
|
+
const gaps = analyzeClarity(plan);
|
|
115
|
+
expect(gaps.some((g) => g._trigger === 'short_task_descriptions')).toBe(true);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it('does not flag tasks with adequate descriptions', () => {
|
|
119
|
+
const plan = makePlan();
|
|
120
|
+
const gaps = analyzeClarity(plan);
|
|
121
|
+
expect(gaps.some((g) => g._trigger === 'short_task_descriptions')).toBe(false);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it('limits ambiguous words shown to 5', () => {
|
|
125
|
+
const plan = makePlan({
|
|
126
|
+
objective: 'Maybe perhaps we might could possibly somehow probably do various several things soon with some easy simple appropriate changes etc',
|
|
127
|
+
scope: 'Everything. Not limited.',
|
|
128
|
+
});
|
|
129
|
+
const gaps = analyzeClarity(plan);
|
|
130
|
+
const ambiguousGap = gaps.find((g) => g._trigger?.startsWith('ambiguous_words:'));
|
|
131
|
+
expect(ambiguousGap).toBeDefined();
|
|
132
|
+
// Description should mention (+N more) when more than 5 words found
|
|
133
|
+
if (ambiguousGap) {
|
|
134
|
+
expect(ambiguousGap.description).toContain('+');
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
describe('Pass 6: Semantic Quality', () => {
|
|
140
|
+
it('flags generic objective', () => {
|
|
141
|
+
const plan = makePlan({ objective: 'Create something' });
|
|
142
|
+
const gaps = analyzeSemanticQuality(plan);
|
|
143
|
+
expect(gaps.some((g) => g._trigger === 'generic_objective')).toBe(true);
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it('flags short objective (< 5 words)', () => {
|
|
147
|
+
const plan = makePlan({ objective: 'Fix the auth bug' });
|
|
148
|
+
const gaps = analyzeSemanticQuality(plan);
|
|
149
|
+
expect(gaps.some((g) => g._trigger === 'generic_objective')).toBe(true);
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it('does not flag detailed objective', () => {
|
|
153
|
+
const plan = makePlan();
|
|
154
|
+
const gaps = analyzeSemanticQuality(plan);
|
|
155
|
+
expect(gaps.some((g) => g._trigger === 'generic_objective')).toBe(false);
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it('flags too few tasks', () => {
|
|
159
|
+
const plan = makePlan({
|
|
160
|
+
tasks: [
|
|
161
|
+
{ id: 't1', title: 'Single task', description: 'Do everything in one task', status: 'pending', updatedAt: Date.now() },
|
|
162
|
+
],
|
|
163
|
+
});
|
|
164
|
+
const gaps = analyzeSemanticQuality(plan);
|
|
165
|
+
expect(gaps.some((g) => g._trigger === 'too_few_tasks')).toBe(true);
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it('flags too many tasks (> 20)', () => {
|
|
169
|
+
const tasks = Array.from({ length: 21 }, (_, i) => ({
|
|
170
|
+
id: `t${i}`, title: `Task ${i}`, description: `Description for task ${i} with enough detail`, status: 'pending' as const, updatedAt: Date.now(),
|
|
171
|
+
}));
|
|
172
|
+
const plan = makePlan({ tasks });
|
|
173
|
+
const gaps = analyzeSemanticQuality(plan);
|
|
174
|
+
expect(gaps.some((g) => g._trigger === 'too_many_tasks')).toBe(true);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it('flags shallow rationale in decisions', () => {
|
|
178
|
+
const plan = makePlan({
|
|
179
|
+
decisions: [{ decision: 'This approach is better', rationale: 'It is good and nice' }],
|
|
180
|
+
});
|
|
181
|
+
const gaps = analyzeSemanticQuality(plan);
|
|
182
|
+
expect(gaps.some((g) => g._trigger === 'shallow_rationale')).toBe(true);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
it('does not flag decisions with proper rationale', () => {
|
|
186
|
+
const plan = makePlan({
|
|
187
|
+
decisions: [{ decision: 'Use JWT', rationale: 'This is better because it scales horizontally' }],
|
|
188
|
+
});
|
|
189
|
+
const gaps = analyzeSemanticQuality(plan);
|
|
190
|
+
expect(gaps.some((g) => g._trigger === 'shallow_rationale')).toBe(false);
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it('flags duplicate task titles', () => {
|
|
194
|
+
const plan = makePlan({
|
|
195
|
+
tasks: [
|
|
196
|
+
{ id: 't1', title: 'Implement feature', description: 'First implementation', status: 'pending', updatedAt: Date.now() },
|
|
197
|
+
{ id: 't2', title: 'Implement feature', description: 'Duplicate title', status: 'pending', updatedAt: Date.now() },
|
|
198
|
+
{ id: 't3', title: 'Test feature', description: 'Test the feature with assertions', status: 'pending', updatedAt: Date.now() },
|
|
199
|
+
],
|
|
200
|
+
});
|
|
201
|
+
const gaps = analyzeSemanticQuality(plan);
|
|
202
|
+
expect(gaps.some((g) => g._trigger === 'duplicate_task_titles')).toBe(true);
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
it('flags no decisions for multi-task plans', () => {
|
|
206
|
+
const plan = makePlan({ decisions: [] });
|
|
207
|
+
const gaps = analyzeSemanticQuality(plan);
|
|
208
|
+
expect(gaps.some((g) => g._trigger === 'no_decisions')).toBe(true);
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
it('does not flag no decisions for < 3 tasks', () => {
|
|
212
|
+
const plan = makePlan({
|
|
213
|
+
decisions: [],
|
|
214
|
+
tasks: [
|
|
215
|
+
{ id: 't1', title: 'Single task', description: 'Do the thing', status: 'pending', updatedAt: Date.now() },
|
|
216
|
+
],
|
|
217
|
+
});
|
|
218
|
+
const gaps = analyzeSemanticQuality(plan);
|
|
219
|
+
expect(gaps.some((g) => g._trigger === 'no_decisions')).toBe(false);
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
describe('Pass 7: Knowledge Depth', () => {
|
|
224
|
+
it('awards bonus for 5+ vault pattern references', () => {
|
|
225
|
+
const plan = makePlan({
|
|
226
|
+
tasks: [
|
|
227
|
+
{ id: 't1', title: 'Apply patterns', description: 'Use zod-form-validation and react-query-caching and error-boundary-pattern', status: 'pending', updatedAt: Date.now() },
|
|
228
|
+
{ id: 't2', title: 'More patterns', description: 'Use accessibility-focus-ring and semantic-token-usage and component-variant-pattern', status: 'pending', updatedAt: Date.now() },
|
|
229
|
+
{ id: 't3', title: 'Testing', description: 'Test with vitest-snapshot-testing approach', status: 'pending', updatedAt: Date.now() },
|
|
230
|
+
],
|
|
231
|
+
});
|
|
232
|
+
const gaps = analyzeKnowledgeDepth(plan);
|
|
233
|
+
expect(gaps.some((g) => g._trigger === 'vault_pattern_refs_high')).toBe(true);
|
|
234
|
+
expect(gaps.some((g) => g._trigger === 'vault_pattern_density')).toBe(true);
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
it('awards bonus for 2-4 vault pattern references', () => {
|
|
238
|
+
const plan = makePlan({
|
|
239
|
+
tasks: [
|
|
240
|
+
{ id: 't1', title: 'Apply patterns', description: 'Use zod-form-validation and react-query-caching', status: 'pending', updatedAt: Date.now() },
|
|
241
|
+
{ id: 't2', title: 'Build', description: 'Build the component', status: 'pending', updatedAt: Date.now() },
|
|
242
|
+
{ id: 't3', title: 'Test', description: 'Run the test suite', status: 'pending', updatedAt: Date.now() },
|
|
243
|
+
],
|
|
244
|
+
});
|
|
245
|
+
const gaps = analyzeKnowledgeDepth(plan);
|
|
246
|
+
expect(gaps.some((g) => g._trigger === 'vault_pattern_refs_medium')).toBe(true);
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
it('awards bonus for high acceptance criteria coverage', () => {
|
|
250
|
+
const plan = makePlan({
|
|
251
|
+
tasks: [
|
|
252
|
+
{ id: 't1', title: 'T1', description: 'Desc 1', status: 'pending', updatedAt: Date.now(), acceptanceCriteria: ['Criteria A'] },
|
|
253
|
+
{ id: 't2', title: 'T2', description: 'Desc 2', status: 'pending', updatedAt: Date.now(), acceptanceCriteria: ['Criteria B'] },
|
|
254
|
+
{ id: 't3', title: 'T3', description: 'Desc 3', status: 'pending', updatedAt: Date.now(), acceptanceCriteria: ['Criteria C'] },
|
|
255
|
+
{ id: 't4', title: 'T4', description: 'Desc 4', status: 'pending', updatedAt: Date.now(), acceptanceCriteria: ['Criteria D'] },
|
|
256
|
+
{ id: 't5', title: 'T5', description: 'Desc 5', status: 'pending', updatedAt: Date.now(), acceptanceCriteria: ['Criteria E'] },
|
|
257
|
+
],
|
|
258
|
+
});
|
|
259
|
+
const gaps = analyzeKnowledgeDepth(plan);
|
|
260
|
+
expect(gaps.some((g) => g._trigger === 'high_acceptance_criteria')).toBe(true);
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
it('does not award acceptance criteria bonus below 80% threshold', () => {
|
|
264
|
+
const plan = makePlan({
|
|
265
|
+
tasks: [
|
|
266
|
+
{ id: 't1', title: 'T1', description: 'Desc', status: 'pending', updatedAt: Date.now(), acceptanceCriteria: ['A'] },
|
|
267
|
+
{ id: 't2', title: 'T2', description: 'Desc', status: 'pending', updatedAt: Date.now() },
|
|
268
|
+
{ id: 't3', title: 'T3', description: 'Desc', status: 'pending', updatedAt: Date.now() },
|
|
269
|
+
],
|
|
270
|
+
});
|
|
271
|
+
const gaps = analyzeKnowledgeDepth(plan);
|
|
272
|
+
expect(gaps.some((g) => g._trigger === 'high_acceptance_criteria')).toBe(false);
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
it('awards bonus for rich task descriptions (avg >= 80 chars)', () => {
|
|
276
|
+
const longDesc = 'This is a very detailed task description that provides specific technical context about what needs to be implemented.';
|
|
277
|
+
const plan = makePlan({
|
|
278
|
+
tasks: [
|
|
279
|
+
{ id: 't1', title: 'T1', description: longDesc, status: 'pending', updatedAt: Date.now() },
|
|
280
|
+
{ id: 't2', title: 'T2', description: longDesc, status: 'pending', updatedAt: Date.now() },
|
|
281
|
+
{ id: 't3', title: 'T3', description: longDesc, status: 'pending', updatedAt: Date.now() },
|
|
282
|
+
],
|
|
283
|
+
});
|
|
284
|
+
const gaps = analyzeKnowledgeDepth(plan);
|
|
285
|
+
expect(gaps.some((g) => g._trigger === 'rich_task_descriptions')).toBe(true);
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
it('awards bonus for domain knowledge indicators', () => {
|
|
289
|
+
const plan = makePlan({
|
|
290
|
+
tasks: [
|
|
291
|
+
{ id: 't1', title: 'A11y audit', description: 'Check WCAG 2.1 compliance and aria-label usage with vault patterns', status: 'pending', updatedAt: Date.now() },
|
|
292
|
+
{ id: 't2', title: 'Contrast', description: '4.5:1 contrast ratio for all text, anti-pattern detection', status: 'pending', updatedAt: Date.now() },
|
|
293
|
+
{ id: 't3', title: 'Touch', description: '44px touch target minimum, acceptance criteria for all buttons', status: 'pending', updatedAt: Date.now() },
|
|
294
|
+
],
|
|
295
|
+
});
|
|
296
|
+
const gaps = analyzeKnowledgeDepth(plan);
|
|
297
|
+
expect(gaps.some((g) => g._trigger === 'domain_knowledge_indicators')).toBe(true);
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
it('returns no bonuses for basic plan', () => {
|
|
301
|
+
const plan = makePlan({
|
|
302
|
+
tasks: [
|
|
303
|
+
{ id: 't1', title: 'Do thing', description: 'Do it', status: 'pending', updatedAt: Date.now() },
|
|
304
|
+
],
|
|
305
|
+
});
|
|
306
|
+
const gaps = analyzeKnowledgeDepth(plan);
|
|
307
|
+
const bonuses = gaps.filter((g) => g.severity === 'bonus');
|
|
308
|
+
expect(bonuses).toHaveLength(0);
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
it('excludes common hyphenated words from pattern refs', () => {
|
|
312
|
+
const plan = makePlan({
|
|
313
|
+
tasks: [
|
|
314
|
+
{ id: 't1', title: 'T1', description: 'Use front-end and back-end and real-time and client-side and server-side', status: 'pending', updatedAt: Date.now() },
|
|
315
|
+
],
|
|
316
|
+
});
|
|
317
|
+
const gaps = analyzeKnowledgeDepth(plan);
|
|
318
|
+
expect(gaps.some((g) => g._trigger === 'vault_pattern_refs_medium')).toBe(false);
|
|
319
|
+
expect(gaps.some((g) => g._trigger === 'vault_pattern_refs_high')).toBe(false);
|
|
320
|
+
});
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
describe('Pass 8: Alternative Analysis', () => {
|
|
324
|
+
it('flags no alternatives', () => {
|
|
325
|
+
const plan = makePlan();
|
|
326
|
+
const gaps = analyzeAlternatives(plan);
|
|
327
|
+
expect(gaps.some((g) => g._trigger === 'no_alternatives')).toBe(true);
|
|
328
|
+
expect(gaps[0].severity).toBe('major');
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
it('flags fewer than 2 alternatives', () => {
|
|
332
|
+
const plan = makePlan({ alternatives: [makeAlternative()] });
|
|
333
|
+
const gaps = analyzeAlternatives(plan);
|
|
334
|
+
expect(gaps.some((g) => g._trigger === 'few_alternatives')).toBe(true);
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
it('returns no gaps for 2+ well-formed alternatives', () => {
|
|
338
|
+
const plan = makePlan({
|
|
339
|
+
alternatives: [
|
|
340
|
+
makeAlternative(),
|
|
341
|
+
makeAlternative({ approach: 'Use OAuth2', rejected_reason: 'Too complex' }),
|
|
342
|
+
],
|
|
343
|
+
});
|
|
344
|
+
const gaps = analyzeAlternatives(plan);
|
|
345
|
+
expect(gaps).toHaveLength(0);
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
it('flags missing rejection rationale', () => {
|
|
349
|
+
const plan = makePlan({
|
|
350
|
+
alternatives: [
|
|
351
|
+
makeAlternative(),
|
|
352
|
+
makeAlternative({ approach: 'Basic auth', rejected_reason: '' }),
|
|
353
|
+
],
|
|
354
|
+
});
|
|
355
|
+
const gaps = analyzeAlternatives(plan);
|
|
356
|
+
expect(gaps.some((g) => g._trigger === 'missing_rejection_rationale')).toBe(true);
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
it('handles undefined alternatives', () => {
|
|
360
|
+
const plan = makePlan();
|
|
361
|
+
delete (plan as Record<string, unknown>).alternatives;
|
|
362
|
+
const gaps = analyzeAlternatives(plan);
|
|
363
|
+
expect(gaps.some((g) => g._trigger === 'no_alternatives')).toBe(true);
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
it('returns early after no-alternatives gap', () => {
|
|
367
|
+
const plan = makePlan();
|
|
368
|
+
const gaps = analyzeAlternatives(plan);
|
|
369
|
+
// Should only have the one "no alternatives" gap, not also "few alternatives"
|
|
370
|
+
expect(gaps).toHaveLength(1);
|
|
371
|
+
});
|
|
372
|
+
});
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Quality and substance analysis passes (5-8).
|
|
3
|
+
* These passes examine clarity, semantic quality, knowledge depth,
|
|
4
|
+
* and alternative analysis of plans.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { Plan } from './planner.js';
|
|
8
|
+
import type { PlanGap } from './gap-types.js';
|
|
9
|
+
import {
|
|
10
|
+
gap,
|
|
11
|
+
taskText,
|
|
12
|
+
decisionText,
|
|
13
|
+
decisionsText,
|
|
14
|
+
containsAny,
|
|
15
|
+
} from './gap-patterns.js';
|
|
16
|
+
|
|
17
|
+
// ─── Pattern Constants (Passes 5-8) ─────────────────────────────
|
|
18
|
+
|
|
19
|
+
export const AMBIGUOUS_WORDS = [
|
|
20
|
+
'maybe', 'perhaps', 'might', 'could', 'some', 'etc', 'soon',
|
|
21
|
+
'simple', 'easy', 'appropriate', 'various', 'several',
|
|
22
|
+
'probably', 'possibly', 'somehow',
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
export const GENERIC_OBJECTIVE_PATTERNS = [
|
|
26
|
+
/^(create|build|implement|add|make|do)\s+\w+$/i,
|
|
27
|
+
/^fix\s+\w+$/i,
|
|
28
|
+
/^update\s+\w+$/i,
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
export const RATIONALE_INDICATORS = [
|
|
32
|
+
'because', 'since', 'due to', 'in order to',
|
|
33
|
+
'so that', 'given that', 'as a result',
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
export const SHALLOW_INDICATORS = ['better', 'good', 'best', 'nice', 'great', 'improved'];
|
|
37
|
+
|
|
38
|
+
export const KNOWLEDGE_INDICATORS = [
|
|
39
|
+
/vault\s*pattern/i,
|
|
40
|
+
/vault\s*patterns/i,
|
|
41
|
+
/anti-pattern/i,
|
|
42
|
+
/wcag\s*[\d.]+/i,
|
|
43
|
+
/aria-[a-z]+/i,
|
|
44
|
+
/\d+(\.\d+)?:\d+\s*(contrast|ratio)/i,
|
|
45
|
+
/\d+px\s*(touch|target|minimum|min)/i,
|
|
46
|
+
/acceptance\s*criteria/i,
|
|
47
|
+
];
|
|
48
|
+
|
|
49
|
+
/** Checks if task descriptions reference specific named patterns (e.g. "zod-form-validation"). */
|
|
50
|
+
export const NAMED_PATTERN_REGEX = /[a-z]+-[a-z]+-[a-z]+/;
|
|
51
|
+
|
|
52
|
+
// ─── Pass 5: Clarity ─────────────────────────────────────────────
|
|
53
|
+
|
|
54
|
+
export function analyzeClarity(plan: Plan): PlanGap[] {
|
|
55
|
+
const gaps: PlanGap[] = [];
|
|
56
|
+
const allText = `${plan.objective} ${plan.scope} ${decisionsText(plan)}`;
|
|
57
|
+
const lower = allText.toLowerCase();
|
|
58
|
+
|
|
59
|
+
const found = AMBIGUOUS_WORDS.filter((w) => {
|
|
60
|
+
const regex = new RegExp(`\\b${w}\\b`, 'i');
|
|
61
|
+
return regex.test(lower);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
if (found.length > 0) {
|
|
65
|
+
gaps.push(
|
|
66
|
+
gap(
|
|
67
|
+
'minor', 'clarity',
|
|
68
|
+
`Ambiguous language detected: ${found.slice(0, 5).join(', ')}${found.length > 5 ? ` (+${found.length - 5} more)` : ''}.`,
|
|
69
|
+
'Replace vague terms with concrete, specific language.',
|
|
70
|
+
undefined, `ambiguous_words:${found.join(',')}`,
|
|
71
|
+
),
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const shortTasks = plan.tasks.filter((t) => !t.description || t.description.trim().length < 10);
|
|
76
|
+
if (shortTasks.length > 0) {
|
|
77
|
+
gaps.push(
|
|
78
|
+
gap(
|
|
79
|
+
'minor', 'clarity',
|
|
80
|
+
`${shortTasks.length} task(s) with very short descriptions: ${shortTasks.map((t) => t.id).join(', ')}.`,
|
|
81
|
+
'Add detailed descriptions to all tasks explaining what needs to be done.',
|
|
82
|
+
'tasks', 'short_task_descriptions',
|
|
83
|
+
),
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return gaps;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// ─── Pass 6: Semantic Quality ────────────────────────────────────
|
|
91
|
+
|
|
92
|
+
export function analyzeSemanticQuality(plan: Plan): PlanGap[] {
|
|
93
|
+
const gaps: PlanGap[] = [];
|
|
94
|
+
|
|
95
|
+
if (plan.objective) {
|
|
96
|
+
const words = plan.objective.trim().split(/\s+/);
|
|
97
|
+
const isGeneric = GENERIC_OBJECTIVE_PATTERNS.some((p) => p.test(plan.objective.trim()));
|
|
98
|
+
|
|
99
|
+
if (isGeneric || words.length < 5) {
|
|
100
|
+
gaps.push(
|
|
101
|
+
gap(
|
|
102
|
+
'major', 'semantic-quality',
|
|
103
|
+
`Objective is too generic${words.length < 5 ? ` (${words.length} words)` : ''}: "${plan.objective.trim()}".`,
|
|
104
|
+
'Expand the objective to describe the specific outcome, context, and constraints.',
|
|
105
|
+
'objective', 'generic_objective',
|
|
106
|
+
),
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (plan.tasks.length > 0 && plan.tasks.length < 3) {
|
|
112
|
+
gaps.push(
|
|
113
|
+
gap(
|
|
114
|
+
'minor', 'semantic-quality',
|
|
115
|
+
`Only ${plan.tasks.length} task(s) — plan may lack sufficient breakdown.`,
|
|
116
|
+
'Break down the work into 3-15 well-defined tasks for better tracking.',
|
|
117
|
+
'tasks', 'too_few_tasks',
|
|
118
|
+
),
|
|
119
|
+
);
|
|
120
|
+
} else if (plan.tasks.length > 20) {
|
|
121
|
+
gaps.push(
|
|
122
|
+
gap(
|
|
123
|
+
'major', 'semantic-quality',
|
|
124
|
+
`${plan.tasks.length} tasks — plan scope may be too large.`,
|
|
125
|
+
'Split into multiple plans or consolidate related tasks to stay under 20.',
|
|
126
|
+
'tasks', 'too_many_tasks',
|
|
127
|
+
),
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
for (let i = 0; i < plan.decisions.length; i++) {
|
|
132
|
+
const d = decisionText(plan.decisions[i]);
|
|
133
|
+
const hasShallow = containsAny(d, SHALLOW_INDICATORS);
|
|
134
|
+
const hasRationale = containsAny(d, RATIONALE_INDICATORS);
|
|
135
|
+
if (hasShallow && !hasRationale) {
|
|
136
|
+
gaps.push(
|
|
137
|
+
gap(
|
|
138
|
+
'minor', 'semantic-quality',
|
|
139
|
+
`Decision ${i + 1} uses subjective language without justification.`,
|
|
140
|
+
'Replace "better/good/best" with concrete reasoning using "because/since/due to".',
|
|
141
|
+
`decisions[${i}]`, 'shallow_rationale',
|
|
142
|
+
),
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const titleSet = new Set<string>();
|
|
148
|
+
const duplicates: string[] = [];
|
|
149
|
+
for (const t of plan.tasks) {
|
|
150
|
+
if (titleSet.has(t.title)) duplicates.push(t.title);
|
|
151
|
+
titleSet.add(t.title);
|
|
152
|
+
}
|
|
153
|
+
if (duplicates.length > 0) {
|
|
154
|
+
gaps.push(
|
|
155
|
+
gap(
|
|
156
|
+
'minor', 'semantic-quality',
|
|
157
|
+
`Duplicate task titles: ${[...new Set(duplicates)].join(', ')}.`,
|
|
158
|
+
'Give each task a unique, descriptive title.',
|
|
159
|
+
'tasks', 'duplicate_task_titles',
|
|
160
|
+
),
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (plan.tasks.length >= 3 && plan.decisions.length === 0) {
|
|
165
|
+
gaps.push(
|
|
166
|
+
gap(
|
|
167
|
+
'major', 'semantic-quality',
|
|
168
|
+
`${plan.tasks.length} tasks but no decisions documented.`,
|
|
169
|
+
'Document key decisions and their rationale — at least 1 per 3 tasks.',
|
|
170
|
+
'decisions', 'no_decisions',
|
|
171
|
+
),
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return gaps;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// ─── Pass 7: Knowledge Depth (Substance Bonuses) ────────────────
|
|
179
|
+
|
|
180
|
+
export function analyzeKnowledgeDepth(plan: Plan): PlanGap[] {
|
|
181
|
+
const gaps: PlanGap[] = [];
|
|
182
|
+
const allTaskText = taskText(plan);
|
|
183
|
+
|
|
184
|
+
let namedPatternCount = 0;
|
|
185
|
+
for (const task of plan.tasks) {
|
|
186
|
+
const desc = task.description || '';
|
|
187
|
+
const matches = desc.match(/[a-z]+-[a-z]+(-[a-z]+)*/g) || [];
|
|
188
|
+
const patternRefs = matches.filter(
|
|
189
|
+
(m) =>
|
|
190
|
+
m.length > 8 &&
|
|
191
|
+
NAMED_PATTERN_REGEX.test(m) &&
|
|
192
|
+
!['front-end', 'back-end', 'real-time', 'client-side', 'server-side'].includes(m),
|
|
193
|
+
);
|
|
194
|
+
namedPatternCount += patternRefs.length;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if (namedPatternCount >= 5) {
|
|
198
|
+
gaps.push(
|
|
199
|
+
gap('bonus', 'knowledge-depth',
|
|
200
|
+
`${namedPatternCount} vault pattern references across tasks — strong knowledge-informed plan.`,
|
|
201
|
+
'', 'tasks', 'vault_pattern_refs_high'),
|
|
202
|
+
);
|
|
203
|
+
gaps.push(
|
|
204
|
+
gap('bonus', 'knowledge-depth',
|
|
205
|
+
'Vault pattern density indicates expert-level domain knowledge.',
|
|
206
|
+
'', 'tasks', 'vault_pattern_density'),
|
|
207
|
+
);
|
|
208
|
+
} else if (namedPatternCount >= 2) {
|
|
209
|
+
gaps.push(
|
|
210
|
+
gap('bonus', 'knowledge-depth',
|
|
211
|
+
`${namedPatternCount} vault pattern references across tasks.`,
|
|
212
|
+
'', 'tasks', 'vault_pattern_refs_medium'),
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
let tasksWithCriteria = 0;
|
|
217
|
+
let totalCriteria = 0;
|
|
218
|
+
for (const task of plan.tasks) {
|
|
219
|
+
if (task.acceptanceCriteria && task.acceptanceCriteria.length > 0) {
|
|
220
|
+
tasksWithCriteria++;
|
|
221
|
+
totalCriteria += task.acceptanceCriteria.length;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if (plan.tasks.length > 0 && tasksWithCriteria / plan.tasks.length >= 0.8) {
|
|
226
|
+
gaps.push(
|
|
227
|
+
gap('bonus', 'knowledge-depth',
|
|
228
|
+
`${tasksWithCriteria}/${plan.tasks.length} tasks have acceptance criteria (${totalCriteria} total).`,
|
|
229
|
+
'', 'tasks', 'high_acceptance_criteria'),
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
let indicatorHits = 0;
|
|
234
|
+
for (const pattern of KNOWLEDGE_INDICATORS) {
|
|
235
|
+
if (pattern.test(allTaskText)) indicatorHits++;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if (indicatorHits >= 4) {
|
|
239
|
+
gaps.push(
|
|
240
|
+
gap('bonus', 'knowledge-depth',
|
|
241
|
+
`${indicatorHits} domain-specific knowledge indicators found (WCAG, ARIA, contrast ratios, touch targets, etc.).`,
|
|
242
|
+
'', 'tasks', 'domain_knowledge_indicators'),
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
if (plan.tasks.length > 0) {
|
|
247
|
+
const avgDescLength =
|
|
248
|
+
plan.tasks.reduce((sum, t) => sum + (t.description?.length ?? 0), 0) / plan.tasks.length;
|
|
249
|
+
if (avgDescLength >= 80) {
|
|
250
|
+
gaps.push(
|
|
251
|
+
gap('bonus', 'knowledge-depth',
|
|
252
|
+
`Task descriptions average ${Math.round(avgDescLength)} chars — detailed and specific.`,
|
|
253
|
+
'', 'tasks', 'rich_task_descriptions'),
|
|
254
|
+
);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
return gaps;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// ─── Pass 8: Alternative Analysis ────────────────────────────────
|
|
262
|
+
|
|
263
|
+
export function analyzeAlternatives(plan: Plan): PlanGap[] {
|
|
264
|
+
const gaps: PlanGap[] = [];
|
|
265
|
+
const alts = plan.alternatives;
|
|
266
|
+
|
|
267
|
+
if (!alts || alts.length === 0) {
|
|
268
|
+
gaps.push(
|
|
269
|
+
gap('major', 'alternative-analysis',
|
|
270
|
+
'No alternatives considered — risk of tunnel vision.',
|
|
271
|
+
'Add at least 2 rejected alternatives with pros, cons, and rejection rationale.',
|
|
272
|
+
'alternatives', 'no_alternatives'),
|
|
273
|
+
);
|
|
274
|
+
return gaps;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
if (alts.length < 2) {
|
|
278
|
+
gaps.push(
|
|
279
|
+
gap('minor', 'alternative-analysis',
|
|
280
|
+
`Only ${alts.length} alternative explored — consider at least 2.`,
|
|
281
|
+
'Add another rejected alternative to strengthen decision rationale.',
|
|
282
|
+
'alternatives', 'few_alternatives'),
|
|
283
|
+
);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
for (let i = 0; i < alts.length; i++) {
|
|
287
|
+
if (!alts[i].rejected_reason || alts[i].rejected_reason.trim().length === 0) {
|
|
288
|
+
gaps.push(
|
|
289
|
+
gap('minor', 'alternative-analysis',
|
|
290
|
+
`Alternative ${i + 1} ("${alts[i].approach}") missing rejection rationale.`,
|
|
291
|
+
'Explain why this alternative was rejected.',
|
|
292
|
+
`alternatives[${i}]`, 'missing_rejection_rationale'),
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
return gaps;
|
|
298
|
+
}
|