@isaacriehm/cairn-core 0.9.8 → 0.10.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.
Files changed (72) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/hooks/runners/stop.js +105 -0
  3. package/dist/hooks/runners/stop.js.map +1 -1
  4. package/dist/index.d.ts +1 -0
  5. package/dist/index.js +1 -0
  6. package/dist/index.js.map +1 -1
  7. package/dist/mcp/errors.d.ts +1 -1
  8. package/dist/mcp/errors.js.map +1 -1
  9. package/dist/mcp/schemas.d.ts +101 -0
  10. package/dist/mcp/schemas.js +92 -0
  11. package/dist/mcp/schemas.js.map +1 -1
  12. package/dist/mcp/tools/index.js +19 -0
  13. package/dist/mcp/tools/index.js.map +1 -1
  14. package/dist/mcp/tools/mission-accept-draft.d.ts +16 -0
  15. package/dist/mcp/tools/mission-accept-draft.js +102 -0
  16. package/dist/mcp/tools/mission-accept-draft.js.map +1 -0
  17. package/dist/mcp/tools/mission-advance.d.ts +8 -0
  18. package/dist/mcp/tools/mission-advance.js +124 -0
  19. package/dist/mcp/tools/mission-advance.js.map +1 -0
  20. package/dist/mcp/tools/mission-close.d.ts +8 -0
  21. package/dist/mcp/tools/mission-close.js +48 -0
  22. package/dist/mcp/tools/mission-close.js.map +1 -0
  23. package/dist/mcp/tools/mission-get.d.ts +6 -0
  24. package/dist/mcp/tools/mission-get.js +64 -0
  25. package/dist/mcp/tools/mission-get.js.map +1 -0
  26. package/dist/mcp/tools/mission-reopen.d.ts +13 -0
  27. package/dist/mcp/tools/mission-reopen.js +56 -0
  28. package/dist/mcp/tools/mission-reopen.js.map +1 -0
  29. package/dist/mcp/tools/mission-resume.d.ts +15 -0
  30. package/dist/mcp/tools/mission-resume.js +219 -0
  31. package/dist/mcp/tools/mission-resume.js.map +1 -0
  32. package/dist/mcp/tools/mission-resync-accept.d.ts +19 -0
  33. package/dist/mcp/tools/mission-resync-accept.js +192 -0
  34. package/dist/mcp/tools/mission-resync-accept.js.map +1 -0
  35. package/dist/mcp/tools/mission-resync.d.ts +20 -0
  36. package/dist/mcp/tools/mission-resync.js +113 -0
  37. package/dist/mcp/tools/mission-resync.js.map +1 -0
  38. package/dist/mcp/tools/mission-start.d.ts +8 -0
  39. package/dist/mcp/tools/mission-start.js +76 -0
  40. package/dist/mcp/tools/mission-start.js.map +1 -0
  41. package/dist/mcp/tools/task-create.d.ts +2 -0
  42. package/dist/mcp/tools/task-create.js +40 -2
  43. package/dist/mcp/tools/task-create.js.map +1 -1
  44. package/dist/missions/cli.d.ts +106 -0
  45. package/dist/missions/cli.js +279 -0
  46. package/dist/missions/cli.js.map +1 -0
  47. package/dist/missions/cursor.d.ts +40 -0
  48. package/dist/missions/cursor.js +99 -0
  49. package/dist/missions/cursor.js.map +1 -0
  50. package/dist/missions/draft.d.ts +28 -0
  51. package/dist/missions/draft.js +112 -0
  52. package/dist/missions/draft.js.map +1 -0
  53. package/dist/missions/index.d.ts +9 -0
  54. package/dist/missions/index.js +10 -0
  55. package/dist/missions/index.js.map +1 -0
  56. package/dist/missions/task-link.d.ts +51 -0
  57. package/dist/missions/task-link.js +155 -0
  58. package/dist/missions/task-link.js.map +1 -0
  59. package/dist/session-start/build.d.ts +1 -1
  60. package/dist/session-start/build.js +58 -1
  61. package/dist/session-start/build.js.map +1 -1
  62. package/dist/status-line/format.d.ts +15 -1
  63. package/dist/status-line/format.js +12 -1
  64. package/dist/status-line/format.js.map +1 -1
  65. package/dist/status-line/index.d.ts +1 -1
  66. package/dist/status-line/index.js +1 -1
  67. package/dist/status-line/index.js.map +1 -1
  68. package/dist/status-line/reader.js +33 -2
  69. package/dist/status-line/reader.js.map +1 -1
  70. package/dist/tasks/lifecycle.js +11 -0
  71. package/dist/tasks/lifecycle.js.map +1 -1
  72. package/package.json +2 -2
@@ -0,0 +1,76 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { isAbsolute, resolve } from "node:path";
3
+ import { findActiveMission } from "@isaacriehm/cairn-state";
4
+ import { requireBootstrap } from "../bootstrap-guard.js";
5
+ import { mcpError } from "../errors.js";
6
+ import { missionStartInput } from "../schemas.js";
7
+ import { draftRoadmapFromSpec, stubRoadmap } from "../../missions/index.js";
8
+ async function handler(ctx, input) {
9
+ const block = requireBootstrap(ctx.repoRoot);
10
+ if (block !== null)
11
+ return block;
12
+ if (findActiveMission(ctx.repoRoot) !== null) {
13
+ return mcpError("MISSION_ALREADY_ACTIVE", "An active mission already exists. Close or abort it before starting another (one active mission per repo).");
14
+ }
15
+ const absSpec = isAbsolute(input.spec_path)
16
+ ? input.spec_path
17
+ : resolve(ctx.repoRoot, input.spec_path);
18
+ if (!absSpec.startsWith(ctx.repoRoot)) {
19
+ return mcpError("PATH_OUTSIDE_REPO", `${input.spec_path} resolves outside the repo`);
20
+ }
21
+ if (!existsSync(absSpec)) {
22
+ return mcpError("FILE_NOT_FOUND", `Spec doc not found: ${input.spec_path}`);
23
+ }
24
+ let source;
25
+ try {
26
+ source = readFileSync(absSpec, "utf8");
27
+ }
28
+ catch (err) {
29
+ return mcpError("INTERNAL_ERROR", `Failed to read spec doc: ${err instanceof Error ? err.message : String(err)}`);
30
+ }
31
+ const proposedTitle = deriveTitleFromSpec(source, input.spec_path);
32
+ if (input.no_llm === true) {
33
+ return {
34
+ ok: true,
35
+ proposed_title: proposedTitle,
36
+ spec_path: input.spec_path,
37
+ exit_gate: input.exit_gate,
38
+ phases: stubRoadmap(),
39
+ truncated: false,
40
+ llm_used: false,
41
+ };
42
+ }
43
+ const draft = await draftRoadmapFromSpec({
44
+ repoRoot: ctx.repoRoot,
45
+ spec: source,
46
+ specPath: input.spec_path,
47
+ });
48
+ if (draft === null) {
49
+ return mcpError("MISSION_DRAFT_FAILED", "Haiku failed to parse the spec doc. Retry, or pass `no_llm: true` to write a single-phase stub roadmap and hand-edit it.");
50
+ }
51
+ return {
52
+ ok: true,
53
+ proposed_title: proposedTitle,
54
+ spec_path: input.spec_path,
55
+ exit_gate: input.exit_gate,
56
+ phases: draft.phases,
57
+ truncated: draft.truncated,
58
+ llm_used: true,
59
+ };
60
+ }
61
+ /**
62
+ * First H1 in the spec, or the spec's filename without extension.
63
+ * Capped at 60 chars so the slug fits within the statusline budget.
64
+ */
65
+ function deriveTitleFromSpec(source, fallback) {
66
+ const m = source.match(/^#\s+(.+?)\s*$/m);
67
+ const raw = m?.[1] ?? fallback.replace(/^.*\//, "").replace(/\.[a-z]+$/i, "");
68
+ return raw.slice(0, 60);
69
+ }
70
+ export const missionStartTool = {
71
+ name: "cairn_mission_start",
72
+ description: "Read a planning spec doc and draft a mission roadmap via Haiku. Returns the draft (proposed_title + ordered phases + spec_path + exit_gate) for operator approval. Does NOT write anything to disk; the caller invokes cairn_mission_accept_draft once the operator confirms. Pass `no_llm: true` to skip Haiku and return a single-phase stub.",
73
+ inputSchema: missionStartInput,
74
+ handler,
75
+ };
76
+ //# sourceMappingURL=mission-start.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mission-start.js","sourceRoot":"","sources":["../../../src/mcp/tools/mission-start.ts"],"names":[],"mappings":"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"}
@@ -11,6 +11,8 @@ interface Input {
11
11
  acceptance?: string[];
12
12
  module?: string;
13
13
  needs_review?: boolean;
14
+ mission_id?: string;
15
+ phase_id?: string;
14
16
  }
15
17
  export declare const taskCreateTool: ToolDef<Input>;
16
18
  export {};
@@ -2,6 +2,7 @@ import { existsSync, mkdirSync, writeFileSync } from "node:fs";
2
2
  import { join } from "node:path";
3
3
  import { createHash, randomUUID } from "node:crypto";
4
4
  import { stringify as stringifyYaml } from "yaml";
5
+ import { findActiveMission, readMissionState, readRoadmap, } from "@isaacriehm/cairn-state";
5
6
  import { requireBootstrap } from "../bootstrap-guard.js";
6
7
  import { mcpError } from "../errors.js";
7
8
  import { taskCreateInput } from "../schemas.js";
@@ -45,6 +46,36 @@ async function handler(ctx, input) {
45
46
  mkdirSync(taskDir, { recursive: true });
46
47
  const generatedAt = new Date().toISOString();
47
48
  const needsReview = input.needs_review ?? true;
49
+ // Mission anchor — explicit input wins; otherwise inherit from the
50
+ // active mission's cursor. Empty string means opt-out (side-task).
51
+ let missionId = null;
52
+ let phaseId = null;
53
+ if (input.mission_id === "") {
54
+ missionId = null;
55
+ phaseId = null;
56
+ }
57
+ else if (input.mission_id !== undefined && input.mission_id !== null) {
58
+ missionId = input.mission_id;
59
+ phaseId = input.phase_id ?? null;
60
+ }
61
+ else {
62
+ const activeMission = findActiveMission(ctx.repoRoot);
63
+ if (activeMission !== null) {
64
+ const state = readMissionState(ctx.repoRoot, activeMission);
65
+ const roadmap = readRoadmap(ctx.repoRoot, activeMission);
66
+ const cursorPhase = state?.cursor.active_phase ?? null;
67
+ if (cursorPhase !== null && roadmap?.frontmatter.phases.some((p) => p.id === cursorPhase)) {
68
+ missionId = activeMission;
69
+ phaseId = input.phase_id ?? cursorPhase;
70
+ }
71
+ }
72
+ }
73
+ if (missionId !== null && phaseId !== null) {
74
+ const roadmap = readRoadmap(ctx.repoRoot, missionId);
75
+ if (roadmap !== null && !roadmap.frontmatter.phases.some((p) => p.id === phaseId)) {
76
+ return mcpError("VALIDATION_FAILED", `phase_id ${phaseId} not present in roadmap of ${missionId}`);
77
+ }
78
+ }
48
79
  const specFrontmatter = {
49
80
  id: taskId,
50
81
  title: input.title,
@@ -77,13 +108,18 @@ async function handler(ctx, input) {
77
108
  const specContent = `---\n${stringifyYaml(specFrontmatter)}---\n\n${specBody}`;
78
109
  const specPath = join(taskDir, "spec.tightened.md");
79
110
  writeFileSync(specPath, specContent, "utf8");
80
- const statusContent = stringifyYaml({
111
+ const statusFrame = {
81
112
  id: taskId,
82
113
  phase: "running",
83
114
  module: input.module ?? input.target_path_globs[0]?.split("/")[0] ?? ".",
84
115
  title: input.title,
85
116
  started_at: generatedAt,
86
- });
117
+ };
118
+ if (missionId !== null && phaseId !== null) {
119
+ statusFrame["mission_id"] = missionId;
120
+ statusFrame["phase_id"] = phaseId;
121
+ }
122
+ const statusContent = stringifyYaml(statusFrame);
87
123
  const statusPath = join(taskDir, "status.yaml");
88
124
  writeFileSync(statusPath, statusContent, "utf8");
89
125
  return {
@@ -93,6 +129,8 @@ async function handler(ctx, input) {
93
129
  status_path: `.cairn/tasks/active/${taskId}/status.yaml`,
94
130
  in_scope_decisions: input.in_scope_decisions ?? [],
95
131
  in_scope_invariants: (input.in_scope_invariants ?? []).map(renderInvariantId),
132
+ mission_id: missionId,
133
+ phase_id: phaseId,
96
134
  };
97
135
  }
98
136
  export const taskCreateTool = {
@@ -1 +1 @@
1
- {"version":3,"file":"task-create.js","sourceRoot":"","sources":["../../../src/mcp/tools/task-create.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"task-create.js","sourceRoot":"","sources":["../../../src/mcp/tools/task-create.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,106 @@
1
+ /**
2
+ * CLI wrappers around the mission MCP tools — `cairn mission ...`
3
+ * subcommands. Reuses the helper modules (cursor, draft, task-link)
4
+ * directly so the CLI stays in lock-step with the MCP surface.
5
+ */
6
+ import { type MissionExitGate, type MissionPhase } from "@isaacriehm/cairn-state";
7
+ export interface MissionStartArgs {
8
+ repoRoot: string;
9
+ specPath: string;
10
+ exitGate: MissionExitGate;
11
+ noLlm?: boolean;
12
+ }
13
+ export interface MissionStartResult {
14
+ proposed_title: string;
15
+ spec_path: string;
16
+ exit_gate: MissionExitGate;
17
+ phases: MissionPhase[];
18
+ llm_used: boolean;
19
+ }
20
+ export declare function runMissionStart(args: MissionStartArgs): Promise<MissionStartResult>;
21
+ export interface MissionAcceptArgs {
22
+ repoRoot: string;
23
+ title: string;
24
+ specPath: string;
25
+ exitGate: MissionExitGate;
26
+ phases: MissionPhase[];
27
+ }
28
+ export interface MissionAcceptResult {
29
+ mission_id: string;
30
+ cursor: {
31
+ active_phase: string | null;
32
+ };
33
+ total_phases: number;
34
+ }
35
+ export declare function runMissionAccept(args: MissionAcceptArgs): MissionAcceptResult;
36
+ export interface MissionGetResult {
37
+ active: boolean;
38
+ mission_id?: string;
39
+ title?: string;
40
+ cursor?: {
41
+ active_phase: string | null;
42
+ };
43
+ progress?: {
44
+ done: number;
45
+ total: number;
46
+ };
47
+ drift_phase_ids?: string[];
48
+ }
49
+ export declare function runMissionGet(repoRoot: string): MissionGetResult;
50
+ export interface MissionAdvanceArgs {
51
+ repoRoot: string;
52
+ phaseId: string;
53
+ force?: boolean;
54
+ drop?: boolean;
55
+ }
56
+ export declare function runMissionAdvance(args: MissionAdvanceArgs): {
57
+ kind: "advanced";
58
+ phase_advanced: string;
59
+ next_phase: string | null;
60
+ closed: boolean;
61
+ } | {
62
+ kind: "dropped";
63
+ phase_id: string;
64
+ orphaned_task_ids: string[];
65
+ };
66
+ export declare function runMissionClose(repoRoot: string, missionId: string, outcome: "done" | "aborted", reason?: string): {
67
+ mission_id: string;
68
+ outcome: string;
69
+ closed_at: string;
70
+ };
71
+ export declare function runMissionReopen(repoRoot: string, missionId: string): {
72
+ mission_id: string;
73
+ cursor: {
74
+ active_phase: string | null;
75
+ } | null;
76
+ reopened_at: string;
77
+ };
78
+ export declare function listMissions(repoRoot: string): {
79
+ active: string[];
80
+ done: string[];
81
+ };
82
+ /**
83
+ * Pretty-print a roadmap to a string for `cairn mission start --print`
84
+ * preview output. Matches the YAML-frontmatter shape Cairn writes to
85
+ * disk so the operator can copy + edit it before approval.
86
+ */
87
+ export declare function previewRoadmap(args: {
88
+ title: string;
89
+ specPath: string;
90
+ exitGate: MissionExitGate;
91
+ phases: MissionPhase[];
92
+ }): string;
93
+ /** Used by `cairn mission accept --from <file>` to load a hand-edited roadmap draft. */
94
+ export declare function loadDraftFromFile(path: string): {
95
+ title: string;
96
+ spec_path: string;
97
+ exit_gate: MissionExitGate;
98
+ phases: MissionPhase[];
99
+ };
100
+ /** Persist the proposed roadmap draft to a temp JSON file for hand-editing. */
101
+ export declare function writeDraftToFile(path: string, draft: {
102
+ title: string;
103
+ spec_path: string;
104
+ exit_gate: MissionExitGate;
105
+ phases: MissionPhase[];
106
+ }): void;
@@ -0,0 +1,279 @@
1
+ /**
2
+ * CLI wrappers around the mission MCP tools — `cairn mission ...`
3
+ * subcommands. Reuses the helper modules (cursor, draft, task-link)
4
+ * directly so the CLI stays in lock-step with the MCP surface.
5
+ */
6
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
7
+ import { isAbsolute, resolve as pathResolve } from "node:path";
8
+ import { appendMissionJournal, archiveMission, countDonePhases, deriveMissionId, detectRoadmapDrift, findActiveMission, initialPhaseProgress, listActiveMissionIds, listDoneMissionIds, locateMission, nextPendingPhase, readMissionState, readRoadmap, restoreMission, writeMissionSpec, writeMissionState, writeRoadmap, } from "@isaacriehm/cairn-state";
9
+ import { advancePhase } from "./cursor.js";
10
+ import { draftRoadmapFromSpec, stubRoadmap } from "./draft.js";
11
+ export async function runMissionStart(args) {
12
+ if (findActiveMission(args.repoRoot) !== null) {
13
+ throw new Error("An active mission already exists; close or abort it before starting another.");
14
+ }
15
+ const abs = isAbsolute(args.specPath) ? args.specPath : pathResolve(args.repoRoot, args.specPath);
16
+ if (!abs.startsWith(args.repoRoot)) {
17
+ throw new Error(`${args.specPath} resolves outside the repo`);
18
+ }
19
+ if (!existsSync(abs)) {
20
+ throw new Error(`Spec doc not found: ${args.specPath}`);
21
+ }
22
+ const source = readFileSync(abs, "utf8");
23
+ const proposedTitle = deriveTitleFromSpec(source, args.specPath);
24
+ if (args.noLlm === true) {
25
+ return {
26
+ proposed_title: proposedTitle,
27
+ spec_path: args.specPath,
28
+ exit_gate: args.exitGate,
29
+ phases: stubRoadmap(),
30
+ llm_used: false,
31
+ };
32
+ }
33
+ const draft = await draftRoadmapFromSpec({
34
+ repoRoot: args.repoRoot,
35
+ spec: source,
36
+ specPath: args.specPath,
37
+ });
38
+ if (draft === null) {
39
+ throw new Error("Haiku failed to parse the spec doc; retry or pass --no-llm");
40
+ }
41
+ return {
42
+ proposed_title: proposedTitle,
43
+ spec_path: args.specPath,
44
+ exit_gate: args.exitGate,
45
+ phases: draft.phases,
46
+ llm_used: true,
47
+ };
48
+ }
49
+ export function runMissionAccept(args) {
50
+ if (findActiveMission(args.repoRoot) !== null) {
51
+ throw new Error("An active mission already exists; close or abort it before starting another.");
52
+ }
53
+ const abs = isAbsolute(args.specPath) ? args.specPath : pathResolve(args.repoRoot, args.specPath);
54
+ if (!existsSync(abs)) {
55
+ throw new Error(`Spec doc not found: ${args.specPath}`);
56
+ }
57
+ const startedAt = new Date().toISOString();
58
+ const missionId = deriveMissionId({ title: args.title, spec_path: args.specPath, started_at: startedAt });
59
+ const frontmatter = {
60
+ mission_id: missionId,
61
+ title: args.title,
62
+ spec_path: args.specPath,
63
+ created_at: startedAt,
64
+ exit_gate: args.exitGate,
65
+ phases: args.phases,
66
+ };
67
+ writeRoadmap(args.repoRoot, missionId, frontmatter, `# Mission — ${args.title}\n\nSpec: \`${args.specPath}\`.\n`);
68
+ writeMissionSpec(args.repoRoot, missionId, readFileSync(abs, "utf8"));
69
+ const phaseProgress = initialPhaseProgress(frontmatter);
70
+ const firstPhase = nextPendingPhase(frontmatter, {
71
+ mission_id: missionId,
72
+ started_at: startedAt,
73
+ cursor: { active_phase: null, active_phase_started_at: null },
74
+ phase_progress: phaseProgress,
75
+ outcome: "active",
76
+ });
77
+ if (firstPhase !== null) {
78
+ phaseProgress[firstPhase.id] = { state: "in_progress", task_ids: [] };
79
+ }
80
+ writeMissionState(args.repoRoot, missionId, {
81
+ mission_id: missionId,
82
+ started_at: startedAt,
83
+ cursor: {
84
+ active_phase: firstPhase?.id ?? null,
85
+ active_phase_started_at: firstPhase !== null ? startedAt : null,
86
+ },
87
+ phase_progress: phaseProgress,
88
+ outcome: "active",
89
+ });
90
+ appendMissionJournal(args.repoRoot, missionId, {
91
+ ts: startedAt,
92
+ kind: "started",
93
+ detail: `${args.phases.length} phases, exit_gate=${args.exitGate}`,
94
+ });
95
+ return {
96
+ mission_id: missionId,
97
+ cursor: { active_phase: firstPhase?.id ?? null },
98
+ total_phases: args.phases.length,
99
+ };
100
+ }
101
+ export function runMissionGet(repoRoot) {
102
+ const id = findActiveMission(repoRoot);
103
+ if (id === null)
104
+ return { active: false };
105
+ const roadmap = readRoadmap(repoRoot, id);
106
+ const state = readMissionState(repoRoot, id);
107
+ if (roadmap === null || state === null)
108
+ return { active: false };
109
+ return {
110
+ active: true,
111
+ mission_id: id,
112
+ title: roadmap.frontmatter.title,
113
+ cursor: { active_phase: state.cursor.active_phase },
114
+ progress: { done: countDonePhases(state), total: roadmap.frontmatter.phases.length },
115
+ drift_phase_ids: detectRoadmapDrift(roadmap.frontmatter, state),
116
+ };
117
+ }
118
+ export function runMissionAdvance(args) {
119
+ const missionId = findActiveMission(args.repoRoot);
120
+ if (missionId === null)
121
+ throw new Error("No active mission");
122
+ const state = readMissionState(args.repoRoot, missionId);
123
+ if (state === null)
124
+ throw new Error(`state.json missing for ${missionId}`);
125
+ const roadmap = readRoadmap(args.repoRoot, missionId);
126
+ if (roadmap === null)
127
+ throw new Error(`roadmap.md missing for ${missionId}`);
128
+ if (args.drop === true) {
129
+ if (roadmap.frontmatter.phases.some((p) => p.id === args.phaseId)) {
130
+ throw new Error(`phase ${args.phaseId} is still in roadmap.md; --drop only resolves drifted ids`);
131
+ }
132
+ const progress = state.phase_progress[args.phaseId];
133
+ if (progress === undefined) {
134
+ throw new Error(`phase ${args.phaseId} not present in phase_progress`);
135
+ }
136
+ const taskIds = progress.task_ids;
137
+ delete state.phase_progress[args.phaseId];
138
+ writeMissionState(args.repoRoot, missionId, state);
139
+ appendMissionJournal(args.repoRoot, missionId, {
140
+ ts: new Date().toISOString(),
141
+ kind: "drift-detected",
142
+ phase_id: args.phaseId,
143
+ detail: `dropped — ${taskIds.length} graduated task(s) orphaned`,
144
+ });
145
+ return { kind: "dropped", phase_id: args.phaseId, orphaned_task_ids: taskIds };
146
+ }
147
+ if (args.force !== true) {
148
+ const progress = state.phase_progress[args.phaseId];
149
+ if (progress === undefined || progress.task_ids.length === 0) {
150
+ throw new Error(`phase ${args.phaseId} has no linked tasks; pass --force to advance`);
151
+ }
152
+ }
153
+ const r = advancePhase(args.repoRoot, missionId, args.phaseId);
154
+ if (!r.ok)
155
+ throw new Error(r.message);
156
+ return {
157
+ kind: "advanced",
158
+ phase_advanced: r.phase_advanced,
159
+ next_phase: r.next_phase?.id ?? null,
160
+ closed: r.closed,
161
+ };
162
+ }
163
+ export function runMissionClose(repoRoot, missionId, outcome, reason) {
164
+ if (locateMission(repoRoot, missionId) !== "active") {
165
+ throw new Error(`Mission ${missionId} is not active`);
166
+ }
167
+ const state = readMissionState(repoRoot, missionId);
168
+ if (state === null)
169
+ throw new Error(`state.json missing for ${missionId}`);
170
+ const closedAt = new Date().toISOString();
171
+ state.outcome = outcome;
172
+ state.cursor.active_phase = null;
173
+ state.cursor.active_phase_started_at = null;
174
+ state.closed_at = closedAt;
175
+ if (outcome === "aborted" && reason !== undefined)
176
+ state.abort_reason = reason;
177
+ writeMissionState(repoRoot, missionId, state);
178
+ appendMissionJournal(repoRoot, missionId, {
179
+ ts: closedAt,
180
+ kind: "closed",
181
+ detail: outcome === "aborted" ? `aborted${reason !== undefined ? `: ${reason}` : ""}` : "manual close",
182
+ });
183
+ archiveMission(repoRoot, missionId);
184
+ return { mission_id: missionId, outcome, closed_at: closedAt };
185
+ }
186
+ export function runMissionReopen(repoRoot, missionId) {
187
+ if (locateMission(repoRoot, missionId) !== "done") {
188
+ throw new Error(`Mission ${missionId} is not archived`);
189
+ }
190
+ if (findActiveMission(repoRoot) !== null) {
191
+ throw new Error("Another mission is already active");
192
+ }
193
+ if (!restoreMission(repoRoot, missionId)) {
194
+ throw new Error(`Could not restore archived dirs for ${missionId}`);
195
+ }
196
+ const state = readMissionState(repoRoot, missionId);
197
+ const reopenedAt = new Date().toISOString();
198
+ if (state !== null) {
199
+ state.outcome = "active";
200
+ delete state.closed_at;
201
+ delete state.abort_reason;
202
+ writeMissionState(repoRoot, missionId, state);
203
+ }
204
+ appendMissionJournal(repoRoot, missionId, {
205
+ ts: reopenedAt,
206
+ kind: "reopened",
207
+ detail: `cursor: ${state?.cursor.active_phase ?? "(none)"}`,
208
+ });
209
+ return {
210
+ mission_id: missionId,
211
+ cursor: state?.cursor ?? null,
212
+ reopened_at: reopenedAt,
213
+ };
214
+ }
215
+ export function listMissions(repoRoot) {
216
+ return {
217
+ active: listActiveMissionIds(repoRoot),
218
+ done: listDoneMissionIds(repoRoot),
219
+ };
220
+ }
221
+ function deriveTitleFromSpec(source, fallback) {
222
+ const m = source.match(/^#\s+(.+?)\s*$/m);
223
+ const raw = m?.[1] ?? fallback.replace(/^.*\//, "").replace(/\.[a-z]+$/i, "");
224
+ return raw.slice(0, 60);
225
+ }
226
+ /**
227
+ * Pretty-print a roadmap to a string for `cairn mission start --print`
228
+ * preview output. Matches the YAML-frontmatter shape Cairn writes to
229
+ * disk so the operator can copy + edit it before approval.
230
+ */
231
+ export function previewRoadmap(args) {
232
+ const lines = [];
233
+ lines.push(`# Mission preview — ${args.title}`);
234
+ lines.push("");
235
+ lines.push(`spec_path: ${args.specPath}`);
236
+ lines.push(`exit_gate: ${args.exitGate}`);
237
+ lines.push("");
238
+ lines.push("Phases:");
239
+ for (const p of args.phases) {
240
+ lines.push(` - ${p.id}: ${p.title}`);
241
+ if (p.depends_on.length > 0)
242
+ lines.push(` depends_on: ${p.depends_on.join(", ")}`);
243
+ lines.push(` exit_criteria: ${p.exit_criteria}`);
244
+ }
245
+ return lines.join("\n");
246
+ }
247
+ /** Used by `cairn mission accept --from <file>` to load a hand-edited roadmap draft. */
248
+ export function loadDraftFromFile(path) {
249
+ if (!existsSync(path))
250
+ throw new Error(`Draft file not found: ${path}`);
251
+ const raw = readFileSync(path, "utf8");
252
+ const parsed = JSON.parse(raw);
253
+ if (typeof parsed !== "object" || parsed === null)
254
+ throw new Error("Draft file must be a JSON object");
255
+ const obj = parsed;
256
+ if (typeof obj["title"] !== "string")
257
+ throw new Error("Draft missing title");
258
+ if (typeof obj["spec_path"] !== "string")
259
+ throw new Error("Draft missing spec_path");
260
+ if (typeof obj["exit_gate"] !== "string")
261
+ throw new Error("Draft missing exit_gate");
262
+ if (!Array.isArray(obj["phases"]))
263
+ throw new Error("Draft missing phases array");
264
+ const exitGate = obj["exit_gate"];
265
+ if (exitGate !== "prompt" && exitGate !== "auto" && exitGate !== "manual") {
266
+ throw new Error(`Invalid exit_gate: ${exitGate}`);
267
+ }
268
+ return {
269
+ title: obj["title"],
270
+ spec_path: obj["spec_path"],
271
+ exit_gate: exitGate,
272
+ phases: obj["phases"],
273
+ };
274
+ }
275
+ /** Persist the proposed roadmap draft to a temp JSON file for hand-editing. */
276
+ export function writeDraftToFile(path, draft) {
277
+ writeFileSync(path, JSON.stringify(draft, null, 2) + "\n", "utf8");
278
+ }
279
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/missions/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Mission cursor advance helpers — shared logic between the explicit
3
+ * `cairn_mission_advance` MCP tool, the Stop hook auto-advance path
4
+ * (exit_gate=auto), and the Stop hook prompt path (exit_gate=prompt
5
+ * after operator picks `a`).
6
+ */
7
+ import { type MissionPhase, type MissionRoadmapFrontmatter, type MissionState } from "@isaacriehm/cairn-state";
8
+ export interface AdvanceResult {
9
+ ok: true;
10
+ phase_advanced: string;
11
+ next_phase: MissionPhase | null;
12
+ /** True when this advance closed the mission. */
13
+ closed: boolean;
14
+ donePhases: number;
15
+ totalPhases: number;
16
+ }
17
+ export interface AdvanceError {
18
+ ok: false;
19
+ code: "MISSION_NOT_FOUND" | "PHASE_NOT_FOUND" | "PHASE_ALREADY_DONE" | "ROADMAP_MISSING" | "STATE_MISSING";
20
+ message: string;
21
+ }
22
+ /**
23
+ * Mark `phaseId` as done in `phase_progress` and pick the next pending
24
+ * phase whose `depends_on` set is satisfied. When no eligible phase
25
+ * remains, set `cursor.active_phase = null`, mark `outcome: done`, and
26
+ * archive the mission dirs.
27
+ */
28
+ export declare function advancePhase(repoRoot: string, missionId: string, phaseId: string, now?: Date): AdvanceResult | AdvanceError;
29
+ /**
30
+ * Determine whether every linked task on a phase has graduated.
31
+ * Returns `false` when the phase has zero tasks (the operator has to
32
+ * `mission_advance --force` for empty phases — never auto-advance an
33
+ * empty phase silently).
34
+ */
35
+ export declare function allPhaseTasksDone(state: MissionState, phaseId: string, taskIsDone: (taskId: string) => boolean): boolean;
36
+ /**
37
+ * Resolve a roadmap phase by id from a mission's roadmap. Returns null
38
+ * when the id was deleted in a mid-mission roadmap edit (drift case).
39
+ */
40
+ export declare function lookupPhase(roadmap: MissionRoadmapFrontmatter, phaseId: string): MissionPhase | null;