@isaacriehm/cairn-core 0.13.2 → 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/attention/bulk-accept.js +19 -0
- package/dist/attention/bulk-accept.js.map +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 +260 -115
- 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/index.d.ts +1 -0
- package/dist/mcp/index.js +1 -0
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/schemas.d.ts +16 -94
- package/dist/mcp/schemas.js +41 -89
- package/dist/mcp/schemas.js.map +1 -1
- package/dist/mcp/tools/decision-get.js +9 -0
- package/dist/mcp/tools/decision-get.js.map +1 -1
- package/dist/mcp/tools/index.js +8 -29
- package/dist/mcp/tools/index.js.map +1 -1
- package/dist/mcp/tools/invariant-get.js +8 -0
- package/dist/mcp/tools/invariant-get.js.map +1 -1
- package/dist/mcp/tools/mission-advance.d.ts +15 -0
- package/dist/mcp/tools/mission-advance.js +36 -1
- package/dist/mcp/tools/mission-advance.js.map +1 -1
- package/dist/mcp/tools/record-decision.js +14 -1
- package/dist/mcp/tools/record-decision.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 +28 -22
- 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 +41 -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/mcp/tools/task-reopen.d.ts +7 -0
- package/dist/mcp/tools/task-reopen.js +40 -0
- package/dist/mcp/tools/task-reopen.js.map +1 -0
- 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 +62 -19
- package/dist/tasks/lifecycle.js +147 -42
- 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 -48
- 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
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `cairn_retire_decision` / `cairn_retire_invariant` — the manual OUT
|
|
3
|
+
* verb for the ground ledger.
|
|
4
|
+
*
|
|
5
|
+
* Retirement = archive, never hard-delete: the entity moves to
|
|
6
|
+
* `.cairn/ground/.archive/`, drops from the active ledger + SoT cache,
|
|
7
|
+
* and its body stays reachable via `cairn_query_history`. A lingering
|
|
8
|
+
* `§DEC-/§INV-` cite degrades to an `orphaned_citation` GC finding
|
|
9
|
+
* rather than a dangling reference.
|
|
10
|
+
*
|
|
11
|
+
* This is also the shared apply primitive the entity-orphan autonomous
|
|
12
|
+
* path and the cairn-attention "retire" action both invoke — one place
|
|
13
|
+
* decides what archival means.
|
|
14
|
+
*/
|
|
15
|
+
import type { ToolDef } from "./types.js";
|
|
16
|
+
interface Input {
|
|
17
|
+
id: string;
|
|
18
|
+
reason?: string;
|
|
19
|
+
}
|
|
20
|
+
export declare const retireDecisionTool: ToolDef<Input>;
|
|
21
|
+
export declare const retireInvariantTool: ToolDef<Input>;
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `cairn_retire_decision` / `cairn_retire_invariant` — the manual OUT
|
|
3
|
+
* verb for the ground ledger.
|
|
4
|
+
*
|
|
5
|
+
* Retirement = archive, never hard-delete: the entity moves to
|
|
6
|
+
* `.cairn/ground/.archive/`, drops from the active ledger + SoT cache,
|
|
7
|
+
* and its body stays reachable via `cairn_query_history`. A lingering
|
|
8
|
+
* `§DEC-/§INV-` cite degrades to an `orphaned_citation` GC finding
|
|
9
|
+
* rather than a dangling reference.
|
|
10
|
+
*
|
|
11
|
+
* This is also the shared apply primitive the entity-orphan autonomous
|
|
12
|
+
* path and the cairn-attention "retire" action both invoke — one place
|
|
13
|
+
* decides what archival means.
|
|
14
|
+
*/
|
|
15
|
+
import { existsSync } from "node:fs";
|
|
16
|
+
import { join } from "node:path";
|
|
17
|
+
import { archiveEntity, decisionsDir, invariantsDir, } from "@isaacriehm/cairn-state";
|
|
18
|
+
import { mcpError } from "../errors.js";
|
|
19
|
+
import { requireBootstrap } from "../bootstrap-guard.js";
|
|
20
|
+
import { withWriteLock } from "../../lock.js";
|
|
21
|
+
import { retireDecisionInput, retireInvariantInput } from "../schemas.js";
|
|
22
|
+
function makeHandler(kind) {
|
|
23
|
+
return async (ctx, input) => {
|
|
24
|
+
const block = requireBootstrap(ctx.repoRoot);
|
|
25
|
+
if (block !== null)
|
|
26
|
+
return block;
|
|
27
|
+
const dir = kind === "INV" ? invariantsDir(ctx.repoRoot) : decisionsDir(ctx.repoRoot);
|
|
28
|
+
const abs = join(dir, `${input.id}.md`);
|
|
29
|
+
if (!existsSync(abs)) {
|
|
30
|
+
return mcpError(kind === "INV" ? "INVARIANT_NOT_FOUND" : "DECISION_NOT_FOUND", `${input.id} is not in the active ledger (already retired, or never existed)`);
|
|
31
|
+
}
|
|
32
|
+
return withWriteLock(ctx.repoRoot, async () => {
|
|
33
|
+
const res = archiveEntity({
|
|
34
|
+
repoRoot: ctx.repoRoot,
|
|
35
|
+
id: input.id,
|
|
36
|
+
reason: input.reason ?? "manual retire via cairn_retire",
|
|
37
|
+
});
|
|
38
|
+
if (!res.ok) {
|
|
39
|
+
return mcpError("RETIRE_FAILED", `failed to retire ${input.id}: ${res.error ?? "unknown error"}`);
|
|
40
|
+
}
|
|
41
|
+
return {
|
|
42
|
+
ok: true,
|
|
43
|
+
id: res.id,
|
|
44
|
+
kind: res.kind,
|
|
45
|
+
archived_path: res.archivedPath,
|
|
46
|
+
};
|
|
47
|
+
});
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
export const retireDecisionTool = {
|
|
51
|
+
name: "cairn_retire_decision",
|
|
52
|
+
description: "Retire (archive) an accepted DEC that has rotted — superseded in spirit, or its backing source is gone. Moves it to .cairn/ground/.archive/, drops it from the active ledger, and preserves the body for cairn_query_history. NOT a hard delete.",
|
|
53
|
+
inputSchema: retireDecisionInput,
|
|
54
|
+
handler: makeHandler("DEC"),
|
|
55
|
+
};
|
|
56
|
+
export const retireInvariantTool = {
|
|
57
|
+
name: "cairn_retire_invariant",
|
|
58
|
+
description: "Retire (archive) an active INV that no longer holds — refactored away, or its backing source is gone. Moves it to .cairn/ground/.archive/, drops it from the active ledger, and preserves the body for cairn_query_history. NOT a hard delete.",
|
|
59
|
+
inputSchema: retireInvariantInput,
|
|
60
|
+
handler: makeHandler("INV"),
|
|
61
|
+
};
|
|
62
|
+
//# sourceMappingURL=retire-entity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retire-entity.js","sourceRoot":"","sources":["../../../src/mcp/tools/retire-entity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EACL,aAAa,EACb,YAAY,EACZ,aAAa,GACd,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAQ1E,SAAS,WAAW,CAAC,IAAmB;IACtC,OAAO,KAAK,EAAE,GAAe,EAAE,KAAY,EAAoB,EAAE;QAC/D,MAAM,KAAK,GAAG,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC7C,IAAI,KAAK,KAAK,IAAI;YAAE,OAAO,KAAK,CAAC;QACjC,MAAM,GAAG,GACP,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC5E,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC;QACxC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACrB,OAAO,QAAQ,CACb,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,oBAAoB,EAC7D,GAAG,KAAK,CAAC,EAAE,kEAAkE,CAC9E,CAAC;QACJ,CAAC;QACD,OAAO,aAAa,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE;YAC5C,MAAM,GAAG,GAAG,aAAa,CAAC;gBACxB,QAAQ,EAAE,GAAG,CAAC,QAAQ;gBACtB,EAAE,EAAE,KAAK,CAAC,EAAE;gBACZ,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,gCAAgC;aACzD,CAAC,CAAC;YACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;gBACZ,OAAO,QAAQ,CACb,eAAe,EACf,oBAAoB,KAAK,CAAC,EAAE,KAAK,GAAG,CAAC,KAAK,IAAI,eAAe,EAAE,CAChE,CAAC;YACJ,CAAC;YACD,OAAO;gBACL,EAAE,EAAE,IAAI;gBACR,EAAE,EAAE,GAAG,CAAC,EAAE;gBACV,IAAI,EAAE,GAAG,CAAC,IAAI;gBACd,aAAa,EAAE,GAAG,CAAC,YAAY;aAChC,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,kBAAkB,GAAmB;IAChD,IAAI,EAAE,uBAAuB;IAC7B,WAAW,EACT,kPAAkP;IACpP,WAAW,EAAE,mBAAmB;IAChC,OAAO,EAAE,WAAW,CAAC,KAAK,CAAC;CAC5B,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAmB;IACjD,IAAI,EAAE,wBAAwB;IAC9B,WAAW,EACT,gPAAgP;IAClP,WAAW,EAAE,oBAAoB;IACjC,OAAO,EAAE,WAAW,CAAC,KAAK,CAAC;CAC5B,CAAC"}
|
|
@@ -18,7 +18,7 @@ import { join } from "node:path";
|
|
|
18
18
|
import { requireBootstrap } from "../bootstrap-guard.js";
|
|
19
19
|
import { mcpError } from "../errors.js";
|
|
20
20
|
import { taskCompleteInput } from "../schemas.js";
|
|
21
|
-
import { completeTask, findCurrentActiveTask } from "../../tasks/index.js";
|
|
21
|
+
import { completeTask, findCurrentActiveTask, readTaskSessionAffinity, } from "../../tasks/index.js";
|
|
22
22
|
import { findActiveMission, readMissionState, readRoadmap, } from "@isaacriehm/cairn-state";
|
|
23
23
|
const SUMMARY_ADVISORY = 2000;
|
|
24
24
|
/**
|
|
@@ -182,9 +182,27 @@ async function handler(ctx, input) {
|
|
|
182
182
|
const block = requireBootstrap(ctx.repoRoot);
|
|
183
183
|
if (block !== null)
|
|
184
184
|
return block;
|
|
185
|
-
|
|
185
|
+
let taskId = input.task_id ?? null;
|
|
186
186
|
if (taskId === null) {
|
|
187
|
-
|
|
187
|
+
// No explicit task_id — pick the current active task, but ONLY if
|
|
188
|
+
// it belongs to this session. Bug-mine: a parallel session with no
|
|
189
|
+
// active task of its own picked up another session's active task
|
|
190
|
+
// by mtime and graduated it silently. With session-affinity stamps,
|
|
191
|
+
// we can now require explicit task_id when the implicit pick would
|
|
192
|
+
// cross a session boundary.
|
|
193
|
+
const implicit = findCurrentActiveTask(ctx.repoRoot);
|
|
194
|
+
if (implicit === null) {
|
|
195
|
+
return mcpError("TASK_NOT_FOUND", "no active task — pass task_id explicitly or call cairn_task_create first");
|
|
196
|
+
}
|
|
197
|
+
const affinity = readTaskSessionAffinity(ctx.repoRoot, implicit);
|
|
198
|
+
const sid = ctx.sessionId ?? null;
|
|
199
|
+
const owner = affinity.lastJournalSession ?? affinity.createdBySession ?? null;
|
|
200
|
+
if (sid !== null &&
|
|
201
|
+
owner !== null &&
|
|
202
|
+
owner !== sid) {
|
|
203
|
+
return mcpError("VALIDATION_FAILED", `Implicit active task ${implicit} was last touched by a different session (${owner}). Pass task_id explicitly so you don't accidentally graduate another session's work.`);
|
|
204
|
+
}
|
|
205
|
+
taskId = implicit;
|
|
188
206
|
}
|
|
189
207
|
const summaryResult = input.summary !== undefined ? softTruncate(input.summary, SUMMARY_ADVISORY) : null;
|
|
190
208
|
const result = completeTask({
|
|
@@ -202,12 +220,12 @@ async function handler(ctx, input) {
|
|
|
202
220
|
}
|
|
203
221
|
// When the task graduating closed out a `gate=prompt` phase, the
|
|
204
222
|
// completion ALSO means the operator owes a phase-exit decision.
|
|
205
|
-
// Surface
|
|
206
|
-
//
|
|
207
|
-
//
|
|
208
|
-
// auto-graduator path still writes
|
|
209
|
-
// `systemMessage` warning so
|
|
210
|
-
// the next prompt when the model isn't in the loop.
|
|
223
|
+
// Surface the structured metadata in the tool response; the caller
|
|
224
|
+
// (cairn-direction skill / cairn-attention skill) decides whether
|
|
225
|
+
// to surface the prompt via `AskUserQuestion` based on operator
|
|
226
|
+
// autonomy state. The Stop hook's auto-graduator path still writes
|
|
227
|
+
// the pending file + a `systemMessage` warning so UPS picks the
|
|
228
|
+
// hint up on the next prompt when the model isn't in the loop.
|
|
211
229
|
const phaseReady = result.phase_ready_to_exit;
|
|
212
230
|
if (phaseReady !== null) {
|
|
213
231
|
return {
|
|
@@ -223,18 +241,6 @@ async function handler(ctx, input) {
|
|
|
223
241
|
phase_id: phaseReady.phase_id,
|
|
224
242
|
phase_title: phaseReady.phase_title,
|
|
225
243
|
exit_criteria: phaseReady.exit_criteria,
|
|
226
|
-
render_instruction: [
|
|
227
|
-
`The phase \`${phaseReady.phase_title}\` is ready to exit (all linked tasks graduated). Surface this question to the operator via \`AskUserQuestion\` BEFORE ending your turn:`,
|
|
228
|
-
``,
|
|
229
|
-
`> Phase \`${phaseReady.phase_title}\` looks done. Move on?`,
|
|
230
|
-
`>`,
|
|
231
|
-
`> Exit criteria: ${phaseReady.exit_criteria}`,
|
|
232
|
-
`>`,
|
|
233
|
-
`> - [a] Mark phase done, advance to next phase`,
|
|
234
|
-
`> - [b] Keep working on this phase`,
|
|
235
|
-
``,
|
|
236
|
-
`On [a], call \`cairn_mission_advance({phase_id: "${phaseReady.phase_id}", choice: "exit"})\`. On [b], call \`cairn_mission_advance({phase_id: "${phaseReady.phase_id}", choice: "not_yet"})\`.`,
|
|
237
|
-
].join("\n"),
|
|
238
244
|
},
|
|
239
245
|
};
|
|
240
246
|
}
|
|
@@ -261,7 +267,7 @@ async function handler(ctx, input) {
|
|
|
261
267
|
}
|
|
262
268
|
export const taskCompleteTool = {
|
|
263
269
|
name: "cairn_task_complete",
|
|
264
|
-
description: "Graduate an active task (`.cairn/tasks/active/<task_id>/`) to a terminal phase (succeeded / failed / aborted) and move its directory to `.cairn/tasks/done/`. `task_id` is optional — defaults to the most-recently-touched active task. Called by the reviewer subagent after writing attestation.yaml, by the cairn-direction skill on a confirmed pivot, or by the Stop-hook auto-graduator. Returns TASK_NOT_FOUND if the task was already completed or no active task exists. When the completion satisfies the active phase's exit criteria under `exit_gate=prompt`, the response includes a `phase_ready_to_exit` block
|
|
270
|
+
description: "Graduate an active task (`.cairn/tasks/active/<task_id>/`) to a terminal phase (succeeded / failed / aborted) and move its directory to `.cairn/tasks/done/`. `task_id` is optional — defaults to the most-recently-touched active task. Called by the reviewer subagent after writing attestation.yaml, by the cairn-direction skill on a confirmed pivot, or by the Stop-hook auto-graduator. Returns TASK_NOT_FOUND if the task was already completed or no active task exists. When the completion satisfies the active phase's exit criteria under `exit_gate=prompt`, the response includes a structured `phase_ready_to_exit` block (mission_id, mission_title, phase_id, phase_title, exit_criteria); the caller decides whether to surface a phase-exit prompt — typical flow is `AskUserQuestion` before ending the turn unless the operator's running autonomously. When the task was mission-anchored, succeeded, and no phase-exit prompt fired, the response also carries a `next_action_hint` block telling the model what to do next (continue with the next pending PR in the cursor phase, start the auto-advanced next phase, or end the turn because the mission closed). The hint is the autonomous-continuation contract: the model reads `next_action_hint.instruction` and either calls `cairn_task_create` for the gap or ends the turn cleanly.",
|
|
265
271
|
inputSchema: taskCompleteInput,
|
|
266
272
|
handler,
|
|
267
273
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task-complete.js","sourceRoot":"","sources":["../../../src/mcp/tools/task-complete.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAElD,OAAO,
|
|
1
|
+
{"version":3,"file":"task-complete.js","sourceRoot":"","sources":["../../../src/mcp/tools/task-complete.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,6 +7,26 @@ import { requireBootstrap } from "../bootstrap-guard.js";
|
|
|
7
7
|
import { mcpError } from "../errors.js";
|
|
8
8
|
import { taskCreateInput } from "../schemas.js";
|
|
9
9
|
import { linkTaskToPhase } from "../../missions/task-link.js";
|
|
10
|
+
const TITLE_ADVISORY = 80;
|
|
11
|
+
/**
|
|
12
|
+
* Soft-truncate to `advisory` chars with a trailing marker. Returns
|
|
13
|
+
* the unchanged string when it fits. Splits at the last word boundary
|
|
14
|
+
* before the cap to avoid mid-token truncation. Mirrors the helper
|
|
15
|
+
* in task-complete / task-journal-append — same marker shape, same
|
|
16
|
+
* word-boundary rule, sized for an 80-char title cap.
|
|
17
|
+
*/
|
|
18
|
+
function softTruncate(s, advisory) {
|
|
19
|
+
if (s.length <= advisory)
|
|
20
|
+
return { value: s, truncated: false };
|
|
21
|
+
const removed = s.length - advisory;
|
|
22
|
+
const markerSuffix = `…[+${removed} chars truncated]`;
|
|
23
|
+
const keep = Math.max(0, advisory - markerSuffix.length);
|
|
24
|
+
let cut = s.slice(0, keep);
|
|
25
|
+
const lastSpace = cut.lastIndexOf(" ");
|
|
26
|
+
if (lastSpace > advisory - 20)
|
|
27
|
+
cut = cut.slice(0, lastSpace);
|
|
28
|
+
return { value: cut + markerSuffix, truncated: true };
|
|
29
|
+
}
|
|
10
30
|
/**
|
|
11
31
|
* Generate a `task_id` matching the regex `^TSK-[a-z0-9-]+-[0-9a-f]{7}$`.
|
|
12
32
|
*
|
|
@@ -39,6 +59,8 @@ async function handler(ctx, input) {
|
|
|
39
59
|
const block = requireBootstrap(ctx.repoRoot);
|
|
40
60
|
if (block !== null)
|
|
41
61
|
return block;
|
|
62
|
+
const titleResult = softTruncate(input.title, TITLE_ADVISORY);
|
|
63
|
+
const title = titleResult.value;
|
|
42
64
|
const taskId = generateTaskId(input.slug);
|
|
43
65
|
const taskDir = join(ctx.repoRoot, ".cairn", "tasks", "active", taskId);
|
|
44
66
|
if (existsSync(taskDir)) {
|
|
@@ -46,7 +68,6 @@ async function handler(ctx, input) {
|
|
|
46
68
|
}
|
|
47
69
|
mkdirSync(taskDir, { recursive: true });
|
|
48
70
|
const generatedAt = new Date().toISOString();
|
|
49
|
-
const needsReview = input.needs_review ?? true;
|
|
50
71
|
// Mission anchor — explicit input wins; otherwise inherit from the
|
|
51
72
|
// active mission's cursor. Empty string means opt-out (side-task).
|
|
52
73
|
let missionId = null;
|
|
@@ -89,7 +110,7 @@ async function handler(ctx, input) {
|
|
|
89
110
|
const phaseDef = roadmap?.frontmatter.phases.find((p) => p.id === phaseId);
|
|
90
111
|
if (phaseDef !== undefined) {
|
|
91
112
|
const tokens = new Set();
|
|
92
|
-
for (const s of [
|
|
113
|
+
for (const s of [title, input.slug, input.module ?? ""]) {
|
|
93
114
|
for (const tok of s.toLowerCase().split(/[^a-z0-9]+/)) {
|
|
94
115
|
if (tok.length >= 3)
|
|
95
116
|
tokens.add(tok);
|
|
@@ -113,7 +134,7 @@ async function handler(ctx, input) {
|
|
|
113
134
|
}
|
|
114
135
|
const specFrontmatter = {
|
|
115
136
|
id: taskId,
|
|
116
|
-
title
|
|
137
|
+
title,
|
|
117
138
|
type: "spec",
|
|
118
139
|
status: "ready",
|
|
119
140
|
audience: "dual",
|
|
@@ -121,10 +142,9 @@ async function handler(ctx, input) {
|
|
|
121
142
|
target_path_globs: input.target_path_globs ?? [],
|
|
122
143
|
in_scope_decisions: input.in_scope_decisions ?? [],
|
|
123
144
|
in_scope_invariants: input.in_scope_invariants ?? [],
|
|
124
|
-
needs_review: needsReview,
|
|
125
145
|
};
|
|
126
146
|
const specBody = [
|
|
127
|
-
`# ${
|
|
147
|
+
`# ${title}`,
|
|
128
148
|
"",
|
|
129
149
|
"## Goal",
|
|
130
150
|
"",
|
|
@@ -140,21 +160,31 @@ async function handler(ctx, input) {
|
|
|
140
160
|
"",
|
|
141
161
|
renderBulletList(input.acceptance, "(implementation passes the operator's spot check)"),
|
|
142
162
|
].join("\n");
|
|
143
|
-
const specContent = `---\n${stringifyYaml(specFrontmatter)}---\n\n${specBody}`;
|
|
163
|
+
const specContent = `---\n${stringifyYaml(specFrontmatter, { lineWidth: 0 })}---\n\n${specBody}`;
|
|
144
164
|
const specPath = join(taskDir, "spec.tightened.md");
|
|
145
165
|
writeFileSync(specPath, specContent, "utf8");
|
|
146
166
|
const statusFrame = {
|
|
147
167
|
id: taskId,
|
|
148
168
|
phase: "running",
|
|
149
169
|
module: input.module ?? input.target_path_globs?.[0]?.split("/")[0] ?? ".",
|
|
150
|
-
title
|
|
170
|
+
title,
|
|
151
171
|
started_at: generatedAt,
|
|
152
172
|
};
|
|
173
|
+
// Session affinity — stamp the creating session id so the stall scan
|
|
174
|
+
// can tell whether a 30m-idle task is being worked in a parallel
|
|
175
|
+
// session vs. genuinely abandoned. Bug-mine: an operator running
|
|
176
|
+
// two concurrent Claude Code sessions on the same checkout saw each
|
|
177
|
+
// session flag the other's tasks as "stalled" and got asked to
|
|
178
|
+
// triage, breaking flow in both windows.
|
|
179
|
+
if (ctx.sessionId !== null && ctx.sessionId !== undefined) {
|
|
180
|
+
statusFrame["created_by_session"] = ctx.sessionId;
|
|
181
|
+
statusFrame["last_journal_session"] = ctx.sessionId;
|
|
182
|
+
}
|
|
153
183
|
if (missionId !== null && phaseId !== null) {
|
|
154
184
|
statusFrame["mission_id"] = missionId;
|
|
155
185
|
statusFrame["phase_id"] = phaseId;
|
|
156
186
|
}
|
|
157
|
-
const statusContent = stringifyYaml(statusFrame);
|
|
187
|
+
const statusContent = stringifyYaml(statusFrame, { lineWidth: 0 });
|
|
158
188
|
const statusPath = join(taskDir, "status.yaml");
|
|
159
189
|
writeFileSync(statusPath, statusContent, "utf8");
|
|
160
190
|
// Eagerly link the task to its phase's `task_ids`. Before this, linkage
|
|
@@ -175,14 +205,15 @@ async function handler(ctx, input) {
|
|
|
175
205
|
in_scope_invariants: (input.in_scope_invariants ?? []).map(renderInvariantId),
|
|
176
206
|
mission_id: missionId,
|
|
177
207
|
phase_id: phaseId,
|
|
208
|
+
...(titleResult.truncated ? { truncated: ["title"] } : {}),
|
|
178
209
|
...(scopeWarning !== null ? { warning: scopeWarning } : {}),
|
|
179
210
|
};
|
|
180
211
|
}
|
|
181
212
|
export const taskCreateTool = {
|
|
182
213
|
name: "cairn_task_create",
|
|
183
214
|
description: "Allocate a task_id and atomically write spec.tightened.md + status.yaml under .cairn/tasks/active/<task_id>/. " +
|
|
184
|
-
"**Required fields**: `slug` (lowercase kebab, 3-80 chars), `title` (≤80 chars), `goal` (free-form). " +
|
|
185
|
-
"**Optional**: `target_path_globs` (defaults to []; pass paths to pin scope), `in_scope_decisions`, `in_scope_invariants`, `constraints`, `out_of_scope`, `acceptance`, `module`, `
|
|
215
|
+
"**Required fields**: `slug` (lowercase kebab, 3-80 chars), `title` (advisory ≤80 chars; longer titles soft-truncate at the word boundary with a `…[+N chars truncated]` marker and the response carries `truncated: [\"title\"]`), `goal` (free-form). " +
|
|
216
|
+
"**Optional**: `target_path_globs` (defaults to []; pass paths to pin scope), `in_scope_decisions`, `in_scope_invariants`, `constraints`, `out_of_scope`, `acceptance`, `module`, `mission_id` (anchor to mission; defaults to active mission's cursor — pass `''` to opt out as side-task), `phase_id`. " +
|
|
186
217
|
"Server controls task_id format (`TSK-<slug>-<7-hex>`); callers cannot misformat it. " +
|
|
187
218
|
"Auto-links the new task to its phase's `task_ids` immediately so `cairn_mission_advance choice='exit'` sees the task without waiting for `cairn_task_complete`. " +
|
|
188
219
|
"Required by the cairn-direction skill before any source mutation.",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task-create.js","sourceRoot":"","sources":["../../../src/mcp/tools/task-create.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,SAAS,IAAI,aAAa,EAAE,MAAM,MAAM,CAAC;AAClD,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,WAAW,GACZ,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"task-create.js","sourceRoot":"","sources":["../../../src/mcp/tools/task-create.ts"],"names":[],"mappings":"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"}
|
|
@@ -14,6 +14,7 @@ import { mcpError } from "../errors.js";
|
|
|
14
14
|
import { taskJournalAppendInput } from "../schemas.js";
|
|
15
15
|
import { appendTaskJournal, findCurrentActiveTask } from "../../tasks/index.js";
|
|
16
16
|
const SUMMARY_ADVISORY = 320;
|
|
17
|
+
const FILES_TOUCHED_ADVISORY = 20;
|
|
17
18
|
/**
|
|
18
19
|
* Soft-truncate to `advisory` chars with a trailing marker. Returns the
|
|
19
20
|
* unchanged string when it fits. Splits at the last word boundary
|
|
@@ -42,13 +43,29 @@ async function handler(ctx, input) {
|
|
|
42
43
|
}
|
|
43
44
|
const summaryResult = softTruncate(input.summary, SUMMARY_ADVISORY);
|
|
44
45
|
const nextStepResult = input.next_step !== undefined ? softTruncate(input.next_step, SUMMARY_ADVISORY) : null;
|
|
46
|
+
// Soft-truncate the files_touched array. Keep the first N entries (the
|
|
47
|
+
// most-recently-cited paths in the AI's own ordering); surface the
|
|
48
|
+
// dropped tail in `dropped.files_touched` so the caller can re-batch
|
|
49
|
+
// them in a follow-up append without losing signal. Mirrors the
|
|
50
|
+
// string softTruncate UX: warn, never reject.
|
|
51
|
+
let filesTouched;
|
|
52
|
+
let droppedFiles;
|
|
53
|
+
if (input.files_touched !== undefined) {
|
|
54
|
+
if (input.files_touched.length > FILES_TOUCHED_ADVISORY) {
|
|
55
|
+
filesTouched = input.files_touched.slice(0, FILES_TOUCHED_ADVISORY);
|
|
56
|
+
droppedFiles = input.files_touched.slice(FILES_TOUCHED_ADVISORY);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
filesTouched = input.files_touched;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
45
62
|
const ok = appendTaskJournal({
|
|
46
63
|
repoRoot: ctx.repoRoot,
|
|
47
64
|
taskId,
|
|
48
65
|
sessionId: input.session_id ?? null,
|
|
49
66
|
summary: summaryResult.value,
|
|
50
67
|
...(nextStepResult !== null ? { nextStep: nextStepResult.value } : {}),
|
|
51
|
-
...(
|
|
68
|
+
...(filesTouched !== undefined ? { filesTouched } : {}),
|
|
52
69
|
...(input.decisions_loaded !== undefined ? { decisionsLoaded: input.decisions_loaded } : {}),
|
|
53
70
|
});
|
|
54
71
|
if (!ok) {
|
|
@@ -59,10 +76,13 @@ async function handler(ctx, input) {
|
|
|
59
76
|
truncatedFields.push("summary");
|
|
60
77
|
if (nextStepResult?.truncated === true)
|
|
61
78
|
truncatedFields.push("next_step");
|
|
79
|
+
if (droppedFiles !== undefined)
|
|
80
|
+
truncatedFields.push("files_touched");
|
|
62
81
|
return {
|
|
63
82
|
ok: true,
|
|
64
83
|
task_id: taskId,
|
|
65
84
|
...(truncatedFields.length > 0 ? { truncated: truncatedFields } : {}),
|
|
85
|
+
...(droppedFiles !== undefined ? { dropped: { files_touched: droppedFiles } } : {}),
|
|
66
86
|
};
|
|
67
87
|
}
|
|
68
88
|
export const taskJournalAppendTool = {
|
|
@@ -70,8 +90,9 @@ export const taskJournalAppendTool = {
|
|
|
70
90
|
description: "Append one journal entry to the active task's journal.jsonl. Call at the end of every assistant turn while a task is active so that `/cairn-resume <task_id>` after a `/clear` rebuilds the operator's mental state cold. " +
|
|
71
91
|
"`summary` is a terse one-liner (~320 chars; soft-truncated above that with a trailing marker — no validation reject). " +
|
|
72
92
|
"`next_step` is what comes next, same length budget. " +
|
|
93
|
+
"`files_touched` advisory cap = 20 paths; longer arrays keep the first 20 and the dropped tail comes back in `dropped.files_touched`. " +
|
|
73
94
|
"`task_id` is optional — Cairn picks the most-recently-touched active task when omitted. " +
|
|
74
|
-
"Response includes `truncated: [field…]` when any input was soft-truncated.",
|
|
95
|
+
"Response includes `truncated: [field…]` when any input was soft-truncated, plus `dropped.<field>` when an array was sliced.",
|
|
75
96
|
inputSchema: taskJournalAppendInput,
|
|
76
97
|
handler,
|
|
77
98
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task-journal-append.js","sourceRoot":"","sources":["../../../src/mcp/tools/task-journal-append.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAEvD,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAWhF,MAAM,gBAAgB,GAAG,GAAG,CAAC;
|
|
1
|
+
{"version":3,"file":"task-journal-append.js","sourceRoot":"","sources":["../../../src/mcp/tools/task-journal-append.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { reopenTask } from "../../tasks/index.js";
|
|
2
|
+
import { requireBootstrap } from "../bootstrap-guard.js";
|
|
3
|
+
import { mcpError } from "../errors.js";
|
|
4
|
+
import { taskReopenInput } from "../schemas.js";
|
|
5
|
+
async function handler(ctx, input) {
|
|
6
|
+
const block = requireBootstrap(ctx.repoRoot);
|
|
7
|
+
if (block !== null)
|
|
8
|
+
return block;
|
|
9
|
+
const result = reopenTask({
|
|
10
|
+
repoRoot: ctx.repoRoot,
|
|
11
|
+
taskId: input.task_id,
|
|
12
|
+
...(input.reason !== undefined ? { reason: input.reason } : {}),
|
|
13
|
+
source: "cairn_task_reopen",
|
|
14
|
+
});
|
|
15
|
+
if (!result.ok) {
|
|
16
|
+
if (result.code === "TASK_NOT_FOUND") {
|
|
17
|
+
return mcpError("TASK_NOT_FOUND", result.message);
|
|
18
|
+
}
|
|
19
|
+
if (result.code === "NOT_IN_DONE") {
|
|
20
|
+
return mcpError("VALIDATION_FAILED", result.message);
|
|
21
|
+
}
|
|
22
|
+
if (result.code === "ACTIVE_DIR_COLLISION") {
|
|
23
|
+
return mcpError("INTERNAL_ERROR", result.message);
|
|
24
|
+
}
|
|
25
|
+
return mcpError("INTERNAL_ERROR", result.message);
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
ok: true,
|
|
29
|
+
task_id: result.taskId,
|
|
30
|
+
reopened_at: result.reopenedAt,
|
|
31
|
+
moved_to: result.movedTo,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export const taskReopenTool = {
|
|
35
|
+
name: "cairn_task_reopen",
|
|
36
|
+
description: "Move a completed task from `tasks/done/<id>/` back to `tasks/active/<id>/`. Resets `phase: running`, archives any existing `attestation.yaml` so the Stop hook auto-graduator doesn't immediately re-close the task, and emits a `task-reopened` event. Use when `cairn_task_complete` graduated the wrong task (rare — typically from omitting `task_id` and picking up a parallel-session active task) or when an operator decides shipped work needs more changes. Reversible via `cairn_task_complete`.",
|
|
37
|
+
inputSchema: taskReopenInput,
|
|
38
|
+
handler,
|
|
39
|
+
};
|
|
40
|
+
//# sourceMappingURL=task-reopen.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-reopen.js","sourceRoot":"","sources":["../../../src/mcp/tools/task-reopen.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAElD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAQhD,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,MAAM,GAAG,UAAU,CAAC;QACxB,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,MAAM,EAAE,KAAK,CAAC,OAAO;QACrB,GAAG,CAAC,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/D,MAAM,EAAE,mBAAmB;KAC5B,CAAC,CAAC;IAEH,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;QACf,IAAI,MAAM,CAAC,IAAI,KAAK,gBAAgB,EAAE,CAAC;YACrC,OAAO,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;QACpD,CAAC;QACD,IAAI,MAAM,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;YAClC,OAAO,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;QACvD,CAAC;QACD,IAAI,MAAM,CAAC,IAAI,KAAK,sBAAsB,EAAE,CAAC;YAC3C,OAAO,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;QACpD,CAAC;QACD,OAAO,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IACpD,CAAC;IAED,OAAO;QACL,EAAE,EAAE,IAAI;QACR,OAAO,EAAE,MAAM,CAAC,MAAM;QACtB,WAAW,EAAE,MAAM,CAAC,UAAU;QAC9B,QAAQ,EAAE,MAAM,CAAC,OAAO;KACzB,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,cAAc,GAAmB;IAC5C,IAAI,EAAE,mBAAmB;IACzB,WAAW,EACT,6eAA6e;IAC/e,WAAW,EAAE,eAAe;IAC5B,OAAO;CACR,CAAC"}
|
package/dist/tasks/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { appendTaskJournal, completeTask, findCurrentActiveTask, readTaskAttestationState, readTaskJournal,
|
|
2
|
-
export type { AppendJournalArgs, CompleteTaskArgs, CompleteTaskError, CompleteTaskResult, JournalEntry,
|
|
1
|
+
export { appendTaskJournal, completeTask, findCurrentActiveTask, readTaskAttestationState, readTaskJournal, readTaskSessionAffinity, reopenTask, } from "./lifecycle.js";
|
|
2
|
+
export type { AppendJournalArgs, CompleteTaskArgs, CompleteTaskError, CompleteTaskResult, JournalEntry, ReopenTaskArgs, ReopenTaskError, ReopenTaskResult, TaskAttestationState, TaskOutcome, } from "./lifecycle.js";
|
package/dist/tasks/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { appendTaskJournal, completeTask, findCurrentActiveTask, readTaskAttestationState, readTaskJournal,
|
|
1
|
+
export { appendTaskJournal, completeTask, findCurrentActiveTask, readTaskAttestationState, readTaskJournal, readTaskSessionAffinity, reopenTask, } from "./lifecycle.js";
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/tasks/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tasks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,qBAAqB,EACrB,wBAAwB,EACxB,eAAe,EACf,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tasks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,qBAAqB,EACrB,wBAAwB,EACxB,eAAe,EACf,uBAAuB,EACvB,UAAU,GACX,MAAM,gBAAgB,CAAC"}
|