@mindrian_os/install 1.13.0-beta.11
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/.claude-plugin/plugin.json +21 -0
- package/.mcp.json +9 -0
- package/CHANGELOG.md +3333 -0
- package/LICENSE +123 -0
- package/README.md +673 -0
- package/agents/brain-query.md +80 -0
- package/agents/framework-runner.md +237 -0
- package/agents/grading.md +188 -0
- package/agents/investor.md +128 -0
- package/agents/larry-extended.md +135 -0
- package/agents/opportunity-scanner.md +91 -0
- package/agents/persona-analyst.md +132 -0
- package/agents/research.md +89 -0
- package/agents/reverse-salient-agent.md +27 -0
- package/bin/cli.js +142 -0
- package/bin/mindrian-mcp-server.cjs +182 -0
- package/bin/mindrian-tools.cjs +765 -0
- package/commands/act.md +439 -0
- package/commands/admin.md +404 -0
- package/commands/analyze-needs.md +42 -0
- package/commands/analyze-systems.md +39 -0
- package/commands/analyze-timing.md +42 -0
- package/commands/auto-explore.md +64 -0
- package/commands/beautiful-question.md +40 -0
- package/commands/brain-derive.md +78 -0
- package/commands/build-knowledge.md +42 -0
- package/commands/build-thesis.md +46 -0
- package/commands/causal.md +234 -0
- package/commands/challenge-assumptions.md +33 -0
- package/commands/compare-ventures.md +83 -0
- package/commands/dashboard.md +110 -0
- package/commands/deep-grade.md +82 -0
- package/commands/diagnose.md +58 -0
- package/commands/diagnostics.md +151 -0
- package/commands/doctor.md +151 -0
- package/commands/dominant-designs.md +40 -0
- package/commands/explain-decision.md +87 -0
- package/commands/explore-domains.md +42 -0
- package/commands/explore-futures.md +40 -0
- package/commands/explore-trends.md +42 -0
- package/commands/export.md +103 -0
- package/commands/file-meeting.md +724 -0
- package/commands/find-analogies.md +188 -0
- package/commands/find-bottlenecks.md +62 -0
- package/commands/find-connections.md +76 -0
- package/commands/funding.md +81 -0
- package/commands/grade.md +203 -0
- package/commands/graph.md +128 -0
- package/commands/hat-briefing.md +125 -0
- package/commands/heal.md +196 -0
- package/commands/help.md +399 -0
- package/commands/hmi-status.md +172 -0
- package/commands/jtbd.md +241 -0
- package/commands/leadership.md +73 -0
- package/commands/lean-canvas.md +40 -0
- package/commands/macro-trends.md +40 -0
- package/commands/map-unknowns.md +40 -0
- package/commands/memory.md +173 -0
- package/commands/models.md +175 -0
- package/commands/mos-reason.md +285 -0
- package/commands/mullins.md +120 -0
- package/commands/new-project.md +481 -0
- package/commands/onboard.md +434 -0
- package/commands/operator.md +149 -0
- package/commands/opportunities.md +144 -0
- package/commands/organize.md +497 -0
- package/commands/persona.md +198 -0
- package/commands/pipeline.md +112 -0
- package/commands/present.md +91 -0
- package/commands/publish.md +201 -0
- package/commands/query.md +124 -0
- package/commands/radar.md +72 -0
- package/commands/reanalyze.md +91 -0
- package/commands/research.md +196 -0
- package/commands/room.md +352 -0
- package/commands/rooms.md +598 -0
- package/commands/root-cause.md +40 -0
- package/commands/rs-experts.md +85 -0
- package/commands/rs-explain.md +100 -0
- package/commands/rs-fetch.md +94 -0
- package/commands/rs-thesis.md +85 -0
- package/commands/scenario-plan.md +40 -0
- package/commands/scheduled-tasks.md +285 -0
- package/commands/score-innovation.md +43 -0
- package/commands/scout.md +239 -0
- package/commands/setup.md +618 -0
- package/commands/snapshot.md +147 -0
- package/commands/speakers.md +84 -0
- package/commands/splash.md +28 -0
- package/commands/status.md +75 -0
- package/commands/structure-argument.md +42 -0
- package/commands/suggest-next.md +80 -0
- package/commands/systems-thinking.md +40 -0
- package/commands/think-hats.md +42 -0
- package/commands/update.md +181 -0
- package/commands/user-needs.md +40 -0
- package/commands/validate.md +40 -0
- package/commands/value-proposition.md +61 -0
- package/commands/vault.md +180 -0
- package/commands/visualize.md +52 -0
- package/commands/whitespace.md +507 -0
- package/commands/wiki.md +69 -0
- package/hooks/hooks.json +381 -0
- package/hooks/run-hook.cmd +64 -0
- package/lib/__init__.py +0 -0
- package/lib/__pycache__/__init__.cpython-312.pyc +0 -0
- package/lib/agents/auto-explore-agent.cjs +1043 -0
- package/lib/agents/reverse-salient-agent.cjs +679 -0
- package/lib/agents/tension-hook-agent.cjs +544 -0
- package/lib/brain/ROOM.md +44 -0
- package/lib/brain/chain-recommender.cjs +301 -0
- package/lib/chat/chat-context.js +185 -0
- package/lib/chat/chat-panel.js +721 -0
- package/lib/chat/fabric-chat.cjs +288 -0
- package/lib/chat/generative-tools.js +219 -0
- package/lib/conversation/ROOM.md +39 -0
- package/lib/conversation/classifier-rules.json +38 -0
- package/lib/conversation/classifier.cjs +264 -0
- package/lib/conversation/operator.cjs +287 -0
- package/lib/copy/115-spec-strings.cjs +55 -0
- package/lib/core/__init__.py +0 -0
- package/lib/core/__nav-stub.cjs +14 -0
- package/lib/core/__pycache__/__init__.cpython-312.pyc +0 -0
- package/lib/core/__pycache__/rs-math.cpython-312.pyc +0 -0
- package/lib/core/__pycache__/rs_cache.cpython-312.pyc +0 -0
- package/lib/core/__pycache__/rs_corpus.cpython-312.pyc +0 -0
- package/lib/core/__pycache__/rs_hybrid.cpython-312.pyc +0 -0
- package/lib/core/__pycache__/rs_math.cpython-312.pyc +0 -0
- package/lib/core/__pycache__/rs_rooms.cpython-312.pyc +0 -0
- package/lib/core/artifact-id.cjs +148 -0
- package/lib/core/asset-ops.cjs +151 -0
- package/lib/core/auto-commit-throttle.cjs +129 -0
- package/lib/core/bearer-token.cjs +199 -0
- package/lib/core/brain-client.cjs +865 -0
- package/lib/core/brain-derivation-prompts.cjs +326 -0
- package/lib/core/brain-derivation-queue.cjs +431 -0
- package/lib/core/brain-derivation.cjs +580 -0
- package/lib/core/brain-md-schema.cjs +528 -0
- package/lib/core/brain-md-staleness.cjs +357 -0
- package/lib/core/brain-response-sanitize.cjs +188 -0
- package/lib/core/bridge-writer.cjs +477 -0
- package/lib/core/chat-context-builder.cjs +253 -0
- package/lib/core/cross-room-aggregator.cjs +762 -0
- package/lib/core/daily-briefing.cjs +438 -0
- package/lib/core/decision-capture.cjs +618 -0
- package/lib/core/deep-links.cjs +82 -0
- package/lib/core/dispatch-optimizer.cjs +354 -0
- package/lib/core/dual-path-detector.cjs +84 -0
- package/lib/core/dual-path-detector.test.cjs +334 -0
- package/lib/core/exports-log.cjs +79 -0
- package/lib/core/feynman-minto-invariants.cjs +605 -0
- package/lib/core/folder-memory-async.cjs +338 -0
- package/lib/core/folder-memory-shared.cjs +890 -0
- package/lib/core/folder-memory.cjs +416 -0
- package/lib/core/framework-chain-composer.cjs +411 -0
- package/lib/core/frontmatter-schemas.cjs +330 -0
- package/lib/core/git-ops.cjs +141 -0
- package/lib/core/graph-ops.cjs +258 -0
- package/lib/core/hat-persistence.cjs +362 -0
- package/lib/core/index.cjs +60 -0
- package/lib/core/integration-registry.cjs +232 -0
- package/lib/core/intelligence-cascade.cjs +661 -0
- package/lib/core/lazygraph-ops.cjs +1057 -0
- package/lib/core/lru-cache.cjs +139 -0
- package/lib/core/mcp-profiles.cjs +182 -0
- package/lib/core/meeting-ops.cjs +54 -0
- package/lib/core/memory-ops.cjs +600 -0
- package/lib/core/migrations/ROOM.md +33 -0
- package/lib/core/migrations/phase-109-nodes-provenance.cjs +339 -0
- package/lib/core/migrations/phase-109-session-focus.cjs +99 -0
- package/lib/core/model-profiles.cjs +246 -0
- package/lib/core/mullins-scaffold.cjs +160 -0
- package/lib/core/nav-dial.cjs +316 -0
- package/lib/core/navigation/ROOM.md +15 -0
- package/lib/core/navigation/explanation.cjs +43 -0
- package/lib/core/navigation/focus.cjs +135 -0
- package/lib/core/navigation/ingestion.cjs +82 -0
- package/lib/core/navigation/insights.cjs +350 -0
- package/lib/core/navigation/memory-events.cjs +118 -0
- package/lib/core/navigation/neighborhood.cjs +78 -0
- package/lib/core/navigation/packet.cjs +182 -0
- package/lib/core/navigation/room-home.cjs +127 -0
- package/lib/core/navigation/transitions.cjs +82 -0
- package/lib/core/navigation-engine-shared.cjs +242 -0
- package/lib/core/navigation-engine.cjs +664 -0
- package/lib/core/navigation.cjs +60 -0
- package/lib/core/nl-graph-queries.cjs +164 -0
- package/lib/core/offer-presenter.cjs +406 -0
- package/lib/core/opportunity-extractor.cjs +183 -0
- package/lib/core/opportunity-ops.cjs +1371 -0
- package/lib/core/persona-ops.cjs +537 -0
- package/lib/core/persona-taxonomy.cjs +190 -0
- package/lib/core/platform-gates.cjs +120 -0
- package/lib/core/platform.cjs +257 -0
- package/lib/core/proactive-intelligence.cjs +528 -0
- package/lib/core/problem-type-router.cjs +315 -0
- package/lib/core/reasoning-ops.cjs +639 -0
- package/lib/core/reverse-salient-persona-suffix.cjs +115 -0
- package/lib/core/room-classifier-strict-mode.cjs +229 -0
- package/lib/core/room-db.cjs +127 -0
- package/lib/core/room-ops-async.cjs +92 -0
- package/lib/core/room-ops-shared.cjs +64 -0
- package/lib/core/room-ops-sync.cjs +70 -0
- package/lib/core/room-ops.cjs +32 -0
- package/lib/core/room-type-detector.cjs +386 -0
- package/lib/core/rs-brain-substrate-prompts.cjs +129 -0
- package/lib/core/rs-brain-substrate.cjs +570 -0
- package/lib/core/rs-breakthrough-scorer.cjs +255 -0
- package/lib/core/rs-canon-violations.cjs +82 -0
- package/lib/core/rs-chain-feeder.cjs +343 -0
- package/lib/core/rs-commercial-assessor.cjs +280 -0
- package/lib/core/rs-differential-scorer.cjs +376 -0
- package/lib/core/rs-domain-analyzer.cjs +385 -0
- package/lib/core/rs-egress-prompts.cjs +113 -0
- package/lib/core/rs-egress-telemetry.cjs +225 -0
- package/lib/core/rs-egress-violations.cjs +53 -0
- package/lib/core/rs-expert-mapper.cjs +467 -0
- package/lib/core/rs-fetcher-academic.cjs +697 -0
- package/lib/core/rs-fetcher-experts.cjs +314 -0
- package/lib/core/rs-fetcher-industry.cjs +731 -0
- package/lib/core/rs-fetcher-patents.cjs +564 -0
- package/lib/core/rs-innovation-classifier.cjs +194 -0
- package/lib/core/rs-mind-map.cjs +656 -0
- package/lib/core/rs-neo4j-writer.cjs +388 -0
- package/lib/core/rs-nl-to-query.cjs +425 -0
- package/lib/core/rs-pinecone-bridge.cjs +303 -0
- package/lib/core/rs-preprocessor.cjs +350 -0
- package/lib/core/rs-query-matrix.cjs +316 -0
- package/lib/core/rs-query-to-text.cjs +438 -0
- package/lib/core/rs-sqlite-mirror.cjs +443 -0
- package/lib/core/rs-thesis-generator.cjs +188 -0
- package/lib/core/rs_cache.py +479 -0
- package/lib/core/rs_corpus.py +468 -0
- package/lib/core/rs_hybrid.py +586 -0
- package/lib/core/rs_math.py +287 -0
- package/lib/core/rs_rooms.py +193 -0
- package/lib/core/scheduled-scanner.cjs +463 -0
- package/lib/core/scratchpad-ops.cjs +201 -0
- package/lib/core/section-8-trace-schema.cjs +138 -0
- package/lib/core/section-registry.cjs +111 -0
- package/lib/core/session-state.cjs +144 -0
- package/lib/core/shallow-doc-parser.cjs +174 -0
- package/lib/core/shallow-doc-parser.test.cjs +226 -0
- package/lib/core/skill-activation-router.cjs +284 -0
- package/lib/core/state-ops.cjs +46 -0
- package/lib/core/statusline-cache.cjs +266 -0
- package/lib/core/token-estimator.cjs +348 -0
- package/lib/core/user-archetype.cjs +239 -0
- package/lib/core/user-md-ops.cjs +524 -0
- package/lib/core/visual-ops.cjs +624 -0
- package/lib/core/write-lock.cjs +149 -0
- package/lib/graph/canvas-graph.js +467 -0
- package/lib/graph/constellation-config.cjs +299 -0
- package/lib/graph/graph-detail-panel.js +165 -0
- package/lib/hmi/ROOM.md +47 -0
- package/lib/hmi/across-session-memory.cjs +604 -0
- package/lib/hmi/cross-room-memory.cjs +575 -0
- package/lib/hmi/decoy-tier.cjs +395 -0
- package/lib/hmi/jtbd-classifier.cjs +219 -0
- package/lib/hmi/jtbd-state.cjs +199 -0
- package/lib/hmi/jtbd-taxonomy.json +392 -0
- package/lib/hmi/selector-dispatcher.cjs +546 -0
- package/lib/hmi/selector-telemetry.cjs +263 -0
- package/lib/hmi/shape-f0-renderer.cjs +139 -0
- package/lib/hmi/shape-f1-fallback.cjs +80 -0
- package/lib/hmi/shape-f1-renderer.cjs +138 -0
- package/lib/hmi/shape-f2-renderer.cjs +132 -0
- package/lib/hmi/shape-f3-renderer.cjs +66 -0
- package/lib/hmi/shape-f4-renderer.cjs +72 -0
- package/lib/hmi/shape-f5-renderer.cjs +155 -0
- package/lib/hmi/shape-f6-plan-review-renderer.cjs +312 -0
- package/lib/hmi/shape-f6-renderer.cjs +144 -0
- package/lib/hmi/shape-g-renderer.cjs +219 -0
- package/lib/hmi/shape-h-renderer.cjs +222 -0
- package/lib/hmi/tier-check.cjs +63 -0
- package/lib/import/PRECONDITIONS.md +41 -0
- package/lib/import/branding.cjs +210 -0
- package/lib/import/branding.test.cjs +235 -0
- package/lib/import/classifications-sync.cjs +104 -0
- package/lib/import/classifications-sync.test.cjs +129 -0
- package/lib/import/enricher.cjs +296 -0
- package/lib/import/enricher.test.cjs +273 -0
- package/lib/import/integration.test.cjs +376 -0
- package/lib/import/manifest.cjs +129 -0
- package/lib/import/manifest.schema.json +185 -0
- package/lib/import/manifest.test.cjs +123 -0
- package/lib/import/meeting-detector.cjs +92 -0
- package/lib/import/meeting-detector.test.cjs +100 -0
- package/lib/import/person-detector.cjs +229 -0
- package/lib/import/person-detector.test.cjs +149 -0
- package/lib/import/report.cjs +186 -0
- package/lib/import/report.test.cjs +186 -0
- package/lib/import/room-md-scaffolder.cjs +49 -0
- package/lib/import/router.cjs +224 -0
- package/lib/import/router.test.cjs +356 -0
- package/lib/import/run-all-tests.cjs +36 -0
- package/lib/import/smoke-test.cjs +213 -0
- package/lib/import/smoke-test.test.cjs +148 -0
- package/lib/import/test-fixtures/collision-vault/preexisting-room/STATE.md +8 -0
- package/lib/import/test-fixtures/collision-vault/preexisting-room/problem-definition/onboarding/onboarding.md +7 -0
- package/lib/import/test-fixtures/collision-vault/source/onboarding.md +5 -0
- package/lib/import/test-fixtures/obsidian-vault/.obsidian/workspace.json +1 -0
- package/lib/import/test-fixtures/obsidian-vault/notes/with-wikilinks.md +4 -0
- package/lib/import/test-fixtures/tiny-vault/notes/2026-01-15-team-sync.md +9 -0
- package/lib/import/test-fixtures/tiny-vault/notes/empty.md +3 -0
- package/lib/import/test-fixtures/tiny-vault/notes/onboarding.md +5 -0
- package/lib/import/test-fixtures/tiny-vault/notes/pricing.md +5 -0
- package/lib/import/test-fixtures/tiny-vault/notes/random.md +4 -0
- package/lib/import/undo.test.cjs +199 -0
- package/lib/import/vault-scanner.cjs +105 -0
- package/lib/import/vault-scanner.test.cjs +67 -0
- package/lib/mcp/app-html/dashboard.html +316 -0
- package/lib/mcp/app-html/graph.html +428 -0
- package/lib/mcp/app-html/mindrian-platform.html +1841 -0
- package/lib/mcp/app-html/wiki.html +383 -0
- package/lib/mcp/app-views.cjs +322 -0
- package/lib/mcp/brain-router.cjs +418 -0
- package/lib/mcp/capability-registry.cjs +62 -0
- package/lib/mcp/larry-context.cjs +46 -0
- package/lib/mcp/larry-server-instructions.md +114 -0
- package/lib/mcp/pipeline-state.cjs +275 -0
- package/lib/mcp/prompts.cjs +302 -0
- package/lib/mcp/resources.cjs +227 -0
- package/lib/mcp/session-catchup.cjs +327 -0
- package/lib/mcp/surface-detect.cjs +75 -0
- package/lib/mcp/tool-router.cjs +1034 -0
- package/lib/memory/aaak-compress.cjs +403 -0
- package/lib/memory/aaak-compress.test.cjs +288 -0
- package/lib/memory/async-artifact-auto-commit.test.cjs +223 -0
- package/lib/memory/bearer-token.test.cjs +315 -0
- package/lib/memory/brain-cache-lru.test.cjs +259 -0
- package/lib/memory/brain-client-query-shape.test.cjs +160 -0
- package/lib/memory/brain-derivation-graceful-degradation.test.cjs +1019 -0
- package/lib/memory/brain-derivation-queue.test.cjs +539 -0
- package/lib/memory/brain-derivation.test.cjs +634 -0
- package/lib/memory/brain-derive-command.test.cjs +534 -0
- package/lib/memory/brain-md-invariants-validator.test.cjs +704 -0
- package/lib/memory/brain-md-schema.test.cjs +467 -0
- package/lib/memory/brain-md-staleness.test.cjs +525 -0
- package/lib/memory/brain-server-resolution.test.cjs +314 -0
- package/lib/memory/chain-recommender.test.cjs +233 -0
- package/lib/memory/chat-context.test.cjs +128 -0
- package/lib/memory/command-registry.test.cjs +220 -0
- package/lib/memory/cross-room-aggregator.test.cjs +909 -0
- package/lib/memory/dashboard-server.test.cjs +256 -0
- package/lib/memory/debouncer-drain-at-prompt.test.cjs +389 -0
- package/lib/memory/decision-capture.test.cjs +632 -0
- package/lib/memory/decision-capture.worker.cjs +70 -0
- package/lib/memory/explain-decision-command.test.cjs +521 -0
- package/lib/memory/explain-decision-footer.test.cjs +316 -0
- package/lib/memory/explored-materials-store.cjs +392 -0
- package/lib/memory/feynman-minto-guardian.test.cjs +736 -0
- package/lib/memory/feynman-minto-invariants.test.cjs +511 -0
- package/lib/memory/feynman-prompts-drift.test.cjs +144 -0
- package/lib/memory/feynman-prompts.cjs +151 -0
- package/lib/memory/feynman-prompts.test.cjs +96 -0
- package/lib/memory/folder-memory-quadruple.test.cjs +548 -0
- package/lib/memory/folder-memory.test.cjs +503 -0
- package/lib/memory/framework-chain-composer.test.cjs +515 -0
- package/lib/memory/frontmatter-schema-validator.test.cjs +290 -0
- package/lib/memory/heal-command.test.cjs +604 -0
- package/lib/memory/index-artifact-transaction.test.cjs +333 -0
- package/lib/memory/lazygraph-rs-discoveries-view.test.cjs +122 -0
- package/lib/memory/mcp-input-validation.test.cjs +240 -0
- package/lib/memory/mcp-server-brain-deps.test.cjs +270 -0
- package/lib/memory/mcp-stack-fallback.test.cjs +433 -0
- package/lib/memory/minto-debouncer.test.cjs +407 -0
- package/lib/memory/minto-debouncer.worker.cjs +46 -0
- package/lib/memory/minto-migration-v88.test.cjs +265 -0
- package/lib/memory/minto-schema-v88.test.cjs +390 -0
- package/lib/memory/mos-status-renderer.test.cjs +631 -0
- package/lib/memory/narrative-schema.cjs +376 -0
- package/lib/memory/narrative-schema.test.cjs +209 -0
- package/lib/memory/nav-dial.test.cjs +414 -0
- package/lib/memory/navigation-engine-core.test.cjs +722 -0
- package/lib/memory/navigation-invariants.test.cjs +483 -0
- package/lib/memory/offer-presenter.test.cjs +554 -0
- package/lib/memory/on-stop-snapshot.test.cjs +404 -0
- package/lib/memory/pending-tension-store.cjs +373 -0
- package/lib/memory/post-compact-reinjection.test.cjs +854 -0
- package/lib/memory/post-write-triple.test.cjs +317 -0
- package/lib/memory/pre-compact-snapshot.test.cjs +495 -0
- package/lib/memory/problem-type-router.test.cjs +656 -0
- package/lib/memory/query-efficiency-telemetry.test.cjs +370 -0
- package/lib/memory/recompile-room-references.test.cjs +392 -0
- package/lib/memory/recompile-room-references.worker.cjs +42 -0
- package/lib/memory/record-decision-dual-write.test.cjs +454 -0
- package/lib/memory/room-classifier-strict-mode.test.cjs +417 -0
- package/lib/memory/room-minto-hook.test.cjs +398 -0
- package/lib/memory/rs-discovery-engine.test.cjs +323 -0
- package/lib/memory/run-feynman-tests.cjs +1247 -0
- package/lib/memory/security-trifecta.test.cjs +312 -0
- package/lib/memory/session-start-brain-staleness.test.cjs +363 -0
- package/lib/memory/session-start-triple-injection.test.cjs +514 -0
- package/lib/memory/sessionstart-banner-formatter.cjs +318 -0
- package/lib/memory/sessionstart-minto-banner.test.cjs +373 -0
- package/lib/memory/skill-activation-router.test.cjs +419 -0
- package/lib/memory/stamp-artifact-write.test.cjs +304 -0
- package/lib/memory/statusline-active-room.test.cjs +315 -0
- package/lib/memory/statusline-minto-segment.test.cjs +292 -0
- package/lib/memory/sync-async-entry-points.test.cjs +204 -0
- package/lib/memory/test-bridge-writer-enhanced.cjs +452 -0
- package/lib/memory/test-rs-brain-substrate-shape.cjs +529 -0
- package/lib/memory/test-rs-brain-substrate.cjs +636 -0
- package/lib/memory/test-rs-breakthrough-scorer.cjs +375 -0
- package/lib/memory/test-rs-canon-violations.cjs +218 -0
- package/lib/memory/test-rs-chain-feeder-core.cjs +344 -0
- package/lib/memory/test-rs-chain-feeder-skill-spawn.cjs +297 -0
- package/lib/memory/test-rs-commercial-assessor.cjs +385 -0
- package/lib/memory/test-rs-differential-scorer.cjs +480 -0
- package/lib/memory/test-rs-discovery-engine.cjs +603 -0
- package/lib/memory/test-rs-domain-analyzer.cjs +492 -0
- package/lib/memory/test-rs-egress-primitives.cjs +420 -0
- package/lib/memory/test-rs-expert-mapper.cjs +547 -0
- package/lib/memory/test-rs-explain-command.cjs +443 -0
- package/lib/memory/test-rs-fetcher-academic.cjs +848 -0
- package/lib/memory/test-rs-fetcher-experts.cjs +496 -0
- package/lib/memory/test-rs-fetcher-industry.cjs +702 -0
- package/lib/memory/test-rs-fetcher-patents.cjs +674 -0
- package/lib/memory/test-rs-innovation-classifier.cjs +301 -0
- package/lib/memory/test-rs-mind-map.cjs +646 -0
- package/lib/memory/test-rs-neo4j-writer.cjs +518 -0
- package/lib/memory/test-rs-nl-to-query.cjs +449 -0
- package/lib/memory/test-rs-pinecone-bridge.cjs +277 -0
- package/lib/memory/test-rs-preprocessor.cjs +433 -0
- package/lib/memory/test-rs-query-matrix.cjs +391 -0
- package/lib/memory/test-rs-query-to-text.cjs +551 -0
- package/lib/memory/test-rs-sqlite-mirror.cjs +649 -0
- package/lib/memory/test-rs-thesis-generator.cjs +360 -0
- package/lib/memory/triple-context-formatter.cjs +473 -0
- package/lib/memory/triple-context-formatter.test.cjs +442 -0
- package/lib/memory/user-md-persona.test.cjs +565 -0
- package/lib/memory/userpromptsubmit-integration.test.cjs +690 -0
- package/lib/memory/validators/README.md +157 -0
- package/lib/memory/validators/brain-md-invariants.cjs +475 -0
- package/lib/memory/validators/brain-substrate-invariants.cjs +285 -0
- package/lib/memory/validators/external-academic-invariants.cjs +249 -0
- package/lib/memory/validators/external-industry-invariants.cjs +271 -0
- package/lib/memory/validators/external-patents-invariants.cjs +266 -0
- package/lib/memory/validators/minto-invariants.cjs +62 -0
- package/lib/memory/validators/navigation-invariants.cjs +340 -0
- package/lib/memory/validators/queue-health.cjs +95 -0
- package/lib/memory/validators/snapshot-integrity.cjs +129 -0
- package/lib/memory/validators/stale-lifecycle.cjs +116 -0
- package/lib/memory/vault-section-minto-generator-atomic.test.cjs +556 -0
- package/lib/memory/vault-section-minto-generator-atomic.worker.cjs +73 -0
- package/lib/memory/write-lock-atomic.test.cjs +137 -0
- package/lib/memory/write-lock-atomic.worker.cjs +55 -0
- package/lib/parity/check-parity.cjs +83 -0
- package/lib/presentation/presentation-server.cjs +101 -0
- package/lib/presentation/presentation-watcher.cjs +123 -0
- package/lib/quickview/hub-server.cjs +719 -0
- package/lib/quickview/server.cjs +533 -0
- package/lib/render/JTBD-PALETTES.md +145 -0
- package/lib/render/ROOM.md +59 -0
- package/lib/render/render-v2.cjs +486 -0
- package/lib/render/render-v2.test.cjs +267 -0
- package/lib/render/render.cjs +65 -0
- package/lib/state/ROOM.md +46 -0
- package/lib/state/state-md-parser.cjs +215 -0
- package/lib/statusline/ROOM.md +38 -0
- package/lib/statusline/banner-suppression.cjs +50 -0
- package/lib/statusline/surface-detect.cjs +85 -0
- package/lib/update-bootstrap.sh.template +145 -0
- package/lib/vault/frontmatter-schema.cjs +297 -0
- package/lib/vault/room-scanner.cjs +352 -0
- package/lib/vault/wikilink-builder.cjs +231 -0
- package/lib/vault/wikilink-builder.test.cjs +182 -0
- package/lib/wiki/graph-links.cjs +281 -0
- package/lib/wiki/page-renderer.cjs +229 -0
- package/lib/wiki/wiki-chat.cjs +81 -0
- package/lib/wiki/wiki-layout.cjs +1459 -0
- package/lib/wiki/wiki-search.cjs +142 -0
- package/lib/wiki/wiki-server.cjs +678 -0
- package/lib/wiki/wiki-watcher.cjs +105 -0
- package/lib/workflow/ROOM.md +47 -0
- package/lib/workflow/command-resolver.cjs +155 -0
- package/lib/workflow/command-resolver.test.cjs +235 -0
- package/package.json +44 -0
- package/pipelines/analogy/01-decompose.md +80 -0
- package/pipelines/analogy/02-abstract.md +87 -0
- package/pipelines/analogy/03-search.md +135 -0
- package/pipelines/analogy/04-transfer.md +101 -0
- package/pipelines/analogy/05-validate.md +106 -0
- package/pipelines/analogy/CHAIN.md +56 -0
- package/pipelines/discovery/01-explore-domains.md +44 -0
- package/pipelines/discovery/02-think-hats.md +50 -0
- package/pipelines/discovery/03-analyze-needs.md +54 -0
- package/pipelines/discovery/CHAIN.md +37 -0
- package/pipelines/thesis/01-structure-argument.md +45 -0
- package/pipelines/thesis/02-challenge-assumptions.md +48 -0
- package/pipelines/thesis/03-build-thesis.md +54 -0
- package/pipelines/thesis/CHAIN.md +37 -0
- package/references/brain/causal-directives.md +91 -0
- package/references/brain/causal-enrichment.cypher +165 -0
- package/references/brain/command-triggers-schema.md +226 -0
- package/references/brain/graph-architecture.md +317 -0
- package/references/brain/query-patterns.md +460 -0
- package/references/brain/room-hierarchy-schema.md +218 -0
- package/references/brain/schema.md +76 -0
- package/references/capability-radar/capabilities-index.md +241 -0
- package/references/capability-radar/changelog-cache.md +81 -0
- package/references/causal/causal-schema.md +103 -0
- package/references/design/email-template-standard.md +155 -0
- package/references/design/graph-visualization-standard.md +178 -0
- package/references/document-generation.md +179 -0
- package/references/hsi/HSI-TOOLS-REFERENCE.md +222 -0
- package/references/import-config.md +141 -0
- package/references/integrations/detection-patterns.md +101 -0
- package/references/meeting/artifact-template.md +377 -0
- package/references/meeting/cross-meeting-intelligence.md +216 -0
- package/references/meeting/cross-relationship-patterns.md +202 -0
- package/references/meeting/live-join-interface.md +244 -0
- package/references/meeting/section-mapping.md +192 -0
- package/references/meeting/segment-classification.md +258 -0
- package/references/meeting/speaker-profile-template.md +219 -0
- package/references/meeting/summary-template.md +348 -0
- package/references/meeting/transcript-patterns.md +226 -0
- package/references/methodology/analyze-needs.md +135 -0
- package/references/methodology/analyze-systems.md +121 -0
- package/references/methodology/analyze-timing.md +149 -0
- package/references/methodology/beautiful-question.md +109 -0
- package/references/methodology/build-knowledge.md +161 -0
- package/references/methodology/build-thesis.md +237 -0
- package/references/methodology/challenge-assumptions.md +127 -0
- package/references/methodology/diagnose.md +169 -0
- package/references/methodology/dominant-designs.md +212 -0
- package/references/methodology/explore-domains.md +147 -0
- package/references/methodology/explore-futures.md +163 -0
- package/references/methodology/explore-trends.md +129 -0
- package/references/methodology/find-bottlenecks.md +131 -0
- package/references/methodology/grade.md +211 -0
- package/references/methodology/index.md +97 -0
- package/references/methodology/leadership.md +200 -0
- package/references/methodology/lean-canvas.md +116 -0
- package/references/methodology/macro-trends.md +192 -0
- package/references/methodology/map-unknowns.md +137 -0
- package/references/methodology/mullins-7-domains.md +104 -0
- package/references/methodology/problem-types.md +65 -0
- package/references/methodology/root-cause.md +178 -0
- package/references/methodology/sapphire-encoding.md +355 -0
- package/references/methodology/scenario-plan.md +178 -0
- package/references/methodology/score-innovation.md +154 -0
- package/references/methodology/structure-argument.md +158 -0
- package/references/methodology/systems-thinking.md +159 -0
- package/references/methodology/think-hats.md +147 -0
- package/references/methodology/triz-matrix.json +751 -0
- package/references/methodology/triz-principles.md +501 -0
- package/references/methodology/user-needs.md +199 -0
- package/references/methodology/validate.md +163 -0
- package/references/methodology/value-proposition.md +244 -0
- package/references/opportunities/funding-lifecycle.md +103 -0
- package/references/opportunities/grant-api-patterns.md +99 -0
- package/references/opportunities/opportunity-template.md +84 -0
- package/references/personality/assessment-philosophy.md +72 -0
- package/references/personality/lexicon.md +100 -0
- package/references/personality/persona-chains.md +56 -0
- package/references/personality/pws-lexicon-full.md +499 -0
- package/references/personality/voice-dna.md +156 -0
- package/references/personas/hat-perspectives.md +76 -0
- package/references/personas/persona-template.md +63 -0
- package/references/pipeline/act-output-contract.md +88 -0
- package/references/pipeline/chains-index.md +39 -0
- package/references/pws-profile-generation.md +79 -0
- package/references/reasoning/reasoning-schema.md +143 -0
- package/references/reasoning/reasoning-template.md +68 -0
- package/references/reasoning/run-template.md +38 -0
- package/references/research/RESEARCH_14_CLAUDE_CODE_SOURCE_ARCHITECTURE.md +209 -0
- package/references/research/RESEARCH_15_V1.8_OPTIMIZATION_JTBD.md +375 -0
- package/references/research/RESEARCH_16_NATIVE_FIRST_PLUGIN_ARCHITECTURE.md +575 -0
- package/references/research/RESEARCH_17_MCP_UI_FRAMEWORKS.md +272 -0
- package/references/taxonomy/TAXONOMY.md +192 -0
- package/references/templates/MINTO.md +36 -0
- package/references/user-research/2026-04-05-leah-lawrence-session.md +202 -0
- package/references/vault-kit/README.md +35 -0
- package/references/vault-kit/app.json +12 -0
- package/references/vault-kit/appearance.json +12 -0
- package/references/vault-kit/graph.json +35 -0
- package/references/vault-kit/snippets/mindrian-destijl.css +297 -0
- package/references/vault-kit/templates/new-artifact.md +37 -0
- package/references/vault-kit/templates/new-meeting-note.md +35 -0
- package/references/vault-kit/templates/new-team-profile.md +29 -0
- package/references/vault-kit/templates/new-xref.md +35 -0
- package/references/visual/symbol-system.md +151 -0
- package/skills/MOSDeckEngine/SKILL.md +325 -0
- package/skills/brain-connector/SKILL.md +114 -0
- package/skills/context-engine/SKILL.md +147 -0
- package/skills/conversation-mode/SKILL.md +102 -0
- package/skills/larry-personality/SKILL.md +219 -0
- package/skills/larry-personality/framework-chains.md +92 -0
- package/skills/larry-personality/mode-engine.md +185 -0
- package/skills/mullins-scaffold/SKILL.md +61 -0
- package/skills/mullins-scaffold/scaffold.json +146 -0
- package/skills/pws-methodology/SKILL.md +49 -0
- package/skills/room-passive/SKILL.md +165 -0
- package/skills/room-proactive/SKILL.md +250 -0
- package/skills/ui-system/SKILL.md +277 -0
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2026 Mindrian. BSL 1.1.
|
|
3
|
+
* Phase 89.2 Plan 07 Task 2 -- Phase 3 deterministic breakthrough scorer.
|
|
4
|
+
*
|
|
5
|
+
* 5-dimension 0-10 rubric per kickoff §5 Phase 3 enumeration. Deterministic
|
|
6
|
+
* weighted sum from substrate metadata + classifier output. Each dimension
|
|
7
|
+
* is scored 0-2; total is the simple sum.
|
|
8
|
+
*
|
|
9
|
+
* feasibility 0-2 from substrate.tier
|
|
10
|
+
* core -> 2.0
|
|
11
|
+
* applied -> 1.5
|
|
12
|
+
* theoretical -> 1.0
|
|
13
|
+
* <other> -> 1.0 (defensive default)
|
|
14
|
+
*
|
|
15
|
+
* market 0-2 from industry signal count (Tavily-orchestrated
|
|
16
|
+
* industry-fetcher signal count for the target domain):
|
|
17
|
+
* 0 -> 0.0
|
|
18
|
+
* 1-3 -> 0.5
|
|
19
|
+
* 4-9 -> 1.0
|
|
20
|
+
* 10-19 -> 1.5
|
|
21
|
+
* >=20 -> 2.0
|
|
22
|
+
*
|
|
23
|
+
* magnitude 0-2 from differential score (`diff` value mapped):
|
|
24
|
+
* 0.0 - 0.3 -> 0.0
|
|
25
|
+
* 0.3 - 0.5 -> 1.0
|
|
26
|
+
* 0.5 - 0.7 -> 1.5
|
|
27
|
+
* >=0.7 -> 2.0
|
|
28
|
+
*
|
|
29
|
+
* advantage 0-2 from cross-domain pair rarity. Computed from
|
|
30
|
+
* opts.pair_density (density of similar pairs in the
|
|
31
|
+
* substrate, [0, 1]; 1 = fully dense, 0 = perfectly rare).
|
|
32
|
+
* advantage = 2 * (1 - density), clamped to [0, 2].
|
|
33
|
+
* Default density = 1.0 (fully dense -> zero advantage)
|
|
34
|
+
* when pair_density is omitted -- pessimistic default.
|
|
35
|
+
*
|
|
36
|
+
* impact 0-2 from BERT cosine score (semantic depth):
|
|
37
|
+
* 0.0 - 0.2 -> 0.0
|
|
38
|
+
* 0.2 - 0.4 -> 0.5
|
|
39
|
+
* 0.4 - 0.6 -> 1.0
|
|
40
|
+
* 0.6 - 0.8 -> 1.5
|
|
41
|
+
* >=0.8 -> 2.0
|
|
42
|
+
*
|
|
43
|
+
* dominant_dimension is the breakdown key with the highest score. Ties
|
|
44
|
+
* are broken by frozen DIMENSIONS order ['feasibility', 'market',
|
|
45
|
+
* 'magnitude', 'advantage', 'impact'] -- the FIRST matching key wins.
|
|
46
|
+
* The frozen-order tie-break is the determinism contract; without it,
|
|
47
|
+
* Object.keys insertion order would be the implicit tie-breaker, which
|
|
48
|
+
* is fragile under refactor.
|
|
49
|
+
*
|
|
50
|
+
* Determinism contract: byte-identical JSON.stringify(out1) === JSON.stringify(out2)
|
|
51
|
+
* for identical inputs. No Math.random, no Date.now, no LLM call.
|
|
52
|
+
*
|
|
53
|
+
* Canon Part 8 (Graph Boundary): two defense-in-depth layers.
|
|
54
|
+
*
|
|
55
|
+
* Layer 1 -- pre-input scan: classified_pair.query_concept and
|
|
56
|
+
* classified_pair.doc_concept passed through auditQueryString BEFORE
|
|
57
|
+
* any rubric application. Throws ExternalEgressViolation on hit.
|
|
58
|
+
*
|
|
59
|
+
* Layer 2 -- pre-return audit: composite output passed through
|
|
60
|
+
* auditQueryObject before return. Defense-in-depth so any forbidden
|
|
61
|
+
* pattern smuggled via opts.substrate_metadata.title (or any field
|
|
62
|
+
* that propagates into the return envelope) is caught at the gate.
|
|
63
|
+
*
|
|
64
|
+
* Pure CJS, zero npm deps, node built-ins only beyond rs-egress-* primitives.
|
|
65
|
+
*/
|
|
66
|
+
'use strict';
|
|
67
|
+
|
|
68
|
+
const { auditQueryString, auditQueryObject } = require('./rs-egress-prompts.cjs');
|
|
69
|
+
require('./rs-egress-violations.cjs');
|
|
70
|
+
|
|
71
|
+
// ---------- Frozen invariants ----------
|
|
72
|
+
|
|
73
|
+
// 5-dimension space, frozen. Order is the tie-break contract for
|
|
74
|
+
// dominant_dimension: first matching key wins.
|
|
75
|
+
const DIMENSIONS = Object.freeze([
|
|
76
|
+
'feasibility',
|
|
77
|
+
'market',
|
|
78
|
+
'magnitude',
|
|
79
|
+
'advantage',
|
|
80
|
+
'impact',
|
|
81
|
+
]);
|
|
82
|
+
|
|
83
|
+
// substrate.tier -> feasibility lookup (frozen).
|
|
84
|
+
const TIER_TO_FEASIBILITY = Object.freeze({
|
|
85
|
+
core: 2.0,
|
|
86
|
+
applied: 1.5,
|
|
87
|
+
theoretical: 1.0,
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// ---------- Dimension functions ----------
|
|
91
|
+
|
|
92
|
+
// Industry signal count -> market score. Pure step function.
|
|
93
|
+
function SIGNAL_COUNT_TO_MARKET(n) {
|
|
94
|
+
const x = (typeof n === 'number' && isFinite(n)) ? n : 0;
|
|
95
|
+
if (x >= 20) return 2.0;
|
|
96
|
+
if (x >= 10) return 1.5;
|
|
97
|
+
if (x >= 4) return 1.0;
|
|
98
|
+
if (x >= 1) return 0.5;
|
|
99
|
+
return 0.0;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Differential score -> magnitude score. Pure step function.
|
|
103
|
+
function DIFF_TO_MAGNITUDE(d) {
|
|
104
|
+
const x = (typeof d === 'number' && isFinite(d)) ? d : 0;
|
|
105
|
+
if (x >= 0.7) return 2.0;
|
|
106
|
+
if (x >= 0.5) return 1.5;
|
|
107
|
+
if (x >= 0.3) return 1.0;
|
|
108
|
+
return 0.0;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Cross-domain pair density -> advantage score. Density in [0, 1] inverts
|
|
112
|
+
// to advantage = 2 * (1 - density), clamped to [0, 2] for defense against
|
|
113
|
+
// out-of-range inputs (e.g., NaN, density > 1, density < 0).
|
|
114
|
+
function PAIR_DENSITY_TO_ADVANTAGE(rho) {
|
|
115
|
+
const x = (typeof rho === 'number' && isFinite(rho)) ? rho : 1.0;
|
|
116
|
+
const raw = 2.0 * (1.0 - x);
|
|
117
|
+
if (raw < 0) return 0.0;
|
|
118
|
+
if (raw > 2.0) return 2.0;
|
|
119
|
+
return raw;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// BERT score -> impact score. Pure step function.
|
|
123
|
+
function BERT_TO_IMPACT(b) {
|
|
124
|
+
const x = (typeof b === 'number' && isFinite(b)) ? b : 0;
|
|
125
|
+
if (x >= 0.8) return 2.0;
|
|
126
|
+
if (x >= 0.6) return 1.5;
|
|
127
|
+
if (x >= 0.4) return 1.0;
|
|
128
|
+
if (x >= 0.2) return 0.5;
|
|
129
|
+
return 0.0;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// ---------- computeDominant ----------
|
|
133
|
+
//
|
|
134
|
+
// Returns the first DIMENSIONS key whose breakdown value equals the max.
|
|
135
|
+
// Frozen-order tie-break is the determinism contract.
|
|
136
|
+
|
|
137
|
+
function computeDominant(breakdown) {
|
|
138
|
+
if (!breakdown || typeof breakdown !== 'object') return DIMENSIONS[0];
|
|
139
|
+
let max = -Infinity;
|
|
140
|
+
for (let i = 0; i < DIMENSIONS.length; i += 1) {
|
|
141
|
+
const v = breakdown[DIMENSIONS[i]];
|
|
142
|
+
if (typeof v === 'number' && v > max) max = v;
|
|
143
|
+
}
|
|
144
|
+
for (let i = 0; i < DIMENSIONS.length; i += 1) {
|
|
145
|
+
if (breakdown[DIMENSIONS[i]] === max) return DIMENSIONS[i];
|
|
146
|
+
}
|
|
147
|
+
return DIMENSIONS[0];
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// ---------- scoreBreakthrough ----------
|
|
151
|
+
//
|
|
152
|
+
// Public entry point. Synchronous (no I/O, no spawn). Throws only on
|
|
153
|
+
// Canon Part 8 violations.
|
|
154
|
+
//
|
|
155
|
+
// Inputs:
|
|
156
|
+
// classified_pair object the post-classifier shape (pass-through fields)
|
|
157
|
+
// opts optional:
|
|
158
|
+
// substrate_metadata {tier: 'core'|'applied'|'theoretical', ...}
|
|
159
|
+
// industry_signal_count number count of industry-fetcher signals
|
|
160
|
+
// pair_density number [0, 1]; 1 = fully dense, 0 = rare
|
|
161
|
+
//
|
|
162
|
+
// Output (happy path):
|
|
163
|
+
// {<pass-through classified_pair fields>,
|
|
164
|
+
// breakthrough: {
|
|
165
|
+
// score: 0-10,
|
|
166
|
+
// breakdown: {feasibility, market, magnitude, advantage, impact},
|
|
167
|
+
// dominant_dimension: <one of DIMENSIONS>,
|
|
168
|
+
// }}
|
|
169
|
+
//
|
|
170
|
+
// Output (invalid input):
|
|
171
|
+
// {error: 'invalid_input', reason: <string>}
|
|
172
|
+
|
|
173
|
+
function scoreBreakthrough(classified_pair, opts) {
|
|
174
|
+
if (!classified_pair || typeof classified_pair !== 'object') {
|
|
175
|
+
return { error: 'invalid_input', reason: 'not_object' };
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Canon Part 8 Layer 1: pre-input scan on user-controlled concepts
|
|
179
|
+
// BEFORE any rubric application. Throws ExternalEgressViolation on hit.
|
|
180
|
+
if (typeof classified_pair.query_concept === 'string') {
|
|
181
|
+
auditQueryString(classified_pair.query_concept, 'breakthrough-scorer');
|
|
182
|
+
}
|
|
183
|
+
if (typeof classified_pair.doc_concept === 'string') {
|
|
184
|
+
auditQueryString(classified_pair.doc_concept, 'breakthrough-scorer');
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
opts = opts || {};
|
|
188
|
+
const substrateMeta = (opts.substrate_metadata && typeof opts.substrate_metadata === 'object')
|
|
189
|
+
? opts.substrate_metadata
|
|
190
|
+
: {};
|
|
191
|
+
const tier = (typeof substrateMeta.tier === 'string') ? substrateMeta.tier : 'theoretical';
|
|
192
|
+
|
|
193
|
+
// 5-dimension rubric application.
|
|
194
|
+
const feasibility = (tier in TIER_TO_FEASIBILITY) ? TIER_TO_FEASIBILITY[tier] : 1.0;
|
|
195
|
+
const market = SIGNAL_COUNT_TO_MARKET(opts.industry_signal_count);
|
|
196
|
+
const magnitude = DIFF_TO_MAGNITUDE(classified_pair.diff);
|
|
197
|
+
const advantage = PAIR_DENSITY_TO_ADVANTAGE(
|
|
198
|
+
(typeof opts.pair_density === 'number') ? opts.pair_density : 1.0
|
|
199
|
+
);
|
|
200
|
+
const impact = BERT_TO_IMPACT(classified_pair.bert);
|
|
201
|
+
|
|
202
|
+
const breakdown = {
|
|
203
|
+
feasibility: feasibility,
|
|
204
|
+
market: market,
|
|
205
|
+
magnitude: magnitude,
|
|
206
|
+
advantage: advantage,
|
|
207
|
+
impact: impact,
|
|
208
|
+
};
|
|
209
|
+
// Score = simple sum, bounded in [0, 10] by construction (each
|
|
210
|
+
// dimension is in [0, 2]).
|
|
211
|
+
const score = feasibility + market + magnitude + advantage + impact;
|
|
212
|
+
const dominant_dimension = computeDominant(breakdown);
|
|
213
|
+
|
|
214
|
+
// Pass-through preserves the classifier shape so downstream
|
|
215
|
+
// thesis-generator can read all 3 layers (pair + classification +
|
|
216
|
+
// breakthrough) from a single object.
|
|
217
|
+
const out = {
|
|
218
|
+
query_concept: classified_pair.query_concept,
|
|
219
|
+
doc_concept: classified_pair.doc_concept,
|
|
220
|
+
diff: classified_pair.diff,
|
|
221
|
+
lsa: classified_pair.lsa,
|
|
222
|
+
bert: classified_pair.bert,
|
|
223
|
+
passes: classified_pair.passes,
|
|
224
|
+
classification: classified_pair.classification,
|
|
225
|
+
bridge_concept: classified_pair.bridge_concept,
|
|
226
|
+
breakthrough: {
|
|
227
|
+
score: score,
|
|
228
|
+
breakdown: breakdown,
|
|
229
|
+
dominant_dimension: dominant_dimension,
|
|
230
|
+
},
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
// Canon Part 8 Layer 2: pre-return audit on composite output. Defense
|
|
234
|
+
// in depth. If a future refactor propagates substrate_metadata.title or
|
|
235
|
+
// similar fields into the envelope, the audit catches forbidden bytes
|
|
236
|
+
// at the gate.
|
|
237
|
+
auditQueryObject(out, 'breakthrough-scorer');
|
|
238
|
+
|
|
239
|
+
return out;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// ---------- Exports ----------
|
|
243
|
+
|
|
244
|
+
module.exports = {
|
|
245
|
+
scoreBreakthrough: scoreBreakthrough,
|
|
246
|
+
_test: {
|
|
247
|
+
DIMENSIONS: DIMENSIONS,
|
|
248
|
+
TIER_TO_FEASIBILITY: TIER_TO_FEASIBILITY,
|
|
249
|
+
SIGNAL_COUNT_TO_MARKET: SIGNAL_COUNT_TO_MARKET,
|
|
250
|
+
DIFF_TO_MAGNITUDE: DIFF_TO_MAGNITUDE,
|
|
251
|
+
PAIR_DENSITY_TO_ADVANTAGE: PAIR_DENSITY_TO_ADVANTAGE,
|
|
252
|
+
BERT_TO_IMPACT: BERT_TO_IMPACT,
|
|
253
|
+
computeDominant: computeDominant,
|
|
254
|
+
},
|
|
255
|
+
};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2026 Mindrian. BSL 1.1.
|
|
3
|
+
* Phase 89.4 Plan 01 -- Canon Part 3 closed-vocabulary enforcement.
|
|
4
|
+
*
|
|
5
|
+
* Sibling of rs-egress-violations.cjs (89.2-01) by ANATOMY but
|
|
6
|
+
* SEPARATE module by SEMANTICS. ExternalEgressViolation guards
|
|
7
|
+
* outbound flow to public external fetchers; CanonVerbViolation
|
|
8
|
+
* guards the 10-verb closed vocabulary at the Decision Gate
|
|
9
|
+
* boundary. Sharing the class would conflate two distinct
|
|
10
|
+
* chokepoints. Both classes follow identical anatomy (.name + .meta)
|
|
11
|
+
* so Canon-aware caller wrappers catch them uniformly via err.name.
|
|
12
|
+
*
|
|
13
|
+
* The 10-verb canonical vocabulary is authoritative per
|
|
14
|
+
* docs/MINDRIAN-CANON.md Part 3 lines 153-162. New verbs require
|
|
15
|
+
* canon amendment, not a code-level invention.
|
|
16
|
+
*
|
|
17
|
+
* meta convention (informal, not enforced): callers SHOULD populate
|
|
18
|
+
* meta.attempted_verb (string) the verb_string that failed validation
|
|
19
|
+
* meta.surface (string) the call-site tag, e.g. 'navigation-engine'
|
|
20
|
+
* The class itself does not enforce shape so adversarial fixtures can
|
|
21
|
+
* probe edge cases (default meta = {}, omitted meta) without
|
|
22
|
+
* instantiation fighting them.
|
|
23
|
+
*
|
|
24
|
+
* validateVerb contract:
|
|
25
|
+
* typeof verb_string !== 'string' -> TypeError ('must be a string')
|
|
26
|
+
* empty or out-of-set string -> CanonVerbViolation
|
|
27
|
+
* in-set string -> returns the input verbatim
|
|
28
|
+
*
|
|
29
|
+
* surface argument is optional. When supplied as a non-empty string it
|
|
30
|
+
* propagates to err.meta.surface. When omitted or empty, defaults to
|
|
31
|
+
* the literal 'unknown' so downstream audit log lines always carry a
|
|
32
|
+
* non-empty surface tag (mirrors Phase 89.2 audit-triple convention).
|
|
33
|
+
*
|
|
34
|
+
* CANONICAL_VERBS is Object.freeze'd so accidental mutation throws in
|
|
35
|
+
* strict mode and Object.isFrozen returns true. Downstream consumers
|
|
36
|
+
* (89.5 NL-Graph Surface UI, future Decision Gate renderers) can
|
|
37
|
+
* enumerate the set without defensive copying.
|
|
38
|
+
*
|
|
39
|
+
* Pure CJS, zero npm deps, no Node built-ins beyond core require.
|
|
40
|
+
*/
|
|
41
|
+
'use strict';
|
|
42
|
+
|
|
43
|
+
class CanonVerbViolation extends Error {
|
|
44
|
+
constructor(message, meta) {
|
|
45
|
+
super(message);
|
|
46
|
+
this.name = 'CanonVerbViolation';
|
|
47
|
+
this.meta = meta || {};
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const CANONICAL_VERBS = Object.freeze([
|
|
52
|
+
'Run Methodology',
|
|
53
|
+
'Reformulate',
|
|
54
|
+
'Spawn Sub-Agent',
|
|
55
|
+
'Navigate Graph',
|
|
56
|
+
"Devil's Advocate",
|
|
57
|
+
'Scenario Plan',
|
|
58
|
+
'Synthesize',
|
|
59
|
+
'Bank Opportunity',
|
|
60
|
+
'Defer',
|
|
61
|
+
'Free-Text',
|
|
62
|
+
]);
|
|
63
|
+
|
|
64
|
+
function validateVerb(verb_string, surface) {
|
|
65
|
+
if (typeof verb_string !== 'string') {
|
|
66
|
+
throw new TypeError(
|
|
67
|
+
'validateVerb: input must be a string; got ' + typeof verb_string
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
const surfaceTag = (typeof surface === 'string' && surface.length > 0)
|
|
71
|
+
? surface
|
|
72
|
+
: 'unknown';
|
|
73
|
+
if (!CANONICAL_VERBS.includes(verb_string)) {
|
|
74
|
+
throw new CanonVerbViolation(
|
|
75
|
+
'verb not in Canon Part 3 closed vocabulary: ' + JSON.stringify(verb_string),
|
|
76
|
+
{ attempted_verb: verb_string, surface: surfaceTag }
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
return verb_string;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
module.exports = { CanonVerbViolation, CANONICAL_VERBS, validateVerb };
|
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2026 Mindrian. BSL 1.1.
|
|
3
|
+
* Phase 89.4 Plan 02 -- engine-choreography codification (core).
|
|
4
|
+
* Phase 89.4 Plan 03 -- skill-spawn rule table wired in place.
|
|
5
|
+
*
|
|
6
|
+
* Codifies upstream + downstream chain wiring for the RS Discovery
|
|
7
|
+
* Engine per kickoff section 6 (USER LOAD-BEARING INTENT 7).
|
|
8
|
+
*
|
|
9
|
+
* lookupUpstream(problem_type, stage, opts?)
|
|
10
|
+
* -- queries Brain FEEDS_INTO topology via the EXISTING brain-client
|
|
11
|
+
* chokepoint (Canon Part 7); returns {state: 'ready'} OR
|
|
12
|
+
* {state: 'pause', missing_upstream, suggested_action}.
|
|
13
|
+
*
|
|
14
|
+
* emitChainMetadata(rs_type, breakthrough_score, active_context)
|
|
15
|
+
* -- returns the chain metadata block consumed by RS output
|
|
16
|
+
* layer; recommended_verb validated via Canon Part 3 closed-
|
|
17
|
+
* vocabulary checker (89.4-01) BEFORE the block is returned.
|
|
18
|
+
* Plan 89.4-03 wires the internal recommendSkillSpawn call so the
|
|
19
|
+
* chain metadata block carries spawn_skill + confidence + reasoning
|
|
20
|
+
* derived from the SKILL_SPAWN_RULES table.
|
|
21
|
+
*
|
|
22
|
+
* recommendSkillSpawn(rs_type, breakthrough_score, opts)
|
|
23
|
+
* -- Plan 89.4-03 swap: first-match-wins iteration over the locked
|
|
24
|
+
* SKILL_SPAWN_RULES table per kickoff section 6.4. Returns the
|
|
25
|
+
* recommendation; NEVER auto-invokes a skill (the user picks via
|
|
26
|
+
* the Canon Part 3 verb at the Decision Gate; 89.5 / 91 concern).
|
|
27
|
+
*
|
|
28
|
+
* SKILL_SPAWN_RULES (frozen)
|
|
29
|
+
* -- 5 rules per kickoff section 6.4 in declared order. Object.freeze'd
|
|
30
|
+
* at module scope AND each rule entry is independently frozen so
|
|
31
|
+
* the table cannot mutate at runtime.
|
|
32
|
+
*
|
|
33
|
+
* Reuses (Canon Part 7):
|
|
34
|
+
* brain-client.cjs::query / isAvailable (89.1a chokepoint)
|
|
35
|
+
* rs-egress-prompts.cjs::auditQueryObject (89.2-01 chokepoint)
|
|
36
|
+
* rs-canon-violations.cjs::validateVerb (89.4-01)
|
|
37
|
+
* rs-canon-violations.cjs::CanonVerbViolation (89.4-01)
|
|
38
|
+
* rs-egress-violations.cjs::ExternalEgressViolation (89.2-01)
|
|
39
|
+
*
|
|
40
|
+
* Brain query graceful-degradation order (mirrors Phase 90 Mode B/C/Tier-0):
|
|
41
|
+
* 1. brainClient.isAvailable() === false -> {state: 'ready'} + warn
|
|
42
|
+
* 2. brainClient.query() throws or returns null -> {state: 'ready'} + warn
|
|
43
|
+
* 3. response.records absent or wrong shape -> {state: 'ready'} + warn
|
|
44
|
+
* 4. Cross-reference returned framework names against
|
|
45
|
+
* opts.upstreamFreshness Map<name, boolean>; absent key = fresh.
|
|
46
|
+
*
|
|
47
|
+
* Canon Part 8 defense-in-depth:
|
|
48
|
+
* - lookupUpstream input ({problem_type, stage}) is audited via
|
|
49
|
+
* auditQueryObject BEFORE any Brain query is dispatched. If the
|
|
50
|
+
* audit trips, no Brain RPC is made and ExternalEgressViolation
|
|
51
|
+
* bubbles to the caller.
|
|
52
|
+
* - emitChainMetadata input (active_context) is audited via
|
|
53
|
+
* auditQueryObject so adversarial bytes nested in active_context.meta
|
|
54
|
+
* cannot smuggle into the returned metadata block.
|
|
55
|
+
* - recommendSkillSpawn opts (when non-empty) is audited as well.
|
|
56
|
+
* - The module never reaches the network directly; the only outbound
|
|
57
|
+
* surface is brainClient.query, which inherits 89.1a's allow-list.
|
|
58
|
+
*
|
|
59
|
+
* Pure CJS, zero npm deps, no Node built-ins beyond core require.
|
|
60
|
+
*/
|
|
61
|
+
'use strict';
|
|
62
|
+
|
|
63
|
+
const brainClientDefault = require('./brain-client.cjs');
|
|
64
|
+
const { auditQueryObject } = require('./rs-egress-prompts.cjs');
|
|
65
|
+
const { ExternalEgressViolation } = require('./rs-egress-violations.cjs');
|
|
66
|
+
const {
|
|
67
|
+
validateVerb,
|
|
68
|
+
CanonVerbViolation,
|
|
69
|
+
CANONICAL_VERBS,
|
|
70
|
+
} = require('./rs-canon-violations.cjs');
|
|
71
|
+
|
|
72
|
+
// ---------- Skill-spawn rule table (Plan 89.4-03; LOCKED per kickoff section 6.4) ----------
|
|
73
|
+
|
|
74
|
+
// Rules are evaluated in declared order via first-match-wins semantics.
|
|
75
|
+
// Confidence values match the kickoff section 6.4 specification verbatim;
|
|
76
|
+
// the 0.7 RECOMMENDED threshold is enforced by the CALLER (Plan 89.5
|
|
77
|
+
// Decision Gate UI) per Phase 88.2 Navigation Engine Brain interface
|
|
78
|
+
// contract. recommendSkillSpawn returns the raw confidence so callers can
|
|
79
|
+
// choose whether to surface a RECOMMENDED chip.
|
|
80
|
+
//
|
|
81
|
+
// Each rule entry is independently Object.freeze'd so the table cannot be
|
|
82
|
+
// mutated at runtime even if a caller obtains a reference to a rule. The
|
|
83
|
+
// match() functions are pure (no side effects, no I/O) and tolerate
|
|
84
|
+
// missing opts keys via `(opts.X || 0)` / `(opts.X || []).length` guards.
|
|
85
|
+
const SKILL_SPAWN_RULES = Object.freeze([
|
|
86
|
+
Object.freeze({
|
|
87
|
+
match: function (rs, score, opts) {
|
|
88
|
+
return score >= 7 && rs === 'structural_transfer';
|
|
89
|
+
},
|
|
90
|
+
spawn: '/mos:find-analogies',
|
|
91
|
+
confidence: 0.85,
|
|
92
|
+
reasoning: 'high breakthrough + structural transfer -> SAPPhIRE/TRIZ deepening',
|
|
93
|
+
}),
|
|
94
|
+
Object.freeze({
|
|
95
|
+
match: function (rs, score, opts) {
|
|
96
|
+
return score >= 7 && (opts.industry_signals_count || 0) > 0;
|
|
97
|
+
},
|
|
98
|
+
spawn: '/mos:lean-canvas',
|
|
99
|
+
confidence: 0.80,
|
|
100
|
+
reasoning: 'high breakthrough + market signal -> business model exploration',
|
|
101
|
+
}),
|
|
102
|
+
Object.freeze({
|
|
103
|
+
match: function (rs, score, opts) {
|
|
104
|
+
return (opts.cross_methodology_substrates || []).length > 1;
|
|
105
|
+
},
|
|
106
|
+
spawn: '/mos:pipeline',
|
|
107
|
+
confidence: 0.75,
|
|
108
|
+
reasoning: 'cross-methodology discovery -> chained pipeline (RS -> JTBD -> Persona)',
|
|
109
|
+
}),
|
|
110
|
+
Object.freeze({
|
|
111
|
+
match: function (rs, score, opts) {
|
|
112
|
+
return (opts.resolved_experts_count || 0) > 5
|
|
113
|
+
&& (opts.resolved_institutions_count || 0) > 1;
|
|
114
|
+
},
|
|
115
|
+
spawn: '/mos:persona',
|
|
116
|
+
confidence: 0.70,
|
|
117
|
+
reasoning: 'expert network dense -> team composition',
|
|
118
|
+
}),
|
|
119
|
+
Object.freeze({
|
|
120
|
+
match: function (rs, score, opts) {
|
|
121
|
+
return score < 5 && opts.cynefin === 'complex';
|
|
122
|
+
},
|
|
123
|
+
spawn: '/mos:think-hats',
|
|
124
|
+
confidence: 0.65,
|
|
125
|
+
reasoning: 'low breakthrough + Cynefin complex -> perspective diversity',
|
|
126
|
+
}),
|
|
127
|
+
]);
|
|
128
|
+
|
|
129
|
+
// ---------- Internal helpers ----------
|
|
130
|
+
|
|
131
|
+
// Sanitize a string for embedding in a Cypher query. Mirrors the byte-
|
|
132
|
+
// for-byte whitelist from brain-client.cjs::sanitizeCypherInput
|
|
133
|
+
// ([a-zA-Z0-9 ._-]). We do NOT call brainClient._test.sanitizeCypherInput
|
|
134
|
+
// directly so this module remains testable with a stub brainClient.
|
|
135
|
+
function _sanitizeCypher(value) {
|
|
136
|
+
if (value === null || value === undefined) return '';
|
|
137
|
+
const s = typeof value === 'string' ? value : String(value);
|
|
138
|
+
return s.replace(/[^a-zA-Z0-9 ._-]/g, '');
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Build the Brain Cypher query asking for upstream FEEDS_INTO frameworks
|
|
142
|
+
// for the reverse-salient engine, parameterized (defensively sanitized)
|
|
143
|
+
// by problem_type + stage for forward-compat (89.5 may bind these via
|
|
144
|
+
// Brain's parameterized query path).
|
|
145
|
+
function _buildUpstreamCypher(problem_type, stage) {
|
|
146
|
+
const safeProblem = _sanitizeCypher(problem_type);
|
|
147
|
+
const safeStage = _sanitizeCypher(stage);
|
|
148
|
+
// Note: safeProblem / safeStage are intentionally embedded in a
|
|
149
|
+
// comment line so they participate in the query text without
|
|
150
|
+
// affecting the MATCH semantics. The authoritative Brain edge query
|
|
151
|
+
// is for upstream frameworks pointing at the reverse-salient node.
|
|
152
|
+
return (
|
|
153
|
+
'// chain-feeder upstream lookup (problem_type=' + safeProblem +
|
|
154
|
+
' stage=' + safeStage + ')\n' +
|
|
155
|
+
'MATCH (rs:Framework {id: "reverse-salient-framework"}) ' +
|
|
156
|
+
'<-[:FEEDS_INTO]-(upstream:Framework) ' +
|
|
157
|
+
'WHERE rs.id IS NOT NULL ' +
|
|
158
|
+
'RETURN upstream.name AS name LIMIT 10'
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Defensively pull the framework name from a Brain record. Brain
|
|
163
|
+
// returns either {name: '...'} (driver-mode) or [n0, n1, ...] (raw
|
|
164
|
+
// columns). We support both.
|
|
165
|
+
function _recordName(rec) {
|
|
166
|
+
if (!rec || typeof rec !== 'object') return null;
|
|
167
|
+
if (typeof rec.name === 'string') return rec.name;
|
|
168
|
+
if (Array.isArray(rec) && typeof rec[0] === 'string') return rec[0];
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// ---------- Public surface: lookupUpstream ----------
|
|
173
|
+
|
|
174
|
+
async function lookupUpstream(problem_type, stage, opts) {
|
|
175
|
+
opts = opts || {};
|
|
176
|
+
const brainClient = opts.brainClient || brainClientDefault;
|
|
177
|
+
|
|
178
|
+
// Canon Part 8: pre-flight audit on the input strings before they
|
|
179
|
+
// can reach Brain. ExternalEgressViolation bubbles to the caller.
|
|
180
|
+
auditQueryObject(
|
|
181
|
+
{ problem_type: problem_type, stage: stage },
|
|
182
|
+
'rs-chain-feeder-lookup-upstream'
|
|
183
|
+
);
|
|
184
|
+
|
|
185
|
+
if (!brainClient.isAvailable()) {
|
|
186
|
+
process.stderr.write('chain-feeder: Brain unreachable; assuming upstream ready\n');
|
|
187
|
+
return { state: 'ready' };
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
let result;
|
|
191
|
+
try {
|
|
192
|
+
const cypher = _buildUpstreamCypher(problem_type, stage);
|
|
193
|
+
result = await brainClient.query(cypher);
|
|
194
|
+
} catch (_err) {
|
|
195
|
+
process.stderr.write('chain-feeder: Brain query threw; assuming upstream ready\n');
|
|
196
|
+
return { state: 'ready' };
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if (!result || !Array.isArray(result.records)) {
|
|
200
|
+
process.stderr.write(
|
|
201
|
+
'chain-feeder: Brain query returned unexpected shape; assuming upstream ready\n'
|
|
202
|
+
);
|
|
203
|
+
return { state: 'ready' };
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Cross-reference upstream framework names against active room state
|
|
207
|
+
// freshness. Plan 89.4-02 ships a minimal in-memory check: if
|
|
208
|
+
// opts.upstreamFreshness is provided (Map<framework_name, boolean>),
|
|
209
|
+
// use it. Absent key = fresh by default (Phase 89.5 will integrate
|
|
210
|
+
// folder-memory.cjs for real freshness reads against BRAIN.md
|
|
211
|
+
// quadruples per Phase 90).
|
|
212
|
+
const freshness = opts.upstreamFreshness instanceof Map
|
|
213
|
+
? opts.upstreamFreshness
|
|
214
|
+
: new Map();
|
|
215
|
+
|
|
216
|
+
const missing = [];
|
|
217
|
+
for (const rec of result.records) {
|
|
218
|
+
const name = _recordName(rec);
|
|
219
|
+
if (typeof name !== 'string' || name.length === 0) continue;
|
|
220
|
+
if (freshness.has(name) && freshness.get(name) === false) {
|
|
221
|
+
missing.push(name);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if (missing.length === 0) return { state: 'ready' };
|
|
226
|
+
return {
|
|
227
|
+
state: 'pause',
|
|
228
|
+
missing_upstream: missing,
|
|
229
|
+
suggested_action: 'Run Methodology',
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// ---------- Public surface: emitChainMetadata ----------
|
|
234
|
+
|
|
235
|
+
function emitChainMetadata(rs_type, breakthrough_score, active_context) {
|
|
236
|
+
active_context = active_context || {};
|
|
237
|
+
|
|
238
|
+
// Canon Part 8: scan active_context for FORBIDDEN_PATTERNS via the
|
|
239
|
+
// existing chokepoint. Adversarial bytes nested in any field
|
|
240
|
+
// (e.g., active_context.meta.contact) get caught here.
|
|
241
|
+
auditQueryObject(active_context, 'rs-chain-feeder-emit-metadata');
|
|
242
|
+
|
|
243
|
+
// feeds_into mapping (deterministic per rs_type).
|
|
244
|
+
let feeds_into;
|
|
245
|
+
if (rs_type === 'structural_transfer') feeds_into = 'PWS VP';
|
|
246
|
+
else if (rs_type === 'semantic_implementation') feeds_into = 'Causal Loop';
|
|
247
|
+
else if (rs_type === 'hybrid') feeds_into = 'Navigation Engine';
|
|
248
|
+
else feeds_into = 'JTBD'; // fallback for unknown rs_type
|
|
249
|
+
|
|
250
|
+
// recommended_verb selection (deterministic per breakthrough_score).
|
|
251
|
+
// Plan 89.4-03 may refine via skill rules; this module ships the
|
|
252
|
+
// baseline heuristic.
|
|
253
|
+
const score = Number(breakthrough_score);
|
|
254
|
+
const safeScore = Number.isFinite(score) ? score : 0;
|
|
255
|
+
let recommended_verb;
|
|
256
|
+
if (safeScore >= 7) recommended_verb = 'Bank Opportunity';
|
|
257
|
+
else if (safeScore >= 5) recommended_verb = 'Synthesize';
|
|
258
|
+
else recommended_verb = 'Reformulate';
|
|
259
|
+
|
|
260
|
+
// Canon Part 3: validate before returning. Defensive against future
|
|
261
|
+
// edits to the heuristic introducing out-of-set verbs.
|
|
262
|
+
validateVerb(recommended_verb, 'rs-chain-feeder-emit-metadata');
|
|
263
|
+
|
|
264
|
+
// Plan 89.4-03 wiring: the chain metadata block now carries the rule
|
|
265
|
+
// recommendation. active_context is reused as opts for the rule-table
|
|
266
|
+
// evaluation. recommendSkillSpawn re-runs auditQueryObject under its
|
|
267
|
+
// own surface tag; this is intentional double-defense and matches the
|
|
268
|
+
// sibling pattern in lookupUpstream (audit before any consequential
|
|
269
|
+
// computation, even if the caller already audited).
|
|
270
|
+
const skill = recommendSkillSpawn(rs_type, safeScore, active_context);
|
|
271
|
+
|
|
272
|
+
return {
|
|
273
|
+
recommended_verb: recommended_verb,
|
|
274
|
+
feeds_into: feeds_into,
|
|
275
|
+
spawn_skill: skill.spawn_skill,
|
|
276
|
+
confidence: skill.confidence,
|
|
277
|
+
reasoning: skill.reasoning,
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// ---------- Public surface: recommendSkillSpawn (Plan 89.4-03 rule-table wired) ----------
|
|
282
|
+
|
|
283
|
+
function recommendSkillSpawn(rs_type, breakthrough_score, opts) {
|
|
284
|
+
opts = opts || {};
|
|
285
|
+
// Canon Part 8 defense-in-depth (TIGHTENED in Plan 89.4-03): always run
|
|
286
|
+
// auditQueryObject when opts is a non-null object. The Plan 89.4-02 stub
|
|
287
|
+
// had a `Object.keys().length > 0` guard which, while sufficient for the
|
|
288
|
+
// stub, allowed adversarial single-key payloads to slip through if a
|
|
289
|
+
// caller post-mutated opts after the gate. The unconditional audit
|
|
290
|
+
// closes that window. Empty `{}` opts pass JSON.stringify('{}') trivially
|
|
291
|
+
// (zero forbidden-pattern hits).
|
|
292
|
+
auditQueryObject(opts, 'rs-chain-feeder-recommend-skill-spawn');
|
|
293
|
+
|
|
294
|
+
const score = Number(breakthrough_score);
|
|
295
|
+
const safeScore = Number.isFinite(score) ? score : 0;
|
|
296
|
+
|
|
297
|
+
// First-match-wins: iterate SKILL_SPAWN_RULES in declared order; the
|
|
298
|
+
// first rule whose match() returns true wins; subsequent rules are NOT
|
|
299
|
+
// evaluated. If no rule matches, return the no-rule fallback shape.
|
|
300
|
+
for (let i = 0; i < SKILL_SPAWN_RULES.length; i++) {
|
|
301
|
+
const rule = SKILL_SPAWN_RULES[i];
|
|
302
|
+
let matched = false;
|
|
303
|
+
try {
|
|
304
|
+
matched = !!rule.match(rs_type, safeScore, opts);
|
|
305
|
+
} catch (_e) {
|
|
306
|
+
// Defensive: a rule predicate that throws on unexpected opts shape
|
|
307
|
+
// never crashes the loop. Treated as a non-match so the iteration
|
|
308
|
+
// continues. This preserves first-match-wins semantics even under
|
|
309
|
+
// malformed input.
|
|
310
|
+
matched = false;
|
|
311
|
+
}
|
|
312
|
+
if (matched) {
|
|
313
|
+
return {
|
|
314
|
+
spawn_skill: rule.spawn,
|
|
315
|
+
confidence: rule.confidence,
|
|
316
|
+
reasoning: rule.reasoning,
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
return {
|
|
322
|
+
spawn_skill: null,
|
|
323
|
+
confidence: 0,
|
|
324
|
+
reasoning: 'no rule matched',
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// ---------- Module exports ----------
|
|
329
|
+
|
|
330
|
+
module.exports = {
|
|
331
|
+
lookupUpstream,
|
|
332
|
+
emitChainMetadata,
|
|
333
|
+
recommendSkillSpawn,
|
|
334
|
+
// Plan 89.4-03 export (additive). Frozen array; callers may iterate
|
|
335
|
+
// for introspection (e.g., 89.5 NL-Graph Surface UI listing
|
|
336
|
+
// recommended skills) but cannot mutate.
|
|
337
|
+
SKILL_SPAWN_RULES,
|
|
338
|
+
// Re-export so Canon-aware caller wrappers can catch by err.name
|
|
339
|
+
// without re-requiring the upstream modules themselves.
|
|
340
|
+
ExternalEgressViolation,
|
|
341
|
+
CanonVerbViolation,
|
|
342
|
+
CANONICAL_VERBS,
|
|
343
|
+
};
|