@isaacriehm/cairn-core 0.13.3 → 0.14.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/gc/entity-orphan.d.ts +55 -0
- package/dist/gc/entity-orphan.js +171 -0
- package/dist/gc/entity-orphan.js.map +1 -0
- package/dist/gc/index.d.ts +4 -0
- package/dist/gc/index.js +2 -0
- package/dist/gc/index.js.map +1 -1
- package/dist/gc/retire.d.ts +57 -0
- package/dist/gc/retire.js +189 -0
- package/dist/gc/retire.js.map +1 -0
- package/dist/gc/sweep.js +11 -0
- package/dist/gc/sweep.js.map +1 -1
- package/dist/gc/types.d.ts +2 -2
- package/dist/hooks/ask-user-blocked.d.ts +8 -0
- package/dist/hooks/ask-user-blocked.js +13 -0
- package/dist/hooks/ask-user-blocked.js.map +1 -0
- package/dist/hooks/post-tool-use/ask-user-blocked.d.ts +18 -0
- package/dist/hooks/post-tool-use/ask-user-blocked.js +113 -0
- package/dist/hooks/post-tool-use/ask-user-blocked.js.map +1 -0
- package/dist/hooks/post-tool-use/index.d.ts +1 -0
- package/dist/hooks/post-tool-use/index.js +1 -0
- package/dist/hooks/post-tool-use/index.js.map +1 -1
- package/dist/hooks/runners/context-threshold.js +2 -2
- package/dist/hooks/runners/context-threshold.js.map +1 -1
- package/dist/hooks/runners/gc-autotrigger.d.ts +7 -4
- package/dist/hooks/runners/gc-autotrigger.js +7 -4
- package/dist/hooks/runners/gc-autotrigger.js.map +1 -1
- package/dist/hooks/runners/stop.js +173 -90
- package/dist/hooks/runners/stop.js.map +1 -1
- package/dist/init/ingest-docs.d.ts +2 -4
- package/dist/init/ingest-docs.js +2 -4
- package/dist/init/ingest-docs.js.map +1 -1
- package/dist/mcp/errors.d.ts +1 -1
- package/dist/mcp/errors.js.map +1 -1
- package/dist/mcp/schemas.d.ts +7 -94
- package/dist/mcp/schemas.js +23 -87
- package/dist/mcp/schemas.js.map +1 -1
- package/dist/mcp/tools/index.js +6 -29
- package/dist/mcp/tools/index.js.map +1 -1
- package/dist/mcp/tools/retire-entity.d.ts +22 -0
- package/dist/mcp/tools/retire-entity.js +62 -0
- package/dist/mcp/tools/retire-entity.js.map +1 -0
- package/dist/mcp/tools/task-complete.js +7 -19
- package/dist/mcp/tools/task-complete.js.map +1 -1
- package/dist/mcp/tools/task-create.d.ts +0 -1
- package/dist/mcp/tools/task-create.js +31 -10
- package/dist/mcp/tools/task-create.js.map +1 -1
- package/dist/mcp/tools/task-journal-append.js +23 -2
- package/dist/mcp/tools/task-journal-append.js.map +1 -1
- package/dist/tasks/index.d.ts +2 -2
- package/dist/tasks/index.js +1 -1
- package/dist/tasks/index.js.map +1 -1
- package/dist/tasks/lifecycle.d.ts +14 -22
- package/dist/tasks/lifecycle.js +14 -47
- package/dist/tasks/lifecycle.js.map +1 -1
- package/package.json +2 -2
- package/dist/mcp/tools/align-drain.d.ts +0 -7
- package/dist/mcp/tools/align-drain.js +0 -26
- package/dist/mcp/tools/align-drain.js.map +0 -1
- package/dist/mcp/tools/archive.d.ts +0 -8
- package/dist/mcp/tools/archive.js +0 -72
- package/dist/mcp/tools/archive.js.map +0 -1
- package/dist/mcp/tools/attention-restore.d.ts +0 -14
- package/dist/mcp/tools/attention-restore.js +0 -22
- package/dist/mcp/tools/attention-restore.js.map +0 -1
- package/dist/mcp/tools/decisions-for-symbol.d.ts +0 -7
- package/dist/mcp/tools/decisions-for-symbol.js +0 -42
- package/dist/mcp/tools/decisions-for-symbol.js.map +0 -1
- package/dist/mcp/tools/get-full.d.ts +0 -7
- package/dist/mcp/tools/get-full.js +0 -46
- package/dist/mcp/tools/get-full.js.map +0 -1
- package/dist/mcp/tools/ground-get.d.ts +0 -7
- package/dist/mcp/tools/ground-get.js +0 -77
- package/dist/mcp/tools/ground-get.js.map +0 -1
- package/dist/mcp/tools/mission-close.d.ts +0 -8
- package/dist/mcp/tools/mission-close.js +0 -53
- package/dist/mcp/tools/mission-close.js.map +0 -1
- package/dist/mcp/tools/mission-reopen.d.ts +0 -13
- package/dist/mcp/tools/mission-reopen.js +0 -56
- package/dist/mcp/tools/mission-reopen.js.map +0 -1
- package/dist/mcp/tools/reject-candidate.d.ts +0 -24
- package/dist/mcp/tools/reject-candidate.js +0 -71
- package/dist/mcp/tools/reject-candidate.js.map +0 -1
- package/dist/mcp/tools/search-candidates.d.ts +0 -20
- package/dist/mcp/tools/search-candidates.js +0 -93
- package/dist/mcp/tools/search-candidates.js.map +0 -1
- package/dist/mcp/tools/supersedes-chain.d.ts +0 -6
- package/dist/mcp/tools/supersedes-chain.js +0 -66
- package/dist/mcp/tools/supersedes-chain.js.map +0 -1
- package/dist/mcp/tools/timeline.d.ts +0 -9
- package/dist/mcp/tools/timeline.js +0 -61
- package/dist/mcp/tools/timeline.js.map +0 -1
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { appendMissionJournal, archiveMission, locateMission, readMissionState, writeMissionState, } from "@isaacriehm/cairn-state";
|
|
2
|
-
import { requireBootstrap } from "../bootstrap-guard.js";
|
|
3
|
-
import { mcpError } from "../errors.js";
|
|
4
|
-
import { missionCloseInput } from "../schemas.js";
|
|
5
|
-
import { clearMissionPhaseDeferIfMatches } from "./mission-advance.js";
|
|
6
|
-
async function handler(ctx, input) {
|
|
7
|
-
const block = requireBootstrap(ctx.repoRoot);
|
|
8
|
-
if (block !== null)
|
|
9
|
-
return block;
|
|
10
|
-
const scope = locateMission(ctx.repoRoot, input.mission_id);
|
|
11
|
-
if (scope !== "active") {
|
|
12
|
-
return mcpError("MISSION_NOT_FOUND", `Mission ${input.mission_id} not active (scope=${scope ?? "missing"})`);
|
|
13
|
-
}
|
|
14
|
-
const state = readMissionState(ctx.repoRoot, input.mission_id);
|
|
15
|
-
if (state === null) {
|
|
16
|
-
return mcpError("MISSION_NOT_FOUND", `state.json missing for ${input.mission_id}`);
|
|
17
|
-
}
|
|
18
|
-
const closedAt = new Date().toISOString();
|
|
19
|
-
state.outcome = input.outcome;
|
|
20
|
-
state.cursor.active_phase = null;
|
|
21
|
-
state.cursor.active_phase_started_at = null;
|
|
22
|
-
state.closed_at = closedAt;
|
|
23
|
-
if (input.outcome === "aborted" && input.reason !== undefined) {
|
|
24
|
-
state.abort_reason = input.reason;
|
|
25
|
-
}
|
|
26
|
-
writeMissionState(ctx.repoRoot, input.mission_id, state);
|
|
27
|
-
appendMissionJournal(ctx.repoRoot, input.mission_id, {
|
|
28
|
-
ts: closedAt,
|
|
29
|
-
kind: "closed",
|
|
30
|
-
detail: input.outcome === "aborted"
|
|
31
|
-
? `aborted${input.reason !== undefined ? `: ${input.reason}` : ""}`
|
|
32
|
-
: "manual close",
|
|
33
|
-
});
|
|
34
|
-
archiveMission(ctx.repoRoot, input.mission_id);
|
|
35
|
-
// Drop any `.mission-phase-deferred-until` marker that still points
|
|
36
|
-
// at this mission. Closed missions should never suppress prompts on
|
|
37
|
-
// other missions or sessions.
|
|
38
|
-
clearMissionPhaseDeferIfMatches(ctx.repoRoot, { missionId: input.mission_id });
|
|
39
|
-
return {
|
|
40
|
-
ok: true,
|
|
41
|
-
mission_id: input.mission_id,
|
|
42
|
-
outcome: input.outcome,
|
|
43
|
-
closed_at: closedAt,
|
|
44
|
-
archived_to: `.cairn/ground/missions/_done/${input.mission_id}/`,
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
export const missionCloseTool = {
|
|
48
|
-
name: "cairn_mission_close",
|
|
49
|
-
description: "Close a mission and archive its dirs. `outcome=done` is the manual analogue of auto-close on last phase complete; `outcome=aborted` is the operator-driven cancel path (with optional `reason`). Roadmap moves to `.cairn/ground/missions/_done/<id>/`; per-clone runtime moves to `.cairn/missions/_done/<id>/`. Reversible via cairn_mission_reopen.",
|
|
50
|
-
inputSchema: missionCloseInput,
|
|
51
|
-
handler,
|
|
52
|
-
};
|
|
53
|
-
//# sourceMappingURL=mission-close.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mission-close.js","sourceRoot":"","sources":["../../../src/mcp/tools/mission-close.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `cairn_mission_reopen` — un-archive a closed mission. Moves the
|
|
3
|
-
* `_done/<id>/` dirs back to live locations and clears the
|
|
4
|
-
* `outcome: done|aborted` stamp so the cursor (whatever it was at
|
|
5
|
-
* close) drives the next session. Does NOT re-execute graduated
|
|
6
|
-
* phase tasks.
|
|
7
|
-
*/
|
|
8
|
-
import type { ToolDef } from "./types.js";
|
|
9
|
-
interface Input {
|
|
10
|
-
mission_id: string;
|
|
11
|
-
}
|
|
12
|
-
export declare const missionReopenTool: ToolDef<Input>;
|
|
13
|
-
export {};
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `cairn_mission_reopen` — un-archive a closed mission. Moves the
|
|
3
|
-
* `_done/<id>/` dirs back to live locations and clears the
|
|
4
|
-
* `outcome: done|aborted` stamp so the cursor (whatever it was at
|
|
5
|
-
* close) drives the next session. Does NOT re-execute graduated
|
|
6
|
-
* phase tasks.
|
|
7
|
-
*/
|
|
8
|
-
import { appendMissionJournal, findActiveMission, locateMission, readMissionState, restoreMission, writeMissionState, } from "@isaacriehm/cairn-state";
|
|
9
|
-
import { requireBootstrap } from "../bootstrap-guard.js";
|
|
10
|
-
import { mcpError } from "../errors.js";
|
|
11
|
-
import { missionReopenInput } from "../schemas.js";
|
|
12
|
-
async function handler(ctx, input) {
|
|
13
|
-
const block = requireBootstrap(ctx.repoRoot);
|
|
14
|
-
if (block !== null)
|
|
15
|
-
return block;
|
|
16
|
-
const scope = locateMission(ctx.repoRoot, input.mission_id);
|
|
17
|
-
if (scope === null) {
|
|
18
|
-
return mcpError("MISSION_NOT_FOUND", `Mission ${input.mission_id} not found`);
|
|
19
|
-
}
|
|
20
|
-
if (scope === "active") {
|
|
21
|
-
return mcpError("VALIDATION_FAILED", `Mission ${input.mission_id} is already active (no reopen needed)`);
|
|
22
|
-
}
|
|
23
|
-
if (findActiveMission(ctx.repoRoot) !== null) {
|
|
24
|
-
return mcpError("MISSION_ALREADY_ACTIVE", "Another mission is already active; close it before reopening this one (one active mission per repo).");
|
|
25
|
-
}
|
|
26
|
-
const moved = restoreMission(ctx.repoRoot, input.mission_id);
|
|
27
|
-
if (!moved) {
|
|
28
|
-
return mcpError("MISSION_NOT_FOUND", `Could not move archived dirs for ${input.mission_id}`);
|
|
29
|
-
}
|
|
30
|
-
const state = readMissionState(ctx.repoRoot, input.mission_id);
|
|
31
|
-
if (state !== null) {
|
|
32
|
-
state.outcome = "active";
|
|
33
|
-
delete state.closed_at;
|
|
34
|
-
delete state.abort_reason;
|
|
35
|
-
writeMissionState(ctx.repoRoot, input.mission_id, state);
|
|
36
|
-
}
|
|
37
|
-
const reopenedAt = new Date().toISOString();
|
|
38
|
-
appendMissionJournal(ctx.repoRoot, input.mission_id, {
|
|
39
|
-
ts: reopenedAt,
|
|
40
|
-
kind: "reopened",
|
|
41
|
-
detail: `cursor: ${state?.cursor.active_phase ?? "(none)"}`,
|
|
42
|
-
});
|
|
43
|
-
return {
|
|
44
|
-
ok: true,
|
|
45
|
-
mission_id: input.mission_id,
|
|
46
|
-
cursor: state?.cursor ?? null,
|
|
47
|
-
reopened_at: reopenedAt,
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
export const missionReopenTool = {
|
|
51
|
-
name: "cairn_mission_reopen",
|
|
52
|
-
description: "Un-archive a closed mission. Moves `.cairn/ground/missions/_done/<id>/` and `.cairn/missions/_done/<id>/` back to their live locations, resets `outcome` to active, and preserves the cursor at close-time. Refuses when another mission is already active. Does NOT re-execute graduated phase tasks.",
|
|
53
|
-
inputSchema: missionReopenInput,
|
|
54
|
-
handler,
|
|
55
|
-
};
|
|
56
|
-
//# sourceMappingURL=mission-reopen.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mission-reopen.js","sourceRoot":"","sources":["../../../src/mcp/tools/mission-reopen.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,aAAa,EACb,gBAAgB,EAChB,cAAc,EACd,iBAAiB,GAClB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAOnD,KAAK,UAAU,OAAO,CAAC,GAAe,EAAE,KAAY;IAClD,MAAM,KAAK,GAAG,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC7C,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAEjC,MAAM,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;IAC5D,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,OAAO,QAAQ,CAAC,mBAAmB,EAAE,WAAW,KAAK,CAAC,UAAU,YAAY,CAAC,CAAC;IAChF,CAAC;IACD,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;QACvB,OAAO,QAAQ,CACb,mBAAmB,EACnB,WAAW,KAAK,CAAC,UAAU,uCAAuC,CACnE,CAAC;IACJ,CAAC;IAED,IAAI,iBAAiB,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,IAAI,EAAE,CAAC;QAC7C,OAAO,QAAQ,CACb,wBAAwB,EACxB,sGAAsG,CACvG,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAG,cAAc,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;IAC7D,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,QAAQ,CAAC,mBAAmB,EAAE,oCAAoC,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC;IAC/F,CAAC;IAED,MAAM,KAAK,GAAG,gBAAgB,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;IAC/D,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,KAAK,CAAC,OAAO,GAAG,QAAQ,CAAC;QACzB,OAAO,KAAK,CAAC,SAAS,CAAC;QACvB,OAAO,KAAK,CAAC,YAAY,CAAC;QAC1B,iBAAiB,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;IAC3D,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC5C,oBAAoB,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,UAAU,EAAE;QACnD,EAAE,EAAE,UAAU;QACd,IAAI,EAAE,UAAU;QAChB,MAAM,EAAE,WAAW,KAAK,EAAE,MAAM,CAAC,YAAY,IAAI,QAAQ,EAAE;KAC5D,CAAC,CAAC;IAEH,OAAO;QACL,EAAE,EAAE,IAAI;QACR,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,MAAM,EAAE,KAAK,EAAE,MAAM,IAAI,IAAI;QAC7B,WAAW,EAAE,UAAU;KACxB,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,iBAAiB,GAAmB;IAC/C,IAAI,EAAE,sBAAsB;IAC5B,WAAW,EACT,wSAAwS;IAC1S,WAAW,EAAE,kBAAkB;IAC/B,OAAO;CACR,CAAC"}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `cairn_reject_candidate` — append a topic-index slug to
|
|
3
|
-
* `.cairn/ground/_rejected.yaml` so phase 6 / `cairn ingest` /
|
|
4
|
-
* `cairn_propose_decision` skip it on the next pass.
|
|
5
|
-
*
|
|
6
|
-
* Dedup by slug — first writer wins the
|
|
7
|
-
* `reason` string; subsequent writes only refresh `rejected_at`. The
|
|
8
|
-
* AI-curator path stamps `rejected_by: "ai-curator"`; operator-driven
|
|
9
|
-
* rejections (`cairn-attention` skill) reuse the same writer with
|
|
10
|
-
* `rejected_by: "operator"`.
|
|
11
|
-
*
|
|
12
|
-
* Refusal modes:
|
|
13
|
-
* - `not_found` — slug not present in the topic-index. We refuse so
|
|
14
|
-
* stale agent calls can't poison the rejection
|
|
15
|
-
* ledger with phantom slugs that the GC pass would
|
|
16
|
-
* immediately drop.
|
|
17
|
-
*/
|
|
18
|
-
import type { ToolDef } from "./types.js";
|
|
19
|
-
interface Input {
|
|
20
|
-
slug: string;
|
|
21
|
-
reason: string;
|
|
22
|
-
}
|
|
23
|
-
export declare const rejectCandidateTool: ToolDef<Input>;
|
|
24
|
-
export {};
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `cairn_reject_candidate` — append a topic-index slug to
|
|
3
|
-
* `.cairn/ground/_rejected.yaml` so phase 6 / `cairn ingest` /
|
|
4
|
-
* `cairn_propose_decision` skip it on the next pass.
|
|
5
|
-
*
|
|
6
|
-
* Dedup by slug — first writer wins the
|
|
7
|
-
* `reason` string; subsequent writes only refresh `rejected_at`. The
|
|
8
|
-
* AI-curator path stamps `rejected_by: "ai-curator"`; operator-driven
|
|
9
|
-
* rejections (`cairn-attention` skill) reuse the same writer with
|
|
10
|
-
* `rejected_by: "operator"`.
|
|
11
|
-
*
|
|
12
|
-
* Refusal modes:
|
|
13
|
-
* - `not_found` — slug not present in the topic-index. We refuse so
|
|
14
|
-
* stale agent calls can't poison the rejection
|
|
15
|
-
* ledger with phantom slugs that the GC pass would
|
|
16
|
-
* immediately drop.
|
|
17
|
-
*/
|
|
18
|
-
import { appendRejected, readRejectedYaml, readTopicIndex, writeRejectedYaml, } from "@isaacriehm/cairn-state";
|
|
19
|
-
import { withWriteLock } from "../../lock.js";
|
|
20
|
-
import { requireBootstrap } from "../bootstrap-guard.js";
|
|
21
|
-
import { rejectCandidateInput } from "../schemas.js";
|
|
22
|
-
const REJECTED_BY = "ai-curator";
|
|
23
|
-
async function handler(ctx, input) {
|
|
24
|
-
const block = requireBootstrap(ctx.repoRoot);
|
|
25
|
-
if (block !== null)
|
|
26
|
-
return block;
|
|
27
|
-
return withWriteLock(ctx.repoRoot, () => {
|
|
28
|
-
const topicIndex = readTopicIndex(ctx.repoRoot);
|
|
29
|
-
const entry = topicIndex.topics[input.slug];
|
|
30
|
-
if (entry === undefined) {
|
|
31
|
-
return {
|
|
32
|
-
ok: false,
|
|
33
|
-
reason: "not_found",
|
|
34
|
-
detail: `slug "${input.slug}" not in topic-index`,
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
const sot = entry.candidates.find((c) => c.file === entry.sot_source);
|
|
38
|
-
const now = new Date().toISOString();
|
|
39
|
-
const record = {
|
|
40
|
-
slug: input.slug,
|
|
41
|
-
rejected_at: now,
|
|
42
|
-
rejected_by: REJECTED_BY,
|
|
43
|
-
reason: input.reason,
|
|
44
|
-
sot_source: entry.sot_source,
|
|
45
|
-
...(sot?.line_range !== undefined ? { line_range: sot.line_range } : {}),
|
|
46
|
-
};
|
|
47
|
-
const current = readRejectedYaml(ctx.repoRoot);
|
|
48
|
-
const existing = current.get(input.slug);
|
|
49
|
-
const next = appendRejected(current, record);
|
|
50
|
-
writeRejectedYaml(ctx.repoRoot, next);
|
|
51
|
-
if (existing !== undefined) {
|
|
52
|
-
return {
|
|
53
|
-
ok: true,
|
|
54
|
-
slug: input.slug,
|
|
55
|
-
warning: `Slug ${input.slug} was already rejected by ${existing.rejected_by} (${existing.reason}). ` +
|
|
56
|
-
`Refreshed rejected_at; original reason preserved.`,
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
return {
|
|
60
|
-
ok: true,
|
|
61
|
-
slug: input.slug,
|
|
62
|
-
};
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
export const rejectCandidateTool = {
|
|
66
|
-
name: "cairn_reject_candidate",
|
|
67
|
-
description: "Mark a topic-index slug as not-a-decision in `.cairn/ground/_rejected.yaml`. Phase 6 / cairn ingest skip rejected slugs. Dedup by slug; first writer wins the reason string. Use when the candidate is research, narrative, plan, status, or otherwise not a binding rule.",
|
|
68
|
-
inputSchema: rejectCandidateInput,
|
|
69
|
-
handler,
|
|
70
|
-
};
|
|
71
|
-
//# sourceMappingURL=reject-candidate.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"reject-candidate.js","sourceRoot":"","sources":["../../../src/mcp/tools/reject-candidate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,iBAAiB,GAElB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAgBrD,MAAM,WAAW,GAAG,YAAY,CAAC;AAEjC,KAAK,UAAU,OAAO,CAAC,GAAe,EAAE,KAAY;IAClD,MAAM,KAAK,GAAG,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC7C,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAEjC,OAAO,aAAa,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,EAAE;QACtC,MAAM,UAAU,GAAG,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAChD,MAAM,KAAK,GAAG,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC5C,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,MAAM,EAAE,WAAW;gBACnB,MAAM,EAAE,SAAS,KAAK,CAAC,IAAI,sBAAsB;aAClB,CAAC;QACpC,CAAC;QAED,MAAM,GAAG,GAAG,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,UAAU,CAAC,CAAC;QACtE,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QACrC,MAAM,MAAM,GAAkB;YAC5B,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,WAAW,EAAE,GAAG;YAChB,WAAW,EAAE,WAAW;YACxB,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,GAAG,CAAC,GAAG,EAAE,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACzE,CAAC;QAEF,MAAM,OAAO,GAAG,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC/C,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACzC,MAAM,IAAI,GAAG,cAAc,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC7C,iBAAiB,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAEtC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3B,OAAO;gBACL,EAAE,EAAE,IAAI;gBACR,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,OAAO,EACL,QAAQ,KAAK,CAAC,IAAI,4BAA4B,QAAQ,CAAC,WAAW,KAAK,QAAQ,CAAC,MAAM,KAAK;oBAC3F,mDAAmD;aACtB,CAAC;QACpC,CAAC;QACD,OAAO;YACL,EAAE,EAAE,IAAI;YACR,IAAI,EAAE,KAAK,CAAC,IAAI;SACe,CAAC;IACpC,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,MAAM,mBAAmB,GAAmB;IACjD,IAAI,EAAE,wBAAwB;IAC9B,WAAW,EACT,4QAA4Q;IAC9Q,WAAW,EAAE,oBAAoB;IACjC,OAAO;CACR,CAAC"}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `cairn_search_candidates` — query topic-index entries that haven't
|
|
3
|
-
* been promoted to a DEC yet (`dec_id IS NULL`).
|
|
4
|
-
*
|
|
5
|
-
* Spec: Mirrors the response shape of
|
|
6
|
-
* `cairn_in_scope` so AI agents can use the two interchangeably
|
|
7
|
-
* during the daily read-enrich-driven curator flow.
|
|
8
|
-
*
|
|
9
|
-
* The slugs returned by this tool are exactly the slugs accepted by
|
|
10
|
-
* `cairn_propose_decision` and `cairn_reject_candidate`.
|
|
11
|
-
*/
|
|
12
|
-
import type { ToolDef } from "./types.js";
|
|
13
|
-
interface Input {
|
|
14
|
-
query?: string;
|
|
15
|
-
scope?: string;
|
|
16
|
-
kind?: "decision" | "rule";
|
|
17
|
-
limit?: number;
|
|
18
|
-
}
|
|
19
|
-
export declare const searchCandidatesTool: ToolDef<Input>;
|
|
20
|
-
export {};
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `cairn_search_candidates` — query topic-index entries that haven't
|
|
3
|
-
* been promoted to a DEC yet (`dec_id IS NULL`).
|
|
4
|
-
*
|
|
5
|
-
* Spec: Mirrors the response shape of
|
|
6
|
-
* `cairn_in_scope` so AI agents can use the two interchangeably
|
|
7
|
-
* during the daily read-enrich-driven curator flow.
|
|
8
|
-
*
|
|
9
|
-
* The slugs returned by this tool are exactly the slugs accepted by
|
|
10
|
-
* `cairn_propose_decision` and `cairn_reject_candidate`.
|
|
11
|
-
*/
|
|
12
|
-
import { matchGlob, readRejectedYaml, readTopicIndex, } from "@isaacriehm/cairn-state";
|
|
13
|
-
import { readSotBody } from "../../init/sot-emit.js";
|
|
14
|
-
import { readAnchorMap } from "@isaacriehm/cairn-state";
|
|
15
|
-
import { searchCandidatesInput } from "../schemas.js";
|
|
16
|
-
/** Matches the body-preview cap used elsewhere when surfacing prose to AI agents. */
|
|
17
|
-
const BODY_PREVIEW_CHARS = 280;
|
|
18
|
-
const DEFAULT_LIMIT = 50;
|
|
19
|
-
async function handler(ctx, input) {
|
|
20
|
-
const limit = Math.min(input.limit ?? DEFAULT_LIMIT, 200);
|
|
21
|
-
const topicIndex = readTopicIndex(ctx.repoRoot);
|
|
22
|
-
const anchorMap = readAnchorMap(ctx.repoRoot);
|
|
23
|
-
const rejected = readRejectedYaml(ctx.repoRoot);
|
|
24
|
-
const q = input.query !== undefined ? input.query.toLowerCase() : null;
|
|
25
|
-
const scope = input.scope ?? null;
|
|
26
|
-
const out = [];
|
|
27
|
-
for (const entry of Object.values(topicIndex.topics)) {
|
|
28
|
-
if (entry.dec_id !== undefined)
|
|
29
|
-
continue;
|
|
30
|
-
if (rejected.has(entry.slug))
|
|
31
|
-
continue;
|
|
32
|
-
if (input.kind !== undefined && entry.marker_kind !== input.kind)
|
|
33
|
-
continue;
|
|
34
|
-
if (scope !== null && !matchGlob(entry.sot_source, scope))
|
|
35
|
-
continue;
|
|
36
|
-
const body = readSotBody(ctx.repoRoot, entry, anchorMap) ?? "";
|
|
37
|
-
const title = deriveTitle(entry, body);
|
|
38
|
-
if (q !== null) {
|
|
39
|
-
const titleHit = title.toLowerCase().includes(q);
|
|
40
|
-
const bodyHit = body.toLowerCase().includes(q);
|
|
41
|
-
if (!titleHit && !bodyHit)
|
|
42
|
-
continue;
|
|
43
|
-
}
|
|
44
|
-
const sot = entry.candidates.find((c) => c.file === entry.sot_source);
|
|
45
|
-
const summary = {
|
|
46
|
-
slug: entry.slug,
|
|
47
|
-
title,
|
|
48
|
-
sot_source: entry.sot_source,
|
|
49
|
-
body_preview: previewBody(body),
|
|
50
|
-
};
|
|
51
|
-
if (sot?.line_range !== undefined)
|
|
52
|
-
summary.line_range = sot.line_range;
|
|
53
|
-
if (entry.marker_kind !== undefined)
|
|
54
|
-
summary.marker_kind = entry.marker_kind;
|
|
55
|
-
out.push(summary);
|
|
56
|
-
}
|
|
57
|
-
// Stable ordering: marker-kinded first, then alpha by sot_source so
|
|
58
|
-
// pagination via `limit` is predictable across runs.
|
|
59
|
-
out.sort((a, b) => {
|
|
60
|
-
const am = a.marker_kind !== undefined ? 0 : 1;
|
|
61
|
-
const bm = b.marker_kind !== undefined ? 0 : 1;
|
|
62
|
-
if (am !== bm)
|
|
63
|
-
return am - bm;
|
|
64
|
-
if (a.sot_source !== b.sot_source)
|
|
65
|
-
return a.sot_source.localeCompare(b.sot_source);
|
|
66
|
-
return a.slug.localeCompare(b.slug);
|
|
67
|
-
});
|
|
68
|
-
return out.slice(0, limit);
|
|
69
|
-
}
|
|
70
|
-
function deriveTitle(entry, body) {
|
|
71
|
-
const sot = entry.candidates.find((c) => c.file === entry.sot_source);
|
|
72
|
-
if (sot?.anchor !== undefined && sot.anchor.length > 0) {
|
|
73
|
-
return sot.anchor.replace(/[-_]+/g, " ").trim().slice(0, 120) || firstLineFallback(body);
|
|
74
|
-
}
|
|
75
|
-
return firstLineFallback(body);
|
|
76
|
-
}
|
|
77
|
-
function firstLineFallback(body) {
|
|
78
|
-
const first = body.split("\n").find((l) => l.trim().length > 0) ?? "";
|
|
79
|
-
return first.replace(/^#+\s*/, "").trim().slice(0, 120) || "(untitled)";
|
|
80
|
-
}
|
|
81
|
-
function previewBody(body) {
|
|
82
|
-
const trimmed = body.trim();
|
|
83
|
-
if (trimmed.length <= BODY_PREVIEW_CHARS)
|
|
84
|
-
return trimmed;
|
|
85
|
-
return `${trimmed.slice(0, BODY_PREVIEW_CHARS)}…`;
|
|
86
|
-
}
|
|
87
|
-
export const searchCandidatesTool = {
|
|
88
|
-
name: "cairn_search_candidates",
|
|
89
|
-
description: "List unpromoted topic-index candidates (slugs whose `dec_id` is null). Filter by `query` (substring on title/body), `scope` (glob on sot_source), or `kind` (marker_kind). Returned slugs feed `cairn_record_decision({ slug })` and `cairn_reject_candidate`.",
|
|
90
|
-
inputSchema: searchCandidatesInput,
|
|
91
|
-
handler,
|
|
92
|
-
};
|
|
93
|
-
//# sourceMappingURL=search-candidates.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"search-candidates.js","sourceRoot":"","sources":["../../../src/mcp/tools/search-candidates.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
2
|
-
import { join } from "node:path";
|
|
3
|
-
import { decisionsDir, parseFrontmatter } from "@isaacriehm/cairn-state";
|
|
4
|
-
import { DecisionFrontmatter } from "@isaacriehm/cairn-state";
|
|
5
|
-
import { mcpError } from "../errors.js";
|
|
6
|
-
import { supersedesChainInput } from "../schemas.js";
|
|
7
|
-
async function handler(ctx, input) {
|
|
8
|
-
const dir = decisionsDir(ctx.repoRoot);
|
|
9
|
-
if (!existsSync(dir))
|
|
10
|
-
return mcpError("DECISION_NOT_FOUND", `No decisions directory`);
|
|
11
|
-
const all = new Map();
|
|
12
|
-
for (const entry of readdirSync(dir, { withFileTypes: true, encoding: "utf8" })) {
|
|
13
|
-
if (!entry.isFile() || !entry.name.endsWith(".md"))
|
|
14
|
-
continue;
|
|
15
|
-
const parsed = parseFrontmatter(readFileSync(join(dir, entry.name), "utf8"));
|
|
16
|
-
const fm = DecisionFrontmatter.safeParse(parsed.frontmatter);
|
|
17
|
-
if (!fm.success)
|
|
18
|
-
continue;
|
|
19
|
-
all.set(fm.data.id, {
|
|
20
|
-
id: fm.data.id,
|
|
21
|
-
status: fm.data.status,
|
|
22
|
-
supersedes: fm.data.supersedes ?? null,
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
if (!all.has(input.decision_id)) {
|
|
26
|
-
return mcpError("DECISION_NOT_FOUND", `Unknown decision id ${input.decision_id}`);
|
|
27
|
-
}
|
|
28
|
-
// Walk back to root, then forward via reverse-supersedes index.
|
|
29
|
-
const reverse = new Map(); // supersedes-id → newer-id
|
|
30
|
-
for (const e of all.values()) {
|
|
31
|
-
if (e.supersedes)
|
|
32
|
-
reverse.set(e.supersedes, e.id);
|
|
33
|
-
}
|
|
34
|
-
// Find root (oldest) by walking supersedes chain backward.
|
|
35
|
-
let root = input.decision_id;
|
|
36
|
-
const seen = new Set();
|
|
37
|
-
while (true) {
|
|
38
|
-
if (seen.has(root))
|
|
39
|
-
break;
|
|
40
|
-
seen.add(root);
|
|
41
|
-
const cur = all.get(root);
|
|
42
|
-
if (!cur || cur.supersedes === null)
|
|
43
|
-
break;
|
|
44
|
-
root = cur.supersedes;
|
|
45
|
-
}
|
|
46
|
-
// Forward chain.
|
|
47
|
-
const chain = [];
|
|
48
|
-
const fwdSeen = new Set();
|
|
49
|
-
let cursor = root;
|
|
50
|
-
while (cursor && !fwdSeen.has(cursor)) {
|
|
51
|
-
fwdSeen.add(cursor);
|
|
52
|
-
const e = all.get(cursor);
|
|
53
|
-
if (!e)
|
|
54
|
-
break;
|
|
55
|
-
chain.push(e);
|
|
56
|
-
cursor = reverse.get(cursor);
|
|
57
|
-
}
|
|
58
|
-
return chain;
|
|
59
|
-
}
|
|
60
|
-
export const supersedesChainTool = {
|
|
61
|
-
name: "cairn_supersedes_chain",
|
|
62
|
-
description: "Forward chain from earliest superseded decision to current binding decision (status=accepted at the head).",
|
|
63
|
-
inputSchema: supersedesChainInput,
|
|
64
|
-
handler,
|
|
65
|
-
};
|
|
66
|
-
//# sourceMappingURL=supersedes-chain.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"supersedes-chain.js","sourceRoot":"","sources":["../../../src/mcp/tools/supersedes-chain.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
2
|
-
import { join } from "node:path";
|
|
3
|
-
import { runsTerminalDir } from "@isaacriehm/cairn-state";
|
|
4
|
-
import { timelineInput } from "../schemas.js";
|
|
5
|
-
/** Returns chronologically ordered run/event records intersecting the scope window. */
|
|
6
|
-
async function handler(ctx, input) {
|
|
7
|
-
const out = [];
|
|
8
|
-
const since = input.since ? Date.parse(input.since) : 0;
|
|
9
|
-
const until = input.until ? Date.parse(input.until) : Number.POSITIVE_INFINITY;
|
|
10
|
-
const wantKinds = input.kinds ? new Set(input.kinds) : null;
|
|
11
|
-
const dir = runsTerminalDir(ctx.repoRoot);
|
|
12
|
-
if (existsSync(dir)) {
|
|
13
|
-
for (const e of readdirSync(dir, { withFileTypes: true, encoding: "utf8" })) {
|
|
14
|
-
if (!e.isDirectory())
|
|
15
|
-
continue;
|
|
16
|
-
const meta = readJson(join(dir, e.name, "meta.json"));
|
|
17
|
-
if (!meta)
|
|
18
|
-
continue;
|
|
19
|
-
const ts = meta.finished_at ?? meta.started_at;
|
|
20
|
-
if (!ts)
|
|
21
|
-
continue;
|
|
22
|
-
const tsMs = Date.parse(ts);
|
|
23
|
-
if (Number.isNaN(tsMs) || tsMs < since || tsMs > until)
|
|
24
|
-
continue;
|
|
25
|
-
if (wantKinds && !wantKinds.has("run"))
|
|
26
|
-
continue;
|
|
27
|
-
// scope filter — scoped_module substring match.
|
|
28
|
-
if (input.scope && input.scope.length > 0 && meta.scoped_module) {
|
|
29
|
-
const hit = input.scope.some((g) => meta.scoped_module?.includes(g) ?? false);
|
|
30
|
-
if (!hit)
|
|
31
|
-
continue;
|
|
32
|
-
}
|
|
33
|
-
out.push({
|
|
34
|
-
ts,
|
|
35
|
-
kind: "run",
|
|
36
|
-
run_id: meta.run_id,
|
|
37
|
-
...(meta.task_id !== undefined ? { task_id: meta.task_id } : {}),
|
|
38
|
-
...(meta.phase !== undefined ? { detail: meta.phase } : {}),
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
out.sort((a, b) => b.ts.localeCompare(a.ts));
|
|
43
|
-
return out;
|
|
44
|
-
}
|
|
45
|
-
function readJson(path) {
|
|
46
|
-
if (!existsSync(path))
|
|
47
|
-
return null;
|
|
48
|
-
try {
|
|
49
|
-
return JSON.parse(readFileSync(path, "utf8"));
|
|
50
|
-
}
|
|
51
|
-
catch {
|
|
52
|
-
return null;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
export const timelineTool = {
|
|
56
|
-
name: "cairn_timeline",
|
|
57
|
-
description: "Chronological run-event stream intersecting the scope window. Reads runs/terminal/.",
|
|
58
|
-
inputSchema: timelineInput,
|
|
59
|
-
handler,
|
|
60
|
-
};
|
|
61
|
-
//# sourceMappingURL=timeline.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"timeline.js","sourceRoot":"","sources":["../../../src/mcp/tools/timeline.ts"],"names":[],"mappings":"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"}
|