@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,304 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2026 Mindrian. BSL 1.1.
|
|
3
|
+
*
|
|
4
|
+
* Phase 88-04 Task 1 -- stamp-artifact-write tests
|
|
5
|
+
* =================================================
|
|
6
|
+
* Covers the 5 behavior cases:
|
|
7
|
+
* 1. MINTO.md exists -> stamp updates last_artifact_write_seen_at to current ISO;
|
|
8
|
+
* all other frontmatter keys untouched.
|
|
9
|
+
* 2. MINTO.md absent -> stamp writes to .mindrian/pending-stamps/<section>.json
|
|
10
|
+
* with {section, last_artifact_write_seen_at}.
|
|
11
|
+
* 3. Narrative body preserved byte-for-byte across stamp.
|
|
12
|
+
* 4. Concurrent stamp writes (2 forks) -> final MINTO has ONE timestamp, no corruption.
|
|
13
|
+
* 5. Malformed MINTO frontmatter -> stamp writes to pending-stamps instead, logs
|
|
14
|
+
* warning to stderr; no throw; exit 0.
|
|
15
|
+
*
|
|
16
|
+
* Test harness mirrors the pattern in lib/memory/minto-debouncer.test.cjs +
|
|
17
|
+
* lib/memory/recompile-room-references.test.cjs: synchronous runner, mkTmp
|
|
18
|
+
* helper per test, cleanup via process.on('exit').
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
'use strict';
|
|
22
|
+
|
|
23
|
+
const assert = require('node:assert');
|
|
24
|
+
const fs = require('node:fs');
|
|
25
|
+
const path = require('node:path');
|
|
26
|
+
const os = require('node:os');
|
|
27
|
+
const { fork, spawnSync } = require('node:child_process');
|
|
28
|
+
|
|
29
|
+
const REPO_ROOT = path.resolve(__dirname, '..', '..');
|
|
30
|
+
const STAMP_CLI = path.join(REPO_ROOT, 'scripts', 'stamp-artifact-write.cjs');
|
|
31
|
+
|
|
32
|
+
// --- tmp dir management -----------------------------------------------------
|
|
33
|
+
|
|
34
|
+
const createdTmpDirs = [];
|
|
35
|
+
function mkTmp(prefix) {
|
|
36
|
+
const d = fs.mkdtempSync(path.join(os.tmpdir(), prefix));
|
|
37
|
+
createdTmpDirs.push(d);
|
|
38
|
+
return d;
|
|
39
|
+
}
|
|
40
|
+
process.on('exit', () => {
|
|
41
|
+
for (const d of createdTmpDirs) {
|
|
42
|
+
try { fs.rmSync(d, { recursive: true, force: true }); } catch (_) {}
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// --- helpers ----------------------------------------------------------------
|
|
47
|
+
|
|
48
|
+
function seedRoomAndSection(tmp, sectionName) {
|
|
49
|
+
// .room-root sentinel at tmp; section is a sibling folder.
|
|
50
|
+
fs.writeFileSync(path.join(tmp, '.room-root'), '');
|
|
51
|
+
fs.mkdirSync(path.join(tmp, '.mindrian'), { recursive: true });
|
|
52
|
+
const sectionDir = path.join(tmp, sectionName);
|
|
53
|
+
fs.mkdirSync(sectionDir, { recursive: true });
|
|
54
|
+
return sectionDir;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function writeMintoMd(sectionDir, frontmatterLines, bodyLines) {
|
|
58
|
+
const content =
|
|
59
|
+
['---', ...frontmatterLines, '---', '', ...bodyLines, ''].join('\n');
|
|
60
|
+
fs.writeFileSync(path.join(sectionDir, 'MINTO.md'), content);
|
|
61
|
+
return content;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function runStampCli(sectionDir, extraEnv) {
|
|
65
|
+
return spawnSync(
|
|
66
|
+
process.execPath,
|
|
67
|
+
[STAMP_CLI, sectionDir],
|
|
68
|
+
{
|
|
69
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
70
|
+
env: Object.assign({}, process.env, extraEnv || {}),
|
|
71
|
+
}
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// --- test runner ------------------------------------------------------------
|
|
76
|
+
|
|
77
|
+
const tests = [];
|
|
78
|
+
function test(name, fn) { tests.push({ name, fn }); }
|
|
79
|
+
|
|
80
|
+
// ---------- Test 1: happy path, updates only last_artifact_write_seen_at ----
|
|
81
|
+
test('Test 1: MINTO.md present -> last_artifact_write_seen_at stamped', async () => {
|
|
82
|
+
const tmp = mkTmp('stamp-t1-');
|
|
83
|
+
const sec = seedRoomAndSection(tmp, 'market-analysis');
|
|
84
|
+
const fm = [
|
|
85
|
+
'schema_version: "1.0"',
|
|
86
|
+
'type: section-minto',
|
|
87
|
+
'section: market-analysis',
|
|
88
|
+
'governing_thought: "Market analysis anchors the venture thesis."',
|
|
89
|
+
'last_generated_at: "2026-01-01T00:00:00Z"',
|
|
90
|
+
'last_artifact_write_seen_at: null',
|
|
91
|
+
'reasoning_health_score: null',
|
|
92
|
+
'flagged_weaknesses: []',
|
|
93
|
+
'decision_log: []',
|
|
94
|
+
];
|
|
95
|
+
const body = ['# Market Analysis -- Minto Reasoning', '', 'Body paragraph.'];
|
|
96
|
+
const before = writeMintoMd(sec, fm, body);
|
|
97
|
+
|
|
98
|
+
const r = runStampCli(sec);
|
|
99
|
+
assert.strictEqual(r.status, 0, 'stamp CLI must exit 0');
|
|
100
|
+
|
|
101
|
+
const after = fs.readFileSync(path.join(sec, 'MINTO.md'), 'utf8');
|
|
102
|
+
// last_artifact_write_seen_at now carries an ISO timestamp.
|
|
103
|
+
const mm = after.match(
|
|
104
|
+
/^last_artifact_write_seen_at:\s*"(20\d{2}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z)"\s*$/m
|
|
105
|
+
);
|
|
106
|
+
assert.ok(mm, 'last_artifact_write_seen_at must be ISO-stamped (got: ' + after + ')');
|
|
107
|
+
|
|
108
|
+
// All other keys unchanged.
|
|
109
|
+
assert.ok(/^schema_version: "1\.0"$/m.test(after), 'schema_version preserved');
|
|
110
|
+
assert.ok(/^type: section-minto$/m.test(after), 'type preserved');
|
|
111
|
+
assert.ok(/^section: market-analysis$/m.test(after), 'section preserved');
|
|
112
|
+
assert.ok(
|
|
113
|
+
/^governing_thought: "Market analysis anchors the venture thesis\."$/m.test(after),
|
|
114
|
+
'governing_thought preserved'
|
|
115
|
+
);
|
|
116
|
+
assert.ok(
|
|
117
|
+
/^last_generated_at: "2026-01-01T00:00:00Z"$/m.test(after),
|
|
118
|
+
'last_generated_at preserved'
|
|
119
|
+
);
|
|
120
|
+
assert.ok(/^reasoning_health_score: null$/m.test(after), 'reasoning_health_score preserved');
|
|
121
|
+
assert.ok(/^flagged_weaknesses: \[\]$/m.test(after), 'flagged_weaknesses preserved');
|
|
122
|
+
assert.ok(/^decision_log: \[\]$/m.test(after), 'decision_log preserved');
|
|
123
|
+
|
|
124
|
+
// Body preserved.
|
|
125
|
+
assert.ok(after.includes('# Market Analysis -- Minto Reasoning'), 'body H1 preserved');
|
|
126
|
+
assert.ok(after.includes('Body paragraph.'), 'body paragraph preserved');
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
// ---------- Test 2: MINTO absent -> pending-stamps fallback ----------------
|
|
130
|
+
test('Test 2: MINTO.md absent -> pending-stamps fallback', async () => {
|
|
131
|
+
const tmp = mkTmp('stamp-t2-');
|
|
132
|
+
const sec = seedRoomAndSection(tmp, 'problem-definition');
|
|
133
|
+
|
|
134
|
+
const r = runStampCli(sec);
|
|
135
|
+
assert.strictEqual(r.status, 0, 'stamp CLI must exit 0 even when MINTO absent');
|
|
136
|
+
|
|
137
|
+
const pendingDir = path.join(tmp, '.mindrian', 'pending-stamps');
|
|
138
|
+
assert.ok(fs.existsSync(pendingDir), 'pending-stamps dir created');
|
|
139
|
+
const pendingFile = path.join(pendingDir, 'problem-definition.json');
|
|
140
|
+
assert.ok(fs.existsSync(pendingFile), 'pending stamp JSON written for section');
|
|
141
|
+
|
|
142
|
+
const payload = JSON.parse(fs.readFileSync(pendingFile, 'utf8'));
|
|
143
|
+
assert.strictEqual(payload.section, 'problem-definition');
|
|
144
|
+
assert.ok(
|
|
145
|
+
/^20\d{2}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/.test(payload.last_artifact_write_seen_at),
|
|
146
|
+
'pending stamp carries ISO timestamp'
|
|
147
|
+
);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
// ---------- Test 3: narrative body preserved byte-for-byte -----------------
|
|
151
|
+
test('Test 3: narrative body preserved byte-for-byte after stamp', async () => {
|
|
152
|
+
const tmp = mkTmp('stamp-t3-');
|
|
153
|
+
const sec = seedRoomAndSection(tmp, 'solution-design');
|
|
154
|
+
const fm = [
|
|
155
|
+
'schema_version: "1.0"',
|
|
156
|
+
'type: section-minto',
|
|
157
|
+
'section: solution-design',
|
|
158
|
+
'governing_thought: "Solution design is the synthesis of prior analysis."',
|
|
159
|
+
'last_generated_at: "2026-02-01T00:00:00Z"',
|
|
160
|
+
'last_artifact_write_seen_at: null',
|
|
161
|
+
'reasoning_health_score: 0.42',
|
|
162
|
+
'flagged_weaknesses: []',
|
|
163
|
+
'decision_log: []',
|
|
164
|
+
];
|
|
165
|
+
// Body with multiple lines, wikilinks, special chars.
|
|
166
|
+
const body = [
|
|
167
|
+
'# Solution Design -- Minto Reasoning',
|
|
168
|
+
'',
|
|
169
|
+
'> [!abstract] Governing Thought',
|
|
170
|
+
'> Solution design is the synthesis of prior analysis.',
|
|
171
|
+
'',
|
|
172
|
+
'## Argument Structure',
|
|
173
|
+
'',
|
|
174
|
+
'### Claim 1: Architecture',
|
|
175
|
+
'',
|
|
176
|
+
'See [[../problem-definition/MINTO.md|Problem]]',
|
|
177
|
+
'',
|
|
178
|
+
'### Claim 2: Constraints',
|
|
179
|
+
'',
|
|
180
|
+
'Unicode safe: citations (Smith 2024) -> key-results.',
|
|
181
|
+
'',
|
|
182
|
+
'---',
|
|
183
|
+
'',
|
|
184
|
+
];
|
|
185
|
+
writeMintoMd(sec, fm, body);
|
|
186
|
+
const before = fs.readFileSync(path.join(sec, 'MINTO.md'), 'utf8');
|
|
187
|
+
|
|
188
|
+
const r = runStampCli(sec);
|
|
189
|
+
assert.strictEqual(r.status, 0, 'stamp CLI must exit 0');
|
|
190
|
+
|
|
191
|
+
const after = fs.readFileSync(path.join(sec, 'MINTO.md'), 'utf8');
|
|
192
|
+
|
|
193
|
+
// Extract the body regions (everything after closing `---`) and diff them.
|
|
194
|
+
function bodyOf(content) {
|
|
195
|
+
const m = content.match(/^---\r?\n[\s\S]*?\r?\n---\r?\n([\s\S]*)$/);
|
|
196
|
+
return m ? m[1] : content;
|
|
197
|
+
}
|
|
198
|
+
const beforeBody = bodyOf(before);
|
|
199
|
+
const afterBody = bodyOf(after);
|
|
200
|
+
assert.strictEqual(
|
|
201
|
+
afterBody, beforeBody,
|
|
202
|
+
'body region must be byte-identical after stamp'
|
|
203
|
+
);
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
// ---------- Test 4: concurrent stamp writes serialize, no corruption -------
|
|
207
|
+
test('Test 4: 2 concurrent stamp forks -> one ISO, no corruption', async () => {
|
|
208
|
+
const tmp = mkTmp('stamp-t4-');
|
|
209
|
+
const sec = seedRoomAndSection(tmp, 'business-model');
|
|
210
|
+
const fm = [
|
|
211
|
+
'schema_version: "1.0"',
|
|
212
|
+
'type: section-minto',
|
|
213
|
+
'section: business-model',
|
|
214
|
+
'governing_thought: "Business model drives monetization pathways."',
|
|
215
|
+
'last_generated_at: "2026-03-01T00:00:00Z"',
|
|
216
|
+
'last_artifact_write_seen_at: null',
|
|
217
|
+
'reasoning_health_score: null',
|
|
218
|
+
'flagged_weaknesses: []',
|
|
219
|
+
'decision_log: []',
|
|
220
|
+
];
|
|
221
|
+
writeMintoMd(sec, fm, ['# Business Model -- Minto', '', 'Body.']);
|
|
222
|
+
|
|
223
|
+
// Fork two concurrent stamp CLIs.
|
|
224
|
+
const children = [
|
|
225
|
+
fork(STAMP_CLI, [sec], { silent: true }),
|
|
226
|
+
fork(STAMP_CLI, [sec], { silent: true }),
|
|
227
|
+
];
|
|
228
|
+
const results = await Promise.all(children.map((c) => new Promise((resolve) => {
|
|
229
|
+
c.on('exit', (code) => resolve(code));
|
|
230
|
+
})));
|
|
231
|
+
// Both should exit 0 (soft-fail guarantee; worst case one bails on lock).
|
|
232
|
+
for (const code of results) {
|
|
233
|
+
assert.strictEqual(code, 0, 'every concurrent stamp exits 0');
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// MINTO.md still well-formed: frontmatter parses, body intact.
|
|
237
|
+
const after = fs.readFileSync(path.join(sec, 'MINTO.md'), 'utf8');
|
|
238
|
+
assert.ok(
|
|
239
|
+
/^---\r?\n[\s\S]*?\r?\n---/.test(after),
|
|
240
|
+
'MINTO.md frontmatter structure preserved'
|
|
241
|
+
);
|
|
242
|
+
const matches = after.match(/^last_artifact_write_seen_at:\s*.*$/gm);
|
|
243
|
+
assert.ok(matches && matches.length === 1,
|
|
244
|
+
'exactly one last_artifact_write_seen_at line (no duplication)');
|
|
245
|
+
assert.ok(
|
|
246
|
+
/last_artifact_write_seen_at:\s*"20\d{2}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z"/.test(after),
|
|
247
|
+
'final stamp has valid ISO timestamp'
|
|
248
|
+
);
|
|
249
|
+
assert.ok(after.includes('# Business Model -- Minto'), 'body preserved after race');
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
// ---------- Test 5: malformed frontmatter -> pending-stamps fallback ------
|
|
253
|
+
test('Test 5: malformed MINTO frontmatter -> pending-stamps + stderr warn', async () => {
|
|
254
|
+
const tmp = mkTmp('stamp-t5-');
|
|
255
|
+
const sec = seedRoomAndSection(tmp, 'team');
|
|
256
|
+
// Write a file called MINTO.md but missing the closing --- delimiter.
|
|
257
|
+
fs.writeFileSync(
|
|
258
|
+
path.join(sec, 'MINTO.md'),
|
|
259
|
+
'---\nschema_version: "1.0"\ntype: section-minto\n# NO CLOSING DELIMITER\nbody text'
|
|
260
|
+
);
|
|
261
|
+
|
|
262
|
+
const r = runStampCli(sec);
|
|
263
|
+
assert.strictEqual(r.status, 0, 'stamp CLI must exit 0 even on malformed MINTO');
|
|
264
|
+
|
|
265
|
+
const pendingDir = path.join(tmp, '.mindrian', 'pending-stamps');
|
|
266
|
+
assert.ok(fs.existsSync(pendingDir), 'pending-stamps dir created as fallback');
|
|
267
|
+
const pendingFile = path.join(pendingDir, 'team.json');
|
|
268
|
+
assert.ok(fs.existsSync(pendingFile), 'pending stamp written as fallback');
|
|
269
|
+
|
|
270
|
+
// Stderr should carry a warning but must not throw.
|
|
271
|
+
const stderr = r.stderr ? r.stderr.toString() : '';
|
|
272
|
+
// Warning is expected but we stay permissive: at minimum, no uncaught exception.
|
|
273
|
+
assert.ok(
|
|
274
|
+
!/UnhandledPromiseRejection|Error:\s+ENOENT/i.test(stderr) ||
|
|
275
|
+
/pending-stamps|malformed|frontmatter/i.test(stderr),
|
|
276
|
+
'stderr does not crash; malformed signal acceptable'
|
|
277
|
+
);
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
// --- CLI smoke: non-existent section path -> still exits 0 -----------------
|
|
281
|
+
test('Test 6 (acceptance): non-existent section path -> exit 0 (soft-fail)', async () => {
|
|
282
|
+
const r = runStampCli('/does/not/exist/anywhere/section');
|
|
283
|
+
assert.strictEqual(r.status, 0, 'stamp on missing dir must still exit 0');
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
// --- runner ----------------------------------------------------------------
|
|
287
|
+
|
|
288
|
+
(async () => {
|
|
289
|
+
let failed = 0;
|
|
290
|
+
for (const t of tests) {
|
|
291
|
+
try {
|
|
292
|
+
await t.fn();
|
|
293
|
+
process.stdout.write('PASS ' + t.name + '\n');
|
|
294
|
+
} catch (e) {
|
|
295
|
+
failed += 1;
|
|
296
|
+
process.stderr.write('FAIL ' + t.name + '\n' + (e && e.stack || e) + '\n');
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
process.stdout.write(
|
|
300
|
+
'\nstamp-artifact-write.test.cjs: ' +
|
|
301
|
+
(tests.length - failed) + '/' + tests.length + ' passed\n'
|
|
302
|
+
);
|
|
303
|
+
process.exit(failed === 0 ? 0 : 1);
|
|
304
|
+
})();
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/*
|
|
5
|
+
* Copyright (c) 2026 Mindrian. BSL 1.1.
|
|
6
|
+
*
|
|
7
|
+
* Phase 94-01 -- statusline active room read contract acceptance tests.
|
|
8
|
+
* (Business Source License 1.1; SPDX BUSL-1.1; see LICENSE.)
|
|
9
|
+
*
|
|
10
|
+
* Verifies the canonical read path for the statusline's active-room name:
|
|
11
|
+
*
|
|
12
|
+
* STATE.md frontmatter current_room
|
|
13
|
+
* -> lib/core/folder-memory.cjs getCurrentRoom()
|
|
14
|
+
* -> scripts/context-monitor render
|
|
15
|
+
*
|
|
16
|
+
* Lawrence Aronhime reproducer: in his 2026-04-28 38-minute live test he
|
|
17
|
+
* said "look at the bottom. It still says core power" four times. Root
|
|
18
|
+
* cause was the statusline deriving the room name from a stale source
|
|
19
|
+
* (cwd or its own cache) instead of STATE.md. This test fixture proves
|
|
20
|
+
* the new canonical contract: switch rooms in fixture STATE.md, the very
|
|
21
|
+
* next getCurrentRoom() call returns the new slug. No caching across
|
|
22
|
+
* calls, no exceptions on every failure mode.
|
|
23
|
+
*
|
|
24
|
+
* Test map (8 cases, one-to-one with the PLAN <behavior> block):
|
|
25
|
+
* 1. getCurrentRoom() returns null when STATE.md missing in canonical path
|
|
26
|
+
* 2. getCurrentRoom() returns null when STATE.md exists but lacks frontmatter
|
|
27
|
+
* 3. getCurrentRoom() returns null when frontmatter exists but current_room absent
|
|
28
|
+
* 4. getCurrentRoom() returns {slug, path, source} on a happy frontmatter
|
|
29
|
+
* 5. getCurrentRoom() returns null when YAML frontmatter is malformed
|
|
30
|
+
* 6. Lawrence reproducer: switch room slug, next call reflects within one cycle
|
|
31
|
+
* 7. getCurrentRoom() ignores quotes and trailing whitespace around slug
|
|
32
|
+
* 8. End-to-end: spawn scripts/context-monitor with fixture STATE.md, stdout
|
|
33
|
+
* contains the new slug
|
|
34
|
+
*
|
|
35
|
+
* Registered in lib/memory/run-feynman-tests.cjs.
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
const assert = require('node:assert/strict');
|
|
39
|
+
const fs = require('node:fs');
|
|
40
|
+
const os = require('node:os');
|
|
41
|
+
const path = require('node:path');
|
|
42
|
+
const { execFileSync } = require('node:child_process');
|
|
43
|
+
|
|
44
|
+
const REPO = path.resolve(__dirname, '..', '..');
|
|
45
|
+
const SYNC_PATH = path.join(REPO, 'lib/core/folder-memory.cjs');
|
|
46
|
+
const CONTEXT_MONITOR = path.join(REPO, 'scripts/context-monitor');
|
|
47
|
+
|
|
48
|
+
// ---------- Fixture helpers ----------
|
|
49
|
+
|
|
50
|
+
const TMP_ROOTS = [];
|
|
51
|
+
function mkTmp(prefix) {
|
|
52
|
+
const d = fs.mkdtempSync(path.join(os.tmpdir(), prefix));
|
|
53
|
+
TMP_ROOTS.push(d);
|
|
54
|
+
return d;
|
|
55
|
+
}
|
|
56
|
+
process.on('exit', () => {
|
|
57
|
+
for (const d of TMP_ROOTS) {
|
|
58
|
+
try {
|
|
59
|
+
fs.rmSync(d, { recursive: true, force: true });
|
|
60
|
+
} catch (_e) { /* best effort */ }
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
function writeStateMdWithFrontmatter(dir, frontmatterLines, body) {
|
|
65
|
+
const lines = ['---'];
|
|
66
|
+
for (const fl of frontmatterLines) lines.push(fl);
|
|
67
|
+
lines.push('---');
|
|
68
|
+
lines.push('');
|
|
69
|
+
lines.push(body || '# Room State');
|
|
70
|
+
fs.writeFileSync(path.join(dir, 'STATE.md'), lines.join('\n'), 'utf8');
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function writeRoomFixture(roomDir, currentRoomValue) {
|
|
74
|
+
fs.mkdirSync(roomDir, { recursive: true });
|
|
75
|
+
const frontmatter = [
|
|
76
|
+
'venture_stage: Pre-Opportunity',
|
|
77
|
+
'last_updated: 2026-04-28',
|
|
78
|
+
];
|
|
79
|
+
if (currentRoomValue !== undefined) {
|
|
80
|
+
frontmatter.push('current_room: ' + currentRoomValue);
|
|
81
|
+
}
|
|
82
|
+
writeStateMdWithFrontmatter(roomDir, frontmatter, '# Room State');
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function writeRegistry(workDir, activeSlug, roomDirAbs) {
|
|
86
|
+
const dotRooms = path.join(workDir, '.rooms');
|
|
87
|
+
fs.mkdirSync(dotRooms, { recursive: true });
|
|
88
|
+
const registry = {
|
|
89
|
+
active: activeSlug,
|
|
90
|
+
rooms: {},
|
|
91
|
+
};
|
|
92
|
+
registry.rooms[activeSlug] = {
|
|
93
|
+
name: activeSlug,
|
|
94
|
+
path: path.relative(workDir, roomDirAbs) || '.',
|
|
95
|
+
};
|
|
96
|
+
fs.writeFileSync(
|
|
97
|
+
path.join(dotRooms, 'registry.json'),
|
|
98
|
+
JSON.stringify(registry, null, 2),
|
|
99
|
+
'utf8'
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// ---------- Module pre-condition ----------
|
|
104
|
+
|
|
105
|
+
function t0_moduleFileExists() {
|
|
106
|
+
assert.ok(fs.existsSync(SYNC_PATH), 'lib/core/folder-memory.cjs missing');
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// ---------- Test 1: missing STATE.md returns null ----------
|
|
110
|
+
|
|
111
|
+
function test_1_missingStateMdReturnsNull(sync) {
|
|
112
|
+
const work = mkTmp('statusline-active-room-t1-');
|
|
113
|
+
// No STATE.md anywhere; no .rooms registry; no room/ legacy dir.
|
|
114
|
+
let r;
|
|
115
|
+
assert.doesNotThrow(() => {
|
|
116
|
+
r = sync.getCurrentRoom(work);
|
|
117
|
+
}, 't1: no throws when STATE.md absent');
|
|
118
|
+
assert.strictEqual(r, null, 't1: returns null on missing STATE.md');
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// ---------- Test 2: STATE.md without frontmatter returns null ----------
|
|
122
|
+
|
|
123
|
+
function test_2_stateMdWithoutFrontmatterReturnsNull(sync) {
|
|
124
|
+
const work = mkTmp('statusline-active-room-t2-');
|
|
125
|
+
const room = path.join(work, 'room');
|
|
126
|
+
fs.mkdirSync(room, { recursive: true });
|
|
127
|
+
// No leading --- delimiter; just plain markdown.
|
|
128
|
+
fs.writeFileSync(
|
|
129
|
+
path.join(room, 'STATE.md'),
|
|
130
|
+
'# Room State\n\nNo frontmatter here.\n',
|
|
131
|
+
'utf8'
|
|
132
|
+
);
|
|
133
|
+
const r = sync.getCurrentRoom(work);
|
|
134
|
+
assert.strictEqual(r, null, 't2: returns null when frontmatter absent');
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// ---------- Test 3: frontmatter without current_room returns null ----------
|
|
138
|
+
|
|
139
|
+
function test_3_frontmatterWithoutCurrentRoomReturnsNull(sync) {
|
|
140
|
+
const work = mkTmp('statusline-active-room-t3-');
|
|
141
|
+
const room = path.join(work, 'room');
|
|
142
|
+
fs.mkdirSync(room, { recursive: true });
|
|
143
|
+
writeStateMdWithFrontmatter(room, [
|
|
144
|
+
'venture_stage: Pre-Opportunity',
|
|
145
|
+
'last_updated: 2026-04-28',
|
|
146
|
+
], '# Room State');
|
|
147
|
+
const r = sync.getCurrentRoom(work);
|
|
148
|
+
assert.strictEqual(r, null, 't3: returns null when current_room absent');
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// ---------- Test 4: happy path ----------
|
|
152
|
+
|
|
153
|
+
function test_4_happyFrontmatterReturnsTriple(sync) {
|
|
154
|
+
const work = mkTmp('statusline-active-room-t4-');
|
|
155
|
+
const room = path.join(work, 'room');
|
|
156
|
+
writeRoomFixture(room, 'core-power');
|
|
157
|
+
|
|
158
|
+
const r = sync.getCurrentRoom(work);
|
|
159
|
+
assert.ok(r !== null, 't4: returns non-null when current_room present');
|
|
160
|
+
assert.strictEqual(r.slug, 'core-power', 't4: slug parsed');
|
|
161
|
+
assert.strictEqual(r.source, 'state_md', 't4: source tag');
|
|
162
|
+
assert.ok(typeof r.path === 'string' && r.path.length > 0, 't4: path string');
|
|
163
|
+
assert.ok(path.isAbsolute(r.path), 't4: path is absolute');
|
|
164
|
+
assert.ok(r.path.endsWith('STATE.md'), 't4: path points at STATE.md');
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// ---------- Test 5: malformed YAML returns null ----------
|
|
168
|
+
|
|
169
|
+
function test_5_malformedYamlReturnsNull(sync) {
|
|
170
|
+
const work = mkTmp('statusline-active-room-t5-');
|
|
171
|
+
const room = path.join(work, 'room');
|
|
172
|
+
fs.mkdirSync(room, { recursive: true });
|
|
173
|
+
// Frontmatter open delimiter but never closes; malformed key syntax.
|
|
174
|
+
fs.writeFileSync(
|
|
175
|
+
path.join(room, 'STATE.md'),
|
|
176
|
+
'---\nthis is not valid yaml because : : : :\nmore garbage\n',
|
|
177
|
+
'utf8'
|
|
178
|
+
);
|
|
179
|
+
let r;
|
|
180
|
+
assert.doesNotThrow(() => {
|
|
181
|
+
r = sync.getCurrentRoom(work);
|
|
182
|
+
}, 't5: no throws on malformed YAML');
|
|
183
|
+
assert.strictEqual(r, null, 't5: returns null on malformed YAML');
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// ---------- Test 6: Lawrence reproducer (no caching across calls) ----------
|
|
187
|
+
|
|
188
|
+
function test_6_lawrenceReproducerNoCaching(sync) {
|
|
189
|
+
const work = mkTmp('statusline-active-room-t6-');
|
|
190
|
+
const room = path.join(work, 'room');
|
|
191
|
+
|
|
192
|
+
writeRoomFixture(room, 'core-power');
|
|
193
|
+
const first = sync.getCurrentRoom(work);
|
|
194
|
+
assert.ok(first !== null, 't6a: first read returns object');
|
|
195
|
+
assert.strictEqual(first.slug, 'core-power', 't6a: first slug = core-power');
|
|
196
|
+
|
|
197
|
+
// Lawrence's reproducer step: /mos:rooms switches to a new room.
|
|
198
|
+
// STATE.md is rewritten with the new current_room.
|
|
199
|
+
writeRoomFixture(room, 'curriculum-redesign-fall-2026');
|
|
200
|
+
|
|
201
|
+
const second = sync.getCurrentRoom(work);
|
|
202
|
+
assert.ok(second !== null, 't6b: second read returns object');
|
|
203
|
+
assert.strictEqual(
|
|
204
|
+
second.slug,
|
|
205
|
+
'curriculum-redesign-fall-2026',
|
|
206
|
+
't6b: second slug = curriculum-redesign-fall-2026 (no stale cache)'
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// ---------- Test 7: quotes and whitespace stripped ----------
|
|
211
|
+
|
|
212
|
+
function test_7_quotesAndWhitespaceStripped(sync) {
|
|
213
|
+
const variants = [
|
|
214
|
+
{ raw: 'core-power', expected: 'core-power' },
|
|
215
|
+
{ raw: '"core-power"', expected: 'core-power' },
|
|
216
|
+
{ raw: "'core-power'", expected: 'core-power' },
|
|
217
|
+
{ raw: ' core-power ', expected: 'core-power' },
|
|
218
|
+
{ raw: '" core-power "', expected: 'core-power' },
|
|
219
|
+
];
|
|
220
|
+
for (const v of variants) {
|
|
221
|
+
const work = mkTmp('statusline-active-room-t7-');
|
|
222
|
+
const room = path.join(work, 'room');
|
|
223
|
+
writeRoomFixture(room, v.raw);
|
|
224
|
+
const r = sync.getCurrentRoom(work);
|
|
225
|
+
assert.ok(r !== null, 't7: non-null for variant ' + JSON.stringify(v.raw));
|
|
226
|
+
assert.strictEqual(
|
|
227
|
+
r.slug,
|
|
228
|
+
v.expected,
|
|
229
|
+
't7: variant ' + JSON.stringify(v.raw) + ' -> ' + v.expected
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// ---------- Test 8: end-to-end context-monitor render ----------
|
|
235
|
+
|
|
236
|
+
function test_8_endToEndContextMonitorRender(sync) {
|
|
237
|
+
const work = mkTmp('statusline-active-room-t8-');
|
|
238
|
+
const room = path.join(work, 'room');
|
|
239
|
+
writeRoomFixture(room, 'switched-room-name-94-01');
|
|
240
|
+
|
|
241
|
+
// Also seed a registry entry pointing at our fixture room so the
|
|
242
|
+
// existing context-monitor room-resolution path can find it. The
|
|
243
|
+
// registry's active slug stays aligned with current_room for the
|
|
244
|
+
// happy-path test.
|
|
245
|
+
writeRegistry(work, 'switched-room-name-94-01', room);
|
|
246
|
+
|
|
247
|
+
// Prepare the JSON payload Claude Code feeds the statusline on stdin.
|
|
248
|
+
const stdinPayload = JSON.stringify({
|
|
249
|
+
model: { id: 'claude-3-5-sonnet', display_name: 'Sonnet' },
|
|
250
|
+
workspace: { current_dir: work },
|
|
251
|
+
context_window: {
|
|
252
|
+
remaining_percentage: 80,
|
|
253
|
+
used_percentage: 20,
|
|
254
|
+
context_window_size: 200000,
|
|
255
|
+
},
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
let stdout = '';
|
|
259
|
+
try {
|
|
260
|
+
stdout = execFileSync(process.execPath, [CONTEXT_MONITOR], {
|
|
261
|
+
input: stdinPayload,
|
|
262
|
+
encoding: 'utf8',
|
|
263
|
+
timeout: 5000,
|
|
264
|
+
env: Object.assign({}, process.env, {
|
|
265
|
+
MINDRIAN_OS_ROOT: REPO,
|
|
266
|
+
}),
|
|
267
|
+
});
|
|
268
|
+
} catch (e) {
|
|
269
|
+
// Surface the captured streams for diagnostic clarity.
|
|
270
|
+
const detail = e && e.stdout ? String(e.stdout) : '(no stdout)';
|
|
271
|
+
const errDetail = e && e.stderr ? String(e.stderr) : '(no stderr)';
|
|
272
|
+
throw new Error(
|
|
273
|
+
't8: context-monitor exec failed -- stdout=' + detail +
|
|
274
|
+
' stderr=' + errDetail
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
assert.ok(
|
|
279
|
+
stdout.indexOf('switched-room-name-94-01') !== -1,
|
|
280
|
+
't8: context-monitor stdout contains switched-room-name-94-01 ' +
|
|
281
|
+
'(got: ' + stdout.replace(/\x1b\[[0-9;]*m/g, '').slice(0, 300) + ')'
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// ---------- Runner ----------
|
|
286
|
+
|
|
287
|
+
async function run() {
|
|
288
|
+
t0_moduleFileExists();
|
|
289
|
+
|
|
290
|
+
// eslint-disable-next-line global-require
|
|
291
|
+
const sync = require(SYNC_PATH);
|
|
292
|
+
|
|
293
|
+
assert.ok(
|
|
294
|
+
typeof sync.getCurrentRoom === 'function',
|
|
295
|
+
'precondition: folder-memory.cjs must export getCurrentRoom function'
|
|
296
|
+
);
|
|
297
|
+
|
|
298
|
+
test_1_missingStateMdReturnsNull(sync);
|
|
299
|
+
test_2_stateMdWithoutFrontmatterReturnsNull(sync);
|
|
300
|
+
test_3_frontmatterWithoutCurrentRoomReturnsNull(sync);
|
|
301
|
+
test_4_happyFrontmatterReturnsTriple(sync);
|
|
302
|
+
test_5_malformedYamlReturnsNull(sync);
|
|
303
|
+
test_6_lawrenceReproducerNoCaching(sync);
|
|
304
|
+
test_7_quotesAndWhitespaceStripped(sync);
|
|
305
|
+
test_8_endToEndContextMonitorRender(sync);
|
|
306
|
+
|
|
307
|
+
process.stdout.write('statusline-active-room: 8/8 tests passed\n');
|
|
308
|
+
process.exit(0);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
run().catch((e) => {
|
|
312
|
+
process.stderr.write((e && e.stack) || String(e));
|
|
313
|
+
process.stderr.write('\n');
|
|
314
|
+
process.exit(1);
|
|
315
|
+
});
|