aiwcli 0.12.6 → 0.12.7
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/bin/dev.cmd +3 -3
- package/bin/dev.js +16 -16
- package/bin/run.cmd +3 -3
- package/bin/run.js +21 -21
- package/dist/commands/branch.js +7 -2
- package/dist/lib/bmad-installer.js +37 -37
- package/dist/lib/terminal.d.ts +2 -0
- package/dist/lib/terminal.js +57 -7
- package/dist/templates/CLAUDE.md +205 -205
- package/dist/templates/_shared/.claude/commands/handoff-resume.md +12 -12
- package/dist/templates/_shared/.claude/commands/handoff.md +12 -12
- package/dist/templates/_shared/.claude/settings.json +65 -65
- package/dist/templates/_shared/.codex/workflows/handoff.md +226 -226
- package/dist/templates/_shared/.windsurf/workflows/handoff.md +226 -226
- package/dist/templates/_shared/handoff-system/CLAUDE.md +421 -421
- package/dist/templates/_shared/handoff-system/lib/document-generator.ts +215 -215
- package/dist/templates/_shared/handoff-system/lib/handoff-reader.ts +158 -158
- package/dist/templates/_shared/handoff-system/scripts/resume_handoff.ts +373 -373
- package/dist/templates/_shared/handoff-system/scripts/save_handoff.ts +469 -469
- package/dist/templates/_shared/handoff-system/workflows/handoff-resume.md +66 -66
- package/dist/templates/_shared/handoff-system/workflows/handoff.md +254 -254
- package/dist/templates/_shared/hooks-ts/_utils/git-state.ts +2 -2
- package/dist/templates/_shared/hooks-ts/archive_plan.ts +159 -159
- package/dist/templates/_shared/hooks-ts/context_monitor.ts +147 -147
- package/dist/templates/_shared/hooks-ts/file-suggestion.ts +128 -128
- package/dist/templates/_shared/hooks-ts/pre_compact.ts +49 -49
- package/dist/templates/_shared/hooks-ts/session_end.ts +196 -196
- package/dist/templates/_shared/hooks-ts/session_start.ts +163 -163
- package/dist/templates/_shared/hooks-ts/task_create_capture.ts +48 -48
- package/dist/templates/_shared/hooks-ts/task_update_capture.ts +74 -74
- package/dist/templates/_shared/hooks-ts/user_prompt_submit.ts +93 -93
- package/dist/templates/_shared/lib-ts/CLAUDE.md +367 -367
- package/dist/templates/_shared/lib-ts/base/atomic-write.ts +138 -138
- package/dist/templates/_shared/lib-ts/base/constants.ts +303 -303
- package/dist/templates/_shared/lib-ts/base/git-state.ts +58 -58
- package/dist/templates/_shared/lib-ts/base/hook-utils.ts +582 -582
- package/dist/templates/_shared/lib-ts/base/inference.ts +301 -301
- package/dist/templates/_shared/lib-ts/base/logger.ts +247 -247
- package/dist/templates/_shared/lib-ts/base/state-io.ts +202 -202
- package/dist/templates/_shared/lib-ts/base/stop-words.ts +184 -184
- package/dist/templates/_shared/lib-ts/base/utils.ts +184 -184
- package/dist/templates/_shared/lib-ts/context/context-formatter.ts +566 -566
- package/dist/templates/_shared/lib-ts/context/context-selector.ts +524 -524
- package/dist/templates/_shared/lib-ts/context/context-store.ts +712 -712
- package/dist/templates/_shared/lib-ts/context/plan-manager.ts +312 -312
- package/dist/templates/_shared/lib-ts/context/task-tracker.ts +185 -185
- package/dist/templates/_shared/lib-ts/package.json +20 -20
- package/dist/templates/_shared/lib-ts/templates/formatters.ts +102 -102
- package/dist/templates/_shared/lib-ts/templates/plan-context.ts +58 -58
- package/dist/templates/_shared/lib-ts/tsconfig.json +13 -13
- package/dist/templates/_shared/lib-ts/types.ts +186 -186
- package/dist/templates/_shared/scripts/resolve_context.ts +33 -33
- package/dist/templates/_shared/scripts/status_line.ts +690 -690
- package/dist/templates/cc-native/.claude/commands/cc-native/rlm/ask.md +136 -136
- package/dist/templates/cc-native/.claude/commands/cc-native/rlm/index.md +21 -21
- package/dist/templates/cc-native/.claude/commands/cc-native/rlm/overview.md +56 -56
- package/dist/templates/cc-native/.claude/commands/cc-native/specdev.md +10 -10
- package/dist/templates/cc-native/.windsurf/workflows/cc-native/fix.md +8 -8
- package/dist/templates/cc-native/.windsurf/workflows/cc-native/implement.md +8 -8
- package/dist/templates/cc-native/.windsurf/workflows/cc-native/research.md +8 -8
- package/dist/templates/cc-native/CC-NATIVE-README.md +189 -189
- package/dist/templates/cc-native/TEMPLATE-SCHEMA.md +304 -304
- package/dist/templates/cc-native/_cc-native/agents/CLAUDE.md +143 -143
- package/dist/templates/cc-native/_cc-native/agents/PLAN-ORCHESTRATOR.md +213 -213
- package/dist/templates/cc-native/_cc-native/agents/plan-questions/PLAN-QUESTIONER.md +70 -70
- package/dist/templates/cc-native/_cc-native/cc-native.config.json +96 -96
- package/dist/templates/cc-native/_cc-native/hooks/CLAUDE.md +247 -247
- package/dist/templates/cc-native/_cc-native/hooks/cc-native-plan-review.ts +76 -76
- package/dist/templates/cc-native/_cc-native/hooks/enhance_plan_post_subagent.ts +54 -54
- package/dist/templates/cc-native/_cc-native/hooks/enhance_plan_post_write.ts +51 -51
- package/dist/templates/cc-native/_cc-native/hooks/mark_questions_asked.ts +53 -53
- package/dist/templates/cc-native/_cc-native/hooks/plan_questions_early.ts +61 -61
- package/dist/templates/cc-native/_cc-native/lib-ts/agent-selection.ts +163 -163
- package/dist/templates/cc-native/_cc-native/lib-ts/aggregate-agents.ts +156 -156
- package/dist/templates/cc-native/_cc-native/lib-ts/artifacts/format.ts +597 -597
- package/dist/templates/cc-native/_cc-native/lib-ts/artifacts/index.ts +26 -26
- package/dist/templates/cc-native/_cc-native/lib-ts/artifacts/tracker.ts +107 -107
- package/dist/templates/cc-native/_cc-native/lib-ts/artifacts/write.ts +119 -119
- package/dist/templates/cc-native/_cc-native/lib-ts/artifacts.ts +21 -21
- package/dist/templates/cc-native/_cc-native/lib-ts/cc-native-state.ts +319 -319
- package/dist/templates/cc-native/_cc-native/lib-ts/cli-output-parser.ts +144 -144
- package/dist/templates/cc-native/_cc-native/lib-ts/config.ts +57 -57
- package/dist/templates/cc-native/_cc-native/lib-ts/constants.ts +83 -83
- package/dist/templates/cc-native/_cc-native/lib-ts/corroboration.ts +119 -119
- package/dist/templates/cc-native/_cc-native/lib-ts/debug.ts +79 -79
- package/dist/templates/cc-native/_cc-native/lib-ts/graduation.ts +132 -132
- package/dist/templates/cc-native/_cc-native/lib-ts/index.ts +116 -116
- package/dist/templates/cc-native/_cc-native/lib-ts/json-parser.ts +168 -168
- package/dist/templates/cc-native/_cc-native/lib-ts/orchestrator.ts +70 -70
- package/dist/templates/cc-native/_cc-native/lib-ts/output-builder.ts +130 -130
- package/dist/templates/cc-native/_cc-native/lib-ts/plan-discovery.ts +80 -80
- package/dist/templates/cc-native/_cc-native/lib-ts/plan-enhancement.ts +41 -41
- package/dist/templates/cc-native/_cc-native/lib-ts/plan-questions.ts +101 -101
- package/dist/templates/cc-native/_cc-native/lib-ts/review-pipeline.ts +511 -511
- package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/agent.ts +71 -71
- package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/base/base-agent.ts +217 -217
- package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/index.ts +12 -12
- package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/providers/claude-agent.ts +66 -66
- package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/providers/codex-agent.ts +184 -184
- package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/providers/gemini-agent.ts +39 -39
- package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/providers/orchestrator-claude-agent.ts +196 -196
- package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/schemas.ts +201 -201
- package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/types.ts +21 -21
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/CLAUDE.md +480 -480
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/embedding-indexer.ts +287 -287
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/hyde.ts +148 -148
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/index.ts +54 -54
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/logger.ts +58 -58
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/ollama-client.ts +208 -208
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/retrieval-pipeline.ts +460 -460
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/transcript-indexer.ts +446 -446
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/transcript-loader.ts +280 -280
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/transcript-searcher.ts +274 -274
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/types.ts +201 -201
- package/dist/templates/cc-native/_cc-native/lib-ts/rlm/vector-store.ts +278 -278
- package/dist/templates/cc-native/_cc-native/lib-ts/settings.ts +184 -184
- package/dist/templates/cc-native/_cc-native/lib-ts/state.ts +275 -275
- package/dist/templates/cc-native/_cc-native/lib-ts/tsconfig.json +18 -18
- package/dist/templates/cc-native/_cc-native/lib-ts/types.ts +329 -329
- package/dist/templates/cc-native/_cc-native/lib-ts/verdict.ts +72 -72
- package/dist/templates/cc-native/_cc-native/workflows/specdev.md +9 -9
- package/oclif.manifest.json +1 -1
- package/package.json +108 -108
- package/dist/templates/cc-native/_cc-native/lib-ts/nul +0 -3
|
@@ -1,215 +1,215 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Handoff document generator for context-aware session management.
|
|
3
|
-
* See SPEC.md §12
|
|
4
|
-
*
|
|
5
|
-
* Creates structured handoff documents when a session needs to transfer
|
|
6
|
-
* work to a new session (typically due to context window limits).
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import * as fs from "node:fs";
|
|
10
|
-
import * as path from "node:path";
|
|
11
|
-
import * as crypto from "node:crypto";
|
|
12
|
-
import { getContextHandoffsDir, getContextDir } from "../base/constants.js";
|
|
13
|
-
import { atomicWrite } from "../base/atomic-write.js";
|
|
14
|
-
import { logInfo, logError } from "../base/logger.js";
|
|
15
|
-
import { nowIso } from "../base/utils.js";
|
|
16
|
-
import { getContext, saveState } from "../context/context-store.js";
|
|
17
|
-
import { getTasks } from "../context/task-tracker.js";
|
|
18
|
-
import { renderTaskList, formatContinuationHeader, formatReason } from "../templates/formatters.js";
|
|
19
|
-
import type { HandoffDocument, Task } from "../types.js";
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Generate and save a handoff document for a context.
|
|
23
|
-
* See SPEC.md §12.2
|
|
24
|
-
*/
|
|
25
|
-
export function generateHandoffDocument(
|
|
26
|
-
contextId: string,
|
|
27
|
-
reason = "low_context",
|
|
28
|
-
workSummary = "",
|
|
29
|
-
nextSteps?: string[],
|
|
30
|
-
importantNotes?: string[],
|
|
31
|
-
completedThisSession?: string[],
|
|
32
|
-
projectRoot?: string,
|
|
33
|
-
): HandoffDocument | null {
|
|
34
|
-
const context = getContext(contextId, projectRoot);
|
|
35
|
-
if (!context) {
|
|
36
|
-
logError("handoff", `Context '${contextId}' not found`);
|
|
37
|
-
return null;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// Generate session ID
|
|
41
|
-
const sessionId = crypto.randomUUID().slice(0, 8);
|
|
42
|
-
|
|
43
|
-
// Get pending tasks from state.json
|
|
44
|
-
const allTasks = getTasks(contextId, projectRoot);
|
|
45
|
-
const pendingTasks = allTasks.filter(
|
|
46
|
-
t => t.status === "pending" || t.status === "in_progress" || t.status === "blocked",
|
|
47
|
-
);
|
|
48
|
-
|
|
49
|
-
// Build document
|
|
50
|
-
const now = nowIso();
|
|
51
|
-
const contextDir = getContextDir(contextId, projectRoot);
|
|
52
|
-
|
|
53
|
-
const doc: HandoffDocument = {
|
|
54
|
-
context_id: contextId,
|
|
55
|
-
context_summary: context.summary,
|
|
56
|
-
session_id: sessionId,
|
|
57
|
-
reason,
|
|
58
|
-
created_at: now,
|
|
59
|
-
plan_path: context.plan_path,
|
|
60
|
-
context_folder: contextDir,
|
|
61
|
-
events_log_path: path.join(contextDir, "state.json"),
|
|
62
|
-
active_tasks: pendingTasks,
|
|
63
|
-
completed_tasks_this_session: (completedThisSession ?? []).map(s => ({ subject: s })),
|
|
64
|
-
work_summary: workSummary,
|
|
65
|
-
next_steps: nextSteps ?? [],
|
|
66
|
-
important_notes: importantNotes ?? [],
|
|
67
|
-
file_path: null,
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
// Compute file path BEFORE rendering markdown
|
|
71
|
-
const handoffsDir = getContextHandoffsDir(contextId, projectRoot);
|
|
72
|
-
fs.mkdirSync(handoffsDir, { recursive: true });
|
|
73
|
-
|
|
74
|
-
const d = new Date();
|
|
75
|
-
const dateStr = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
|
|
76
|
-
const filename = `${dateStr}-session-${sessionId}.md`;
|
|
77
|
-
const filePath = path.join(handoffsDir, filename);
|
|
78
|
-
|
|
79
|
-
// Set file_path on doc BEFORE rendering markdown
|
|
80
|
-
doc.file_path = filePath;
|
|
81
|
-
|
|
82
|
-
// Generate markdown content
|
|
83
|
-
const markdown = renderHandoffMarkdown(doc);
|
|
84
|
-
|
|
85
|
-
// Save to handoffs folder
|
|
86
|
-
const [success, error] = atomicWrite(filePath, markdown);
|
|
87
|
-
if (!success) {
|
|
88
|
-
logError("handoff", `Failed to write handoff document: ${error}`);
|
|
89
|
-
return null;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
logInfo("handoff", `Created handoff document: ${filePath}`);
|
|
93
|
-
return doc;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Render handoff document as markdown.
|
|
98
|
-
*/
|
|
99
|
-
function renderHandoffMarkdown(doc: HandoffDocument): string {
|
|
100
|
-
const lines: string[] = [
|
|
101
|
-
formatContinuationHeader("handoff", doc.context_id),
|
|
102
|
-
"",
|
|
103
|
-
`**Created**: ${doc.created_at}`,
|
|
104
|
-
`**Context ID**: ${doc.context_id}`,
|
|
105
|
-
`**Session ID**: ${doc.session_id}`,
|
|
106
|
-
`**Reason**: ${formatReason(doc.reason)}`,
|
|
107
|
-
"",
|
|
108
|
-
"## Links",
|
|
109
|
-
"",
|
|
110
|
-
];
|
|
111
|
-
|
|
112
|
-
// Plan link
|
|
113
|
-
if (doc.plan_path) {
|
|
114
|
-
const planName = path.basename(doc.plan_path);
|
|
115
|
-
lines.push(`- **Plan**: [${planName}](${doc.plan_path})`);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
lines.push(
|
|
119
|
-
`- **Context Folder**: \`${doc.context_folder}\``,
|
|
120
|
-
`- **Events Log**: \`${doc.events_log_path}\``,
|
|
121
|
-
"",
|
|
122
|
-
"## Current State",
|
|
123
|
-
"",
|
|
124
|
-
);
|
|
125
|
-
|
|
126
|
-
// Active tasks
|
|
127
|
-
lines.push(renderTaskList(doc.active_tasks, "Active Tasks", true).trimEnd());
|
|
128
|
-
lines.push("");
|
|
129
|
-
|
|
130
|
-
// Completed this session
|
|
131
|
-
if (doc.completed_tasks_this_session.length > 0) {
|
|
132
|
-
lines.push(renderTaskList(
|
|
133
|
-
doc.completed_tasks_this_session as any[],
|
|
134
|
-
"Completed This Session",
|
|
135
|
-
false,
|
|
136
|
-
).trimEnd());
|
|
137
|
-
lines.push("");
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// Work summary
|
|
141
|
-
if (doc.work_summary) {
|
|
142
|
-
lines.push("## Context Summary", "", doc.work_summary, "");
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// Next steps
|
|
146
|
-
if (doc.next_steps.length > 0) {
|
|
147
|
-
lines.push("## Next Steps", "");
|
|
148
|
-
for (let i = 0; i < doc.next_steps.length; i++) {
|
|
149
|
-
lines.push(`${i + 1}. ${doc.next_steps[i]}`);
|
|
150
|
-
}
|
|
151
|
-
lines.push("");
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
// Important notes
|
|
155
|
-
if (doc.important_notes.length > 0) {
|
|
156
|
-
lines.push("## Important Notes", "");
|
|
157
|
-
for (const note of doc.important_notes) {
|
|
158
|
-
lines.push(`- ${note}`);
|
|
159
|
-
}
|
|
160
|
-
lines.push("");
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
// Continuation prompt
|
|
164
|
-
lines.push(
|
|
165
|
-
"---",
|
|
166
|
-
"",
|
|
167
|
-
"**Continuation Prompt**:",
|
|
168
|
-
"```",
|
|
169
|
-
`Continue working on context "${doc.context_id}".`,
|
|
170
|
-
"",
|
|
171
|
-
`Handoff document: ${doc.file_path ?? "See above"}`,
|
|
172
|
-
"",
|
|
173
|
-
"Read the handoff document, restore tasks with TaskCreate, and continue implementation.",
|
|
174
|
-
"```",
|
|
175
|
-
);
|
|
176
|
-
|
|
177
|
-
return lines.join("\n");
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* Generate the prompt to paste into new session for continuation.
|
|
182
|
-
* See SPEC.md §12.3
|
|
183
|
-
*/
|
|
184
|
-
export function getHandoffContinuationPrompt(doc: HandoffDocument): string {
|
|
185
|
-
return `Continue working on context "${doc.context_id}".\n\nHandoff document: ${doc.file_path}\n\nRead the handoff document, restore tasks with TaskCreate, and continue implementation.`;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* Generate system reminder for low context warning.
|
|
190
|
-
* See SPEC.md §12.4
|
|
191
|
-
*/
|
|
192
|
-
export function getLowContextWarning(contextRemainingPercent: number, contextId: string): string {
|
|
193
|
-
return `<system-reminder>
|
|
194
|
-
## LOW CONTEXT WARNING (${contextRemainingPercent}% remaining)
|
|
195
|
-
|
|
196
|
-
Your context window is running low. Please:
|
|
197
|
-
|
|
198
|
-
1. **Finish current task** if 1-2 steps away, OR save current progress
|
|
199
|
-
2. **Create handoff document** by calling:
|
|
200
|
-
\`\`\`python
|
|
201
|
-
from _shared.lib.handoff import generate_handoff_document
|
|
202
|
-
doc = generate_handoff_document(
|
|
203
|
-
context_id="${contextId}",
|
|
204
|
-
reason="low_context",
|
|
205
|
-
work_summary="<describe current work>",
|
|
206
|
-
next_steps=["<step 1>", "<step 2>"],
|
|
207
|
-
important_notes=["<key decision 1>"]
|
|
208
|
-
)
|
|
209
|
-
\`\`\`
|
|
210
|
-
3. **Ask permission** to clear and paste continuation prompt
|
|
211
|
-
|
|
212
|
-
After creating handoff, ask the user:
|
|
213
|
-
"Context is low. I've created a handoff document. May I clear and continue in a new session?"
|
|
214
|
-
</system-reminder>`;
|
|
215
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Handoff document generator for context-aware session management.
|
|
3
|
+
* See SPEC.md §12
|
|
4
|
+
*
|
|
5
|
+
* Creates structured handoff documents when a session needs to transfer
|
|
6
|
+
* work to a new session (typically due to context window limits).
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import * as fs from "node:fs";
|
|
10
|
+
import * as path from "node:path";
|
|
11
|
+
import * as crypto from "node:crypto";
|
|
12
|
+
import { getContextHandoffsDir, getContextDir } from "../base/constants.js";
|
|
13
|
+
import { atomicWrite } from "../base/atomic-write.js";
|
|
14
|
+
import { logInfo, logError } from "../base/logger.js";
|
|
15
|
+
import { nowIso } from "../base/utils.js";
|
|
16
|
+
import { getContext, saveState } from "../context/context-store.js";
|
|
17
|
+
import { getTasks } from "../context/task-tracker.js";
|
|
18
|
+
import { renderTaskList, formatContinuationHeader, formatReason } from "../templates/formatters.js";
|
|
19
|
+
import type { HandoffDocument, Task } from "../types.js";
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Generate and save a handoff document for a context.
|
|
23
|
+
* See SPEC.md §12.2
|
|
24
|
+
*/
|
|
25
|
+
export function generateHandoffDocument(
|
|
26
|
+
contextId: string,
|
|
27
|
+
reason = "low_context",
|
|
28
|
+
workSummary = "",
|
|
29
|
+
nextSteps?: string[],
|
|
30
|
+
importantNotes?: string[],
|
|
31
|
+
completedThisSession?: string[],
|
|
32
|
+
projectRoot?: string,
|
|
33
|
+
): HandoffDocument | null {
|
|
34
|
+
const context = getContext(contextId, projectRoot);
|
|
35
|
+
if (!context) {
|
|
36
|
+
logError("handoff", `Context '${contextId}' not found`);
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Generate session ID
|
|
41
|
+
const sessionId = crypto.randomUUID().slice(0, 8);
|
|
42
|
+
|
|
43
|
+
// Get pending tasks from state.json
|
|
44
|
+
const allTasks = getTasks(contextId, projectRoot);
|
|
45
|
+
const pendingTasks = allTasks.filter(
|
|
46
|
+
t => t.status === "pending" || t.status === "in_progress" || t.status === "blocked",
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
// Build document
|
|
50
|
+
const now = nowIso();
|
|
51
|
+
const contextDir = getContextDir(contextId, projectRoot);
|
|
52
|
+
|
|
53
|
+
const doc: HandoffDocument = {
|
|
54
|
+
context_id: contextId,
|
|
55
|
+
context_summary: context.summary,
|
|
56
|
+
session_id: sessionId,
|
|
57
|
+
reason,
|
|
58
|
+
created_at: now,
|
|
59
|
+
plan_path: context.plan_path,
|
|
60
|
+
context_folder: contextDir,
|
|
61
|
+
events_log_path: path.join(contextDir, "state.json"),
|
|
62
|
+
active_tasks: pendingTasks,
|
|
63
|
+
completed_tasks_this_session: (completedThisSession ?? []).map(s => ({ subject: s })),
|
|
64
|
+
work_summary: workSummary,
|
|
65
|
+
next_steps: nextSteps ?? [],
|
|
66
|
+
important_notes: importantNotes ?? [],
|
|
67
|
+
file_path: null,
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
// Compute file path BEFORE rendering markdown
|
|
71
|
+
const handoffsDir = getContextHandoffsDir(contextId, projectRoot);
|
|
72
|
+
fs.mkdirSync(handoffsDir, { recursive: true });
|
|
73
|
+
|
|
74
|
+
const d = new Date();
|
|
75
|
+
const dateStr = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
|
|
76
|
+
const filename = `${dateStr}-session-${sessionId}.md`;
|
|
77
|
+
const filePath = path.join(handoffsDir, filename);
|
|
78
|
+
|
|
79
|
+
// Set file_path on doc BEFORE rendering markdown
|
|
80
|
+
doc.file_path = filePath;
|
|
81
|
+
|
|
82
|
+
// Generate markdown content
|
|
83
|
+
const markdown = renderHandoffMarkdown(doc);
|
|
84
|
+
|
|
85
|
+
// Save to handoffs folder
|
|
86
|
+
const [success, error] = atomicWrite(filePath, markdown);
|
|
87
|
+
if (!success) {
|
|
88
|
+
logError("handoff", `Failed to write handoff document: ${error}`);
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
logInfo("handoff", `Created handoff document: ${filePath}`);
|
|
93
|
+
return doc;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Render handoff document as markdown.
|
|
98
|
+
*/
|
|
99
|
+
function renderHandoffMarkdown(doc: HandoffDocument): string {
|
|
100
|
+
const lines: string[] = [
|
|
101
|
+
formatContinuationHeader("handoff", doc.context_id),
|
|
102
|
+
"",
|
|
103
|
+
`**Created**: ${doc.created_at}`,
|
|
104
|
+
`**Context ID**: ${doc.context_id}`,
|
|
105
|
+
`**Session ID**: ${doc.session_id}`,
|
|
106
|
+
`**Reason**: ${formatReason(doc.reason)}`,
|
|
107
|
+
"",
|
|
108
|
+
"## Links",
|
|
109
|
+
"",
|
|
110
|
+
];
|
|
111
|
+
|
|
112
|
+
// Plan link
|
|
113
|
+
if (doc.plan_path) {
|
|
114
|
+
const planName = path.basename(doc.plan_path);
|
|
115
|
+
lines.push(`- **Plan**: [${planName}](${doc.plan_path})`);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
lines.push(
|
|
119
|
+
`- **Context Folder**: \`${doc.context_folder}\``,
|
|
120
|
+
`- **Events Log**: \`${doc.events_log_path}\``,
|
|
121
|
+
"",
|
|
122
|
+
"## Current State",
|
|
123
|
+
"",
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
// Active tasks
|
|
127
|
+
lines.push(renderTaskList(doc.active_tasks, "Active Tasks", true).trimEnd());
|
|
128
|
+
lines.push("");
|
|
129
|
+
|
|
130
|
+
// Completed this session
|
|
131
|
+
if (doc.completed_tasks_this_session.length > 0) {
|
|
132
|
+
lines.push(renderTaskList(
|
|
133
|
+
doc.completed_tasks_this_session as any[],
|
|
134
|
+
"Completed This Session",
|
|
135
|
+
false,
|
|
136
|
+
).trimEnd());
|
|
137
|
+
lines.push("");
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Work summary
|
|
141
|
+
if (doc.work_summary) {
|
|
142
|
+
lines.push("## Context Summary", "", doc.work_summary, "");
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Next steps
|
|
146
|
+
if (doc.next_steps.length > 0) {
|
|
147
|
+
lines.push("## Next Steps", "");
|
|
148
|
+
for (let i = 0; i < doc.next_steps.length; i++) {
|
|
149
|
+
lines.push(`${i + 1}. ${doc.next_steps[i]}`);
|
|
150
|
+
}
|
|
151
|
+
lines.push("");
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Important notes
|
|
155
|
+
if (doc.important_notes.length > 0) {
|
|
156
|
+
lines.push("## Important Notes", "");
|
|
157
|
+
for (const note of doc.important_notes) {
|
|
158
|
+
lines.push(`- ${note}`);
|
|
159
|
+
}
|
|
160
|
+
lines.push("");
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Continuation prompt
|
|
164
|
+
lines.push(
|
|
165
|
+
"---",
|
|
166
|
+
"",
|
|
167
|
+
"**Continuation Prompt**:",
|
|
168
|
+
"```",
|
|
169
|
+
`Continue working on context "${doc.context_id}".`,
|
|
170
|
+
"",
|
|
171
|
+
`Handoff document: ${doc.file_path ?? "See above"}`,
|
|
172
|
+
"",
|
|
173
|
+
"Read the handoff document, restore tasks with TaskCreate, and continue implementation.",
|
|
174
|
+
"```",
|
|
175
|
+
);
|
|
176
|
+
|
|
177
|
+
return lines.join("\n");
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Generate the prompt to paste into new session for continuation.
|
|
182
|
+
* See SPEC.md §12.3
|
|
183
|
+
*/
|
|
184
|
+
export function getHandoffContinuationPrompt(doc: HandoffDocument): string {
|
|
185
|
+
return `Continue working on context "${doc.context_id}".\n\nHandoff document: ${doc.file_path}\n\nRead the handoff document, restore tasks with TaskCreate, and continue implementation.`;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Generate system reminder for low context warning.
|
|
190
|
+
* See SPEC.md §12.4
|
|
191
|
+
*/
|
|
192
|
+
export function getLowContextWarning(contextRemainingPercent: number, contextId: string): string {
|
|
193
|
+
return `<system-reminder>
|
|
194
|
+
## LOW CONTEXT WARNING (${contextRemainingPercent}% remaining)
|
|
195
|
+
|
|
196
|
+
Your context window is running low. Please:
|
|
197
|
+
|
|
198
|
+
1. **Finish current task** if 1-2 steps away, OR save current progress
|
|
199
|
+
2. **Create handoff document** by calling:
|
|
200
|
+
\`\`\`python
|
|
201
|
+
from _shared.lib.handoff import generate_handoff_document
|
|
202
|
+
doc = generate_handoff_document(
|
|
203
|
+
context_id="${contextId}",
|
|
204
|
+
reason="low_context",
|
|
205
|
+
work_summary="<describe current work>",
|
|
206
|
+
next_steps=["<step 1>", "<step 2>"],
|
|
207
|
+
important_notes=["<key decision 1>"]
|
|
208
|
+
)
|
|
209
|
+
\`\`\`
|
|
210
|
+
3. **Ask permission** to clear and paste continuation prompt
|
|
211
|
+
|
|
212
|
+
After creating handoff, ask the user:
|
|
213
|
+
"Context is low. I've created a handoff document. May I clear and continue in a new session?"
|
|
214
|
+
</system-reminder>`;
|
|
215
|
+
}
|