@isaacriehm/cairn-core 0.6.0 → 0.7.1
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/dist/.tsbuildinfo +1 -1
- package/dist/align-undo/undo.js +2 -2
- package/dist/align-undo/undo.js.map +1 -1
- package/dist/attention/bulk-accept.js +104 -55
- package/dist/attention/bulk-accept.js.map +1 -1
- package/dist/attention/dedup.js +23 -10
- package/dist/attention/dedup.js.map +1 -1
- package/dist/attention/restore.js +2 -2
- package/dist/attention/restore.js.map +1 -1
- package/dist/attention/scoring.js +1 -1
- package/dist/attention/scoring.js.map +1 -1
- package/dist/attention/serve/api.d.ts +1 -0
- package/dist/attention/serve/api.js +130 -77
- package/dist/attention/serve/api.js.map +1 -1
- package/dist/attention/serve/index.d.ts +1 -0
- package/dist/attention/serve/index.js +21 -7
- package/dist/attention/serve/index.js.map +1 -1
- package/dist/attention/source-strip.js +41 -46
- package/dist/attention/source-strip.js.map +1 -1
- package/dist/claude/cache.d.ts +10 -19
- package/dist/claude/cache.js +0 -0
- package/dist/claude/cache.js.map +1 -1
- package/dist/claude/runner.d.ts +4 -6
- package/dist/claude/runner.js +242 -203
- package/dist/claude/runner.js.map +1 -1
- package/dist/claude/types.d.ts +5 -5
- package/dist/context/handoff-builder.d.ts +28 -4
- package/dist/context/handoff-builder.js +75 -157
- package/dist/context/handoff-builder.js.map +1 -1
- package/dist/context/spec-delta.js +61 -9
- package/dist/context/spec-delta.js.map +1 -1
- package/dist/context/task-summary.js +5 -1
- package/dist/context/task-summary.js.map +1 -1
- package/dist/decision-capture/id.js +1 -1
- package/dist/decision-capture/id.js.map +1 -1
- package/dist/doctor/index.d.ts +9 -11
- package/dist/doctor/index.js +118 -175
- package/dist/doctor/index.js.map +1 -1
- package/dist/drain/drain.d.ts +1 -1
- package/dist/drain/drain.js +16 -16
- package/dist/drain/drain.js.map +1 -1
- package/dist/drain/index.d.ts +1 -1
- package/dist/drain/index.js +1 -1
- package/dist/events/reader.d.ts +9 -10
- package/dist/events/reader.js +46 -57
- package/dist/events/reader.js.map +1 -1
- package/dist/events/writer.js +1 -1
- package/dist/events/writer.js.map +1 -1
- package/dist/fix-align/index.d.ts +1 -1
- package/dist/fix-align/index.js +1 -1
- package/dist/fix-align/run.d.ts +1 -1
- package/dist/fix-align/run.js +4 -3
- package/dist/fix-align/run.js.map +1 -1
- package/dist/fix-align/sentinel.d.ts +1 -2
- package/dist/fix-align/sentinel.js +3 -4
- package/dist/fix-align/sentinel.js.map +1 -1
- package/dist/gc/apply.js +1 -1
- package/dist/gc/apply.js.map +1 -1
- package/dist/gc/attested-commits.d.ts +19 -0
- package/dist/gc/attested-commits.js +48 -0
- package/dist/gc/attested-commits.js.map +1 -0
- package/dist/gc/canary.d.ts +11 -21
- package/dist/gc/canary.js +18 -24
- package/dist/gc/canary.js.map +1 -1
- package/dist/gc/citation-integrity.d.ts +11 -14
- package/dist/gc/citation-integrity.js +124 -125
- package/dist/gc/citation-integrity.js.map +1 -1
- package/dist/gc/classify.d.ts +1 -1
- package/dist/gc/classify.js +2 -2
- package/dist/gc/classify.js.map +1 -1
- package/dist/gc/completion-integrity.d.ts +6 -7
- package/dist/gc/completion-integrity.js +45 -53
- package/dist/gc/completion-integrity.js.map +1 -1
- package/dist/gc/doc-gardening.js +1 -9
- package/dist/gc/doc-gardening.js.map +1 -1
- package/dist/gc/frontmatter.js +2 -2
- package/dist/gc/frontmatter.js.map +1 -1
- package/dist/gc/index.d.ts +7 -6
- package/dist/gc/index.js +3 -2
- package/dist/gc/index.js.map +1 -1
- package/dist/gc/quality-update.d.ts +6 -10
- package/dist/gc/quality-update.js +12 -15
- package/dist/gc/quality-update.js.map +1 -1
- package/dist/gc/scope-coverage.js +1 -1
- package/dist/gc/scope-coverage.js.map +1 -1
- package/dist/gc/stub-hits.d.ts +7 -25
- package/dist/gc/stub-hits.js +14 -40
- package/dist/gc/stub-hits.js.map +1 -1
- package/dist/gc/sweep.js +15 -6
- package/dist/gc/sweep.js.map +1 -1
- package/dist/gc/types.d.ts +5 -5
- package/dist/gc/types.js +2 -2
- package/dist/gc/walk-source.js +8 -28
- package/dist/gc/walk-source.js.map +1 -1
- package/dist/hooks/defer.d.ts +9 -20
- package/dist/hooks/defer.js +10 -27
- package/dist/hooks/defer.js.map +1 -1
- package/dist/hooks/post-tool-use/allowlist-reader.d.ts +2 -1
- package/dist/hooks/post-tool-use/allowlist-reader.js +49 -34
- package/dist/hooks/post-tool-use/allowlist-reader.js.map +1 -1
- package/dist/hooks/post-tool-use/index.d.ts +3 -4
- package/dist/hooks/post-tool-use/index.js +3 -3
- package/dist/hooks/post-tool-use/index.js.map +1 -1
- package/dist/hooks/post-tool-use/legend-builder.d.ts +11 -2
- package/dist/hooks/post-tool-use/legend-builder.js +27 -2
- package/dist/hooks/post-tool-use/legend-builder.js.map +1 -1
- package/dist/hooks/post-tool-use/post-write.d.ts +8 -0
- package/dist/hooks/post-tool-use/post-write.js +112 -0
- package/dist/hooks/post-tool-use/post-write.js.map +1 -0
- package/dist/hooks/post-tool-use/read-enricher.d.ts +10 -5
- package/dist/hooks/post-tool-use/read-enricher.js +114 -149
- package/dist/hooks/post-tool-use/read-enricher.js.map +1 -1
- package/dist/hooks/post-tool-use/sot-align.d.ts +12 -0
- package/dist/hooks/post-tool-use/sot-align.js +73 -49
- package/dist/hooks/post-tool-use/sot-align.js.map +1 -1
- package/dist/hooks/post-tool-use/write-guardian.d.ts +40 -8
- package/dist/hooks/post-tool-use/write-guardian.js +202 -254
- package/dist/hooks/post-tool-use/write-guardian.js.map +1 -1
- package/dist/hooks/pre-commit/sot-align-precommit.js +2 -2
- package/dist/hooks/pre-commit/sot-align-precommit.js.map +1 -1
- package/dist/hooks/runners/index.d.ts +2 -2
- package/dist/hooks/runners/index.js +1 -1
- package/dist/hooks/runners/index.js.map +1 -1
- package/dist/hooks/runners/payload.d.ts +34 -19
- package/dist/hooks/runners/payload.js +47 -44
- package/dist/hooks/runners/payload.js.map +1 -1
- package/dist/hooks/runners/session-end.js +12 -11
- package/dist/hooks/runners/session-end.js.map +1 -1
- package/dist/hooks/runners/session-start.d.ts +4 -2
- package/dist/hooks/runners/session-start.js +88 -261
- package/dist/hooks/runners/session-start.js.map +1 -1
- package/dist/hooks/runners/stop.js +27 -8
- package/dist/hooks/runners/stop.js.map +1 -1
- package/dist/hooks/runners/user-prompt-submit.js +7 -1
- package/dist/hooks/runners/user-prompt-submit.js.map +1 -1
- package/dist/hooks/sot-align-common.d.ts +1 -2
- package/dist/hooks/sot-align-common.js +2 -2
- package/dist/hooks/sot-align-common.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +12 -3
- package/dist/index.js.map +1 -1
- package/dist/init/baseline-audit.d.ts +14 -58
- package/dist/init/baseline-audit.js +92 -320
- package/dist/init/baseline-audit.js.map +1 -1
- package/dist/init/brand-derive.d.ts +11 -15
- package/dist/init/brand-derive.js +21 -46
- package/dist/init/brand-derive.js.map +1 -1
- package/dist/init/brand-setup.d.ts +1 -1
- package/dist/init/brand-setup.js +1 -1
- package/dist/init/detect.d.ts +25 -6
- package/dist/init/detect.js +107 -136
- package/dist/init/detect.js.map +1 -1
- package/dist/init/index.d.ts +4 -4
- package/dist/init/index.js +2 -2
- package/dist/init/index.js.map +1 -1
- package/dist/init/ingest-docs.d.ts +83 -23
- package/dist/init/ingest-docs.js +648 -136
- package/dist/init/ingest-docs.js.map +1 -1
- package/dist/init/init.d.ts +29 -20
- package/dist/init/init.js +132 -290
- package/dist/init/init.js.map +1 -1
- package/dist/init/mapper-merge.js +1 -1
- package/dist/init/mapper-merge.js.map +1 -1
- package/dist/init/mapper-parallel.d.ts +1 -1
- package/dist/init/mapper-parallel.js +10 -1
- package/dist/init/mapper-parallel.js.map +1 -1
- package/dist/init/mapper.js +1 -1
- package/dist/init/mapper.js.map +1 -1
- package/dist/init/multi-dev/install.d.ts +5 -5
- package/dist/init/multi-dev/install.js +4 -4
- package/dist/init/overlay.js +1 -0
- package/dist/init/overlay.js.map +1 -1
- package/dist/init/phases/1-detect.js +1 -1
- package/dist/init/phases/1-detect.js.map +1 -1
- package/dist/init/phases/{7c-rules-merge.d.ts → 10-rules-merge.d.ts} +2 -2
- package/dist/init/phases/{7c-rules-merge.js → 10-rules-merge.js} +6 -12
- package/dist/init/phases/10-rules-merge.js.map +1 -0
- package/dist/init/phases/11-baseline.d.ts +7 -0
- package/dist/init/phases/{8-baseline.js → 11-baseline.js} +5 -9
- package/dist/init/phases/11-baseline.js.map +1 -0
- package/dist/init/phases/12-strip.d.ts +10 -0
- package/dist/init/phases/{10-strip.js → 12-strip.js} +10 -14
- package/dist/init/phases/12-strip.js.map +1 -0
- package/dist/init/phases/{12-multidev.d.ts → 13-multidev.d.ts} +2 -2
- package/dist/init/phases/{12-multidev.js → 13-multidev.js} +4 -4
- package/dist/init/phases/{12-multidev.js.map → 13-multidev.js.map} +1 -1
- package/dist/init/phases/3-mapper.d.ts +1 -1
- package/dist/init/phases/3-mapper.js +2 -2
- package/dist/init/phases/3-mapper.js.map +1 -1
- package/dist/init/phases/{3b-seed.d.ts → 4-seed.d.ts} +2 -2
- package/dist/init/phases/{3b-seed.js → 4-seed.js} +7 -7
- package/dist/init/phases/4-seed.js.map +1 -0
- package/dist/init/phases/{4-pilot.d.ts → 5-pilot.d.ts} +2 -2
- package/dist/init/phases/{4-pilot.js → 5-pilot.js} +9 -9
- package/dist/init/phases/{4-pilot.js.map → 5-pilot.js.map} +1 -1
- package/dist/init/phases/{5-brand.d.ts → 6-brand.d.ts} +2 -7
- package/dist/init/phases/{5-brand.js → 6-brand.js} +6 -14
- package/dist/init/phases/6-brand.js.map +1 -0
- package/dist/init/phases/{5b-topic-index.d.ts → 7-topic-index.d.ts} +2 -11
- package/dist/init/phases/{5b-topic-index.js → 7-topic-index.js} +9 -18
- package/dist/init/phases/7-topic-index.js.map +1 -0
- package/dist/init/phases/8-docs-ingest.d.ts +10 -0
- package/dist/init/phases/{6-docs-ingest.js → 8-docs-ingest.js} +12 -14
- package/dist/init/phases/8-docs-ingest.js.map +1 -0
- package/dist/init/phases/9-source-comments.d.ts +6 -0
- package/dist/init/phases/{7b-source-comments.js → 9-source-comments.js} +7 -26
- package/dist/init/phases/9-source-comments.js.map +1 -0
- package/dist/init/phases/index.d.ts +12 -12
- package/dist/init/phases/index.js +11 -11
- package/dist/init/phases/index.js.map +1 -1
- package/dist/init/phases/{parallel-678.d.ts → parallel-8910.d.ts} +7 -8
- package/dist/init/phases/{parallel-678.js → parallel-8910.js} +34 -46
- package/dist/init/phases/parallel-8910.js.map +1 -0
- package/dist/init/phases/source-comments-output-io.d.ts +3 -3
- package/dist/init/phases/source-comments-output-io.js +3 -3
- package/dist/init/phases/types.d.ts +1 -1
- package/dist/init/phases/types.js +10 -10
- package/dist/init/phases/types.js.map +1 -1
- package/dist/init/rules-merge/discover.d.ts +2 -2
- package/dist/init/rules-merge/discover.js +28 -43
- package/dist/init/rules-merge/discover.js.map +1 -1
- package/dist/init/rules-merge/ingest.d.ts +6 -6
- package/dist/init/rules-merge/ingest.js +9 -10
- package/dist/init/rules-merge/ingest.js.map +1 -1
- package/dist/init/rules-merge/keep-markers.d.ts +1 -1
- package/dist/init/rules-merge/keep-markers.js +1 -1
- package/dist/init/rules-merge/regenerate.d.ts +3 -3
- package/dist/init/rules-merge/regenerate.js +3 -3
- package/dist/init/seed.js +17 -24
- package/dist/init/seed.js.map +1 -1
- package/dist/init/sot-emit.d.ts +48 -8
- package/dist/init/sot-emit.js +88 -10
- package/dist/init/sot-emit.js.map +1 -1
- package/dist/init/source-comments/classify.d.ts +2 -2
- package/dist/init/source-comments/classify.js +9 -1
- package/dist/init/source-comments/classify.js.map +1 -1
- package/dist/init/source-comments/index.d.ts +1 -1
- package/dist/init/source-comments/index.js.map +1 -1
- package/dist/init/source-comments/ingest.d.ts +2 -2
- package/dist/init/source-comments/ingest.js +110 -12
- package/dist/init/source-comments/ingest.js.map +1 -1
- package/dist/init/source-comments/strip-replace.js +3 -2
- package/dist/init/source-comments/strip-replace.js.map +1 -1
- package/dist/init/source-comments/walker.d.ts +3 -26
- package/dist/init/source-comments/walker.js +18 -30
- package/dist/init/source-comments/walker.js.map +1 -1
- package/dist/init/topic-index/index.d.ts +15 -1
- package/dist/init/topic-index/index.js +84 -5
- package/dist/init/topic-index/index.js.map +1 -1
- package/dist/init/topic-index/judge.d.ts +5 -9
- package/dist/init/topic-index/judge.js +25 -17
- package/dist/init/topic-index/judge.js.map +1 -1
- package/dist/init/topic-index/resolve.d.ts +23 -3
- package/dist/init/topic-index/resolve.js +102 -16
- package/dist/init/topic-index/resolve.js.map +1 -1
- package/dist/init/topic-index/walk.d.ts +36 -4
- package/dist/init/topic-index/walk.js +78 -12
- package/dist/init/topic-index/walk.js.map +1 -1
- package/dist/lock.js +4 -1
- package/dist/lock.js.map +1 -1
- package/dist/logger.js +3 -0
- package/dist/logger.js.map +1 -1
- package/dist/mcp/history/summarizer.js +6 -1
- package/dist/mcp/history/summarizer.js.map +1 -1
- package/dist/mcp/history/walker.js +1 -1
- package/dist/mcp/history/walker.js.map +1 -1
- package/dist/mcp/path-allowlist.js +1 -1
- package/dist/mcp/path-allowlist.js.map +1 -1
- package/dist/mcp/schemas.d.ts +47 -21
- package/dist/mcp/schemas.js +38 -9
- package/dist/mcp/schemas.js.map +1 -1
- package/dist/mcp/server.js +10 -0
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/tools/archive.js +1 -1
- package/dist/mcp/tools/archive.js.map +1 -1
- package/dist/mcp/tools/attention-wait.js +12 -2
- package/dist/mcp/tools/attention-wait.js.map +1 -1
- package/dist/mcp/tools/bulk-accept-attention.js +29 -30
- package/dist/mcp/tools/bulk-accept-attention.js.map +1 -1
- package/dist/mcp/tools/canonical-for-topic.js +37 -15
- package/dist/mcp/tools/canonical-for-topic.js.map +1 -1
- package/dist/mcp/tools/decision-get.js +2 -2
- package/dist/mcp/tools/decision-get.js.map +1 -1
- package/dist/mcp/tools/decisions-for-symbol.js +2 -2
- package/dist/mcp/tools/decisions-for-symbol.js.map +1 -1
- package/dist/mcp/tools/get-full.js +1 -1
- package/dist/mcp/tools/get-full.js.map +1 -1
- package/dist/mcp/tools/ground-get.js +1 -1
- package/dist/mcp/tools/ground-get.js.map +1 -1
- package/dist/mcp/tools/in-scope.d.ts +8 -0
- package/dist/mcp/tools/in-scope.js +125 -0
- package/dist/mcp/tools/in-scope.js.map +1 -0
- package/dist/mcp/tools/index.js +11 -6
- package/dist/mcp/tools/index.js.map +1 -1
- package/dist/mcp/tools/init-phases.d.ts +3 -2
- package/dist/mcp/tools/init-phases.js +125 -124
- package/dist/mcp/tools/init-phases.js.map +1 -1
- package/dist/mcp/tools/invariant-get.js +2 -2
- package/dist/mcp/tools/invariant-get.js.map +1 -1
- package/dist/mcp/tools/record-decision.d.ts +4 -3
- package/dist/mcp/tools/record-decision.js +111 -36
- package/dist/mcp/tools/record-decision.js.map +1 -1
- package/dist/mcp/tools/reject-candidate.d.ts +24 -0
- package/dist/mcp/tools/reject-candidate.js +71 -0
- package/dist/mcp/tools/reject-candidate.js.map +1 -0
- package/dist/mcp/tools/resolve-attention.d.ts +5 -18
- package/dist/mcp/tools/resolve-attention.js +58 -158
- package/dist/mcp/tools/resolve-attention.js.map +1 -1
- package/dist/mcp/tools/search-candidates.d.ts +20 -0
- package/dist/mcp/tools/search-candidates.js +93 -0
- package/dist/mcp/tools/search-candidates.js.map +1 -0
- package/dist/mcp/tools/search.js +5 -4
- package/dist/mcp/tools/search.js.map +1 -1
- package/dist/mcp/tools/supersedes-chain.js +2 -2
- package/dist/mcp/tools/supersedes-chain.js.map +1 -1
- package/dist/mcp/tools/task-create.d.ts +1 -0
- package/dist/mcp/tools/task-create.js +2 -0
- package/dist/mcp/tools/task-create.js.map +1 -1
- package/dist/mcp/tools/timeline.js +1 -1
- package/dist/mcp/tools/timeline.js.map +1 -1
- package/dist/mcp/tools/types.d.ts +1 -0
- package/dist/mcp/tools/types.js +9 -1
- package/dist/mcp/tools/types.js.map +1 -1
- package/dist/sensors/attestation.d.ts +1 -1
- package/dist/sensors/attestation.js +2 -2
- package/dist/sensors/attestation.js.map +1 -1
- package/dist/sensors/catalog.d.ts +26 -28
- package/dist/sensors/catalog.js +79 -81
- package/dist/sensors/catalog.js.map +1 -1
- package/dist/sensors/decisions.d.ts +1 -1
- package/dist/sensors/decisions.js +15 -14
- package/dist/sensors/decisions.js.map +1 -1
- package/dist/sensors/diff.js +46 -22
- package/dist/sensors/diff.js.map +1 -1
- package/dist/sensors/runner.d.ts +2 -2
- package/dist/sensors/runner.js +3 -3
- package/dist/sensors/shell.d.ts +4 -0
- package/dist/sensors/shell.js +16 -0
- package/dist/sensors/shell.js.map +1 -0
- package/dist/sensors/structural.d.ts +3 -2
- package/dist/sensors/structural.js +3 -11
- package/dist/sensors/structural.js.map +1 -1
- package/dist/sensors/stub-catalog.d.ts +2 -1
- package/dist/sensors/stub-catalog.js +2 -9
- package/dist/sensors/stub-catalog.js.map +1 -1
- package/dist/sensors/types.d.ts +3 -4
- package/dist/sensors/types.js +1 -2
- package/dist/sensors/types.js.map +1 -1
- package/dist/session-start/build.js +1 -1
- package/dist/session-start/build.js.map +1 -1
- package/dist/status-line/event-queue.js +1 -1
- package/dist/status-line/index.d.ts +1 -1
- package/package.json +3 -2
- package/templates/.cairn/config/sensors.yaml +8 -8
- package/templates/attention-ui/app.js +101 -39
- package/dist/fs.d.ts +0 -5
- package/dist/fs.js +0 -11
- package/dist/fs.js.map +0 -1
- package/dist/ground/alignment-pending.d.ts +0 -28
- package/dist/ground/alignment-pending.js +0 -83
- package/dist/ground/alignment-pending.js.map +0 -1
- package/dist/ground/anchor-map.d.ts +0 -14
- package/dist/ground/anchor-map.js +0 -56
- package/dist/ground/anchor-map.js.map +0 -1
- package/dist/ground/drift.d.ts +0 -8
- package/dist/ground/drift.js +0 -23
- package/dist/ground/drift.js.map +0 -1
- package/dist/ground/frontmatter.d.ts +0 -32
- package/dist/ground/frontmatter.js +0 -77
- package/dist/ground/frontmatter.js.map +0 -1
- package/dist/ground/glob.d.ts +0 -10
- package/dist/ground/glob.js +0 -46
- package/dist/ground/glob.js.map +0 -1
- package/dist/ground/index.d.ts +0 -23
- package/dist/ground/index.js +0 -17
- package/dist/ground/index.js.map +0 -1
- package/dist/ground/ledgers.d.ts +0 -14
- package/dist/ground/ledgers.js +0 -105
- package/dist/ground/ledgers.js.map +0 -1
- package/dist/ground/manifest.d.ts +0 -10
- package/dist/ground/manifest.js +0 -84
- package/dist/ground/manifest.js.map +0 -1
- package/dist/ground/paths.d.ts +0 -41
- package/dist/ground/paths.js +0 -103
- package/dist/ground/paths.js.map +0 -1
- package/dist/ground/quality-grades.d.ts +0 -11
- package/dist/ground/quality-grades.js +0 -100
- package/dist/ground/quality-grades.js.map +0 -1
- package/dist/ground/schemas.d.ts +0 -502
- package/dist/ground/schemas.js +0 -318
- package/dist/ground/schemas.js.map +0 -1
- package/dist/ground/scope-index.d.ts +0 -96
- package/dist/ground/scope-index.js +0 -290
- package/dist/ground/scope-index.js.map +0 -1
- package/dist/ground/slug.d.ts +0 -60
- package/dist/ground/slug.js +0 -103
- package/dist/ground/slug.js.map +0 -1
- package/dist/ground/sot-bindings.d.ts +0 -14
- package/dist/ground/sot-bindings.js +0 -79
- package/dist/ground/sot-bindings.js.map +0 -1
- package/dist/ground/sot-cache.d.ts +0 -18
- package/dist/ground/sot-cache.js +0 -62
- package/dist/ground/sot-cache.js.map +0 -1
- package/dist/ground/topic-index.d.ts +0 -27
- package/dist/ground/topic-index.js +0 -82
- package/dist/ground/topic-index.js.map +0 -1
- package/dist/ground/walk.d.ts +0 -7
- package/dist/ground/walk.js +0 -53
- package/dist/ground/walk.js.map +0 -1
- package/dist/hooks/post-tool-use/ledger-cache.d.ts +0 -40
- package/dist/hooks/post-tool-use/ledger-cache.js +0 -290
- package/dist/hooks/post-tool-use/ledger-cache.js.map +0 -1
- package/dist/init/phases/10-strip.d.ts +0 -11
- package/dist/init/phases/10-strip.js.map +0 -1
- package/dist/init/phases/3b-seed.js.map +0 -1
- package/dist/init/phases/5-brand.js.map +0 -1
- package/dist/init/phases/5b-topic-index.js.map +0 -1
- package/dist/init/phases/6-docs-ingest.d.ts +0 -10
- package/dist/init/phases/6-docs-ingest.js.map +0 -1
- package/dist/init/phases/7b-source-comments.d.ts +0 -15
- package/dist/init/phases/7b-source-comments.js.map +0 -1
- package/dist/init/phases/7c-rules-merge.js.map +0 -1
- package/dist/init/phases/8-baseline.d.ts +0 -10
- package/dist/init/phases/8-baseline.js.map +0 -1
- package/dist/init/phases/parallel-678.js.map +0 -1
- package/dist/mcp/tools/decisions-in-scope.d.ts +0 -7
- package/dist/mcp/tools/decisions-in-scope.js +0 -66
- package/dist/mcp/tools/decisions-in-scope.js.map +0 -1
- package/dist/mcp/tools/invariants-in-scope.d.ts +0 -7
- package/dist/mcp/tools/invariants-in-scope.js +0 -81
- package/dist/mcp/tools/invariants-in-scope.js.map +0 -1
package/dist/init/init.js
CHANGED
|
@@ -9,15 +9,16 @@
|
|
|
9
9
|
* 4. Mapper (Tier-2 chunked Sonnet) → seed `<slug>:` workflow.md block +
|
|
10
10
|
* `.cairn/config.yaml` project_globs.
|
|
11
11
|
* 5. Brand setup (4-question wizard).
|
|
12
|
-
* 6. Phase
|
|
13
|
-
* 7. Phase
|
|
12
|
+
* 6. Phase 8 docs ingestion + baseline sensor sweep.
|
|
13
|
+
* 7. Phase 9 source-comment ingestion + Phase 10 rules merge (mock-friendly
|
|
14
14
|
* via `mockSourceCommentClassify` / `mockRulesMergeClassify`).
|
|
15
|
-
* 8. Phase
|
|
15
|
+
* 8. Phase 13 multi-dev install (deterministic, idempotent).
|
|
16
16
|
*/
|
|
17
17
|
import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync, } from "node:fs";
|
|
18
18
|
import { join, relative } from "node:path";
|
|
19
19
|
import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
|
|
20
|
-
import {
|
|
20
|
+
import { z } from "zod";
|
|
21
|
+
import { scopeIndexPath, writeScopeIndex, } from "@isaacriehm/cairn-state";
|
|
21
22
|
import { normalizeProjectName } from "../paths/index.js";
|
|
22
23
|
import { homedir } from "node:os";
|
|
23
24
|
import { logger, setLogFile } from "../logger.js";
|
|
@@ -46,6 +47,7 @@ export async function runInit(args = {}) {
|
|
|
46
47
|
const cwd = process.cwd();
|
|
47
48
|
const mode = args.mode ?? "interactive";
|
|
48
49
|
const warnings = [];
|
|
50
|
+
const initStartMs = Date.now();
|
|
49
51
|
// ── Phase -1: self-adoption hard stop ──────────────────────────────
|
|
50
52
|
// If repoRoot or cwd looks like the Cairn source repo itself, refuse —
|
|
51
53
|
// running init here would overwrite cairn internals.
|
|
@@ -92,7 +94,7 @@ export async function runInit(args = {}) {
|
|
|
92
94
|
autoSubmodule: args.autoSubmodule ?? "init",
|
|
93
95
|
warnings,
|
|
94
96
|
});
|
|
95
|
-
const detection = await detectAll(repoRoot);
|
|
97
|
+
const detection = await detectAll({ repoRoot });
|
|
96
98
|
const decidedSlug = args.slugOverride !== undefined
|
|
97
99
|
? normalizeProjectName(args.slugOverride)
|
|
98
100
|
: detection.project_slug;
|
|
@@ -275,19 +277,19 @@ export async function runInit(args = {}) {
|
|
|
275
277
|
brandSetup = { answered: 0, updated_files: [] };
|
|
276
278
|
}
|
|
277
279
|
}
|
|
278
|
-
// ── Phase
|
|
280
|
+
// ── Phase 7 (topic-index): cross-source dedup pre-pass ────────────
|
|
279
281
|
// Walks every prose-bearing markdown source the SoT model recognizes
|
|
280
282
|
// (`docs/*`, `CLAUDE.md`, `AGENTS.md`, `.claude/rules/*`) and writes
|
|
281
283
|
// `topic-index.yaml` + `anchor-map.yaml`. Phases 6 / 7b / 7c read both
|
|
282
284
|
// before emitting so a single fact never duplicates across sources.
|
|
283
|
-
// Skipped under the same condition as Phase
|
|
285
|
+
// Skipped under the same condition as Phase 8.
|
|
284
286
|
const skipTopicIndex = args.skipIngestion === true ||
|
|
285
287
|
(mode === "auto" &&
|
|
286
288
|
args.mockSourceCommentClassify === undefined &&
|
|
287
289
|
args.mockRulesMergeClassify === undefined);
|
|
288
290
|
if (!skipTopicIndex) {
|
|
289
291
|
process.stdout.write("\n");
|
|
290
|
-
process.stdout.write(` ${visualC.bold("Phase
|
|
292
|
+
process.stdout.write(` ${visualC.bold("Phase 7")} — topic-index (cross-source dedup)…\n`);
|
|
291
293
|
try {
|
|
292
294
|
const topicArgs = { repoRoot };
|
|
293
295
|
if (args.mockTopicIndexJudge !== undefined)
|
|
@@ -304,23 +306,32 @@ export async function runInit(args = {}) {
|
|
|
304
306
|
process.stdout.write(` ${visualC.yellow("⚠")} topic-index build failed — ${msg}\n`);
|
|
305
307
|
}
|
|
306
308
|
}
|
|
307
|
-
// ── Phase
|
|
309
|
+
// ── Phase 8: ingestion sweep + baseline audit ──────────────────────
|
|
308
310
|
// Populates project brain from docs that already exist in the repo, then
|
|
309
311
|
// runs every runnable sensor against the full codebase to surface pre-
|
|
310
312
|
// Cairn debt. Both pieces are best-effort; failures degrade to empty
|
|
311
313
|
// result, never block the init.
|
|
312
|
-
const
|
|
314
|
+
const phase6Args = {
|
|
313
315
|
repoRoot,
|
|
314
316
|
decidedSlug,
|
|
315
317
|
detection,
|
|
316
318
|
mapperOutput,
|
|
317
|
-
|
|
319
|
+
// Auto mode skips Haiku-backed ingestion by default. Smokes that
|
|
320
|
+
// need to exercise the phase-6 emit path (e2e-adoption,
|
|
321
|
+
// ingestion-baseline) provide `mockIngestionClassify` so the
|
|
322
|
+
// pipeline runs end-to-end without burning Haiku.
|
|
323
|
+
skip: args.skipIngestion === true ||
|
|
324
|
+
(mode === "auto" && args.mockIngestionClassify === undefined),
|
|
318
325
|
warnings,
|
|
319
|
-
}
|
|
320
|
-
|
|
326
|
+
};
|
|
327
|
+
if (args.mockIngestionClassify !== undefined) {
|
|
328
|
+
phase6Args.mockClassify = args.mockIngestionClassify;
|
|
329
|
+
}
|
|
330
|
+
const phase6 = await runPhaseSix(phase6Args);
|
|
331
|
+
// ── Phase 9: source-comment ingestion ─────────────────────────────
|
|
321
332
|
// Walks every source file, batches block-comments through Haiku, files
|
|
322
333
|
// DEC drafts + invariant proposals + canonical citations into
|
|
323
|
-
// `.cairn/baseline/`. Skipped under the same condition as Phase
|
|
334
|
+
// `.cairn/baseline/`. Skipped under the same condition as Phase 8
|
|
324
335
|
// unless a `mockSourceCommentClassify` is supplied (smokes).
|
|
325
336
|
let sourceComments = null;
|
|
326
337
|
const skip7b = args.skipPhase7b === true ||
|
|
@@ -328,7 +339,7 @@ export async function runInit(args = {}) {
|
|
|
328
339
|
args.mockSourceCommentClassify === undefined);
|
|
329
340
|
if (!skip7b) {
|
|
330
341
|
process.stdout.write("\n");
|
|
331
|
-
process.stdout.write(` ${visualC.bold("Phase
|
|
342
|
+
process.stdout.write(` ${visualC.bold("Phase 9")} — source-comment ingestion…\n`);
|
|
332
343
|
try {
|
|
333
344
|
sourceComments = await runSourceCommentsIngestion({
|
|
334
345
|
repoRoot,
|
|
@@ -344,7 +355,7 @@ export async function runInit(args = {}) {
|
|
|
344
355
|
process.stdout.write(` DECs: ${sourceComments.decsWritten.length}; ` +
|
|
345
356
|
`invariants: ${sourceComments.invsWritten.length}; ` +
|
|
346
357
|
`cites: ${sourceComments.citesEmitted.length}; ` +
|
|
347
|
-
`strip applied: ${sourceComments.
|
|
358
|
+
`strip applied: ${sourceComments.decsWritten.length + sourceComments.invsWritten.length}\n`);
|
|
348
359
|
}
|
|
349
360
|
catch (err) {
|
|
350
361
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -352,7 +363,7 @@ export async function runInit(args = {}) {
|
|
|
352
363
|
process.stdout.write(` ${visualC.yellow("⚠")} source-comment ingestion failed — ${msg}\n`);
|
|
353
364
|
}
|
|
354
365
|
}
|
|
355
|
-
// ── Phase
|
|
366
|
+
// ── Phase 10: existing-rules merge + first regenerate ──────────────
|
|
356
367
|
// Reads CLAUDE.md / AGENTS.md / .claude/CLAUDE.md / .claude/rules/**.md,
|
|
357
368
|
// classifies sections via Haiku into rule-net-new / rule-conflict /
|
|
358
369
|
// informational / operator-keep, persists net-new as DEC drafts. The
|
|
@@ -365,7 +376,7 @@ export async function runInit(args = {}) {
|
|
|
365
376
|
args.mockRulesMergeClassify === undefined);
|
|
366
377
|
if (!skip7c) {
|
|
367
378
|
process.stdout.write("\n");
|
|
368
|
-
process.stdout.write(` ${visualC.bold("Phase
|
|
379
|
+
process.stdout.write(` ${visualC.bold("Phase 10")} — existing-rules merge…\n`);
|
|
369
380
|
try {
|
|
370
381
|
rulesMerge = await runRulesMerge({
|
|
371
382
|
repoRoot,
|
|
@@ -374,12 +385,10 @@ export async function runInit(args = {}) {
|
|
|
374
385
|
: {}),
|
|
375
386
|
});
|
|
376
387
|
process.stdout.write(` Sources: ${rulesMerge.sources.length}; ` +
|
|
377
|
-
`
|
|
378
|
-
`INVs: ${rulesMerge.invsWritten.length}; ` +
|
|
388
|
+
`Emitted: ${rulesMerge.decsWritten.length + rulesMerge.invsWritten.length}; ` +
|
|
379
389
|
`cites: ${rulesMerge.citesEmitted.length}; ` +
|
|
380
390
|
`conflicts: ${rulesMerge.conflicts.length}; ` +
|
|
381
|
-
`informational: ${rulesMerge.kindCounts
|
|
382
|
-
`operator-keep: ${rulesMerge.kindCounts["operator-keep"]}\n`);
|
|
391
|
+
`informational: ${rulesMerge.kindCounts["informational"] ?? 0}\n`);
|
|
383
392
|
}
|
|
384
393
|
catch (err) {
|
|
385
394
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -387,7 +396,7 @@ export async function runInit(args = {}) {
|
|
|
387
396
|
process.stdout.write(` ${visualC.yellow("⚠")} rules merge failed — ${msg}\n`);
|
|
388
397
|
}
|
|
389
398
|
}
|
|
390
|
-
// ── Phase
|
|
399
|
+
// ── Phase 13: multi-developer enforcement install ──────────────────
|
|
391
400
|
// Idempotent + deterministic. Patches `package.json` `scripts.prepare`
|
|
392
401
|
// for Node projects so every clone runs `cairn join` on install.
|
|
393
402
|
// Surfaces manual hints for non-Node hosts. Templates (.cairn/
|
|
@@ -396,7 +405,7 @@ export async function runInit(args = {}) {
|
|
|
396
405
|
let multiDev = null;
|
|
397
406
|
if (args.skipPhase12 !== true) {
|
|
398
407
|
process.stdout.write("\n");
|
|
399
|
-
process.stdout.write(` ${visualC.bold("Phase
|
|
408
|
+
process.stdout.write(` ${visualC.bold("Phase 13")} — multi-dev enforcement install…\n`);
|
|
400
409
|
try {
|
|
401
410
|
multiDev = installMultiDev({ repoRoot });
|
|
402
411
|
const hostList = multiDev.hostKinds.join(", ");
|
|
@@ -415,20 +424,15 @@ export async function runInit(args = {}) {
|
|
|
415
424
|
// (PLUGIN_ARCHITECTURE §7). Init no longer writes it; the next
|
|
416
425
|
// SessionStart in any clone seeds the per-session file with the
|
|
417
426
|
// current attention_count derived from drafts + baseline findings.
|
|
418
|
-
// ── Step 6: completion summary (
|
|
427
|
+
// ── Step 6: completion summary (terse, per ) ──
|
|
419
428
|
printCompletionSummary({
|
|
420
429
|
projectName: decidedSlug,
|
|
421
430
|
repoRoot,
|
|
422
|
-
seededFiles: seed.written_files,
|
|
423
|
-
brandSetup,
|
|
424
|
-
submodules: submoduleSummary,
|
|
425
|
-
scanTruncated: repoSummary.truncated_at_file_cap ||
|
|
426
|
-
repoSummary.truncated_at_depth_cap,
|
|
427
431
|
mapperFallbackSlugs,
|
|
428
|
-
ingestion: phase6.ingestion,
|
|
429
432
|
baselineAudit: phase6.baselineAudit,
|
|
430
433
|
logFilePath,
|
|
431
434
|
warnings,
|
|
435
|
+
durationMs: Date.now() - initStartMs,
|
|
432
436
|
});
|
|
433
437
|
log.info({
|
|
434
438
|
repo_root: repoRoot,
|
|
@@ -440,7 +444,7 @@ export async function runInit(args = {}) {
|
|
|
440
444
|
mapper_applied_to_config: mapperAppliedToConfig,
|
|
441
445
|
brand_answered: brandSetup?.answered ?? null,
|
|
442
446
|
ingestion_drafts: phase6.ingestion?.decsWritten.length ?? null,
|
|
443
|
-
baseline_findings: phase6.baselineAudit?.
|
|
447
|
+
baseline_findings: phase6.baselineAudit?.findingsCount ?? null,
|
|
444
448
|
warnings: warnings.length,
|
|
445
449
|
}, "init complete");
|
|
446
450
|
return {
|
|
@@ -706,58 +710,43 @@ async function preflightSubmodules(args) {
|
|
|
706
710
|
success: true,
|
|
707
711
|
};
|
|
708
712
|
}
|
|
713
|
+
/**
|
|
714
|
+
* Cold-start summary, locked wording from
|
|
715
|
+
*
|
|
716
|
+
* Adopted <project> in <duration>.
|
|
717
|
+
* - <N> active rules baseline verified.
|
|
718
|
+
* - <M> new decision drafts found.
|
|
719
|
+
* - <K> unpromoted candidates indexed.
|
|
720
|
+
*
|
|
721
|
+
* Run `cairn attention` to review drafts and commit them to the ledger.
|
|
722
|
+
*
|
|
723
|
+
* No auto-wizard. No statusline drumbeat. Operator drives the next
|
|
724
|
+
* step. Warnings (if any) tail the locked block. Rich operational
|
|
725
|
+
* status moved to `cairn doctor`.
|
|
726
|
+
*/
|
|
709
727
|
function printCompletionSummary(args) {
|
|
710
|
-
const
|
|
711
|
-
const
|
|
712
|
-
const
|
|
713
|
-
const
|
|
714
|
-
const mcpReport = describeMcpRegistration(args.repoRoot);
|
|
728
|
+
const N = describeActiveRulesVerified(args.baselineAudit);
|
|
729
|
+
const M = countInboxDrafts(args.repoRoot);
|
|
730
|
+
const K = countUnpromotedCandidates(args.repoRoot);
|
|
731
|
+
const duration = formatDuration(args.durationMs);
|
|
715
732
|
info("");
|
|
716
|
-
info(`
|
|
733
|
+
info(` Adopted ${args.projectName} in ${duration}.`);
|
|
734
|
+
info(` - ${N} active rules baseline verified.`);
|
|
735
|
+
info(` - ${M} new decision drafts found.`);
|
|
736
|
+
info(` - ${K} unpromoted candidates indexed.`);
|
|
717
737
|
info("");
|
|
718
|
-
info(
|
|
719
|
-
|
|
720
|
-
|
|
738
|
+
info(" Run `cairn attention` to review drafts and commit them to the ledger.");
|
|
739
|
+
if (args.logFilePath !== null) {
|
|
740
|
+
info("");
|
|
741
|
+
info(` Log ${shortenHomePath(args.logFilePath)}`);
|
|
742
|
+
}
|
|
721
743
|
if (args.mapperFallbackSlugs.length > 0) {
|
|
722
744
|
const head = args.mapperFallbackSlugs.slice(0, 3).join(", ");
|
|
723
745
|
const more = args.mapperFallbackSlugs.length > 3
|
|
724
746
|
? ` +${args.mapperFallbackSlugs.length - 3} more`
|
|
725
747
|
: "";
|
|
726
|
-
info(`
|
|
727
|
-
}
|
|
728
|
-
info(` Brand ${brandReport}`);
|
|
729
|
-
info(` Scope index ${scopeReport.line}`);
|
|
730
|
-
if (scopeReport.followUp !== null) {
|
|
731
|
-
info(` ${scopeReport.followUp}`);
|
|
732
|
-
}
|
|
733
|
-
if (args.logFilePath !== null) {
|
|
734
|
-
info(` Log ${shortenHomePath(args.logFilePath)}`);
|
|
735
|
-
}
|
|
736
|
-
// Project brain populated from existing codebase.
|
|
737
|
-
const ingestionReport = describeIngestion(args.ingestion);
|
|
738
|
-
const canonicalReport = describeCanonical(args.ingestion);
|
|
739
|
-
const baselineReport = describeBaseline(args.baselineAudit);
|
|
740
|
-
if (ingestionReport !== null ||
|
|
741
|
-
canonicalReport !== null ||
|
|
742
|
-
baselineReport !== null) {
|
|
743
|
-
info("");
|
|
744
|
-
info(" Project brain populated from existing codebase:");
|
|
745
|
-
if (ingestionReport !== null) {
|
|
746
|
-
info(` DEC drafts ${ingestionReport}`);
|
|
747
|
-
}
|
|
748
|
-
if (canonicalReport !== null) {
|
|
749
|
-
info(` Canonical map ${canonicalReport}`);
|
|
750
|
-
}
|
|
751
|
-
if (baselineReport !== null) {
|
|
752
|
-
info(` Baseline debt ${baselineReport}`);
|
|
753
|
-
}
|
|
748
|
+
info(` Mapper fallback ${head}${more} — rerun cairn scope rebuild`);
|
|
754
749
|
}
|
|
755
|
-
info("");
|
|
756
|
-
info(" Open Claude Code in this directory. Cairn is live immediately.");
|
|
757
|
-
info("");
|
|
758
|
-
info(" Next: cairn attention see pending items");
|
|
759
|
-
info(" cairn doctor verify everything is working");
|
|
760
|
-
info(" cairn configure brand fill in brand guidelines");
|
|
761
750
|
if (args.warnings.length > 0) {
|
|
762
751
|
info("");
|
|
763
752
|
info(` ${args.warnings.length} warning${args.warnings.length === 1 ? "" : "s"}:`);
|
|
@@ -765,181 +754,73 @@ function printCompletionSummary(args) {
|
|
|
765
754
|
info(` ! ${w}`);
|
|
766
755
|
}
|
|
767
756
|
}
|
|
768
|
-
function
|
|
769
|
-
|
|
770
|
-
if (abs.startsWith(home))
|
|
771
|
-
return `~${abs.slice(home.length)}`;
|
|
772
|
-
return abs;
|
|
773
|
-
}
|
|
774
|
-
function countGroundFiles(repoRoot) {
|
|
775
|
-
const groundDir = join(repoRoot, ".cairn", "ground");
|
|
776
|
-
if (!existsSync(groundDir))
|
|
757
|
+
function describeActiveRulesVerified(audit) {
|
|
758
|
+
if (audit === null)
|
|
777
759
|
return 0;
|
|
778
|
-
|
|
779
|
-
const stack = [groundDir];
|
|
780
|
-
while (stack.length > 0) {
|
|
781
|
-
const dir = stack.pop();
|
|
782
|
-
if (dir === undefined)
|
|
783
|
-
break;
|
|
784
|
-
let entries;
|
|
785
|
-
try {
|
|
786
|
-
entries = readdirSync(dir, { withFileTypes: true, encoding: "utf8" });
|
|
787
|
-
}
|
|
788
|
-
catch {
|
|
789
|
-
continue;
|
|
790
|
-
}
|
|
791
|
-
for (const e of entries) {
|
|
792
|
-
const abs = join(dir, e.name);
|
|
793
|
-
if (e.isDirectory()) {
|
|
794
|
-
if (e.name === "_inbox")
|
|
795
|
-
continue;
|
|
796
|
-
stack.push(abs);
|
|
797
|
-
}
|
|
798
|
-
else if (e.isFile()) {
|
|
799
|
-
count++;
|
|
800
|
-
}
|
|
801
|
-
}
|
|
802
|
-
}
|
|
803
|
-
return count;
|
|
760
|
+
return 0; // Deprecated field
|
|
804
761
|
}
|
|
805
|
-
function
|
|
806
|
-
const
|
|
807
|
-
if (!existsSync(
|
|
762
|
+
function countInboxDrafts(repoRoot) {
|
|
763
|
+
const inbox = join(repoRoot, ".cairn", "ground", "decisions", "_inbox");
|
|
764
|
+
if (!existsSync(inbox))
|
|
808
765
|
return 0;
|
|
766
|
+
let entries;
|
|
809
767
|
try {
|
|
810
|
-
|
|
811
|
-
if (typeof parsed !== "object" || parsed === null)
|
|
812
|
-
return 0;
|
|
813
|
-
const sensorsRaw = parsed["sensors"];
|
|
814
|
-
if (!Array.isArray(sensorsRaw))
|
|
815
|
-
return 0;
|
|
816
|
-
return sensorsRaw.length;
|
|
768
|
+
entries = readdirSync(inbox, { withFileTypes: true, encoding: "utf8" });
|
|
817
769
|
}
|
|
818
770
|
catch {
|
|
819
771
|
return 0;
|
|
820
772
|
}
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
const submoduleNoteJustInitialized = submodules !== null &&
|
|
825
|
-
submodules.initialized &&
|
|
826
|
-
submodules.success;
|
|
827
|
-
const truncationFollowUp = "Run cairn scope rebuild for full classification";
|
|
828
|
-
if (!existsSync(path)) {
|
|
829
|
-
return {
|
|
830
|
-
line: "missing — run cairn scope rebuild",
|
|
831
|
-
followUp: null,
|
|
832
|
-
};
|
|
833
|
-
}
|
|
834
|
-
try {
|
|
835
|
-
const parsed = parseYaml(readFileSync(path, "utf8"));
|
|
836
|
-
if (typeof parsed !== "object" || parsed === null) {
|
|
837
|
-
return {
|
|
838
|
-
line: "empty — run cairn scope rebuild",
|
|
839
|
-
followUp: null,
|
|
840
|
-
};
|
|
841
|
-
}
|
|
842
|
-
const filesRaw = parsed["files"];
|
|
843
|
-
if (typeof filesRaw !== "object" || filesRaw === null) {
|
|
844
|
-
return {
|
|
845
|
-
line: "empty — run cairn scope rebuild",
|
|
846
|
-
followUp: null,
|
|
847
|
-
};
|
|
848
|
-
}
|
|
849
|
-
const count = Object.keys(filesRaw).length;
|
|
850
|
-
if (count === 0) {
|
|
851
|
-
if (scanTruncated) {
|
|
852
|
-
return {
|
|
853
|
-
line: "empty — analysis was truncated during init",
|
|
854
|
-
followUp: truncationFollowUp,
|
|
855
|
-
};
|
|
856
|
-
}
|
|
857
|
-
return {
|
|
858
|
-
line: submoduleNoteJustInitialized
|
|
859
|
-
? "empty — submodules now initialized, run cairn scope rebuild"
|
|
860
|
-
: "empty — run cairn scope rebuild",
|
|
861
|
-
followUp: null,
|
|
862
|
-
};
|
|
863
|
-
}
|
|
864
|
-
if (scanTruncated) {
|
|
865
|
-
return {
|
|
866
|
-
line: "partial — analysis was truncated during init",
|
|
867
|
-
followUp: truncationFollowUp,
|
|
868
|
-
};
|
|
869
|
-
}
|
|
870
|
-
if (submoduleNoteJustInitialized) {
|
|
871
|
-
return {
|
|
872
|
-
line: `partial — ${count} file${count === 1 ? "" : "s"} classified (submodules now initialized)`,
|
|
873
|
-
followUp: truncationFollowUp,
|
|
874
|
-
};
|
|
875
|
-
}
|
|
876
|
-
return {
|
|
877
|
-
line: `ready (${count} file${count === 1 ? "" : "s"} classified)`,
|
|
878
|
-
followUp: null,
|
|
879
|
-
};
|
|
880
|
-
}
|
|
881
|
-
catch {
|
|
882
|
-
return {
|
|
883
|
-
line: "unreadable — run cairn scope rebuild",
|
|
884
|
-
followUp: null,
|
|
885
|
-
};
|
|
886
|
-
}
|
|
887
|
-
}
|
|
888
|
-
function describeBrandStatus(repoRoot) {
|
|
889
|
-
const overview = join(repoRoot, ".cairn", "ground", "brand", "overview.md");
|
|
890
|
-
const positioning = join(repoRoot, ".cairn", "ground", "product", "positioning.md");
|
|
891
|
-
const voice = join(repoRoot, ".cairn", "ground", "brand", "voice.md");
|
|
892
|
-
const all = [overview, positioning, voice];
|
|
893
|
-
let currentCount = 0;
|
|
894
|
-
let total = 0;
|
|
895
|
-
for (const p of all) {
|
|
896
|
-
if (!existsSync(p))
|
|
773
|
+
let n = 0;
|
|
774
|
+
for (const e of entries) {
|
|
775
|
+
if (!e.isFile())
|
|
897
776
|
continue;
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
currentCount++;
|
|
901
|
-
}
|
|
902
|
-
if (total === 0)
|
|
903
|
-
return "missing — re-run cairn init";
|
|
904
|
-
if (currentCount === total)
|
|
905
|
-
return "ready";
|
|
906
|
-
if (currentCount === 0)
|
|
907
|
-
return "draft — run cairn configure brand";
|
|
908
|
-
return `partial (${currentCount}/${total} current) — run cairn configure brand`;
|
|
909
|
-
}
|
|
910
|
-
function readFrontmatterStatus(path) {
|
|
911
|
-
try {
|
|
912
|
-
const text = readFileSync(path, "utf8");
|
|
913
|
-
const m = text.match(/^---\n([\s\S]*?\n)---/);
|
|
914
|
-
if (!m)
|
|
915
|
-
return null;
|
|
916
|
-
const fm = m[1] ?? "";
|
|
917
|
-
const sm = fm.match(/^status:\s*(\S+)\s*$/m);
|
|
918
|
-
return sm && sm[1] ? sm[1] : null;
|
|
919
|
-
}
|
|
920
|
-
catch {
|
|
921
|
-
return null;
|
|
777
|
+
if (e.name.endsWith(".draft.md"))
|
|
778
|
+
n += 1;
|
|
922
779
|
}
|
|
780
|
+
return n;
|
|
923
781
|
}
|
|
924
|
-
|
|
925
|
-
|
|
782
|
+
const TopicIndexSchema = z.object({
|
|
783
|
+
topics: z.record(z.string(), z.object({
|
|
784
|
+
dec_id: z.string().optional(),
|
|
785
|
+
}).passthrough()),
|
|
786
|
+
}).passthrough();
|
|
787
|
+
function countUnpromotedCandidates(repoRoot) {
|
|
788
|
+
const path = join(repoRoot, ".cairn", "ground", "topic-index.yaml");
|
|
926
789
|
if (!existsSync(path))
|
|
927
|
-
return
|
|
790
|
+
return 0;
|
|
928
791
|
try {
|
|
929
|
-
const
|
|
930
|
-
const
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
792
|
+
const raw = readFileSync(path, "utf8");
|
|
793
|
+
const parsed = parseYaml(raw);
|
|
794
|
+
const result = TopicIndexSchema.safeParse(parsed);
|
|
795
|
+
if (!result.success)
|
|
796
|
+
return 0;
|
|
797
|
+
let n = 0;
|
|
798
|
+
for (const entry of Object.values(result.data.topics)) {
|
|
799
|
+
if (entry.dec_id === undefined)
|
|
800
|
+
n += 1;
|
|
936
801
|
}
|
|
937
|
-
return
|
|
802
|
+
return n;
|
|
938
803
|
}
|
|
939
804
|
catch {
|
|
940
|
-
return
|
|
805
|
+
return 0;
|
|
941
806
|
}
|
|
942
807
|
}
|
|
808
|
+
function formatDuration(ms) {
|
|
809
|
+
if (ms < 1_000)
|
|
810
|
+
return `${ms}ms`;
|
|
811
|
+
const seconds = ms / 1_000;
|
|
812
|
+
if (seconds < 60)
|
|
813
|
+
return `${seconds.toFixed(1)}s`;
|
|
814
|
+
const minutes = Math.floor(seconds / 60);
|
|
815
|
+
const remSeconds = Math.round(seconds - minutes * 60);
|
|
816
|
+
return `${minutes}m ${remSeconds}s`;
|
|
817
|
+
}
|
|
818
|
+
function shortenHomePath(abs) {
|
|
819
|
+
const home = homedir();
|
|
820
|
+
if (abs.startsWith(home))
|
|
821
|
+
return `~${abs.slice(home.length)}`;
|
|
822
|
+
return abs;
|
|
823
|
+
}
|
|
943
824
|
function printDiscovery(d, decidedSlug, warnings, summary) {
|
|
944
825
|
process.stdout.write("\n");
|
|
945
826
|
process.stdout.write(` ${visualC.bold("Scanning")}${visualC.dim("…")}\n`);
|
|
@@ -1009,22 +890,30 @@ async function runPhaseSix(args) {
|
|
|
1009
890
|
return { ingestion: null, baselineAudit: null };
|
|
1010
891
|
}
|
|
1011
892
|
process.stdout.write("\n");
|
|
1012
|
-
process.stdout.write(` ${visualC.bold("Phase
|
|
1013
|
-
// ── 6.1 — docs ingestion (
|
|
893
|
+
process.stdout.write(` ${visualC.bold("Phase 8")} — ingesting existing project knowledge…\n`);
|
|
894
|
+
// ── 6.1 — docs ingestion (staged: marker → file-filter → section) ──
|
|
1014
895
|
let ingestion = null;
|
|
1015
896
|
try {
|
|
1016
|
-
let
|
|
1017
|
-
|
|
1018
|
-
ingestion = await runDocsIngestion({
|
|
897
|
+
let lastStage = null;
|
|
898
|
+
const ingestionArgs = {
|
|
1019
899
|
repoRoot: args.repoRoot,
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
900
|
+
onChunkProgress: (row) => {
|
|
901
|
+
// Print one trailer line per stage so the operator sees the
|
|
902
|
+
// staged pipeline land — Stage 1 (file filter) finishes first
|
|
903
|
+
// and is usually the smaller batch; Stage 2 (section classify)
|
|
904
|
+
// follows once authoritative files are known.
|
|
905
|
+
if (row.chunksDone === row.totalChunks && row.stage !== lastStage) {
|
|
906
|
+
lastStage = row.stage;
|
|
907
|
+
const label = row.stage === "file-filter"
|
|
908
|
+
? "stage 1 file filter"
|
|
909
|
+
: "stage 2 section classify";
|
|
910
|
+
process.stdout.write(` ${label.padEnd(28)} ✓ ${row.entriesDone}/${row.totalEntries} in ${row.totalChunks} batches\n`);
|
|
1025
911
|
}
|
|
1026
912
|
},
|
|
1027
|
-
}
|
|
913
|
+
};
|
|
914
|
+
if (args.mockClassify !== undefined)
|
|
915
|
+
ingestionArgs.mockClassify = args.mockClassify;
|
|
916
|
+
ingestion = await runDocsIngestion(ingestionArgs);
|
|
1028
917
|
}
|
|
1029
918
|
catch (err) {
|
|
1030
919
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -1047,22 +936,6 @@ async function runPhaseSix(args) {
|
|
|
1047
936
|
baselineAudit = await runBaselineAudit({
|
|
1048
937
|
repoRoot: args.repoRoot,
|
|
1049
938
|
languages: defaultBaselineLanguages(stackKinds),
|
|
1050
|
-
projectGlobs,
|
|
1051
|
-
onSensorProgress: (row) => {
|
|
1052
|
-
if (printedSensors.length < 3) {
|
|
1053
|
-
const id = row.sensor_id.padEnd(22);
|
|
1054
|
-
const status = row.skipped
|
|
1055
|
-
? visualC.dim("skipped")
|
|
1056
|
-
: row.finding_count > 0
|
|
1057
|
-
? `${row.finding_count} existing violation${row.finding_count === 1 ? "" : "s"} found`
|
|
1058
|
-
: "clean";
|
|
1059
|
-
process.stdout.write(` ${id} ${row.skipped ? "○" : row.finding_count > 0 ? "⚠" : "✓"} ${status}\n`);
|
|
1060
|
-
printedSensors.push(row.sensor_id);
|
|
1061
|
-
}
|
|
1062
|
-
else {
|
|
1063
|
-
suppressedCount += 1;
|
|
1064
|
-
}
|
|
1065
|
-
},
|
|
1066
939
|
});
|
|
1067
940
|
if (suppressedCount > 0) {
|
|
1068
941
|
process.stdout.write(` ${visualC.dim(`+ ${suppressedCount} more…`)}\n`);
|
|
@@ -1076,37 +949,6 @@ async function runPhaseSix(args) {
|
|
|
1076
949
|
}
|
|
1077
950
|
return { ingestion, baselineAudit };
|
|
1078
951
|
}
|
|
1079
|
-
function describeIngestion(ingestion) {
|
|
1080
|
-
if (ingestion === null)
|
|
1081
|
-
return null;
|
|
1082
|
-
const decCount = ingestion.decsWritten.length;
|
|
1083
|
-
if (decCount === 0) {
|
|
1084
|
-
if (ingestion.scannedEntries === 0) {
|
|
1085
|
-
return `0 emitted (no docs/* paragraphs in topic-index)`;
|
|
1086
|
-
}
|
|
1087
|
-
return `0 emitted (${ingestion.scannedEntries} entries scanned, none classified as decision/domain-rule)`;
|
|
1088
|
-
}
|
|
1089
|
-
return `${decCount} DEC${decCount === 1 ? "" : "s"} written verbatim from docs/* (auto-promoted)`;
|
|
1090
|
-
}
|
|
1091
|
-
function describeCanonical(_ingestion) {
|
|
1092
|
-
// canonical-map seeding moved out of phase 6 in v0.5.0 — handled by
|
|
1093
|
-
// the standalone topic-index pipeline instead.
|
|
1094
|
-
return null;
|
|
1095
|
-
}
|
|
1096
|
-
function describeBaseline(audit) {
|
|
1097
|
-
if (audit === null)
|
|
1098
|
-
return null;
|
|
1099
|
-
const fileNote = audit.truncatedAtFileCap
|
|
1100
|
-
? `${audit.filesScanned}/${audit.filesAvailable} files — sample mode`
|
|
1101
|
-
: `${audit.filesScanned} files`;
|
|
1102
|
-
if (audit.totalFindings === 0) {
|
|
1103
|
-
if (audit.skippedSensorIds.length > 0 && audit.cleanSensorIds.length === 0) {
|
|
1104
|
-
return null;
|
|
1105
|
-
}
|
|
1106
|
-
return `0 findings (run on ${fileNote})`;
|
|
1107
|
-
}
|
|
1108
|
-
return `${audit.totalFindings} existing sensor finding${audit.totalFindings === 1 ? "" : "s"} (run cairn attention; ${fileNote})`;
|
|
1109
|
-
}
|
|
1110
952
|
function remoteShorthand(url) {
|
|
1111
953
|
// https://github.com/foo/bar.git → github.com/foo/bar
|
|
1112
954
|
// git@github.com:foo/bar.git → github.com/foo/bar
|