@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,333 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Plan 87-06 Test: indexArtifact transaction wrap + lock-release semantics
|
|
6
|
+
* ========================================================================
|
|
7
|
+
*
|
|
8
|
+
* BSL 1.1. Copyright (c) Mindrian 2026.
|
|
9
|
+
*
|
|
10
|
+
* Closes CASCADE-04. Proves three independent invariants of the indexArtifact
|
|
11
|
+
* flow (lib/core/graph-ops.cjs -> lib/core/lazygraph-ops.cjs):
|
|
12
|
+
*
|
|
13
|
+
* 1. Happy path: filing a single artifact produces the expected Artifact
|
|
14
|
+
* and Section nodes, and the outer enqueueWrite lock is released on
|
|
15
|
+
* success (write.lock file absent after call).
|
|
16
|
+
*
|
|
17
|
+
* 2. Mid-transaction rollback (R-87-06-ROLLBACK): when an error is
|
|
18
|
+
* injected INSIDE the BEGIN/COMMIT boundary (after the first INSERT has
|
|
19
|
+
* fired but before COMMIT), SQLite must roll back the partial writes.
|
|
20
|
+
* We assert countAfter === countBefore on the Artifact node count;
|
|
21
|
+
* if the rollback did not fire, the first INSERT would persist and
|
|
22
|
+
* the assertion would fail.
|
|
23
|
+
*
|
|
24
|
+
* 3. Lock release after commit (testLockReleaseAfterCommit): a DIFFERENT
|
|
25
|
+
* failure mode -- the caller's fn inside enqueueWrite throws OUTSIDE
|
|
26
|
+
* the SQLite transaction (here: fs.readFileSync on a nonexistent
|
|
27
|
+
* path). The outer try/finally in enqueueWrite must still release the
|
|
28
|
+
* write-lock. This tests the lock-release semantic, not the txn
|
|
29
|
+
* rollback semantic; both matter, both are tested separately.
|
|
30
|
+
*
|
|
31
|
+
* 4. Rollback does not leak the lock (testRollbackDoesNotLeakLock): a
|
|
32
|
+
* throw INSIDE the transaction (same injection strategy as Test 2)
|
|
33
|
+
* must still release the enqueueWrite write-lock. This combines the
|
|
34
|
+
* two concerns: ROLLBACK happens AND the outer finally fires.
|
|
35
|
+
* Distinct from Test 3 because Test 3 throws BEFORE the txn even
|
|
36
|
+
* starts; this one throws WITH an active BEGIN/COMMIT block that
|
|
37
|
+
* must be rolled back.
|
|
38
|
+
*
|
|
39
|
+
* Why three failure tests (2, 3, 4 are distinct):
|
|
40
|
+
* - Test 2 exercises the BEGIN/COMMIT/ROLLBACK inside indexArtifact.
|
|
41
|
+
* - Test 3 exercises the acquireLock/releaseLock finally when no txn
|
|
42
|
+
* was ever opened.
|
|
43
|
+
* - Test 4 exercises BOTH: txn rolls back AND lock releases.
|
|
44
|
+
* Either one failing silently would leave a different kind of breakage in
|
|
45
|
+
* prod. Bundling them into one test would mask which guarantee regressed.
|
|
46
|
+
*
|
|
47
|
+
* Exit codes:
|
|
48
|
+
* 0 -- all tests passed
|
|
49
|
+
* 1 -- any test failed (real regression)
|
|
50
|
+
*
|
|
51
|
+
* Business Source License 1.1 -- see repository LICENSE.
|
|
52
|
+
*/
|
|
53
|
+
|
|
54
|
+
const assert = require('node:assert/strict');
|
|
55
|
+
const fs = require('node:fs');
|
|
56
|
+
const os = require('node:os');
|
|
57
|
+
const path = require('node:path');
|
|
58
|
+
const { DatabaseSync } = require('node:sqlite');
|
|
59
|
+
|
|
60
|
+
const lazygraph = require('../core/lazygraph-ops.cjs');
|
|
61
|
+
const graphOps = require('../core/graph-ops.cjs');
|
|
62
|
+
|
|
63
|
+
const FIXTURE = path.resolve(__dirname, '../../test/fixtures/cascade-e2e/seed-room');
|
|
64
|
+
|
|
65
|
+
// ----------------------------------------------------------------------------
|
|
66
|
+
// Test 1: Happy path -- indexArtifact via graph-ops wrapper (lock + txn OK)
|
|
67
|
+
// ----------------------------------------------------------------------------
|
|
68
|
+
|
|
69
|
+
async function testHappyPath(tmpRoom, dbPath, goodFile, mindrian) {
|
|
70
|
+
const res = await graphOps.indexArtifact(tmpRoom, goodFile);
|
|
71
|
+
assert.strictEqual(res.success, true, 'happy path must return success');
|
|
72
|
+
|
|
73
|
+
const db1 = new DatabaseSync(dbPath, { readOnly: true });
|
|
74
|
+
const nodeCount1 = db1.prepare("SELECT COUNT(*) as n FROM nodes WHERE type = 'Artifact'").get().n;
|
|
75
|
+
db1.close();
|
|
76
|
+
assert.ok(nodeCount1 >= 1, `happy path must insert at least one Artifact node (got ${nodeCount1})`);
|
|
77
|
+
|
|
78
|
+
// Write lock released after successful call (enqueueWrite finally)
|
|
79
|
+
const lockPath = path.join(mindrian, 'write.lock');
|
|
80
|
+
assert.strictEqual(fs.existsSync(lockPath), false, 'write lock must be released after happy path');
|
|
81
|
+
return nodeCount1;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// ----------------------------------------------------------------------------
|
|
85
|
+
// Test 2: Mid-transaction rollback (R-87-06-ROLLBACK)
|
|
86
|
+
// ----------------------------------------------------------------------------
|
|
87
|
+
//
|
|
88
|
+
// Injection strategy: patch conn.prepare so the FIRST prepare (BEGIN) returns
|
|
89
|
+
// the real stmt, the SECOND prepare (first INSERT) returns a stmt whose
|
|
90
|
+
// .run() throws. That places the throw AFTER BEGIN has fired but BEFORE any
|
|
91
|
+
// INSERT commits. With the BEGIN/COMMIT wrap in place, indexArtifact's catch
|
|
92
|
+
// issues ROLLBACK and the Artifact count stays identical to the pre-call
|
|
93
|
+
// value. Without the wrap, the first INSERT would persist and the assertion
|
|
94
|
+
// would fail. This is the concrete proof of rollback behavior.
|
|
95
|
+
//
|
|
96
|
+
// We call lazygraph.indexArtifact directly (not graphOps.indexArtifact) so
|
|
97
|
+
// we control the conn that is patched; graphOps opens its own conn inside
|
|
98
|
+
// enqueueWrite and we cannot intercept it at the lazygraph-body level.
|
|
99
|
+
|
|
100
|
+
async function testMidTransactionRollback(tmpRoom, dbPath) {
|
|
101
|
+
const db2 = new DatabaseSync(dbPath);
|
|
102
|
+
lazygraph.initSchema(db2); // idempotent
|
|
103
|
+
|
|
104
|
+
// Capture pre-call Artifact count
|
|
105
|
+
const countBefore = db2.prepare("SELECT COUNT(*) as n FROM nodes WHERE type = 'Artifact'").get().n;
|
|
106
|
+
|
|
107
|
+
// Patch: intercept conn.prepare so the 3rd prepare (the 2nd INSERT in the
|
|
108
|
+
// indexArtifact body, AFTER BEGIN and AFTER the first Artifact INSERT) gets
|
|
109
|
+
// a stmt whose .run() throws. This guarantees:
|
|
110
|
+
// prepare #1 -> 'BEGIN' -> real run() fires, txn starts
|
|
111
|
+
// prepare #2 -> INSERT Artifact node -> real run() fires, row written
|
|
112
|
+
// prepare #3 -> INSERT Section node -> stub run() throws mid-txn
|
|
113
|
+
//
|
|
114
|
+
// That placement matters: at least ONE INSERT has already hit the database
|
|
115
|
+
// inside the BEGIN block before the throw. If indexArtifact lacks the
|
|
116
|
+
// BEGIN/COMMIT wrap, that first INSERT auto-commits and countAfter would
|
|
117
|
+
// be countBefore + 1 (regression caught). With the wrap in place, the
|
|
118
|
+
// catch block issues ROLLBACK and undoes the first INSERT, so
|
|
119
|
+
// countAfter === countBefore. This is the ONLY injection point that
|
|
120
|
+
// proves rollback actually fired (vs. "the throw happened before any
|
|
121
|
+
// write, so there was nothing to roll back").
|
|
122
|
+
//
|
|
123
|
+
// runCount >= 2 is the canonical marker per plan: "throw after the 2nd
|
|
124
|
+
// stmt.run() invocation" -- our prepareCount === 3 means two real run()
|
|
125
|
+
// calls already succeeded (BEGIN + first INSERT).
|
|
126
|
+
const origPrepare = db2.prepare.bind(db2);
|
|
127
|
+
let prepareCount = 0;
|
|
128
|
+
db2.prepare = function (sql) {
|
|
129
|
+
prepareCount++;
|
|
130
|
+
const stmt = origPrepare(sql);
|
|
131
|
+
if (prepareCount === 3) {
|
|
132
|
+
stmt.run = function (..._args) {
|
|
133
|
+
// Restore prepare() BEFORE throwing so ROLLBACK (which also goes
|
|
134
|
+
// through db2.prepare) reaches the real implementation. Otherwise
|
|
135
|
+
// ROLLBACK would loop back into this stub.
|
|
136
|
+
db2.prepare = origPrepare;
|
|
137
|
+
throw new Error('injected mid-transaction failure at prepare #' + prepareCount + ' (runCount >= 2)');
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
return stmt;
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
// Try to index an artifact -- should throw due to injection
|
|
144
|
+
const anotherFile = path.join(tmpRoom, 'market-analysis', 's-curve-mature-market.md');
|
|
145
|
+
let threw = false;
|
|
146
|
+
let threwMsg = '';
|
|
147
|
+
try {
|
|
148
|
+
await lazygraph.indexArtifact(db2, tmpRoom, anotherFile);
|
|
149
|
+
} catch (e) {
|
|
150
|
+
threw = true;
|
|
151
|
+
threwMsg = e.message;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Safety: restore prepare in case the stub was never triggered
|
|
155
|
+
db2.prepare = origPrepare;
|
|
156
|
+
|
|
157
|
+
assert.ok(threw, 'injected failure must propagate to caller');
|
|
158
|
+
assert.ok(
|
|
159
|
+
threwMsg.includes('injected mid-transaction') || threwMsg.includes('runCount >= 2'),
|
|
160
|
+
`error message should carry injection marker, got: ${threwMsg}`
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
// The critical assertion: ROLLBACK reverted the partial write.
|
|
164
|
+
const countAfter = db2.prepare("SELECT COUNT(*) as n FROM nodes WHERE type = 'Artifact'").get().n;
|
|
165
|
+
assert.strictEqual(
|
|
166
|
+
countAfter,
|
|
167
|
+
countBefore,
|
|
168
|
+
`ROLLBACK FAILED: node count changed from ${countBefore} to ${countAfter} -- partial write survived`
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
db2.close();
|
|
172
|
+
return { countBefore, countAfter };
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// ----------------------------------------------------------------------------
|
|
176
|
+
// Test 3: testLockReleaseAfterCommit -- distinct failure mode, distinct name
|
|
177
|
+
// ----------------------------------------------------------------------------
|
|
178
|
+
//
|
|
179
|
+
// This test is INTENTIONALLY distinct from testMidTransactionRollback. It
|
|
180
|
+
// verifies that enqueueWrite's try/finally releases the lock even when the
|
|
181
|
+
// caller's fn throws OUTSIDE the SQLite transaction (here: fs.readFileSync
|
|
182
|
+
// fails on a nonexistent file, before any prepare() runs). That is a lock
|
|
183
|
+
// release semantic, not a transaction rollback semantic.
|
|
184
|
+
//
|
|
185
|
+
// Why the name: "after commit" refers to "after the transaction boundary
|
|
186
|
+
// is complete OR was never entered". Both paths exercise the same finally
|
|
187
|
+
// block in enqueueWrite. If a future refactor moves BEGIN before the
|
|
188
|
+
// fs.readFileSync (shouldn't happen, but defensive), this test still
|
|
189
|
+
// catches a lock leak because fs.readFileSync throwing before any INSERT
|
|
190
|
+
// would hit the ROLLBACK path and then the finally.
|
|
191
|
+
|
|
192
|
+
async function testLockReleaseAfterCommit(tmpRoom, mindrian) {
|
|
193
|
+
const lockPath = path.join(mindrian, 'write.lock');
|
|
194
|
+
let graphOpsThrewOnBadFile = false;
|
|
195
|
+
try {
|
|
196
|
+
await graphOps.indexArtifact(tmpRoom, path.join(tmpRoom, 'does-not-exist.md'));
|
|
197
|
+
} catch (_) {
|
|
198
|
+
graphOpsThrewOnBadFile = true;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
assert.ok(graphOpsThrewOnBadFile, 'bad file path must cause indexArtifact to throw');
|
|
202
|
+
assert.strictEqual(
|
|
203
|
+
fs.existsSync(lockPath),
|
|
204
|
+
false,
|
|
205
|
+
'write lock must be released even when indexArtifact throws (enqueueWrite finally)'
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// ----------------------------------------------------------------------------
|
|
210
|
+
// Test 4: testRollbackDoesNotLeakLock -- combined concern
|
|
211
|
+
// ----------------------------------------------------------------------------
|
|
212
|
+
//
|
|
213
|
+
// This test proves that BOTH the SQLite ROLLBACK AND the enqueueWrite
|
|
214
|
+
// finally fire when the inner transaction body throws. We go through the
|
|
215
|
+
// public graphOps.indexArtifact API so enqueueWrite is in the stack, and
|
|
216
|
+
// we monkey-patch lazygraph.indexArtifact so that the call opens its own
|
|
217
|
+
// BEGIN, issues one INSERT, then throws. The patched version includes its
|
|
218
|
+
// own ROLLBACK on catch -- same pattern as production indexArtifact --
|
|
219
|
+
// so we verify (a) the throw propagates out through enqueueWrite's fn
|
|
220
|
+
// callback, (b) enqueueWrite's finally still fires releaseLock, (c) the
|
|
221
|
+
// partial INSERT did not survive.
|
|
222
|
+
|
|
223
|
+
async function testRollbackDoesNotLeakLock(tmpRoom, dbPath, mindrian) {
|
|
224
|
+
const lockPath = path.join(mindrian, 'write.lock');
|
|
225
|
+
assert.strictEqual(fs.existsSync(lockPath), false, 'precondition: no lock before test');
|
|
226
|
+
|
|
227
|
+
// Capture pre-test Artifact count
|
|
228
|
+
const dbRead = new DatabaseSync(dbPath, { readOnly: true });
|
|
229
|
+
const countBefore = dbRead.prepare("SELECT COUNT(*) as n FROM nodes WHERE type = 'Artifact'").get().n;
|
|
230
|
+
dbRead.close();
|
|
231
|
+
|
|
232
|
+
// Save the real indexArtifact so we can restore after
|
|
233
|
+
const realIndex = lazygraph.indexArtifact;
|
|
234
|
+
|
|
235
|
+
// Replace with a version that simulates "threw inside the transaction"
|
|
236
|
+
// after one real INSERT fires. This mirrors the production flow: BEGIN,
|
|
237
|
+
// one INSERT, throw, ROLLBACK, throw-out. The caller (enqueueWrite) must
|
|
238
|
+
// still hit its finally.
|
|
239
|
+
lazygraph.indexArtifact = async function (conn, roomDir, _filePath) {
|
|
240
|
+
conn.prepare('BEGIN').run();
|
|
241
|
+
try {
|
|
242
|
+
conn.prepare(
|
|
243
|
+
"INSERT INTO nodes (id, type, properties) VALUES (?, ?, ?) ON CONFLICT(id) DO UPDATE SET properties = excluded.properties"
|
|
244
|
+
).run('t4-partial-artifact', 'Artifact', '{"title":"will-not-survive"}');
|
|
245
|
+
throw new Error('injected mid-transaction failure for testRollbackDoesNotLeakLock');
|
|
246
|
+
// unreachable:
|
|
247
|
+
// eslint-disable-next-line no-unreachable
|
|
248
|
+
conn.prepare('COMMIT').run();
|
|
249
|
+
} catch (err) {
|
|
250
|
+
try { conn.prepare('ROLLBACK').run(); } catch (_) {}
|
|
251
|
+
throw err;
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
let threw = false;
|
|
256
|
+
try {
|
|
257
|
+
await graphOps.indexArtifact(tmpRoom, path.join(tmpRoom, 'market-analysis', 's-curve-mature-market.md'));
|
|
258
|
+
} catch (_) {
|
|
259
|
+
threw = true;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// Restore
|
|
263
|
+
lazygraph.indexArtifact = realIndex;
|
|
264
|
+
|
|
265
|
+
assert.ok(threw, 'injected mid-transaction failure must propagate out of graphOps.indexArtifact');
|
|
266
|
+
|
|
267
|
+
// Lock released in enqueueWrite finally, even though the inner fn threw.
|
|
268
|
+
assert.strictEqual(
|
|
269
|
+
fs.existsSync(lockPath),
|
|
270
|
+
false,
|
|
271
|
+
'write lock MUST be released even when the inner transaction rolled back'
|
|
272
|
+
);
|
|
273
|
+
|
|
274
|
+
// Partial INSERT did not survive (ROLLBACK fired correctly).
|
|
275
|
+
const dbRead2 = new DatabaseSync(dbPath, { readOnly: true });
|
|
276
|
+
const countAfter = dbRead2.prepare("SELECT COUNT(*) as n FROM nodes WHERE type = 'Artifact'").get().n;
|
|
277
|
+
dbRead2.close();
|
|
278
|
+
assert.strictEqual(
|
|
279
|
+
countAfter,
|
|
280
|
+
countBefore,
|
|
281
|
+
`ROLLBACK FAILED in testRollbackDoesNotLeakLock: ${countBefore} -> ${countAfter}`
|
|
282
|
+
);
|
|
283
|
+
|
|
284
|
+
return { countBefore, countAfter };
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// ----------------------------------------------------------------------------
|
|
288
|
+
// Test runner
|
|
289
|
+
// ----------------------------------------------------------------------------
|
|
290
|
+
|
|
291
|
+
async function run() {
|
|
292
|
+
const tmpRoom = fs.mkdtempSync(path.join(os.tmpdir(), 'indexart-'));
|
|
293
|
+
try {
|
|
294
|
+
fs.cpSync(FIXTURE, tmpRoom, { recursive: true });
|
|
295
|
+
const mindrian = path.join(tmpRoom, '.mindrian');
|
|
296
|
+
fs.mkdirSync(mindrian, { recursive: true });
|
|
297
|
+
|
|
298
|
+
const dbPath = path.join(mindrian, 'room.db');
|
|
299
|
+
const goodFile = path.join(tmpRoom, 'problem-definition', 'jtbd-underservice.md');
|
|
300
|
+
|
|
301
|
+
// Test 1: happy path
|
|
302
|
+
const nodeCount1 = await testHappyPath(tmpRoom, dbPath, goodFile, mindrian);
|
|
303
|
+
|
|
304
|
+
// Test 2: REAL mid-transaction rollback
|
|
305
|
+
const rollback = await testMidTransactionRollback(tmpRoom, dbPath);
|
|
306
|
+
|
|
307
|
+
// Test 3: lock release after commit (distinct concern)
|
|
308
|
+
await testLockReleaseAfterCommit(tmpRoom, mindrian);
|
|
309
|
+
|
|
310
|
+
// Test 4: combined -- rollback inside txn AND lock released
|
|
311
|
+
const t4 = await testRollbackDoesNotLeakLock(tmpRoom, dbPath, mindrian);
|
|
312
|
+
|
|
313
|
+
process.stdout.write(
|
|
314
|
+
`index-artifact-transaction: all tests passed` +
|
|
315
|
+
` (happy-path nodes=${nodeCount1}, rollback-countBefore=${rollback.countBefore},` +
|
|
316
|
+
` rollback-countAfter=${rollback.countAfter},` +
|
|
317
|
+
` t4-lock-released-after-rollback=${t4.countBefore}==${t4.countAfter})\n`
|
|
318
|
+
);
|
|
319
|
+
process.exit(0);
|
|
320
|
+
} catch (e) {
|
|
321
|
+
process.stderr.write('FAIL: ' + e.message + '\n');
|
|
322
|
+
if (e.stack) process.stderr.write(e.stack + '\n');
|
|
323
|
+
process.exit(1);
|
|
324
|
+
} finally {
|
|
325
|
+
try {
|
|
326
|
+
fs.rmSync(tmpRoom, { recursive: true, force: true });
|
|
327
|
+
} catch (_) {
|
|
328
|
+
/* ignore */
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
run();
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/*
|
|
5
|
+
* Copyright (c) 2026 Mindrian. BSL 1.1.
|
|
6
|
+
*
|
|
7
|
+
* Regression test for the rs_discoveries SQL view (graph-on-graph P0 cont., 2026-05-11).
|
|
8
|
+
* =====================================================================================
|
|
9
|
+
* The RS SQLite mirror (rs-sqlite-mirror.cjs) writes RSDiscovery records into
|
|
10
|
+
* the `nodes` table with the payload in a JSON `properties` bag. The RS NL/SQL
|
|
11
|
+
* readers (rs-nl-to-query.cjs SQL templates, scripts/rs-thesis-command.cjs)
|
|
12
|
+
* query `FROM rs_discoveries` -- a table that did not exist, so queryGraph
|
|
13
|
+
* swallowed the "no such table" error as []. lazygraph-ops.cjs initSchema now
|
|
14
|
+
* creates a `rs_discoveries` VIEW over `nodes WHERE type = 'RSDiscovery'` that
|
|
15
|
+
* json_extract's the payload keys into the columns the readers expect, renaming
|
|
16
|
+
* the writer's `room_id` -> reader's `room_slug` and `classification` -> `rs_type`.
|
|
17
|
+
*
|
|
18
|
+
* This test:
|
|
19
|
+
* - opens a throwaway room.db via openGraph
|
|
20
|
+
* - inserts two RSDiscovery nodes directly into `nodes` (one fintech, one biotech)
|
|
21
|
+
* - queries `SELECT * FROM rs_discoveries WHERE room_slug = ?` with a bound param
|
|
22
|
+
* -> asserts the WHERE filter works AND thesis/rs_type/breakthrough_score/room_slug
|
|
23
|
+
* come back populated
|
|
24
|
+
* - queries the rs-thesis-shaped read `SELECT id, thesis, rs_type, breakthrough_score,
|
|
25
|
+
* room_slug, created_at FROM rs_discoveries WHERE id = ? LIMIT 1`
|
|
26
|
+
*
|
|
27
|
+
* Self-contained: no live Brain, no live Aura. Pure CJS, node built-ins only
|
|
28
|
+
* (assert + os + fs + path).
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
const assert = require('node:assert/strict');
|
|
32
|
+
const os = require('os');
|
|
33
|
+
const fs = require('fs');
|
|
34
|
+
const path = require('path');
|
|
35
|
+
|
|
36
|
+
const lg = require('../core/lazygraph-ops.cjs');
|
|
37
|
+
|
|
38
|
+
let passed = 0;
|
|
39
|
+
let failed = 0;
|
|
40
|
+
const failures = [];
|
|
41
|
+
|
|
42
|
+
(async function main() {
|
|
43
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'rsv-'));
|
|
44
|
+
let db;
|
|
45
|
+
try {
|
|
46
|
+
const opened = await lg.openGraph(tmpDir);
|
|
47
|
+
db = opened.db;
|
|
48
|
+
const conn = opened.conn;
|
|
49
|
+
|
|
50
|
+
// Insert two RSDiscovery nodes directly into `nodes` (mirrors what
|
|
51
|
+
// rs-sqlite-mirror.cjs writes: type='RSDiscovery', properties=JSON bag).
|
|
52
|
+
conn.prepare('INSERT INTO nodes (id, type, properties) VALUES (?, ?, ?)').run(
|
|
53
|
+
'd1', 'RSDiscovery', JSON.stringify({
|
|
54
|
+
thesis: 'fraud-graph mapping',
|
|
55
|
+
classification: 'structural_transfer',
|
|
56
|
+
breakthrough_score: 8,
|
|
57
|
+
room_id: 'fintech',
|
|
58
|
+
created_at: '2026-01-02T00:00:00Z',
|
|
59
|
+
bridge_concept: 'graph similarity',
|
|
60
|
+
dominant_dimension: 'magnitude',
|
|
61
|
+
diff: 0.2,
|
|
62
|
+
lsa: 0.7,
|
|
63
|
+
bert: 0.65,
|
|
64
|
+
domain: 'fintech',
|
|
65
|
+
})
|
|
66
|
+
);
|
|
67
|
+
conn.prepare('INSERT INTO nodes (id, type, properties) VALUES (?, ?, ?)').run(
|
|
68
|
+
'd2', 'RSDiscovery', JSON.stringify({
|
|
69
|
+
thesis: 'CRISPR delivery analogue',
|
|
70
|
+
classification: 'semantic_implementation',
|
|
71
|
+
breakthrough_score: 6,
|
|
72
|
+
room_id: 'biotech',
|
|
73
|
+
created_at: '2026-01-01T00:00:00Z',
|
|
74
|
+
bridge_concept: 'vector packaging',
|
|
75
|
+
dominant_dimension: 'feasibility',
|
|
76
|
+
diff: 0.1,
|
|
77
|
+
lsa: 0.5,
|
|
78
|
+
bert: 0.55,
|
|
79
|
+
domain: 'biotech',
|
|
80
|
+
})
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
// (1) rs-nl-to-query-shaped read with a bound room_slug param.
|
|
84
|
+
const rows = await lg.queryGraph(
|
|
85
|
+
conn,
|
|
86
|
+
'SELECT * FROM rs_discoveries WHERE room_slug = ? ORDER BY created_at DESC',
|
|
87
|
+
['fintech']
|
|
88
|
+
);
|
|
89
|
+
assert.strictEqual(rows.length, 1, 'WHERE room_slug = ? must return exactly the fintech row');
|
|
90
|
+
assert.strictEqual(rows[0].thesis, 'fraud-graph mapping', 'thesis column populated from $.thesis');
|
|
91
|
+
assert.strictEqual(rows[0].rs_type, 'structural_transfer', 'rs_type column mapped from $.classification');
|
|
92
|
+
assert.strictEqual(Number(rows[0].breakthrough_score), 8, 'breakthrough_score column populated');
|
|
93
|
+
assert.strictEqual(rows[0].room_slug, 'fintech', 'room_slug column mapped from $.room_id');
|
|
94
|
+
|
|
95
|
+
// (2) rs-thesis-command-shaped read by id.
|
|
96
|
+
const t = await lg.queryGraph(
|
|
97
|
+
conn,
|
|
98
|
+
'SELECT id, thesis, rs_type, breakthrough_score, room_slug, created_at FROM rs_discoveries WHERE id = ? LIMIT 1',
|
|
99
|
+
['d1']
|
|
100
|
+
);
|
|
101
|
+
assert.strictEqual(t.length, 1, 'WHERE id = ? must return exactly one row');
|
|
102
|
+
assert.strictEqual(t[0].id, 'd1', 'id column passthrough');
|
|
103
|
+
assert.strictEqual(t[0].thesis, 'fraud-graph mapping', 'thesis column populated in id-shaped read');
|
|
104
|
+
assert.strictEqual(t[0].rs_type, 'structural_transfer', 'rs_type column populated in id-shaped read');
|
|
105
|
+
|
|
106
|
+
passed = 2;
|
|
107
|
+
} catch (err) {
|
|
108
|
+
failed = 1;
|
|
109
|
+
failures.push(err && err.message ? err.message : String(err));
|
|
110
|
+
} finally {
|
|
111
|
+
try { if (db) await lg.closeGraph(db); } catch (_e) { /* ignore */ }
|
|
112
|
+
try { fs.rmSync(tmpDir, { recursive: true, force: true }); } catch (_e) { /* ignore */ }
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (failed > 0) {
|
|
116
|
+
process.stderr.write('lazygraph-rs-discoveries-view: FAIL\n');
|
|
117
|
+
for (const f of failures) process.stderr.write(' - ' + f + '\n');
|
|
118
|
+
process.exit(1);
|
|
119
|
+
}
|
|
120
|
+
process.stdout.write('lazygraph-rs-discoveries-view: all assertions passed (bound-param room_slug read + id-shaped read over the view)\n');
|
|
121
|
+
process.exit(0);
|
|
122
|
+
})();
|