Round-2 verification of v9 against round-1 Sonnet panel (coverage/architecture/adversarial/security)
Spec: docs/architecture/specs/task-workflow-format-unification.md, v9 (ec5d062), branch claude/akm-markdown-tasks-history-75l6du. Baseline for code claims: same checkout.
Method: for every critical/major in the four r1 reports, located the v9 text via §11's
cross-reference table, read the cited section in full, and where the fix leans on a
factual code claim, re-verified the claim by reading the cited file. Then checked the
new text against the rest of v9 for reintroduced contradictions, with extra scrutiny on
the five areas called out (§5.6 ceiling, persona-snapshot hash, with: merge, tombstone
- crash-window ordering, shim vs resolve-akm-bin.ts).
Criticals — all four verified fixed, no reintroduced contradiction
- coverage C5 (§5.6 grant contradicts activation-policy's no-new-trust decision):
v9 deletes the
bundles.<name>.allowScriptExecutiongrant entirely and replaces it with exact inheritance of the existingtools:provenance ceiling (primary-stash-only, no override, fail-closed) — verifiedshow.ts:433-445really has no override (if (response.toolPolicy !== undefined && !isPrimaryStash) delete ...), matching v9's description exactly.activation-policy.ts's "no new trust machinery" decision (header comment, 2026-07-14) is respected: zero new config, zero persisted state. Fixed. - security "grant mechanism doesn't exist" / "ceiling philosophy unverified": moot —
v8's grant is withdrawn. The second half of this finding (reviewer claimed the
tools:ceiling "was not found" in code) is factually wrong — it exists atshow.ts:433-445— and v9 §11 correctly flags this as the one rejected panel claim. Confirmed correct. - adversarial "
with:merge/replace semantics undefined": §2.2 now states the rule explicitly — per-key shallow merge on a step→task→(command|workflow) composition chain, referencing step wins,with.argumentsreplaced whole. Checked against §2.3 ("no nesting: a task referencing a task is an error") — the chain is capped at depth 1 exactly where the merge rule assumes it stops, no gap. Checked against §4 ("with:is not a value field... merges per-key at its target, outside the cascade") — value-field cascade (§4's layer list, which includesuses: tasks/<ref>as a layer) andwith:merge are two disjoint mechanisms over two disjoint key sets; no overlap, no contradiction. Fixed. - adversarial "hashVersion 5 omits persona snapshot": §5.3's table now has a
persona snapshot hashrow (system prompt, tool policy, value fields). Matches §4.2's persona-snapshot shape ({systemPrompt, toolPolicy, model, …valueFields}) verbatim — same field list on both sides. Fixed, consistent. - adversarial "
.ymltombstone hard-error has no remedy for read-only bundles": §8 now carves out read-only/third-party bundles to a warning instead of a hard error, explicitly citing it as matching the existing migrator precedent. Verified againstscripts/akm-migrate/migrate/legacy/task-target-ref-migration.ts:246-266—planTaskTargetRefMigrationreally does skip non-writable bundles and warn-and-continue for legacy files it can't rewrite, word-for-word the precedent v9 claims. Fixed.
Editor's note (archival). The cosmetic stage-name mismatch this report flags in §5.6 was fixed in the same revision that followed this panel: v9 now says the ceiling is evaluated in the resolve stage for both surfaces. The finding is retained as the historical record of what the panel saw, not as an open issue.
Majors — verified fixed unless noted
All of the following were checked and are substantively addressed with no new
contradiction: architecture's five majors (task-path staging named in §5.1 as
"resolve → execute"; RunnerSpec-vs-UnitDispatchRequest split pushed to the sink
per §5.1; ShellUnitExecutor explicitly extracted from the task runner's hardened path,
not rebuilt; monotemporal composition rule pins config-snapshot timing for uses: tasks/<ref>; persona resolver extraction named and costed in §9); adversarial's
extra_params deep-merge preservation (§4 merge-classes, matches freeze.ts:211-216
mergedLlmOverrides/deepMergeConfig exactly), shell timeoutMs slot (§5.2), shell
crash/lease semantics (§5.2), persona-toolPolicy-vs-engine-capability reconciliation
(§4.2's "unconsumed-field notice" line folds it into §4 item 4's capability-notice
mechanism); security's composition-chain bypass (§5.6 bullet 3, "inherit from the
defining asset's own source"), grant-granularity/bundle-update bypass (moot — grant
removed), sync-vs-fire-time gap (§5.6 bullet 2, evaluated at resolution not at
sync/enable time), env: literal-secret-heuristic reuse (§5.5, points at
param-secrets.ts's detectSecretShapedParams directly), AKM_ITEM shell-injection
story (§5.5 pins it to the exec-utils env-object pattern, never shell-text splice),
and the two-file migration atomicity gap (§8 states journal-then-verify-then-delete
ordering explicitly as new work, costed in §9, rather than claiming the existing
4-artifact migration-backup.ts model already covers it — checked, that model really
is scoped to config.json/state.db/workflow.db/index.db only, so v9's honesty
about this being an extension is accurate, not a claim contradicted by code).
- coverage M13 (improve-exclusion mechanism): §3 now removes the
type:"task"pure-YAML special-case (markdown base checks fire) and separately declares tasks improve-ineligible via a per-type adapter capability. The capability-declaration pattern genuinely exists today (bundle-adapter.ts:9, "one interface, optional capability methods"), so naming that seam is not fabricated — but the concrete eligibility check insrc/commands/improve/eligibility.tsis currently a hardcodedindexed.entry.type === "..."string comparison, not adapter-capability-driven; v9 doesn't say eligibility.ts itself gets refactored to consult the new capability rather than its own type-string list. Not a contradiction, but thinner than "names a mechanism" suggests — residual gap, not blocking. - coverage M9 / adversarial-adjacent (akm-bin shim): §5.7's synthesized-shim design
(write a temp-dir
sh/.cmdshim invoking the exact resolved multi-element invocation, PATH-prepend the shim's directory) matchesresolve-akm-bin.ts's actual return shape (argv: string[], up to two elements for the npm/checkout launcher cases) — the shim approach correctly generalizes to the multi-element case a bare PATH prepend cannot. Fixed.
Special-attention items — findings
- §5.6 ceiling enforceability at both resolve points: the mechanism itself (primary-stash-only, checked at the point the target asset is resolved, no override) is sound and symmetric for workflows and tasks. However, v9 states the enforcement point as "freeze for workflows, dispatch for tasks" — but §5.1 (this same v9 revision) explicitly renames task staging to "resolve → execute" (no stage named "dispatch"), and §5.4 explicitly splits workflow freeze into compile → resolve → freeze, with asset loading (the thing the ceiling needs to inspect) happening in resolve, not in the now-narrower freeze ("snapshot + hash" only). So §5.6's own enforcement-point language doesn't line up with the stage names v9 itself just introduced elsewhere (§5.1, §5.4) to fix the architecture panel's "staging is unstated" finding. This is cosmetic (both "resolve" and "freeze"/"dispatch" as used here occur before any shell/agent actually spawns, so no execution-order security gap results), but it is a real terminology inconsistency introduced by the v9 redesign, not present as such before the two staging fixes existed to be inconsistent with. Not blocking; a copy-edit item.
- "scope: non-AI exec surface only" loophole for third-party
run:tasks scheduled via sync review: no loophole found. §5.6's own definition of "shell-class work" explicitly includes "therun:text of a task," so a third-party task whose target isrun:is covered by the ceiling and refuses regardless of whether the operator reviewed and enabled it viasync(activation-policy rule 3 is a separate, orthogonal gate that only concerns whether the task fires at all, not whether its shell target is trusted). The "agent-dispatched third-party tasks... unchanged" carve-out only exempts prose/agent-dispatch tasks (which have no direct shell surface here), notrun:/script tasks. No new hole. - Persona-snapshot hash vs §4.2 resolver extraction: consistent — §5.3's new row lists exactly the fields §4.2's snapshot shape defines (systemPrompt, toolPolicy, value fields), and both are attributed to the same extracted resolver.
with:merge rule vs §4 cascade and §2.3's override bullet: consistent — verified above, disjoint mechanisms, no double-counting.- Tombstone carve-out + crash-window ordering vs §8's journal claims and the real
migrator: consistent — the read-only carve-out matches
task-target-ref-migration.ts's existing warn-and-skip behavior; the create-verify- delete ordering is honestly presented as new work extending (not already covered by)migration-backup.ts's 4-artifact model, and it's costed in §9's "Named refactors" row. - Shim design vs
resolve-akm-bin.ts: consistent — the shim generalizes correctly to the multi-element launcher caseresolveAkmInvocation()can return.
Verdict
ALL FIXES HOLD.
Residual (non-blocking) notes:
- §5.6's "freeze for workflows, dispatch for tasks" enforcement-point language uses stage names that don't match the stage vocabulary §5.1/§5.4 just introduced in this same revision ("resolve → execute" for tasks; compile→resolve→freeze for workflows, with asset resolution living in "resolve" not "freeze"). Suggest wording as "resolve for workflows, resolve for tasks" (or just "at resolve, for both") to align with §5.1/§5.4.
- §3's improve-ineligibility fix correctly names an existing capability-declaration
pattern in the adapter interface, but doesn't state that
src/commands/improve/eligibility.ts's current hardcodedentry.type === "..."checks need to be rewired to consult that capability — worth a one-line addition if precision matters, but doesn't reopen the original finding (a mechanism is now named, whereas before none was).