nodedex 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/adapters/claude-code-watcher.mjs +336 -0
- package/adapters/hermes-statedb-watcher.mjs +234 -0
- package/adapters/nodedex-capture-core.mjs +129 -0
- package/adapters/nodedex-capture.mjs +169 -0
- package/dist/agent-protocol.d.ts +7 -0
- package/dist/agent-protocol.d.ts.map +1 -0
- package/dist/agent-protocol.js +38 -0
- package/dist/agent-protocol.js.map +1 -0
- package/dist/api-server.d.ts +5 -0
- package/dist/api-server.d.ts.map +1 -0
- package/dist/api-server.js +351 -0
- package/dist/api-server.js.map +1 -0
- package/dist/boot-env.d.ts +2 -0
- package/dist/boot-env.d.ts.map +1 -0
- package/dist/boot-env.js +12 -0
- package/dist/boot-env.js.map +1 -0
- package/dist/engine/__tests__/search-core.test.d.ts +2 -0
- package/dist/engine/__tests__/search-core.test.d.ts.map +1 -0
- package/dist/engine/__tests__/search-core.test.js +139 -0
- package/dist/engine/__tests__/search-core.test.js.map +1 -0
- package/dist/engine/ai-provider.d.ts +45 -0
- package/dist/engine/ai-provider.d.ts.map +1 -0
- package/dist/engine/ai-provider.js +5 -0
- package/dist/engine/ai-provider.js.map +1 -0
- package/dist/engine/embeddings.d.ts +51 -0
- package/dist/engine/embeddings.d.ts.map +1 -0
- package/dist/engine/embeddings.js +89 -0
- package/dist/engine/embeddings.js.map +1 -0
- package/dist/engine/providers/__tests__/failure-policy.test.d.ts +2 -0
- package/dist/engine/providers/__tests__/failure-policy.test.d.ts.map +1 -0
- package/dist/engine/providers/__tests__/failure-policy.test.js +134 -0
- package/dist/engine/providers/__tests__/failure-policy.test.js.map +1 -0
- package/dist/engine/providers/__tests__/model-caps.test.d.ts +2 -0
- package/dist/engine/providers/__tests__/model-caps.test.d.ts.map +1 -0
- package/dist/engine/providers/__tests__/model-caps.test.js +38 -0
- package/dist/engine/providers/__tests__/model-caps.test.js.map +1 -0
- package/dist/engine/providers/__tests__/openai-structured.test.d.ts +2 -0
- package/dist/engine/providers/__tests__/openai-structured.test.d.ts.map +1 -0
- package/dist/engine/providers/__tests__/openai-structured.test.js +73 -0
- package/dist/engine/providers/__tests__/openai-structured.test.js.map +1 -0
- package/dist/engine/providers/__tests__/usage-ledger.test.d.ts +2 -0
- package/dist/engine/providers/__tests__/usage-ledger.test.d.ts.map +1 -0
- package/dist/engine/providers/__tests__/usage-ledger.test.js +108 -0
- package/dist/engine/providers/__tests__/usage-ledger.test.js.map +1 -0
- package/dist/engine/providers/anthropic.d.ts +17 -0
- package/dist/engine/providers/anthropic.d.ts.map +1 -0
- package/dist/engine/providers/anthropic.js +125 -0
- package/dist/engine/providers/anthropic.js.map +1 -0
- package/dist/engine/providers/failure-policy.d.ts +56 -0
- package/dist/engine/providers/failure-policy.d.ts.map +1 -0
- package/dist/engine/providers/failure-policy.js +120 -0
- package/dist/engine/providers/failure-policy.js.map +1 -0
- package/dist/engine/providers/gemini.d.ts +22 -0
- package/dist/engine/providers/gemini.d.ts.map +1 -0
- package/dist/engine/providers/gemini.js +180 -0
- package/dist/engine/providers/gemini.js.map +1 -0
- package/dist/engine/providers/index.d.ts +8 -0
- package/dist/engine/providers/index.d.ts.map +1 -0
- package/dist/engine/providers/index.js +67 -0
- package/dist/engine/providers/index.js.map +1 -0
- package/dist/engine/providers/local.d.ts +12 -0
- package/dist/engine/providers/local.d.ts.map +1 -0
- package/dist/engine/providers/local.js +46 -0
- package/dist/engine/providers/local.js.map +1 -0
- package/dist/engine/providers/model-caps.d.ts +6 -0
- package/dist/engine/providers/model-caps.d.ts.map +1 -0
- package/dist/engine/providers/model-caps.js +49 -0
- package/dist/engine/providers/model-caps.js.map +1 -0
- package/dist/engine/providers/openai.d.ts +30 -0
- package/dist/engine/providers/openai.d.ts.map +1 -0
- package/dist/engine/providers/openai.js +309 -0
- package/dist/engine/providers/openai.js.map +1 -0
- package/dist/engine/providers/usage-ledger.d.ts +69 -0
- package/dist/engine/providers/usage-ledger.d.ts.map +1 -0
- package/dist/engine/providers/usage-ledger.js +209 -0
- package/dist/engine/providers/usage-ledger.js.map +1 -0
- package/dist/engine/search-core.d.ts +40 -0
- package/dist/engine/search-core.d.ts.map +1 -0
- package/dist/engine/search-core.js +109 -0
- package/dist/engine/search-core.js.map +1 -0
- package/dist/engine/vector-math.d.ts +5 -0
- package/dist/engine/vector-math.d.ts.map +1 -0
- package/dist/engine/vector-math.js +25 -0
- package/dist/engine/vector-math.js.map +1 -0
- package/dist/home-env.d.ts +26 -0
- package/dist/home-env.d.ts.map +1 -0
- package/dist/home-env.js +87 -0
- package/dist/home-env.js.map +1 -0
- package/dist/mcp-server.d.ts +13 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +79 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/middleware/auth.d.ts +23 -0
- package/dist/middleware/auth.d.ts.map +1 -0
- package/dist/middleware/auth.js +104 -0
- package/dist/middleware/auth.js.map +1 -0
- package/dist/middleware/auto-recall.d.ts +7 -0
- package/dist/middleware/auto-recall.d.ts.map +1 -0
- package/dist/middleware/auto-recall.js +257 -0
- package/dist/middleware/auto-recall.js.map +1 -0
- package/dist/middleware/auto-reflect.d.ts +4 -0
- package/dist/middleware/auto-reflect.d.ts.map +1 -0
- package/dist/middleware/auto-reflect.js +5 -0
- package/dist/middleware/auto-reflect.js.map +1 -0
- package/dist/middleware/reflect/apply-flag-verdict.d.ts +27 -0
- package/dist/middleware/reflect/apply-flag-verdict.d.ts.map +1 -0
- package/dist/middleware/reflect/apply-flag-verdict.js +57 -0
- package/dist/middleware/reflect/apply-flag-verdict.js.map +1 -0
- package/dist/middleware/reflect/arc-entity-resolve.d.ts +29 -0
- package/dist/middleware/reflect/arc-entity-resolve.d.ts.map +1 -0
- package/dist/middleware/reflect/arc-entity-resolve.js +356 -0
- package/dist/middleware/reflect/arc-entity-resolve.js.map +1 -0
- package/dist/middleware/reflect/arc-inactivity-timer.d.ts +47 -0
- package/dist/middleware/reflect/arc-inactivity-timer.d.ts.map +1 -0
- package/dist/middleware/reflect/arc-inactivity-timer.js +175 -0
- package/dist/middleware/reflect/arc-inactivity-timer.js.map +1 -0
- package/dist/middleware/reflect/arc-pipeline.d.ts +33 -0
- package/dist/middleware/reflect/arc-pipeline.d.ts.map +1 -0
- package/dist/middleware/reflect/arc-pipeline.js +498 -0
- package/dist/middleware/reflect/arc-pipeline.js.map +1 -0
- package/dist/middleware/reflect/comprehend-pergroup.d.ts +100 -0
- package/dist/middleware/reflect/comprehend-pergroup.d.ts.map +1 -0
- package/dist/middleware/reflect/comprehend-pergroup.js +610 -0
- package/dist/middleware/reflect/comprehend-pergroup.js.map +1 -0
- package/dist/middleware/reflect/comprehend.d.ts +237 -0
- package/dist/middleware/reflect/comprehend.d.ts.map +1 -0
- package/dist/middleware/reflect/comprehend.js +706 -0
- package/dist/middleware/reflect/comprehend.js.map +1 -0
- package/dist/middleware/reflect/config.d.ts +34 -0
- package/dist/middleware/reflect/config.d.ts.map +1 -0
- package/dist/middleware/reflect/config.js +131 -0
- package/dist/middleware/reflect/config.js.map +1 -0
- package/dist/middleware/reflect/context.d.ts +138 -0
- package/dist/middleware/reflect/context.d.ts.map +1 -0
- package/dist/middleware/reflect/context.js +619 -0
- package/dist/middleware/reflect/context.js.map +1 -0
- package/dist/middleware/reflect/cost-breakdown.d.ts +69 -0
- package/dist/middleware/reflect/cost-breakdown.d.ts.map +1 -0
- package/dist/middleware/reflect/cost-breakdown.js +63 -0
- package/dist/middleware/reflect/cost-breakdown.js.map +1 -0
- package/dist/middleware/reflect/cost-guard.d.ts +102 -0
- package/dist/middleware/reflect/cost-guard.d.ts.map +1 -0
- package/dist/middleware/reflect/cost-guard.js +243 -0
- package/dist/middleware/reflect/cost-guard.js.map +1 -0
- package/dist/middleware/reflect/cost-pricing.d.ts +54 -0
- package/dist/middleware/reflect/cost-pricing.d.ts.map +1 -0
- package/dist/middleware/reflect/cost-pricing.js +148 -0
- package/dist/middleware/reflect/cost-pricing.js.map +1 -0
- package/dist/middleware/reflect/cross-group-link.d.ts +61 -0
- package/dist/middleware/reflect/cross-group-link.d.ts.map +1 -0
- package/dist/middleware/reflect/cross-group-link.js +212 -0
- package/dist/middleware/reflect/cross-group-link.js.map +1 -0
- package/dist/middleware/reflect/dedup-by-source-and-value.d.ts +70 -0
- package/dist/middleware/reflect/dedup-by-source-and-value.d.ts.map +1 -0
- package/dist/middleware/reflect/dedup-by-source-and-value.js +0 -0
- package/dist/middleware/reflect/dedup-by-source-and-value.js.map +1 -0
- package/dist/middleware/reflect/describe-roots.d.ts +58 -0
- package/dist/middleware/reflect/describe-roots.d.ts.map +1 -0
- package/dist/middleware/reflect/describe-roots.js +266 -0
- package/dist/middleware/reflect/describe-roots.js.map +1 -0
- package/dist/middleware/reflect/flag-reviewer-startup.d.ts +16 -0
- package/dist/middleware/reflect/flag-reviewer-startup.d.ts.map +1 -0
- package/dist/middleware/reflect/flag-reviewer-startup.js +107 -0
- package/dist/middleware/reflect/flag-reviewer-startup.js.map +1 -0
- package/dist/middleware/reflect/flag-reviewer.d.ts +69 -0
- package/dist/middleware/reflect/flag-reviewer.d.ts.map +1 -0
- package/dist/middleware/reflect/flag-reviewer.js +520 -0
- package/dist/middleware/reflect/flag-reviewer.js.map +1 -0
- package/dist/middleware/reflect/inline-dedup.d.ts +26 -0
- package/dist/middleware/reflect/inline-dedup.d.ts.map +1 -0
- package/dist/middleware/reflect/inline-dedup.js +131 -0
- package/dist/middleware/reflect/inline-dedup.js.map +1 -0
- package/dist/middleware/reflect/justify-decisions.d.ts +37 -0
- package/dist/middleware/reflect/justify-decisions.d.ts.map +1 -0
- package/dist/middleware/reflect/justify-decisions.js +159 -0
- package/dist/middleware/reflect/justify-decisions.js.map +1 -0
- package/dist/middleware/reflect/nl-accept.d.ts +35 -0
- package/dist/middleware/reflect/nl-accept.d.ts.map +1 -0
- package/dist/middleware/reflect/nl-accept.js +167 -0
- package/dist/middleware/reflect/nl-accept.js.map +1 -0
- package/dist/middleware/reflect/pass0.d.ts +20 -0
- package/dist/middleware/reflect/pass0.d.ts.map +1 -0
- package/dist/middleware/reflect/pass0.js +423 -0
- package/dist/middleware/reflect/pass0.js.map +1 -0
- package/dist/middleware/reflect/pass1.d.ts +17 -0
- package/dist/middleware/reflect/pass1.d.ts.map +1 -0
- package/dist/middleware/reflect/pass1.js +241 -0
- package/dist/middleware/reflect/pass1.js.map +1 -0
- package/dist/middleware/reflect/pass2-quarantine.d.ts +129 -0
- package/dist/middleware/reflect/pass2-quarantine.d.ts.map +1 -0
- package/dist/middleware/reflect/pass2-quarantine.js +272 -0
- package/dist/middleware/reflect/pass2-quarantine.js.map +1 -0
- package/dist/middleware/reflect/pass2-seams.d.ts +205 -0
- package/dist/middleware/reflect/pass2-seams.d.ts.map +1 -0
- package/dist/middleware/reflect/pass2-seams.js +279 -0
- package/dist/middleware/reflect/pass2-seams.js.map +1 -0
- package/dist/middleware/reflect/pass2-split-orchestrator.d.ts +37 -0
- package/dist/middleware/reflect/pass2-split-orchestrator.d.ts.map +1 -0
- package/dist/middleware/reflect/pass2-split-orchestrator.js +531 -0
- package/dist/middleware/reflect/pass2-split-orchestrator.js.map +1 -0
- package/dist/middleware/reflect/pass2.d.ts +17 -0
- package/dist/middleware/reflect/pass2.d.ts.map +1 -0
- package/dist/middleware/reflect/pass2.js +324 -0
- package/dist/middleware/reflect/pass2.js.map +1 -0
- package/dist/middleware/reflect/pass2a.d.ts +141 -0
- package/dist/middleware/reflect/pass2a.d.ts.map +1 -0
- package/dist/middleware/reflect/pass2a.js +404 -0
- package/dist/middleware/reflect/pass2a.js.map +1 -0
- package/dist/middleware/reflect/pass2b.d.ts +108 -0
- package/dist/middleware/reflect/pass2b.d.ts.map +1 -0
- package/dist/middleware/reflect/pass2b.js +480 -0
- package/dist/middleware/reflect/pass2b.js.map +1 -0
- package/dist/middleware/reflect/pass2c.d.ts +113 -0
- package/dist/middleware/reflect/pass2c.d.ts.map +1 -0
- package/dist/middleware/reflect/pass2c.js +360 -0
- package/dist/middleware/reflect/pass2c.js.map +1 -0
- package/dist/middleware/reflect/pass3-batch.d.ts +62 -0
- package/dist/middleware/reflect/pass3-batch.d.ts.map +1 -0
- package/dist/middleware/reflect/pass3-batch.js +139 -0
- package/dist/middleware/reflect/pass3-batch.js.map +1 -0
- package/dist/middleware/reflect/pass3.d.ts +23 -0
- package/dist/middleware/reflect/pass3.d.ts.map +1 -0
- package/dist/middleware/reflect/pass3.js +371 -0
- package/dist/middleware/reflect/pass3.js.map +1 -0
- package/dist/middleware/reflect/pass4-slice.d.ts +25 -0
- package/dist/middleware/reflect/pass4-slice.d.ts.map +1 -0
- package/dist/middleware/reflect/pass4-slice.js +315 -0
- package/dist/middleware/reflect/pass4-slice.js.map +1 -0
- package/dist/middleware/reflect/pass4.d.ts +30 -0
- package/dist/middleware/reflect/pass4.d.ts.map +1 -0
- package/dist/middleware/reflect/pass4.js +193 -0
- package/dist/middleware/reflect/pass4.js.map +1 -0
- package/dist/middleware/reflect/pass5.d.ts +22 -0
- package/dist/middleware/reflect/pass5.d.ts.map +1 -0
- package/dist/middleware/reflect/pass5.js +178 -0
- package/dist/middleware/reflect/pass5.js.map +1 -0
- package/dist/middleware/reflect/pass_judge.d.ts +44 -0
- package/dist/middleware/reflect/pass_judge.d.ts.map +1 -0
- package/dist/middleware/reflect/pass_judge.js +263 -0
- package/dist/middleware/reflect/pass_judge.js.map +1 -0
- package/dist/middleware/reflect/pipeline-flags.d.ts +140 -0
- package/dist/middleware/reflect/pipeline-flags.d.ts.map +1 -0
- package/dist/middleware/reflect/pipeline-flags.js +314 -0
- package/dist/middleware/reflect/pipeline-flags.js.map +1 -0
- package/dist/middleware/reflect/pipeline.d.ts +237 -0
- package/dist/middleware/reflect/pipeline.d.ts.map +1 -0
- package/dist/middleware/reflect/pipeline.js +3114 -0
- package/dist/middleware/reflect/pipeline.js.map +1 -0
- package/dist/middleware/reflect/promptOverride.d.ts +14 -0
- package/dist/middleware/reflect/promptOverride.d.ts.map +1 -0
- package/dist/middleware/reflect/promptOverride.js +28 -0
- package/dist/middleware/reflect/promptOverride.js.map +1 -0
- package/dist/middleware/reflect/provenance-check.d.ts +48 -0
- package/dist/middleware/reflect/provenance-check.d.ts.map +1 -0
- package/dist/middleware/reflect/provenance-check.js +180 -0
- package/dist/middleware/reflect/provenance-check.js.map +1 -0
- package/dist/middleware/reflect/provenance-reviewer.d.ts +52 -0
- package/dist/middleware/reflect/provenance-reviewer.d.ts.map +1 -0
- package/dist/middleware/reflect/provenance-reviewer.js +253 -0
- package/dist/middleware/reflect/provenance-reviewer.js.map +1 -0
- package/dist/middleware/reflect/prune-collapsed-types.d.ts +11 -0
- package/dist/middleware/reflect/prune-collapsed-types.d.ts.map +1 -0
- package/dist/middleware/reflect/prune-collapsed-types.js +32 -0
- package/dist/middleware/reflect/prune-collapsed-types.js.map +1 -0
- package/dist/middleware/reflect/recognize-root.d.ts +75 -0
- package/dist/middleware/reflect/recognize-root.d.ts.map +1 -0
- package/dist/middleware/reflect/recognize-root.js +204 -0
- package/dist/middleware/reflect/recognize-root.js.map +1 -0
- package/dist/middleware/reflect/render-agent-flag.d.ts +25 -0
- package/dist/middleware/reflect/render-agent-flag.d.ts.map +1 -0
- package/dist/middleware/reflect/render-agent-flag.js +39 -0
- package/dist/middleware/reflect/render-agent-flag.js.map +1 -0
- package/dist/middleware/reflect/retrieve-graph-slice.d.ts +54 -0
- package/dist/middleware/reflect/retrieve-graph-slice.d.ts.map +1 -0
- package/dist/middleware/reflect/retrieve-graph-slice.js +173 -0
- package/dist/middleware/reflect/retrieve-graph-slice.js.map +1 -0
- package/dist/middleware/reflect/root-relatedness.d.ts +31 -0
- package/dist/middleware/reflect/root-relatedness.d.ts.map +1 -0
- package/dist/middleware/reflect/root-relatedness.js +92 -0
- package/dist/middleware/reflect/root-relatedness.js.map +1 -0
- package/dist/middleware/reflect/schema-heal.d.ts +22 -0
- package/dist/middleware/reflect/schema-heal.d.ts.map +1 -0
- package/dist/middleware/reflect/schema-heal.js +119 -0
- package/dist/middleware/reflect/schema-heal.js.map +1 -0
- package/dist/middleware/reflect/schema-validator.d.ts +85 -0
- package/dist/middleware/reflect/schema-validator.d.ts.map +1 -0
- package/dist/middleware/reflect/schema-validator.js +196 -0
- package/dist/middleware/reflect/schema-validator.js.map +1 -0
- package/dist/middleware/reflect/stage-audit-graph.d.ts +115 -0
- package/dist/middleware/reflect/stage-audit-graph.d.ts.map +1 -0
- package/dist/middleware/reflect/stage-audit-graph.js +563 -0
- package/dist/middleware/reflect/stage-audit-graph.js.map +1 -0
- package/dist/middleware/reflect/stage-d-resolve-graph.d.ts +87 -0
- package/dist/middleware/reflect/stage-d-resolve-graph.d.ts.map +1 -0
- package/dist/middleware/reflect/stage-d-resolve-graph.js +256 -0
- package/dist/middleware/reflect/stage-d-resolve-graph.js.map +1 -0
- package/dist/middleware/reflect/synthesizeFromSceneCard.d.ts +15 -0
- package/dist/middleware/reflect/synthesizeFromSceneCard.d.ts.map +1 -0
- package/dist/middleware/reflect/synthesizeFromSceneCard.js +91 -0
- package/dist/middleware/reflect/synthesizeFromSceneCard.js.map +1 -0
- package/dist/middleware/reflect/types.d.ts +261 -0
- package/dist/middleware/reflect/types.d.ts.map +1 -0
- package/dist/middleware/reflect/types.js +3 -0
- package/dist/middleware/reflect/types.js.map +1 -0
- package/dist/middleware/reflect/v2-integrate.d.ts +120 -0
- package/dist/middleware/reflect/v2-integrate.d.ts.map +1 -0
- package/dist/middleware/reflect/v2-integrate.js +388 -0
- package/dist/middleware/reflect/v2-integrate.js.map +1 -0
- package/dist/middleware/reflect/v2-judge.d.ts +44 -0
- package/dist/middleware/reflect/v2-judge.d.ts.map +1 -0
- package/dist/middleware/reflect/v2-judge.js +191 -0
- package/dist/middleware/reflect/v2-judge.js.map +1 -0
- package/dist/relation-sets.d.ts +2 -0
- package/dist/relation-sets.d.ts.map +1 -0
- package/dist/relation-sets.js +35 -0
- package/dist/relation-sets.js.map +1 -0
- package/dist/routes/__tests__/flags.test.d.ts +2 -0
- package/dist/routes/__tests__/flags.test.d.ts.map +1 -0
- package/dist/routes/__tests__/flags.test.js +257 -0
- package/dist/routes/__tests__/flags.test.js.map +1 -0
- package/dist/routes/__tests__/models-catalog.test.d.ts +2 -0
- package/dist/routes/__tests__/models-catalog.test.d.ts.map +1 -0
- package/dist/routes/__tests__/models-catalog.test.js +130 -0
- package/dist/routes/__tests__/models-catalog.test.js.map +1 -0
- package/dist/routes/__tests__/reflect-pause-drain.test.d.ts +2 -0
- package/dist/routes/__tests__/reflect-pause-drain.test.d.ts.map +1 -0
- package/dist/routes/__tests__/reflect-pause-drain.test.js +38 -0
- package/dist/routes/__tests__/reflect-pause-drain.test.js.map +1 -0
- package/dist/routes/__tests__/spend-pause-drain.test.d.ts +2 -0
- package/dist/routes/__tests__/spend-pause-drain.test.d.ts.map +1 -0
- package/dist/routes/__tests__/spend-pause-drain.test.js +38 -0
- package/dist/routes/__tests__/spend-pause-drain.test.js.map +1 -0
- package/dist/routes/admin.d.ts +49 -0
- package/dist/routes/admin.d.ts.map +1 -0
- package/dist/routes/admin.js +471 -0
- package/dist/routes/admin.js.map +1 -0
- package/dist/routes/blocks.d.ts +4 -0
- package/dist/routes/blocks.d.ts.map +1 -0
- package/dist/routes/blocks.js +893 -0
- package/dist/routes/blocks.js.map +1 -0
- package/dist/routes/chat-proxy.d.ts +5 -0
- package/dist/routes/chat-proxy.d.ts.map +1 -0
- package/dist/routes/chat-proxy.js +225 -0
- package/dist/routes/chat-proxy.js.map +1 -0
- package/dist/routes/conversations.d.ts +4 -0
- package/dist/routes/conversations.d.ts.map +1 -0
- package/dist/routes/conversations.js +139 -0
- package/dist/routes/conversations.js.map +1 -0
- package/dist/routes/flags.d.ts +4 -0
- package/dist/routes/flags.d.ts.map +1 -0
- package/dist/routes/flags.js +151 -0
- package/dist/routes/flags.js.map +1 -0
- package/dist/routes/inject.d.ts +4 -0
- package/dist/routes/inject.d.ts.map +1 -0
- package/dist/routes/inject.js +183 -0
- package/dist/routes/inject.js.map +1 -0
- package/dist/routes/mcp-http.d.ts +5 -0
- package/dist/routes/mcp-http.d.ts.map +1 -0
- package/dist/routes/mcp-http.js +94 -0
- package/dist/routes/mcp-http.js.map +1 -0
- package/dist/routes/quarantine.d.ts +4 -0
- package/dist/routes/quarantine.d.ts.map +1 -0
- package/dist/routes/quarantine.js +66 -0
- package/dist/routes/quarantine.js.map +1 -0
- package/dist/routes/recall.d.ts +5 -0
- package/dist/routes/recall.d.ts.map +1 -0
- package/dist/routes/recall.js +573 -0
- package/dist/routes/recall.js.map +1 -0
- package/dist/routes/reflect.d.ts +5 -0
- package/dist/routes/reflect.d.ts.map +1 -0
- package/dist/routes/reflect.js +231 -0
- package/dist/routes/reflect.js.map +1 -0
- package/dist/routes/session.d.ts +4 -0
- package/dist/routes/session.d.ts.map +1 -0
- package/dist/routes/session.js +418 -0
- package/dist/routes/session.js.map +1 -0
- package/dist/routes/state.d.ts +116 -0
- package/dist/routes/state.d.ts.map +1 -0
- package/dist/routes/state.js +621 -0
- package/dist/routes/state.js.map +1 -0
- package/dist/routes/usage.d.ts +3 -0
- package/dist/routes/usage.d.ts.map +1 -0
- package/dist/routes/usage.js +141 -0
- package/dist/routes/usage.js.map +1 -0
- package/dist/routes/workspace.d.ts +5 -0
- package/dist/routes/workspace.d.ts.map +1 -0
- package/dist/routes/workspace.js +435 -0
- package/dist/routes/workspace.js.map +1 -0
- package/dist/server.d.ts +13 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +298 -0
- package/dist/server.js.map +1 -0
- package/dist/store/__tests__/backup.test.d.ts +2 -0
- package/dist/store/__tests__/backup.test.d.ts.map +1 -0
- package/dist/store/__tests__/backup.test.js +53 -0
- package/dist/store/__tests__/backup.test.js.map +1 -0
- package/dist/store/__tests__/quality.test.d.ts +2 -0
- package/dist/store/__tests__/quality.test.d.ts.map +1 -0
- package/dist/store/__tests__/quality.test.js +75 -0
- package/dist/store/__tests__/quality.test.js.map +1 -0
- package/dist/store/backup.d.ts +14 -0
- package/dist/store/backup.d.ts.map +1 -0
- package/dist/store/backup.js +95 -0
- package/dist/store/backup.js.map +1 -0
- package/dist/store/database.d.ts +407 -0
- package/dist/store/database.d.ts.map +1 -0
- package/dist/store/database.js +2004 -0
- package/dist/store/database.js.map +1 -0
- package/dist/store/quality.d.ts +25 -0
- package/dist/store/quality.d.ts.map +1 -0
- package/dist/store/quality.js +48 -0
- package/dist/store/quality.js.map +1 -0
- package/dist/tools/__tests__/assemble-block-chains.test.d.ts +2 -0
- package/dist/tools/__tests__/assemble-block-chains.test.d.ts.map +1 -0
- package/dist/tools/__tests__/assemble-block-chains.test.js +118 -0
- package/dist/tools/__tests__/assemble-block-chains.test.js.map +1 -0
- package/dist/tools/__tests__/filter-roots-by-concepts.test.d.ts +2 -0
- package/dist/tools/__tests__/filter-roots-by-concepts.test.d.ts.map +1 -0
- package/dist/tools/__tests__/filter-roots-by-concepts.test.js +68 -0
- package/dist/tools/__tests__/filter-roots-by-concepts.test.js.map +1 -0
- package/dist/tools/__tests__/flag-surface.test.d.ts +2 -0
- package/dist/tools/__tests__/flag-surface.test.d.ts.map +1 -0
- package/dist/tools/__tests__/flag-surface.test.js +130 -0
- package/dist/tools/__tests__/flag-surface.test.js.map +1 -0
- package/dist/tools/core.d.ts +5 -0
- package/dist/tools/core.d.ts.map +1 -0
- package/dist/tools/core.js +962 -0
- package/dist/tools/core.js.map +1 -0
- package/dist/tools/derive.d.ts +5 -0
- package/dist/tools/derive.d.ts.map +1 -0
- package/dist/tools/derive.js +182 -0
- package/dist/tools/derive.js.map +1 -0
- package/dist/tools/flag-surface.d.ts +26 -0
- package/dist/tools/flag-surface.d.ts.map +1 -0
- package/dist/tools/flag-surface.js +59 -0
- package/dist/tools/flag-surface.js.map +1 -0
- package/dist/tools/helpers.d.ts +99 -0
- package/dist/tools/helpers.d.ts.map +1 -0
- package/dist/tools/helpers.js +243 -0
- package/dist/tools/helpers.js.map +1 -0
- package/dist/tools/projects.d.ts +5 -0
- package/dist/tools/projects.d.ts.map +1 -0
- package/dist/tools/projects.js +175 -0
- package/dist/tools/projects.js.map +1 -0
- package/dist/tools/system.d.ts +5 -0
- package/dist/tools/system.d.ts.map +1 -0
- package/dist/tools/system.js +1361 -0
- package/dist/tools/system.js.map +1 -0
- package/dist/tools/tasks.d.ts +5 -0
- package/dist/tools/tasks.d.ts.map +1 -0
- package/dist/tools/tasks.js +289 -0
- package/dist/tools/tasks.js.map +1 -0
- package/package.json +69 -0
- package/scripts/nodedex-entry.mjs +396 -0
- package/tui-dist/App.js +185 -0
- package/tui-dist/api.js +197 -0
- package/tui-dist/cli.js +53 -0
- package/tui-dist/components.js +63 -0
- package/tui-dist/config.js +242 -0
- package/tui-dist/connect-snippets.js +98 -0
- package/tui-dist/feed.js +51 -0
- package/tui-dist/health.js +465 -0
- package/tui-dist/hooks.js +23 -0
- package/tui-dist/memory.js +220 -0
- package/tui-dist/onboarding.js +498 -0
- package/tui-dist/review.js +193 -0
- package/tui-dist/servers.js +556 -0
- package/tui-dist/smoke.js +15 -0
- package/tui-dist/theme.js +106 -0
|
@@ -0,0 +1,706 @@
|
|
|
1
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
2
|
+
// PIPELINE v2 (TRANSFORM) — COMPREHEND fragment: schema + SEAM 1 + converter
|
|
3
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
4
|
+
//
|
|
5
|
+
// Design: docs/PIPELINE-TRANSFORM-DESIGN.md + docs/PIPELINE-V2-MOVING-PARTS.md.
|
|
6
|
+
//
|
|
7
|
+
// This is build STEP 2 (the schema foundation). $0 / no LLM. Default-OFF
|
|
8
|
+
// (NODEDEX_PIPELINE_V2). NOTHING here is wired into the live pipeline yet — it is
|
|
9
|
+
// the contract + the deterministic code that proves the fragment maps onto the
|
|
10
|
+
// EXISTING machinery (so LLM 2 / WRITE reuse is real, not aspirational).
|
|
11
|
+
//
|
|
12
|
+
// WHAT COMPREHEND (LLM 1, built in step 3) will emit:
|
|
13
|
+
// one holistic read of an arc → topic GROUPS → typed schema blocks + the
|
|
14
|
+
// within-group causal links it READ from the prose + a provenance excerpt per
|
|
15
|
+
// block + PROVISIONAL names. It replaces Pass 0+1+JUDGE+2a+2b+2c and kills Pass
|
|
16
|
+
// 2c's O(n²) (links are read, not pair-compared).
|
|
17
|
+
//
|
|
18
|
+
// THE BRIDGE (this file): `comprehendResultToPass2Items` flattens the grouped
|
|
19
|
+
// fragment into Pass2Item[] — the exact shape Pass 3 / resolve / dedup / WRITE
|
|
20
|
+
// already consume. The within-group links distribute onto Pass2Item's existing
|
|
21
|
+
// causal fields (triggered_by_items / based_on_items / extends_item / relations).
|
|
22
|
+
// So the v2 producer feeds the v1 consumer: swap the engine, not the car.
|
|
23
|
+
//
|
|
24
|
+
// MEANING-FIRST reuse (not a parallel vocabulary):
|
|
25
|
+
// - types + unique{} field shape ← schema-validator.ts (TYPE_UNIQUE_SCHEMA /
|
|
26
|
+
// validateUniqueSchema) — the SAME source of truth Pass 2/save use.
|
|
27
|
+
// - link relation types ← the subset of pipeline.ts ALLOWED_RELS a holistic
|
|
28
|
+
// READ produces (see COMPREHEND_LINK_RELS).
|
|
29
|
+
// - block shape ← Pass2Item (types.ts).
|
|
30
|
+
//
|
|
31
|
+
// NAMING IS PROVISIONAL ONLY here. Canonical strict labels + project-root
|
|
32
|
+
// resolution happen in LLM 2 (INTEGRATE), AFTER resolve — naming-before-resolve
|
|
33
|
+
// is the root-fork bug (recognizer design, Insight 2).
|
|
34
|
+
import { TYPE_UNIQUE_SCHEMA, validateUniqueSchema } from "./schema-validator.js";
|
|
35
|
+
import { getThinkingBudget, modelOverride, intFromEnv } from "./config.js";
|
|
36
|
+
// ─── Flag gate ──────────────────────────────────────────────────────────────
|
|
37
|
+
// Default OFF. Mirrors recognizerEnabled() ("1" convention). The current
|
|
38
|
+
// pipeline stays the default until the A/B (§12) earns a flip.
|
|
39
|
+
export function pipelineV2Enabled() {
|
|
40
|
+
// ⚠ OLD v1 PIPELINE — DO NOT TURN ON. v2 (COMPREHEND / transform) is the ONLY
|
|
41
|
+
// extraction engine in this release. The v1 front-half (pass2a / pass2c /
|
|
42
|
+
// pass_judge / split-orchestrator / seams / quarantine / synthesizeFromSceneCard)
|
|
43
|
+
// is RETIRED — kept in-tree for reference only, never executed. The
|
|
44
|
+
// NODEDEX_PIPELINE_V2 env var is now INERT: there is no off-switch back to v1.
|
|
45
|
+
// (Pre-release, =0 ran the v1 front-half as the primary engine; that path is
|
|
46
|
+
// intentionally unreachable now.)
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
/** Bounded inline retry budget for the v2 ARC path — applied at BOTH failure sites:
|
|
50
|
+
* the front-half (COMPREHEND failed / SEAM-1 invalid / threw) AND the back-half
|
|
51
|
+
* (Pass 3 returned a re-queue checkpoint = items dropped). On exhaustion the arc
|
|
52
|
+
* FAILS CLEAN: turns are left re-extractable (never marked extracted with unsaved
|
|
53
|
+
* residue) and — v2-only — it NEVER auto-falls to v1. A fresh COMPREHEND / a
|
|
54
|
+
* resume-from-pass3 re-run recovers LLM-variance failures; the cap stops a
|
|
55
|
+
* deterministic fault from looping. Default 2 (→ up to 3 attempts total); set 0 to
|
|
56
|
+
* fail clean on the first failure. NODEDEX_ARC_MAX_RETRIES. */
|
|
57
|
+
export function arcMaxRetries() {
|
|
58
|
+
return intFromEnv("NODEDEX_ARC_MAX_RETRIES", 2, 0);
|
|
59
|
+
}
|
|
60
|
+
// Gap (cost): v2-aware LAZY CAPTURE. The v2 arc engine re-reads the RAW transcript
|
|
61
|
+
// and IGNORES the per-turn pass01 items, so running Pass 0-1 at capture is pure
|
|
62
|
+
// waste in v2 mode (~25% of an arc's spend). When ON, the per-turn capture stores
|
|
63
|
+
// the raw transcript + marks the turn arc-ready WITHOUT running Pass 0-1. If v2
|
|
64
|
+
// later fails at arc, the v1 fallback fills Pass 0-1 lazily from the raw transcript
|
|
65
|
+
// (so the safety net is preserved — the cost just moves to the rare failure path).
|
|
66
|
+
// Default ON (promoted 2026-06-14 — validated ~42% capture-cost win); set =0 to opt out.
|
|
67
|
+
// Only meaningful when v2 is the engine.
|
|
68
|
+
export function v2LazyCaptureEnabled() {
|
|
69
|
+
return process.env.NODEDEX_V2_LAZY_CAPTURE !== "0";
|
|
70
|
+
}
|
|
71
|
+
// ─── Within-group link relations COMPREHEND may emit ──────────────────────────
|
|
72
|
+
// The subset of pipeline.ts ALLOWED_RELS that a holistic READ of the prose
|
|
73
|
+
// produces. EXCLUDES: superseded_by (auto-inverse, written at WRITE), part_of /
|
|
74
|
+
// member_of (structural containment / clustering, not the causal thread — wired
|
|
75
|
+
// at WRITE from project resolution + groups).
|
|
76
|
+
// ⚠ KEEP IN SYNC with ALLOWED_RELS in pipeline.ts (it is duplicated inline there,
|
|
77
|
+
// not exported; if that set changes, change this).
|
|
78
|
+
export const COMPREHEND_LINK_RELS = new Set([
|
|
79
|
+
"prompted_by", // consequence → trigger → Pass2Item.triggered_by_items[]
|
|
80
|
+
"based_on", // conclusion → evidence → Pass2Item.based_on_items[]
|
|
81
|
+
"extends", // specific → broader → Pass2Item.extends_item (single)
|
|
82
|
+
"supersedes", // new → old → Pass2Item.supersedes_ref (single)
|
|
83
|
+
"resolves", // answer → question → Pass2Item.resolved_ref (single)
|
|
84
|
+
"supports", // fact → hypothesis → Pass2Item.relations[]
|
|
85
|
+
"contradicts", // A ↔ B → Pass2Item.relations[]
|
|
86
|
+
"related_to", // A ↔ B → Pass2Item.relations[]
|
|
87
|
+
"derived_from", // derived → source → Pass2Item.relations[]
|
|
88
|
+
"affects", // agent → patient (x-proj)→ Pass2Item.relations[]
|
|
89
|
+
]);
|
|
90
|
+
export function validateComprehendResult(result) {
|
|
91
|
+
const errors = [];
|
|
92
|
+
const warnings = [];
|
|
93
|
+
const err = (message, group_id, local_id) => errors.push({ severity: "error", message, group_id, local_id });
|
|
94
|
+
const warn = (message, group_id, local_id) => warnings.push({ severity: "warning", message, group_id, local_id });
|
|
95
|
+
const r = result;
|
|
96
|
+
if (!r || typeof r !== "object" || !Array.isArray(r.groups)) {
|
|
97
|
+
err("result.groups is missing or not an array");
|
|
98
|
+
return { valid: false, errors, warnings };
|
|
99
|
+
}
|
|
100
|
+
// Legitimately empty = the session had no residue worth saving. VALID → the
|
|
101
|
+
// pipeline saves nothing (not an error, not a retry). Distinct from malformed
|
|
102
|
+
// above. A real outcome of the worth gate (e.g. pure debugging chatter — the
|
|
103
|
+
// noise trap that produced the old 87-job junk).
|
|
104
|
+
if (r.groups.length === 0)
|
|
105
|
+
return { valid: true, errors, warnings };
|
|
106
|
+
// local_ids are GROUP-SCOPED — the LLM numbers blocks per group (block_1, block_2,
|
|
107
|
+
// … restart in each group). So uniqueness + link resolution are checked WITHIN
|
|
108
|
+
// each group; within_group_links only reference blocks of their own group (a
|
|
109
|
+
// reference to another group's block = not a within-group link → LLM 2's job, and
|
|
110
|
+
// surfaces here as "no block in this group"). The converter qualifies ids by
|
|
111
|
+
// group to make them globally unique downstream.
|
|
112
|
+
for (const group of r.groups) {
|
|
113
|
+
const gid = group?.group_id;
|
|
114
|
+
if (!gid)
|
|
115
|
+
err("group missing group_id");
|
|
116
|
+
if (!Array.isArray(group?.blocks)) {
|
|
117
|
+
err("group missing blocks[]", gid);
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
const idsInGroup = new Set();
|
|
121
|
+
const decisionIds = new Set();
|
|
122
|
+
for (const b of group.blocks) {
|
|
123
|
+
const lid = b?.local_id;
|
|
124
|
+
if (!lid) {
|
|
125
|
+
err("block missing local_id", gid);
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
if (idsInGroup.has(lid))
|
|
129
|
+
err(`duplicate local_id "${lid}" within group`, gid, lid);
|
|
130
|
+
idsInGroup.add(lid);
|
|
131
|
+
if (!b.type) {
|
|
132
|
+
err("block missing type", gid, lid);
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
if (b.type === "decision")
|
|
136
|
+
decisionIds.add(lid);
|
|
137
|
+
// Unknown type with no schema{} → warning (novel types are trusted IF
|
|
138
|
+
// they declare schema{}, exactly like schema-validator.ts).
|
|
139
|
+
if (!(b.type in TYPE_UNIQUE_SCHEMA) && !b.schema) {
|
|
140
|
+
warn(`unknown type "${b.type}" without schema{}`, gid, lid);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
if (!b.provenance || !b.provenance.trim()) {
|
|
144
|
+
err("block missing provenance excerpt", gid, lid); // HARD — anti-confab key
|
|
145
|
+
}
|
|
146
|
+
if (!b.essence || !b.essence.trim()) {
|
|
147
|
+
warn("block missing essence", gid, lid);
|
|
148
|
+
}
|
|
149
|
+
// unique{} key-set shape — SOFT (reuse the save-time validator)
|
|
150
|
+
const chk = validateUniqueSchema(b.type, b.unique);
|
|
151
|
+
if (!chk.ok)
|
|
152
|
+
warn(`unique{} ${chk.detail}`, gid, lid);
|
|
153
|
+
}
|
|
154
|
+
// Links resolve WITHIN this group. ALL link defects are warnings — every one
|
|
155
|
+
// is dropped at convert (the converter skips unresolvable/unknown links), and
|
|
156
|
+
// a dropped link is repairable downstream; a degraded arc is not (see the seam
|
|
157
|
+
// header). A dangling endpoint usually means the LLM renamed a block it DID
|
|
158
|
+
// emit (it recalls the meaning, not the exact id) — the blocks are fine.
|
|
159
|
+
const links = Array.isArray(group?.within_group_links) ? group.within_group_links : [];
|
|
160
|
+
const hasBasedOnFrom = new Set();
|
|
161
|
+
for (const link of links) {
|
|
162
|
+
if (!COMPREHEND_LINK_RELS.has(link?.type)) {
|
|
163
|
+
warn(`link with unknown/unsupported relation "${link?.type}" (dropped at convert)`, gid);
|
|
164
|
+
}
|
|
165
|
+
if (!idsInGroup.has(link?.from))
|
|
166
|
+
warn(`link.from "${link?.from}" references no block in this group (dropped at convert)`, gid);
|
|
167
|
+
if (!idsInGroup.has(link?.to))
|
|
168
|
+
warn(`link.to "${link?.to}" references no block in this group (dropped at convert)`, gid);
|
|
169
|
+
// Only a link that will actually SURVIVE convert satisfies the decision's
|
|
170
|
+
// based_on requirement — a dangling one is dropped, leaving the decision
|
|
171
|
+
// unwired, which the warning below must report truthfully (JUSTIFY's
|
|
172
|
+
// detect step then finds the genuinely-empty based_on and repairs it).
|
|
173
|
+
if (link?.type === "based_on" && link?.from && idsInGroup.has(link?.to))
|
|
174
|
+
hasBasedOnFrom.add(link.from);
|
|
175
|
+
}
|
|
176
|
+
// decision must be justified by ≥1 based_on (block-types.md:54). SOFT: if the
|
|
177
|
+
// evidence isn't in the transcript that's a flag, not a fabrication.
|
|
178
|
+
for (const did of decisionIds) {
|
|
179
|
+
if (!hasBasedOnFrom.has(did)) {
|
|
180
|
+
warn("decision has no based_on link (block-types.md requires one)", gid, did);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return { valid: errors.length === 0, errors, warnings };
|
|
185
|
+
}
|
|
186
|
+
/** Bucket COMPREHEND validation WARNINGS for a quieter, honest log line. Most fire on
|
|
187
|
+
* the raw draft and are REPAIRED DOWNSTREAM — unique{} shape by Pass 2b fill, dangling
|
|
188
|
+
* within-group links dropped at convert, a decision's missing based_on by JUSTIFY — so
|
|
189
|
+
* counting them raw made a clean arc look alarming ("warnings=35"). `notable` is the few
|
|
190
|
+
* worth a glance (missing essence, unknown type, a group with no topic/root). Pure. */
|
|
191
|
+
export function summarizeWarnings(warnings) {
|
|
192
|
+
let draft = 0;
|
|
193
|
+
let notable = 0;
|
|
194
|
+
for (const w of warnings ?? []) {
|
|
195
|
+
const m = w?.message ?? "";
|
|
196
|
+
if (m.includes("unique{}") || m.includes("link") || m.includes("based_on"))
|
|
197
|
+
draft++;
|
|
198
|
+
else
|
|
199
|
+
notable++;
|
|
200
|
+
}
|
|
201
|
+
return `${notable} notable` + (draft ? `, ${draft} draft (repaired downstream)` : "");
|
|
202
|
+
}
|
|
203
|
+
/** Group-scoped local_id → a globally-unique Pass2Item id. The LLM numbers
|
|
204
|
+
* blocks per group (block_1 in every group), so we namespace by group. */
|
|
205
|
+
function qualifyId(groupId, localId) {
|
|
206
|
+
return `${groupId}::${localId}`;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Distribute ONE link onto the SOURCE item's existing causal field by relation
|
|
210
|
+
* type — the single source of truth for the link→field mapping. Used by the
|
|
211
|
+
* within-group converter AND the cross-group linker (cross-group-link.ts) so they
|
|
212
|
+
* never drift on which field a relation lands in. Caller must pre-validate that
|
|
213
|
+
* `type` ∈ COMPREHEND_LINK_RELS and that `toId` resolves to a real item.
|
|
214
|
+
*/
|
|
215
|
+
export function applyLinkToPass2Item(from, type, toId, reasoning) {
|
|
216
|
+
switch (type) {
|
|
217
|
+
case "prompted_by":
|
|
218
|
+
from.triggered_by_items.push(toId);
|
|
219
|
+
break;
|
|
220
|
+
case "based_on":
|
|
221
|
+
from.based_on_items.push(toId);
|
|
222
|
+
break;
|
|
223
|
+
case "extends":
|
|
224
|
+
from.extends_item = toId;
|
|
225
|
+
break; // single; last wins
|
|
226
|
+
case "supersedes":
|
|
227
|
+
from.supersedes_ref = toId;
|
|
228
|
+
break;
|
|
229
|
+
case "resolves":
|
|
230
|
+
from.resolved_ref = toId;
|
|
231
|
+
break;
|
|
232
|
+
default: // supports / contradicts / related_to / derived_from / affects
|
|
233
|
+
(from.relations ??= []).push({ type, target: toId, reasoning });
|
|
234
|
+
break;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* A project name is a single label DIMENSION ({project}_{entity}_{type}_{concept}),
|
|
239
|
+
* so it MUST be hyphens-only — an underscore would fake a dimension boundary and
|
|
240
|
+
* make Pass 3 fork a DUPLICATE root (the hyphenated project_creates root vs the
|
|
241
|
+
* verbatim underscore block label). COMPREHEND occasionally emits underscores
|
|
242
|
+
* (e.g. "backend_api_service"); the other passes enforce hyphens via a PROMPT
|
|
243
|
+
* instruction (pass0/pass3), which COMPREHEND doesn't carry — so we enforce it
|
|
244
|
+
* deterministically here, where item.project is born. Lossless for already-valid
|
|
245
|
+
* names; undefined in → undefined out (no project). (Run 9 big-arc bug.)
|
|
246
|
+
*/
|
|
247
|
+
export function normalizeProjectName(p) {
|
|
248
|
+
if (!p)
|
|
249
|
+
return undefined;
|
|
250
|
+
const out = p.trim().toLowerCase()
|
|
251
|
+
.replace(/[\s_]+/g, "-") // underscores + whitespace → hyphen (the dimension rule)
|
|
252
|
+
.replace(/[^a-z0-9-]/g, "") // strip anything not lowercase-alnum-hyphen
|
|
253
|
+
.replace(/-+/g, "-") // collapse repeats
|
|
254
|
+
.replace(/^-|-$/g, ""); // trim edge hyphens
|
|
255
|
+
return out.length > 0 ? out : undefined;
|
|
256
|
+
}
|
|
257
|
+
/** The most common normalized provisional_project across an arc's groups — the arc's
|
|
258
|
+
* ROOT to inherit when an individual group's guess is missing. Groups in one arc
|
|
259
|
+
* usually belong to ONE root, so inheriting the dominant guess keeps clusters together
|
|
260
|
+
* rather than fragmenting (each empty group otherwise becoming its own topic-named
|
|
261
|
+
* root). undefined only when NO group named a project. Pure / testable. */
|
|
262
|
+
export function dominantProvisionalProject(groups) {
|
|
263
|
+
const counts = new Map();
|
|
264
|
+
for (const g of groups ?? []) {
|
|
265
|
+
const p = normalizeProjectName(g.provisional_project);
|
|
266
|
+
if (p)
|
|
267
|
+
counts.set(p, (counts.get(p) ?? 0) + 1);
|
|
268
|
+
}
|
|
269
|
+
let best;
|
|
270
|
+
let bestN = 0;
|
|
271
|
+
for (const [p, n] of counts)
|
|
272
|
+
if (n > bestN) {
|
|
273
|
+
best = p;
|
|
274
|
+
bestN = n;
|
|
275
|
+
}
|
|
276
|
+
return best;
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Flatten the grouped fragment into Pass2Item[], distributing each within-group
|
|
280
|
+
* link onto the SOURCE item's existing causal field by relation type. local_ids
|
|
281
|
+
* are GROUP-SCOPED → qualified to `{group_id}::{local_id}` for global uniqueness;
|
|
282
|
+
* links resolve within their own group. Pure + defensive: skips links whose
|
|
283
|
+
* endpoints don't resolve (the validator reports those as errors; the converter
|
|
284
|
+
* must not throw on them).
|
|
285
|
+
*
|
|
286
|
+
* NOTE: `project` is set to the group's PROVISIONAL project. LLM 2 / the
|
|
287
|
+
* recognizer overrides it with the canonical root before WRITE.
|
|
288
|
+
*/
|
|
289
|
+
export function comprehendResultToPass2Items(result) {
|
|
290
|
+
const items = [];
|
|
291
|
+
const groupByItemId = {};
|
|
292
|
+
const itemById = new Map();
|
|
293
|
+
// item.project is BORN here from the GUESS (provisional_project). The holistic
|
|
294
|
+
// COMPREHEND schema once made that guess OPTIONAL, so it could arrive empty — and an
|
|
295
|
+
// undefined item.project starves the recognizer (newRootCandidateNames skips
|
|
296
|
+
// undef-project items) AND leaves Pass 3 to coin a placeholder root (the "group_1"
|
|
297
|
+
// regression, 2026-06-14). Guarantee a real name: the group's own guess, else the
|
|
298
|
+
// arc's DOMINANT guess (groups in one arc usually share a root — keeps "one root,
|
|
299
|
+
// many clusters" instead of fragmenting on topic), else the group's topic. Only
|
|
300
|
+
// undefined when the arc named nothing at all.
|
|
301
|
+
const arcRoot = dominantProvisionalProject(result.groups ?? []);
|
|
302
|
+
for (const group of result.groups ?? []) {
|
|
303
|
+
const gid = group.group_id;
|
|
304
|
+
const groupProject = normalizeProjectName(group.provisional_project) ?? arcRoot ?? normalizeProjectName(group.topic);
|
|
305
|
+
for (const b of group.blocks ?? []) {
|
|
306
|
+
const id = qualifyId(gid, b.local_id);
|
|
307
|
+
const item = {
|
|
308
|
+
id,
|
|
309
|
+
text: b.essence ?? "",
|
|
310
|
+
type: b.type,
|
|
311
|
+
project: groupProject,
|
|
312
|
+
unique: b.unique,
|
|
313
|
+
schema: b.schema,
|
|
314
|
+
excerpt: b.provenance,
|
|
315
|
+
triggered_by_items: [],
|
|
316
|
+
based_on_items: [],
|
|
317
|
+
relations: [],
|
|
318
|
+
// Observability: the LLM's own worth + typing rationale MUST survive to the
|
|
319
|
+
// turn-log (charter rule 8 — diagnose from reasoning). Dropped here before
|
|
320
|
+
// 2026-06-12 → per-turn v2 logs had no auditable reasoning. Pass 3 strips
|
|
321
|
+
// these from its prompt copy, so they never reach a downstream LLM.
|
|
322
|
+
keep_reason: b.keep_reason,
|
|
323
|
+
type_reasoning: b.type_reasoning,
|
|
324
|
+
};
|
|
325
|
+
if (b.uncertain)
|
|
326
|
+
item.review_reason = "comprehend_uncertain";
|
|
327
|
+
items.push(item);
|
|
328
|
+
itemById.set(id, item);
|
|
329
|
+
groupByItemId[id] = gid;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
for (const group of result.groups ?? []) {
|
|
333
|
+
const gid = group.group_id;
|
|
334
|
+
for (const link of group.within_group_links ?? []) {
|
|
335
|
+
// Drop links the model mis-typed (a relation outside COMPREHEND_LINK_RELS —
|
|
336
|
+
// usually a unique{} field name). SEAM 1 warns; the info lives in the block's
|
|
337
|
+
// own field. Dropping here keeps junk relations out of the graph.
|
|
338
|
+
if (!COMPREHEND_LINK_RELS.has(link.type))
|
|
339
|
+
continue;
|
|
340
|
+
const fromId = qualifyId(gid, link.from);
|
|
341
|
+
const toId = qualifyId(gid, link.to);
|
|
342
|
+
const from = itemById.get(fromId);
|
|
343
|
+
if (!from || !itemById.has(toId))
|
|
344
|
+
continue; // the designed drop — seam 1 warns on these (never fatal)
|
|
345
|
+
applyLinkToPass2Item(from, link.type, toId, link.reasoning);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
return { items, groupByItemId };
|
|
349
|
+
}
|
|
350
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
351
|
+
// BRIDGE TO RUNNABLE — fragment → a Pass-3-resume checkpoint
|
|
352
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
353
|
+
//
|
|
354
|
+
// runAutoReflect already supports resuming from a checkpoint: when
|
|
355
|
+
// `checkpoint.pass2Classified` is set it SKIPS Pass 0/1/2 and runs Pass 3+ on
|
|
356
|
+
// those items (pipeline.ts:934). v2 reuses that seam — COMPREHEND produces the
|
|
357
|
+
// classified items, this builds the checkpoint, and the EXISTING back-half
|
|
358
|
+
// (Pass 3→5 + recognizer/Stage D + chain-stamp) runs unchanged. No hot-path edit.
|
|
359
|
+
//
|
|
360
|
+
// pass1Items are derived (minimal) so Pass 3's budget hint + any pass1 reference
|
|
361
|
+
// is satisfied; pass0.sceneCard is left undefined (Pass 3 handles its absence).
|
|
362
|
+
export function comprehendResultToCheckpoint(result) {
|
|
363
|
+
const { items } = comprehendResultToPass2Items(result);
|
|
364
|
+
const pass1Items = items.map((it) => ({
|
|
365
|
+
id: it.id,
|
|
366
|
+
text: it.text,
|
|
367
|
+
source: "comprehend",
|
|
368
|
+
excerpt: it.excerpt ?? "",
|
|
369
|
+
provisional_type: it.type,
|
|
370
|
+
}));
|
|
371
|
+
return {
|
|
372
|
+
resumeFrom: "pass3",
|
|
373
|
+
pass0: { sceneCard: undefined, raw: undefined },
|
|
374
|
+
pass1Items,
|
|
375
|
+
pass2Classified: items,
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
379
|
+
// LLM 1 — COMPREHEND: the prompt + the call (build step 3)
|
|
380
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
381
|
+
//
|
|
382
|
+
// One holistic read of the whole session → grouped typed blocks + the links it
|
|
383
|
+
// READ from the prose + provenance. Replaces Pass 0/1/JUDGE/2a/2b/2c. The output
|
|
384
|
+
// is validated by SEAM 1 (validateComprehendResult) and converted to Pass2Item[]
|
|
385
|
+
// (comprehendResultToPass2Items) which the EXISTING Pass 3+ back-half consumes.
|
|
386
|
+
//
|
|
387
|
+
// Prompt discipline (PROMPT-CHARTER): reason about MEANING, never match surface
|
|
388
|
+
// words; universal across domains (no signal words, no domain examples); reuse the
|
|
389
|
+
// worth spine + STATE CONVENTION verbatim from the current JUDGE/Pass-1 prompts;
|
|
390
|
+
// types defined by epistemic role, not text shape.
|
|
391
|
+
export const COMPREHEND_PROMPT = `You read ONE complete work session between a user and an AI agent, and transcribe
|
|
392
|
+
its already-structured story into the memory schema. Read the whole session first,
|
|
393
|
+
then write.
|
|
394
|
+
|
|
395
|
+
Decide EVERYTHING by reasoning about MEANING in this session's context — what role
|
|
396
|
+
each piece played in what actually happened here. Never decide by matching surface
|
|
397
|
+
words, phrasings, or connectors. The same meaning appears in countless wordings
|
|
398
|
+
across domains; you are reading for the structure beneath the words.
|
|
399
|
+
|
|
400
|
+
── STATE CONVENTION ─────────────────────────────────────────────────────────
|
|
401
|
+
"State" = text in the TRANSCRIPT below. Your training knowledge and "what's
|
|
402
|
+
commonly known" are NOT state. Every block must quote a verbatim excerpt from the
|
|
403
|
+
transcript as its provenance. If it is not in the transcript, do not write it.
|
|
404
|
+
Familiarity ≠ recorded.
|
|
405
|
+
|
|
406
|
+
── WHAT TO KEEP (reason per candidate, from this session) ───────────────────
|
|
407
|
+
Keep the irreplaceable RESIDUE of this session — what was DECIDED, TRIED-AND-
|
|
408
|
+
ABANDONED, CONSTRAINED, OBSERVED, or STATED here — together with the REASONING.
|
|
409
|
+
|
|
410
|
+
The spine question, per candidate:
|
|
411
|
+
"Could a competent model — given the project context but WITHOUT having lived
|
|
412
|
+
this session — already produce this?"
|
|
413
|
+
YES → it is knowledge the model already carries → do not emit.
|
|
414
|
+
NO → it exists only because this session happened → emit it.
|
|
415
|
+
|
|
416
|
+
Asymmetric cost: anything that exists ONLY because this session happened is
|
|
417
|
+
unrecoverable once dropped — not just a decision / dead_end / constraint, but also a
|
|
418
|
+
session-specific observation, measurement, or stated value. Only what the model
|
|
419
|
+
ALREADY carries regenerates for free; a value measured or stated here is not that.
|
|
420
|
+
When unsure → keep.
|
|
421
|
+
|
|
422
|
+
Consulting the agent's own memory is not such a happening. A statement whose subject
|
|
423
|
+
is that MEMORY itself — that what is already stored is complete, was reviewed, or that
|
|
424
|
+
reading it changed nothing — is not residue, even though the reading occurred this
|
|
425
|
+
session; reading memory is not an action in the work. Emit only what the work produced
|
|
426
|
+
about ITS subject, never the agent's reading of what it had already stored.
|
|
427
|
+
|
|
428
|
+
A conclusion's EVIDENCE is residue too — the observation, measurement, or result it
|
|
429
|
+
is reasoned from. Keep it as its own block and ground the conclusion to it
|
|
430
|
+
(based_on / supports); a conclusion saved without what it rests on is
|
|
431
|
+
half the record. Keep that evidence EVEN when nothing links to it yet — a later
|
|
432
|
+
session grounds it; never drop a session-specific observation for lack of a link.
|
|
433
|
+
|
|
434
|
+
Do not emit:
|
|
435
|
+
• an option that was only RAISED in thought — never chosen, entered, or acted on.
|
|
436
|
+
• a bare sequence of steps carrying no reason that nothing rests on — the WHEN with
|
|
437
|
+
no WHY. (A step or value a conclusion is reasoned from is not bare — keep it.)
|
|
438
|
+
|
|
439
|
+
If the same claim appears more than once in the session (e.g. restated in a recap),
|
|
440
|
+
write it once, using its most complete statement.
|
|
441
|
+
|
|
442
|
+
If the session holds no residue at all — pure procedure, scaffolding, or chatter —
|
|
443
|
+
write nothing. An empty result is correct when nothing here could only have come
|
|
444
|
+
from this session.
|
|
445
|
+
|
|
446
|
+
Every block carries keep_reason: one line, from the session, naming what makes it
|
|
447
|
+
residue (it was chosen / entered-then-abandoned / imposed / measured / asserted by
|
|
448
|
+
a party), or why you kept it when it was borderline.
|
|
449
|
+
|
|
450
|
+
Every block also carries type_reasoning: one line stating why THIS type's epistemic
|
|
451
|
+
role fits — what distinguishes it from the neighbouring types, judged by the role the
|
|
452
|
+
block plays for a future reader, not by surface wording. Decide this before you commit
|
|
453
|
+
the type.
|
|
454
|
+
|
|
455
|
+
── STEP 1 — SEGMENT into GROUPS (clusters under a root) ─────────────────────
|
|
456
|
+
FIRST split the session into GROUPS. A group is one coherent sub-thread — a single
|
|
457
|
+
problem worked, question pursued, or thing decided. KEEP DISTINCT SUB-THREADS AS
|
|
458
|
+
SEPARATE GROUPS even when they belong to the same overall project; one sub-thread
|
|
459
|
+
scattered across the session is one group. Judge by what the participants were
|
|
460
|
+
trying to do, not by topic words. Do NOT collapse several sub-threads into one big
|
|
461
|
+
group — keep them fine-grained.
|
|
462
|
+
|
|
463
|
+
THEN assign each group a provisional_project — the ONE overarching ROOT it belongs
|
|
464
|
+
to. The ROOT is the project; the GROUP is a CLUSTER under it; ONE root has MANY
|
|
465
|
+
clusters. Sub-threads of the same overall effort SHARE a root but STAY SEPARATE
|
|
466
|
+
GROUPS — same root, several clusters; do NOT merge them into one group.
|
|
467
|
+
• Use a DIFFERENT provisional_project ONLY for a genuinely separate topic — a
|
|
468
|
+
real context-switch or an unrelated tangent.
|
|
469
|
+
• A separate root must have a NAMEABLE SUBJECT: you must be able to say what the
|
|
470
|
+
group's work is ABOUT without referring to the speaker's own remembering,
|
|
471
|
+
reasoning, or composing of replies in this conversation. Recalling, weighing,
|
|
472
|
+
and planning how to respond are the MEANS of every conversation, never a topic
|
|
473
|
+
of their own — claims born of that procedure belong under the root of the work
|
|
474
|
+
they serve (and only those that pass the residue test above).
|
|
475
|
+
• When unsure whether two groups share a root, prefer the SAME root — splitting
|
|
476
|
+
one topic across many roots (fragmentation) is worse than a slightly-broad root.
|
|
477
|
+
• NAME the root with the most SPECIFIC identifier the session gives the SUBJECT the
|
|
478
|
+
work is ABOUT — named as specifically as the session itself names it. NEVER a
|
|
479
|
+
generic category word, a placeholder, or the group_id. If nothing that specific is
|
|
480
|
+
named, use the clearest phrase for what the work is about — never a bare
|
|
481
|
+
"group"/number. lowercase, hyphens only, no underscores. provisional_project must
|
|
482
|
+
always be filled.
|
|
483
|
+
This is provisional; cross-SESSION matching to existing roots happens later.
|
|
484
|
+
|
|
485
|
+
── STEP 2 — within each group, write TYPED blocks ───────────────────────────
|
|
486
|
+
A type is the agent's RELATIONSHIP to the knowledge, not its subject matter — the
|
|
487
|
+
same type spans every domain. For each piece of residue, reason about which
|
|
488
|
+
relationship fits, then FILL THAT TYPE'S unique{} FIELDS — this is the block's
|
|
489
|
+
structured identity and is REQUIRED, never empty. Put the actual content there
|
|
490
|
+
(the choice + reason, the value, the limit, the approach + why it failed), in the
|
|
491
|
+
session's own language. essence is only a one-line SUMMARY of those fields — it
|
|
492
|
+
does not replace them. A block whose unique{} is empty is incomplete; fill every
|
|
493
|
+
field of the type that the session supports. One passage can carry several
|
|
494
|
+
relationships → several blocks.
|
|
495
|
+
|
|
496
|
+
CORE relationships (consider these first):
|
|
497
|
+
decision {choice, reason, alternatives_rejected} — the participants CLOSED a
|
|
498
|
+
fork: a path was committed to, adopted, or acted on. The decision is
|
|
499
|
+
the path TAKEN; a path they CLOSED OFF is a dead_end (below), not a
|
|
500
|
+
decision — even when one passage both settles the choice and rules out
|
|
501
|
+
the alternative. A path one participant PUT FORWARD for another to
|
|
502
|
+
accept leaves the fork open — that is a blueprint (below), not a
|
|
503
|
+
decision, no matter how strongly it was urged. To type decision you
|
|
504
|
+
must be able to point at WHERE the fork closed, not just where a path
|
|
505
|
+
was proposed. Justify it: link based_on >=1 fact/constraint (Step 3).
|
|
506
|
+
dead_end {approach, reason, alternative} — an approach CLOSED OFF for a stated
|
|
507
|
+
reason, so a future reader should not re-open it. Covers one tried then
|
|
508
|
+
abandoned AND one evaluated and definitively rejected before trying. A
|
|
509
|
+
path merely floated with no verdict is NOT a dead_end — the close-off
|
|
510
|
+
must be definite and reasoned.
|
|
511
|
+
constraint {limit, reason, source} — a boundary that bounds EVERY option and that
|
|
512
|
+
the participants must work within. May be imposed from outside OR set by
|
|
513
|
+
the participants as a fixed limit; what makes it a constraint is that it
|
|
514
|
+
GOVERNS the other choices rather than being one of them.
|
|
515
|
+
fact {value, why_matters} — a specific observed value or concrete state.
|
|
516
|
+
insight {observation, implication} — a realization drawn from combining things.
|
|
517
|
+
blueprint {purpose, status, trigger_to_implement} — a planned or proposed path
|
|
518
|
+
whose outcome is not yet settled: a plan adopted but not yet executed,
|
|
519
|
+
OR a path put forward that no one has yet accepted. The fork is still
|
|
520
|
+
open; when it later closes, a decision supersedes this.
|
|
521
|
+
preference {lean, over, condition} — a standing lean that shapes future choices,
|
|
522
|
+
short of a committed decision.
|
|
523
|
+
question {question, why_matters} — left genuinely open, with no path forward.
|
|
524
|
+
|
|
525
|
+
When the level of commitment is unclear, type the LESS-committed role (blueprint
|
|
526
|
+
over decision, preference over constraint): the residue is still captured, and a
|
|
527
|
+
later session promotes it (a decision supersedes its blueprint). A false decision
|
|
528
|
+
misleads every future reader into treating an open fork as closed.
|
|
529
|
+
|
|
530
|
+
OTHER roles, with their REQUIRED fields (fill these exact field names), when none of
|
|
531
|
+
the above fits:
|
|
532
|
+
hypothesis {proposal, evidence_against} — a claim offered as possibly true but
|
|
533
|
+
NOT yet verified: reasoned TOWARD, not asserted as established. What it
|
|
534
|
+
rests on is recorded as its OWN block and linked (based_on), not
|
|
535
|
+
restated here; evidence_against is only what would weigh against it.
|
|
536
|
+
entity {name, role} — a thing the work REFERS TO by name, not a claim about it;
|
|
537
|
+
identity is the name, role is the part it plays in the work.
|
|
538
|
+
task {status, description, owner} — work still TO BE DONE, tracked by its state
|
|
539
|
+
of completion and who holds it.
|
|
540
|
+
event {what_happened, outcome, date} — a thing that OCCURRED at a point in time,
|
|
541
|
+
as opposed to a standing truth that simply holds.
|
|
542
|
+
note {} — no field schema; the catch-all, only when no sharper role fits.
|
|
543
|
+
If a genuinely distinct epistemic role STILL fits none of these, name the type and
|
|
544
|
+
include schema{} (field -> what it captures).
|
|
545
|
+
|
|
546
|
+
Each block also carries: essence (one sentence, <=120 chars — what it is and why
|
|
547
|
+
it matters), concepts (a few terms naming what it is about), provisional_name (a
|
|
548
|
+
short slug for the thing — provisional, not a final label), provenance, keep_reason.
|
|
549
|
+
|
|
550
|
+
── STEP 3 — WIRE the relationships WITHIN each group ─────────────────────────
|
|
551
|
+
Where the session shows one block standing in a real relationship to another —
|
|
552
|
+
one thing led to another, justified it, replaced it, answered it, elaborates it,
|
|
553
|
+
provides evidence for it, or conflicts with it — record that link. Infer it from
|
|
554
|
+
what happened, whether or not any connecting word is present.
|
|
555
|
+
|
|
556
|
+
Each link is {from, to, type}, where "from" holds the relationship. Choose the
|
|
557
|
+
type whose MEANING matches:
|
|
558
|
+
prompted_by — from happened as a consequence of to (to is the trigger)
|
|
559
|
+
based_on — from is a conclusion grounded in to (evidence)
|
|
560
|
+
extends — from is a more specific case of to (broader)
|
|
561
|
+
supersedes — from replaces an earlier to
|
|
562
|
+
resolves — from answers the open question to
|
|
563
|
+
supports — from is evidence for the proposal to
|
|
564
|
+
contradicts — from and to conflict
|
|
565
|
+
related_to — from and to are associated, with no sharper relationship
|
|
566
|
+
derived_from — from was reasoned out from to
|
|
567
|
+
affects — from has an impact on to
|
|
568
|
+
|
|
569
|
+
Reach for the SHARPEST relation the meaning supports. related_to and affects are the
|
|
570
|
+
WEAKEST — a last resort, used ONLY when no grounding, consequence, replacement, or
|
|
571
|
+
answer actually holds.
|
|
572
|
+
|
|
573
|
+
Every block sits in a HISTORY — wire each way it connects BACKWARD to what came
|
|
574
|
+
before, not only its evidence:
|
|
575
|
+
- what it was REASONED FROM: the observation, measurement, or result a later
|
|
576
|
+
realization, boundary, choice, or lean rests on (based_on / supports / derived_from);
|
|
577
|
+
- what it REPLACED: an earlier approach, value, or state this makes obsolete. The
|
|
578
|
+
earlier block stays as history and MUST be linked FROM the newer one (supersedes) —
|
|
579
|
+
never leave a superseded block standing as if nothing replaced it;
|
|
580
|
+
- what TRIGGERED it: the event, failure, or need it arose as a consequence of
|
|
581
|
+
(prompted_by);
|
|
582
|
+
- the open QUESTION it answers (resolves).
|
|
583
|
+
The trap to avoid, for ANY block type: a block that REPLACED or was TRIGGERED BY
|
|
584
|
+
another, but is wired only to its supporting evidence, leaves that other block
|
|
585
|
+
ORPHANED — you recorded why it is justified but dropped what it displaced or
|
|
586
|
+
responded to. Both are how the state was reached; wire both.
|
|
587
|
+
|
|
588
|
+
The link type MUST be exactly one of these ten relations — never invent one, and
|
|
589
|
+
never use a block's unique{} field name as a link type. A detail that belongs to a
|
|
590
|
+
single block (a decision's rejected alternatives, a constraint's source, and the
|
|
591
|
+
like) is recorded INSIDE that block's own fields — never as a link, and never as a
|
|
592
|
+
separate block created only so something can link to it.
|
|
593
|
+
|
|
594
|
+
Every decision — and every hypothesis or insight that rests on a finding — needs >=1
|
|
595
|
+
based_on to the observation it is reasoned from. If that evidence is genuinely not in
|
|
596
|
+
this session, mark the block uncertain — never supply the evidence yourself.
|
|
597
|
+
|
|
598
|
+
Stay within this session: do not assign final names, do not match against any
|
|
599
|
+
existing memory, do not link across groups. Those are later stages.`;
|
|
600
|
+
// Structured-output schema for COMPREHEND. Mirrors ComprehendResult. unique{} and
|
|
601
|
+
// schema{} are freeform maps (type:object) — the system's most complex schema, so
|
|
602
|
+
// the universality path (tool-use for Anthropic + prompt-JSON fallback, b8513a5)
|
|
603
|
+
// carries it; round-trip-verify on the target model before any A/B spend.
|
|
604
|
+
export const COMPREHEND_SCHEMA = {
|
|
605
|
+
type: "object",
|
|
606
|
+
properties: {
|
|
607
|
+
groups: {
|
|
608
|
+
type: "array",
|
|
609
|
+
items: {
|
|
610
|
+
type: "object",
|
|
611
|
+
properties: {
|
|
612
|
+
group_id: { type: "string" },
|
|
613
|
+
topic: { type: "string" },
|
|
614
|
+
provisional_project: { type: "string" },
|
|
615
|
+
blocks: {
|
|
616
|
+
type: "array",
|
|
617
|
+
items: {
|
|
618
|
+
type: "object",
|
|
619
|
+
properties: {
|
|
620
|
+
local_id: { type: "string" },
|
|
621
|
+
type: { type: "string" },
|
|
622
|
+
unique: {
|
|
623
|
+
type: "object",
|
|
624
|
+
description: "REQUIRED structured identity fields for the type — never empty. e.g. decision: {choice, reason, alternatives_rejected}; fact: {value, why_matters}; dead_end: {approach, reason, alternative}; constraint: {limit, reason, source}; insight: {observation, implication}. Fill from the transcript.",
|
|
625
|
+
},
|
|
626
|
+
schema: { type: "object" },
|
|
627
|
+
essence: { type: "string" },
|
|
628
|
+
concepts: { type: "array", items: { type: "string" } },
|
|
629
|
+
provisional_name: { type: "string" },
|
|
630
|
+
provenance: { type: "string" },
|
|
631
|
+
keep_reason: { type: "string" },
|
|
632
|
+
type_reasoning: { type: "string" },
|
|
633
|
+
uncertain: { type: "boolean" },
|
|
634
|
+
},
|
|
635
|
+
required: ["local_id", "type", "unique", "essence", "provenance", "keep_reason"],
|
|
636
|
+
},
|
|
637
|
+
},
|
|
638
|
+
within_group_links: {
|
|
639
|
+
type: "array",
|
|
640
|
+
items: {
|
|
641
|
+
type: "object",
|
|
642
|
+
properties: {
|
|
643
|
+
from: { type: "string" },
|
|
644
|
+
to: { type: "string" },
|
|
645
|
+
type: { type: "string" },
|
|
646
|
+
reasoning: { type: "string" },
|
|
647
|
+
},
|
|
648
|
+
required: ["from", "to", "type"],
|
|
649
|
+
},
|
|
650
|
+
},
|
|
651
|
+
},
|
|
652
|
+
required: ["group_id", "topic", "provisional_project", "blocks", "within_group_links"],
|
|
653
|
+
},
|
|
654
|
+
},
|
|
655
|
+
reasoning: { type: "string" },
|
|
656
|
+
},
|
|
657
|
+
required: ["groups"],
|
|
658
|
+
};
|
|
659
|
+
// Model override for COMPREHEND (the bet → strong model). Undefined → provider
|
|
660
|
+
// default. Own env var (PassId union has no "comprehend", so modelForPass can't
|
|
661
|
+
// route it).
|
|
662
|
+
/** Single source for all three COMPREHEND-path callers (here, per-group, cross-link). */
|
|
663
|
+
export function comprehendModel() {
|
|
664
|
+
return modelOverride("NODEDEX_COMPREHEND_MODEL");
|
|
665
|
+
}
|
|
666
|
+
/**
|
|
667
|
+
* Run the single COMPREHEND read over a session transcript. Graph-blind: input is
|
|
668
|
+
* the raw transcript ONLY (the caller assembles user+agent turns — the all-sources
|
|
669
|
+
* lesson). Validates via SEAM 1 but does not throw or mutate global token stats —
|
|
670
|
+
* the caller decides retry/quarantine and attributes cost.
|
|
671
|
+
*/
|
|
672
|
+
export async function callComprehendLLM(provider, transcript, thinkingBudget = 8192) {
|
|
673
|
+
const userInput = `TRANSCRIPT (one work session — read all of it before writing):\n\n${transcript}`;
|
|
674
|
+
const r = await provider.generateStructured(COMPREHEND_PROMPT, userInput, COMPREHEND_SCHEMA, {
|
|
675
|
+
thinkingBudget: getThinkingBudget(thinkingBudget),
|
|
676
|
+
// INTERIM PATCH (latency, not capture): 65536 (the model max) let a runaway
|
|
677
|
+
// generation burn the full budget before failing a JSON.parse → "truncated"
|
|
678
|
+
// → re-roll, costing ~200s+ (the 307s arc). 32768 fails ~2x faster AND gives
|
|
679
|
+
// the provider's 1.5x truncation-bump real headroom (32768→49152, vs a no-op
|
|
680
|
+
// at 65536). Biggest legit fragment seen = 13347 tokens (Run 9, 57 blocks),
|
|
681
|
+
// so 32768 keeps a ~2.4x margin. DEBT this buys time against: the SINGLE
|
|
682
|
+
// monolithic COMPREHEND call is a latency/single-point wildcard — the
|
|
683
|
+
// structural fix is PER-GROUP COMPREHEND (segment once → bounded parallel
|
|
684
|
+
// per-group production; design §11 risk 3). Capture is already safe (a
|
|
685
|
+
// persistent COMPREHEND failure degrades to v1 in arc-pipeline.ts).
|
|
686
|
+
maxOutputTokens: 32768,
|
|
687
|
+
modelOverride: comprehendModel(),
|
|
688
|
+
});
|
|
689
|
+
let validation = null;
|
|
690
|
+
if (r.result) {
|
|
691
|
+
validation = validateComprehendResult(r.result);
|
|
692
|
+
const groups = r.result.groups?.length ?? 0;
|
|
693
|
+
const blocks = (r.result.groups ?? []).reduce((n, g) => n + (g.blocks?.length ?? 0), 0);
|
|
694
|
+
console.log(`Auto-Reflect COMPREHEND: ${groups} groups, ${blocks} blocks | valid=${validation.valid} ` +
|
|
695
|
+
`errors=${validation.errors.length} warnings: ${summarizeWarnings(validation.warnings)} | ` +
|
|
696
|
+
`tokens: in=${r.usage?.input ?? "?"} think=${r.usage?.thinking ?? "?"} out=${r.usage?.output ?? "?"}`);
|
|
697
|
+
for (const e of validation.errors) {
|
|
698
|
+
console.warn(` [COMPREHEND error] ${e.message}${e.local_id ? ` (${e.local_id})` : ""}`);
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
else {
|
|
702
|
+
console.warn(`Auto-Reflect COMPREHEND: ${r.rateLimited ? "rate limited" : "failed"} — no fragment produced`);
|
|
703
|
+
}
|
|
704
|
+
return { result: r.result, validation, rateLimited: r.rateLimited, creditExhausted: r.creditExhausted, model: r.model, attempts: r.attempts, usage: r.usage };
|
|
705
|
+
}
|
|
706
|
+
//# sourceMappingURL=comprehend.js.map
|