Skip to content

Commit 42171dd

Browse files
committed
elaborate: remove han keep dependency & improve intent state management
Detailed analysis of the han CLI dependency (155 refs across 32 files) covering both `han keep` (branch-scoped KV storage) and `han parse` (YAML/JSON utilities). Proposes file-based state in .ai-dlc/{slug}/state/ as a transparent, git-native replacement. Identifies 5 state management improvements: single source of truth, explicit phase machine, reduced parsing overhead, validation, and observability. https://claude.ai/code/session_01DzBkZ55Ls5oxB3RfJML4WT
1 parent 725a2c8 commit 42171dd

File tree

1 file changed

+260
-0
lines changed
  • .ai-dlc/remove-hankeep-improve-state

1 file changed

+260
-0
lines changed
Lines changed: 260 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,260 @@
1+
---
2+
workflow: default
3+
created: 2026-03-14
4+
status: active
5+
---
6+
7+
# Intent: Remove Han Keep Dependency & Improve Intent State Management
8+
9+
## Problem Statement
10+
11+
AI-DLC currently has a **hard dependency on the `han` CLI** for two distinct capabilities:
12+
13+
### 1. `han keep` — Branch-scoped ephemeral key-value storage
14+
Used across 32 files (hooks, skills, hats, docs) for persisting state that survives context resets but is scoped to a git branch. This is the **core state layer** of AI-DLC.
15+
16+
**What it does:** Stores key-value pairs scoped to a git branch. Under the hood, `han keep` uses git notes or a similar git-native mechanism to attach arbitrary data to branches without polluting the working tree.
17+
18+
**Current usage (155 references across 32 files):**
19+
- `han keep save <key> <content>` — persist ephemeral state
20+
- `han keep load <key> --quiet` — retrieve state
21+
- `han keep delete <key>` — remove a key
22+
- `han keep list` — list all keys
23+
- `han keep clear --branch` — clear all state for a branch
24+
- `han keep load --branch <branch> <key>` — cross-branch state access
25+
26+
**Keys managed:**
27+
| Key | Scope | Purpose |
28+
|-----|-------|---------|
29+
| `iteration.json` | intent branch | Hat, iteration count, workflow, status, unitStates |
30+
| `intent-slug` | intent branch | Pointer to current intent directory |
31+
| `scratchpad.md` | unit branch | Progress notes and learnings from previous bolts |
32+
| `blockers.md` | unit branch | Documented blockers |
33+
| `current-plan.md` | unit branch | Planner's tactical output |
34+
| `completion-criteria.md` | intent branch | Success criteria (also on filesystem) |
35+
| `next-prompt.md` | unit branch | Continuation prompt for next iteration |
36+
| `operation-status.json` | intent branch | Operation phase tracking |
37+
| `reflection-status.json` | intent branch | Reflection phase tracking |
38+
| `providers.json` | intent branch | Cached MCP provider discovery |
39+
40+
### 2. `han parse` — YAML/JSON parsing utility
41+
Used across 13 files (107 occurrences) for parsing YAML frontmatter and manipulating JSON. This is a **utility dependency**, not a state dependency.
42+
43+
**Current usage:**
44+
- `han parse yaml <field> -r` — extract YAML field
45+
- `han parse yaml --json` — convert YAML to JSON
46+
- `han parse yaml-to-json` — same
47+
- `han parse yaml-set <field> <value>` — update YAML frontmatter in-place
48+
- `han parse json <field> -r` — extract JSON field
49+
- `han parse json-validate --schema <schema>` — validate JSON structure
50+
- `han parse json-set <field> <value>` — update JSON field
51+
52+
---
53+
54+
## Analysis: Why Remove Han?
55+
56+
1. **External CLI dependency** — Users must install `han` before AI-DLC works. This is the only external runtime dependency beyond git itself.
57+
2. **Opaque storage**`han keep` stores data in a way that's invisible to standard git tools (not in working tree, not easily inspectable).
58+
3. **Cross-branch complexity** — The `--branch` flag for accessing intent-level state from unit branches adds complexity and potential race conditions.
59+
4. **Two concerns conflated**`han keep` (state storage) and `han parse` (YAML/JSON parsing) are unrelated capabilities bundled in one tool.
60+
61+
---
62+
63+
## Proposed Replacement: File-Based State in `.ai-dlc/`
64+
65+
### Principle: State should be **visible, git-tracked, and inspectable**
66+
67+
Instead of opaque `han keep` storage, move all ephemeral state to files within the `.ai-dlc/` directory structure that are committed to git. This aligns with AI-DLC's existing pattern where `intent.md`, `unit-*.md`, and `completion-criteria.md` already live on the filesystem.
68+
69+
### New State Layout
70+
71+
```
72+
.ai-dlc/{intent-slug}/
73+
├── intent.md # (existing) Intent definition
74+
├── unit-*.md # (existing) Unit specs
75+
├── completion-criteria.md # (existing) Success criteria
76+
├── discovery.md # (existing) Elaboration findings
77+
├── state/ # NEW: ephemeral state directory
78+
│ ├── iteration.json # Was: han keep save iteration.json
79+
│ ├── scratchpad.md # Was: han keep save scratchpad.md
80+
│ ├── blockers.md # Was: han keep save blockers.md
81+
│ ├── current-plan.md # Was: han keep save current-plan.md
82+
│ ├── next-prompt.md # Was: han keep save next-prompt.md
83+
│ ├── operation-status.json # Was: han keep save operation-status.json
84+
│ ├── reflection-status.json # Was: han keep save reflection-status.json
85+
│ └── providers.json # Was: han keep save providers.json
86+
├── operations.md # (existing) Operational plan
87+
└── reflection.md # (existing) Reflection artifacts
88+
```
89+
90+
### Key Design Decisions
91+
92+
**1. Intent-scoped vs. unit-scoped state**
93+
94+
Currently, `han keep` scopes state to the **git branch** you're on. Unit branches get unit-scoped state, intent branches get intent-scoped state. This is implicit and requires `--branch` for cross-scope access.
95+
96+
**Proposed:** Make scoping **explicit via directory structure**:
97+
- Intent-scoped state: `.ai-dlc/{intent-slug}/state/`
98+
- Unit-scoped state: `.ai-dlc/{intent-slug}/units/{unit-slug}/state/`
99+
100+
This eliminates the need for `--branch` cross-access since all state is in the working tree and accessible from any branch.
101+
102+
**2. State committed to git**
103+
104+
Since state files are in the working tree, they get committed with normal `git add && git commit`. This means:
105+
- State is visible in `git diff` and `git log`
106+
- State survives branch switches
107+
- State is inspectable with any text editor
108+
- No special tooling needed to read/write state
109+
- State merge conflicts are possible but manageable (JSON/MD files)
110+
111+
**3. `han parse` replacement**
112+
113+
Replace `han parse` with lightweight alternatives:
114+
- **JSON parsing:** Use `jq` (already used in `config.sh`) or a small built-in shell function
115+
- **YAML parsing:** Use the existing `_yaml_get_simple` / `_yaml_get_array` functions from `dag.sh` (already working, no external dep)
116+
- **YAML-to-JSON:** Use `python3 -c 'import yaml, json, sys; ...'` or `yq` as optional
117+
- **JSON-set:** Use `jq` for JSON manipulation
118+
- **YAML-set:** Use `sed` for simple frontmatter updates (already partially done in `dag.sh`)
119+
120+
### State Management Helper Library
121+
122+
Create a new `plugin/lib/state.sh` that provides a clean API matching the current `han keep` interface but using files:
123+
124+
```bash
125+
# Save state (writes file, auto-commits if in git)
126+
dlc_state_save <key> <content> [--scope intent|unit] [--unit <unit-slug>]
127+
128+
# Load state (reads file)
129+
dlc_state_load <key> [--scope intent|unit] [--unit <unit-slug>]
130+
131+
# Delete state (removes file)
132+
dlc_state_delete <key> [--scope intent|unit] [--unit <unit-slug>]
133+
134+
# List state keys
135+
dlc_state_list [--scope intent|unit] [--unit <unit-slug>]
136+
137+
# Clear all state
138+
dlc_state_clear [--scope intent|unit] [--unit <unit-slug>]
139+
```
140+
141+
---
142+
143+
## Improvement Opportunities for Intent State Management
144+
145+
Beyond removing `han keep`, the migration presents an opportunity to improve how state flows through the system:
146+
147+
### 1. Single Source of Truth for Iteration State
148+
149+
**Current problem:** `iteration.json` stores `unitStates` as a nested object that duplicates status from `unit-*.md` frontmatter. Two sources of truth for unit status.
150+
151+
**Improvement:** Remove `unitStates` from `iteration.json`. The unit files already have `status` in frontmatter — the DAG library (`dag.sh`) already reads status from unit files, not from `iteration.json`. The `unitStates` field is redundant.
152+
153+
Simplified `iteration.json`:
154+
```json
155+
{
156+
"iteration": 3,
157+
"hat": "builder",
158+
"workflow": ["planner", "builder", "reviewer"],
159+
"workflowName": "default",
160+
"status": "active",
161+
"currentUnit": "unit-02-auth",
162+
"targetUnit": null,
163+
"phase": "execution",
164+
"maxIterations": 0,
165+
"needsAdvance": false
166+
}
167+
```
168+
169+
### 2. Explicit Phase State Machine
170+
171+
**Current problem:** The `phase` field was added as a migration (see `inject-context.sh:316-331`) and inferred from the current hat. There's no formal phase transition logic.
172+
173+
**Improvement:** Define a formal phase state machine:
174+
```
175+
elaboration → execution → [operation] → [reflection] → closed
176+
↑ |
177+
└──────────── iterate ─────────┘
178+
```
179+
180+
Each transition should be explicit (e.g., `/execute` transitions from elaboration to execution, `/operate` transitions to operation, etc.).
181+
182+
### 3. Reduce State Parsing Overhead
183+
184+
**Current problem:** The `inject-context.sh` hook spawns 10+ subprocesses to parse iteration.json (one `han parse json` call per field). This is slow on session start.
185+
186+
**Improvement:** Parse iteration.json **once** using `jq` and extract all needed fields in a single call:
187+
```bash
188+
eval "$(echo "$ITERATION_JSON" | jq -r '@sh "
189+
ITERATION=\(.iteration // 1)
190+
HAT=\(.hat // "planner")
191+
STATUS=\(.status // "active")
192+
WORKFLOW_NAME=\(.workflowName // "default")
193+
PHASE=\(.phase // "execution")
194+
"')"
195+
```
196+
197+
### 4. State Validation
198+
199+
**Current problem:** State validation is minimal — just a basic JSON schema check on iteration.json. Invalid state can cause silent failures.
200+
201+
**Improvement:** Add validation on load:
202+
- Required fields check for iteration.json
203+
- Hat must exist in current workflow
204+
- Phase must be valid enum
205+
- currentUnit must reference an existing unit file
206+
- Warn (don't crash) on validation failures
207+
208+
### 5. State Observability
209+
210+
**Current problem:** State is stored in opaque `han keep` storage, making debugging difficult. Users can't easily see what state exists or inspect it.
211+
212+
**Improvement:** Since state moves to files:
213+
- `git diff .ai-dlc/*/state/` shows all state changes
214+
- `cat .ai-dlc/{slug}/state/iteration.json | jq .` inspects current state
215+
- State changes appear in commit diffs
216+
- Add a `/status` skill that pretty-prints current state
217+
218+
---
219+
220+
## Units
221+
222+
### Unit 1: Create `state.sh` Library
223+
Build `plugin/lib/state.sh` with file-based state management functions that mirror `han keep` semantics but use `.ai-dlc/{slug}/state/` files.
224+
225+
### Unit 2: Create `parse.sh` Library
226+
Build `plugin/lib/parse.sh` with JSON/YAML parsing utilities that replace `han parse` using `jq`, `sed`, and existing `_yaml_get_simple` patterns.
227+
228+
### Unit 3: Migrate Hooks
229+
Update `inject-context.sh`, `enforce-iteration.sh`, and `subagent-context.sh` to use `state.sh` and `parse.sh` instead of `han keep` and `han parse`.
230+
231+
### Unit 4: Migrate Skills
232+
Update all 10 skills that use `han keep` (advance, blockers, completion-criteria, construct, elaborate, execute, fail, operate, reflect, refine, reset, resume) to use the new libraries.
233+
234+
### Unit 5: Migrate Hat Documentation
235+
Update references in hat markdown files (builder, experimenter, observer, planner, red-team).
236+
237+
### Unit 6: Migrate Config Libraries
238+
Update `config.sh` and `config.ts` to remove `han keep`/`han parse` dependencies.
239+
240+
### Unit 7: Simplify iteration.json
241+
Remove redundant `unitStates` field, add formal phase enum, reduce parsing overhead.
242+
243+
### Unit 8: Update Documentation
244+
Update README.md, website docs, paper references to reflect the removal of the `han` dependency.
245+
246+
---
247+
248+
## Out of Scope
249+
250+
- Removing git as a dependency (git remains the foundation)
251+
- Changing the DAG resolution logic (works well as-is)
252+
- Changing workflow/hat definitions
253+
- Website/UI changes beyond documentation
254+
- jj VCS support (not implemented anyway)
255+
256+
## Risk Assessment
257+
258+
- **Low risk:** State files are a simpler, more transparent mechanism
259+
- **Migration path:** Can keep `han keep` as optional fallback during transition
260+
- **Testing:** Each unit can be validated independently since hooks/skills have clear boundaries

0 commit comments

Comments
 (0)