@isaacriehm/cairn 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/README.md +37 -0
- package/dist/.tsbuildinfo +1 -0
- package/dist/backprop/id.d.ts +14 -0
- package/dist/backprop/id.js +40 -0
- package/dist/backprop/id.js.map +1 -0
- package/dist/backprop/index.d.ts +23 -0
- package/dist/backprop/index.js +21 -0
- package/dist/backprop/index.js.map +1 -0
- package/dist/backprop/prompt.d.ts +16 -0
- package/dist/backprop/prompt.js +101 -0
- package/dist/backprop/prompt.js.map +1 -0
- package/dist/backprop/runner.d.ts +18 -0
- package/dist/backprop/runner.js +95 -0
- package/dist/backprop/runner.js.map +1 -0
- package/dist/backprop/schema.d.ts +61 -0
- package/dist/backprop/schema.js +55 -0
- package/dist/backprop/schema.js.map +1 -0
- package/dist/backprop/types.d.ts +101 -0
- package/dist/backprop/types.js +24 -0
- package/dist/backprop/types.js.map +1 -0
- package/dist/backprop/writer.d.ts +27 -0
- package/dist/backprop/writer.js +301 -0
- package/dist/backprop/writer.js.map +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/cli/attention.d.ts +11 -0
- package/dist/cli/attention.js +234 -0
- package/dist/cli/attention.js.map +1 -0
- package/dist/cli/daemon.d.ts +54 -0
- package/dist/cli/daemon.js +351 -0
- package/dist/cli/daemon.js.map +1 -0
- package/dist/cli/doctor.d.ts +8 -0
- package/dist/cli/doctor.js +116 -0
- package/dist/cli/doctor.js.map +1 -0
- package/dist/cli/gc.d.ts +15 -0
- package/dist/cli/gc.js +139 -0
- package/dist/cli/gc.js.map +1 -0
- package/dist/cli/hook.d.ts +18 -0
- package/dist/cli/hook.js +57 -0
- package/dist/cli/hook.js.map +1 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +127 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/init.d.ts +1 -0
- package/dist/cli/init.js +77 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/install.d.ts +52 -0
- package/dist/cli/install.js +308 -0
- package/dist/cli/install.js.map +1 -0
- package/dist/cli/join.d.ts +1 -0
- package/dist/cli/join.js +84 -0
- package/dist/cli/join.js.map +1 -0
- package/dist/cli/mcp.d.ts +1 -0
- package/dist/cli/mcp.js +62 -0
- package/dist/cli/mcp.js.map +1 -0
- package/dist/cli/mirror.d.ts +1 -0
- package/dist/cli/mirror.js +97 -0
- package/dist/cli/mirror.js.map +1 -0
- package/dist/cli/run.d.ts +1 -0
- package/dist/cli/run.js +174 -0
- package/dist/cli/run.js.map +1 -0
- package/dist/cli/scope.d.ts +8 -0
- package/dist/cli/scope.js +65 -0
- package/dist/cli/scope.js.map +1 -0
- package/dist/cli/task.d.ts +18 -0
- package/dist/cli/task.js +137 -0
- package/dist/cli/task.js.map +1 -0
- package/dist/cli/watch.d.ts +1 -0
- package/dist/cli/watch.js +73 -0
- package/dist/cli/watch.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 +14 -0
- package/dist/decision-capture/id.js +44 -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/frontend/discord/acl.d.ts +6 -0
- package/dist/frontend/discord/acl.js +19 -0
- package/dist/frontend/discord/acl.js.map +1 -0
- package/dist/frontend/discord/channels.d.ts +29 -0
- package/dist/frontend/discord/channels.js +58 -0
- package/dist/frontend/discord/channels.js.map +1 -0
- package/dist/frontend/discord/classifier.d.ts +16 -0
- package/dist/frontend/discord/classifier.js +29 -0
- package/dist/frontend/discord/classifier.js.map +1 -0
- package/dist/frontend/discord/index.d.ts +118 -0
- package/dist/frontend/discord/index.js +1104 -0
- package/dist/frontend/discord/index.js.map +1 -0
- package/dist/frontend/discord/slash.d.ts +18 -0
- package/dist/frontend/discord/slash.js +90 -0
- package/dist/frontend/discord/slash.js.map +1 -0
- package/dist/frontend/inbox.d.ts +17 -0
- package/dist/frontend/inbox.js +30 -0
- package/dist/frontend/inbox.js.map +1 -0
- package/dist/frontend/index.d.ts +8 -0
- package/dist/frontend/index.js +6 -0
- package/dist/frontend/index.js.map +1 -0
- package/dist/frontend/stub/index.d.ts +58 -0
- package/dist/frontend/stub/index.js +144 -0
- package/dist/frontend/stub/index.js.map +1 -0
- package/dist/frontend/types.d.ts +247 -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/classify.d.ts +25 -0
- package/dist/gc/classify.js +89 -0
- package/dist/gc/classify.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 +111 -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 +35 -0
- package/dist/gc/index.js +26 -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/stub-hits.d.ts +31 -0
- package/dist/gc/stub-hits.js +125 -0
- package/dist/gc/stub-hits.js.map +1 -0
- package/dist/gc/sweep.d.ts +56 -0
- package/dist/gc/sweep.js +178 -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/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 +14 -0
- package/dist/ground/index.js +10 -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/walk.d.ts +7 -0
- package/dist/ground/walk.js +53 -0
- package/dist/ground/walk.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/init/detect.d.ts +25 -0
- package/dist/init/detect.js +336 -0
- package/dist/init/detect.js.map +1 -0
- package/dist/init/index.d.ts +14 -0
- package/dist/init/index.js +9 -0
- package/dist/init/index.js.map +1 -0
- package/dist/init/init.d.ts +68 -0
- package/dist/init/init.js +673 -0
- package/dist/init/init.js.map +1 -0
- package/dist/init/mapper.d.ts +160 -0
- package/dist/init/mapper.js +248 -0
- package/dist/init/mapper.js.map +1 -0
- package/dist/init/prompts.d.ts +70 -0
- package/dist/init/prompts.js +80 -0
- package/dist/init/prompts.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 +75 -0
- package/dist/init/seed.js.map +1 -0
- package/dist/init/setup-runners.d.ts +17 -0
- package/dist/init/setup-runners.js +70 -0
- package/dist/init/setup-runners.js.map +1 -0
- package/dist/init/types.d.ts +59 -0
- package/dist/init/types.js +10 -0
- package/dist/init/types.js.map +1 -0
- package/dist/init/walker.d.ts +53 -0
- package/dist/init/walker.js +460 -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/logger.d.ts +3 -0
- package/dist/logger.js +23 -0
- package/dist/logger.js.map +1 -0
- package/dist/mcp/context.d.ts +16 -0
- package/dist/mcp/context.js +8 -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/index.d.ts +10 -0
- package/dist/mcp/index.js +7 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/path-allowlist.d.ts +25 -0
- package/dist/mcp/path-allowlist.js +66 -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 +153 -0
- package/dist/mcp/schemas.js +135 -0
- package/dist/mcp/schemas.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.d.ts +8 -0
- package/dist/mcp/tools/append.js +33 -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 +49 -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 +93 -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 +47 -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 +80 -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 +44 -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 +65 -0
- package/dist/mcp/tools/invariants-in-scope.js.map +1 -0
- package/dist/mcp/tools/query-history.d.ts +9 -0
- package/dist/mcp/tools/query-history.js +33 -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 +101 -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 +28 -0
- package/dist/mcp/tools/record-run-event.js.map +1 -0
- package/dist/mcp/tools/search.d.ts +9 -0
- package/dist/mcp/tools/search.js +165 -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 +77 -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/orchestrator/activity-summarizer.d.ts +33 -0
- package/dist/orchestrator/activity-summarizer.js +120 -0
- package/dist/orchestrator/activity-summarizer.js.map +1 -0
- package/dist/orchestrator/inbox.d.ts +78 -0
- package/dist/orchestrator/inbox.js +115 -0
- package/dist/orchestrator/inbox.js.map +1 -0
- package/dist/orchestrator/index.d.ts +9 -0
- package/dist/orchestrator/index.js +7 -0
- package/dist/orchestrator/index.js.map +1 -0
- package/dist/orchestrator/orchestrator.d.ts +154 -0
- package/dist/orchestrator/orchestrator.js +2437 -0
- package/dist/orchestrator/orchestrator.js.map +1 -0
- package/dist/orchestrator/prompt.d.ts +19 -0
- package/dist/orchestrator/prompt.js +50 -0
- package/dist/orchestrator/prompt.js.map +1 -0
- package/dist/orchestrator/queue.d.ts +21 -0
- package/dist/orchestrator/queue.js +80 -0
- package/dist/orchestrator/queue.js.map +1 -0
- package/dist/orchestrator/run-log.d.ts +53 -0
- package/dist/orchestrator/run-log.js +92 -0
- package/dist/orchestrator/run-log.js.map +1 -0
- package/dist/orchestrator/runner.d.ts +56 -0
- package/dist/orchestrator/runner.js +172 -0
- package/dist/orchestrator/runner.js.map +1 -0
- package/dist/orchestrator/tool-digest.d.ts +35 -0
- package/dist/orchestrator/tool-digest.js +116 -0
- package/dist/orchestrator/tool-digest.js.map +1 -0
- package/dist/orchestrator/types.d.ts +263 -0
- package/dist/orchestrator/types.js +2 -0
- package/dist/orchestrator/types.js.map +1 -0
- package/dist/orchestrator/workspace.d.ts +21 -0
- package/dist/orchestrator/workspace.js +31 -0
- package/dist/orchestrator/workspace.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/reviewer/index.d.ts +6 -0
- package/dist/reviewer/index.js +5 -0
- package/dist/reviewer/index.js.map +1 -0
- package/dist/reviewer/prompt.d.ts +11 -0
- package/dist/reviewer/prompt.js +132 -0
- package/dist/reviewer/prompt.js.map +1 -0
- package/dist/reviewer/remediation.d.ts +15 -0
- package/dist/reviewer/remediation.js +61 -0
- package/dist/reviewer/remediation.js.map +1 -0
- package/dist/reviewer/reviewer.d.ts +9 -0
- package/dist/reviewer/reviewer.js +89 -0
- package/dist/reviewer/reviewer.js.map +1 -0
- package/dist/reviewer/schema.d.ts +45 -0
- package/dist/reviewer/schema.js +43 -0
- package/dist/reviewer/schema.js.map +1 -0
- package/dist/reviewer/types.d.ts +74 -0
- package/dist/reviewer/types.js +14 -0
- package/dist/reviewer/types.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/tier0/classify.d.ts +5 -0
- package/dist/tier0/classify.js +91 -0
- package/dist/tier0/classify.js.map +1 -0
- package/dist/tier0/index.d.ts +3 -0
- package/dist/tier0/index.js +3 -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 +7 -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/uat/bundle.d.ts +68 -0
- package/dist/uat/bundle.js +168 -0
- package/dist/uat/bundle.js.map +1 -0
- package/dist/uat/index.d.ts +15 -0
- package/dist/uat/index.js +10 -0
- package/dist/uat/index.js.map +1 -0
- package/dist/uat/persistent.d.ts +64 -0
- package/dist/uat/persistent.js +206 -0
- package/dist/uat/persistent.js.map +1 -0
- package/dist/uat/probes/cli.d.ts +11 -0
- package/dist/uat/probes/cli.js +107 -0
- package/dist/uat/probes/cli.js.map +1 -0
- package/dist/uat/probes/http.d.ts +12 -0
- package/dist/uat/probes/http.js +139 -0
- package/dist/uat/probes/http.js.map +1 -0
- package/dist/uat/probes/index.d.ts +21 -0
- package/dist/uat/probes/index.js +30 -0
- package/dist/uat/probes/index.js.map +1 -0
- package/dist/uat/probes/integration.d.ts +18 -0
- package/dist/uat/probes/integration.js +188 -0
- package/dist/uat/probes/integration.js.map +1 -0
- package/dist/uat/probes/sql/config.d.ts +14 -0
- package/dist/uat/probes/sql/config.js +57 -0
- package/dist/uat/probes/sql/config.js.map +1 -0
- package/dist/uat/probes/sql/index.d.ts +29 -0
- package/dist/uat/probes/sql/index.js +43 -0
- package/dist/uat/probes/sql/index.js.map +1 -0
- package/dist/uat/probes/sql/mysql.d.ts +12 -0
- package/dist/uat/probes/sql/mysql.js +96 -0
- package/dist/uat/probes/sql/mysql.js.map +1 -0
- package/dist/uat/probes/sql/pg.d.ts +20 -0
- package/dist/uat/probes/sql/pg.js +102 -0
- package/dist/uat/probes/sql/pg.js.map +1 -0
- package/dist/uat/probes/sql/sqlite.d.ts +9 -0
- package/dist/uat/probes/sql/sqlite.js +58 -0
- package/dist/uat/probes/sql/sqlite.js.map +1 -0
- package/dist/uat/probes/sql/types.d.ts +46 -0
- package/dist/uat/probes/sql/types.js +10 -0
- package/dist/uat/probes/sql/types.js.map +1 -0
- package/dist/uat/probes/sql.d.ts +9 -0
- package/dist/uat/probes/sql.js +119 -0
- package/dist/uat/probes/sql.js.map +1 -0
- package/dist/uat/probes/ui.d.ts +19 -0
- package/dist/uat/probes/ui.js +244 -0
- package/dist/uat/probes/ui.js.map +1 -0
- package/dist/uat/prompt.d.ts +10 -0
- package/dist/uat/prompt.js +85 -0
- package/dist/uat/prompt.js.map +1 -0
- package/dist/uat/question.d.ts +50 -0
- package/dist/uat/question.js +139 -0
- package/dist/uat/question.js.map +1 -0
- package/dist/uat/rejection.d.ts +58 -0
- package/dist/uat/rejection.js +163 -0
- package/dist/uat/rejection.js.map +1 -0
- package/dist/uat/runner.d.ts +6 -0
- package/dist/uat/runner.js +96 -0
- package/dist/uat/runner.js.map +1 -0
- package/dist/uat/schema.d.ts +322 -0
- package/dist/uat/schema.js +189 -0
- package/dist/uat/schema.js.map +1 -0
- package/dist/uat/types.d.ts +268 -0
- package/dist/uat/types.js +18 -0
- package/dist/uat/types.js.map +1 -0
- package/dist/uat/uat.d.ts +89 -0
- package/dist/uat/uat.js +256 -0
- package/dist/uat/uat.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/dist/watch/daemon.d.ts +21 -0
- package/dist/watch/daemon.js +143 -0
- package/dist/watch/daemon.js.map +1 -0
- package/dist/watch/index.d.ts +4 -0
- package/dist/watch/index.js +3 -0
- package/dist/watch/index.js.map +1 -0
- package/dist/watch/regenerate.d.ts +25 -0
- package/dist/watch/regenerate.js +51 -0
- package/dist/watch/regenerate.js.map +1 -0
- package/package.json +75 -0
|
@@ -0,0 +1,673 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `harness init` orchestrator — full guided setup.
|
|
3
|
+
*
|
|
4
|
+
* Stages:
|
|
5
|
+
* 1. Detect → print summary
|
|
6
|
+
* 2. Proceed dialog (cancel exits cleanly, no writes)
|
|
7
|
+
* 3. Guided setup loop — for each missing prerequisite, prompt to fix:
|
|
8
|
+
* • discord bot token + guild → write to ~/.local/harness/.env
|
|
9
|
+
* • whisper model → curl download
|
|
10
|
+
* • ollama service → brew install + ollama pull
|
|
11
|
+
* • claude CLI → instruct (interactive auth, can't automate)
|
|
12
|
+
* 4. Seed `.harness/` + .archive/ from templates with `<project_name>`
|
|
13
|
+
* substituted. Write `.harness/config.yaml`.
|
|
14
|
+
* 5. Mirror init (skippable).
|
|
15
|
+
* 6. E2E dialog — now actually executes setup:uat-* via subprocess.
|
|
16
|
+
*
|
|
17
|
+
* Pre-configured environment skips guided setup dialogs entirely; init
|
|
18
|
+
* for an already-set-up operator runs proceed + e2e and that's it.
|
|
19
|
+
*/
|
|
20
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
21
|
+
import { join } from "node:path";
|
|
22
|
+
import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
|
|
23
|
+
import { ensureMirror, normalizeProjectName } from "../mirror/index.js";
|
|
24
|
+
import { logger } from "../logger.js";
|
|
25
|
+
import { detectAll } from "./detect.js";
|
|
26
|
+
import { runMapper, validateMapperOutput, } from "./mapper.js";
|
|
27
|
+
import { done, editYaml, freeTextWithDefault, header, info, secretInput, squareIntoSquareHole, yesNo, } from "./prompts.js";
|
|
28
|
+
import { upsertHarnessEnv } from "./secrets.js";
|
|
29
|
+
import { seedHarnessLayout } from "./seed.js";
|
|
30
|
+
import { downloadWhisperModel, offerInstallOllama, pullOllamaModel, runHarnessSetupScript, } from "./setup-runners.js";
|
|
31
|
+
import { buildRepoSummary } from "./walker.js";
|
|
32
|
+
import { updateWorkflowSlugBlock } from "./workflow-block.js";
|
|
33
|
+
const log = logger("init");
|
|
34
|
+
const DEFAULT_OFF_LIMITS = [
|
|
35
|
+
".env",
|
|
36
|
+
".env.*",
|
|
37
|
+
"node_modules/",
|
|
38
|
+
"dist/",
|
|
39
|
+
"build/",
|
|
40
|
+
"target/",
|
|
41
|
+
"__pycache__/",
|
|
42
|
+
"vendor/",
|
|
43
|
+
".venv/",
|
|
44
|
+
".direnv/",
|
|
45
|
+
".cache/",
|
|
46
|
+
"coverage/",
|
|
47
|
+
];
|
|
48
|
+
export async function runInit(args = {}) {
|
|
49
|
+
const repoRoot = args.repoRoot ?? process.cwd();
|
|
50
|
+
const mode = args.mode ?? "interactive";
|
|
51
|
+
const warnings = [];
|
|
52
|
+
header(`Harness init — ${repoRoot}`);
|
|
53
|
+
if (!existsSync(join(repoRoot, ".git"))) {
|
|
54
|
+
warnings.push("no .git directory — mirror init will be skipped; the harness expects a git-tracked working tree");
|
|
55
|
+
}
|
|
56
|
+
const detection = await detectAll(repoRoot);
|
|
57
|
+
const decidedSlug = args.slugOverride !== undefined
|
|
58
|
+
? normalizeProjectName(args.slugOverride)
|
|
59
|
+
: detection.project_slug;
|
|
60
|
+
printSummary(detection, decidedSlug);
|
|
61
|
+
printAdvisoryWarnings(detection, warnings);
|
|
62
|
+
// ── Dialog 1: proceed? ──────────────────────────────────────────────
|
|
63
|
+
const proceedChoice = await squareIntoSquareHole({
|
|
64
|
+
mode,
|
|
65
|
+
prompt: "Continue with these defaults?",
|
|
66
|
+
choices: [
|
|
67
|
+
{ id: "a", label: "yes — seed .harness/, set up mirror, configure", isDefault: true },
|
|
68
|
+
{ id: "b", label: "cancel" },
|
|
69
|
+
],
|
|
70
|
+
auto: args.autoProceed ?? "a",
|
|
71
|
+
});
|
|
72
|
+
if (proceedChoice === "b") {
|
|
73
|
+
info("\ncancelled — no files written.");
|
|
74
|
+
return {
|
|
75
|
+
detection,
|
|
76
|
+
decided_slug: decidedSlug,
|
|
77
|
+
proceed: false,
|
|
78
|
+
seeded_files: [],
|
|
79
|
+
collisions: [],
|
|
80
|
+
config_path: "",
|
|
81
|
+
mirror_path: null,
|
|
82
|
+
e2e_setup: null,
|
|
83
|
+
mapper_output: null,
|
|
84
|
+
mapper_applied_to_workflow: false,
|
|
85
|
+
mapper_applied_to_config: false,
|
|
86
|
+
warnings,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
// ── Guided setup: fix each missing prerequisite ────────────────────
|
|
90
|
+
let envState = detection.environment;
|
|
91
|
+
if (mode === "interactive" && args.skipGuidedSetup !== true) {
|
|
92
|
+
envState = await runGuidedSetup({ envState, warnings, mode });
|
|
93
|
+
}
|
|
94
|
+
// ── Init mapper (Tier 2 / Sonnet) — proposes pilot_module + project_globs.
|
|
95
|
+
// Without this, project_globs.{route_handler,dto,generator_source,high_stakes}
|
|
96
|
+
// sit empty and Layer-D sensors never fire on real diffs (rework brief §3.1).
|
|
97
|
+
const mapperOutput = await maybeRunMapper({
|
|
98
|
+
repoRoot,
|
|
99
|
+
detection,
|
|
100
|
+
mode,
|
|
101
|
+
skipMapper: args.skipMapper === true,
|
|
102
|
+
...(args.mockMapperOutput !== undefined
|
|
103
|
+
? { mockMapperOutput: args.mockMapperOutput }
|
|
104
|
+
: {}),
|
|
105
|
+
envClaudeAuth: envState.claude_auth,
|
|
106
|
+
warnings,
|
|
107
|
+
});
|
|
108
|
+
// ── Step 2: seed templates ─────────────────────────────────────────
|
|
109
|
+
header("Seeding .harness/ + .archive/");
|
|
110
|
+
const seed = seedHarnessLayout({
|
|
111
|
+
repoRoot,
|
|
112
|
+
projectSlug: decidedSlug,
|
|
113
|
+
...(args.force === true ? { force: true } : {}),
|
|
114
|
+
});
|
|
115
|
+
for (const f of seed.written_files)
|
|
116
|
+
done(`+ ${f}`);
|
|
117
|
+
for (const c of seed.collisions) {
|
|
118
|
+
warnings.push(`collision (kept existing): ${c}`);
|
|
119
|
+
done(`= ${c} (kept existing — pass --force to overwrite)`);
|
|
120
|
+
}
|
|
121
|
+
// ── Step 2b: apply mapper output to workflow.md `<slug>:` block.
|
|
122
|
+
// Only when workflow.md was just seeded (or --force re-seeded). Re-runs that
|
|
123
|
+
// kept the existing workflow.md skip this so operator edits aren't clobbered.
|
|
124
|
+
const wfRelPath = ".harness/config/workflow.md";
|
|
125
|
+
const wfWasSeeded = seed.written_files.includes(wfRelPath);
|
|
126
|
+
let mapperAppliedToWorkflow = false;
|
|
127
|
+
if (mapperOutput !== null && wfWasSeeded) {
|
|
128
|
+
const wfPath = join(repoRoot, wfRelPath);
|
|
129
|
+
try {
|
|
130
|
+
const r = updateWorkflowSlugBlock({
|
|
131
|
+
workflowMdPath: wfPath,
|
|
132
|
+
slug: decidedSlug,
|
|
133
|
+
update: {
|
|
134
|
+
pilot_module: mapperOutput.pilot_module,
|
|
135
|
+
route_handler_globs: mapperOutput.route_handler_globs,
|
|
136
|
+
dto_globs: mapperOutput.dto_globs,
|
|
137
|
+
generator_source_globs: mapperOutput.generator_source_globs,
|
|
138
|
+
high_stakes_globs: mapperOutput.high_stakes_globs,
|
|
139
|
+
off_limits_append: mapperOutput.off_limits_globs,
|
|
140
|
+
},
|
|
141
|
+
});
|
|
142
|
+
done(`+ patched <${decidedSlug}>: block in ${wfRelPath} (${r.applied_keys.join(", ")}; +${r.off_limits_added.length} off-limits)`);
|
|
143
|
+
mapperAppliedToWorkflow = true;
|
|
144
|
+
}
|
|
145
|
+
catch (err) {
|
|
146
|
+
warnings.push(`workflow.md slug-block update failed: ${String(err)}`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
else if (mapperOutput !== null && !wfWasSeeded) {
|
|
150
|
+
warnings.push(`mapper output NOT applied to ${wfRelPath} — kept existing; re-run with --force to overwrite, or merge globs manually`);
|
|
151
|
+
}
|
|
152
|
+
// ── Step 3: write project-overlay config.yaml ──────────────────────
|
|
153
|
+
header("Writing .harness/config.yaml");
|
|
154
|
+
const configPath = join(repoRoot, ".harness", "config.yaml");
|
|
155
|
+
mkdirSync(join(repoRoot, ".harness"), { recursive: true });
|
|
156
|
+
let mapperAppliedToConfig = false;
|
|
157
|
+
if (existsSync(configPath) && args.force !== true) {
|
|
158
|
+
warnings.push(`.harness/config.yaml already exists — kept existing (use --force to overwrite)`);
|
|
159
|
+
done(`= .harness/config.yaml (kept)`);
|
|
160
|
+
if (mapperOutput !== null) {
|
|
161
|
+
warnings.push(`mapper output NOT applied to .harness/config.yaml — kept existing; project_globs may be stale`);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
const config = buildProjectOverlay({
|
|
166
|
+
detection,
|
|
167
|
+
decidedSlug,
|
|
168
|
+
...(mapperOutput !== null ? { mapperOutput } : {}),
|
|
169
|
+
});
|
|
170
|
+
writeFileSync(configPath, stringifyYaml(config), "utf8");
|
|
171
|
+
done(`+ .harness/config.yaml`);
|
|
172
|
+
if (mapperOutput !== null)
|
|
173
|
+
mapperAppliedToConfig = true;
|
|
174
|
+
}
|
|
175
|
+
// ── Step 4: mirror ─────────────────────────────────────────────────
|
|
176
|
+
let mirrorPath = null;
|
|
177
|
+
if (args.skipMirror === true) {
|
|
178
|
+
info("\nmirror init skipped (--skip-mirror)");
|
|
179
|
+
}
|
|
180
|
+
else if (detection.origin_url === null) {
|
|
181
|
+
warnings.push("no git origin — mirror init skipped");
|
|
182
|
+
info("\nmirror init skipped (no git origin)");
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
header(`Mirror checkout → ~/.local/harness/repos/${decidedSlug}/`);
|
|
186
|
+
try {
|
|
187
|
+
const record = await ensureMirror({
|
|
188
|
+
projectName: decidedSlug,
|
|
189
|
+
originUrl: detection.origin_url,
|
|
190
|
+
userTreePath: repoRoot,
|
|
191
|
+
});
|
|
192
|
+
mirrorPath = record.mirrorPath;
|
|
193
|
+
done(`+ ${mirrorPath}`);
|
|
194
|
+
}
|
|
195
|
+
catch (err) {
|
|
196
|
+
warnings.push(`mirror init failed: ${String(err)}`);
|
|
197
|
+
info(`mirror init failed: ${String(err)}`);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
// ── Dialog 2: E2E setup ────────────────────────────────────────────
|
|
201
|
+
const e2eChoice = await squareIntoSquareHole({
|
|
202
|
+
mode,
|
|
203
|
+
prompt: "E2E heavy probes (browsers / sql / docker compose) — set up now?",
|
|
204
|
+
choices: [
|
|
205
|
+
{
|
|
206
|
+
id: "now",
|
|
207
|
+
label: "now",
|
|
208
|
+
description: "run setup:uat-browsers + setup:uat-sql --build-binding + setup:uat-docker",
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
id: "defer",
|
|
212
|
+
label: "defer (recommended for first adoption)",
|
|
213
|
+
description: "orchestrator prompts again on the first UAT need",
|
|
214
|
+
isDefault: true,
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
id: "skip",
|
|
218
|
+
label: "skip",
|
|
219
|
+
description: "code-class UAT becomes review-only; high-stakes refused dispatch",
|
|
220
|
+
},
|
|
221
|
+
],
|
|
222
|
+
auto: args.autoE2e ?? "defer",
|
|
223
|
+
});
|
|
224
|
+
recordE2eDecision({ repoRoot, e2eChoice });
|
|
225
|
+
if (e2eChoice === "now") {
|
|
226
|
+
header("E2E setup — running setup:uat-browsers + setup:uat-sql + setup:uat-docker");
|
|
227
|
+
const browsers = await runHarnessSetupScript("setup-uat-browsers");
|
|
228
|
+
if (!browsers.ok) {
|
|
229
|
+
warnings.push(`setup:uat-browsers exited ${browsers.exit_code} — re-run manually`);
|
|
230
|
+
}
|
|
231
|
+
const sql = await runHarnessSetupScript("setup-uat-sql", ["--build-binding"]);
|
|
232
|
+
if (!sql.ok) {
|
|
233
|
+
warnings.push(`setup:uat-sql exited ${sql.exit_code} — re-run manually`);
|
|
234
|
+
}
|
|
235
|
+
const docker = await runHarnessSetupScript("setup-uat-docker");
|
|
236
|
+
if (!docker.ok) {
|
|
237
|
+
warnings.push(`setup:uat-docker exited ${docker.exit_code} — re-run manually`);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
// ── Step 5: next-steps ─────────────────────────────────────────────
|
|
241
|
+
header("Done. Next steps");
|
|
242
|
+
info(` cd "${repoRoot}"`);
|
|
243
|
+
info(` pnpm dlx @devplusllc/harness watch --project ${decidedSlug} # daemon`);
|
|
244
|
+
if (envState.discord_token && envState.discord_guild) {
|
|
245
|
+
info(` pnpm dlx @devplusllc/harness run --project ${decidedSlug} --frontend discord`);
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
info(` # discord adapter not configured — using stub. Set DISCORD_BOT_TOKEN + DISCORD_GUILD_ID, then:`);
|
|
249
|
+
info(` pnpm dlx @devplusllc/harness run --project ${decidedSlug} --frontend stub`);
|
|
250
|
+
}
|
|
251
|
+
if (warnings.length > 0) {
|
|
252
|
+
info("\nWarnings:");
|
|
253
|
+
for (const w of warnings)
|
|
254
|
+
info(` ! ${w}`);
|
|
255
|
+
}
|
|
256
|
+
log.info({
|
|
257
|
+
repo_root: repoRoot,
|
|
258
|
+
slug: decidedSlug,
|
|
259
|
+
seeded: seed.written_files.length,
|
|
260
|
+
collisions: seed.collisions.length,
|
|
261
|
+
e2e: e2eChoice,
|
|
262
|
+
mapper_ran: mapperOutput !== null,
|
|
263
|
+
mapper_applied_to_workflow: mapperAppliedToWorkflow,
|
|
264
|
+
mapper_applied_to_config: mapperAppliedToConfig,
|
|
265
|
+
warnings: warnings.length,
|
|
266
|
+
}, "init complete");
|
|
267
|
+
return {
|
|
268
|
+
detection,
|
|
269
|
+
decided_slug: decidedSlug,
|
|
270
|
+
proceed: true,
|
|
271
|
+
seeded_files: seed.written_files,
|
|
272
|
+
collisions: seed.collisions,
|
|
273
|
+
config_path: ".harness/config.yaml",
|
|
274
|
+
mirror_path: mirrorPath,
|
|
275
|
+
e2e_setup: e2eChoice,
|
|
276
|
+
mapper_output: mapperOutput,
|
|
277
|
+
mapper_applied_to_workflow: mapperAppliedToWorkflow,
|
|
278
|
+
mapper_applied_to_config: mapperAppliedToConfig,
|
|
279
|
+
warnings,
|
|
280
|
+
};
|
|
281
|
+
function recordE2eDecision(a) {
|
|
282
|
+
const p = join(a.repoRoot, ".harness", "config.yaml");
|
|
283
|
+
if (!existsSync(p))
|
|
284
|
+
return;
|
|
285
|
+
const text = readFileSync(p, "utf8");
|
|
286
|
+
if (/^e2e_setup:/m.test(text)) {
|
|
287
|
+
const updated = text.replace(/^e2e_setup:.*$/m, `e2e_setup: ${a.e2eChoice}`);
|
|
288
|
+
writeFileSync(p, updated, "utf8");
|
|
289
|
+
}
|
|
290
|
+
else {
|
|
291
|
+
writeFileSync(p, text + (text.endsWith("\n") ? "" : "\n") + `e2e_setup: ${a.e2eChoice}\n`, "utf8");
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* For each missing prerequisite, prompt the operator to fix it. Returns
|
|
297
|
+
* the (possibly mutated) environment state.
|
|
298
|
+
*
|
|
299
|
+
* Order matters: claude → whisper → ollama → discord. Claude is the
|
|
300
|
+
* hardest blocker (no Tier-1 calls without it); discord is the most
|
|
301
|
+
* likely missing piece (operator hasn't pasted the bot token yet).
|
|
302
|
+
*/
|
|
303
|
+
async function runGuidedSetup(args) {
|
|
304
|
+
const env = { ...args.envState };
|
|
305
|
+
header("Guided setup — fixing missing prerequisites");
|
|
306
|
+
// ── claude CLI: can't auto. ─────────────────────────────────────────
|
|
307
|
+
if (!env.claude_auth) {
|
|
308
|
+
info("");
|
|
309
|
+
info("✗ claude CLI is missing or unauthenticated.");
|
|
310
|
+
info(" Install: https://docs.claude.com/claude-code");
|
|
311
|
+
info(" Then run: claude (one-time interactive auth)");
|
|
312
|
+
const ack = await yesNo({
|
|
313
|
+
mode: args.mode,
|
|
314
|
+
prompt: "Continue without claude? (Tier-1+ LLM calls will fail.)",
|
|
315
|
+
defaultYes: false,
|
|
316
|
+
});
|
|
317
|
+
if (!ack) {
|
|
318
|
+
throw new Error("init aborted — operator declined to continue without claude");
|
|
319
|
+
}
|
|
320
|
+
args.warnings.push("claude CLI not available — Tier-1+ LLM calls will fail");
|
|
321
|
+
}
|
|
322
|
+
else {
|
|
323
|
+
done("✓ claude CLI authenticated");
|
|
324
|
+
}
|
|
325
|
+
// ── whisper model. ──────────────────────────────────────────────────
|
|
326
|
+
if (!env.whisper_model) {
|
|
327
|
+
info("");
|
|
328
|
+
info("✗ whisper model not found at ~/.local/harness/models/.");
|
|
329
|
+
const action = await yesNo({
|
|
330
|
+
mode: args.mode,
|
|
331
|
+
prompt: "Download whisper model now (~800MB, ~2 min on fast wifi)?",
|
|
332
|
+
defaultYes: true,
|
|
333
|
+
});
|
|
334
|
+
if (action) {
|
|
335
|
+
const r = await downloadWhisperModel();
|
|
336
|
+
if (r.ok) {
|
|
337
|
+
env.whisper_model = true;
|
|
338
|
+
done("✓ whisper model downloaded");
|
|
339
|
+
}
|
|
340
|
+
else {
|
|
341
|
+
args.warnings.push(`whisper download failed (${r.exit_code}) — re-run manually`);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
else {
|
|
345
|
+
args.warnings.push("whisper model not present — voice ingress disabled");
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
else {
|
|
349
|
+
done("✓ whisper model present");
|
|
350
|
+
}
|
|
351
|
+
// ── ollama service. ─────────────────────────────────────────────────
|
|
352
|
+
if (!env.ollama_running) {
|
|
353
|
+
info("");
|
|
354
|
+
info("✗ ollama is not reachable on $OLLAMA_HOST (default http://localhost:11434).");
|
|
355
|
+
const action = await squareIntoSquareHole({
|
|
356
|
+
mode: args.mode,
|
|
357
|
+
prompt: "Set up Ollama (Tier-0 classifier)?",
|
|
358
|
+
choices: [
|
|
359
|
+
{ id: "install", label: "install via brew + pull llama3.2:3b", isDefault: true },
|
|
360
|
+
{ id: "skip", label: "skip — Tier-0 falls back to regex" },
|
|
361
|
+
],
|
|
362
|
+
auto: "skip",
|
|
363
|
+
});
|
|
364
|
+
if (action === "install") {
|
|
365
|
+
const installR = await offerInstallOllama();
|
|
366
|
+
if (installR.ok)
|
|
367
|
+
done("✓ ollama installed");
|
|
368
|
+
else
|
|
369
|
+
args.warnings.push(`brew install ollama failed (${installR.exit_code})`);
|
|
370
|
+
info(" starting ollama service in background — run `brew services start ollama`");
|
|
371
|
+
info(" then: ollama pull llama3.2:3b");
|
|
372
|
+
const pullR = await pullOllamaModel("llama3.2:3b");
|
|
373
|
+
if (pullR.ok) {
|
|
374
|
+
env.ollama_running = true;
|
|
375
|
+
done("✓ llama3.2:3b pulled");
|
|
376
|
+
}
|
|
377
|
+
else {
|
|
378
|
+
args.warnings.push(`ollama pull failed (${pullR.exit_code}) — start service then re-run`);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
else {
|
|
382
|
+
args.warnings.push("ollama skipped — Tier-0 uses regex fallback");
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
else {
|
|
386
|
+
done("✓ ollama reachable");
|
|
387
|
+
}
|
|
388
|
+
// ── discord token + guild. ──────────────────────────────────────────
|
|
389
|
+
const discordMissing = !env.discord_token || !env.discord_guild;
|
|
390
|
+
if (discordMissing) {
|
|
391
|
+
info("");
|
|
392
|
+
info("✗ Discord adapter not configured (DISCORD_BOT_TOKEN / DISCORD_GUILD_ID missing).");
|
|
393
|
+
const action = await squareIntoSquareHole({
|
|
394
|
+
mode: args.mode,
|
|
395
|
+
prompt: "Enter Discord bot credentials now?",
|
|
396
|
+
choices: [
|
|
397
|
+
{
|
|
398
|
+
id: "enter",
|
|
399
|
+
label: "enter token + guild now",
|
|
400
|
+
description: "writes to ~/.local/harness/.env (mode 0600)",
|
|
401
|
+
isDefault: true,
|
|
402
|
+
},
|
|
403
|
+
{
|
|
404
|
+
id: "skip",
|
|
405
|
+
label: "skip — use stub adapter for now",
|
|
406
|
+
description: "you can `harness init` again later to add credentials",
|
|
407
|
+
},
|
|
408
|
+
],
|
|
409
|
+
auto: "skip",
|
|
410
|
+
});
|
|
411
|
+
if (action === "enter") {
|
|
412
|
+
const updates = {};
|
|
413
|
+
if (!env.discord_token) {
|
|
414
|
+
const token = await secretInput({
|
|
415
|
+
mode: args.mode,
|
|
416
|
+
prompt: "DISCORD_BOT_TOKEN (Bot tab → Reset Token, paste hidden):",
|
|
417
|
+
});
|
|
418
|
+
if (token.length > 0) {
|
|
419
|
+
updates["DISCORD_BOT_TOKEN"] = token;
|
|
420
|
+
env.discord_token = true;
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
if (!env.discord_guild) {
|
|
424
|
+
const guild = await freeTextWithDefault({
|
|
425
|
+
mode: args.mode,
|
|
426
|
+
prompt: "DISCORD_GUILD_ID (right-click server → Copy Server ID):",
|
|
427
|
+
defaultValue: "",
|
|
428
|
+
});
|
|
429
|
+
if (guild.trim().length > 0) {
|
|
430
|
+
updates["DISCORD_GUILD_ID"] = guild.trim();
|
|
431
|
+
env.discord_guild = true;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
if (Object.keys(updates).length > 0) {
|
|
435
|
+
const path = upsertHarnessEnv(updates);
|
|
436
|
+
done(`✓ wrote ${Object.keys(updates).join(" + ")} → ${path}`);
|
|
437
|
+
}
|
|
438
|
+
else {
|
|
439
|
+
args.warnings.push("discord credentials skipped — adapter will fall back to stub");
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
else {
|
|
443
|
+
args.warnings.push("discord credentials skipped — adapter falls back to stub");
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
else {
|
|
447
|
+
done("✓ Discord credentials present");
|
|
448
|
+
}
|
|
449
|
+
return env;
|
|
450
|
+
}
|
|
451
|
+
function buildProjectOverlay(args) {
|
|
452
|
+
const detected_sensor_commands = args.detection.proposed_sensors.map((s) => ({
|
|
453
|
+
id: s.id,
|
|
454
|
+
command: s.command,
|
|
455
|
+
args: s.args,
|
|
456
|
+
applies_to: s.applies_to,
|
|
457
|
+
reason: s.reason,
|
|
458
|
+
}));
|
|
459
|
+
const m = args.mapperOutput;
|
|
460
|
+
const offLimits = [...DEFAULT_OFF_LIMITS];
|
|
461
|
+
if (m !== undefined) {
|
|
462
|
+
for (const x of m.off_limits_globs) {
|
|
463
|
+
if (!offLimits.includes(x))
|
|
464
|
+
offLimits.push(x);
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
const overlay = {
|
|
468
|
+
version: 1,
|
|
469
|
+
slug: args.decidedSlug,
|
|
470
|
+
origin_url: args.detection.origin_url,
|
|
471
|
+
stack_signatures: args.detection.stack_signatures.map((s) => s.kind),
|
|
472
|
+
hook_capability: args.detection.hook_capability,
|
|
473
|
+
start_command: args.detection.start_command,
|
|
474
|
+
detected_sensor_commands,
|
|
475
|
+
off_limits: offLimits,
|
|
476
|
+
high_stakes_globs: m?.high_stakes_globs ?? [],
|
|
477
|
+
project_globs: {
|
|
478
|
+
route_handler_globs: m?.route_handler_globs ?? [],
|
|
479
|
+
dto_globs: m?.dto_globs ?? [],
|
|
480
|
+
generator_source_globs: m?.generator_source_globs ?? [],
|
|
481
|
+
high_stakes_globs: m?.high_stakes_globs ?? [],
|
|
482
|
+
},
|
|
483
|
+
};
|
|
484
|
+
if (m !== undefined) {
|
|
485
|
+
overlay["pilot_module"] = m.pilot_module;
|
|
486
|
+
overlay["domain_summary"] = m.domain_summary;
|
|
487
|
+
overlay["key_modules"] = m.key_modules;
|
|
488
|
+
overlay["mapper_proposed_sensors"] = m.proposed_sensors;
|
|
489
|
+
if (m.notes.trim().length > 0)
|
|
490
|
+
overlay["mapper_notes"] = m.notes;
|
|
491
|
+
}
|
|
492
|
+
return overlay;
|
|
493
|
+
}
|
|
494
|
+
async function maybeRunMapper(args) {
|
|
495
|
+
if (args.mockMapperOutput !== undefined) {
|
|
496
|
+
info("\n── Init mapper — using injected mockMapperOutput (smoke / scripted adoption)");
|
|
497
|
+
return args.mockMapperOutput;
|
|
498
|
+
}
|
|
499
|
+
if (args.skipMapper) {
|
|
500
|
+
info("\n── Init mapper skipped (--skip-mapper); project_globs left empty");
|
|
501
|
+
args.warnings.push("mapper skipped via --skip-mapper — project_globs left empty");
|
|
502
|
+
return null;
|
|
503
|
+
}
|
|
504
|
+
if (args.mode === "auto") {
|
|
505
|
+
info("\n── Init mapper skipped (--no-prompt mode; pass mockMapperOutput to test the apply path)");
|
|
506
|
+
return null;
|
|
507
|
+
}
|
|
508
|
+
if (!args.envClaudeAuth) {
|
|
509
|
+
args.warnings.push("mapper skipped — claude CLI not available; project_globs left empty");
|
|
510
|
+
info("\n── Init mapper skipped — claude CLI not available; re-run init after `claude` auth to fill project_globs");
|
|
511
|
+
return null;
|
|
512
|
+
}
|
|
513
|
+
header("Init mapper (Tier 2 / Sonnet) — proposing pilot_module + project_globs");
|
|
514
|
+
info(" Walking repo (gitignore-aware, depth ≤ 5, file cap 3000)...");
|
|
515
|
+
const summary = buildRepoSummary({ repoRoot: args.repoRoot });
|
|
516
|
+
info(` ${summary.total_files} files, ${summary.total_dirs} dirs, ${summary.package_manifests.length} manifests, ${summary.framework_signals.length} framework signals`);
|
|
517
|
+
if (summary.truncated_at_file_cap)
|
|
518
|
+
info(" (truncated at file cap — pilot scope will be conservative)");
|
|
519
|
+
if (summary.truncated_at_depth_cap)
|
|
520
|
+
info(" (truncated at depth cap)");
|
|
521
|
+
const dispatch = await squareIntoSquareHole({
|
|
522
|
+
mode: args.mode,
|
|
523
|
+
prompt: "Dispatch mapper now (~$1-3 one-time, fills route_handler_globs / dto_globs / etc.)?",
|
|
524
|
+
choices: [
|
|
525
|
+
{ id: "go", label: "yes — dispatch Sonnet", isDefault: true },
|
|
526
|
+
{ id: "skip", label: "skip — keep globs empty (you can re-run init later)" },
|
|
527
|
+
],
|
|
528
|
+
auto: "skip",
|
|
529
|
+
});
|
|
530
|
+
if (dispatch === "skip") {
|
|
531
|
+
args.warnings.push("mapper dispatch declined by operator — project_globs left empty");
|
|
532
|
+
return null;
|
|
533
|
+
}
|
|
534
|
+
let mapperResult;
|
|
535
|
+
try {
|
|
536
|
+
info(" Dispatching... (typically 30-90s)");
|
|
537
|
+
mapperResult = await runMapper({ detection: args.detection, summary });
|
|
538
|
+
}
|
|
539
|
+
catch (err) {
|
|
540
|
+
args.warnings.push(`mapper dispatch failed: ${String(err)}`);
|
|
541
|
+
info(` ✗ mapper failed: ${String(err)}`);
|
|
542
|
+
return null;
|
|
543
|
+
}
|
|
544
|
+
printMapperProposal(mapperResult);
|
|
545
|
+
const choice = await squareIntoSquareHole({
|
|
546
|
+
mode: args.mode,
|
|
547
|
+
prompt: "Apply mapper proposal?",
|
|
548
|
+
choices: [
|
|
549
|
+
{ id: "apply", label: "apply as-is", isDefault: true },
|
|
550
|
+
{
|
|
551
|
+
id: "edit",
|
|
552
|
+
label: "edit YAML before applying",
|
|
553
|
+
description: `opens ${process.env["EDITOR"] ?? "vi"} on the proposal`,
|
|
554
|
+
},
|
|
555
|
+
{
|
|
556
|
+
id: "skip",
|
|
557
|
+
label: "skip — keep globs empty (re-run init later to retry)",
|
|
558
|
+
},
|
|
559
|
+
],
|
|
560
|
+
auto: "apply",
|
|
561
|
+
});
|
|
562
|
+
if (choice === "skip") {
|
|
563
|
+
args.warnings.push("mapper proposal declined at confirm — project_globs left empty");
|
|
564
|
+
return null;
|
|
565
|
+
}
|
|
566
|
+
if (choice === "edit") {
|
|
567
|
+
const initialYaml = stringifyYaml(mapperResult.output);
|
|
568
|
+
const edited = await editYaml({
|
|
569
|
+
mode: args.mode,
|
|
570
|
+
prompt: "Edit YAML proposal (save + exit to apply, leave empty to abort)",
|
|
571
|
+
initial: initialYaml,
|
|
572
|
+
});
|
|
573
|
+
if (edited.trim().length === 0) {
|
|
574
|
+
args.warnings.push("mapper proposal aborted at edit (empty input) — project_globs left empty");
|
|
575
|
+
return null;
|
|
576
|
+
}
|
|
577
|
+
let parsed;
|
|
578
|
+
try {
|
|
579
|
+
parsed = parseYaml(edited);
|
|
580
|
+
}
|
|
581
|
+
catch (err) {
|
|
582
|
+
args.warnings.push(`mapper proposal edit returned invalid YAML: ${String(err)}`);
|
|
583
|
+
return null;
|
|
584
|
+
}
|
|
585
|
+
try {
|
|
586
|
+
return validateMapperOutput(parsed);
|
|
587
|
+
}
|
|
588
|
+
catch (err) {
|
|
589
|
+
args.warnings.push(`edited mapper proposal failed shape check: ${String(err)}`);
|
|
590
|
+
return null;
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
return mapperResult.output;
|
|
594
|
+
}
|
|
595
|
+
function printMapperProposal(r) {
|
|
596
|
+
const o = r.output;
|
|
597
|
+
info("");
|
|
598
|
+
info(`Mapper proposal (${(r.duration_ms / 1000).toFixed(1)}s, in=${r.usage?.input_tokens ?? "?"} out=${r.usage?.output_tokens ?? "?"} tokens):`);
|
|
599
|
+
info(` domain: ${truncateOneLine(o.domain_summary, 90)}`);
|
|
600
|
+
info(` pilot_module: ${o.pilot_module}`);
|
|
601
|
+
info(` key_modules (${o.key_modules.length}):`);
|
|
602
|
+
for (const km of o.key_modules) {
|
|
603
|
+
info(` - ${km.name} (${km.path}) — ${truncateOneLine(km.purpose, 70)}`);
|
|
604
|
+
}
|
|
605
|
+
printGlobs(`route_handler_globs (${o.route_handler_globs.length})`, o.route_handler_globs);
|
|
606
|
+
printGlobs(`dto_globs (${o.dto_globs.length})`, o.dto_globs);
|
|
607
|
+
printGlobs(`generator_source_globs (${o.generator_source_globs.length})`, o.generator_source_globs);
|
|
608
|
+
printGlobs(`high_stakes_globs (${o.high_stakes_globs.length})`, o.high_stakes_globs);
|
|
609
|
+
printGlobs(`off_limits_globs (${o.off_limits_globs.length})`, o.off_limits_globs);
|
|
610
|
+
info(` proposed_sensors (${o.proposed_sensors.length}):`);
|
|
611
|
+
for (const ps of o.proposed_sensors) {
|
|
612
|
+
info(` - ${ps.id} — ${truncateOneLine(ps.description, 80)} [${ps.applies_to_globs.join(", ")}]`);
|
|
613
|
+
}
|
|
614
|
+
if (o.notes.trim().length > 0)
|
|
615
|
+
info(` notes: ${truncateOneLine(o.notes, 200)}`);
|
|
616
|
+
}
|
|
617
|
+
function printGlobs(label, globs) {
|
|
618
|
+
info(` ${label}:`);
|
|
619
|
+
if (globs.length === 0) {
|
|
620
|
+
info(` (none)`);
|
|
621
|
+
return;
|
|
622
|
+
}
|
|
623
|
+
for (const g of globs)
|
|
624
|
+
info(` - ${g}`);
|
|
625
|
+
}
|
|
626
|
+
function truncateOneLine(s, max) {
|
|
627
|
+
const collapsed = s.replace(/\s+/g, " ").trim();
|
|
628
|
+
return collapsed.length > max ? `${collapsed.slice(0, max - 1)}…` : collapsed;
|
|
629
|
+
}
|
|
630
|
+
function printSummary(d, decidedSlug) {
|
|
631
|
+
info("");
|
|
632
|
+
info("DETECTED:");
|
|
633
|
+
info(` project_slug: ${decidedSlug}${decidedSlug === d.project_slug ? "" : " (override)"}`);
|
|
634
|
+
info(` origin_url: ${d.origin_url ?? "(none — local-only repo)"}`);
|
|
635
|
+
info(` stack: ${d.stack_signatures.map((s) => s.kind).join(", ") || "unknown"}`);
|
|
636
|
+
if (d.start_command !== null) {
|
|
637
|
+
info(` start_command: ${[d.start_command.command, ...d.start_command.args].join(" ")} (${d.start_command.reason})`);
|
|
638
|
+
}
|
|
639
|
+
else {
|
|
640
|
+
info(` start_command: (none detected — UAT-on-phone needs manual config)`);
|
|
641
|
+
}
|
|
642
|
+
info(` hook_capability: ${d.hook_capability}`);
|
|
643
|
+
if (d.proposed_sensors.length > 0) {
|
|
644
|
+
info(` proposed sensors:`);
|
|
645
|
+
for (const s of d.proposed_sensors) {
|
|
646
|
+
info(` - ${s.id} (${s.command} ${s.args.join(" ")}) — ${s.reason}`);
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
else {
|
|
650
|
+
info(` proposed sensors: (none — generic harness layer A/B/C/D still apply)`);
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
function printAdvisoryWarnings(d, warnings) {
|
|
654
|
+
info("");
|
|
655
|
+
info("ENVIRONMENT:");
|
|
656
|
+
const e = d.environment;
|
|
657
|
+
info(` claude CLI: ${e.claude_auth ? "ok" : "missing — install + authenticate Claude Code"}`);
|
|
658
|
+
if (!e.claude_auth)
|
|
659
|
+
warnings.push("claude CLI not available");
|
|
660
|
+
info(` whisper model: ${e.whisper_model ? "ok" : "missing — voice ingress disabled"}`);
|
|
661
|
+
if (!e.whisper_model)
|
|
662
|
+
warnings.push("whisper model not at ~/.local/harness/models/ggml-large-v3-turbo-q5_0.bin — voice ingress disabled");
|
|
663
|
+
info(` ollama: ${e.ollama_running ? "ok" : "not reachable — Tier-0 falls back to regex classifier"}`);
|
|
664
|
+
if (!e.ollama_running)
|
|
665
|
+
warnings.push("ollama not reachable on $OLLAMA_HOST — Tier-0 falls back to regex");
|
|
666
|
+
info(` discord token: ${e.discord_token ? "ok" : "missing — discord adapter unusable"}`);
|
|
667
|
+
if (!e.discord_token)
|
|
668
|
+
warnings.push("DISCORD_BOT_TOKEN not set in env");
|
|
669
|
+
info(` discord guild: ${e.discord_guild ? "ok" : "missing — discord adapter unusable"}`);
|
|
670
|
+
if (!e.discord_guild)
|
|
671
|
+
warnings.push("DISCORD_GUILD_ID not set in env");
|
|
672
|
+
}
|
|
673
|
+
//# sourceMappingURL=init.js.map
|