@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,13 @@
|
|
|
1
|
+
export type { Attestation, AttestationDelivered, AttestationDeferred, DiffEntry, ProjectGlobs, SensorFinding, SensorInput, SensorLanguage, SensorResult, SensorSweepResult, StubCatalog, StubPattern, } from "./types.js";
|
|
2
|
+
export { getDiff, diffHasGlobMatch, filterDiffByGlobs } from "./diff.js";
|
|
3
|
+
export { loadStubCatalog, parseStubCatalog, loadSensorRegistry } from "./catalog.js";
|
|
4
|
+
export type { SensorRegistry, SensorRegistryEntry } from "./catalog.js";
|
|
5
|
+
export { detectStubMatches, runStubCatalog, detectLanguage } from "./stub-catalog.js";
|
|
6
|
+
export type { StubMatch } from "./stub-catalog.js";
|
|
7
|
+
export { extractAttestation, runAttestationCrossCheck, } from "./attestation.js";
|
|
8
|
+
export { runRouteHandlerNonEmpty, runDtoNoFakeFields, } from "./structural.js";
|
|
9
|
+
export { loadAcceptedDecisions, decisionsInScope, listMirrorFiles, runDecisionAssertions, } from "./decisions.js";
|
|
10
|
+
export { formatRemediation } from "./remediation.js";
|
|
11
|
+
export type { RemediationOptions } from "./remediation.js";
|
|
12
|
+
export { runSensors } from "./runner.js";
|
|
13
|
+
export type { RunSensorsArgs } from "./runner.js";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { getDiff, diffHasGlobMatch, filterDiffByGlobs } from "./diff.js";
|
|
2
|
+
export { loadStubCatalog, parseStubCatalog, loadSensorRegistry } from "./catalog.js";
|
|
3
|
+
export { detectStubMatches, runStubCatalog, detectLanguage } from "./stub-catalog.js";
|
|
4
|
+
export { extractAttestation, runAttestationCrossCheck, } from "./attestation.js";
|
|
5
|
+
export { runRouteHandlerNonEmpty, runDtoNoFakeFields, } from "./structural.js";
|
|
6
|
+
export { loadAcceptedDecisions, decisionsInScope, listMirrorFiles, runDecisionAssertions, } from "./decisions.js";
|
|
7
|
+
export { formatRemediation } from "./remediation.js";
|
|
8
|
+
export { runSensors } from "./runner.js";
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/sensors/index.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAErF,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEtF,OAAO,EACL,kBAAkB,EAClB,wBAAwB,GACzB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,uBAAuB,EACvB,kBAAkB,GACnB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,qBAAqB,EACrB,gBAAgB,EAChB,eAAe,EACf,qBAAqB,GACtB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAErD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build a remediation prompt from sensor findings.
|
|
3
|
+
*
|
|
4
|
+
* Per OpenAI's pattern: failure messages are remediation prompts the agent
|
|
5
|
+
* consumes on retry. The orchestrator appends this body to the original
|
|
6
|
+
* prompt and re-dispatches the agent. The agent sees concrete failures with
|
|
7
|
+
* paths, lines, matched text, and remediation guidance.
|
|
8
|
+
*/
|
|
9
|
+
import type { SensorResult } from "./types.js";
|
|
10
|
+
export interface RemediationOptions {
|
|
11
|
+
/** Number of the upcoming retry (1 = first retry). */
|
|
12
|
+
attempt: number;
|
|
13
|
+
/** Max attempts the orchestrator will allow. */
|
|
14
|
+
maxAttempts: number;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Format a remediation prompt body to be appended to the original task
|
|
18
|
+
* prompt. Empty string when there are no hard failures.
|
|
19
|
+
*/
|
|
20
|
+
export declare function formatRemediation(results: SensorResult[], opts: RemediationOptions): string;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build a remediation prompt from sensor findings.
|
|
3
|
+
*
|
|
4
|
+
* Per OpenAI's pattern: failure messages are remediation prompts the agent
|
|
5
|
+
* consumes on retry. The orchestrator appends this body to the original
|
|
6
|
+
* prompt and re-dispatches the agent. The agent sees concrete failures with
|
|
7
|
+
* paths, lines, matched text, and remediation guidance.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Format a remediation prompt body to be appended to the original task
|
|
11
|
+
* prompt. Empty string when there are no hard failures.
|
|
12
|
+
*/
|
|
13
|
+
export function formatRemediation(results, opts) {
|
|
14
|
+
const hardFails = results.filter((r) => !r.ok);
|
|
15
|
+
if (hardFails.length === 0)
|
|
16
|
+
return "";
|
|
17
|
+
const lines = [];
|
|
18
|
+
lines.push("## Sensor failures (from previous attempt)", "", `Your previous turn was rejected by ${hardFails.length} sensor(s). Read each finding below; the path/line/match are concrete. Fix every hard finding before your next turn — this is retry attempt ${opts.attempt} of ${opts.maxAttempts}.`, "", "Do NOT re-run the parts that already passed. Edit only what the failures point to.", "");
|
|
19
|
+
for (const result of hardFails) {
|
|
20
|
+
const hard = result.findings.filter((f) => f.severity === "hard");
|
|
21
|
+
if (hard.length === 0)
|
|
22
|
+
continue;
|
|
23
|
+
lines.push(`### Sensor \`${result.sensor_id}\` — ${hard.length} failure(s)`);
|
|
24
|
+
lines.push("");
|
|
25
|
+
for (const finding of hard) {
|
|
26
|
+
lines.push(formatFinding(finding));
|
|
27
|
+
}
|
|
28
|
+
lines.push("");
|
|
29
|
+
}
|
|
30
|
+
// Append soft findings as advisory context (not gating).
|
|
31
|
+
const softFindings = results.flatMap((r) => r.findings).filter((f) => f.severity === "soft");
|
|
32
|
+
if (softFindings.length > 0) {
|
|
33
|
+
lines.push("### Advisory (soft) findings");
|
|
34
|
+
lines.push("");
|
|
35
|
+
lines.push("These do not block your run but represent debt or surfaces a reviewer will inspect:");
|
|
36
|
+
lines.push("");
|
|
37
|
+
for (const f of softFindings)
|
|
38
|
+
lines.push(formatFinding(f));
|
|
39
|
+
lines.push("");
|
|
40
|
+
}
|
|
41
|
+
lines.push("## What to do", "", "1. Re-emit your `attestation:` YAML block at the END of your reply, with corrected `delivered`, `files_touched`, `todos_introduced`, and `stubs_introduced` values.", "2. Edit the files listed above to remove the stub patterns / fix the assertions / fill the empty handlers.", "3. Do NOT re-introduce TODO/FIXME/XXX/HACK markers, `throw new Error('not implemented')`, `as any` casts, or any pattern flagged in `.cairn/config/stub-patterns.yaml`.", "4. If any failure is genuinely impossible to satisfy (e.g. an assertion contradicts a current decision), emit a `blocked_by:` block in your final response instead of a partial diff.", "");
|
|
42
|
+
return lines.join("\n");
|
|
43
|
+
}
|
|
44
|
+
function formatFinding(f) {
|
|
45
|
+
const where = [];
|
|
46
|
+
if (f.path !== undefined && f.line !== undefined)
|
|
47
|
+
where.push(`${f.path}:${f.line}`);
|
|
48
|
+
else if (f.path !== undefined)
|
|
49
|
+
where.push(f.path);
|
|
50
|
+
if (f.pattern_id)
|
|
51
|
+
where.push(`pattern=${f.pattern_id}`);
|
|
52
|
+
if (f.decision_id)
|
|
53
|
+
where.push(`decision=${f.decision_id}`);
|
|
54
|
+
if (f.assertion_id)
|
|
55
|
+
where.push(`assertion=${f.assertion_id}`);
|
|
56
|
+
const head = where.length > 0 ? `[${where.join(" • ")}] ` : "";
|
|
57
|
+
let body = f.message;
|
|
58
|
+
if (f.matched_text)
|
|
59
|
+
body += `\n matched: \`${truncate(f.matched_text, 160)}\``;
|
|
60
|
+
return `- ${head}${body}`;
|
|
61
|
+
}
|
|
62
|
+
function truncate(s, max) {
|
|
63
|
+
return s.length <= max ? s : `${s.slice(0, max)}…`;
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=remediation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remediation.js","sourceRoot":"","sources":["../../src/sensors/remediation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sensor runner — orchestrator-facing entry point.
|
|
3
|
+
*
|
|
4
|
+
* Composes Layer A + Layer B + Layer D + decision-assertions into a single
|
|
5
|
+
* sweep. Returns the aggregated result + the remediation prompt body the
|
|
6
|
+
* orchestrator feeds back to the agent on retry.
|
|
7
|
+
*
|
|
8
|
+
* Phase 9 wires the implementer-side stack only. Layer C (reviewer subagent)
|
|
9
|
+
* is Phase 10; Layer E (high-stakes E2E) and U (UAT) are Phases 11+. Soft
|
|
10
|
+
* findings emitted here are intentionally surfaced for those later layers
|
|
11
|
+
* to consume.
|
|
12
|
+
*/
|
|
13
|
+
import type { Attestation, ProjectGlobs, SensorLanguage, SensorSweepResult } from "./types.js";
|
|
14
|
+
export interface RunSensorsArgs {
|
|
15
|
+
/** Mirror checkout where the agent worked. */
|
|
16
|
+
mirrorPath: string;
|
|
17
|
+
/** SHA pin captured at workspace prep. */
|
|
18
|
+
shaPin: string;
|
|
19
|
+
/** Final assistant text, used to extract the attestation block. */
|
|
20
|
+
finalAssistantText?: string;
|
|
21
|
+
/** Languages active for this profile (filters Layer A patterns). */
|
|
22
|
+
languages: SensorLanguage[];
|
|
23
|
+
/** Project-block globs from workflow.md. */
|
|
24
|
+
projectGlobs: ProjectGlobs;
|
|
25
|
+
/** Run id used in log lines. */
|
|
26
|
+
runId: string;
|
|
27
|
+
/** Number of this attempt (1 = first run, 2 = first retry). */
|
|
28
|
+
attempt: number;
|
|
29
|
+
/** Max attempts the orchestrator will allow. */
|
|
30
|
+
maxAttempts: number;
|
|
31
|
+
/**
|
|
32
|
+
* Optional pre-extracted attestation. Useful for tests / smokes that
|
|
33
|
+
* inject the attestation directly without going through the assistant
|
|
34
|
+
* stream. When supplied, finalAssistantText is ignored for extraction.
|
|
35
|
+
*/
|
|
36
|
+
attestation?: Attestation;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Run all sensors for a finished implementer run. Returns:
|
|
40
|
+
* - per-sensor results (with `ok` + findings)
|
|
41
|
+
* - aggregate `ok` (false if any hard failure)
|
|
42
|
+
* - remediation prompt body for the next retry (empty string on success)
|
|
43
|
+
*/
|
|
44
|
+
export declare function runSensors(args: RunSensorsArgs): Promise<SensorSweepResult>;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sensor runner — orchestrator-facing entry point.
|
|
3
|
+
*
|
|
4
|
+
* Composes Layer A + Layer B + Layer D + decision-assertions into a single
|
|
5
|
+
* sweep. Returns the aggregated result + the remediation prompt body the
|
|
6
|
+
* orchestrator feeds back to the agent on retry.
|
|
7
|
+
*
|
|
8
|
+
* Phase 9 wires the implementer-side stack only. Layer C (reviewer subagent)
|
|
9
|
+
* is Phase 10; Layer E (high-stakes E2E) and U (UAT) are Phases 11+. Soft
|
|
10
|
+
* findings emitted here are intentionally surfaced for those later layers
|
|
11
|
+
* to consume.
|
|
12
|
+
*/
|
|
13
|
+
import { logger } from "../logger.js";
|
|
14
|
+
import { decisionsInScope, loadAcceptedDecisions, runDecisionAssertions } from "./decisions.js";
|
|
15
|
+
import { extractAttestation, runAttestationCrossCheck } from "./attestation.js";
|
|
16
|
+
import { getDiff } from "./diff.js";
|
|
17
|
+
import { loadStubCatalog } from "./catalog.js";
|
|
18
|
+
import { formatRemediation } from "./remediation.js";
|
|
19
|
+
import { runStubCatalog } from "./stub-catalog.js";
|
|
20
|
+
import { runDtoNoFakeFields, runRouteHandlerNonEmpty } from "./structural.js";
|
|
21
|
+
const log = logger("sensors.runner");
|
|
22
|
+
/**
|
|
23
|
+
* Run all sensors for a finished implementer run. Returns:
|
|
24
|
+
* - per-sensor results (with `ok` + findings)
|
|
25
|
+
* - aggregate `ok` (false if any hard failure)
|
|
26
|
+
* - remediation prompt body for the next retry (empty string on success)
|
|
27
|
+
*/
|
|
28
|
+
export async function runSensors(args) {
|
|
29
|
+
const startedAt = Date.now();
|
|
30
|
+
const diff = await getDiff({ mirrorPath: args.mirrorPath, shaPin: args.shaPin });
|
|
31
|
+
const stubCatalog = loadStubCatalog(args.mirrorPath);
|
|
32
|
+
const acceptedDecisions = loadAcceptedDecisions(args.mirrorPath);
|
|
33
|
+
const inScope = decisionsInScope(acceptedDecisions, diff);
|
|
34
|
+
const attestation = args.attestation ?? extractAttestation(args.finalAssistantText ?? "");
|
|
35
|
+
const results = [];
|
|
36
|
+
// Layer A — stub-pattern catalog.
|
|
37
|
+
results.push(runStubCatalog({
|
|
38
|
+
diff,
|
|
39
|
+
catalog: stubCatalog,
|
|
40
|
+
languages: args.languages,
|
|
41
|
+
}));
|
|
42
|
+
// Layer B — attestation cross-check.
|
|
43
|
+
results.push(runAttestationCrossCheck({
|
|
44
|
+
attestation,
|
|
45
|
+
diff,
|
|
46
|
+
stubCatalog,
|
|
47
|
+
ignoreGlobs: [".cairn/runs/active/**", ".cairn/inbox/processed/**"],
|
|
48
|
+
}));
|
|
49
|
+
// Layer D — generic structural sensors.
|
|
50
|
+
results.push(runRouteHandlerNonEmpty({
|
|
51
|
+
diff,
|
|
52
|
+
globs: args.projectGlobs.route_handler_globs,
|
|
53
|
+
}));
|
|
54
|
+
results.push(runDtoNoFakeFields({
|
|
55
|
+
diff,
|
|
56
|
+
globs: args.projectGlobs.dto_globs,
|
|
57
|
+
}));
|
|
58
|
+
// Decision-assertions.
|
|
59
|
+
results.push(runDecisionAssertions({
|
|
60
|
+
mirrorPath: args.mirrorPath,
|
|
61
|
+
diff,
|
|
62
|
+
decisions: inScope,
|
|
63
|
+
}));
|
|
64
|
+
const hard_failures = results.filter((r) => !r.ok).length;
|
|
65
|
+
const soft_findings = results.reduce((n, r) => n + r.findings.filter((f) => f.severity === "soft").length, 0);
|
|
66
|
+
const ok = hard_failures === 0;
|
|
67
|
+
const remediation_prompt = ok
|
|
68
|
+
? ""
|
|
69
|
+
: formatRemediation(results, {
|
|
70
|
+
attempt: args.attempt,
|
|
71
|
+
maxAttempts: args.maxAttempts,
|
|
72
|
+
});
|
|
73
|
+
log.info({
|
|
74
|
+
run_id: args.runId,
|
|
75
|
+
attempt: args.attempt,
|
|
76
|
+
ok,
|
|
77
|
+
hard_failures,
|
|
78
|
+
soft_findings,
|
|
79
|
+
sensors: results.map((r) => ({
|
|
80
|
+
id: r.sensor_id,
|
|
81
|
+
ok: r.ok,
|
|
82
|
+
findings: r.findings.length,
|
|
83
|
+
skipped: r.skipped?.reason,
|
|
84
|
+
})),
|
|
85
|
+
}, "sensor sweep complete");
|
|
86
|
+
return {
|
|
87
|
+
ok,
|
|
88
|
+
hard_failures,
|
|
89
|
+
soft_findings,
|
|
90
|
+
results,
|
|
91
|
+
remediation_prompt,
|
|
92
|
+
duration_ms: Date.now() - startedAt,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/sensors/runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Layer D — generic project-agnostic structural sensors.
|
|
3
|
+
*
|
|
4
|
+
* Triggered when the diff touches files matching the project's glob keys.
|
|
5
|
+
* Each sensor inspects the POST-change content of those files (not just
|
|
6
|
+
* the diff) — Layer D is "do these load-bearing files follow contract",
|
|
7
|
+
* which is stricter than Layer A's "did this run add new debt".
|
|
8
|
+
*
|
|
9
|
+
* route-handler-non-empty — every method in a route/controller class has a
|
|
10
|
+
* non-trivial body. Catches "added handler that
|
|
11
|
+
* does nothing" disguised as completion.
|
|
12
|
+
* dto-no-fake-fields — @IsOptional() fields with no other validator
|
|
13
|
+
* are fake-thoroughness; they look like work and
|
|
14
|
+
* do nothing.
|
|
15
|
+
*
|
|
16
|
+
* Both are pattern-based; profiles plug stack-specific globs. The regex is
|
|
17
|
+
* intentionally conservative (false-negatives over false-positives) — sensors
|
|
18
|
+
* that fail-loud-on-noise get disabled which defeats the purpose.
|
|
19
|
+
*/
|
|
20
|
+
import type { DiffEntry, SensorResult } from "./types.js";
|
|
21
|
+
/** Run route-handler-non-empty against changed files matching globs. */
|
|
22
|
+
export declare function runRouteHandlerNonEmpty(args: {
|
|
23
|
+
diff: DiffEntry[];
|
|
24
|
+
globs: string[] | undefined;
|
|
25
|
+
}): SensorResult;
|
|
26
|
+
/** Run dto-no-fake-fields against changed files matching globs. */
|
|
27
|
+
export declare function runDtoNoFakeFields(args: {
|
|
28
|
+
diff: DiffEntry[];
|
|
29
|
+
globs: string[] | undefined;
|
|
30
|
+
}): SensorResult;
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Layer D — generic project-agnostic structural sensors.
|
|
3
|
+
*
|
|
4
|
+
* Triggered when the diff touches files matching the project's glob keys.
|
|
5
|
+
* Each sensor inspects the POST-change content of those files (not just
|
|
6
|
+
* the diff) — Layer D is "do these load-bearing files follow contract",
|
|
7
|
+
* which is stricter than Layer A's "did this run add new debt".
|
|
8
|
+
*
|
|
9
|
+
* route-handler-non-empty — every method in a route/controller class has a
|
|
10
|
+
* non-trivial body. Catches "added handler that
|
|
11
|
+
* does nothing" disguised as completion.
|
|
12
|
+
* dto-no-fake-fields — @IsOptional() fields with no other validator
|
|
13
|
+
* are fake-thoroughness; they look like work and
|
|
14
|
+
* do nothing.
|
|
15
|
+
*
|
|
16
|
+
* Both are pattern-based; profiles plug stack-specific globs. The regex is
|
|
17
|
+
* intentionally conservative (false-negatives over false-positives) — sensors
|
|
18
|
+
* that fail-loud-on-noise get disabled which defeats the purpose.
|
|
19
|
+
*/
|
|
20
|
+
import { matchAnyGlob } from "../ground/glob.js";
|
|
21
|
+
const ROUTE_SENSOR_ID = "route-handler-non-empty";
|
|
22
|
+
const DTO_SENSOR_ID = "dto-no-fake-fields";
|
|
23
|
+
/** Method body that's effectively a no-op — language-agnostic regex. */
|
|
24
|
+
const EMPTY_BODY_PATTERNS = [
|
|
25
|
+
// TypeScript/JavaScript class method with empty body or null/undefined return.
|
|
26
|
+
{
|
|
27
|
+
regex: /^\s*(?:public|private|protected|async)?\s*(?:async\s+)?(\w+)\s*\([^)]*\)\s*(?::\s*[^{]+)?\{\s*(?:return\s*(?:null|undefined)?\s*;?)?\s*\}/gm,
|
|
28
|
+
reason: "empty / return-null / return-undefined body",
|
|
29
|
+
},
|
|
30
|
+
// throw new Error('not implemented').
|
|
31
|
+
{
|
|
32
|
+
regex: /\b(\w+)\s*\([^)]*\)\s*(?::\s*[^{]+)?\{\s*throw\s+new\s+Error\s*\(\s*['"`][^'"`]*not[\s_]?implemented/gi,
|
|
33
|
+
reason: "throws not-implemented",
|
|
34
|
+
},
|
|
35
|
+
// Python: `def foo(...): pass` with nothing else.
|
|
36
|
+
{
|
|
37
|
+
regex: /def\s+(\w+)\s*\([^)]*\)\s*(?:->[^:]+)?:\s*\n\s*pass\s*\n/g,
|
|
38
|
+
reason: "Python def with `pass` body",
|
|
39
|
+
},
|
|
40
|
+
// Python: `def foo(...): return None`.
|
|
41
|
+
{
|
|
42
|
+
regex: /def\s+(\w+)\s*\([^)]*\)\s*(?:->[^:]+)?:\s*\n\s*return(?:\s+None)?\s*\n/g,
|
|
43
|
+
reason: "Python def returning None",
|
|
44
|
+
},
|
|
45
|
+
];
|
|
46
|
+
/** Detect a class context for TypeScript/JavaScript controllers. */
|
|
47
|
+
const TS_CONTROLLER_HINT = /\bclass\s+\w+(?:Controller|Resource|Resolver|Handler)\b|@(?:Controller|Resource|Resolver|Handler)\b|extends\s+(?:Controller|Resource)\b/;
|
|
48
|
+
/** Detect Python route registration. */
|
|
49
|
+
const PY_ROUTE_HINT = /@(?:app|router|blueprint|bp)\.(?:get|post|put|patch|delete|route)\b|@route\b|class\s+\w+(?:View|Resource)\b/;
|
|
50
|
+
/** Run route-handler-non-empty against changed files matching globs. */
|
|
51
|
+
export function runRouteHandlerNonEmpty(args) {
|
|
52
|
+
const startedAt = Date.now();
|
|
53
|
+
const findings = [];
|
|
54
|
+
if (!args.globs || args.globs.length === 0) {
|
|
55
|
+
return {
|
|
56
|
+
sensor_id: ROUTE_SENSOR_ID,
|
|
57
|
+
ok: true,
|
|
58
|
+
duration_ms: Date.now() - startedAt,
|
|
59
|
+
findings,
|
|
60
|
+
skipped: { reason: "route_handler_globs not configured for this project" },
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
const inScope = args.diff.filter((d) => d.status !== "deleted" && matchAnyGlob(d.path, args.globs ?? []));
|
|
64
|
+
if (inScope.length === 0) {
|
|
65
|
+
return {
|
|
66
|
+
sensor_id: ROUTE_SENSOR_ID,
|
|
67
|
+
ok: true,
|
|
68
|
+
duration_ms: Date.now() - startedAt,
|
|
69
|
+
findings,
|
|
70
|
+
skipped: { reason: "no diff entries match route_handler_globs" },
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
for (const entry of inScope) {
|
|
74
|
+
const text = entry.afterContent ?? "";
|
|
75
|
+
if (text.length === 0)
|
|
76
|
+
continue;
|
|
77
|
+
if (!isRouteHandlerFile(entry.path, text))
|
|
78
|
+
continue;
|
|
79
|
+
for (const { regex, reason } of EMPTY_BODY_PATTERNS) {
|
|
80
|
+
const re = new RegExp(regex.source, regex.flags);
|
|
81
|
+
let m;
|
|
82
|
+
while ((m = re.exec(text)) !== null) {
|
|
83
|
+
const methodName = m[1] ?? "<anon>";
|
|
84
|
+
if (METHOD_ALLOWLIST.has(methodName))
|
|
85
|
+
continue;
|
|
86
|
+
const line = lineOf(text, m.index);
|
|
87
|
+
findings.push({
|
|
88
|
+
sensor_id: ROUTE_SENSOR_ID,
|
|
89
|
+
path: entry.path,
|
|
90
|
+
line,
|
|
91
|
+
matched_text: m[0].slice(0, 200),
|
|
92
|
+
message: `${entry.path}:${line} route-handler method \`${methodName}\` — ${reason}`,
|
|
93
|
+
severity: "hard",
|
|
94
|
+
});
|
|
95
|
+
if (re.lastIndex === m.index)
|
|
96
|
+
re.lastIndex += 1;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return {
|
|
101
|
+
sensor_id: ROUTE_SENSOR_ID,
|
|
102
|
+
ok: findings.length === 0,
|
|
103
|
+
duration_ms: Date.now() - startedAt,
|
|
104
|
+
findings,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
/** Run dto-no-fake-fields against changed files matching globs. */
|
|
108
|
+
export function runDtoNoFakeFields(args) {
|
|
109
|
+
const startedAt = Date.now();
|
|
110
|
+
const findings = [];
|
|
111
|
+
if (!args.globs || args.globs.length === 0) {
|
|
112
|
+
return {
|
|
113
|
+
sensor_id: DTO_SENSOR_ID,
|
|
114
|
+
ok: true,
|
|
115
|
+
duration_ms: Date.now() - startedAt,
|
|
116
|
+
findings,
|
|
117
|
+
skipped: { reason: "dto_globs not configured for this project" },
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
const inScope = args.diff.filter((d) => d.status !== "deleted" && matchAnyGlob(d.path, args.globs ?? []));
|
|
121
|
+
if (inScope.length === 0) {
|
|
122
|
+
return {
|
|
123
|
+
sensor_id: DTO_SENSOR_ID,
|
|
124
|
+
ok: true,
|
|
125
|
+
duration_ms: Date.now() - startedAt,
|
|
126
|
+
findings,
|
|
127
|
+
skipped: { reason: "no diff entries match dto_globs" },
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
for (const entry of inScope) {
|
|
131
|
+
const text = entry.afterContent ?? "";
|
|
132
|
+
if (text.length === 0)
|
|
133
|
+
continue;
|
|
134
|
+
findings.push(...findFakeOptionalFields(entry.path, text));
|
|
135
|
+
}
|
|
136
|
+
return {
|
|
137
|
+
sensor_id: DTO_SENSOR_ID,
|
|
138
|
+
ok: findings.every((f) => f.severity !== "hard"),
|
|
139
|
+
duration_ms: Date.now() - startedAt,
|
|
140
|
+
findings,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* `@IsOptional()` followed by a property declaration with NO additional
|
|
145
|
+
* validator decorator on the same or preceding line(s). Capture group 1 is
|
|
146
|
+
* the field name.
|
|
147
|
+
*/
|
|
148
|
+
function findFakeOptionalFields(path, text) {
|
|
149
|
+
const findings = [];
|
|
150
|
+
// Match `@IsOptional()\n fieldName?: Type;` with no other validator.
|
|
151
|
+
const re = /@IsOptional\s*\(\s*\)\s*\n((?:\s*@[A-Z]\w+\s*\([^)]*\)\s*\n)*)\s*(\w+)\s*\??\s*:\s*[^;\n]+;?/g;
|
|
152
|
+
let m;
|
|
153
|
+
while ((m = re.exec(text)) !== null) {
|
|
154
|
+
const otherDecorators = m[1] ?? "";
|
|
155
|
+
const field = m[2] ?? "";
|
|
156
|
+
// If only `@IsOptional()` and nothing else, that's fake-thoroughness.
|
|
157
|
+
if (otherDecorators.trim().length === 0) {
|
|
158
|
+
const line = lineOf(text, m.index);
|
|
159
|
+
findings.push({
|
|
160
|
+
sensor_id: DTO_SENSOR_ID,
|
|
161
|
+
path,
|
|
162
|
+
line,
|
|
163
|
+
matched_text: m[0].slice(0, 200),
|
|
164
|
+
message: `${path}:${line} field \`${field}\` decorated only with @IsOptional() — add a validator (@IsString, @IsNumber, etc.) or remove the decorator`,
|
|
165
|
+
severity: "soft",
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
if (re.lastIndex === m.index)
|
|
169
|
+
re.lastIndex += 1;
|
|
170
|
+
}
|
|
171
|
+
return findings;
|
|
172
|
+
}
|
|
173
|
+
/** Methods we don't want to flag: constructors, framework hooks, etc. */
|
|
174
|
+
const METHOD_ALLOWLIST = new Set([
|
|
175
|
+
"constructor",
|
|
176
|
+
"ngOnInit",
|
|
177
|
+
"ngOnDestroy",
|
|
178
|
+
"onModuleInit",
|
|
179
|
+
"onModuleDestroy",
|
|
180
|
+
"onApplicationBootstrap",
|
|
181
|
+
"onApplicationShutdown",
|
|
182
|
+
"render",
|
|
183
|
+
]);
|
|
184
|
+
/** Heuristic: file LOOKS like a route/controller before regex-scanning bodies. */
|
|
185
|
+
function isRouteHandlerFile(path, text) {
|
|
186
|
+
if (TS_CONTROLLER_HINT.test(text))
|
|
187
|
+
return true;
|
|
188
|
+
if (PY_ROUTE_HINT.test(text))
|
|
189
|
+
return true;
|
|
190
|
+
// Conservative fallback — if the path matches the glob but the file doesn't
|
|
191
|
+
// declare a class or route decorator, skip rather than false-positive.
|
|
192
|
+
void path;
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
/** 1-based line number from a character offset. */
|
|
196
|
+
function lineOf(text, charIndex) {
|
|
197
|
+
let line = 1;
|
|
198
|
+
for (let i = 0; i < charIndex && i < text.length; i++) {
|
|
199
|
+
if (text.charCodeAt(i) === 10)
|
|
200
|
+
line += 1;
|
|
201
|
+
}
|
|
202
|
+
return line;
|
|
203
|
+
}
|
|
204
|
+
//# sourceMappingURL=structural.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"structural.js","sourceRoot":"","sources":["../../src/sensors/structural.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Layer A — mechanical stub-pattern catalog.
|
|
3
|
+
*
|
|
4
|
+
* Run regex patterns from `.cairn/config/stub-patterns.yaml` against every
|
|
5
|
+
* file changed in the diff. Hard-severity match fails the run; soft-severity
|
|
6
|
+
* contributes to attestation cross-check (stubs_introduced count).
|
|
7
|
+
*
|
|
8
|
+
* Per PRIMER §10 Layer A. Catalog grows additively via /oops dialog (L25).
|
|
9
|
+
*/
|
|
10
|
+
import type { DiffEntry, SensorLanguage, SensorResult, StubCatalog } from "./types.js";
|
|
11
|
+
/** Detect language from extension. Returns undefined for binaries / unknown. */
|
|
12
|
+
export declare function detectLanguage(path: string): SensorLanguage | undefined;
|
|
13
|
+
/** A single stub-pattern regex match found inside the diff. */
|
|
14
|
+
export interface StubMatch {
|
|
15
|
+
sensor_id: string;
|
|
16
|
+
pattern_id: string;
|
|
17
|
+
description: string;
|
|
18
|
+
severity: "hard" | "soft";
|
|
19
|
+
path: string;
|
|
20
|
+
line: number;
|
|
21
|
+
matched_text: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Walk the diff and emit a match for every regex hit on lines that were
|
|
25
|
+
* added or are part of a new file. Modified files: only count hits on lines
|
|
26
|
+
* not present at the SHA pin (i.e. genuinely-new debt).
|
|
27
|
+
*/
|
|
28
|
+
export declare function detectStubMatches(args: {
|
|
29
|
+
diff: DiffEntry[];
|
|
30
|
+
catalog: StubCatalog;
|
|
31
|
+
/** Filter patterns to these languages. `undefined` = all languages. */
|
|
32
|
+
languages: readonly SensorLanguage[] | undefined;
|
|
33
|
+
}): StubMatch[];
|
|
34
|
+
/** Run the Layer A sensor against a diff. */
|
|
35
|
+
export declare function runStubCatalog(args: {
|
|
36
|
+
diff: DiffEntry[];
|
|
37
|
+
catalog: StubCatalog;
|
|
38
|
+
languages: readonly SensorLanguage[];
|
|
39
|
+
}): SensorResult;
|