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,104 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* SessionEnd hook: Save session state, assign plan fields (fallback),
|
|
4
|
+
* stage has_plan/has_handoff for next session.
|
|
5
|
+
*/
|
|
6
|
+
import * as crypto from "node:crypto";
|
|
7
|
+
import * as fs from "node:fs";
|
|
8
|
+
|
|
9
|
+
import { getProjectRoot } from "../lib-ts/base/constants.js";
|
|
10
|
+
import { getGitState } from "../lib-ts/base/git-state.js";
|
|
11
|
+
import {
|
|
12
|
+
loadHookInput, logDebug, logDiagnostic, logError, logInfo, logWarn as _logWarn, runHook,
|
|
13
|
+
} from "../lib-ts/base/hook-utils.js";
|
|
14
|
+
import { nowIso } from "../lib-ts/base/utils.js";
|
|
15
|
+
import { getContextBySessionId, saveState } from "../lib-ts/context/context-store.js";
|
|
16
|
+
import {
|
|
17
|
+
extractPlanAnchors, findLatestPlan, generatePlanId, normalizePlanContent,
|
|
18
|
+
} from "../lib-ts/context/plan-manager.js";
|
|
19
|
+
|
|
20
|
+
function main(): void {
|
|
21
|
+
const payload = loadHookInput();
|
|
22
|
+
if (!payload) return;
|
|
23
|
+
|
|
24
|
+
const sessionId = payload.session_id;
|
|
25
|
+
if (!sessionId) {
|
|
26
|
+
logDebug("session_end", "No session_id, skipping");
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const projectRoot = getProjectRoot(payload.cwd);
|
|
31
|
+
const source = payload.source ?? "unknown";
|
|
32
|
+
const permissionMode = payload.permission_mode ?? "";
|
|
33
|
+
|
|
34
|
+
const state = getContextBySessionId(sessionId, projectRoot);
|
|
35
|
+
if (!state) {
|
|
36
|
+
logDebug("session_end", `No context bound to session ${sessionId}`);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Capture git state
|
|
41
|
+
const gitState = getGitState(projectRoot);
|
|
42
|
+
|
|
43
|
+
// Save session metadata
|
|
44
|
+
state.last_session = {
|
|
45
|
+
session_id: sessionId,
|
|
46
|
+
save_reason: source,
|
|
47
|
+
saved_at: nowIso(),
|
|
48
|
+
transcript_path: payload.transcript_path ?? undefined,
|
|
49
|
+
git_state: gitState,
|
|
50
|
+
};
|
|
51
|
+
state.last_active = nowIso();
|
|
52
|
+
|
|
53
|
+
// Plan fallback assignment (skip in plan mode — rejected plans shouldn't stage)
|
|
54
|
+
if (permissionMode !== "plan") {
|
|
55
|
+
// Step 1: Assign plan fields if missing
|
|
56
|
+
if (!state.plan_hash) {
|
|
57
|
+
const latestPlanPath = findLatestPlan(state.id, projectRoot);
|
|
58
|
+
if (latestPlanPath) {
|
|
59
|
+
try {
|
|
60
|
+
const content = fs.readFileSync(latestPlanPath, "utf8");
|
|
61
|
+
const normalized = normalizePlanContent(content);
|
|
62
|
+
const planHash = crypto.createHash("sha256")
|
|
63
|
+
.update(normalized, "utf-8")
|
|
64
|
+
.digest("hex")
|
|
65
|
+
.slice(0, 12);
|
|
66
|
+
|
|
67
|
+
state.plan_hash = planHash;
|
|
68
|
+
state.plan_path = latestPlanPath;
|
|
69
|
+
state.plan_signature = content.slice(0, 200);
|
|
70
|
+
state.plan_id = generatePlanId();
|
|
71
|
+
state.plan_anchors = extractPlanAnchors(content);
|
|
72
|
+
state.plan_consumed = false;
|
|
73
|
+
|
|
74
|
+
logInfo("session_end", `Assigned plan fallback: hash=${planHash}, path=${latestPlanPath}`);
|
|
75
|
+
} catch (error) {
|
|
76
|
+
logError("session_end", `Failed to read plan: ${error}`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Step 2: Stage has_plan if conditions met
|
|
82
|
+
if (state.plan_hash && state.mode === "active" && !state.plan_consumed) {
|
|
83
|
+
state.mode = "has_plan";
|
|
84
|
+
logInfo("session_end", `Staged ${state.id}: active → has_plan`);
|
|
85
|
+
}
|
|
86
|
+
// If plan_consumed, skip — already consumed, don't re-stage
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Handoff staging (only if mode is still "active" — plan check may have changed it)
|
|
90
|
+
if (state.handoff_path && state.mode === "active" && !state.handoff_consumed) {
|
|
91
|
+
state.mode = "has_handoff";
|
|
92
|
+
logInfo("session_end", `Staged ${state.id}: active → has_handoff`);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Save final state
|
|
96
|
+
const [ok, err] = saveState(state.id, state, projectRoot);
|
|
97
|
+
if (ok) {
|
|
98
|
+
logDiagnostic("session_end", "saved", `${state.id} mode=${state.mode}`);
|
|
99
|
+
} else {
|
|
100
|
+
logError("session_end", `Failed to save state: ${err}`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
runHook(main, "session_end");
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* SessionStart hook: Restore context after /clear (plan/handoff) or compaction.
|
|
4
|
+
* Routes by source field to appropriate handler.
|
|
5
|
+
*/
|
|
6
|
+
import { getProjectRoot } from "../lib-ts/base/constants.js";
|
|
7
|
+
import {
|
|
8
|
+
emitContext, loadHookInput, logDebug,
|
|
9
|
+
logDiagnostic, logError as _logError, logInfo, runHook,
|
|
10
|
+
} from "../lib-ts/base/hook-utils.js";
|
|
11
|
+
import {
|
|
12
|
+
buildRestoreSections, formatHandoffContinuation, getModeDisplay,
|
|
13
|
+
} from "../lib-ts/context/context-formatter.js";
|
|
14
|
+
import {
|
|
15
|
+
bindSession, getAllContexts, getContextBySessionId, updateMode,
|
|
16
|
+
} from "../lib-ts/context/context-store.js";
|
|
17
|
+
import type { ContextState as _ContextState } from "../lib-ts/types.js";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Handle post-compaction restore: re-inject context that was lost during compaction.
|
|
21
|
+
* Plan content is inlined because Claude doesn't auto-paste after compact.
|
|
22
|
+
*/
|
|
23
|
+
function handleCompactRestore(sessionId: string, projectRoot: string): void {
|
|
24
|
+
const state = getContextBySessionId(sessionId, projectRoot);
|
|
25
|
+
if (!state) {
|
|
26
|
+
logDebug("session_start", `No context for session ${sessionId} (compact)`);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const sections: string[] = [
|
|
31
|
+
`## Resuming Context After Compaction: ${state.id}`,
|
|
32
|
+
"",
|
|
33
|
+
`**Summary:** ${state.summary}`,
|
|
34
|
+
`**Mode:** ${getModeDisplay(state.mode) || state.mode}`,
|
|
35
|
+
"",
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
// Inline plan = true (plan not auto-pasted after compact)
|
|
39
|
+
const restore = buildRestoreSections(state, projectRoot, true);
|
|
40
|
+
if (restore) sections.push(restore);
|
|
41
|
+
|
|
42
|
+
sections.push(
|
|
43
|
+
"",
|
|
44
|
+
"---",
|
|
45
|
+
"*Context was compacted to free up space. The above restores your working state.*",
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
emitContext(sections.join("\n"));
|
|
49
|
+
logInfo("session_start", `Compact restore for ${state.id}`);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Handle post-clear restore: find staged has_plan or has_handoff context,
|
|
54
|
+
* bind session, transition to active, inject context.
|
|
55
|
+
*/
|
|
56
|
+
function handleClearRestore(sessionId: string, projectRoot: string): void {
|
|
57
|
+
const allContexts = getAllContexts("active", projectRoot);
|
|
58
|
+
|
|
59
|
+
// Priority 1: has_plan contexts
|
|
60
|
+
const hasPlan = allContexts.filter(c => c.mode === "has_plan");
|
|
61
|
+
if (hasPlan.length > 0) {
|
|
62
|
+
// Pick most recently active (getAllContexts sorts by last_active desc)
|
|
63
|
+
const ctx = hasPlan[0]!;
|
|
64
|
+
|
|
65
|
+
bindSession(ctx.id, sessionId, projectRoot);
|
|
66
|
+
updateMode(ctx.id, "active", projectRoot, { plan_consumed: true });
|
|
67
|
+
|
|
68
|
+
logInfo("session_start", `Clear restore: ${ctx.id} has_plan → active (plan_consumed=true)`);
|
|
69
|
+
|
|
70
|
+
const sections: string[] = [
|
|
71
|
+
`## Resuming Context After Plan Clear: ${ctx.id}`,
|
|
72
|
+
"",
|
|
73
|
+
`**Summary:** ${ctx.summary}`,
|
|
74
|
+
`**Mode:** Active (Plan Restored)`,
|
|
75
|
+
"",
|
|
76
|
+
];
|
|
77
|
+
|
|
78
|
+
// inline_plan=false — Claude auto-pastes plan content after /clear
|
|
79
|
+
const restore = buildRestoreSections(ctx, projectRoot, false);
|
|
80
|
+
if (restore) sections.push(restore);
|
|
81
|
+
|
|
82
|
+
sections.push(
|
|
83
|
+
"",
|
|
84
|
+
"---",
|
|
85
|
+
"*Plan has been accepted. The plan content was auto-pasted above. Implement according to the plan.*",
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
emitContext(sections.join("\n"));
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Priority 2: has_handoff contexts
|
|
93
|
+
const hasHandoff = allContexts.filter(c => c.mode === "has_handoff");
|
|
94
|
+
if (hasHandoff.length > 0) {
|
|
95
|
+
const ctx = hasHandoff[0]!;
|
|
96
|
+
|
|
97
|
+
bindSession(ctx.id, sessionId, projectRoot);
|
|
98
|
+
updateMode(ctx.id, "active", projectRoot, { handoff_consumed: true });
|
|
99
|
+
|
|
100
|
+
logInfo("session_start", `Clear restore: ${ctx.id} has_handoff → active (handoff_consumed=true)`);
|
|
101
|
+
|
|
102
|
+
const handoffContent = formatHandoffContinuation(ctx, projectRoot);
|
|
103
|
+
emitContext(handoffContent);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Nothing to restore
|
|
108
|
+
logDebug("session_start", "No has_plan or has_handoff contexts found");
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function main(): void {
|
|
112
|
+
const payload = loadHookInput();
|
|
113
|
+
if (!payload) return;
|
|
114
|
+
|
|
115
|
+
const sessionId = payload.session_id;
|
|
116
|
+
if (!sessionId) {
|
|
117
|
+
logDebug("session_start", "No session_id");
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const projectRoot = getProjectRoot(payload.cwd);
|
|
122
|
+
const source = payload.source ?? "";
|
|
123
|
+
|
|
124
|
+
logDiagnostic("session_start", "entry", `source=${source}, session=${sessionId}`);
|
|
125
|
+
|
|
126
|
+
switch (source) {
|
|
127
|
+
case "clear": {
|
|
128
|
+
handleClearRestore(sessionId, projectRoot);
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
case "compact": {
|
|
133
|
+
handleCompactRestore(sessionId, projectRoot);
|
|
134
|
+
break;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
default: {
|
|
138
|
+
logDebug("session_start", `Unhandled source: ${source}`);
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
runHook(main, "session_start");
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* PostToolUse:TaskCreate hook: Persist Claude's TaskCreate calls to state.json.
|
|
4
|
+
*/
|
|
5
|
+
import { getProjectRoot } from "../lib-ts/base/constants.js";
|
|
6
|
+
import {
|
|
7
|
+
checkSkipPersistence, getToolInput, loadHookInput, logDebug,
|
|
8
|
+
logError, logInfo, logWarn, runHook, validateHookEvent,
|
|
9
|
+
} from "../lib-ts/base/hook-utils.js";
|
|
10
|
+
import { getContextBySessionId } from "../lib-ts/context/context-store.js";
|
|
11
|
+
import { addTask } from "../lib-ts/context/task-tracker.js";
|
|
12
|
+
|
|
13
|
+
function main(): void {
|
|
14
|
+
const payload = loadHookInput();
|
|
15
|
+
if (!payload) return;
|
|
16
|
+
if (!validateHookEvent(payload, "PostToolUse", "TaskCreate")) return;
|
|
17
|
+
|
|
18
|
+
const toolInput = getToolInput(payload);
|
|
19
|
+
if (!toolInput) return;
|
|
20
|
+
if (checkSkipPersistence(payload, "task_create_capture")) return;
|
|
21
|
+
|
|
22
|
+
const projectRoot = getProjectRoot(payload.cwd);
|
|
23
|
+
const sessionId = payload.session_id ?? "unknown";
|
|
24
|
+
|
|
25
|
+
const state = getContextBySessionId(sessionId, projectRoot);
|
|
26
|
+
if (!state) {
|
|
27
|
+
logDebug("task_create_capture", `No context for session ${sessionId}`);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const subject = toolInput.subject as string | undefined;
|
|
32
|
+
if (!subject) {
|
|
33
|
+
logWarn("task_create_capture", "TaskCreate missing subject field");
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const description = (toolInput.description as string) ?? "";
|
|
38
|
+
const activeForm = (toolInput.activeForm as string) ?? "";
|
|
39
|
+
|
|
40
|
+
const task = addTask(state.id, subject, description, activeForm, sessionId, projectRoot);
|
|
41
|
+
if (task) {
|
|
42
|
+
logInfo("task_create_capture", `Persisted task ${task.id}: ${subject}`);
|
|
43
|
+
} else {
|
|
44
|
+
logError("task_create_capture", `Failed to persist task: ${subject}`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
runHook(main, "task_create_capture");
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* PostToolUse:TaskUpdate hook: Persist Claude's TaskUpdate calls to state.json.
|
|
4
|
+
* Maps Claude's ephemeral task IDs to persistent aiw-N IDs.
|
|
5
|
+
*/
|
|
6
|
+
import { getProjectRoot } from "../lib-ts/base/constants.js";
|
|
7
|
+
import {
|
|
8
|
+
checkSkipPersistence, getToolInput, loadHookInput, logDebug,
|
|
9
|
+
logError as _logError, logInfo, logWarn, runHook, validateHookEvent,
|
|
10
|
+
} from "../lib-ts/base/hook-utils.js";
|
|
11
|
+
import { getContextBySessionId } from "../lib-ts/context/context-store.js";
|
|
12
|
+
import { deleteTask, updateTask } from "../lib-ts/context/task-tracker.js";
|
|
13
|
+
|
|
14
|
+
function main(): void {
|
|
15
|
+
const payload = loadHookInput();
|
|
16
|
+
if (!payload) return;
|
|
17
|
+
if (!validateHookEvent(payload, "PostToolUse", "TaskUpdate")) return;
|
|
18
|
+
|
|
19
|
+
const toolInput = getToolInput(payload);
|
|
20
|
+
if (!toolInput) return;
|
|
21
|
+
if (checkSkipPersistence(payload, "task_update_capture")) return;
|
|
22
|
+
|
|
23
|
+
const projectRoot = getProjectRoot(payload.cwd);
|
|
24
|
+
const sessionId = payload.session_id ?? "unknown";
|
|
25
|
+
|
|
26
|
+
const state = getContextBySessionId(sessionId, projectRoot);
|
|
27
|
+
if (!state) {
|
|
28
|
+
logDebug("task_update_capture", `No context for session ${sessionId}`);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const claudeTaskId = toolInput.taskId as string | undefined;
|
|
33
|
+
if (!claudeTaskId) {
|
|
34
|
+
logWarn("task_update_capture", "TaskUpdate missing taskId");
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Map Claude's ephemeral ID to persistent ID
|
|
39
|
+
const metadata = (toolInput.metadata ?? {}) as Record<string, any>;
|
|
40
|
+
const persistentId = (metadata.persistent_id as string) ?? `aiw-${claudeTaskId}`;
|
|
41
|
+
|
|
42
|
+
const status = toolInput.status as string | undefined;
|
|
43
|
+
|
|
44
|
+
if (status === "deleted") {
|
|
45
|
+
const ok = deleteTask(state.id, persistentId, projectRoot);
|
|
46
|
+
if (ok) {
|
|
47
|
+
logInfo("task_update_capture", `Deleted task ${persistentId}`);
|
|
48
|
+
} else {
|
|
49
|
+
logWarn("task_update_capture", `Task ${persistentId} not found for deletion`);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (status) {
|
|
56
|
+
const opts: Record<string, any> = { status };
|
|
57
|
+
if (metadata.evidence) opts.evidence = metadata.evidence;
|
|
58
|
+
if (metadata.work_summary) opts.work_summary = metadata.work_summary;
|
|
59
|
+
if (metadata.files_changed && Array.isArray(metadata.files_changed)) {
|
|
60
|
+
opts.files_changed = metadata.files_changed;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
opts.session_id = sessionId;
|
|
64
|
+
|
|
65
|
+
const ok = updateTask(state.id, persistentId, opts, projectRoot);
|
|
66
|
+
if (ok) {
|
|
67
|
+
logInfo("task_update_capture", `Updated task ${persistentId} → ${status}`);
|
|
68
|
+
} else {
|
|
69
|
+
logWarn("task_update_capture", `Task ${persistentId} not found for update`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
runHook(main, "task_update_capture");
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* UserPromptSubmit hook: Context enforcement — ensures every prompt belongs
|
|
4
|
+
* to a tracked context. The most complex shared hook.
|
|
5
|
+
*
|
|
6
|
+
* Uses emitContext() for output — context text is passed via hookSpecificOutput JSON.
|
|
7
|
+
* Catches BlockRequest and exits with code 2 to block the prompt.
|
|
8
|
+
*/
|
|
9
|
+
import { getProjectRoot } from "../lib-ts/base/constants.js";
|
|
10
|
+
import {
|
|
11
|
+
emitContext, hookLog, loadHookInput, logBlocking, logDebug, logDiagnostic as _logDiagnostic, logInfo, logWarn as _logWarn, runHookAsync,
|
|
12
|
+
} from "../lib-ts/base/hook-utils.js";
|
|
13
|
+
import { BlockRequest, determineContext } from "../lib-ts/context/context-selector.js";
|
|
14
|
+
import {
|
|
15
|
+
bindSession, getContextBySessionId, maybeActivate, saveState,
|
|
16
|
+
} from "../lib-ts/context/context-store.js";
|
|
17
|
+
|
|
18
|
+
async function asyncMain(): Promise<void> {
|
|
19
|
+
const payload = loadHookInput();
|
|
20
|
+
if (!payload) return;
|
|
21
|
+
|
|
22
|
+
const prompt = (payload as any).prompt as string | undefined;
|
|
23
|
+
const sessionId = payload.session_id;
|
|
24
|
+
const permissionMode = payload.permission_mode ?? "";
|
|
25
|
+
const projectRoot = getProjectRoot(payload.cwd);
|
|
26
|
+
|
|
27
|
+
if (!sessionId) {
|
|
28
|
+
logDebug("user_prompt_submit", "No session_id");
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const outputs: string[] = [];
|
|
33
|
+
|
|
34
|
+
// Check if session is already bound to a context
|
|
35
|
+
const existingCtx = getContextBySessionId(sessionId, projectRoot);
|
|
36
|
+
|
|
37
|
+
if (existingCtx) {
|
|
38
|
+
// Returning user — context already bound (stderr: false to avoid "hook error" display)
|
|
39
|
+
try {
|
|
40
|
+
maybeActivate(existingCtx.id, permissionMode, projectRoot, "user_prompt_submit");
|
|
41
|
+
} catch (error) {
|
|
42
|
+
hookLog("warn", "user_prompt_submit", `maybeActivate failed (non-critical): ${error}`, { stderr: false });
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
hookLog("debug", "user_prompt_submit", `Session bound to ${existingCtx.id}`, { stderr: false });
|
|
46
|
+
} else if (prompt) {
|
|
47
|
+
// First prompt — need to determine context
|
|
48
|
+
try {
|
|
49
|
+
const [contextId, method, outputText] = await determineContext(prompt, sessionId, projectRoot);
|
|
50
|
+
|
|
51
|
+
if (contextId) {
|
|
52
|
+
bindSession(contextId, sessionId, projectRoot);
|
|
53
|
+
maybeActivate(contextId, permissionMode, projectRoot, "user_prompt_submit");
|
|
54
|
+
|
|
55
|
+
// Clear handoff_path after binding (prevents re-injection)
|
|
56
|
+
const state = getContextBySessionId(sessionId, projectRoot);
|
|
57
|
+
if (state && state.handoff_path) {
|
|
58
|
+
state.handoff_path = null;
|
|
59
|
+
saveState(state.id, state, projectRoot);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
logInfo("user_prompt_submit", `Context ${contextId} via ${method}`);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (outputText) {
|
|
66
|
+
outputs.push(outputText);
|
|
67
|
+
}
|
|
68
|
+
} catch (error) {
|
|
69
|
+
if (error instanceof BlockRequest) {
|
|
70
|
+
logBlocking("user_prompt_submit", (error as Error).message);
|
|
71
|
+
process.exit(2); // Block the prompt
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
throw error; // Re-throw unexpected errors
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (outputs.length > 0) {
|
|
79
|
+
emitContext(outputs.join("\n\n"));
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
runHookAsync(asyncMain, "user_prompt_submit");
|