@isaacriehm/cairn-core 0.19.1 → 0.22.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/dist/.tsbuildinfo +1 -1
- package/dist/align-undo/log.js +3 -2
- package/dist/align-undo/log.js.map +1 -1
- package/dist/attention/index.d.ts +0 -2
- package/dist/attention/index.js +0 -2
- package/dist/attention/index.js.map +1 -1
- package/dist/attention/restore.d.ts +1 -1
- package/dist/attention/restore.js +1 -1
- package/dist/attention/source-strip.d.ts +2 -2
- package/dist/attention/source-strip.js +4 -3
- package/dist/attention/source-strip.js.map +1 -1
- package/dist/components/audit.d.ts +7 -1
- package/dist/components/audit.js +144 -72
- package/dist/components/audit.js.map +1 -1
- package/dist/components/emit.js +33 -6
- package/dist/components/emit.js.map +1 -1
- package/dist/components/freshness.d.ts +51 -0
- package/dist/components/freshness.js +121 -0
- package/dist/components/freshness.js.map +1 -0
- package/dist/components/index.d.ts +4 -0
- package/dist/components/index.js +2 -0
- package/dist/components/index.js.map +1 -1
- package/dist/components/reconfirm.d.ts +64 -0
- package/dist/components/reconfirm.js +204 -0
- package/dist/components/reconfirm.js.map +1 -0
- package/dist/context/handoff-builder.js +3 -3
- package/dist/context/handoff-builder.js.map +1 -1
- package/dist/context/task-summary.js +2 -2
- package/dist/context/task-summary.js.map +1 -1
- package/dist/doctor/index.js +102 -9
- package/dist/doctor/index.js.map +1 -1
- package/dist/events/paths.js +2 -2
- package/dist/events/paths.js.map +1 -1
- package/dist/fix-align/sentinel.js +2 -3
- package/dist/fix-align/sentinel.js.map +1 -1
- package/dist/gc/attested-commits.js +2 -2
- package/dist/gc/attested-commits.js.map +1 -1
- package/dist/gc/canary.js +2 -3
- package/dist/gc/canary.js.map +1 -1
- package/dist/gc/citation-integrity.d.ts +4 -5
- package/dist/gc/citation-integrity.js +11 -33
- package/dist/gc/citation-integrity.js.map +1 -1
- package/dist/gc/classify.js +3 -16
- package/dist/gc/classify.js.map +1 -1
- package/dist/gc/completion-integrity.js +4 -3
- package/dist/gc/completion-integrity.js.map +1 -1
- package/dist/gc/entity-orphan.js +66 -12
- package/dist/gc/entity-orphan.js.map +1 -1
- package/dist/gc/ghost-anchor.d.ts +57 -0
- package/dist/gc/ghost-anchor.js +171 -0
- package/dist/gc/ghost-anchor.js.map +1 -0
- package/dist/gc/index.d.ts +2 -0
- package/dist/gc/index.js +1 -0
- package/dist/gc/index.js.map +1 -1
- package/dist/gc/sweep.d.ts +1 -1
- package/dist/gc/sweep.js +13 -1
- package/dist/gc/sweep.js.map +1 -1
- package/dist/gc/types.d.ts +1 -1
- package/dist/hooks/bypass-detection.js +3 -2
- package/dist/hooks/bypass-detection.js.map +1 -1
- package/dist/hooks/defer.js +3 -2
- package/dist/hooks/defer.js.map +1 -1
- package/dist/hooks/ghost-backup.d.ts +37 -0
- package/dist/hooks/ghost-backup.js +82 -0
- package/dist/hooks/ghost-backup.js.map +1 -0
- package/dist/hooks/post-tool-use/allowlist-reader.js +2 -2
- package/dist/hooks/post-tool-use/allowlist-reader.js.map +1 -1
- package/dist/hooks/post-tool-use/ask-user-blocked.d.ts +1 -2
- package/dist/hooks/post-tool-use/ask-user-blocked.js +3 -4
- package/dist/hooks/post-tool-use/ask-user-blocked.js.map +1 -1
- package/dist/hooks/post-tool-use/citation-scanner.d.ts +9 -7
- package/dist/hooks/post-tool-use/citation-scanner.js +9 -14
- package/dist/hooks/post-tool-use/citation-scanner.js.map +1 -1
- package/dist/hooks/post-tool-use/legend-builder.d.ts +2 -2
- package/dist/hooks/post-tool-use/legend-builder.js +1 -19
- package/dist/hooks/post-tool-use/legend-builder.js.map +1 -1
- package/dist/hooks/post-tool-use/post-write.js +18 -1
- package/dist/hooks/post-tool-use/post-write.js.map +1 -1
- package/dist/hooks/post-tool-use/read-enricher.d.ts +2 -2
- package/dist/hooks/post-tool-use/read-enricher.js +4 -6
- package/dist/hooks/post-tool-use/read-enricher.js.map +1 -1
- package/dist/hooks/post-tool-use/sot-align.js +29 -3
- package/dist/hooks/post-tool-use/sot-align.js.map +1 -1
- package/dist/hooks/post-tool-use/write-guardian.d.ts +1 -5
- package/dist/hooks/post-tool-use/write-guardian.js +25 -18
- package/dist/hooks/post-tool-use/write-guardian.js.map +1 -1
- package/dist/hooks/runners/context-threshold.js +3 -3
- package/dist/hooks/runners/context-threshold.js.map +1 -1
- package/dist/hooks/runners/payload.js +2 -1
- package/dist/hooks/runners/payload.js.map +1 -1
- package/dist/hooks/runners/phase-ready-surface.js +3 -2
- package/dist/hooks/runners/phase-ready-surface.js.map +1 -1
- package/dist/hooks/runners/session-start.js +103 -4
- package/dist/hooks/runners/session-start.js.map +1 -1
- package/dist/hooks/runners/stop.js +46 -42
- package/dist/hooks/runners/stop.js.map +1 -1
- package/dist/hooks/runners/user-prompt-submit.d.ts +2 -2
- package/dist/hooks/runners/user-prompt-submit.js +4 -9
- package/dist/hooks/runners/user-prompt-submit.js.map +1 -1
- package/dist/hooks/seed-attested.js +3 -2
- package/dist/hooks/seed-attested.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/init/baseline-audit.js +3 -3
- package/dist/init/baseline-audit.js.map +1 -1
- package/dist/init/claude-rule.js +13 -1
- package/dist/init/claude-rule.js.map +1 -1
- package/dist/init/curator/corpus.d.ts +1 -0
- package/dist/init/curator/corpus.js +6 -2
- package/dist/init/curator/corpus.js.map +1 -1
- package/dist/init/curator/emit.js +2 -3
- package/dist/init/curator/emit.js.map +1 -1
- package/dist/init/detect-components.d.ts +3 -2
- package/dist/init/detect-components.js +33 -15
- package/dist/init/detect-components.js.map +1 -1
- package/dist/init/detect.d.ts +1 -5
- package/dist/init/detect.js +157 -143
- package/dist/init/detect.js.map +1 -1
- package/dist/init/eta-calibration.js +2 -2
- package/dist/init/eta-calibration.js.map +1 -1
- package/dist/init/glob-inference.js +24 -0
- package/dist/init/glob-inference.js.map +1 -1
- package/dist/init/index.d.ts +4 -4
- package/dist/init/index.js +2 -2
- package/dist/init/index.js.map +1 -1
- package/dist/init/init.d.ts +8 -0
- package/dist/init/init.js +16 -20
- package/dist/init/init.js.map +1 -1
- package/dist/init/mapper-merge.d.ts +1 -4
- package/dist/init/mapper-merge.js +4 -17
- package/dist/init/mapper-merge.js.map +1 -1
- package/dist/init/mapper-parallel.js +1 -1
- package/dist/init/mapper-parallel.js.map +1 -1
- package/dist/init/mapper-prompts.d.ts +1 -23
- package/dist/init/mapper-prompts.js +1 -25
- package/dist/init/mapper-prompts.js.map +1 -1
- package/dist/init/mapper.d.ts +0 -6
- package/dist/init/mapper.js +2 -5
- package/dist/init/mapper.js.map +1 -1
- package/dist/init/module-slicer.js +3 -24
- package/dist/init/module-slicer.js.map +1 -1
- package/dist/init/multi-dev/install.js +24 -0
- package/dist/init/multi-dev/install.js.map +1 -1
- package/dist/init/overlay.js +5 -16
- package/dist/init/overlay.js.map +1 -1
- package/dist/init/phases/11-baseline.js +1 -1
- package/dist/init/phases/11-baseline.js.map +1 -1
- package/dist/init/phases/4-seed.js +7 -5
- package/dist/init/phases/4-seed.js.map +1 -1
- package/dist/init/phases/9a-walker.js +4 -0
- package/dist/init/phases/9a-walker.js.map +1 -1
- package/dist/init/phases/9b-curate.d.ts +1 -0
- package/dist/init/phases/9b-curate.js +6 -2
- package/dist/init/phases/9b-curate.js.map +1 -1
- package/dist/init/phases/9d-comp-walk.js +3 -3
- package/dist/init/phases/9d-comp-walk.js.map +1 -1
- package/dist/init/phases/9e-comp-annotate.js +63 -3
- package/dist/init/phases/9e-comp-annotate.js.map +1 -1
- package/dist/init/phases/index.d.ts +0 -1
- package/dist/init/phases/index.js +0 -1
- package/dist/init/phases/index.js.map +1 -1
- package/dist/init/phases/mapper-output-io.d.ts +1 -1
- package/dist/init/phases/mapper-output-io.js +3 -2
- package/dist/init/phases/mapper-output-io.js.map +1 -1
- package/dist/init/phases/state-io.d.ts +1 -1
- package/dist/init/phases/state-io.js +3 -2
- package/dist/init/phases/state-io.js.map +1 -1
- package/dist/init/phases/types.d.ts +20 -8
- package/dist/init/phases/types.js +0 -1
- package/dist/init/phases/types.js.map +1 -1
- package/dist/init/progress.d.ts +1 -0
- package/dist/init/progress.js +3 -1
- package/dist/init/progress.js.map +1 -1
- package/dist/init/rules-merge/ingest.js +3 -3
- package/dist/init/rules-merge/ingest.js.map +1 -1
- package/dist/init/seed.js +54 -5
- package/dist/init/seed.js.map +1 -1
- package/dist/init/source-comments/strip-replace.d.ts +1 -2
- package/dist/init/source-comments/strip-replace.js +19 -3
- package/dist/init/source-comments/strip-replace.js.map +1 -1
- package/dist/init/source-comments/walker.js +8 -79
- package/dist/init/source-comments/walker.js.map +1 -1
- package/dist/init/types.d.ts +8 -16
- package/dist/init/walker.d.ts +1 -1
- package/dist/init/walker.js +1 -1
- package/dist/join/index.d.ts +9 -0
- package/dist/join/index.js +82 -25
- package/dist/join/index.js.map +1 -1
- package/dist/lock.js +4 -3
- package/dist/lock.js.map +1 -1
- package/dist/mcp/bootstrap-guard.js +10 -1
- package/dist/mcp/bootstrap-guard.js.map +1 -1
- package/dist/mcp/schemas.d.ts +26 -4
- package/dist/mcp/schemas.js +23 -1
- package/dist/mcp/schemas.js.map +1 -1
- package/dist/mcp/serve.js +9 -0
- package/dist/mcp/serve.js.map +1 -1
- package/dist/mcp/server.js +3 -3
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/telemetry.js +4 -3
- package/dist/mcp/telemetry.js.map +1 -1
- package/dist/mcp/tools/component-reconfirm.d.ts +7 -0
- package/dist/mcp/tools/component-reconfirm.js +39 -0
- package/dist/mcp/tools/component-reconfirm.js.map +1 -0
- package/dist/mcp/tools/component-register.d.ts +15 -0
- package/dist/mcp/tools/component-register.js +65 -0
- package/dist/mcp/tools/component-register.js.map +1 -0
- package/dist/mcp/tools/decision-get.js +2 -2
- package/dist/mcp/tools/decision-get.js.map +1 -1
- package/dist/mcp/tools/index.js +5 -6
- package/dist/mcp/tools/index.js.map +1 -1
- package/dist/mcp/tools/init-phases.d.ts +2 -0
- package/dist/mcp/tools/init-phases.js +21 -5
- package/dist/mcp/tools/init-phases.js.map +1 -1
- package/dist/mcp/tools/mission-advance.d.ts +3 -4
- package/dist/mcp/tools/mission-advance.js +15 -19
- package/dist/mcp/tools/mission-advance.js.map +1 -1
- package/dist/mcp/tools/mission-resume.js +3 -3
- package/dist/mcp/tools/mission-resume.js.map +1 -1
- package/dist/mcp/tools/record-decision.js +17 -9
- package/dist/mcp/tools/record-decision.js.map +1 -1
- package/dist/mcp/tools/resolve-attention.js +70 -34
- package/dist/mcp/tools/resolve-attention.js.map +1 -1
- package/dist/mcp/tools/resume.js +3 -2
- package/dist/mcp/tools/resume.js.map +1 -1
- package/dist/mcp/tools/search.js +2 -2
- package/dist/mcp/tools/search.js.map +1 -1
- package/dist/mcp/tools/task-complete.js +2 -3
- package/dist/mcp/tools/task-complete.js.map +1 -1
- package/dist/mcp/tools/task-create.js +2 -2
- package/dist/mcp/tools/task-create.js.map +1 -1
- package/dist/migrate/config-io.d.ts +24 -0
- package/dist/migrate/config-io.js +73 -0
- package/dist/migrate/config-io.js.map +1 -0
- package/dist/migrate/gitignore.d.ts +28 -0
- package/dist/migrate/gitignore.js +82 -0
- package/dist/migrate/gitignore.js.map +1 -0
- package/dist/migrate/index.d.ts +6 -0
- package/dist/migrate/index.js +6 -0
- package/dist/migrate/index.js.map +1 -0
- package/dist/migrate/migrations/0001-drop-dead-config-fields.d.ts +12 -0
- package/dist/migrate/migrations/0001-drop-dead-config-fields.js +39 -0
- package/dist/migrate/migrations/0001-drop-dead-config-fields.js.map +1 -0
- package/dist/migrate/migrations/0002-backfill-gitignore.d.ts +14 -0
- package/dist/migrate/migrations/0002-backfill-gitignore.js +40 -0
- package/dist/migrate/migrations/0002-backfill-gitignore.js.map +1 -0
- package/dist/migrate/registry.d.ts +9 -0
- package/dist/migrate/registry.js +11 -0
- package/dist/migrate/registry.js.map +1 -0
- package/dist/migrate/runner.d.ts +45 -0
- package/dist/migrate/runner.js +177 -0
- package/dist/migrate/runner.js.map +1 -0
- package/dist/migrate/semver.d.ts +11 -0
- package/dist/migrate/semver.js +35 -0
- package/dist/migrate/semver.js.map +1 -0
- package/dist/migrate/types.d.ts +47 -0
- package/dist/migrate/types.js +13 -0
- package/dist/migrate/types.js.map +1 -0
- package/dist/missions/task-link.js +7 -8
- package/dist/missions/task-link.js.map +1 -1
- package/dist/paths/index.d.ts +12 -1
- package/dist/paths/index.js +17 -3
- package/dist/paths/index.js.map +1 -1
- package/dist/sensors/catalog.js +6 -11
- package/dist/sensors/catalog.js.map +1 -1
- package/dist/sensors/decisions.js +55 -19
- package/dist/sensors/decisions.js.map +1 -1
- package/dist/sensors/diff.d.ts +12 -0
- package/dist/sensors/diff.js +103 -0
- package/dist/sensors/diff.js.map +1 -1
- package/dist/sensors/index.d.ts +4 -5
- package/dist/sensors/index.js +2 -3
- package/dist/sensors/index.js.map +1 -1
- package/dist/sensors/runner.d.ts +34 -37
- package/dist/sensors/runner.js +63 -53
- package/dist/sensors/runner.js.map +1 -1
- package/dist/sensors/stub-catalog.d.ts +6 -3
- package/dist/sensors/stub-catalog.js +7 -19
- package/dist/sensors/stub-catalog.js.map +1 -1
- package/dist/sensors/types.d.ts +11 -55
- package/dist/sensors/types.js +4 -8
- package/dist/sensors/types.js.map +1 -1
- package/dist/session-start/build.js +36 -21
- package/dist/session-start/build.js.map +1 -1
- package/dist/session-start/templates.d.ts +1 -1
- package/dist/session-start/templates.js +1 -1
- package/dist/status-line/event-queue.js +2 -1
- package/dist/status-line/event-queue.js.map +1 -1
- package/dist/status-line/reader.js +5 -5
- package/dist/status-line/reader.js.map +1 -1
- package/dist/status-line/writer.js +2 -1
- package/dist/status-line/writer.js.map +1 -1
- package/dist/tasks/lifecycle.d.ts +3 -4
- package/dist/tasks/lifecycle.js +19 -21
- package/dist/tasks/lifecycle.js.map +1 -1
- package/dist/trace/index.js +2 -2
- package/dist/trace/index.js.map +1 -1
- package/dist/update-check.d.ts +28 -0
- package/dist/update-check.js +137 -0
- package/dist/update-check.js.map +1 -0
- package/package.json +2 -2
- package/templates/.cairn/git-hooks/commit-msg +33 -5
- package/templates/.cairn/git-hooks/post-commit +13 -3
- package/templates/.cairn/git-hooks/pre-commit +48 -22
- package/templates/.github/workflows/cairn-check.yml +8 -0
- package/dist/attention/bulk-accept.d.ts +0 -78
- package/dist/attention/bulk-accept.js +0 -348
- package/dist/attention/bulk-accept.js.map +0 -1
- package/dist/attention/serve/api.d.ts +0 -24
- package/dist/attention/serve/api.js +0 -383
- package/dist/attention/serve/api.js.map +0 -1
- package/dist/attention/serve/index.d.ts +0 -63
- package/dist/attention/serve/index.js +0 -219
- package/dist/attention/serve/index.js.map +0 -1
- package/dist/hooks/read-enrich.d.ts +0 -6
- package/dist/hooks/read-enrich.js +0 -11
- package/dist/hooks/read-enrich.js.map +0 -1
- package/dist/hooks/write-guard.d.ts +0 -6
- package/dist/hooks/write-guard.js +0 -11
- package/dist/hooks/write-guard.js.map +0 -1
- package/dist/init/phases/12-strip.d.ts +0 -10
- package/dist/init/phases/12-strip.js +0 -88
- package/dist/init/phases/12-strip.js.map +0 -1
- package/dist/mcp/tools/attention-serve.d.ts +0 -23
- package/dist/mcp/tools/attention-serve.js +0 -84
- package/dist/mcp/tools/attention-serve.js.map +0 -1
- package/dist/mcp/tools/attention-wait.d.ts +0 -18
- package/dist/mcp/tools/attention-wait.js +0 -84
- package/dist/mcp/tools/attention-wait.js.map +0 -1
- package/dist/mcp/tools/bulk-accept-attention.d.ts +0 -22
- package/dist/mcp/tools/bulk-accept-attention.js +0 -84
- package/dist/mcp/tools/bulk-accept-attention.js.map +0 -1
- package/dist/sensors/attestation.d.ts +0 -44
- package/dist/sensors/attestation.js +0 -262
- package/dist/sensors/attestation.js.map +0 -1
|
@@ -1,219 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Browser-based DEC-draft triage GUI.
|
|
3
|
-
*
|
|
4
|
-
* Spawned by `cairn attention serve` (CLI) or
|
|
5
|
-
* `cairn_attention_serve` (MCP). Operator drains the inbox in the
|
|
6
|
-
* browser instead of through `AskUserQuestion` round-trips, then
|
|
7
|
-
* clicks "I'm done" — the server writes a sentinel at
|
|
8
|
-
* `.cairn/cache/attention-done.json` that the caller polls (via
|
|
9
|
-
* `cairn_attention_wait` or by tailing the file).
|
|
10
|
-
*
|
|
11
|
-
* Why a GUI: at >15 drafts the inline `AskUserQuestion` flow burns
|
|
12
|
-
* `cairn_decision_get` calls per draft and 4-cap-per-question batches
|
|
13
|
-
* the operator through dozens of MCP turns. The browser does all the
|
|
14
|
-
* I/O directly against `.cairn/`, dropping per-triage round-trips to
|
|
15
|
-
* zero.
|
|
16
|
-
*
|
|
17
|
-
* Mechanics:
|
|
18
|
-
* - HTTP server on a free port (or operator-supplied), bound to
|
|
19
|
-
* 127.0.0.1 so the surface is local-only.
|
|
20
|
-
* - JSON API mirrors the existing attention handlers (bulk-accept,
|
|
21
|
-
* dedup, resolve, restore) so all writes funnel through the same
|
|
22
|
-
* `withWriteLock` path the MCP tools use.
|
|
23
|
-
* - Static SPA bundle (vanilla HTML+JS+CSS) under
|
|
24
|
-
* `cairn-core/templates/attention-ui/` — no build step.
|
|
25
|
-
* - Idle timeout: 10 min default, reset by `/api/heartbeat`. Server
|
|
26
|
-
* shuts down when idle exceeds the timeout or on `/api/done`.
|
|
27
|
-
*/
|
|
28
|
-
import { createServer } from "node:http";
|
|
29
|
-
import { dirname, join } from "node:path";
|
|
30
|
-
import { fileURLToPath } from "node:url";
|
|
31
|
-
import { randomBytes } from "node:crypto";
|
|
32
|
-
import { existsSync, readFileSync, rmSync, } from "node:fs";
|
|
33
|
-
import { writeFileSafe } from "@isaacriehm/cairn-state";
|
|
34
|
-
import { logger } from "../../logger.js";
|
|
35
|
-
import { handleApi } from "./api.js";
|
|
36
|
-
const log = logger("attention.serve");
|
|
37
|
-
const HERE = dirname(fileURLToPath(import.meta.url));
|
|
38
|
-
/**
|
|
39
|
-
* dist/attention/serve/index.js → walk up to package root, then into
|
|
40
|
-
* templates/attention-ui/. Bundled layout co-locates templates as a
|
|
41
|
-
* sibling of dist/cli.mjs (mirrors the seed.ts pattern).
|
|
42
|
-
*/
|
|
43
|
-
const TEMPLATES_ROOT = typeof __CAIRN_BUNDLED__ !== "undefined" && __CAIRN_BUNDLED__
|
|
44
|
-
? join(HERE, "templates", "attention-ui")
|
|
45
|
-
: join(HERE, "..", "..", "..", "templates", "attention-ui");
|
|
46
|
-
const DEFAULT_IDLE_TIMEOUT_MS = 10 * 60 * 1000;
|
|
47
|
-
const DONE_TIMEOUT_GRACE_MS = 500;
|
|
48
|
-
/**
|
|
49
|
-
* Per-repoRoot live-server registry. The MCP server is a single
|
|
50
|
-
* long-lived process; both `cairn_attention_serve` and
|
|
51
|
-
* `cairn_attention_wait` share this map so wait can await the live
|
|
52
|
-
* `done` promise instead of polling.
|
|
53
|
-
*/
|
|
54
|
-
const liveServers = new Map();
|
|
55
|
-
/** Read-only accessor for `cairn_attention_wait` and tests. */
|
|
56
|
-
export function getActiveAttentionServer(repoRoot) {
|
|
57
|
-
return liveServers.get(repoRoot);
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Boot the triage server. Returns once the listener is ready;
|
|
61
|
-
* `handle.done` resolves when the operator finishes or the server
|
|
62
|
-
* idles out.
|
|
63
|
-
*/
|
|
64
|
-
export async function startAttentionServer(opts) {
|
|
65
|
-
const idleTimeoutMs = opts.idleTimeoutMs ?? DEFAULT_IDLE_TIMEOUT_MS;
|
|
66
|
-
const sentinelPath = join(opts.repoRoot, ".cairn", "cache", "attention-done.json");
|
|
67
|
-
const token = randomBytes(16).toString("hex");
|
|
68
|
-
// Pre-clear any stale sentinel so the caller's wait loop isn't
|
|
69
|
-
// tricked by a previous run's payload.
|
|
70
|
-
try {
|
|
71
|
-
rmSync(sentinelPath, { force: true });
|
|
72
|
-
}
|
|
73
|
-
catch {
|
|
74
|
-
/* best-effort */
|
|
75
|
-
}
|
|
76
|
-
const counters = { accepted: 0, rejected: 0, merged: 0, edited: 0 };
|
|
77
|
-
const startedAt = new Date().toISOString();
|
|
78
|
-
let lastActivity = Date.now();
|
|
79
|
-
const touch = () => {
|
|
80
|
-
lastActivity = Date.now();
|
|
81
|
-
};
|
|
82
|
-
let resolveDone = () => {
|
|
83
|
-
/* sentinel */
|
|
84
|
-
};
|
|
85
|
-
const donePromise = new Promise((resolve) => {
|
|
86
|
-
resolveDone = resolve;
|
|
87
|
-
});
|
|
88
|
-
let server;
|
|
89
|
-
let idleTimer;
|
|
90
|
-
let shutdownStarted = false;
|
|
91
|
-
const writeSentinel = (reason) => {
|
|
92
|
-
const state = {
|
|
93
|
-
reason,
|
|
94
|
-
...counters,
|
|
95
|
-
startedAt,
|
|
96
|
-
endedAt: new Date().toISOString(),
|
|
97
|
-
};
|
|
98
|
-
try {
|
|
99
|
-
writeFileSafe(sentinelPath, JSON.stringify(state, null, 2));
|
|
100
|
-
}
|
|
101
|
-
catch (err) {
|
|
102
|
-
log.warn({ err: err instanceof Error ? err.message : String(err) }, "failed to write sentinel");
|
|
103
|
-
}
|
|
104
|
-
return state;
|
|
105
|
-
};
|
|
106
|
-
const beginShutdown = (reason) => {
|
|
107
|
-
if (shutdownStarted)
|
|
108
|
-
return;
|
|
109
|
-
shutdownStarted = true;
|
|
110
|
-
clearInterval(idleTimer);
|
|
111
|
-
const state = writeSentinel(reason);
|
|
112
|
-
setTimeout(() => {
|
|
113
|
-
server.close(() => {
|
|
114
|
-
resolveDone(state);
|
|
115
|
-
});
|
|
116
|
-
}, DONE_TIMEOUT_GRACE_MS);
|
|
117
|
-
};
|
|
118
|
-
server = createServer((req, res) => {
|
|
119
|
-
void handleRequest(req, res, {
|
|
120
|
-
repoRoot: opts.repoRoot,
|
|
121
|
-
counters,
|
|
122
|
-
touch,
|
|
123
|
-
token,
|
|
124
|
-
onDone: () => beginShutdown("done"),
|
|
125
|
-
});
|
|
126
|
-
});
|
|
127
|
-
await new Promise((resolve, reject) => {
|
|
128
|
-
server.once("error", reject);
|
|
129
|
-
server.listen(opts.port, "127.0.0.1", () => {
|
|
130
|
-
server.off("error", reject);
|
|
131
|
-
resolve();
|
|
132
|
-
});
|
|
133
|
-
});
|
|
134
|
-
const addr = server.address();
|
|
135
|
-
const port = typeof addr === "object" && addr !== null ? addr.port : opts.port;
|
|
136
|
-
const url = `http://127.0.0.1:${port}/?token=${token}`;
|
|
137
|
-
idleTimer = setInterval(() => {
|
|
138
|
-
if (Date.now() - lastActivity >= idleTimeoutMs) {
|
|
139
|
-
log.info({ idleTimeoutMs }, "attention server idle — shutting down");
|
|
140
|
-
beginShutdown("idle");
|
|
141
|
-
}
|
|
142
|
-
}, 30_000);
|
|
143
|
-
if (opts.signal !== undefined) {
|
|
144
|
-
if (opts.signal.aborted) {
|
|
145
|
-
beginShutdown("abort");
|
|
146
|
-
}
|
|
147
|
-
else {
|
|
148
|
-
opts.signal.addEventListener("abort", () => beginShutdown("abort"), {
|
|
149
|
-
once: true,
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
log.info({ port, url, sentinelPath }, "attention server listening");
|
|
154
|
-
const handle = {
|
|
155
|
-
port,
|
|
156
|
-
url,
|
|
157
|
-
token,
|
|
158
|
-
sentinelPath,
|
|
159
|
-
done: donePromise,
|
|
160
|
-
close: async () => {
|
|
161
|
-
beginShutdown("abort");
|
|
162
|
-
await donePromise;
|
|
163
|
-
},
|
|
164
|
-
};
|
|
165
|
-
liveServers.set(opts.repoRoot, handle);
|
|
166
|
-
void donePromise.finally(() => liveServers.delete(opts.repoRoot));
|
|
167
|
-
return handle;
|
|
168
|
-
}
|
|
169
|
-
async function handleRequest(req, res, ctx) {
|
|
170
|
-
ctx.touch();
|
|
171
|
-
const url = req.url ?? "/";
|
|
172
|
-
const parsedUrl = new URL(url, `http://${req.headers.host || "localhost"}`);
|
|
173
|
-
// Static assets are open, but we check token on entry index.html or API
|
|
174
|
-
if (parsedUrl.pathname === "/" || parsedUrl.pathname === "/index.html") {
|
|
175
|
-
const queryToken = parsedUrl.searchParams.get("token");
|
|
176
|
-
if (queryToken !== ctx.token) {
|
|
177
|
-
res.statusCode = 403;
|
|
178
|
-
res.end("forbidden: missing or invalid token");
|
|
179
|
-
return;
|
|
180
|
-
}
|
|
181
|
-
return serveStatic(res, "index.html", "text/html; charset=utf-8");
|
|
182
|
-
}
|
|
183
|
-
if (parsedUrl.pathname === "/static/app.js") {
|
|
184
|
-
return serveStatic(res, "app.js", "application/javascript; charset=utf-8");
|
|
185
|
-
}
|
|
186
|
-
if (parsedUrl.pathname === "/static/app.css") {
|
|
187
|
-
return serveStatic(res, "app.css", "text/css; charset=utf-8");
|
|
188
|
-
}
|
|
189
|
-
if (parsedUrl.pathname.startsWith("/api/")) {
|
|
190
|
-
return handleApi(req, res, ctx);
|
|
191
|
-
}
|
|
192
|
-
res.statusCode = 404;
|
|
193
|
-
res.setHeader("content-type", "text/plain");
|
|
194
|
-
res.end("not found");
|
|
195
|
-
}
|
|
196
|
-
function serveStatic(res, filename, contentType) {
|
|
197
|
-
const path = join(TEMPLATES_ROOT, filename);
|
|
198
|
-
if (!existsSync(path)) {
|
|
199
|
-
res.statusCode = 500;
|
|
200
|
-
res.setHeader("content-type", "text/plain");
|
|
201
|
-
res.end(`attention-ui template missing: ${filename}`);
|
|
202
|
-
return;
|
|
203
|
-
}
|
|
204
|
-
let body;
|
|
205
|
-
try {
|
|
206
|
-
body = readFileSync(path, "utf8");
|
|
207
|
-
}
|
|
208
|
-
catch (err) {
|
|
209
|
-
res.statusCode = 500;
|
|
210
|
-
res.setHeader("content-type", "text/plain");
|
|
211
|
-
res.end(`attention-ui template read failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
212
|
-
return;
|
|
213
|
-
}
|
|
214
|
-
res.statusCode = 200;
|
|
215
|
-
res.setHeader("content-type", contentType);
|
|
216
|
-
res.setHeader("cache-control", "no-store");
|
|
217
|
-
res.end(body);
|
|
218
|
-
}
|
|
219
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/attention/serve/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Bin entrypoint — `node cairn-core/dist/hooks/read-enrich.js`.
|
|
4
|
-
* PostToolUse on Read; injects citation legend.
|
|
5
|
-
*/
|
|
6
|
-
import { runReadEnricher } from "./post-tool-use/index.js";
|
|
7
|
-
runReadEnricher().catch((err) => {
|
|
8
|
-
process.stderr.write(`[cairn read-enrich] ${err instanceof Error ? err.message : String(err)}\n`);
|
|
9
|
-
process.exit(1);
|
|
10
|
-
});
|
|
11
|
-
//# sourceMappingURL=read-enrich.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"read-enrich.js","sourceRoot":"","sources":["../../src/hooks/read-enrich.ts"],"names":[],"mappings":";AACA;;;GAGG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAE3D,eAAe,EAAE,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IACvC,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,uBAAuB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAC5E,CAAC;IACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Bin entrypoint — `node cairn-core/dist/hooks/write-guard.js`.
|
|
4
|
-
* PostToolUse on Write/Edit; copy-safety + scope reminder.
|
|
5
|
-
*/
|
|
6
|
-
import { runWriteGuardian } from "./post-tool-use/index.js";
|
|
7
|
-
runWriteGuardian().catch((err) => {
|
|
8
|
-
process.stderr.write(`[cairn write-guard] ${err instanceof Error ? err.message : String(err)}\n`);
|
|
9
|
-
process.exit(1);
|
|
10
|
-
});
|
|
11
|
-
//# sourceMappingURL=write-guard.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"write-guard.js","sourceRoot":"","sources":["../../src/hooks/write-guard.ts"],"names":[],"mappings":";AACA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAE5D,gBAAgB,EAAE,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IACxC,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,uBAAuB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAC5E,CAAC;IACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Phase 12-strip — per-module strip-replace consent.
|
|
3
|
-
*
|
|
4
|
-
* Surfaces each ingestion-flagged module as an A/B/C choice (strip /
|
|
5
|
-
* keep / skip). Tracks remaining modules in
|
|
6
|
-
* `outputs["12-strip"].pending` and emits one question at a time
|
|
7
|
-
* until the queue is empty.
|
|
8
|
-
*/
|
|
9
|
-
import type { PhaseResult, PhaseState } from "./types.js";
|
|
10
|
-
export declare function runPhase12Strip(state: PhaseState): Promise<PhaseResult>;
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Phase 12-strip — per-module strip-replace consent.
|
|
3
|
-
*
|
|
4
|
-
* Surfaces each ingestion-flagged module as an A/B/C choice (strip /
|
|
5
|
-
* keep / skip). Tracks remaining modules in
|
|
6
|
-
* `outputs["12-strip"].pending` and emits one question at a time
|
|
7
|
-
* until the queue is empty.
|
|
8
|
-
*/
|
|
9
|
-
import { advancePhase, isSelfAdoptState } from "./orchestrator.js";
|
|
10
|
-
export async function runPhase12Strip(state) {
|
|
11
|
-
if (isSelfAdoptState(state)) {
|
|
12
|
-
const skipped = { pending: [], decisions: {} };
|
|
13
|
-
const next = {
|
|
14
|
-
...state,
|
|
15
|
-
outputs: { ...state.outputs, "12-strip": skipped },
|
|
16
|
-
answer: undefined,
|
|
17
|
-
};
|
|
18
|
-
return {
|
|
19
|
-
status: "complete",
|
|
20
|
-
nextPhase: "13-multidev",
|
|
21
|
-
state: advancePhase(next),
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
const existing = state.outputs["12-strip"];
|
|
25
|
-
const modules = computeFlaggedModules(state);
|
|
26
|
-
// Initialize on first entry.
|
|
27
|
-
let s = existing ?? { pending: [...modules], decisions: {} };
|
|
28
|
-
// Operator just answered → record + dequeue.
|
|
29
|
-
if (state.answer !== undefined && state.answer.length > 0 && s.pending.length > 0) {
|
|
30
|
-
const head = s.pending[0];
|
|
31
|
-
const choice = normalizeChoice(state.answer);
|
|
32
|
-
s = {
|
|
33
|
-
pending: s.pending.slice(1),
|
|
34
|
-
decisions: { ...s.decisions, [head]: choice },
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
if (s.pending.length === 0) {
|
|
38
|
-
const next = {
|
|
39
|
-
...state,
|
|
40
|
-
outputs: { ...state.outputs, "12-strip": s },
|
|
41
|
-
answer: undefined,
|
|
42
|
-
};
|
|
43
|
-
return {
|
|
44
|
-
status: "complete",
|
|
45
|
-
nextPhase: "13-multidev",
|
|
46
|
-
state: advancePhase(next),
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
const head = s.pending[0];
|
|
50
|
-
const question = {
|
|
51
|
-
id: `12-strip:${head}`,
|
|
52
|
-
prompt: `Strip the source-comment essay in ${head}?`,
|
|
53
|
-
options: [
|
|
54
|
-
{
|
|
55
|
-
id: "strip",
|
|
56
|
-
label: "strip — DEC is the source of truth",
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
id: "keep",
|
|
60
|
-
label: "keep — leave comment alongside DEC",
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
id: "skip",
|
|
64
|
-
label: "skip — decide later",
|
|
65
|
-
},
|
|
66
|
-
],
|
|
67
|
-
default: "skip",
|
|
68
|
-
};
|
|
69
|
-
return {
|
|
70
|
-
status: "needs_input",
|
|
71
|
-
question,
|
|
72
|
-
state: { ...state, outputs: { ...state.outputs, "12-strip": s }, answer: undefined },
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
function normalizeChoice(answer) {
|
|
76
|
-
switch (answer) {
|
|
77
|
-
case "strip":
|
|
78
|
-
case "keep":
|
|
79
|
-
case "skip":
|
|
80
|
-
return answer;
|
|
81
|
-
default:
|
|
82
|
-
return "skip";
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
function computeFlaggedModules(_state) {
|
|
86
|
-
return [];
|
|
87
|
-
}
|
|
88
|
-
//# sourceMappingURL=12-strip.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"12-strip.js","sourceRoot":"","sources":["../../../src/init/phases/12-strip.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* cairn_attention_serve — launch the browser triage GUI from inside
|
|
3
|
-
* the MCP server process.
|
|
4
|
-
*
|
|
5
|
-
* Why in-process (not spawn): the MCP server is already a long-lived
|
|
6
|
-
* Node process. Running the HTTP server alongside it means writes
|
|
7
|
-
* route through the same `withWriteLock` path as MCP tool calls and
|
|
8
|
-
* we don't need to know the CLI bundle path at runtime. Browser
|
|
9
|
-
* open is best-effort (`open` / `xdg-open` / `start`).
|
|
10
|
-
*
|
|
11
|
-
* Pairs with `cairn_attention_wait` — the calling skill drives:
|
|
12
|
-
* 1. cairn_attention_serve → URL + sentinel path
|
|
13
|
-
* 2. (operator triages in browser, clicks "I'm done")
|
|
14
|
-
* 3. cairn_attention_wait → unblocks when sentinel arrives
|
|
15
|
-
*/
|
|
16
|
-
import type { ToolDef } from "./types.js";
|
|
17
|
-
interface Input {
|
|
18
|
-
port?: number;
|
|
19
|
-
idle_timeout_min?: number;
|
|
20
|
-
no_open?: boolean;
|
|
21
|
-
}
|
|
22
|
-
export declare const attentionServeTool: ToolDef<Input>;
|
|
23
|
-
export {};
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* cairn_attention_serve — launch the browser triage GUI from inside
|
|
3
|
-
* the MCP server process.
|
|
4
|
-
*
|
|
5
|
-
* Why in-process (not spawn): the MCP server is already a long-lived
|
|
6
|
-
* Node process. Running the HTTP server alongside it means writes
|
|
7
|
-
* route through the same `withWriteLock` path as MCP tool calls and
|
|
8
|
-
* we don't need to know the CLI bundle path at runtime. Browser
|
|
9
|
-
* open is best-effort (`open` / `xdg-open` / `start`).
|
|
10
|
-
*
|
|
11
|
-
* Pairs with `cairn_attention_wait` — the calling skill drives:
|
|
12
|
-
* 1. cairn_attention_serve → URL + sentinel path
|
|
13
|
-
* 2. (operator triages in browser, clicks "I'm done")
|
|
14
|
-
* 3. cairn_attention_wait → unblocks when sentinel arrives
|
|
15
|
-
*/
|
|
16
|
-
import { spawn } from "node:child_process";
|
|
17
|
-
import { z } from "zod";
|
|
18
|
-
import { getActiveAttentionServer, startAttentionServer, } from "../../attention/serve/index.js";
|
|
19
|
-
import { requireBootstrap } from "../bootstrap-guard.js";
|
|
20
|
-
const inputShape = {
|
|
21
|
-
port: z.number().int().min(0).max(65535).optional(),
|
|
22
|
-
idle_timeout_min: z.number().int().min(1).max(180).optional(),
|
|
23
|
-
no_open: z.boolean().optional(),
|
|
24
|
-
};
|
|
25
|
-
async function handler(ctx, input) {
|
|
26
|
-
const block = requireBootstrap(ctx.repoRoot);
|
|
27
|
-
if (block !== null)
|
|
28
|
-
return block;
|
|
29
|
-
const existing = getActiveAttentionServer(ctx.repoRoot);
|
|
30
|
-
if (existing !== undefined) {
|
|
31
|
-
return {
|
|
32
|
-
ok: true,
|
|
33
|
-
url: existing.url,
|
|
34
|
-
port: existing.port,
|
|
35
|
-
sentinel_path: existing.sentinelPath,
|
|
36
|
-
reused: true,
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
const port = input.port ?? 0;
|
|
40
|
-
const idleTimeoutMs = input.idle_timeout_min !== undefined
|
|
41
|
-
? input.idle_timeout_min * 60_000
|
|
42
|
-
: undefined;
|
|
43
|
-
const handle = await startAttentionServer({
|
|
44
|
-
repoRoot: ctx.repoRoot,
|
|
45
|
-
port,
|
|
46
|
-
...(idleTimeoutMs !== undefined ? { idleTimeoutMs } : {}),
|
|
47
|
-
});
|
|
48
|
-
if (input.no_open !== true) {
|
|
49
|
-
try {
|
|
50
|
-
if (process.platform === "win32") {
|
|
51
|
-
// `start` is a cmd.exe builtin, not an exe on PATH; the empty
|
|
52
|
-
// "" is the window-title arg so the URL is not consumed as a title.
|
|
53
|
-
spawn("cmd", ["/c", "start", "", handle.url], {
|
|
54
|
-
stdio: "ignore",
|
|
55
|
-
detached: true,
|
|
56
|
-
}).unref();
|
|
57
|
-
}
|
|
58
|
-
else {
|
|
59
|
-
const opener = process.platform === "darwin" ? "open" : "xdg-open";
|
|
60
|
-
spawn(opener, [handle.url], {
|
|
61
|
-
stdio: "ignore",
|
|
62
|
-
detached: true,
|
|
63
|
-
}).unref();
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
catch {
|
|
67
|
-
// operator clicks the printed URL manually
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
return {
|
|
71
|
-
ok: true,
|
|
72
|
-
url: handle.url,
|
|
73
|
-
port: handle.port,
|
|
74
|
-
sentinel_path: handle.sentinelPath,
|
|
75
|
-
reused: false,
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
export const attentionServeTool = {
|
|
79
|
-
name: "cairn_attention_serve",
|
|
80
|
-
description: "Launch the browser triage GUI on a free local port (127.0.0.1). Pairs with cairn_attention_wait — the skill calls this, prints the URL to chat, then blocks on cairn_attention_wait until the operator clicks 'I'm done' in the browser. The GUI handles accept / reject / edit / merge / bulk-accept directly against `.cairn/ground/decisions/`, so MCP round-trips drop to zero during triage. Use when attention_count > 15 — below that, the inline AskUserQuestion flow is more efficient.",
|
|
81
|
-
inputSchema: inputShape,
|
|
82
|
-
handler,
|
|
83
|
-
};
|
|
84
|
-
//# sourceMappingURL=attention-serve.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"attention-serve.js","sourceRoot":"","sources":["../../../src/mcp/tools/attention-serve.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* cairn_attention_wait — block until the browser triage GUI
|
|
3
|
-
* signals "I'm done" (or the server idles out / the timeout expires).
|
|
4
|
-
*
|
|
5
|
-
* Two completion paths:
|
|
6
|
-
* 1. In-process — if `cairn_attention_serve` was called from the
|
|
7
|
-
* same MCP server, the live `AttentionServeHandle.done` promise
|
|
8
|
-
* is awaited directly.
|
|
9
|
-
* 2. Sentinel file — `.cairn/cache/attention-done.json`. Polled
|
|
10
|
-
* every second as a fallback so external `cairn attention serve`
|
|
11
|
-
* (CLI) sessions work too.
|
|
12
|
-
*/
|
|
13
|
-
import type { ToolDef } from "./types.js";
|
|
14
|
-
interface Input {
|
|
15
|
-
timeout_seconds?: number;
|
|
16
|
-
}
|
|
17
|
-
export declare const attentionWaitTool: ToolDef<Input>;
|
|
18
|
-
export {};
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* cairn_attention_wait — block until the browser triage GUI
|
|
3
|
-
* signals "I'm done" (or the server idles out / the timeout expires).
|
|
4
|
-
*
|
|
5
|
-
* Two completion paths:
|
|
6
|
-
* 1. In-process — if `cairn_attention_serve` was called from the
|
|
7
|
-
* same MCP server, the live `AttentionServeHandle.done` promise
|
|
8
|
-
* is awaited directly.
|
|
9
|
-
* 2. Sentinel file — `.cairn/cache/attention-done.json`. Polled
|
|
10
|
-
* every second as a fallback so external `cairn attention serve`
|
|
11
|
-
* (CLI) sessions work too.
|
|
12
|
-
*/
|
|
13
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
14
|
-
import { join } from "node:path";
|
|
15
|
-
import { z } from "zod";
|
|
16
|
-
import { getActiveAttentionServer, } from "../../attention/serve/index.js";
|
|
17
|
-
import { requireBootstrap } from "../bootstrap-guard.js";
|
|
18
|
-
const DoneStateSchema = z.object({
|
|
19
|
-
status: z.enum(["done", "idle", "abort"]),
|
|
20
|
-
accepted: z.number(),
|
|
21
|
-
rejected: z.number(),
|
|
22
|
-
merged: z.number(),
|
|
23
|
-
edited: z.number(),
|
|
24
|
-
}).passthrough();
|
|
25
|
-
const DEFAULT_TIMEOUT_SECONDS = 1800;
|
|
26
|
-
const POLL_INTERVAL_MS = 1000;
|
|
27
|
-
const inputShape = {
|
|
28
|
-
timeout_seconds: z.number().int().min(1).max(7200).optional(),
|
|
29
|
-
};
|
|
30
|
-
async function handler(ctx, input) {
|
|
31
|
-
const block = requireBootstrap(ctx.repoRoot);
|
|
32
|
-
if (block !== null)
|
|
33
|
-
return block;
|
|
34
|
-
const timeoutMs = (input.timeout_seconds ?? DEFAULT_TIMEOUT_SECONDS) * 1000;
|
|
35
|
-
const sentinelPath = join(ctx.repoRoot, ".cairn", "cache", "attention-done.json");
|
|
36
|
-
const live = getActiveAttentionServer(ctx.repoRoot);
|
|
37
|
-
if (live !== undefined) {
|
|
38
|
-
const result = await Promise.race([
|
|
39
|
-
live.done.then((s) => ({ kind: "done", state: s })),
|
|
40
|
-
new Promise((resolve) => setTimeout(() => resolve({ kind: "timeout" }), timeoutMs)),
|
|
41
|
-
]);
|
|
42
|
-
if (result.kind === "done") {
|
|
43
|
-
return { ok: true, ...result.state };
|
|
44
|
-
}
|
|
45
|
-
return {
|
|
46
|
-
ok: false,
|
|
47
|
-
error: "TIMEOUT",
|
|
48
|
-
timeout_seconds: input.timeout_seconds ?? DEFAULT_TIMEOUT_SECONDS,
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
// Fallback — poll the sentinel file. CLI-launched servers route here.
|
|
52
|
-
const deadline = Date.now() + timeoutMs;
|
|
53
|
-
while (Date.now() < deadline) {
|
|
54
|
-
if (existsSync(sentinelPath)) {
|
|
55
|
-
try {
|
|
56
|
-
const raw = readFileSync(sentinelPath, "utf8");
|
|
57
|
-
const parsed = JSON.parse(raw);
|
|
58
|
-
const result = DoneStateSchema.safeParse(parsed);
|
|
59
|
-
if (result.success) {
|
|
60
|
-
return { ok: true, ...result.data };
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
catch {
|
|
64
|
-
// partial write — try again next tick
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
await sleep(POLL_INTERVAL_MS);
|
|
68
|
-
}
|
|
69
|
-
return {
|
|
70
|
-
ok: false,
|
|
71
|
-
error: "TIMEOUT",
|
|
72
|
-
timeout_seconds: input.timeout_seconds ?? DEFAULT_TIMEOUT_SECONDS,
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
function sleep(ms) {
|
|
76
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
77
|
-
}
|
|
78
|
-
export const attentionWaitTool = {
|
|
79
|
-
name: "cairn_attention_wait",
|
|
80
|
-
description: "Block until the browser triage GUI signals completion (`.cairn/cache/attention-done.json` written) or the timeout expires (default 1800s). Returns the DoneState payload — counts of accepted / rejected / merged / edited drafts plus the reason the server stopped (`done` | `idle` | `abort`). Pair with cairn_attention_serve.",
|
|
81
|
-
inputSchema: inputShape,
|
|
82
|
-
handler,
|
|
83
|
-
};
|
|
84
|
-
//# sourceMappingURL=attention-wait.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"attention-wait.js","sourceRoot":"","sources":["../../../src/mcp/tools/attention-wait.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `cairn_bulk_accept_attention` MCP tool.
|
|
3
|
-
*
|
|
4
|
-
* Wraps `bulkAcceptObvious` so the cairn-attention skill can drain
|
|
5
|
-
* obvious DEC drafts in one tool call instead of N rounds of
|
|
6
|
-
* `cairn_resolve_attention(choice="a")` per draft. Loads the project
|
|
7
|
-
* globs from `.cairn/config.yaml` so the scoring
|
|
8
|
-
* heuristic has the same context the cli subcommand does.
|
|
9
|
-
*
|
|
10
|
-
* Returns a slim count-distribution shape — no draft bodies, no file
|
|
11
|
-
* paths beyond the accepted ID list. Skill renders the summary inline,
|
|
12
|
-
* then proceeds to interactive triage of the remaining (medium + low)
|
|
13
|
-
* drafts via the existing per-item flow.
|
|
14
|
-
*/
|
|
15
|
-
import { type DraftConfidence } from "../../attention/index.js";
|
|
16
|
-
import type { ToolDef } from "./types.js";
|
|
17
|
-
interface BulkAcceptInput {
|
|
18
|
-
threshold?: DraftConfidence;
|
|
19
|
-
dryRun?: boolean;
|
|
20
|
-
}
|
|
21
|
-
export declare const bulkAcceptAttentionTool: ToolDef<BulkAcceptInput>;
|
|
22
|
-
export {};
|