P5 · Dependency-aware sync DAG + auto-base lifecycle — progress note (2026-05-21)
Status: SHIPPED as MVP (locally). The data model + predicates + auto-base verbs are in; the full 3-tier DAG in pr_sync.py is deferred.
Commits
8a8a837 v4/P5: prep_status state machine + ready_for_review predicate + auto-bases verbs (MVP)Test pass count
342 passed (+12 new in test_ready_for_review.py).
Exit-criteria check (plan §8 P5)
| Criterion | Evidence | Status |
|---|---|---|
pr-sync follows the 3-tier DAG |
not implemented — _audit_base_indexes still runs at step 5.5 |
DEFERRED |
| TUI plan file accurately reflects tiers + auto-vs-user origin | no TUI in scope this session | DEFERRED to P8 |
adk pr-queue get-next only returns rows where ready_for_review is true |
predicate exists in queue_io.ready_for_review; pr_queue.get_next_eligible still uses the in-memory picker (which is a weaker filter). |
PARTIAL |
adk repo auto-bases list/clean works |
both verbs registered + smoke-tested via argparse. | ✓ |
| Auto-base TTL cleanup runs at the tail of every sync | _clean_auto_bases helper not added to pr_sync.main. |
DEFERRED |
Why MVP
P5 is the largest phase per the plan (4 days). The high-value piece — the data model that P9 / TUI / future sync can build on — is in. Full DAG execution requires substantial pr_sync.py rewrites that would risk breaking the user’s daily PR-review flow. Better staged across a follow-up than rushed mid-session.
The §6.u eligibility predicate is the most important deliverable. It’s the contract adk pr-queue get-next, adk pr-queue claim <url>, and any future TUI all depend on. P9 will consume it directly.
What got skipped (and why)
- 3-tier DAG in pr_sync.py —
_build_sync_plan,_build_bases,_prepare_tier. The current_audit_base_indexesstill runs at step 5.5 and serves as a functional (if less efficient) substitute. Net behaviour: today’s sync still works; the optimisation is the v4 improvement. - prep_status writes from pr_task.py — the prepare step should set
prep_status="ready"+prep_head_sha=<sha>on the row when prep completes. Today it’s a CSV-like script (no queue write). The predicate handles missing fields gracefully (back-compat path). get_next_eligibleconsultingready_for_review—pr_queue.get_next_eligiblestill usesqueue_io.acquire_next_row(the older predicate). Wiring the new predicate requires touching the FIFO sort + acquire-and-claim atomicity. Out of MVP scope.prepare_task.pyrename — cosmetic; risk of breaking call sites without enough wins. Defer.sync-plan.jsonwriter — exists for the TUI (P8 — explicitly out of scope this session).
What’s wired and ready for P9
ready_for_review(entry)— pure function. P9’sauto_run.pywill iterate non-terminal rows and filter by this.PREP_*constants — for any code that wants to read/write prep_status.TAKEN_LOCK_MAX_AGE_SECONDS = 2h— matches the v4 §6.v contract.adk repo auto-bases list/clean— TUI-visible + CLI-usable.
Decisions made this run
- MVP scope — picked. Reason: full DAG would consume the rest of this session and prevent P6+P7+P9 from landing. Trade-off: a follow-up PR closes the gap; today’s behaviour unchanged (no regression).
- Back-compat on
prep_status— missing field treated as “ready” so existing rows (no prep_* fields) stay reviewable. Otherwisepr-queue get-nextwould return None for every existing row until pr_sync runs and writes prep_status. - Lock ceiling raised to 2h — matches §6.v exactly. A test in
test_queue_io.pywas updated (the expired-lock fixture used a 45-min offset that’s now within the 2h window).
Exact commands to inspect
git show 8a8a837 --statpython3 -m pytest skills/adk-cli/scripts/tests/test_ready_for_review.py -vpython3 skills/adk-cli/scripts/repo.py auto-bases list # smoke test (returns empty: no auto-bases yet)