Tasks: portable state — what travels with the work, what belongs to the machine
Phase 3 of 3. A DAG of small, verifiable tasks, each referencing the requirements it satisfies.
mermaid
graph LR
T1["T1 declaration<br/>state.py"] --> T2["T2 test S1–S2<br/>(red first)"]
T1 --> T3["T3 docs/cli/state.md"]
T3 --> T4["T4 .gitignore"]
T3 --> T5["T5 test S3–S5"]
T4 --> T5
T3 --> T6["T6 links & corrections"]
T3 --> T7["T7 decision-046 + capability doc"]
T5 --> T8["T8 evidence + briefing"]
T6 --> T8
T7 --> T8
T8 --> T9["T9 WorkItemStore<br/>(review: consolidate)"]
T9 --> T10["T10 control + poll<br/>onto it"]
T9 --> T11["T11 upgrade shim"]
T10 --> T12["T12 layout + config<br/>portable/ local/"]
T12 --> T13["T13 retire<br/>polling.stateFile"]
T10 --> T14["T14 tests"]
T11 --> T14
T13 --> T14
T12 --> T15["T15 docs, decision,<br/>recipe"]
T14 --> T16["T16 evidence + briefing"]
T15 --> T16Tasks
- [x] T1 — declare the generated paths.
GeneratedPath+GENERATED_PATHSincli/the_loop/state.py: five entries (session record, control record, poll state, event log, pidfile), each withattr,default,portable,holds,why. No runtime consumer. (R3.1) - [x] T2 — pin the declaration against the layout (red first).
cli/tests/test_state_portability.pyS1–S2: every public path property ofStateLayoutis claimed by an entry, and every entry'sattr/defaultresolves. Written before T1 is complete; verified red by removing an entry. (R3.2, R5.2) - [x] T3 — write the state reference.
docs/cli/state.md: the two kinds of state, the classification table (first column = the declaration'sdefault), a section per file with a JSON example, field table and lifecycle, the hand-off procedure, the~/.the-loopcase, the costs, what must never be carried, and the security note. (R1.1–R1.3, R2.1, R2.3, R2.4) - [x] T4 — apply the recipe here. Replace this repository's three the-loop state blocks in
.gitignorewith the documented block, byte for byte, including dropping the blanket ignore of the pre-issue-106 poll state. (R2.2) - [x] T5 — pin the docs and the recipe. S3–S5: every declared path documented with a matching classification; the block verbatim in
.gitignore; the block's patterns actually ignore the local paths and spare the portable ones. (R3.3, R3.4, R3.5) - [x] T6 — links and corrections. Sidebar entry in
docs/.vitepress/config.mts; pointers fromdocs/cli/concepts.md,docs/cli/index.mdand thestate.rootoption; delete "All of it is git-ignored runtime state" fromdocs/config/cli/index.md. (R1.4) - [x] T7 — record the decision.
docs/decisions/decision-046.md+ a row indocs/decisions/decisions.md; behaviour bullet and history row indocs/capabilities/cli.md. (R4.1–R4.3) - [x] T8 — evidence and reviewer briefing. Full suite green,
git check-ignore -vevidence for all five paths, execution log updated, PR briefing posted. (R5.1, R5.2)
Tasks added in review (PR #129)
The owner asked whether the stores could be consolidated, and chose to do it in this PR. R6/R7 and design §9 are the result; these are their tasks. The phase returned to tasks-breakdown and then implementation before re-requesting review.
- [x] T9 — the shared record.
cli/the_loop/workitem.py:WorkItemStoreover<state.root>/portable/<slug>.jsonwithsection/write_section/drop, read-modify-write per section, atomic writes, empty-record removal. (R6.1–R6.3) - [x] T10 — move both writers onto it.
ControlStoredelegates storage (public API unchanged);PollStatebecomes directory-backed with lazy loads, a dirty set, and write-throughforget. (R6.1, R6.2, R6.5) - [x] T11 — the upgrade shim. Read the pre-issue-128 control record, the pre-issue-128 poll state and the pre-issue-106 poll state when a section is absent; write forward on the next write; new record wins. (R7.1–R7.3)
- [x] T12 — the layout.
StateLayout.portable_dir/local_dirreplacingsessions_dir/control_dir/poll_state;LegacyLayoutbeside it;GENERATED_PATHSdown to four entries; dispatcher, poll and sessions commands rewired;sessions --portable-dir,poll --state-dir. (R6.1, R6.4) - [x] T13 — retire
polling.stateFile.migrations.pyrefuses it with the replacement named and removes it on migration; schema + template + this repo's config updated; CLI config version0.2.0→0.3.0. (R7.4) - [x] T14 — tests.
test_workitem.py(11 cases: independence, the clobber direction, fail-closed, every shim path);test_state.pyrewritten for the two-tree layout; the poller/control/CLI suites moved to the new paths; four migration cases for the retired key. (R3, R6, R7) - [x] T15 — docs and decision.
docs/cli/state.mdrewritten around the new layout (including the three-line recipe and the upgrade section); decision-046 extended with the layout decision and the "why each store exists" answer; capability docs, config pages, concepts,upgrade-the-loop. (R1, R2, R4) - [x] T16 — evidence and re-review. Full gate green,
git check-ignore -vre-run on the new paths, execution log and PR briefing updated. (R5)