aiwcli 0.10.2 → 0.11.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/bin/run.js +1 -1
- package/dist/commands/clear.d.ts +11 -6
- package/dist/commands/clear.js +229 -381
- package/dist/commands/init/index.d.ts +1 -17
- package/dist/commands/init/index.js +22 -107
- package/dist/lib/gitignore-manager.d.ts +32 -0
- package/dist/lib/gitignore-manager.js +141 -2
- package/dist/lib/template-installer.d.ts +7 -12
- package/dist/lib/template-installer.js +69 -193
- package/dist/lib/template-settings-reconstructor.d.ts +35 -0
- package/dist/lib/template-settings-reconstructor.js +130 -0
- package/dist/templates/CLAUDE.md +8 -8
- package/dist/templates/_shared/.claude/commands/handoff-resume.md +64 -0
- package/dist/templates/_shared/.claude/commands/handoff.md +16 -10
- package/dist/templates/_shared/.claude/settings.json +7 -7
- package/dist/templates/_shared/hooks-ts/_utils/git-state.ts +2 -0
- package/dist/templates/_shared/hooks-ts/archive_plan.ts +159 -0
- package/dist/templates/_shared/hooks-ts/context_monitor.ts +147 -0
- package/dist/templates/_shared/hooks-ts/file-suggestion.ts +130 -0
- package/dist/templates/_shared/hooks-ts/pre_compact.ts +49 -0
- package/dist/templates/_shared/hooks-ts/session_end.ts +104 -0
- package/dist/templates/_shared/hooks-ts/session_start.ts +144 -0
- package/dist/templates/_shared/hooks-ts/task_create_capture.ts +48 -0
- package/dist/templates/_shared/hooks-ts/task_update_capture.ts +74 -0
- package/dist/templates/_shared/hooks-ts/user_prompt_submit.ts +83 -0
- package/dist/templates/_shared/lib-ts/CLAUDE.md +318 -0
- package/dist/templates/_shared/lib-ts/base/atomic-write.ts +138 -0
- package/dist/templates/_shared/lib-ts/base/constants.ts +306 -0
- package/dist/templates/_shared/lib-ts/base/git-state.ts +58 -0
- package/dist/templates/_shared/lib-ts/base/hook-utils.ts +439 -0
- package/dist/templates/_shared/lib-ts/base/inference.ts +252 -0
- package/dist/templates/_shared/lib-ts/base/logger.ts +250 -0
- package/dist/templates/_shared/lib-ts/base/state-io.ts +116 -0
- package/dist/templates/_shared/lib-ts/base/stop-words.ts +184 -0
- package/dist/templates/_shared/lib-ts/base/subprocess-utils.ts +162 -0
- package/dist/templates/_shared/lib-ts/base/utils.ts +184 -0
- package/dist/templates/_shared/lib-ts/context/context-formatter.ts +438 -0
- package/dist/templates/_shared/lib-ts/context/context-selector.ts +515 -0
- package/dist/templates/_shared/lib-ts/context/context-store.ts +707 -0
- package/dist/templates/_shared/lib-ts/context/plan-manager.ts +316 -0
- package/dist/templates/_shared/lib-ts/context/task-tracker.ts +185 -0
- package/dist/templates/_shared/lib-ts/handoff/document-generator.ts +216 -0
- package/dist/templates/_shared/lib-ts/handoff/handoff-reader.ts +159 -0
- package/dist/templates/_shared/lib-ts/package.json +21 -0
- package/dist/templates/_shared/lib-ts/templates/formatters.ts +104 -0
- package/dist/templates/_shared/{lib/templates/plan_context.py → lib-ts/templates/plan-context.ts} +14 -22
- package/dist/templates/_shared/lib-ts/tsconfig.json +13 -0
- package/dist/templates/_shared/lib-ts/types.ts +164 -0
- package/dist/templates/_shared/scripts/resolve_context.ts +24 -0
- package/dist/templates/_shared/scripts/resume_handoff.ts +321 -0
- package/dist/templates/_shared/scripts/save_handoff.ts +359 -0
- package/dist/templates/_shared/scripts/status_line.ts +733 -0
- package/dist/templates/cc-native/.claude/settings.json +175 -185
- package/dist/templates/cc-native/TEMPLATE-SCHEMA.md +15 -17
- package/dist/templates/cc-native/_cc-native/agents/ARCH-EVOLUTION.md +63 -0
- package/dist/templates/cc-native/_cc-native/agents/ARCH-PATTERNS.md +62 -0
- package/dist/templates/cc-native/_cc-native/agents/ARCH-STRUCTURE.md +63 -0
- package/dist/templates/cc-native/_cc-native/agents/{ASSUMPTION-CHAIN-TRACER.md → ASSUMPTION-TRACER.md} +6 -10
- package/dist/templates/cc-native/_cc-native/agents/CLARITY-AUDITOR.md +6 -10
- package/dist/templates/cc-native/_cc-native/agents/CLAUDE.md +74 -3
- package/dist/templates/cc-native/_cc-native/agents/COMPLETENESS-FEASIBILITY.md +67 -0
- package/dist/templates/cc-native/_cc-native/agents/COMPLETENESS-GAPS.md +71 -0
- package/dist/templates/cc-native/_cc-native/agents/COMPLETENESS-ORDERING.md +63 -0
- package/dist/templates/cc-native/_cc-native/agents/CONSTRAINT-VALIDATOR.md +73 -0
- package/dist/templates/cc-native/_cc-native/agents/DESIGN-ADR-VALIDATOR.md +62 -0
- package/dist/templates/cc-native/_cc-native/agents/DESIGN-SCALE-MATCHER.md +65 -0
- package/dist/templates/cc-native/_cc-native/agents/DEVILS-ADVOCATE.md +6 -9
- package/dist/templates/cc-native/_cc-native/agents/DOCUMENTATION-PHILOSOPHY.md +87 -0
- package/dist/templates/cc-native/_cc-native/agents/HANDOFF-READINESS.md +5 -9
- package/dist/templates/cc-native/_cc-native/agents/{HIDDEN-COMPLEXITY-DETECTOR.md → HIDDEN-COMPLEXITY.md} +6 -10
- package/dist/templates/cc-native/_cc-native/agents/INCREMENTAL-DELIVERY.md +67 -0
- package/dist/templates/cc-native/_cc-native/agents/PLAN-ORCHESTRATOR.md +91 -18
- package/dist/templates/cc-native/_cc-native/agents/RISK-DEPENDENCY.md +63 -0
- package/dist/templates/cc-native/_cc-native/agents/RISK-FMEA.md +67 -0
- package/dist/templates/cc-native/_cc-native/agents/RISK-PREMORTEM.md +72 -0
- package/dist/templates/cc-native/_cc-native/agents/RISK-REVERSIBILITY.md +75 -0
- package/dist/templates/cc-native/_cc-native/agents/SCOPE-BOUNDARY.md +78 -0
- package/dist/templates/cc-native/_cc-native/agents/SIMPLICITY-GUARDIAN.md +5 -9
- package/dist/templates/cc-native/_cc-native/agents/SKEPTIC.md +16 -12
- package/dist/templates/cc-native/_cc-native/agents/TESTDRIVEN-BEHAVIOR-AUDITOR.md +62 -0
- package/dist/templates/cc-native/_cc-native/agents/TESTDRIVEN-CHARACTERIZATION.md +72 -0
- package/dist/templates/cc-native/_cc-native/agents/TESTDRIVEN-FIRST-VALIDATOR.md +62 -0
- package/dist/templates/cc-native/_cc-native/agents/TESTDRIVEN-PYRAMID-ANALYZER.md +62 -0
- package/dist/templates/cc-native/_cc-native/agents/TRADEOFF-COSTS.md +68 -0
- package/dist/templates/cc-native/_cc-native/agents/TRADEOFF-STAKEHOLDERS.md +66 -0
- package/dist/templates/cc-native/_cc-native/agents/VERIFY-COVERAGE.md +75 -0
- package/dist/templates/cc-native/_cc-native/agents/VERIFY-STRENGTH.md +70 -0
- package/dist/templates/cc-native/_cc-native/hooks/CLAUDE.md +109 -135
- package/dist/templates/cc-native/_cc-native/hooks/add_plan_context.ts +119 -0
- package/dist/templates/cc-native/_cc-native/hooks/cc-native-plan-review.ts +921 -0
- package/dist/templates/cc-native/_cc-native/hooks/plan_questions_early.ts +61 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/aggregate-agents.ts +157 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/artifacts.ts +709 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/cc-native-state.ts +199 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/cli-output-parser.ts +124 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/config.ts +57 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/constants.ts +83 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/debug.ts +80 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/index.ts +119 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/json-parser.ts +162 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/nul +3 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/orchestrator.ts +249 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/agent.ts +155 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/codex.ts +130 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/gemini.ts +106 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/index.ts +10 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/types.ts +23 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/state.ts +243 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/tsconfig.json +18 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/types.ts +310 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/verdict.ts +72 -0
- package/dist/templates/cc-native/_cc-native/plan-review.config.json +12 -16
- package/oclif.manifest.json +1 -1
- package/package.json +1 -1
- package/dist/lib/template-merger.d.ts +0 -47
- package/dist/lib/template-merger.js +0 -162
- package/dist/templates/_shared/hooks/__init__.py +0 -16
- package/dist/templates/_shared/hooks/__pycache__/__init__.cpython-313.pyc +0 -0
- package/dist/templates/_shared/hooks/__pycache__/archive_plan.cpython-313.pyc +0 -0
- package/dist/templates/_shared/hooks/__pycache__/context_enforcer.cpython-313.pyc +0 -0
- package/dist/templates/_shared/hooks/__pycache__/context_monitor.cpython-313.pyc +0 -0
- package/dist/templates/_shared/hooks/__pycache__/file-suggestion.cpython-313.pyc +0 -0
- package/dist/templates/_shared/hooks/__pycache__/pre_compact.cpython-313.pyc +0 -0
- package/dist/templates/_shared/hooks/__pycache__/session_end.cpython-313.pyc +0 -0
- package/dist/templates/_shared/hooks/__pycache__/session_start.cpython-313.pyc +0 -0
- package/dist/templates/_shared/hooks/__pycache__/task_create_atomicity.cpython-313.pyc +0 -0
- package/dist/templates/_shared/hooks/__pycache__/task_create_capture.cpython-313.pyc +0 -0
- package/dist/templates/_shared/hooks/__pycache__/task_update_capture.cpython-313.pyc +0 -0
- package/dist/templates/_shared/hooks/__pycache__/user_prompt_submit.cpython-313.pyc +0 -0
- package/dist/templates/_shared/hooks/archive_plan.py +0 -169
- package/dist/templates/_shared/hooks/context_monitor.py +0 -270
- package/dist/templates/_shared/hooks/file-suggestion.py +0 -215
- package/dist/templates/_shared/hooks/pre_compact.py +0 -104
- package/dist/templates/_shared/hooks/session_end.py +0 -173
- package/dist/templates/_shared/hooks/session_start.py +0 -206
- package/dist/templates/_shared/hooks/task_create_capture.py +0 -108
- package/dist/templates/_shared/hooks/task_update_capture.py +0 -145
- package/dist/templates/_shared/hooks/user_prompt_submit.py +0 -139
- package/dist/templates/_shared/lib/__init__.py +0 -1
- package/dist/templates/_shared/lib/__pycache__/__init__.cpython-313.pyc +0 -0
- package/dist/templates/_shared/lib/base/__init__.py +0 -65
- package/dist/templates/_shared/lib/base/__pycache__/__init__.cpython-313.pyc +0 -0
- package/dist/templates/_shared/lib/base/__pycache__/atomic_write.cpython-313.pyc +0 -0
- package/dist/templates/_shared/lib/base/__pycache__/constants.cpython-313.pyc +0 -0
- package/dist/templates/_shared/lib/base/__pycache__/hook_utils.cpython-313.pyc +0 -0
- package/dist/templates/_shared/lib/base/__pycache__/inference.cpython-313.pyc +0 -0
- package/dist/templates/_shared/lib/base/__pycache__/logger.cpython-313.pyc +0 -0
- package/dist/templates/_shared/lib/base/__pycache__/stop_words.cpython-313.pyc +0 -0
- package/dist/templates/_shared/lib/base/__pycache__/subprocess_utils.cpython-313.pyc +0 -0
- package/dist/templates/_shared/lib/base/__pycache__/utils.cpython-313.pyc +0 -0
- package/dist/templates/_shared/lib/base/atomic_write.py +0 -180
- package/dist/templates/_shared/lib/base/constants.py +0 -358
- package/dist/templates/_shared/lib/base/hook_utils.py +0 -341
- package/dist/templates/_shared/lib/base/inference.py +0 -318
- package/dist/templates/_shared/lib/base/logger.py +0 -291
- package/dist/templates/_shared/lib/base/stop_words.py +0 -213
- package/dist/templates/_shared/lib/base/subprocess_utils.py +0 -46
- package/dist/templates/_shared/lib/base/utils.py +0 -242
- package/dist/templates/_shared/lib/context/__init__.py +0 -102
- package/dist/templates/_shared/lib/context/__pycache__/__init__.cpython-313.pyc +0 -0
- package/dist/templates/_shared/lib/context/__pycache__/cache.cpython-313.pyc +0 -0
- package/dist/templates/_shared/lib/context/__pycache__/context_extractor.cpython-313.pyc +0 -0
- package/dist/templates/_shared/lib/context/__pycache__/context_formatter.cpython-313.pyc +0 -0
- package/dist/templates/_shared/lib/context/__pycache__/context_manager.cpython-313.pyc +0 -0
- package/dist/templates/_shared/lib/context/__pycache__/context_selector.cpython-313.pyc +0 -0
- package/dist/templates/_shared/lib/context/__pycache__/context_store.cpython-313.pyc +0 -0
- package/dist/templates/_shared/lib/context/__pycache__/discovery.cpython-313.pyc +0 -0
- package/dist/templates/_shared/lib/context/__pycache__/event_log.cpython-313.pyc +0 -0
- package/dist/templates/_shared/lib/context/__pycache__/plan_archive.cpython-313.pyc +0 -0
- package/dist/templates/_shared/lib/context/__pycache__/plan_manager.cpython-313.pyc +0 -0
- package/dist/templates/_shared/lib/context/__pycache__/task_sync.cpython-313.pyc +0 -0
- package/dist/templates/_shared/lib/context/__pycache__/task_tracker.cpython-313.pyc +0 -0
- package/dist/templates/_shared/lib/context/context_formatter.py +0 -317
- package/dist/templates/_shared/lib/context/context_selector.py +0 -508
- package/dist/templates/_shared/lib/context/context_store.py +0 -653
- package/dist/templates/_shared/lib/context/plan_manager.py +0 -204
- package/dist/templates/_shared/lib/context/task_tracker.py +0 -188
- package/dist/templates/_shared/lib/handoff/__init__.py +0 -22
- package/dist/templates/_shared/lib/handoff/__pycache__/__init__.cpython-313.pyc +0 -0
- package/dist/templates/_shared/lib/handoff/__pycache__/document_generator.cpython-313.pyc +0 -0
- package/dist/templates/_shared/lib/handoff/document_generator.py +0 -278
- package/dist/templates/_shared/lib/templates/README.md +0 -206
- package/dist/templates/_shared/lib/templates/__init__.py +0 -36
- package/dist/templates/_shared/lib/templates/__pycache__/__init__.cpython-313.pyc +0 -0
- package/dist/templates/_shared/lib/templates/__pycache__/formatters.cpython-313.pyc +0 -0
- package/dist/templates/_shared/lib/templates/__pycache__/persona_questions.cpython-313.pyc +0 -0
- package/dist/templates/_shared/lib/templates/__pycache__/plan_context.cpython-313.pyc +0 -0
- package/dist/templates/_shared/lib/templates/formatters.py +0 -146
- package/dist/templates/_shared/scripts/__pycache__/save_handoff.cpython-313.pyc +0 -0
- package/dist/templates/_shared/scripts/__pycache__/status_line.cpython-313.pyc +0 -0
- package/dist/templates/_shared/scripts/save_handoff.py +0 -357
- package/dist/templates/_shared/scripts/status_line.py +0 -701
- package/dist/templates/cc-native/.claude/commands/cc-native/fresh-perspective.md +0 -8
- package/dist/templates/cc-native/.windsurf/workflows/cc-native/fresh-perspective.md +0 -8
- package/dist/templates/cc-native/MIGRATION.md +0 -86
- package/dist/templates/cc-native/_cc-native/agents/ACCESSIBILITY-TESTER.md +0 -79
- package/dist/templates/cc-native/_cc-native/agents/ARCHITECT-REVIEWER.md +0 -48
- package/dist/templates/cc-native/_cc-native/agents/CODE-REVIEWER.md +0 -70
- package/dist/templates/cc-native/_cc-native/agents/COMPLETENESS-CHECKER.md +0 -59
- package/dist/templates/cc-native/_cc-native/agents/CONTEXT-EXTRACTOR.md +0 -92
- package/dist/templates/cc-native/_cc-native/agents/DOCUMENTATION-REVIEWER.md +0 -51
- package/dist/templates/cc-native/_cc-native/agents/FEASIBILITY-ANALYST.md +0 -57
- package/dist/templates/cc-native/_cc-native/agents/FRESH-PERSPECTIVE.md +0 -54
- package/dist/templates/cc-native/_cc-native/agents/INCENTIVE-MAPPER.md +0 -61
- package/dist/templates/cc-native/_cc-native/agents/PENETRATION-TESTER.md +0 -79
- package/dist/templates/cc-native/_cc-native/agents/PERFORMANCE-ENGINEER.md +0 -75
- package/dist/templates/cc-native/_cc-native/agents/PRECEDENT-FINDER.md +0 -70
- package/dist/templates/cc-native/_cc-native/agents/REVERSIBILITY-ANALYST.md +0 -61
- package/dist/templates/cc-native/_cc-native/agents/RISK-ASSESSOR.md +0 -58
- package/dist/templates/cc-native/_cc-native/agents/SECOND-ORDER-ANALYST.md +0 -61
- package/dist/templates/cc-native/_cc-native/agents/STAKEHOLDER-ADVOCATE.md +0 -55
- package/dist/templates/cc-native/_cc-native/agents/TRADE-OFF-ILLUMINATOR.md +0 -204
- package/dist/templates/cc-native/_cc-native/hooks/__pycache__/add_plan_context.cpython-313.pyc +0 -0
- package/dist/templates/cc-native/_cc-native/hooks/__pycache__/cc-native-plan-review.cpython-313.pyc +0 -0
- package/dist/templates/cc-native/_cc-native/hooks/__pycache__/mark_questions_asked.cpython-313.pyc +0 -0
- package/dist/templates/cc-native/_cc-native/hooks/__pycache__/plan_accepted.cpython-313.pyc +0 -0
- package/dist/templates/cc-native/_cc-native/hooks/__pycache__/plan_questions_early.cpython-313.pyc +0 -0
- package/dist/templates/cc-native/_cc-native/hooks/__pycache__/suggest-fresh-perspective.cpython-313.pyc +0 -0
- package/dist/templates/cc-native/_cc-native/hooks/add_plan_context.py +0 -130
- package/dist/templates/cc-native/_cc-native/hooks/cc-native-plan-review.py +0 -869
- package/dist/templates/cc-native/_cc-native/hooks/plan_questions_early.py +0 -81
- package/dist/templates/cc-native/_cc-native/hooks/suggest-fresh-perspective.py +0 -340
- package/dist/templates/cc-native/_cc-native/lib/CLAUDE.md +0 -265
- package/dist/templates/cc-native/_cc-native/lib/__init__.py +0 -53
- package/dist/templates/cc-native/_cc-native/lib/__pycache__/__init__.cpython-313.pyc +0 -0
- package/dist/templates/cc-native/_cc-native/lib/__pycache__/atomic_write.cpython-313.pyc +0 -0
- package/dist/templates/cc-native/_cc-native/lib/__pycache__/constants.cpython-313.pyc +0 -0
- package/dist/templates/cc-native/_cc-native/lib/__pycache__/debug.cpython-313.pyc +0 -0
- package/dist/templates/cc-native/_cc-native/lib/__pycache__/orchestrator.cpython-313.pyc +0 -0
- package/dist/templates/cc-native/_cc-native/lib/__pycache__/state.cpython-313.pyc +0 -0
- package/dist/templates/cc-native/_cc-native/lib/__pycache__/utils.cpython-313.pyc +0 -0
- package/dist/templates/cc-native/_cc-native/lib/constants.py +0 -45
- package/dist/templates/cc-native/_cc-native/lib/debug.py +0 -139
- package/dist/templates/cc-native/_cc-native/lib/orchestrator.py +0 -362
- package/dist/templates/cc-native/_cc-native/lib/reviewers/__init__.py +0 -28
- package/dist/templates/cc-native/_cc-native/lib/reviewers/__pycache__/__init__.cpython-313.pyc +0 -0
- package/dist/templates/cc-native/_cc-native/lib/reviewers/__pycache__/agent.cpython-313.pyc +0 -0
- package/dist/templates/cc-native/_cc-native/lib/reviewers/__pycache__/base.cpython-313.pyc +0 -0
- package/dist/templates/cc-native/_cc-native/lib/reviewers/__pycache__/codex.cpython-313.pyc +0 -0
- package/dist/templates/cc-native/_cc-native/lib/reviewers/__pycache__/gemini.cpython-313.pyc +0 -0
- package/dist/templates/cc-native/_cc-native/lib/reviewers/agent.py +0 -215
- package/dist/templates/cc-native/_cc-native/lib/reviewers/base.py +0 -88
- package/dist/templates/cc-native/_cc-native/lib/reviewers/codex.py +0 -124
- package/dist/templates/cc-native/_cc-native/lib/reviewers/gemini.py +0 -108
- package/dist/templates/cc-native/_cc-native/lib/state.py +0 -268
- package/dist/templates/cc-native/_cc-native/lib/utils.py +0 -1027
- package/dist/templates/cc-native/_cc-native/scripts/__pycache__/aggregate_agents.cpython-313.pyc +0 -0
- package/dist/templates/cc-native/_cc-native/scripts/aggregate_agents.py +0 -168
- package/dist/templates/cc-native/_cc-native/workflows/fresh-perspective.md +0 -134
|
@@ -0,0 +1,216 @@
|
|
|
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 crypto from "node:crypto";
|
|
10
|
+
import * as fs from "node:fs";
|
|
11
|
+
import * as path from "node:path";
|
|
12
|
+
|
|
13
|
+
import { atomicWrite } from "../base/atomic-write.js";
|
|
14
|
+
import { getContextDir, getContextHandoffsDir } from "../base/constants.js";
|
|
15
|
+
import { logError, logInfo } from "../base/logger.js";
|
|
16
|
+
import { nowIso } from "../base/utils.js";
|
|
17
|
+
import { getContext, saveState as _saveState } from "../context/context-store.js";
|
|
18
|
+
import { getTasks } from "../context/task-tracker.js";
|
|
19
|
+
import { formatContinuationHeader, formatReason, renderTaskList } from "../templates/formatters.js";
|
|
20
|
+
import type { HandoffDocument, Task as _Task } from "../types.js";
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Generate and save a handoff document for a context.
|
|
24
|
+
* See SPEC.md §12.2
|
|
25
|
+
*/
|
|
26
|
+
export function generateHandoffDocument(
|
|
27
|
+
contextId: string,
|
|
28
|
+
reason = "low_context",
|
|
29
|
+
workSummary = "",
|
|
30
|
+
nextSteps?: string[],
|
|
31
|
+
importantNotes?: string[],
|
|
32
|
+
completedThisSession?: string[],
|
|
33
|
+
projectRoot?: string,
|
|
34
|
+
): HandoffDocument | null {
|
|
35
|
+
const context = getContext(contextId, projectRoot);
|
|
36
|
+
if (!context) {
|
|
37
|
+
logError("handoff", `Context '${contextId}' not found`);
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Generate session ID
|
|
42
|
+
const sessionId = crypto.randomUUID().slice(0, 8);
|
|
43
|
+
|
|
44
|
+
// Get pending tasks from state.json
|
|
45
|
+
const allTasks = getTasks(contextId, projectRoot);
|
|
46
|
+
const pendingTasks = allTasks.filter(
|
|
47
|
+
t => t.status === "pending" || t.status === "in_progress" || t.status === "blocked",
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
// Build document
|
|
51
|
+
const now = nowIso();
|
|
52
|
+
const contextDir = getContextDir(contextId, projectRoot);
|
|
53
|
+
|
|
54
|
+
const doc: HandoffDocument = {
|
|
55
|
+
context_id: contextId,
|
|
56
|
+
context_summary: context.summary,
|
|
57
|
+
session_id: sessionId,
|
|
58
|
+
reason,
|
|
59
|
+
created_at: now,
|
|
60
|
+
plan_path: context.plan_path,
|
|
61
|
+
context_folder: contextDir,
|
|
62
|
+
events_log_path: path.join(contextDir, "state.json"),
|
|
63
|
+
active_tasks: pendingTasks,
|
|
64
|
+
completed_tasks_this_session: (completedThisSession ?? []).map(s => ({ subject: s })),
|
|
65
|
+
work_summary: workSummary,
|
|
66
|
+
next_steps: nextSteps ?? [],
|
|
67
|
+
important_notes: importantNotes ?? [],
|
|
68
|
+
file_path: null,
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
// Compute file path BEFORE rendering markdown
|
|
72
|
+
const handoffsDir = getContextHandoffsDir(contextId, projectRoot);
|
|
73
|
+
fs.mkdirSync(handoffsDir, { recursive: true });
|
|
74
|
+
|
|
75
|
+
const d = new Date();
|
|
76
|
+
const dateStr = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
|
|
77
|
+
const filename = `${dateStr}-session-${sessionId}.md`;
|
|
78
|
+
const filePath = path.join(handoffsDir, filename);
|
|
79
|
+
|
|
80
|
+
// Set file_path on doc BEFORE rendering markdown
|
|
81
|
+
doc.file_path = filePath;
|
|
82
|
+
|
|
83
|
+
// Generate markdown content
|
|
84
|
+
const markdown = renderHandoffMarkdown(doc);
|
|
85
|
+
|
|
86
|
+
// Save to handoffs folder
|
|
87
|
+
const [success, error] = atomicWrite(filePath, markdown);
|
|
88
|
+
if (!success) {
|
|
89
|
+
logError("handoff", `Failed to write handoff document: ${error}`);
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
logInfo("handoff", `Created handoff document: ${filePath}`);
|
|
94
|
+
return doc;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Render handoff document as markdown.
|
|
99
|
+
*/
|
|
100
|
+
function renderHandoffMarkdown(doc: HandoffDocument): string {
|
|
101
|
+
const lines: string[] = [
|
|
102
|
+
formatContinuationHeader("handoff", doc.context_id),
|
|
103
|
+
"",
|
|
104
|
+
`**Created**: ${doc.created_at}`,
|
|
105
|
+
`**Context ID**: ${doc.context_id}`,
|
|
106
|
+
`**Session ID**: ${doc.session_id}`,
|
|
107
|
+
`**Reason**: ${formatReason(doc.reason)}`,
|
|
108
|
+
"",
|
|
109
|
+
"## Links",
|
|
110
|
+
"",
|
|
111
|
+
];
|
|
112
|
+
|
|
113
|
+
// Plan link
|
|
114
|
+
if (doc.plan_path) {
|
|
115
|
+
const planName = path.basename(doc.plan_path);
|
|
116
|
+
lines.push(`- **Plan**: [${planName}](${doc.plan_path})`);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
lines.push(
|
|
120
|
+
`- **Context Folder**: \`${doc.context_folder}\``,
|
|
121
|
+
`- **Events Log**: \`${doc.events_log_path}\``,
|
|
122
|
+
"",
|
|
123
|
+
"## Current State",
|
|
124
|
+
"",
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
// Active tasks
|
|
128
|
+
lines.push(renderTaskList(doc.active_tasks, "Active Tasks", true).trimEnd(), "");
|
|
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
|
+
}
|
|
138
|
+
|
|
139
|
+
// Work summary
|
|
140
|
+
if (doc.work_summary) {
|
|
141
|
+
lines.push("## Context Summary", "", doc.work_summary, "");
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Next steps
|
|
145
|
+
if (doc.next_steps.length > 0) {
|
|
146
|
+
lines.push("## Next Steps", "");
|
|
147
|
+
for (let i = 0; i < doc.next_steps.length; i++) {
|
|
148
|
+
lines.push(`${i + 1}. ${doc.next_steps[i]}`);
|
|
149
|
+
}
|
|
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
|
+
|
|
161
|
+
lines.push("");
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Continuation prompt
|
|
165
|
+
lines.push(
|
|
166
|
+
"---",
|
|
167
|
+
"",
|
|
168
|
+
"**Continuation Prompt**:",
|
|
169
|
+
"```",
|
|
170
|
+
`Continue working on context "${doc.context_id}".`,
|
|
171
|
+
"",
|
|
172
|
+
`Handoff document: ${doc.file_path ?? "See above"}`,
|
|
173
|
+
"",
|
|
174
|
+
"Read the handoff document, restore tasks with TaskCreate, and continue implementation.",
|
|
175
|
+
"```",
|
|
176
|
+
);
|
|
177
|
+
|
|
178
|
+
return lines.join("\n");
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Generate the prompt to paste into new session for continuation.
|
|
183
|
+
* See SPEC.md §12.3
|
|
184
|
+
*/
|
|
185
|
+
export function getHandoffContinuationPrompt(doc: HandoffDocument): string {
|
|
186
|
+
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.`;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Generate system reminder for low context warning.
|
|
191
|
+
* See SPEC.md §12.4
|
|
192
|
+
*/
|
|
193
|
+
export function getLowContextWarning(contextRemainingPercent: number, contextId: string): string {
|
|
194
|
+
return `<system-reminder>
|
|
195
|
+
## LOW CONTEXT WARNING (${contextRemainingPercent}% remaining)
|
|
196
|
+
|
|
197
|
+
Your context window is running low. Please:
|
|
198
|
+
|
|
199
|
+
1. **Finish current task** if 1-2 steps away, OR save current progress
|
|
200
|
+
2. **Create handoff document** by calling:
|
|
201
|
+
\`\`\`python
|
|
202
|
+
from _shared.lib.handoff import generate_handoff_document
|
|
203
|
+
doc = generate_handoff_document(
|
|
204
|
+
context_id="${contextId}",
|
|
205
|
+
reason="low_context",
|
|
206
|
+
work_summary="<describe current work>",
|
|
207
|
+
next_steps=["<step 1>", "<step 2>"],
|
|
208
|
+
important_notes=["<key decision 1>"]
|
|
209
|
+
)
|
|
210
|
+
\`\`\`
|
|
211
|
+
3. **Ask permission** to clear and paste continuation prompt
|
|
212
|
+
|
|
213
|
+
After creating handoff, ask the user:
|
|
214
|
+
"Context is low. I've created a handoff document. May I clear and continue in a new session?"
|
|
215
|
+
</system-reminder>`;
|
|
216
|
+
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Handoff reader utilities for programmatic resume.
|
|
3
|
+
*
|
|
4
|
+
* Provides functions to find, read, and parse handoff folders
|
|
5
|
+
* created by save_handoff.ts. Used by resume_handoff.ts script
|
|
6
|
+
* and potentially by session_start hooks.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import * as fs from "node:fs";
|
|
10
|
+
import * as path from "node:path";
|
|
11
|
+
|
|
12
|
+
import { getContextHandoffsDir } from "../base/constants.js";
|
|
13
|
+
import { getContext } from "../context/context-store.js";
|
|
14
|
+
import type { HandoffSections } from "../types.js";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Find the most recent handoff folder for a context.
|
|
18
|
+
* Lists subdirectories in the handoffs dir, sorts by name
|
|
19
|
+
* (YYYY-MM-DD-HHMM format ensures lexicographic = chronological).
|
|
20
|
+
* Returns full path to most recent folder, or null.
|
|
21
|
+
*/
|
|
22
|
+
export function findLatestHandoff(contextId: string, projectRoot?: string): null | string {
|
|
23
|
+
const handoffsDir = getContextHandoffsDir(contextId, projectRoot);
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
if (!fs.existsSync(handoffsDir)) return null;
|
|
27
|
+
const entries = fs.readdirSync(handoffsDir, { withFileTypes: true })
|
|
28
|
+
.filter(e => e.isDirectory())
|
|
29
|
+
.map(e => e.name)
|
|
30
|
+
.sort();
|
|
31
|
+
|
|
32
|
+
if (entries.length === 0) return null;
|
|
33
|
+
return path.join(handoffsDir, entries.at(-1)!);
|
|
34
|
+
} catch {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Read all section files from a handoff folder, structured by priority.
|
|
41
|
+
* Returns content for each file (null if missing/unreadable).
|
|
42
|
+
*/
|
|
43
|
+
export function readHandoffSections(handoffFolder: string): HandoffSections {
|
|
44
|
+
const fileMap: Record<keyof HandoffSections, string> = {
|
|
45
|
+
index: "index.md",
|
|
46
|
+
deadEnds: "dead-ends.md",
|
|
47
|
+
pending: "pending.md",
|
|
48
|
+
plan: "plan.md",
|
|
49
|
+
decisions: "decisions.md",
|
|
50
|
+
completedWork: "completed-work.md",
|
|
51
|
+
context: "context.md",
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const sections: HandoffSections = {
|
|
55
|
+
index: null,
|
|
56
|
+
deadEnds: null,
|
|
57
|
+
pending: null,
|
|
58
|
+
plan: null,
|
|
59
|
+
decisions: null,
|
|
60
|
+
completedWork: null,
|
|
61
|
+
context: null,
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
for (const [key, filename] of Object.entries(fileMap)) {
|
|
65
|
+
const filePath = path.join(handoffFolder, filename);
|
|
66
|
+
try {
|
|
67
|
+
if (fs.existsSync(filePath)) {
|
|
68
|
+
sections[key as keyof HandoffSections] = fs.readFileSync(filePath, "utf8");
|
|
69
|
+
}
|
|
70
|
+
} catch {
|
|
71
|
+
// graceful — leave as null
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return sections;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Parse the handoff folder name to extract creation timestamp.
|
|
80
|
+
* Expects YYYY-MM-DD-HHMM format (with optional -N suffix for collisions).
|
|
81
|
+
*/
|
|
82
|
+
export function getHandoffTimestamp(handoffFolder: string): Date | null {
|
|
83
|
+
const basename = path.basename(handoffFolder);
|
|
84
|
+
// Match YYYY-MM-DD-HHMM with optional collision suffix
|
|
85
|
+
const match = basename.match(/^(\d{4})-(\d{2})-(\d{2})-(\d{2})(\d{2})/);
|
|
86
|
+
if (!match) return null;
|
|
87
|
+
|
|
88
|
+
const [, year, month, day, hour, minute] = match;
|
|
89
|
+
const date = new Date(
|
|
90
|
+
Number.parseInt(year!, 10),
|
|
91
|
+
Number.parseInt(month!, 10) - 1,
|
|
92
|
+
Number.parseInt(day!, 10),
|
|
93
|
+
Number.parseInt(hour!, 10),
|
|
94
|
+
Number.parseInt(minute!, 10),
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
return isNaN(date.getTime()) ? null : date;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Get the plan path referenced by a handoff.
|
|
102
|
+
* First checks plan.md frontmatter for plan_path, then falls back
|
|
103
|
+
* to the context state's plan_path.
|
|
104
|
+
*/
|
|
105
|
+
export function getHandoffPlanReference(
|
|
106
|
+
handoffFolder: string,
|
|
107
|
+
contextId: string,
|
|
108
|
+
projectRoot?: string,
|
|
109
|
+
): null | string {
|
|
110
|
+
// Try plan.md frontmatter
|
|
111
|
+
const planMdPath = path.join(handoffFolder, "plan.md");
|
|
112
|
+
try {
|
|
113
|
+
if (fs.existsSync(planMdPath)) {
|
|
114
|
+
const content = fs.readFileSync(planMdPath, "utf8");
|
|
115
|
+
const frontmatter = parseFrontmatter(content);
|
|
116
|
+
if (frontmatter["plan_path"]) {
|
|
117
|
+
const pp = frontmatter["plan_path"];
|
|
118
|
+
if (fs.existsSync(pp)) return pp;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
} catch {
|
|
122
|
+
// fall through to context state
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Fall back to context state
|
|
126
|
+
try {
|
|
127
|
+
const context = getContext(contextId, projectRoot);
|
|
128
|
+
if (context?.plan_path && fs.existsSync(context.plan_path)) {
|
|
129
|
+
return context.plan_path;
|
|
130
|
+
}
|
|
131
|
+
} catch {
|
|
132
|
+
// ignore
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Parse YAML-style frontmatter from markdown content.
|
|
140
|
+
* Returns key-value pairs from the --- block.
|
|
141
|
+
*/
|
|
142
|
+
function parseFrontmatter(content: string): Record<string, string> {
|
|
143
|
+
const frontmatter: Record<string, string> = {};
|
|
144
|
+
if (!content.startsWith("---")) return frontmatter;
|
|
145
|
+
|
|
146
|
+
const parts = content.split("---", 3);
|
|
147
|
+
if (parts.length < 3) return frontmatter;
|
|
148
|
+
|
|
149
|
+
for (const line of parts[1]!.trim().split("\n")) {
|
|
150
|
+
const colonIdx = line.indexOf(":");
|
|
151
|
+
if (colonIdx !== -1) {
|
|
152
|
+
const key = line.slice(0, colonIdx).trim();
|
|
153
|
+
const value = line.slice(colonIdx + 1).trim();
|
|
154
|
+
frontmatter[key] = value;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return frontmatter;
|
|
159
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "lib-ts-tests",
|
|
3
|
+
"private": true,
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"test": "mocha",
|
|
7
|
+
"test:unit": "mocha '__tests__/base/**/*.test.ts' '__tests__/templates/**/*.test.ts'",
|
|
8
|
+
"test:contract": "mocha '__tests__/context/**/*.test.ts' '__tests__/handoff/**/*.test.ts'",
|
|
9
|
+
"test:integration": "mocha '__tests__/integration/**/*.test.ts'",
|
|
10
|
+
"test:parity": "mocha '__tests__/integration/python-parity.test.ts'",
|
|
11
|
+
"fixtures": "python __tests__/fixtures/generate_fixtures.py"
|
|
12
|
+
},
|
|
13
|
+
"devDependencies": {
|
|
14
|
+
"mocha": "^10.0.0",
|
|
15
|
+
"chai": "^5.0.0",
|
|
16
|
+
"@types/mocha": "^10.0.0",
|
|
17
|
+
"@types/sinon": "^17.0.0",
|
|
18
|
+
"sinon": "^17.0.0",
|
|
19
|
+
"typescript": "^5.0.0"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formatters for context management templates.
|
|
3
|
+
* Constants and helpers for consistent formatting across hooks and display.
|
|
4
|
+
* See SPEC.md §13
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { Task } from "../types.js";
|
|
8
|
+
|
|
9
|
+
// §13.1 — Legacy mode display mapping (used by handoff/document_generator)
|
|
10
|
+
export const LEGACY_MODE_MAP: Record<string, string> = {
|
|
11
|
+
planning: "[Planning]",
|
|
12
|
+
pending_implementation: "[Plan Ready]",
|
|
13
|
+
implementing: "[Implementing]",
|
|
14
|
+
none: "",
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
// §13.2 — Status icon mapping
|
|
18
|
+
export const STATUS_ICONS: Record<string, string> = {
|
|
19
|
+
pending: "⬜",
|
|
20
|
+
in_progress: "🔄",
|
|
21
|
+
blocked: "🚫",
|
|
22
|
+
completed: "✅",
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export function getModeDisplay(mode: string): string {
|
|
26
|
+
return LEGACY_MODE_MAP[mode] ?? "";
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function getStatusIcon(status: string): string {
|
|
30
|
+
return STATUS_ICONS[status] ?? "⬜";
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// §13.3 — Task rendering
|
|
34
|
+
export function renderTaskItem(
|
|
35
|
+
task: Record<string, any> | Task,
|
|
36
|
+
showDescription = true,
|
|
37
|
+
maxDescriptionLength = 100,
|
|
38
|
+
): string {
|
|
39
|
+
const status = (task as any).status ?? "pending";
|
|
40
|
+
const subject = (task as any).subject ?? "";
|
|
41
|
+
const description = (task as any).description ?? "";
|
|
42
|
+
|
|
43
|
+
const icon = getStatusIcon(status);
|
|
44
|
+
const statusText = `[${status.toUpperCase()}]`;
|
|
45
|
+
const line = `- ${icon} ${statusText} ${subject}`;
|
|
46
|
+
|
|
47
|
+
if (showDescription && description) {
|
|
48
|
+
let truncated = description.slice(0, maxDescriptionLength);
|
|
49
|
+
if (description.length > maxDescriptionLength) {
|
|
50
|
+
truncated += "...";
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return `${line}\n - ${truncated}`;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return line;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function renderTaskList(
|
|
60
|
+
tasks: Array<Record<string, any> | Task>,
|
|
61
|
+
header = "Active Tasks",
|
|
62
|
+
showDescription = true,
|
|
63
|
+
): string {
|
|
64
|
+
const lines = [`### ${header}`, ""];
|
|
65
|
+
|
|
66
|
+
if (tasks.length === 0) {
|
|
67
|
+
lines.push("No active tasks.");
|
|
68
|
+
} else {
|
|
69
|
+
for (const task of tasks) {
|
|
70
|
+
lines.push(renderTaskItem(task, showDescription));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
lines.push("");
|
|
75
|
+
return lines.join("\n");
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// §13.4 — Continuation headers
|
|
79
|
+
const CONTINUATION_HEADERS: Record<string, (id: string) => string> = {
|
|
80
|
+
context: (id) => `## CONTINUING CONTEXT: ${id}`,
|
|
81
|
+
resuming: (id) => `## RESUMING FROM HANDOFF: ${id}`,
|
|
82
|
+
implementing: (id) => `## CONTINUING IMPLEMENTATION: ${id}`,
|
|
83
|
+
handoff: (id) => `# Session Handoff: ${id}`,
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export function formatContinuationHeader(
|
|
87
|
+
headerType: string,
|
|
88
|
+
contextId: string,
|
|
89
|
+
): string {
|
|
90
|
+
const fn = CONTINUATION_HEADERS[headerType];
|
|
91
|
+
return fn ? fn(contextId) : `## ${contextId}`;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// §13.5 — Reason formatting
|
|
95
|
+
export const REASON_MAP: Record<string, string> = {
|
|
96
|
+
low_context: "Context window running low",
|
|
97
|
+
user_requested: "User requested handoff",
|
|
98
|
+
error_recovery: "Error recovery",
|
|
99
|
+
session_end: "Session ending",
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
export function formatReason(reason: string): string {
|
|
103
|
+
return REASON_MAP[reason] ?? reason;
|
|
104
|
+
}
|
package/dist/templates/_shared/{lib/templates/plan_context.py → lib-ts/templates/plan-context.ts}
RENAMED
|
@@ -1,18 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Plan context templates for add_plan_context hook.
|
|
3
|
+
* See SPEC.md §13.6
|
|
4
|
+
*/
|
|
2
5
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
def get_evaluation_context_reminder() -> str:
|
|
9
|
-
"""Get the plan evaluation context reminder template.
|
|
10
|
-
|
|
11
|
-
Returns:
|
|
12
|
-
Formatted markdown reminder about adding evaluation context
|
|
13
|
-
"""
|
|
14
|
-
return """
|
|
15
|
-
## CRITICAL: Write This Plan for a Different Agent
|
|
6
|
+
export function getEvaluationContextReminder(): string {
|
|
7
|
+
return `## CRITICAL: Write This Plan for a Different Agent
|
|
16
8
|
|
|
17
9
|
The agent executing this plan has ZERO context from this conversation — no chat history, no memory of files you explored or research you did.
|
|
18
10
|
|
|
@@ -20,7 +12,7 @@ The agent executing this plan has ZERO context from this conversation — no cha
|
|
|
20
12
|
|
|
21
13
|
### Required Structure
|
|
22
14
|
|
|
23
|
-
|
|
15
|
+
\`\`\`
|
|
24
16
|
# Plan: <descriptive title>
|
|
25
17
|
|
|
26
18
|
## Background
|
|
@@ -31,10 +23,10 @@ What exactly to build/change
|
|
|
31
23
|
|
|
32
24
|
## Files
|
|
33
25
|
**Modify:**
|
|
34
|
-
-
|
|
26
|
+
- \`exact/path/to/file.py\` - What changes (reference line numbers or patterns)
|
|
35
27
|
|
|
36
28
|
**Reference:**
|
|
37
|
-
-
|
|
29
|
+
- \`exact/path/to/reference.py\` - Why relevant (e.g., "pattern to follow at lines 12-30")
|
|
38
30
|
|
|
39
31
|
## Steps
|
|
40
32
|
1. [Specific steps with function names, patterns, or code snippets]
|
|
@@ -47,7 +39,7 @@ What exactly to build/change
|
|
|
47
39
|
Decisions not written down are lost when this session ends. Update the nearest CLAUDE.md and MEMORY.md so the next session inherits what you learned.
|
|
48
40
|
|
|
49
41
|
**CLAUDE.md** (nearest to changed code — cascades to subdirectories):
|
|
50
|
-
-
|
|
42
|
+
- \`exact/path/to/CLAUDE.md\` — What to document
|
|
51
43
|
|
|
52
44
|
**What to write:**
|
|
53
45
|
- Architectural choices and why alternatives were rejected
|
|
@@ -55,7 +47,7 @@ Decisions not written down are lost when this session ends. Update the nearest C
|
|
|
55
47
|
- Workarounds with context on the underlying issue
|
|
56
48
|
- Patterns that prevent future mistakes
|
|
57
49
|
|
|
58
|
-
**Format:**
|
|
50
|
+
**Format:** \`## Topic\` / \`**Decision:** ...\` / \`**Rationale:** ...\`
|
|
59
51
|
|
|
60
52
|
**MEMORY.md** (cross-session learning for the AI agent):
|
|
61
53
|
- Insight that would prevent a future mistake (e.g., "hook X silently drops field Y")
|
|
@@ -63,11 +55,11 @@ Decisions not written down are lost when this session ends. Update the nearest C
|
|
|
63
55
|
**Include when:** Architectural decisions, non-obvious constraints, workarounds, or patterns discovered during implementation.
|
|
64
56
|
**Omit entries for:** Routine changes with no decisions (rename, formatting, dependency bump).
|
|
65
57
|
When in doubt, write it — a lean entry is better than a lost decision.
|
|
66
|
-
|
|
58
|
+
\`\`\`
|
|
67
59
|
|
|
68
60
|
### Self-Check
|
|
69
61
|
- [ ] Could I execute this if I forgot our entire conversation?
|
|
70
62
|
- [ ] Are file paths exact (not "the auth file")?
|
|
71
63
|
- [ ] Are implementation details specific (not "use the approach we discussed")?
|
|
72
|
-
- [ ] Do documentation entries capture decisions the next session would otherwise lose
|
|
73
|
-
|
|
64
|
+
- [ ] Do documentation entries capture decisions the next session would otherwise lose?`;
|
|
65
|
+
}
|