P1 delta — read-gate findings (2026-05-21)
Read-gate per §2 of docs/plans/adk-v4-overhaul.md. Baseline confirmed; 316 tests pass on feat/pr-review-hybrid-rerank-triage.
Scope inventory (the work, in numbers)
| Legacy term | # of file sites | # of total occurrences |
|---|---|---|
pr_link |
25 | 202 |
head_oid |
31 | 228 |
\bdeclined\b (case-insensitive) |
13 | 53 |
last_reviewed_head_oid (transitively renamed) |
~10 | ~30 |
Total ≈ 484 sites across ~40 files. Mostly mechanical.
Drift from the plan’s P1 file list
The plan’s P1 touched-files list is INCOMPLETE. The following files also carry head_oid / pr_link / declined and must be in P1’s scope:
| File | Legacy term(s) | Reason |
|---|---|---|
scripts/lib/code_index/base_index.py |
head_oid |
Indexer’s notion of the head sha — same field name as queue rows, so rename for consistency. |
scripts/lib/code_index/README.md |
head_oid |
User-visible doc. |
skills/adk-pr-review/scripts/_common.py |
pr_link, head_oid |
Helpers consumed by both skills. |
skills/adk-pr-review/scripts/fetch_pr.py |
head_oid |
Reads + writes pr.json field name. |
skills/adk-pr-review/scripts/create_worktree.py |
head_oid |
Worktree materialisation; reads queue row. |
skills/adk-pr-review/scripts/validate_findings.py |
(no legacy terms found — listed for symmetry) | — |
skills/adk-pr-review/scripts/triage.py |
possibly head_oid in state.json reads |
— |
skills/adk-pr-review/references/indexing.md |
head_oid |
Doc. |
skills/adk-pr-review/references/workflow.md |
head_oid |
Doc. |
skills/adk-cli/SKILL.md |
possibly | Audit. |
Drift: P1’s exit criterion adk pr-queue add 1234 requires more than terminology
The plan §8 P1 exit says: adk pr-queue add 1234 works against defaults.repo. Two prereqs not currently in tree:
defaults.platformanddefaults.repokeys don’t exist in~/.agents-devkit/config/core.yaml’s schema. Need to:- Add them to the documented
core.yamlshape (schema_version stays 4; additive). - Add a reader (
scripts/config_io.pyor inline) that resolves them with a sensible default (platform=github).
- Add them to the documented
pr-queue addcurrently dies on a bare PR number (“unrecognized URL”). Need to extendcmd_addto accept:adk pr-queue add 1234→ resolves repo fromdefaults.repo+platformfromdefaults.platform.- (P6 adds the other shorthand forms; P1 only needs the bare-number form for its exit criterion.)
Resolution: include both in P1 worker D’s scope so the exit criterion is satisfied without leaning on P6.
Drift: read-shim is mandatory because the user’s live queue is Bitbucket-shaped
The user’s ~/.agents-devkit/config/pr-queue.json5 currently contains 10+ rows with pr_link + head_oid + status declined for Bitbucket PRs. If the code renames in lockstep, every row breaks until P7 lands.
Solution: queue_io.read_queue() gets an idempotent read-shim that:
- Renames
pr_link → pr_url,head_oid → head_sha,last_reviewed_head_oid → last_reviewed_head_sha. - Maps
status == "declined" → "closed". - Writes the normalized shape back on next save.
This is in addition to the constant alias STATUS_DECLINED = STATUS_CLOSED the plan calls out. Together they make the migration self-healing on first use of the queue under P1 code.
Drift: classify_pr_state upstream input is unchanged
classify_pr_state reads the host API’s state field (the Bitbucket REST API returns "DECLINED" / "SUPERSEDED"; the GitHub API returns "CLOSED"). These are API-defined and stay as the API delivers them. Only the adk-canonical mapping (“declined” → “closed”) changes:
# was:return "declined"# becomes:return "closed"The host-state branch list ({"DECLINED", "SUPERSEDED", "CLOSED"}) stays unchanged — only the adk-side classification string flips.
Worker decomposition (Round 1 — 4 parallel workers)
Files split along non-overlapping boundaries. Worker A defines the core types; B/C/D commit to the new names and adopt them transparently because of the read-shim.
| Worker | Files | Output |
|---|---|---|
W1 — core types + read-shim (adk-agent-implementer) |
skills/adk-cli/scripts/queue_io.py, skills/adk-cli/scripts/queue_release.py |
Adds STATUS_CLOSED; aliases STATUS_DECLINED = STATUS_CLOSED; updates TERMINAL_STATUSES, classify_pr_state; implements read-shim (pr_link→pr_url, head_oid→head_sha, last_reviewed_head_oid→last_reviewed_head_sha, "declined"→"closed"). Internal field reads updated. |
W2 — CLI scripts + USAGE (adk-agent-implementer) |
skills/adk-cli/scripts/pr_scan.py, pr_queue.py, pr_task.py, pr_sync.py, pr_reminders.py, completion.py, bin/adk (USAGE block). Plus defaults.platform / defaults.repo wiring + bare-number pr-queue add form (the P1 exit criterion). |
All field reads use new names; USAGE / help text refers to head_sha / closed; cmd_add 1234 resolves against defaults.repo. |
W3 — PR-review scripts + indexer (adk-agent-implementer) |
skills/adk-pr-review/scripts/{run_review.py, report.py, post_comments.py, comment_resolver.py, fetch_pr.py, create_worktree.py, _common.py, validate_findings.py, triage.py}, scripts/lib/code_index/base_index.py, scripts/lib/code_index/README.md. ALSO add state.json read-shim (run_review.py / report.py write head_sha; read-shim renames old). |
Field reads consistent; state.json normalises on read. |
W4 — docs + tests (adk-agent-test-engineer) |
README.md, skills/adk-cli/SKILL.md, skills/adk-pr-review/SKILL.md, skills/adk-pr-review/references/*.md, every test file under skills/adk-cli/scripts/tests/ and skills/adk-pr-review/scripts/tests/. |
All user-visible docs use new terms; all test fixtures use new field names; all status assertions use closed not declined. |
Coupling: W1 must finish before W2/W3/W4 can verify pytest, because W2/W3/W4 import from queue_io. Strategy: run W1 first (foreground), then W2+W3+W4 in parallel against W1’s diff.
Actually — W1’s STATUS_DECLINED alias means W2/W3/W4 can use either name during the transition. So all 4 can run in parallel in isolated worktrees, then integrate.
Plan updates (in-place markers)
Will append these <!-- updated 2026-05-21: P1 read-gate --> notes:
- §8 P1 touched-files list: add the omitted files above.
- §8 P1 migration paragraph: mention the read-shim approach (not a one-shot rewrite).
- §11 per-skill checklist: clarify
last_reviewed_head_oid → last_reviewed_head_sha. - §9 P1 row: collapse to 4 workers (round 1) to fit the 4-cap; round 2 is reserved for fix-ups.
Invariants to preserve
- Constitution §I.4 — no Slack post / no PR comment / no Confluence update fired by P1 work. Pure code refactor.
- Constitution §VII — secret values never enter context (no
caton creds files; presence-only checks). - §6 layer rule — Layer-1 (SKILL.mds) never imports Layer-3; this phase doesn’t move that line.
- §6.u eligibility predicate — unchanged in P1 (P5 owns it).
- The user’s live
pr-queue.json5must survive the rename — the read-shim is the contract.