After an acceptance panel settles, the wake re-offers the keep/replace delivery
control. A prose answer there is a malformed control and earns one repair
round, but wait_for_acceptance_feedback parked the task behind the same
binding again: the panel had already settled, so no second wake ever came and
the task hung until its deadline (the keyless system-E2E lane reproduced it on
every run since the async acceptance operation landed). The wait now takes a $0
look at the awaited panel through the same reconcile delivery uses and parks
only while it is still running.
Also widen the no-deadlock join deadline in the extension unload test: one
second was a wall-clock guess that a loaded Windows CI runner misses without
any deadlock.
PLUGIN_API_VERSION=2.0 with full manifest negotiation (major strict, minor
minimum, closed-set capabilities, typed educational refusals) checked before
any plugin import or out-of-process catalog; an absent plugin_api field binds
the LEGACY 1.3 generation by construction and keeps loading on its existing
hash-bound review PASS (grandfather), while a NEW PASS is refused at issuance
by one admission predicate shared by LLM review (a $0 refusal before the
paid panel dispatches), owner attestation, and native-seed trust (native_seed
closed; bundled telegram/unix_computer_use declare the field with version
bumps). Repeat review of grandfathered bytes never clobbers the live PASS,
and the persisted admission finding re-aggregates to PENDING under every
enforcement mode. The deterministic preflight now fails closed (infra
failures refuse without persisting). Frozen RuntimeInfo TypedDict with the
negotiated generation; per-version surface fingerprints fail closed in both
directions; FORBIDDEN_EXTENSION_SETTINGS alias collapsed; legacy
PluginAPIImpl kwargs removed; iframe_raw desync healed by re-deriving
VALID_EXTENSION_PERMISSIONS from skill_manifest (single carrier); the
negotiated generation rides the registration bundle and dispatch-surface
stamps (ABI-9 seam). Owner-A grant resync: a native re-seed with unchanged
requested key/permission sets carries grants to the new content hash.
Owner 6.2=A: declarative dependency fingerprint — .ouroboros_env bytes stay
outside the review hash, declared dependency names are hash-covered, and a
state-plane/payload declaration desync is a typed load refusal.
ADOPTION: ABI-1 -> done. ARCHITECTURE + CREATING_SKILLS deltas same-commit.
(cherry picked from commit 8f3fb629c7b51a2ebd6933cc8742697199206068)
Module side (41 D14 owners at tip): 15 byte-identical across tip/reference/
base (event_bus, extension_isolated_deps, extension_reconcile_queue,
marketplace/{__init__,adapter,clawhub,fetcher,install,install_specs,
isolated_deps}, skill_owner_attestation, skill_readiness,
skill_repair_admission, skill_review_status, skill_token); 16 pure upstream
drift - upstream bytes stand (extension_companion, extension_health,
extension_process_runner, extension_ui_validation,
marketplace/{ouroboroshub,provenance}, skill_dependencies,
skill_lifecycle_queue, skill_loader, skill_publish_eligibility,
skill_review_history, skill_review_passes, skill_review_runner,
tools/skill_{exec,preflight,publish}); 8 NEW post-cutoff upstream modules
with no ledger rows - untouched (betterleaks_runtime, skill_payload_binding,
skill_publish_{github,result,scanner,snapshot} of 8cc2ac69,
skill_review_cycles of 386e9417, skill_review_usage of f18da8c3). The
reference's unrowed failure_kind delta on extension_process_runner is NOT
replayed (typed-dispatch family, F3 territory); the supervised-future leak
in PluginAPIImpl is preserved per plan (F3-acceptance carries the direct
regression test). PluginAPI semantics untouched - mechanical byte-preserving
splits only.
The splits: extension_loader.py 2194 -> 960 into six leaves per ledger rows
2467-2519 (registry_state 87, surface_names 132, child_catalog 109,
import_staging 173, liveness 242, plugin_api 744); 49/53 spans
byte-identical to the oracle leaves, 4 byte-falsified by pure upstream drift
(widget-geometry promotion, durable companion-health overlay) and re-emitted
from tip bytes; two unrowed tip riders travel with their readers
(_widget_geometry_from_render -> surface_names beside its rowed sibling,
_apply_durable_extension_health -> liveness). skill_review.py 1600 -> 841
into four leaves (packs 166, rebuttals 127, prompt 376, output 245); 25/31
ledger rows executed from tip bytes, 6 SUPERSEDED by upstream's own re-home
into skill_review_cycles (386e9417) - upstream ownership stands, the facade
keeps the historical aliases and the identity suite pins them.
_ws_broadcaster deliberately not aliased on the facade (rebindable global
keeps one binding at its owner - the reference contract, pinned). Proof
green: transplant-tool --check per leaf - ast=tokens=bytes=True on all 80
spans, undeclared_top_level=[], leaf_invariants=[], exit 0; facade audit:
17+14 retained top-level statements byte-identical to tip, every tip name
accounted, every moved name re-imported (minus the pinned _ws_broadcaster);
import smoke + shared-registry object-identity checks green.
Test side: identity suites carried - test_extension_loader_extraction.py
(+2 rider rows) and test_skill_review_extraction.py (tool_module_inventory
clauses reverse-mapped out: v7-only mechanism absent at this tip;
cycles-alias identity clause added; facade size bound 800 -> 900 for the
tip-retained lifecycle members, which join the patchable-seams pin).
test_extension_loader.py 1717 -> 359 split into 4 siblings +
_extension_loader_shared.py per 45 ledger rows (zero upstream drift on the
file; 43/45 moved bodies byte-identical, 1 oracle dual-supervisor-patch
adaptation kept, 1 reverse-mapped to the tip spelling supervisor/workers.py
- the reference's worker_process.py is the still-pending D08 split).
test_skill_review.py 1943 -> 579 into 5 siblings + _skill_review_shared.py
per 65 rows (58 byte-identical, 3 re-emitted from tip test drift, 3
patch-retarget adaptations kept; the upstream-deleted advisory test is not
resurrected - its f8d87c69 successors stay in the remainder on tip bytes,
theme re-home deferred to F5). Lossless both families: 52==52 and 74==74
test names, zero duplicate names, no new ast-identical bodies (10
pre-existing review_cycles duplicates at base noted, untouched). Dead-patch
class closed: the remainder's advisory pre-review patch -> prompt owner,
extension_companion supervisor patch doubled onto the plugin_api owner
(single-module patch proven dead by a red run); every other facade patch
site of moved names verified live (production consumers do call-time facade
imports).
size-ratchet manifest regenerated with the official tool (extension_loader,
test_extension_loader, test_skill_review leave GIANT_PATHS; no new band
entries); --check exact; ratchet 5 passed; ruff F clean tree-wide.
Receipts: 12 identity + 126 split-family + 1751 targeted/-n16-loadscope +
full CI-shape battery 11950 parallel + 618 serial, all rc=0; HEAD held and
worktree status unchanged through every pytest run. Ledger corrections:
docs/v7next/LEDGER_CORRECTIONS.md D14 section, entries 1-10.
(cherry picked from commit c7e3d04df95eb9470f5ca3ad824485083a201fe4)