@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,314 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2026 Mindrian. BSL 1.1.
|
|
3
|
+
* Phase 89.2 Plan 05 -- Experts post-processor.
|
|
4
|
+
* Phase 94 Plan 05 amendment (2026-04-28): envelope wrap only.
|
|
5
|
+
* mapExperts now returns an Array-with-properties hybrid: the return
|
|
6
|
+
* value IS still an Array of expert records (preserving every existing
|
|
7
|
+
* consumer: experts.length, experts.find(), experts[i] all work
|
|
8
|
+
* byte-identically) and ALSO carries envelope properties tier, source,
|
|
9
|
+
* results, experts attached to it. tier='derived' annotates that this
|
|
10
|
+
* is a post-processor over academic.papers (not a network fetcher);
|
|
11
|
+
* source='derived' is the canonical sentinel for non-fetcher modules.
|
|
12
|
+
* This zero-blast-radius pattern is the cheapest correct way to honor
|
|
13
|
+
* Plan 94-05's envelope-uniformity contract without breaking the
|
|
14
|
+
* 17-scenario rs-fetcher-experts fixture suite or rs-discovery-engine
|
|
15
|
+
* line 330 mapExperts consumer.
|
|
16
|
+
*
|
|
17
|
+
*
|
|
18
|
+
* Wave-2 module that extracts deduped author records from academic
|
|
19
|
+
* fetcher output (papers[]). The naming convention follows the other
|
|
20
|
+
* Wave-2 modules (rs-fetcher-academic.cjs, rs-fetcher-patents.cjs,
|
|
21
|
+
* rs-fetcher-industry.cjs) but THIS MODULE IS NOT A FETCHER.
|
|
22
|
+
*
|
|
23
|
+
* Input: papers[] from rs-fetcher-academic.cjs (already validated +
|
|
24
|
+
* audited at the network boundary by Plan 89.2-02)
|
|
25
|
+
* Output: experts[] one record per deduped author with shape
|
|
26
|
+
* { name, orcid, institution, paper_count,
|
|
27
|
+
* h_index_estimate, public_email_or_null }
|
|
28
|
+
*
|
|
29
|
+
* NO network egress. NO outbound calls. The post-processor reads its
|
|
30
|
+
* input, deduplicates by (name|orcid) composite key, computes the
|
|
31
|
+
* h-index estimate from per-author citation counts, sorts deterministically
|
|
32
|
+
* (paper_count desc, name asc), and runs auditQueryObject(experts) BEFORE
|
|
33
|
+
* return as the defense-in-depth tripwire. Even though there is no
|
|
34
|
+
* outbound network surface, the experts[] payload is the lineage that
|
|
35
|
+
* downstream Plan 89.5 rs-expert-mapper.cjs writes to the user's own
|
|
36
|
+
* Aura via Cypher; auditing at this boundary is conservative Canon
|
|
37
|
+
* Part 8 enforcement (the user's own Aura is NOT the Brain, but the
|
|
38
|
+
* extra audit ensures that any forbidden bytes that slip past the
|
|
39
|
+
* upstream academic fetcher cannot smuggle into the Aura write).
|
|
40
|
+
*
|
|
41
|
+
* Privacy stance per kickoff section 15 open-question-4: public author
|
|
42
|
+
* emails sourced from OpenAlex are allowed (the data is already public
|
|
43
|
+
* via OpenAlex authorships.author.email). Anything sourced behind a
|
|
44
|
+
* login wall (Scopus, IEEE, Nature) is dropped (public_email_or_null
|
|
45
|
+
* = null). PUBLIC_EMAIL_SOURCES enforces this allow-list.
|
|
46
|
+
*
|
|
47
|
+
* Deterministic: same papers[] input produces byte-identical experts[]
|
|
48
|
+
* output. Sort order: paper_count descending then name ascending.
|
|
49
|
+
*
|
|
50
|
+
* Pure CJS, zero npm deps. Imports the shared ExternalEgressViolation
|
|
51
|
+
* and auditQueryObject primitives from Plan 89.2-01 (Wave 1).
|
|
52
|
+
*/
|
|
53
|
+
'use strict';
|
|
54
|
+
|
|
55
|
+
const { ExternalEgressViolation } = require('./rs-egress-violations.cjs');
|
|
56
|
+
const { auditQueryObject, FORBIDDEN_PATTERNS } = require('./rs-egress-prompts.cjs');
|
|
57
|
+
|
|
58
|
+
// ---------- Frozen invariants ----------
|
|
59
|
+
|
|
60
|
+
// Public-email allow-list per kickoff section 15 open-question-4.
|
|
61
|
+
// Only OpenAlex emails are considered public (data is already public via
|
|
62
|
+
// OpenAlex authorships.author.email field). Any other source is treated
|
|
63
|
+
// as login-gated and dropped to public_email_or_null = null.
|
|
64
|
+
const PUBLIC_EMAIL_SOURCES = Object.freeze(new Set(['openalex']));
|
|
65
|
+
|
|
66
|
+
// Strict email format: no whitespace, single @, TLD at least 2 chars.
|
|
67
|
+
const PUBLIC_EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/;
|
|
68
|
+
|
|
69
|
+
// ---------- scrubScalar ----------
|
|
70
|
+
//
|
|
71
|
+
// Mirrors the 89.1 Plan 02 rs-domain-analyzer.cjs scrubScalar pattern:
|
|
72
|
+
// any string that matches any FORBIDDEN_PATTERNS regex is rejected
|
|
73
|
+
// (returns null). Non-string inputs pass through. Empty strings become
|
|
74
|
+
// null so the caller's "empty or scrubbed" branch is one check.
|
|
75
|
+
|
|
76
|
+
function scrubScalar(s) {
|
|
77
|
+
if (s === null || s === undefined) return null;
|
|
78
|
+
if (typeof s !== 'string') return s;
|
|
79
|
+
if (s.length === 0) return null;
|
|
80
|
+
for (const re of FORBIDDEN_PATTERNS) {
|
|
81
|
+
if (re.test(s)) return null;
|
|
82
|
+
}
|
|
83
|
+
return s;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// ---------- isPublicEmail ----------
|
|
87
|
+
//
|
|
88
|
+
// Three-layer check before allowing an author email into output:
|
|
89
|
+
// 1. paper.source must be on the PUBLIC_EMAIL_SOURCES allow-list
|
|
90
|
+
// 2. author.email must match the strict PUBLIC_EMAIL_REGEX
|
|
91
|
+
// 3. author.email must NOT match any FORBIDDEN_PATTERNS regex (defense
|
|
92
|
+
// in depth: even an openalex source with a malformed email goes null)
|
|
93
|
+
//
|
|
94
|
+
// Returns boolean. Caller must still pass the email through scrubScalar
|
|
95
|
+
// before promoting into output (belt and suspenders).
|
|
96
|
+
|
|
97
|
+
function isPublicEmail(paper, author) {
|
|
98
|
+
if (!paper || typeof paper.source !== 'string') return false;
|
|
99
|
+
if (!PUBLIC_EMAIL_SOURCES.has(paper.source)) return false;
|
|
100
|
+
if (!author || typeof author.email !== 'string') return false;
|
|
101
|
+
if (!PUBLIC_EMAIL_REGEX.test(author.email)) return false;
|
|
102
|
+
for (const re of FORBIDDEN_PATTERNS) {
|
|
103
|
+
if (re.test(author.email)) return false;
|
|
104
|
+
}
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// ---------- computeHIndexEstimate ----------
|
|
109
|
+
//
|
|
110
|
+
// Standard h-index over a citation list. h is the largest value such
|
|
111
|
+
// that h papers each have >= h citations. Sort descending; walk from
|
|
112
|
+
// highest h down to 0 and return the first h that satisfies the
|
|
113
|
+
// condition. Empty list returns 0.
|
|
114
|
+
//
|
|
115
|
+
// Examples:
|
|
116
|
+
// [10, 8, 5, 3, 1] -> 3 (4 papers >= 3 cites; only 3 papers >= 4 cites)
|
|
117
|
+
// [0, 0, 0] -> 0
|
|
118
|
+
// [] -> 0
|
|
119
|
+
// [1] -> 1
|
|
120
|
+
// [5, 5, 5, 5, 5] -> 5
|
|
121
|
+
|
|
122
|
+
function computeHIndexEstimate(citations) {
|
|
123
|
+
if (!Array.isArray(citations) || citations.length === 0) return 0;
|
|
124
|
+
const sorted = citations.slice().sort(function (a, b) { return b - a; });
|
|
125
|
+
for (let h = sorted.length; h >= 1; h -= 1) {
|
|
126
|
+
if (sorted[h - 1] >= h) return h;
|
|
127
|
+
}
|
|
128
|
+
return 0;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// ---------- extractAuthorRecord ----------
|
|
132
|
+
//
|
|
133
|
+
// Build the per-author intermediate record from a single (paper, author)
|
|
134
|
+
// pair. Returns null if the author cannot be safely emitted (scrubbed
|
|
135
|
+
// name, missing required fields). The record is intermediate because
|
|
136
|
+
// paper_count + h_index_estimate are aggregated across multiple papers
|
|
137
|
+
// in mapExperts.
|
|
138
|
+
|
|
139
|
+
function extractAuthorRecord(paper, author) {
|
|
140
|
+
if (!author || typeof author !== 'object') return null;
|
|
141
|
+
const name = scrubScalar(author.name);
|
|
142
|
+
if (name === null) return null; // forbidden or empty -- skip
|
|
143
|
+
const orcid = scrubScalar(author.orcid);
|
|
144
|
+
const institution = scrubScalar(author.institution);
|
|
145
|
+
let email = null;
|
|
146
|
+
if (isPublicEmail(paper, author)) {
|
|
147
|
+
const scrubbed = scrubScalar(author.email);
|
|
148
|
+
if (scrubbed !== null) email = scrubbed;
|
|
149
|
+
}
|
|
150
|
+
return {
|
|
151
|
+
name: name,
|
|
152
|
+
orcid: orcid,
|
|
153
|
+
institution: institution,
|
|
154
|
+
public_email_or_null: email,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// ---------- dedupExperts ----------
|
|
159
|
+
//
|
|
160
|
+
// Walk papers; build authorMap keyed by (name|orcid). For each
|
|
161
|
+
// occurrence: bump paper_count, push the citation count into
|
|
162
|
+
// citations_per_paper, fill in institution if previously null,
|
|
163
|
+
// fill in public_email_or_null if previously null.
|
|
164
|
+
//
|
|
165
|
+
// Note: institution and email "fill if previously null" semantics
|
|
166
|
+
// favor the FIRST non-null value seen (deterministic given the input
|
|
167
|
+
// papers[] order). The same name appearing with different institutions
|
|
168
|
+
// across papers will keep the first non-null institution.
|
|
169
|
+
|
|
170
|
+
function dedupExperts(papers) {
|
|
171
|
+
const authorMap = new Map();
|
|
172
|
+
for (const paper of papers) {
|
|
173
|
+
if (!paper || !Array.isArray(paper.authors)) continue;
|
|
174
|
+
const citationCount = (typeof paper.citationCount === 'number' && isFinite(paper.citationCount))
|
|
175
|
+
? paper.citationCount
|
|
176
|
+
: 0;
|
|
177
|
+
for (const author of paper.authors) {
|
|
178
|
+
const rec = extractAuthorRecord(paper, author);
|
|
179
|
+
if (rec === null) continue;
|
|
180
|
+
const key = rec.name + '|' + (rec.orcid === null ? '__no_orcid__' : rec.orcid);
|
|
181
|
+
if (!authorMap.has(key)) {
|
|
182
|
+
authorMap.set(key, {
|
|
183
|
+
name: rec.name,
|
|
184
|
+
orcid: rec.orcid,
|
|
185
|
+
institution: rec.institution,
|
|
186
|
+
paper_count: 0,
|
|
187
|
+
citations_per_paper: [],
|
|
188
|
+
public_email_or_null: rec.public_email_or_null,
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
const existing = authorMap.get(key);
|
|
192
|
+
existing.paper_count += 1;
|
|
193
|
+
existing.citations_per_paper.push(citationCount);
|
|
194
|
+
if (existing.institution === null && rec.institution !== null) {
|
|
195
|
+
existing.institution = rec.institution;
|
|
196
|
+
}
|
|
197
|
+
if (existing.public_email_or_null === null && rec.public_email_or_null !== null) {
|
|
198
|
+
existing.public_email_or_null = rec.public_email_or_null;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return authorMap;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// ---------- mapExperts ----------
|
|
206
|
+
//
|
|
207
|
+
// Public entry point. Walks papers[], deduplicates authors, computes
|
|
208
|
+
// h_index_estimate per author, sorts deterministically, drops the
|
|
209
|
+
// citations_per_paper helper field from the final output, runs
|
|
210
|
+
// auditQueryObject(experts) as the pre-return defense-in-depth tripwire,
|
|
211
|
+
// and returns the experts[] array.
|
|
212
|
+
//
|
|
213
|
+
// Throws:
|
|
214
|
+
// TypeError if papers is not an array
|
|
215
|
+
// ExternalEgressViolation if any FORBIDDEN_PATTERNS regex matches
|
|
216
|
+
// the JSON.stringify of the output (defense
|
|
217
|
+
// in depth -- the per-field scrubScalar +
|
|
218
|
+
// isPublicEmail allow-list should have caught
|
|
219
|
+
// anything earlier)
|
|
220
|
+
//
|
|
221
|
+
// Returns: experts[] array. May be empty when papers[] is empty or no
|
|
222
|
+
// safely-emittable authors are found.
|
|
223
|
+
|
|
224
|
+
function mapExperts(papers, opts) {
|
|
225
|
+
if (!Array.isArray(papers)) {
|
|
226
|
+
throw new TypeError('mapExperts: papers must be an array; got ' + typeof papers);
|
|
227
|
+
}
|
|
228
|
+
// opts is reserved for forward compatibility (e.g. min_paper_count
|
|
229
|
+
// filter). Reading it would be premature; preserve the parameter so
|
|
230
|
+
// future plans can add knobs without changing the call signature.
|
|
231
|
+
void opts;
|
|
232
|
+
|
|
233
|
+
// Empty papers: still return Array-with-envelope-properties so the
|
|
234
|
+
// T5 envelope-shape contract holds AND existing consumers that do
|
|
235
|
+
// `experts.length === 0` keep working.
|
|
236
|
+
if (papers.length === 0) {
|
|
237
|
+
const empty = [];
|
|
238
|
+
annotateExpertsEnvelope(empty);
|
|
239
|
+
return empty;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
const authorMap = dedupExperts(papers);
|
|
243
|
+
const experts = [];
|
|
244
|
+
for (const rec of authorMap.values()) {
|
|
245
|
+
const h = computeHIndexEstimate(rec.citations_per_paper);
|
|
246
|
+
experts.push({
|
|
247
|
+
name: rec.name,
|
|
248
|
+
orcid: rec.orcid,
|
|
249
|
+
institution: rec.institution,
|
|
250
|
+
paper_count: rec.paper_count,
|
|
251
|
+
h_index_estimate: h,
|
|
252
|
+
public_email_or_null: rec.public_email_or_null,
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Deterministic sort: paper_count descending, then name ascending.
|
|
257
|
+
experts.sort(function (a, b) {
|
|
258
|
+
if (b.paper_count !== a.paper_count) return b.paper_count - a.paper_count;
|
|
259
|
+
return a.name.localeCompare(b.name);
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
// Pre-return Canon Part 8 defense-in-depth audit. JSON.stringify
|
|
263
|
+
// flattens every field; FORBIDDEN_PATTERNS scan catches anything
|
|
264
|
+
// that smuggled past the per-field scrubScalar + isPublicEmail
|
|
265
|
+
// allow-list (e.g. paper.id strings accidentally promoted into a
|
|
266
|
+
// helper field by a future regression). Throws ExternalEgressViolation
|
|
267
|
+
// on hit; the throw point is intentional so any leak is loud not silent.
|
|
268
|
+
auditQueryObject(experts, 'experts');
|
|
269
|
+
|
|
270
|
+
// Phase 94 Plan 05 envelope wrap: attach tier/source/results/experts
|
|
271
|
+
// properties on the Array itself. JS arrays support extra named
|
|
272
|
+
// properties; existing consumers (.length, .find, indexing) are
|
|
273
|
+
// unaffected. Object.keys(experts) will enumerate only the named
|
|
274
|
+
// properties (not the numeric indices), so JSON.stringify of a
|
|
275
|
+
// mapExperts return still serializes as an Array (numeric indices
|
|
276
|
+
// win); that preserves the existing wire format byte-identically.
|
|
277
|
+
annotateExpertsEnvelope(experts);
|
|
278
|
+
return experts;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// ---------- annotateExpertsEnvelope ----------
|
|
282
|
+
//
|
|
283
|
+
// Attaches Phase 94 Plan 05 envelope properties to the experts Array
|
|
284
|
+
// in place. tier='derived' source='derived' results=<array>
|
|
285
|
+
// experts=<array>. The Array remains the authoritative collection;
|
|
286
|
+
// the envelope properties are additive metadata for the T5 envelope-
|
|
287
|
+
// shape contract.
|
|
288
|
+
|
|
289
|
+
function annotateExpertsEnvelope(arr) {
|
|
290
|
+
Object.defineProperty(arr, 'tier', { value: 'derived', enumerable: false, writable: false });
|
|
291
|
+
Object.defineProperty(arr, 'source', { value: 'derived', enumerable: false, writable: false });
|
|
292
|
+
Object.defineProperty(arr, 'results', { value: arr, enumerable: false, writable: false });
|
|
293
|
+
Object.defineProperty(arr, 'experts', { value: arr, enumerable: false, writable: false });
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// ---------- Exports ----------
|
|
297
|
+
|
|
298
|
+
module.exports = {
|
|
299
|
+
mapExperts,
|
|
300
|
+
// _test exposes internals for the fixture suite. Not part of the public
|
|
301
|
+
// API contract; downstream consumers MUST use mapExperts only.
|
|
302
|
+
_test: {
|
|
303
|
+
scrubScalar,
|
|
304
|
+
isPublicEmail,
|
|
305
|
+
computeHIndexEstimate,
|
|
306
|
+
extractAuthorRecord,
|
|
307
|
+
dedupExperts,
|
|
308
|
+
PUBLIC_EMAIL_REGEX,
|
|
309
|
+
PUBLIC_EMAIL_SOURCES,
|
|
310
|
+
},
|
|
311
|
+
// Re-export so callers needing instanceof checks have a stable import
|
|
312
|
+
// path without going to rs-egress-violations.cjs directly.
|
|
313
|
+
ExternalEgressViolation,
|
|
314
|
+
};
|