Skip to content

Commit 7fa3570

Browse files
author
cloud-snapshot
committed
snapshot: chain state at 2026-05-03T03:30Z (S0 done, S1 stalled at finalized due to codex 429)
1 parent 27990e3 commit 7fa3570

31 files changed

Lines changed: 6554 additions & 46 deletions

chain_state.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"current_milestone_index": 1,
3+
"current_plan_name": "sprint-1-foundation-schema-20260503-0201",
4+
"last_state": "stalled",
5+
"completed": [
6+
{
7+
"label": "sprint-0-spike",
8+
"plan": "sprint-0-spike-validate-store-20260503-0106",
9+
"status": "done"
10+
}
11+
]
12+
}

docs/sprint-0-spike-report.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Sprint 0 Spike Report
2+
3+
## What the spike validated
4+
5+
The throwaway-branch spike validated the refined storage direction against real Arnold call sites without touching production megaplan consumers. The unchanged Arnold `create_epic()` and `edit_epic()` flows ran through a compatibility adapter backed by the spike `FileStore`, including the seeded `inbound_message_id` message row, the turn update branch, checklist seeding and mutation, sprint replace/upsert, and queue transitions through `_lock_in`, `_queue`, `_pend`, `_reorder`, and gapless normalization. The spike journal also recovered correctly in both relevant crash windows: a process death after `prepare.json` but before `.commit` left no visible writes, and a process death after the `.commit` marker replayed the committed transaction on reopen.
6+
7+
For the file-mode reader proof, the spike round-tripped copied real fixture trees from `arnold-source/.megaplan/plans/sprint-6-images-second-opinion` and `arnold-source/.megaplan/plans/sprint-3-multi-epic`, and the rework pass reran the same disposable-copy check on `arnold-source/.megaplan/plans/sprint-1b-discord-resident` specifically because that fixture carries both `review.json` and `execution_batch_10.json` (plus `execution_batch_11.json` through `execution_batch_14.json`). Those copies preserved filenames, layout, and file bytes after a byte-preserving read/write pass. The unchanged narrow `auto.py` helper surface still worked on the disposable copies: `_resolve_plan_dir(...)`, `_last_history_step_result(...)` at line 197, `_read_execute_blocking_deviations(...)` at line 223, and `_get_review_marker(...)` in the same tight loop used near line 685 all returned stable values without touching the source fixture tree. This is narrow compatibility evidence only; it is not proof that the broader plan-tree reader surface is already safe to migrate.
8+
9+
## Protocol friction found
10+
11+
The refined protocol is close, but the live Arnold/editorial surface is not yet a direct drop-in match. The real edit path still performs body writes through `update_epic(body=...)` rather than a dedicated `update_body(...)` call. The create path still depends on `seed_checklist(...)` as a first-class store operation. Queue behavior is still expressed as per-sprint mutations plus normalization, not as a single live `set_sprint_queue(...)` write. The store also has to support `transaction(epic_id=None)` plus message and turn updates before an epic exists, because Arnold binds the inbound message and turn rows only after `create_epic()` succeeds.
12+
13+
The high-batch `auto.py` recheck also reinforces that this spike only proved the current narrow reader loop, not idealized plan-tree semantics. The copied `sprint-1b-discord-resident` fixture includes `execution_batch_10.json` through `execution_batch_14.json`, and `_read_execute_blocking_deviations(...)` still completed safely on that copy, but the helper currently sorts batch filenames lexicographically rather than numerically. Sprint 1 should keep that current behavior in mind when deciding whether the eventual repository abstraction needs to preserve filename ordering exactly or should normalize batch selection behind a compatibility layer.
14+
15+
The journal spike also showed that transaction framing cannot be treated as file renames alone. The event log needs transaction-scoped framing with a shared `tx_id`, `_tx_begin`, `_tx_commit`, and tolerant scanning that ignores incomplete tails. Without that, recovery can restore files while leaving `events.jsonl` in a logically torn state.
16+
17+
## Changes to absorb in Sprint 1
18+
19+
Sprint 1 should keep the refined protocol, but land it behind a compatibility layer instead of forcing Arnold to change call shapes immediately. The production `Store` surface should preserve `transaction(epic_id=None)`, bridge `update_epic(body=...)` to `update_body(...)`, and either retain `seed_checklist(...)` or provide an explicit adapter-owned shim for it. Queue support should include the refined `set_sprint_queue(...)` primitive, but Sprint 1 still needs compatibility helpers for the live Arnold per-sprint queue workflow until the caller surface is migrated deliberately.
20+
21+
On the file side, Sprint 1 should carry forward the transaction journal contract from the spike: `prepare.json`, `.commit`, recover-on-open, and framed `events.jsonl` writes that ignore incomplete transactions during replay. On the plan-tree side, Sprint 1 should treat the copied-fixture proof as evidence only for the narrow `auto.py` helper reads exercised here. Broader readers and writers across the rest of the `.megaplan/plans/*` surface remain explicitly deferred and need separate validation before they should be counted as compatible.

megaplan/_core/__init__.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,36 +9,63 @@
99

1010
# -- io.py: pure utilities, atomic I/O, paths, config -----------------------
1111
from .io import (
12+
append_framed_json_records,
13+
append_framed_json_transaction,
1214
artifact_path,
15+
atomic_write_bytes,
1316
atomic_write_json,
1417
atomic_write_text,
1518
batch_artifact_path,
19+
canonical_megaplan_root,
20+
commit_journal_transaction,
21+
committed_framed_json_transactions,
1622
collect_git_diff_patch,
1723
collect_git_diff_summary,
1824
compute_global_batches,
1925
compute_task_batches,
2026
config_dir,
2127
current_iteration_artifact,
2228
current_iteration_raw_artifact,
29+
discard_uncommitted_journal_transaction,
2330
detect_available_agents,
2431
ensure_runtime_layout,
32+
find_plan_dir,
2533
find_command,
34+
framed_json_record_bytes,
35+
fsync_dir,
36+
fsync_file,
2637
get_effective,
38+
has_any_plan_root,
39+
journal_blob_promotion,
40+
journal_bytes_write,
41+
journal_commit_path,
42+
journal_event_log,
43+
journal_prepare_path,
44+
journal_root,
45+
journal_text_write,
2746
json_dump,
2847
list_batch_artifacts,
2948
load_config,
3049
load_finalize_snapshot,
3150
megaplan_root,
3251
normalize_text,
3352
now_utc,
53+
orphan_plans_root,
54+
plan_search_roots,
3455
plans_root,
56+
prepare_journal_transaction,
3557
read_json,
58+
read_committed_framed_json_records,
59+
recover_journal,
60+
repo_storage_id,
3661
render_final_md,
3762
save_config,
3863
schemas_root,
64+
scrub_stale_staging_files,
3965
sha256_file,
4066
sha256_text,
4167
slugify,
68+
write_journal_commit_marker,
4269
)
4370

4471
# -- phase_runtime.py: centralized runtime policy ----------------------------
@@ -125,36 +152,63 @@
125152

126153
__all__ = [
127154
# io
155+
"append_framed_json_records",
156+
"append_framed_json_transaction",
128157
"artifact_path",
158+
"atomic_write_bytes",
129159
"atomic_write_json",
130160
"atomic_write_text",
131161
"batch_artifact_path",
162+
"canonical_megaplan_root",
163+
"commit_journal_transaction",
164+
"committed_framed_json_transactions",
132165
"collect_git_diff_patch",
133166
"collect_git_diff_summary",
134167
"compute_global_batches",
135168
"compute_task_batches",
136169
"config_dir",
137170
"current_iteration_artifact",
138171
"current_iteration_raw_artifact",
172+
"discard_uncommitted_journal_transaction",
139173
"detect_available_agents",
140174
"ensure_runtime_layout",
175+
"find_plan_dir",
141176
"find_command",
177+
"framed_json_record_bytes",
178+
"fsync_dir",
179+
"fsync_file",
142180
"get_effective",
181+
"has_any_plan_root",
182+
"journal_blob_promotion",
183+
"journal_bytes_write",
184+
"journal_commit_path",
185+
"journal_event_log",
186+
"journal_prepare_path",
187+
"journal_root",
188+
"journal_text_write",
143189
"json_dump",
144190
"list_batch_artifacts",
145191
"load_config",
146192
"load_finalize_snapshot",
147193
"megaplan_root",
148194
"normalize_text",
149195
"now_utc",
196+
"orphan_plans_root",
197+
"plan_search_roots",
150198
"plans_root",
199+
"prepare_journal_transaction",
151200
"read_json",
201+
"read_committed_framed_json_records",
202+
"recover_journal",
203+
"repo_storage_id",
152204
"render_final_md",
153205
"save_config",
154206
"schemas_root",
207+
"scrub_stale_staging_files",
155208
"sha256_file",
156209
"sha256_text",
157210
"slugify",
211+
"write_journal_commit_marker",
158212
# phase_runtime
159213
"DEFAULT_NON_EXECUTE_TIMEOUT_CAP_SECONDS",
160214
"PHASE_RUNTIME_POLICY",

0 commit comments

Comments
 (0)