@isaacriehm/cairn-core 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/LICENSE +21 -0
- package/dist/.tsbuildinfo +1 -0
- package/dist/claude/error.d.ts +33 -0
- package/dist/claude/error.js +58 -0
- package/dist/claude/error.js.map +1 -0
- package/dist/claude/index.d.ts +3 -0
- package/dist/claude/index.js +3 -0
- package/dist/claude/index.js.map +1 -0
- package/dist/claude/runner.d.ts +11 -0
- package/dist/claude/runner.js +132 -0
- package/dist/claude/runner.js.map +1 -0
- package/dist/claude/types.d.ts +52 -0
- package/dist/claude/types.js +14 -0
- package/dist/claude/types.js.map +1 -0
- package/dist/context/checkpoint.d.ts +10 -0
- package/dist/context/checkpoint.js +29 -0
- package/dist/context/checkpoint.js.map +1 -0
- package/dist/context/handoff-builder.d.ts +11 -0
- package/dist/context/handoff-builder.js +268 -0
- package/dist/context/handoff-builder.js.map +1 -0
- package/dist/context/index.d.ts +11 -0
- package/dist/context/index.js +11 -0
- package/dist/context/index.js.map +1 -0
- package/dist/context/spec-delta.d.ts +47 -0
- package/dist/context/spec-delta.js +237 -0
- package/dist/context/spec-delta.js.map +1 -0
- package/dist/decision-capture/capture.d.ts +57 -0
- package/dist/decision-capture/capture.js +186 -0
- package/dist/decision-capture/capture.js.map +1 -0
- package/dist/decision-capture/extractor.d.ts +20 -0
- package/dist/decision-capture/extractor.js +103 -0
- package/dist/decision-capture/extractor.js.map +1 -0
- package/dist/decision-capture/id.d.ts +21 -0
- package/dist/decision-capture/id.js +60 -0
- package/dist/decision-capture/id.js.map +1 -0
- package/dist/decision-capture/index.d.ts +25 -0
- package/dist/decision-capture/index.js +21 -0
- package/dist/decision-capture/index.js.map +1 -0
- package/dist/decision-capture/prompt.d.ts +15 -0
- package/dist/decision-capture/prompt.js +68 -0
- package/dist/decision-capture/prompt.js.map +1 -0
- package/dist/decision-capture/refinement-prompt.d.ts +25 -0
- package/dist/decision-capture/refinement-prompt.js +146 -0
- package/dist/decision-capture/refinement-prompt.js.map +1 -0
- package/dist/decision-capture/refinement-schema.d.ts +52 -0
- package/dist/decision-capture/refinement-schema.js +61 -0
- package/dist/decision-capture/refinement-schema.js.map +1 -0
- package/dist/decision-capture/refinement.d.ts +60 -0
- package/dist/decision-capture/refinement.js +439 -0
- package/dist/decision-capture/refinement.js.map +1 -0
- package/dist/decision-capture/schema.d.ts +70 -0
- package/dist/decision-capture/schema.js +71 -0
- package/dist/decision-capture/schema.js.map +1 -0
- package/dist/decision-capture/types.d.ts +201 -0
- package/dist/decision-capture/types.js +20 -0
- package/dist/decision-capture/types.js.map +1 -0
- package/dist/decision-capture/writer.d.ts +90 -0
- package/dist/decision-capture/writer.js +267 -0
- package/dist/decision-capture/writer.js.map +1 -0
- package/dist/doctor/index.d.ts +48 -0
- package/dist/doctor/index.js +460 -0
- package/dist/doctor/index.js.map +1 -0
- package/dist/events/index.d.ts +15 -0
- package/dist/events/index.js +14 -0
- package/dist/events/index.js.map +1 -0
- package/dist/events/paths.d.ts +2 -0
- package/dist/events/paths.js +6 -0
- package/dist/events/paths.js.map +1 -0
- package/dist/events/reader.d.ts +40 -0
- package/dist/events/reader.js +139 -0
- package/dist/events/reader.js.map +1 -0
- package/dist/events/writer.d.ts +61 -0
- package/dist/events/writer.js +68 -0
- package/dist/events/writer.js.map +1 -0
- package/dist/frontend-types.d.ts +243 -0
- package/dist/frontend-types.js +15 -0
- package/dist/frontend-types.js.map +1 -0
- package/dist/gc/apply.d.ts +26 -0
- package/dist/gc/apply.js +48 -0
- package/dist/gc/apply.js.map +1 -0
- package/dist/gc/canary.d.ts +42 -0
- package/dist/gc/canary.js +134 -0
- package/dist/gc/canary.js.map +1 -0
- package/dist/gc/citation-integrity.d.ts +24 -0
- package/dist/gc/citation-integrity.js +151 -0
- package/dist/gc/citation-integrity.js.map +1 -0
- package/dist/gc/classify.d.ts +25 -0
- package/dist/gc/classify.js +89 -0
- package/dist/gc/classify.js.map +1 -0
- package/dist/gc/completion-integrity.d.ts +22 -0
- package/dist/gc/completion-integrity.js +165 -0
- package/dist/gc/completion-integrity.js.map +1 -0
- package/dist/gc/doc-gardening.d.ts +29 -0
- package/dist/gc/doc-gardening.js +146 -0
- package/dist/gc/doc-gardening.js.map +1 -0
- package/dist/gc/frontmatter.d.ts +35 -0
- package/dist/gc/frontmatter.js +105 -0
- package/dist/gc/frontmatter.js.map +1 -0
- package/dist/gc/generator-drift.d.ts +28 -0
- package/dist/gc/generator-drift.js +53 -0
- package/dist/gc/generator-drift.js.map +1 -0
- package/dist/gc/index.d.ts +42 -0
- package/dist/gc/index.js +30 -0
- package/dist/gc/index.js.map +1 -0
- package/dist/gc/quality-update.d.ts +23 -0
- package/dist/gc/quality-update.js +69 -0
- package/dist/gc/quality-update.js.map +1 -0
- package/dist/gc/scope-coverage.d.ts +20 -0
- package/dist/gc/scope-coverage.js +70 -0
- package/dist/gc/scope-coverage.js.map +1 -0
- package/dist/gc/stub-hits.d.ts +31 -0
- package/dist/gc/stub-hits.js +78 -0
- package/dist/gc/stub-hits.js.map +1 -0
- package/dist/gc/sweep.d.ts +56 -0
- package/dist/gc/sweep.js +205 -0
- package/dist/gc/sweep.js.map +1 -0
- package/dist/gc/types.d.ts +129 -0
- package/dist/gc/types.js +26 -0
- package/dist/gc/types.js.map +1 -0
- package/dist/gc/walk-source.d.ts +14 -0
- package/dist/gc/walk-source.js +59 -0
- package/dist/gc/walk-source.js.map +1 -0
- package/dist/ground/drift.d.ts +8 -0
- package/dist/ground/drift.js +23 -0
- package/dist/ground/drift.js.map +1 -0
- package/dist/ground/frontmatter.d.ts +20 -0
- package/dist/ground/frontmatter.js +49 -0
- package/dist/ground/frontmatter.js.map +1 -0
- package/dist/ground/glob.d.ts +10 -0
- package/dist/ground/glob.js +46 -0
- package/dist/ground/glob.js.map +1 -0
- package/dist/ground/index.d.ts +16 -0
- package/dist/ground/index.js +11 -0
- package/dist/ground/index.js.map +1 -0
- package/dist/ground/ledgers.d.ts +18 -0
- package/dist/ground/ledgers.js +103 -0
- package/dist/ground/ledgers.js.map +1 -0
- package/dist/ground/manifest.d.ts +10 -0
- package/dist/ground/manifest.js +88 -0
- package/dist/ground/manifest.js.map +1 -0
- package/dist/ground/paths.d.ts +20 -0
- package/dist/ground/paths.js +61 -0
- package/dist/ground/paths.js.map +1 -0
- package/dist/ground/quality-grades.d.ts +11 -0
- package/dist/ground/quality-grades.js +98 -0
- package/dist/ground/quality-grades.js.map +1 -0
- package/dist/ground/schemas.d.ts +306 -0
- package/dist/ground/schemas.js +188 -0
- package/dist/ground/schemas.js.map +1 -0
- package/dist/ground/scope-index.d.ts +48 -0
- package/dist/ground/scope-index.js +120 -0
- package/dist/ground/scope-index.js.map +1 -0
- package/dist/ground/walk.d.ts +7 -0
- package/dist/ground/walk.js +53 -0
- package/dist/ground/walk.js.map +1 -0
- package/dist/hooks/bypass-detection.d.ts +28 -0
- package/dist/hooks/bypass-detection.js +106 -0
- package/dist/hooks/bypass-detection.js.map +1 -0
- package/dist/hooks/index.d.ts +12 -0
- package/dist/hooks/index.js +13 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/post-tool-use/allowlist-reader.d.ts +14 -0
- package/dist/hooks/post-tool-use/allowlist-reader.js +69 -0
- package/dist/hooks/post-tool-use/allowlist-reader.js.map +1 -0
- package/dist/hooks/post-tool-use/citation-scanner.d.ts +23 -0
- package/dist/hooks/post-tool-use/citation-scanner.js +59 -0
- package/dist/hooks/post-tool-use/citation-scanner.js.map +1 -0
- package/dist/hooks/post-tool-use/copy-scanner.d.ts +25 -0
- package/dist/hooks/post-tool-use/copy-scanner.js +192 -0
- package/dist/hooks/post-tool-use/copy-scanner.js.map +1 -0
- package/dist/hooks/post-tool-use/index.d.ts +19 -0
- package/dist/hooks/post-tool-use/index.js +15 -0
- package/dist/hooks/post-tool-use/index.js.map +1 -0
- package/dist/hooks/post-tool-use/ledger-cache.d.ts +32 -0
- package/dist/hooks/post-tool-use/ledger-cache.js +236 -0
- package/dist/hooks/post-tool-use/ledger-cache.js.map +1 -0
- package/dist/hooks/post-tool-use/legend-builder.d.ts +15 -0
- package/dist/hooks/post-tool-use/legend-builder.js +84 -0
- package/dist/hooks/post-tool-use/legend-builder.js.map +1 -0
- package/dist/hooks/post-tool-use/read-enricher.d.ts +13 -0
- package/dist/hooks/post-tool-use/read-enricher.js +157 -0
- package/dist/hooks/post-tool-use/read-enricher.js.map +1 -0
- package/dist/hooks/post-tool-use/write-guardian.d.ts +17 -0
- package/dist/hooks/post-tool-use/write-guardian.js +176 -0
- package/dist/hooks/post-tool-use/write-guardian.js.map +1 -0
- package/dist/hooks/read-enrich.d.ts +6 -0
- package/dist/hooks/read-enrich.js +11 -0
- package/dist/hooks/read-enrich.js.map +1 -0
- package/dist/hooks/runners/index.d.ts +12 -0
- package/dist/hooks/runners/index.js +11 -0
- package/dist/hooks/runners/index.js.map +1 -0
- package/dist/hooks/runners/payload.d.ts +32 -0
- package/dist/hooks/runners/payload.js +70 -0
- package/dist/hooks/runners/payload.js.map +1 -0
- package/dist/hooks/runners/session-end.d.ts +7 -0
- package/dist/hooks/runners/session-end.js +42 -0
- package/dist/hooks/runners/session-end.js.map +1 -0
- package/dist/hooks/runners/session-start.d.ts +10 -0
- package/dist/hooks/runners/session-start.js +167 -0
- package/dist/hooks/runners/session-start.js.map +1 -0
- package/dist/hooks/runners/stop.d.ts +18 -0
- package/dist/hooks/runners/stop.js +165 -0
- package/dist/hooks/runners/stop.js.map +1 -0
- package/dist/hooks/session-end.d.ts +5 -0
- package/dist/hooks/session-end.js +10 -0
- package/dist/hooks/session-end.js.map +1 -0
- package/dist/hooks/session-start.d.ts +7 -0
- package/dist/hooks/session-start.js +12 -0
- package/dist/hooks/session-start.js.map +1 -0
- package/dist/hooks/stop.d.ts +5 -0
- package/dist/hooks/stop.js +10 -0
- package/dist/hooks/stop.js.map +1 -0
- package/dist/hooks/write-guard.d.ts +6 -0
- package/dist/hooks/write-guard.js +11 -0
- package/dist/hooks/write-guard.js.map +1 -0
- package/dist/inbox.d.ts +17 -0
- package/dist/inbox.js +30 -0
- package/dist/inbox.js.map +1 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.js +32 -0
- package/dist/index.js.map +1 -0
- package/dist/init/baseline-audit.d.ts +71 -0
- package/dist/init/baseline-audit.js +377 -0
- package/dist/init/baseline-audit.js.map +1 -0
- package/dist/init/brand-setup.d.ts +44 -0
- package/dist/init/brand-setup.js +201 -0
- package/dist/init/brand-setup.js.map +1 -0
- package/dist/init/daemon-autostart.d.ts +16 -0
- package/dist/init/daemon-autostart.js +95 -0
- package/dist/init/daemon-autostart.js.map +1 -0
- package/dist/init/detect.d.ts +25 -0
- package/dist/init/detect.js +319 -0
- package/dist/init/detect.js.map +1 -0
- package/dist/init/index.d.ts +32 -0
- package/dist/init/index.js +18 -0
- package/dist/init/index.js.map +1 -0
- package/dist/init/ingest-docs.d.ts +74 -0
- package/dist/init/ingest-docs.js +499 -0
- package/dist/init/ingest-docs.js.map +1 -0
- package/dist/init/init.d.ts +165 -0
- package/dist/init/init.js +1166 -0
- package/dist/init/init.js.map +1 -0
- package/dist/init/mapper-legacy.d.ts +148 -0
- package/dist/init/mapper-legacy.js +238 -0
- package/dist/init/mapper-legacy.js.map +1 -0
- package/dist/init/mapper-merge.d.ts +38 -0
- package/dist/init/mapper-merge.js +238 -0
- package/dist/init/mapper-merge.js.map +1 -0
- package/dist/init/mapper-parallel.d.ts +48 -0
- package/dist/init/mapper-parallel.js +409 -0
- package/dist/init/mapper-parallel.js.map +1 -0
- package/dist/init/mapper-prompts.d.ts +135 -0
- package/dist/init/mapper-prompts.js +189 -0
- package/dist/init/mapper-prompts.js.map +1 -0
- package/dist/init/mapper.d.ts +211 -0
- package/dist/init/mapper.js +151 -0
- package/dist/init/mapper.js.map +1 -0
- package/dist/init/module-slicer.d.ts +39 -0
- package/dist/init/module-slicer.js +809 -0
- package/dist/init/module-slicer.js.map +1 -0
- package/dist/init/multi-dev/index.d.ts +2 -0
- package/dist/init/multi-dev/index.js +2 -0
- package/dist/init/multi-dev/index.js.map +1 -0
- package/dist/init/multi-dev/install.d.ts +40 -0
- package/dist/init/multi-dev/install.js +139 -0
- package/dist/init/multi-dev/install.js.map +1 -0
- package/dist/init/preflight-guards.d.ts +42 -0
- package/dist/init/preflight-guards.js +108 -0
- package/dist/init/preflight-guards.js.map +1 -0
- package/dist/init/prompts.d.ts +61 -0
- package/dist/init/prompts.js +66 -0
- package/dist/init/prompts.js.map +1 -0
- package/dist/init/rules-merge/discover.d.ts +21 -0
- package/dist/init/rules-merge/discover.js +78 -0
- package/dist/init/rules-merge/discover.js.map +1 -0
- package/dist/init/rules-merge/index.d.ts +10 -0
- package/dist/init/rules-merge/index.js +6 -0
- package/dist/init/rules-merge/index.js.map +1 -0
- package/dist/init/rules-merge/ingest.d.ts +56 -0
- package/dist/init/rules-merge/ingest.js +336 -0
- package/dist/init/rules-merge/ingest.js.map +1 -0
- package/dist/init/rules-merge/keep-markers.d.ts +39 -0
- package/dist/init/rules-merge/keep-markers.js +97 -0
- package/dist/init/rules-merge/keep-markers.js.map +1 -0
- package/dist/init/rules-merge/parse-sections.d.ts +24 -0
- package/dist/init/rules-merge/parse-sections.js +71 -0
- package/dist/init/rules-merge/parse-sections.js.map +1 -0
- package/dist/init/rules-merge/regenerate.d.ts +33 -0
- package/dist/init/rules-merge/regenerate.js +163 -0
- package/dist/init/rules-merge/regenerate.js.map +1 -0
- package/dist/init/secrets.d.ts +18 -0
- package/dist/init/secrets.js +76 -0
- package/dist/init/secrets.js.map +1 -0
- package/dist/init/seed.d.ts +21 -0
- package/dist/init/seed.js +96 -0
- package/dist/init/seed.js.map +1 -0
- package/dist/init/setup-runners.d.ts +15 -0
- package/dist/init/setup-runners.js +143 -0
- package/dist/init/setup-runners.js.map +1 -0
- package/dist/init/source-comments/classify.d.ts +98 -0
- package/dist/init/source-comments/classify.js +244 -0
- package/dist/init/source-comments/classify.js.map +1 -0
- package/dist/init/source-comments/index.d.ts +8 -0
- package/dist/init/source-comments/index.js +5 -0
- package/dist/init/source-comments/index.js.map +1 -0
- package/dist/init/source-comments/ingest.d.ts +51 -0
- package/dist/init/source-comments/ingest.js +236 -0
- package/dist/init/source-comments/ingest.js.map +1 -0
- package/dist/init/source-comments/strip-replace.d.ts +106 -0
- package/dist/init/source-comments/strip-replace.js +284 -0
- package/dist/init/source-comments/strip-replace.js.map +1 -0
- package/dist/init/source-comments/walker.d.ts +65 -0
- package/dist/init/source-comments/walker.js +777 -0
- package/dist/init/source-comments/walker.js.map +1 -0
- package/dist/init/submodules.d.ts +48 -0
- package/dist/init/submodules.js +149 -0
- package/dist/init/submodules.js.map +1 -0
- package/dist/init/types.d.ts +55 -0
- package/dist/init/types.js +10 -0
- package/dist/init/types.js.map +1 -0
- package/dist/init/visual.d.ts +69 -0
- package/dist/init/visual.js +265 -0
- package/dist/init/visual.js.map +1 -0
- package/dist/init/walker.d.ts +82 -0
- package/dist/init/walker.js +585 -0
- package/dist/init/walker.js.map +1 -0
- package/dist/init/workflow-block.d.ts +34 -0
- package/dist/init/workflow-block.js +110 -0
- package/dist/init/workflow-block.js.map +1 -0
- package/dist/join/index.d.ts +67 -0
- package/dist/join/index.js +256 -0
- package/dist/join/index.js.map +1 -0
- package/dist/lock.d.ts +39 -0
- package/dist/lock.js +129 -0
- package/dist/lock.js.map +1 -0
- package/dist/logger.d.ts +13 -0
- package/dist/logger.js +78 -0
- package/dist/logger.js.map +1 -0
- package/dist/mcp/bootstrap-guard.d.ts +29 -0
- package/dist/mcp/bootstrap-guard.js +47 -0
- package/dist/mcp/bootstrap-guard.js.map +1 -0
- package/dist/mcp/context.d.ts +23 -0
- package/dist/mcp/context.js +9 -0
- package/dist/mcp/context.js.map +1 -0
- package/dist/mcp/errors.d.ts +17 -0
- package/dist/mcp/errors.js +23 -0
- package/dist/mcp/errors.js.map +1 -0
- package/dist/mcp/history/index.d.ts +6 -0
- package/dist/mcp/history/index.js +5 -0
- package/dist/mcp/history/index.js.map +1 -0
- package/dist/mcp/history/prompt.d.ts +32 -0
- package/dist/mcp/history/prompt.js +99 -0
- package/dist/mcp/history/prompt.js.map +1 -0
- package/dist/mcp/history/schema.d.ts +58 -0
- package/dist/mcp/history/schema.js +41 -0
- package/dist/mcp/history/schema.js.map +1 -0
- package/dist/mcp/history/summarizer.d.ts +81 -0
- package/dist/mcp/history/summarizer.js +196 -0
- package/dist/mcp/history/summarizer.js.map +1 -0
- package/dist/mcp/history/walker.d.ts +57 -0
- package/dist/mcp/history/walker.js +156 -0
- package/dist/mcp/history/walker.js.map +1 -0
- package/dist/mcp/index.d.ts +13 -0
- package/dist/mcp/index.js +9 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/path-allowlist.d.ts +29 -0
- package/dist/mcp/path-allowlist.js +71 -0
- package/dist/mcp/path-allowlist.js.map +1 -0
- package/dist/mcp/result.d.ts +8 -0
- package/dist/mcp/result.js +18 -0
- package/dist/mcp/result.js.map +1 -0
- package/dist/mcp/schemas.d.ts +192 -0
- package/dist/mcp/schemas.js +174 -0
- package/dist/mcp/schemas.js.map +1 -0
- package/dist/mcp/serve.d.ts +15 -0
- package/dist/mcp/serve.js +71 -0
- package/dist/mcp/serve.js.map +1 -0
- package/dist/mcp/server.d.ts +11 -0
- package/dist/mcp/server.js +58 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/telemetry.d.ts +15 -0
- package/dist/mcp/telemetry.js +13 -0
- package/dist/mcp/telemetry.js.map +1 -0
- package/dist/mcp/tools/append-run-note.d.ts +18 -0
- package/dist/mcp/tools/append-run-note.js +47 -0
- package/dist/mcp/tools/append-run-note.js.map +1 -0
- package/dist/mcp/tools/append.d.ts +8 -0
- package/dist/mcp/tools/append.js +37 -0
- package/dist/mcp/tools/append.js.map +1 -0
- package/dist/mcp/tools/archive.d.ts +8 -0
- package/dist/mcp/tools/archive.js +72 -0
- package/dist/mcp/tools/archive.js.map +1 -0
- package/dist/mcp/tools/ask-operator.d.ts +34 -0
- package/dist/mcp/tools/ask-operator.js +97 -0
- package/dist/mcp/tools/ask-operator.js.map +1 -0
- package/dist/mcp/tools/canonical-for-topic.d.ts +6 -0
- package/dist/mcp/tools/canonical-for-topic.js +40 -0
- package/dist/mcp/tools/canonical-for-topic.js.map +1 -0
- package/dist/mcp/tools/decision-get.d.ts +6 -0
- package/dist/mcp/tools/decision-get.js +49 -0
- package/dist/mcp/tools/decision-get.js.map +1 -0
- package/dist/mcp/tools/decisions-for-symbol.d.ts +7 -0
- package/dist/mcp/tools/decisions-for-symbol.js +42 -0
- package/dist/mcp/tools/decisions-for-symbol.js.map +1 -0
- package/dist/mcp/tools/decisions-in-scope.d.ts +7 -0
- package/dist/mcp/tools/decisions-in-scope.js +47 -0
- package/dist/mcp/tools/decisions-in-scope.js.map +1 -0
- package/dist/mcp/tools/drop-task.d.ts +12 -0
- package/dist/mcp/tools/drop-task.js +68 -0
- package/dist/mcp/tools/drop-task.js.map +1 -0
- package/dist/mcp/tools/get-full.d.ts +7 -0
- package/dist/mcp/tools/get-full.js +46 -0
- package/dist/mcp/tools/get-full.js.map +1 -0
- package/dist/mcp/tools/ground-get.d.ts +7 -0
- package/dist/mcp/tools/ground-get.js +77 -0
- package/dist/mcp/tools/ground-get.js.map +1 -0
- package/dist/mcp/tools/index.d.ts +3 -0
- package/dist/mcp/tools/index.js +40 -0
- package/dist/mcp/tools/index.js.map +1 -0
- package/dist/mcp/tools/invariant-get.d.ts +6 -0
- package/dist/mcp/tools/invariant-get.js +49 -0
- package/dist/mcp/tools/invariant-get.js.map +1 -0
- package/dist/mcp/tools/invariants-in-scope.d.ts +7 -0
- package/dist/mcp/tools/invariants-in-scope.js +62 -0
- package/dist/mcp/tools/invariants-in-scope.js.map +1 -0
- package/dist/mcp/tools/query-history.d.ts +20 -0
- package/dist/mcp/tools/query-history.js +51 -0
- package/dist/mcp/tools/query-history.js.map +1 -0
- package/dist/mcp/tools/record-decision.d.ts +14 -0
- package/dist/mcp/tools/record-decision.js +98 -0
- package/dist/mcp/tools/record-decision.js.map +1 -0
- package/dist/mcp/tools/record-run-event.d.ts +10 -0
- package/dist/mcp/tools/record-run-event.js +32 -0
- package/dist/mcp/tools/record-run-event.js.map +1 -0
- package/dist/mcp/tools/resolve-attention.d.ts +31 -0
- package/dist/mcp/tools/resolve-attention.js +191 -0
- package/dist/mcp/tools/resolve-attention.js.map +1 -0
- package/dist/mcp/tools/search.d.ts +9 -0
- package/dist/mcp/tools/search.js +164 -0
- package/dist/mcp/tools/search.js.map +1 -0
- package/dist/mcp/tools/supersedes-chain.d.ts +6 -0
- package/dist/mcp/tools/supersedes-chain.js +66 -0
- package/dist/mcp/tools/supersedes-chain.js.map +1 -0
- package/dist/mcp/tools/timeline.d.ts +9 -0
- package/dist/mcp/tools/timeline.js +65 -0
- package/dist/mcp/tools/timeline.js.map +1 -0
- package/dist/mcp/tools/types.d.ts +9 -0
- package/dist/mcp/tools/types.js +2 -0
- package/dist/mcp/tools/types.js.map +1 -0
- package/dist/mirror/clone.d.ts +6 -0
- package/dist/mirror/clone.js +48 -0
- package/dist/mirror/clone.js.map +1 -0
- package/dist/mirror/dirty-overlap.d.ts +13 -0
- package/dist/mirror/dirty-overlap.js +42 -0
- package/dist/mirror/dirty-overlap.js.map +1 -0
- package/dist/mirror/index.d.ts +7 -0
- package/dist/mirror/index.js +7 -0
- package/dist/mirror/index.js.map +1 -0
- package/dist/mirror/paths.d.ts +18 -0
- package/dist/mirror/paths.js +45 -0
- package/dist/mirror/paths.js.map +1 -0
- package/dist/mirror/push.d.ts +9 -0
- package/dist/mirror/push.js +27 -0
- package/dist/mirror/push.js.map +1 -0
- package/dist/mirror/state.d.ts +4 -0
- package/dist/mirror/state.js +36 -0
- package/dist/mirror/state.js.map +1 -0
- package/dist/mirror/sync.d.ts +9 -0
- package/dist/mirror/sync.js +33 -0
- package/dist/mirror/sync.js.map +1 -0
- package/dist/mirror/types.d.ts +77 -0
- package/dist/mirror/types.js +2 -0
- package/dist/mirror/types.js.map +1 -0
- package/dist/paths/index.d.ts +23 -0
- package/dist/paths/index.js +50 -0
- package/dist/paths/index.js.map +1 -0
- package/dist/profiles/index.d.ts +3 -0
- package/dist/profiles/index.js +3 -0
- package/dist/profiles/index.js.map +1 -0
- package/dist/profiles/registry.d.ts +5 -0
- package/dist/profiles/registry.js +31 -0
- package/dist/profiles/registry.js.map +1 -0
- package/dist/profiles/types.d.ts +48 -0
- package/dist/profiles/types.js +11 -0
- package/dist/profiles/types.js.map +1 -0
- package/dist/profiles/unknown.d.ts +9 -0
- package/dist/profiles/unknown.js +17 -0
- package/dist/profiles/unknown.js.map +1 -0
- package/dist/prompt.d.ts +19 -0
- package/dist/prompt.js +50 -0
- package/dist/prompt.js.map +1 -0
- package/dist/sensors/attestation.d.ts +44 -0
- package/dist/sensors/attestation.js +262 -0
- package/dist/sensors/attestation.js.map +1 -0
- package/dist/sensors/catalog.d.ts +41 -0
- package/dist/sensors/catalog.js +123 -0
- package/dist/sensors/catalog.js.map +1 -0
- package/dist/sensors/decisions.d.ts +30 -0
- package/dist/sensors/decisions.js +393 -0
- package/dist/sensors/decisions.js.map +1 -0
- package/dist/sensors/diff.d.ts +27 -0
- package/dist/sensors/diff.js +148 -0
- package/dist/sensors/diff.js.map +1 -0
- package/dist/sensors/index.d.ts +13 -0
- package/dist/sensors/index.js +9 -0
- package/dist/sensors/index.js.map +1 -0
- package/dist/sensors/remediation.d.ts +20 -0
- package/dist/sensors/remediation.js +65 -0
- package/dist/sensors/remediation.js.map +1 -0
- package/dist/sensors/runner.d.ts +44 -0
- package/dist/sensors/runner.js +95 -0
- package/dist/sensors/runner.js.map +1 -0
- package/dist/sensors/structural.d.ts +30 -0
- package/dist/sensors/structural.js +204 -0
- package/dist/sensors/structural.js.map +1 -0
- package/dist/sensors/stub-catalog.d.ts +39 -0
- package/dist/sensors/stub-catalog.js +115 -0
- package/dist/sensors/stub-catalog.js.map +1 -0
- package/dist/sensors/types.d.ts +135 -0
- package/dist/sensors/types.js +14 -0
- package/dist/sensors/types.js.map +1 -0
- package/dist/session/events-marker.d.ts +39 -0
- package/dist/session/events-marker.js +74 -0
- package/dist/session/events-marker.js.map +1 -0
- package/dist/session/id.d.ts +83 -0
- package/dist/session/id.js +166 -0
- package/dist/session/id.js.map +1 -0
- package/dist/session/index.d.ts +14 -0
- package/dist/session/index.js +13 -0
- package/dist/session/index.js.map +1 -0
- package/dist/session-start/build.d.ts +53 -0
- package/dist/session-start/build.js +645 -0
- package/dist/session-start/build.js.map +1 -0
- package/dist/session-start/index.d.ts +18 -0
- package/dist/session-start/index.js +18 -0
- package/dist/session-start/index.js.map +1 -0
- package/dist/session-start/templates.d.ts +6 -0
- package/dist/session-start/templates.js +38 -0
- package/dist/session-start/templates.js.map +1 -0
- package/dist/status-line/format.d.ts +14 -0
- package/dist/status-line/format.js +40 -0
- package/dist/status-line/format.js.map +1 -0
- package/dist/status-line/index.d.ts +29 -0
- package/dist/status-line/index.js +14 -0
- package/dist/status-line/index.js.map +1 -0
- package/dist/status-line/reader.d.ts +13 -0
- package/dist/status-line/reader.js +76 -0
- package/dist/status-line/reader.js.map +1 -0
- package/dist/status-line/writer.d.ts +33 -0
- package/dist/status-line/writer.js +72 -0
- package/dist/status-line/writer.js.map +1 -0
- package/dist/tier0/classify.d.ts +10 -0
- package/dist/tier0/classify.js +110 -0
- package/dist/tier0/classify.js.map +1 -0
- package/dist/tier0/index.d.ts +2 -0
- package/dist/tier0/index.js +2 -0
- package/dist/tier0/index.js.map +1 -0
- package/dist/tier0/ollama.d.ts +22 -0
- package/dist/tier0/ollama.js +63 -0
- package/dist/tier0/ollama.js.map +1 -0
- package/dist/tier0/types.d.ts +24 -0
- package/dist/tier0/types.js +9 -0
- package/dist/tier0/types.js.map +1 -0
- package/dist/tightener/index.d.ts +4 -0
- package/dist/tightener/index.js +4 -0
- package/dist/tightener/index.js.map +1 -0
- package/dist/tightener/prompt.d.ts +3 -0
- package/dist/tightener/prompt.js +67 -0
- package/dist/tightener/prompt.js.map +1 -0
- package/dist/tightener/schema.d.ts +68 -0
- package/dist/tightener/schema.js +44 -0
- package/dist/tightener/schema.js.map +1 -0
- package/dist/tightener/tighten.d.ts +2 -0
- package/dist/tightener/tighten.js +66 -0
- package/dist/tightener/tighten.js.map +1 -0
- package/dist/tightener/types.d.ts +74 -0
- package/dist/tightener/types.js +6 -0
- package/dist/tightener/types.js.map +1 -0
- package/dist/voice/index.d.ts +4 -0
- package/dist/voice/index.js +4 -0
- package/dist/voice/index.js.map +1 -0
- package/dist/voice/model.d.ts +23 -0
- package/dist/voice/model.js +46 -0
- package/dist/voice/model.js.map +1 -0
- package/dist/voice/pipe.d.ts +9 -0
- package/dist/voice/pipe.js +47 -0
- package/dist/voice/pipe.js.map +1 -0
- package/dist/voice/transcribe.d.ts +3 -0
- package/dist/voice/transcribe.js +43 -0
- package/dist/voice/transcribe.js.map +1 -0
- package/dist/voice/types.d.ts +26 -0
- package/dist/voice/types.js +9 -0
- package/dist/voice/types.js.map +1 -0
- package/package.json +54 -0
- package/templates/.archive/README.md +67 -0
- package/templates/.cairn/JOIN.md +87 -0
- package/templates/.cairn/config/sensors.yaml +185 -0
- package/templates/.cairn/config/stub-patterns.yaml +231 -0
- package/templates/.cairn/config/trust-policy.yaml +95 -0
- package/templates/.cairn/config/workflow.md +230 -0
- package/templates/.cairn/git-hooks/commit-msg +17 -0
- package/templates/.cairn/git-hooks/post-commit +28 -0
- package/templates/.cairn/git-hooks/pre-commit +24 -0
- package/templates/.cairn/ground/brand/overview.md +24 -0
- package/templates/.cairn/ground/brand/voice.md +20 -0
- package/templates/.cairn/ground/canonical-map/topics.yaml +54 -0
- package/templates/.cairn/ground/capabilities/mcp-tools.yaml +4 -0
- package/templates/.cairn/ground/capabilities/skills.yaml +3 -0
- package/templates/.cairn/ground/capabilities/snippets.yaml +3 -0
- package/templates/.cairn/ground/manifest.yaml +16 -0
- package/templates/.cairn/ground/product/personas.yaml +4 -0
- package/templates/.cairn/ground/product/positioning.md +21 -0
- package/templates/.claude/settings.json +57 -0
- package/templates/.github/workflows/cairn-check.yml +31 -0
- package/templates/.mcp.json +8 -0
- package/templates/README.md +24 -0
|
@@ -0,0 +1,645 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `buildSessionStartContext` — composes the SessionStart payload from
|
|
3
|
+
* a cairn-adopted repo's state. Read-only; no side effects beyond
|
|
4
|
+
* filesystem reads.
|
|
5
|
+
*/
|
|
6
|
+
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
7
|
+
import { basename, dirname, join, resolve } from "node:path";
|
|
8
|
+
import { parse as parseYaml } from "yaml";
|
|
9
|
+
import { buildHandoffBlock } from "../context/index.js";
|
|
10
|
+
import { buildDecisionsLedger, buildInvariantsLedger, parseFrontmatter, } from "../ground/index.js";
|
|
11
|
+
import { loadSensorRegistry } from "../sensors/catalog.js";
|
|
12
|
+
import { SESSION_START_HEADER, TOOL_QUICK_REFERENCE, TWO_ZONE_REMINDER_BASE, } from "./templates.js";
|
|
13
|
+
const DEFAULT_MAX_CHARS = 12_000;
|
|
14
|
+
const DECISIONS_CAP = 15;
|
|
15
|
+
const INVARIANTS_CAP = 10;
|
|
16
|
+
const DRAFTS_CAP = 5;
|
|
17
|
+
const QUALITY_TAIL_CAP = 3;
|
|
18
|
+
const TASK_BODY_CAP = 800;
|
|
19
|
+
/**
|
|
20
|
+
* Walk up from `cwd` looking for a `.cairn/` directory. Returns the
|
|
21
|
+
* dir containing it (the repo root) or null if none found within 12
|
|
22
|
+
* ancestors.
|
|
23
|
+
*/
|
|
24
|
+
export function resolveRepoRoot(cwd) {
|
|
25
|
+
let dir = resolve(cwd);
|
|
26
|
+
for (let i = 0; i < 12; i++) {
|
|
27
|
+
if (existsSync(join(dir, ".cairn")) && statSync(join(dir, ".cairn")).isDirectory()) {
|
|
28
|
+
return dir;
|
|
29
|
+
}
|
|
30
|
+
const parent = dirname(dir);
|
|
31
|
+
if (parent === dir)
|
|
32
|
+
return null;
|
|
33
|
+
dir = parent;
|
|
34
|
+
}
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
export async function buildSessionStartContext(args) {
|
|
38
|
+
const maxChars = args.maxChars ?? DEFAULT_MAX_CHARS;
|
|
39
|
+
const includeToolReference = args.includeToolReference !== false;
|
|
40
|
+
const queryHistoryAvailable = args.queryHistoryAvailable !== false;
|
|
41
|
+
const warnings = [];
|
|
42
|
+
const counts = {
|
|
43
|
+
decisions: 0,
|
|
44
|
+
invariants: 0,
|
|
45
|
+
pendingDrafts: 0,
|
|
46
|
+
qualityGrades: 0,
|
|
47
|
+
activeTasks: 0,
|
|
48
|
+
};
|
|
49
|
+
const sectionsRendered = [];
|
|
50
|
+
const sectionsDropped = [];
|
|
51
|
+
// ── Section 0 — run handoff (CONTEXT_CONTINUITY_SPEC §4) ─────────────
|
|
52
|
+
// Inject the prior-run handoff block when the hook source indicates a
|
|
53
|
+
// boundary that benefits from it. `null` → no in-flight run / no
|
|
54
|
+
// commits since sha_pin → section omitted entirely.
|
|
55
|
+
let runHandoffSection = null;
|
|
56
|
+
if (args.source === "resume" || args.source === "compact" || args.source === "startup") {
|
|
57
|
+
try {
|
|
58
|
+
runHandoffSection = await buildHandoffBlock(args.repoRoot);
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
warnings.push(`handoff builder failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
const fixedHeader = SESSION_START_HEADER;
|
|
65
|
+
const fixedTwoZone = composeTwoZoneReminder(queryHistoryAvailable);
|
|
66
|
+
const fixedToolReference = TOOL_QUICK_REFERENCE;
|
|
67
|
+
// ── Section 2 — decisions in scope ─────────────────────────────────
|
|
68
|
+
const decisionEntries = safeBuildDecisionsLedger(args.repoRoot, warnings);
|
|
69
|
+
counts.decisions = decisionEntries.length;
|
|
70
|
+
const filteredDecisions = filterDecisionsToScope(decisionEntries, args.scopeRelPath);
|
|
71
|
+
const decisionsSection = renderDecisionsSection(filteredDecisions);
|
|
72
|
+
// ── Section 3 — invariants active ──────────────────────────────────
|
|
73
|
+
const invariantEntries = safeBuildInvariantsLedger(args.repoRoot, warnings);
|
|
74
|
+
counts.invariants = invariantEntries.length;
|
|
75
|
+
const decisionScopeById = scopeMapFromDecisions(decisionEntries);
|
|
76
|
+
const filteredInvariants = filterInvariantsToScope(invariantEntries, decisionScopeById, args.scopeRelPath);
|
|
77
|
+
const invariantsSection = renderInvariantsSection(filteredInvariants);
|
|
78
|
+
// ── Section 4 — current task ───────────────────────────────────────
|
|
79
|
+
const tasks = listActiveTasks(args.repoRoot);
|
|
80
|
+
counts.activeTasks = tasks.length;
|
|
81
|
+
const currentTaskSection = renderCurrentTaskSection(args.repoRoot, tasks);
|
|
82
|
+
// ── Section 5 — quality grades ─────────────────────────────────────
|
|
83
|
+
const grades = readQualityGrades(args.repoRoot, warnings);
|
|
84
|
+
counts.qualityGrades = grades.length;
|
|
85
|
+
const qualityGradesSection = renderQualityGradesSection(grades);
|
|
86
|
+
// ── Section 6 — pending drafts ─────────────────────────────────────
|
|
87
|
+
const drafts = listPendingDrafts(args.repoRoot, warnings);
|
|
88
|
+
counts.pendingDrafts = drafts.length;
|
|
89
|
+
const pendingDraftsSection = renderPendingDraftsSection(drafts);
|
|
90
|
+
// ── Section 1.5 — brand + product positioning (always injected) ───
|
|
91
|
+
const brandAndPositioningSection = readBrandAndPositioning(args.repoRoot, warnings);
|
|
92
|
+
// ── First-session onboarding block (Phase 6.6) ────────────────────
|
|
93
|
+
// Fires once: decisions_count === 0 AND invariants_count === 0 AND a
|
|
94
|
+
// baseline audit yaml exists. After the first DEC is accepted, the
|
|
95
|
+
// condition no longer holds and this section disappears for good.
|
|
96
|
+
let firstSessionOnboardingSection = null;
|
|
97
|
+
if (counts.decisions === 0 && counts.invariants === 0) {
|
|
98
|
+
firstSessionOnboardingSection = renderFirstSessionOnboarding({
|
|
99
|
+
repoRoot: args.repoRoot,
|
|
100
|
+
pendingDrafts: counts.pendingDrafts,
|
|
101
|
+
warnings,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
// Truncation strategy per spec: always include 1 + 7; then 4, 2, 3,
|
|
105
|
+
// 6, 5; drop in reverse order if over cap.
|
|
106
|
+
const orderedSections = [];
|
|
107
|
+
if (firstSessionOnboardingSection !== null) {
|
|
108
|
+
orderedSections.push({
|
|
109
|
+
id: "first_session_onboarding",
|
|
110
|
+
body: firstSessionOnboardingSection,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
if (runHandoffSection !== null) {
|
|
114
|
+
orderedSections.push({ id: "run_handoff", body: runHandoffSection });
|
|
115
|
+
}
|
|
116
|
+
orderedSections.push({ id: "header", body: fixedHeader });
|
|
117
|
+
orderedSections.push({ id: "two_zone_reminder", body: fixedTwoZone });
|
|
118
|
+
if (brandAndPositioningSection !== null) {
|
|
119
|
+
orderedSections.push({ id: "brand_and_positioning", body: brandAndPositioningSection });
|
|
120
|
+
}
|
|
121
|
+
if (includeToolReference) {
|
|
122
|
+
orderedSections.push({ id: "tool_quick_reference", body: fixedToolReference });
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
sectionsDropped.push("tool_quick_reference");
|
|
126
|
+
}
|
|
127
|
+
if (currentTaskSection !== null) {
|
|
128
|
+
orderedSections.push({ id: "current_task", body: currentTaskSection });
|
|
129
|
+
}
|
|
130
|
+
if (decisionsSection !== null) {
|
|
131
|
+
orderedSections.push({ id: "decisions_in_scope", body: decisionsSection });
|
|
132
|
+
}
|
|
133
|
+
if (invariantsSection !== null) {
|
|
134
|
+
orderedSections.push({ id: "invariants_active", body: invariantsSection });
|
|
135
|
+
}
|
|
136
|
+
if (pendingDraftsSection !== null) {
|
|
137
|
+
orderedSections.push({ id: "pending_drafts", body: pendingDraftsSection });
|
|
138
|
+
}
|
|
139
|
+
if (qualityGradesSection !== null) {
|
|
140
|
+
orderedSections.push({ id: "quality_grades_tail", body: qualityGradesSection });
|
|
141
|
+
}
|
|
142
|
+
// Greedy fill within budget; dropping in reverse order lets us keep
|
|
143
|
+
// the load-bearing sections (header / reminder / tools) while
|
|
144
|
+
// shedding optional context first.
|
|
145
|
+
const dropPriority = [
|
|
146
|
+
"quality_grades_tail",
|
|
147
|
+
"pending_drafts",
|
|
148
|
+
"brand_and_positioning",
|
|
149
|
+
"invariants_active",
|
|
150
|
+
"decisions_in_scope",
|
|
151
|
+
"current_task",
|
|
152
|
+
"tool_quick_reference",
|
|
153
|
+
"two_zone_reminder",
|
|
154
|
+
"header",
|
|
155
|
+
"run_handoff",
|
|
156
|
+
"first_session_onboarding",
|
|
157
|
+
];
|
|
158
|
+
let kept = orderedSections.slice();
|
|
159
|
+
while (computeTotalChars(kept) > maxChars && kept.length > 0) {
|
|
160
|
+
let dropped = false;
|
|
161
|
+
for (const candidate of dropPriority) {
|
|
162
|
+
const idx = kept.findIndex((s) => s.id === candidate);
|
|
163
|
+
if (idx !== -1) {
|
|
164
|
+
sectionsDropped.push(candidate);
|
|
165
|
+
kept.splice(idx, 1);
|
|
166
|
+
dropped = true;
|
|
167
|
+
break;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
if (!dropped)
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
for (const s of kept)
|
|
174
|
+
sectionsRendered.push(s.id);
|
|
175
|
+
// Anything in orderedSections that ended up not in `kept` is in
|
|
176
|
+
// sectionsDropped above; deduplicate while preserving order.
|
|
177
|
+
const seenDropped = new Set(sectionsDropped);
|
|
178
|
+
for (const s of orderedSections) {
|
|
179
|
+
if (!sectionsRendered.includes(s.id) && !seenDropped.has(s.id)) {
|
|
180
|
+
sectionsDropped.push(s.id);
|
|
181
|
+
seenDropped.add(s.id);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
const additionalContext = kept.map((s) => s.body).join("\n\n");
|
|
185
|
+
return {
|
|
186
|
+
additionalContext,
|
|
187
|
+
sectionsRendered,
|
|
188
|
+
sectionsDropped,
|
|
189
|
+
totalChars: additionalContext.length,
|
|
190
|
+
counts,
|
|
191
|
+
warnings,
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
function composeTwoZoneReminder(queryHistoryAvailable) {
|
|
195
|
+
if (queryHistoryAvailable)
|
|
196
|
+
return TWO_ZONE_REMINDER_BASE;
|
|
197
|
+
return `${TWO_ZONE_REMINDER_BASE}
|
|
198
|
+
|
|
199
|
+
NOTE: cairn_query_history is not registered in this project's MCP
|
|
200
|
+
configuration; archive reads are unreachable. Use cairn_decision_get
|
|
201
|
+
or cairn_canonical_for_topic for current-canonical access only.`;
|
|
202
|
+
}
|
|
203
|
+
function readBrandAndPositioning(repoRoot, warnings) {
|
|
204
|
+
const brandPath = join(repoRoot, ".cairn", "ground", "brand", "overview.md");
|
|
205
|
+
const positioningPath = join(repoRoot, ".cairn", "ground", "product", "positioning.md");
|
|
206
|
+
const parts = [];
|
|
207
|
+
for (const [label, path] of [
|
|
208
|
+
["Brand overview", brandPath],
|
|
209
|
+
["Product positioning", positioningPath],
|
|
210
|
+
]) {
|
|
211
|
+
if (!existsSync(path))
|
|
212
|
+
continue;
|
|
213
|
+
try {
|
|
214
|
+
const text = readFileSync(path, "utf8");
|
|
215
|
+
const parsed = parseFrontmatter(text);
|
|
216
|
+
const fm = (parsed.frontmatter ?? {});
|
|
217
|
+
const status = typeof fm["status"] === "string" ? fm["status"] : null;
|
|
218
|
+
const body = parsed.body.trim();
|
|
219
|
+
if (body.length === 0)
|
|
220
|
+
continue;
|
|
221
|
+
const draftHint = status === "draft"
|
|
222
|
+
? " [DRAFT — operator has not filled this in; ask before making design decisions]"
|
|
223
|
+
: "";
|
|
224
|
+
parts.push(`### ${label}${draftHint}\n\n${body}`);
|
|
225
|
+
}
|
|
226
|
+
catch (err) {
|
|
227
|
+
warnings.push(`${label} read failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
if (parts.length === 0)
|
|
231
|
+
return null;
|
|
232
|
+
return `## Brand and product context\n\n${parts.join("\n\n")}`;
|
|
233
|
+
}
|
|
234
|
+
function computeTotalChars(sections) {
|
|
235
|
+
return sections.reduce((sum, s) => sum + s.body.length + 2, 0);
|
|
236
|
+
}
|
|
237
|
+
function safeBuildDecisionsLedger(repoRoot, warnings) {
|
|
238
|
+
try {
|
|
239
|
+
return buildDecisionsLedger({ repoRoot });
|
|
240
|
+
}
|
|
241
|
+
catch (err) {
|
|
242
|
+
warnings.push(`decisions ledger read failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
243
|
+
return [];
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
function safeBuildInvariantsLedger(repoRoot, warnings) {
|
|
247
|
+
try {
|
|
248
|
+
return buildInvariantsLedger({ repoRoot });
|
|
249
|
+
}
|
|
250
|
+
catch (err) {
|
|
251
|
+
warnings.push(`invariants ledger read failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
252
|
+
return [];
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
function scopeMapFromDecisions(decisions) {
|
|
256
|
+
const out = new Map();
|
|
257
|
+
for (const d of decisions) {
|
|
258
|
+
if (d.scope_globs && d.scope_globs.length > 0)
|
|
259
|
+
out.set(d.id, d.scope_globs);
|
|
260
|
+
}
|
|
261
|
+
return out;
|
|
262
|
+
}
|
|
263
|
+
function filterDecisionsToScope(decisions, scopeRelPath) {
|
|
264
|
+
if (!scopeRelPath || scopeRelPath.length === 0 || scopeRelPath === ".")
|
|
265
|
+
return decisions;
|
|
266
|
+
const filtered = decisions.filter((d) => {
|
|
267
|
+
const globs = d.scope_globs ?? [];
|
|
268
|
+
if (globs.length === 0)
|
|
269
|
+
return true;
|
|
270
|
+
return globs.some((g) => relPathOverlapsGlob(scopeRelPath, g));
|
|
271
|
+
});
|
|
272
|
+
return filtered.length > 0 ? filtered : decisions;
|
|
273
|
+
}
|
|
274
|
+
function filterInvariantsToScope(invariants, decisionScopeById, scopeRelPath) {
|
|
275
|
+
if (!scopeRelPath || scopeRelPath.length === 0 || scopeRelPath === ".")
|
|
276
|
+
return invariants;
|
|
277
|
+
const filtered = invariants.filter((inv) => {
|
|
278
|
+
if (!inv.source_decision)
|
|
279
|
+
return true;
|
|
280
|
+
const globs = decisionScopeById.get(inv.source_decision);
|
|
281
|
+
if (!globs || globs.length === 0)
|
|
282
|
+
return true;
|
|
283
|
+
return globs.some((g) => relPathOverlapsGlob(scopeRelPath, g));
|
|
284
|
+
});
|
|
285
|
+
return filtered.length > 0 ? filtered : invariants;
|
|
286
|
+
}
|
|
287
|
+
function relPathOverlapsGlob(relPath, glob) {
|
|
288
|
+
const globPrefix = glob.replace(/\*\*.*$/, "").replace(/\*+$/, "");
|
|
289
|
+
if (globPrefix.length === 0)
|
|
290
|
+
return true;
|
|
291
|
+
return relPath.startsWith(globPrefix) || globPrefix.startsWith(relPath);
|
|
292
|
+
}
|
|
293
|
+
function renderDecisionsSection(decisions) {
|
|
294
|
+
if (decisions.length === 0)
|
|
295
|
+
return null;
|
|
296
|
+
const lines = [];
|
|
297
|
+
lines.push(`## Decisions in scope (${decisions.length} accepted)`);
|
|
298
|
+
lines.push("");
|
|
299
|
+
const slice = decisions.slice(0, DECISIONS_CAP);
|
|
300
|
+
for (const d of slice) {
|
|
301
|
+
const scope = d.scope_globs && d.scope_globs.length > 0 ? d.scope_globs.join(", ") : "(no scope)";
|
|
302
|
+
const supersedes = d.supersedes ? d.supersedes : "—";
|
|
303
|
+
lines.push(`- **${d.id}** — ${d.title}`);
|
|
304
|
+
lines.push(` status: ${d.status}; scope: ${scope}; supersedes: ${supersedes}`);
|
|
305
|
+
}
|
|
306
|
+
if (decisions.length > DECISIONS_CAP) {
|
|
307
|
+
lines.push(`…${decisions.length - DECISIONS_CAP} additional decision${decisions.length - DECISIONS_CAP === 1 ? "" : "s"} — call \`cairn_decisions_in_scope(globs[])\` for the rest.`);
|
|
308
|
+
}
|
|
309
|
+
return lines.join("\n");
|
|
310
|
+
}
|
|
311
|
+
function renderInvariantsSection(invariants) {
|
|
312
|
+
if (invariants.length === 0)
|
|
313
|
+
return null;
|
|
314
|
+
const lines = [];
|
|
315
|
+
lines.push(`## §V invariants active (${invariants.length})`);
|
|
316
|
+
lines.push("");
|
|
317
|
+
const slice = invariants.slice(0, INVARIANTS_CAP);
|
|
318
|
+
for (const inv of slice) {
|
|
319
|
+
lines.push(`- **${inv.id}** — ${inv.title} source_decision: ${inv.source_decision ?? "(none)"}`);
|
|
320
|
+
}
|
|
321
|
+
if (invariants.length > INVARIANTS_CAP) {
|
|
322
|
+
lines.push(`…${invariants.length - INVARIANTS_CAP} additional — call \`cairn_invariants_in_scope(globs[])\`.`);
|
|
323
|
+
}
|
|
324
|
+
return lines.join("\n");
|
|
325
|
+
}
|
|
326
|
+
function listActiveTasks(repoRoot) {
|
|
327
|
+
const dir = join(repoRoot, ".cairn", "tasks", "active");
|
|
328
|
+
if (!existsSync(dir))
|
|
329
|
+
return [];
|
|
330
|
+
let entries;
|
|
331
|
+
try {
|
|
332
|
+
entries = readdirSync(dir, { withFileTypes: true, encoding: "utf8" });
|
|
333
|
+
}
|
|
334
|
+
catch {
|
|
335
|
+
return [];
|
|
336
|
+
}
|
|
337
|
+
const out = [];
|
|
338
|
+
for (const e of entries) {
|
|
339
|
+
if (!e.isDirectory())
|
|
340
|
+
continue;
|
|
341
|
+
const candidates = [
|
|
342
|
+
join(dir, e.name, "spec.tightened.md"),
|
|
343
|
+
join(dir, e.name, "spec.md"),
|
|
344
|
+
];
|
|
345
|
+
let target = null;
|
|
346
|
+
for (const c of candidates) {
|
|
347
|
+
if (existsSync(c)) {
|
|
348
|
+
target = c;
|
|
349
|
+
break;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
if (!target)
|
|
353
|
+
continue;
|
|
354
|
+
let text = "";
|
|
355
|
+
let mtime = 0;
|
|
356
|
+
try {
|
|
357
|
+
text = readFileSync(target, "utf8");
|
|
358
|
+
mtime = statSync(target).mtimeMs;
|
|
359
|
+
}
|
|
360
|
+
catch {
|
|
361
|
+
continue;
|
|
362
|
+
}
|
|
363
|
+
const parsed = parseFrontmatter(text);
|
|
364
|
+
const fm = (parsed.frontmatter ?? {});
|
|
365
|
+
const status = typeof fm["status"] === "string" ? fm["status"] : null;
|
|
366
|
+
out.push({
|
|
367
|
+
id: e.name,
|
|
368
|
+
specPath: target.startsWith(repoRoot) ? target.slice(repoRoot.length + 1) : target,
|
|
369
|
+
specBody: parsed.body,
|
|
370
|
+
status,
|
|
371
|
+
mtime,
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
out.sort((a, b) => b.mtime - a.mtime);
|
|
375
|
+
return out;
|
|
376
|
+
}
|
|
377
|
+
function renderCurrentTaskSection(_repoRoot, tasks) {
|
|
378
|
+
if (tasks.length === 0)
|
|
379
|
+
return null;
|
|
380
|
+
const lines = [];
|
|
381
|
+
if (tasks.length === 1) {
|
|
382
|
+
const t = tasks[0];
|
|
383
|
+
if (t === undefined)
|
|
384
|
+
return null;
|
|
385
|
+
lines.push("## Current task");
|
|
386
|
+
lines.push("");
|
|
387
|
+
lines.push(`ID: ${t.id}`);
|
|
388
|
+
if (t.status !== null)
|
|
389
|
+
lines.push(`Status: ${t.status}`);
|
|
390
|
+
lines.push(`Path: ${t.specPath.replace(/\\/g, "/")}`);
|
|
391
|
+
lines.push("");
|
|
392
|
+
const body = t.specBody.trim();
|
|
393
|
+
const cap = body.length > TASK_BODY_CAP
|
|
394
|
+
? `${body.slice(0, TASK_BODY_CAP).trimEnd()}\n…[truncated; full spec via cairn_get_full({id, kind:"task"})]`
|
|
395
|
+
: body;
|
|
396
|
+
lines.push(cap);
|
|
397
|
+
return lines.join("\n");
|
|
398
|
+
}
|
|
399
|
+
lines.push(`## Active tasks (${tasks.length})`);
|
|
400
|
+
lines.push("");
|
|
401
|
+
for (const t of tasks.slice(0, 8)) {
|
|
402
|
+
const titleMatch = t.specBody.match(/^#\s+(.+)$/m);
|
|
403
|
+
const title = titleMatch?.[1] ?? t.id;
|
|
404
|
+
lines.push(`- **${t.id}** — ${title} status: ${t.status ?? "(unknown)"}`);
|
|
405
|
+
}
|
|
406
|
+
if (tasks.length > 8)
|
|
407
|
+
lines.push(`…${tasks.length - 8} more.`);
|
|
408
|
+
lines.push("");
|
|
409
|
+
lines.push("Multiple active tasks; call `cairn_get_full({id, kind:\"task\"})` to read any.");
|
|
410
|
+
return lines.join("\n");
|
|
411
|
+
}
|
|
412
|
+
function readQualityGrades(repoRoot, warnings) {
|
|
413
|
+
const path = join(repoRoot, ".cairn", "ground", "quality-grades.yaml");
|
|
414
|
+
if (!existsSync(path))
|
|
415
|
+
return [];
|
|
416
|
+
let parsed;
|
|
417
|
+
try {
|
|
418
|
+
parsed = parseYaml(readFileSync(path, "utf8"));
|
|
419
|
+
}
|
|
420
|
+
catch (err) {
|
|
421
|
+
warnings.push(`quality-grades.yaml unparseable: ${err instanceof Error ? err.message : String(err)}`);
|
|
422
|
+
return [];
|
|
423
|
+
}
|
|
424
|
+
if (typeof parsed !== "object" || parsed === null)
|
|
425
|
+
return [];
|
|
426
|
+
const modulesRaw = parsed.modules;
|
|
427
|
+
if (!Array.isArray(modulesRaw))
|
|
428
|
+
return [];
|
|
429
|
+
const out = [];
|
|
430
|
+
for (const m of modulesRaw) {
|
|
431
|
+
if (typeof m !== "object" || m === null)
|
|
432
|
+
continue;
|
|
433
|
+
const mm = m;
|
|
434
|
+
if (typeof mm["module"] !== "string")
|
|
435
|
+
continue;
|
|
436
|
+
if (typeof mm["score"] !== "number")
|
|
437
|
+
continue;
|
|
438
|
+
out.push({
|
|
439
|
+
module: mm["module"],
|
|
440
|
+
score: mm["score"],
|
|
441
|
+
pass_rate: typeof mm["pass_rate"] === "number" ? mm["pass_rate"] : 0,
|
|
442
|
+
drift_count: typeof mm["drift_count"] === "number" ? mm["drift_count"] : 0,
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
out.sort((a, b) => a.score - b.score);
|
|
446
|
+
return out;
|
|
447
|
+
}
|
|
448
|
+
function renderQualityGradesSection(grades) {
|
|
449
|
+
if (grades.length === 0)
|
|
450
|
+
return null;
|
|
451
|
+
const tail = grades.slice(0, QUALITY_TAIL_CAP);
|
|
452
|
+
const lines = [];
|
|
453
|
+
lines.push(`## Quality grades — weakest module${tail.length === 1 ? "" : "s"}`);
|
|
454
|
+
lines.push("");
|
|
455
|
+
for (const g of tail) {
|
|
456
|
+
lines.push(`- ${g.module}: score ${g.score}/100, pass_rate ${g.pass_rate.toFixed(2)}, drift_count ${g.drift_count}`);
|
|
457
|
+
}
|
|
458
|
+
return lines.join("\n");
|
|
459
|
+
}
|
|
460
|
+
function listPendingDrafts(repoRoot, warnings) {
|
|
461
|
+
const dir = join(repoRoot, ".cairn", "ground", "decisions", "_inbox");
|
|
462
|
+
if (!existsSync(dir))
|
|
463
|
+
return [];
|
|
464
|
+
let entries;
|
|
465
|
+
try {
|
|
466
|
+
entries = readdirSync(dir, { withFileTypes: true, encoding: "utf8" });
|
|
467
|
+
}
|
|
468
|
+
catch {
|
|
469
|
+
return [];
|
|
470
|
+
}
|
|
471
|
+
const out = [];
|
|
472
|
+
for (const e of entries) {
|
|
473
|
+
if (!e.isFile())
|
|
474
|
+
continue;
|
|
475
|
+
if (!e.name.endsWith(".draft.md"))
|
|
476
|
+
continue;
|
|
477
|
+
const abs = join(dir, e.name);
|
|
478
|
+
let text;
|
|
479
|
+
try {
|
|
480
|
+
text = readFileSync(abs, "utf8");
|
|
481
|
+
}
|
|
482
|
+
catch (err) {
|
|
483
|
+
warnings.push(`draft ${e.name} unreadable: ${err instanceof Error ? err.message : String(err)}`);
|
|
484
|
+
continue;
|
|
485
|
+
}
|
|
486
|
+
const parsed = parseFrontmatter(text);
|
|
487
|
+
const fm = (parsed.frontmatter ?? {});
|
|
488
|
+
const id = typeof fm["id"] === "string" ? fm["id"] : e.name.replace(/\.draft\.md$/, "");
|
|
489
|
+
const title = typeof fm["title"] === "string" ? fm["title"] : "(untitled draft)";
|
|
490
|
+
const captureSource = typeof fm["capture_source"] === "string" ? fm["capture_source"] : null;
|
|
491
|
+
const decidedAt = typeof fm["decided_at"] === "string" ? fm["decided_at"] : null;
|
|
492
|
+
out.push({ id, title, capture_source: captureSource, decided_at: decidedAt });
|
|
493
|
+
}
|
|
494
|
+
out.sort((a, b) => a.id.localeCompare(b.id));
|
|
495
|
+
return out;
|
|
496
|
+
}
|
|
497
|
+
function renderFirstSessionOnboarding(args) {
|
|
498
|
+
const audit = readLatestBaselineAudit(args.repoRoot, args.warnings);
|
|
499
|
+
if (audit === null)
|
|
500
|
+
return null;
|
|
501
|
+
const projectName = readProjectSlug(args.repoRoot) ?? basename(args.repoRoot);
|
|
502
|
+
const minutesAgo = audit.runAt !== null ? minutesSince(audit.runAt) : null;
|
|
503
|
+
const sensorIds = readActiveSensorIds(args.repoRoot, args.warnings);
|
|
504
|
+
const lines = [];
|
|
505
|
+
lines.push(`⬡ Cairn active — ${projectName}`);
|
|
506
|
+
lines.push("");
|
|
507
|
+
if (minutesAgo !== null) {
|
|
508
|
+
lines.push(` This project was adopted ${humanizeMinutes(minutesAgo)}. Project brain is new.`);
|
|
509
|
+
}
|
|
510
|
+
else {
|
|
511
|
+
lines.push(" This project was adopted recently. Project brain is new.");
|
|
512
|
+
}
|
|
513
|
+
lines.push("");
|
|
514
|
+
if (sensorIds.length > 0) {
|
|
515
|
+
const head = sensorIds.slice(0, 3).join(" · ");
|
|
516
|
+
const more = sensorIds.length > 3
|
|
517
|
+
? ` + ${sensorIds.length - 3} more`
|
|
518
|
+
: "";
|
|
519
|
+
lines.push(" Sensors active (run on complete diff after you emit attestation.yaml):");
|
|
520
|
+
lines.push(` ${head}${more}`);
|
|
521
|
+
lines.push("");
|
|
522
|
+
}
|
|
523
|
+
if (audit.totalFindings > 0) {
|
|
524
|
+
lines.push(` Baseline debt: ${audit.totalFindings} pre-Cairn violation${audit.totalFindings === 1 ? "" : "s"} found in existing code.`);
|
|
525
|
+
lines.push(" Run `cairn attention` to review before starting work.");
|
|
526
|
+
lines.push("");
|
|
527
|
+
}
|
|
528
|
+
else {
|
|
529
|
+
lines.push(` Baseline scan ran clean — no pre-Cairn violations on ${audit.filesScanned} source file${audit.filesScanned === 1 ? "" : "s"}.`);
|
|
530
|
+
lines.push("");
|
|
531
|
+
}
|
|
532
|
+
if (args.pendingDrafts > 0) {
|
|
533
|
+
lines.push(` DEC drafts awaiting review: ${args.pendingDrafts}`);
|
|
534
|
+
lines.push(" Run `cairn attention` to confirm or discard.");
|
|
535
|
+
lines.push("");
|
|
536
|
+
}
|
|
537
|
+
lines.push(" To capture a decision during this session: /direction <your instruction>");
|
|
538
|
+
return lines.join("\n");
|
|
539
|
+
}
|
|
540
|
+
function readLatestBaselineAudit(repoRoot, warnings) {
|
|
541
|
+
const dir = join(repoRoot, ".cairn", "baseline");
|
|
542
|
+
if (!existsSync(dir))
|
|
543
|
+
return null;
|
|
544
|
+
let entries;
|
|
545
|
+
try {
|
|
546
|
+
entries = readdirSync(dir, { encoding: "utf8" });
|
|
547
|
+
}
|
|
548
|
+
catch (err) {
|
|
549
|
+
warnings.push(`baseline dir read failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
550
|
+
return null;
|
|
551
|
+
}
|
|
552
|
+
const matching = entries
|
|
553
|
+
.filter((name) => /^sensor-audit-.*\.yaml$/.test(name))
|
|
554
|
+
.sort();
|
|
555
|
+
const latest = matching.at(-1);
|
|
556
|
+
if (latest === undefined)
|
|
557
|
+
return null;
|
|
558
|
+
const abs = join(dir, latest);
|
|
559
|
+
try {
|
|
560
|
+
const parsed = parseYaml(readFileSync(abs, "utf8"));
|
|
561
|
+
const runAt = typeof parsed["run_at"] === "string" ? parsed["run_at"] : null;
|
|
562
|
+
const totalFindings = typeof parsed["total_findings"] === "number"
|
|
563
|
+
? parsed["total_findings"]
|
|
564
|
+
: 0;
|
|
565
|
+
const filesScanned = typeof parsed["files_scanned"] === "number"
|
|
566
|
+
? parsed["files_scanned"]
|
|
567
|
+
: 0;
|
|
568
|
+
return { runAt, totalFindings, filesScanned };
|
|
569
|
+
}
|
|
570
|
+
catch (err) {
|
|
571
|
+
warnings.push(`baseline audit unreadable: ${err instanceof Error ? err.message : String(err)}`);
|
|
572
|
+
return null;
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
function readActiveSensorIds(repoRoot, warnings) {
|
|
576
|
+
try {
|
|
577
|
+
const reg = loadSensorRegistry(repoRoot);
|
|
578
|
+
const disabled = new Set(reg.disabled_per_project ?? []);
|
|
579
|
+
return reg.sensors
|
|
580
|
+
.map((s) => s.id)
|
|
581
|
+
.filter((id) => id.length > 0)
|
|
582
|
+
.filter((id) => !disabled.has(id));
|
|
583
|
+
}
|
|
584
|
+
catch (err) {
|
|
585
|
+
warnings.push(`sensor registry read failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
586
|
+
return [];
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
function readProjectSlug(repoRoot) {
|
|
590
|
+
const path = join(repoRoot, ".cairn", "config.yaml");
|
|
591
|
+
if (!existsSync(path))
|
|
592
|
+
return null;
|
|
593
|
+
try {
|
|
594
|
+
const parsed = parseYaml(readFileSync(path, "utf8"));
|
|
595
|
+
if (typeof parsed["slug"] === "string")
|
|
596
|
+
return parsed["slug"];
|
|
597
|
+
return null;
|
|
598
|
+
}
|
|
599
|
+
catch {
|
|
600
|
+
return null;
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
function minutesSince(iso) {
|
|
604
|
+
const t = Date.parse(iso);
|
|
605
|
+
if (!Number.isFinite(t))
|
|
606
|
+
return null;
|
|
607
|
+
const diffMs = Date.now() - t;
|
|
608
|
+
if (diffMs < 0)
|
|
609
|
+
return 0;
|
|
610
|
+
return Math.floor(diffMs / 60_000);
|
|
611
|
+
}
|
|
612
|
+
function humanizeMinutes(minutes) {
|
|
613
|
+
if (minutes < 1)
|
|
614
|
+
return "moments ago";
|
|
615
|
+
if (minutes < 60)
|
|
616
|
+
return `${minutes} minute${minutes === 1 ? "" : "s"} ago`;
|
|
617
|
+
const hours = Math.floor(minutes / 60);
|
|
618
|
+
if (hours < 24)
|
|
619
|
+
return `${hours} hour${hours === 1 ? "" : "s"} ago`;
|
|
620
|
+
const days = Math.floor(hours / 24);
|
|
621
|
+
return `${days} day${days === 1 ? "" : "s"} ago`;
|
|
622
|
+
}
|
|
623
|
+
function renderPendingDraftsSection(drafts) {
|
|
624
|
+
if (drafts.length === 0)
|
|
625
|
+
return null;
|
|
626
|
+
const lines = [];
|
|
627
|
+
lines.push(`## Decision drafts pending operator confirm (${drafts.length})`);
|
|
628
|
+
lines.push("");
|
|
629
|
+
const slice = drafts.slice(0, DRAFTS_CAP);
|
|
630
|
+
for (const d of slice) {
|
|
631
|
+
const meta = [];
|
|
632
|
+
if (d.capture_source)
|
|
633
|
+
meta.push(`capture_source: ${d.capture_source}`);
|
|
634
|
+
if (d.decided_at)
|
|
635
|
+
meta.push(`received: ${d.decided_at}`);
|
|
636
|
+
lines.push(`- **${d.id}** (draft) — ${d.title}${meta.length > 0 ? `; ${meta.join("; ")}` : ""}`);
|
|
637
|
+
}
|
|
638
|
+
if (drafts.length > DRAFTS_CAP) {
|
|
639
|
+
lines.push(`…${drafts.length - DRAFTS_CAP} more in _inbox/.`);
|
|
640
|
+
}
|
|
641
|
+
lines.push("");
|
|
642
|
+
lines.push("These have been captured but not committed. The operator has not yet confirmed 🟢. Until they do, do not assume their content is binding.");
|
|
643
|
+
return lines.join("\n");
|
|
644
|
+
}
|
|
645
|
+
//# sourceMappingURL=build.js.map
|