Skip to content

Integrate runtime repair stack and close the cumulative CI census - #32

Merged
Parad0x-Labs merged 104 commits into
mainfrom
integration/stack-20260922
Sep 23, 2026
Merged

Parad0x-Labs merged 104 commits into
mainfrom
integration/stack-20260922

Conversation

@Parad0x-Labs

@Parad0x-Labs Parad0x-Labs commented Sep 22, 2026 •

Copy link
Copy Markdown
Owner

Runtime repair stack integration

The runtime repairs were split across independent branches while main still failed cumulative verification. This candidate integrates the reviewed heads of #10, #12, #13, #14, #15, #16, and #20–#31 (23 commits after ac4bd99), resolves their overlap, and repairs the failures exposed when they run together. Excluded dependencies: #1, #4, #17, #18, #19. Dependabot and nulla CI stay disabled. Merge requires explicit owner approval.

What landed

Integrated branch heads (14 commits)

  • Settings exercised through configured providers and visible controls (83f34a9)
  • Docked companion kept clear of stacked controls; native wallet checks routed (02460ff)
  • Retry races driven by one canonical ingress identity (def2cf8)
  • Regression probes aligned with frozen authority and current delivery contracts (faf83ee)
  • Shared quote fields and requests preserved under retrieval restrictions (9906832)
  • Response lineage columns ensured on legacy databases (f436a54)
  • Current connection and command authority contracts exercised (26a7df7)
  • Attempted tool results distinguished from completed work (bc9765b)
  • Research settings translations completed across shipped locales (b1be4a2)
  • Isolated audit reads and diagnostic fetches bound to their owning scopes (e4305bf)
  • Closed sequence computations bound without swallowing other requests (d7a7329)
  • Exact asset, per-request cap and model scope shown in spending approvals (f68ffb0)
  • Narrow verification evidence preserved through completion; served contracts refreshed (dd5d363)
  • False rollback completion refused when startup restoration fails (2364753)

Product repairs from the integration sessions (8 commits)

  • b299db9 — wallet-paid (x402) sends pass the composer preflight. The prepaid-balance check ran for the accountless lane; the lane's own readiness (wallet approval) is the liquidity gate. Served x402 chat journey passes end to end.
  • d00f0d2 — an operator-stopped turn records CANCELLED, never provider evidence. The front door consults the same cancellation marker the attempt spine honors; the sufficiency writer no longer fabricates verified_success for stopped turns. 350+ cumulative tests including stage-verdict and sufficiency.
  • 5597fbe — served payment journeys aligned to the current money contracts. Pin-time price acceptance binds route ceilings (saveReviewedMaxima); budgetless composer refusal, money-law refusals, one settled dispatch with correlated receipt, disabled budget = no standing authority. Funded 6 / x402 3 / tool-flow 10 / sheet 2.
  • 2f38ecd — contract fixtures refreshed for the current authority surfaces (mutation anchor, honest research-refusal phrase, tool-surface golden's two calendar reads as network reads, bounded initial tooling catalog).
  • 67fe48a — schedule wording attributed to the calendar lane; web-freshness contracts follow the truth guards (disabled web ⇒ honest "didn't run any live lookup" refusal; empty fresh lookup degrades honestly). Routing 100, freshness 25.
  • 7f11b33 — a local-currency ask stays in the place's own money (missing conversion named with the actually-missing pair; never a same-currency subtraction); meet-and-greet scope, arbiter authorization, retraction fixture and CI's virtual display for the headful wallet-handoff session.
  • f9e8276 — a comparison's coordinated attributes split into their own demand units (CT-301); typo recovery requires the first letter to survive so a gold receipt can no longer discharge a units-sold demand (CP3). Demand-unit consumers 1329, live-data continuation 360, test-kit 37.
  • 73549c4 — a policy-contained live-data turn closes as the refusal it is. Under the Local Only composite the deterministic disabled-answer finalizes; all-failed attempts under the composite close as REFUSED_POLICY (non-retryable refusal — renderers listing lifecycle states exhaustively should add it there, never as a FAILED_* alias). Pact family 58, live-data/continuity 571, grounded/sufficiency 90.
  • e57fe1c — the phone journey's approvals are minted through the real permission gate before daemon boot; ids handed to the journey via VOOL_JOURNEY_APPROVAL_IDS; daemon stdout to a file; evidence under tmp_path with an opt-in dir for committed copies. Full mobile journey passes end to end.

CI census closure (67e0870)

Sixteen unique failures over the eight Linux shards of run 35730553862, each traced to its owning contract and repaired there — no skipped failures, weakened consent, suppressed errors, or removed safety assertions:

  • semantic replay (2): the run_once finalization spine stashes per-turn identity records (_closure_verdict, _execution_identity, _presentation_selection, _semantic_admission, details' tool_call_id) on every served result, which re-classified all 252 corpus turns as nondeterministic. Records are now compared by content with identity keys dropped per field, in a dedicated test; the per-run-identity test's subject moved to the corpus's empty turns, which still mint turn ids.
  • tool surface (2): runtime_tool_specs ignored its declared web policy for the contract-backed half of the catalog, so demo.plan/web.fetch flipped with the process-global policy cache mid-shard. The declared policy now governs both halves; a regression test poisons the ambient cache and pins the snapshot.
  • council needs-attention (2): the wait now covers the full quiesce (state reached AND the run not live) — CI measured the store's word arriving 0.03s before the pin release, and the mid-finally thread re-registering itself after teardown.
  • mcp env allowlist: the API runtime started ComputeModeDaemon with no shutdown path, leaking a subprocess-spawning poller into the process; RuntimeServices now owns and stops it, and the pact rig shuts the runtime down.
  • first-run pact wal: the file snapshot no longer raises when sqlite removes a checkpointed -wal mid-walk.
  • toolsmith parity: the blackbox record's minted effect-ledger identities are stripped, with effect count and outcome multiset still compared.
  • v050 remote-attempt accounting: the notes seam followed the routing to _collect_live_web_notes; the synthetic ledger attempt and the accounting law are unchanged.
  • swarm query overrides: the positive test runs under the explicit VOOL_RESEARCH_NETWORKING opt-in (the fail-closed side has its own boundary test).
  • c18 multilingual: step 1 asserts the current contract — the planner pre-opens the typed task (planned_code_task_start), the journal objective is the literal demand, and the model round seats the continuation control plane under the continue-not-reopen law.
  • rename compatibility (3): checks read the state/lock paths the window module itself resolves instead of the hardcoded macOS layout.
  • ci verification contract: the Linux shards' pinned xvfb-run display prefix is accepted token for token (headful wallet-handoff lane); everything behind it unchanged.
  • launcher ollama: the assertion waits briefly for the background server's log line instead of racing the writer.
  • c18 typo-heavy parity and the bundled-chromium render stay asserted exactly as before; their CI-only failures now dump the recorded wire calls / the browser's stderr tail so the next run names the divergence.

Gate census closure, run 35752689216 (44a27a3, 17f633c)

The self-diagnosing outputs added in 67e0870 named all three remaining failures; each is repaired at its owner (the last line of the previous section held — nothing was weakened):

  • 44a27a3 — the bundled chromium gets its userns right on CI; the c18 rig's persona is pinned. Shard 2's render refused to start (rc-5, Chromium's own SUID-sandbox refusal on stderr): the workflow's AppArmor profile granted the userns right to bwrap alone, so on Ubuntu 24.04 the playwright-cache chromium could not create its namespace sandbox — a runner-confinement fact, not a product defect. The provisioning step now loads one userns-only profile per exact (versioned) playwright-cache binary with the same global-sysctl fallback the bwrap step carries. Chromium's sandbox stays ON and --no-sandbox stays out of the default argv (the workflow contract's no-error-suppression law holds — its tests are green). Shard 0's 1 != 2 exact-spend failure was rig fidelity: the stub's answer_marker matched only a persona named by the operator's own ~/.openclaw registration, which CI does not have; the rig pins VOOL_AGENT_NAME and the stub pops scripted replies only for genuine prompt-bearing chat-endpoint calls. Reproduced pre-fix under a registration-less HOME with identical failure bytes; both c18 suites 10 passed + 8 subtests.

  • 7cb7c4c — the provisioning probe is bounded and cannot hang a shard. The first cut of 44a27a3's probe (run 35767154971, cancelled at 84 min) hung every shard before a single test ran: it launched the full Chrome-for-Testing build with no virtual-time budget and no timeout (the fresh-profile hang the preflight's binary preference documents), and captured output in a command-substitution pipe that chromium's forked chrome_crashpad_handler orphans keep open even after the parent is killed. The probe now runs only the headless-shell build the render lane pins, with the engine's own --virtual-time-budget, wrapped in timeout -k 5s 60s, output to a file, and requires the probe page's own bytes in the dumped DOM. All five paths (pass / hang-with-orphan / rc-5 refusal / empty DOM / hanging full build skipped) verified in a sandboxed dry run.

  • 31f875d — the v050 notes-accounting test's sealed-network premise is pinned. Run 35777904719 shard 8 failed intermittently (call_count 0 == 1, ~50% locally, fails lone at 53a0a4d too): the rig never sealed the adaptive-research lane, whose live engine fan-out occasionally delivered a note — after which the product correctly binds it pre-model and never calls the notes seam. The test now pins the empty adaptive double (the tree-wide idiom); the seam assertion and accounting law are unchanged, and each run drops from ~35s of live fan-out to ~2.3s.

  • 1a57469 — the recovery journey's web lane is sealed; rig HTTP errors carry the daemon log. Run 35777904719 shard 5's three failures shared one root: the journey daemon left the live web open, the adaptive-research recognizer widened an ordinary summarization turn, its live search returned summarizer-tool marketing pages, and the publication gate honestly refused the answer quoting them — the suite's outcome rode on live search results. The price_review_journey daemon now runs VOOL_DISABLE_WEB=1 (scoped: sealing the shared base broke three conversation-intent suites that legitimately ride the web — verified, then narrowed). Shard 6's one-off "HTTP Error 500" on the cancel test's first call is unattributed (traceback lost with the runner's ephemeral home; passes 4/4 locally), so the served rig's chat/chat_stream now raise the same HTTPError with the daemon log tail in the message — the next 500 names itself. Run 35777904719 also carried the first CI proof of the earlier repairs: shards 0 (c18 persona pin), 2 (bundled-chromium userns render), and 4 (documents resend precondition + semantic replay) all green.

  • 17f633c — the served documents retry lane meets the page's own resend precondition. Shard 4's "the retry never reached the runtime": the answer bubble loses .pending at the first content chunk while the run only ends/releases when the NDJSON stream closes, so the rig could call resendLastTurn inside that window, where it silently returns; the retry wait then passed on the undisturbed DOM and sampled a resend that never ran. Reproduced bit for bit (in-window resend no-ops, captured==1); the rig now waits for run.ended && run.released && !isChatBusy first, and the same in-window start then reaches the runtime (captured==2). The exact-2-captured, same-turn, retained-bytes and deletion assertions are untouched; full module 12 passed.

  • aa4bef9 — the notes-precedence rig's live-info search lane is sealed. Run 35790183687 — every job green except one test: the notes-append-whose-payload-reads-as-a-lookup variant lost its route to the model lane, ~50% flaky locally and at the 53a0a4d baseline (not caused by this stack). The failing turn's receipt carried two real sources (discussions.apple.com, reddit.com): the rig patched WebAdapter.search_query for weather only, while the live-info lane searches non-weather queries through WebAdapter.planned_search_query — live. Engines answering nothing → the lane declines by its own law and the turn stays with Notes (pass); engines answering → claim → model lane (fail). The fixture now answers planned_search_query with an empty list (weather stays the one synthetic retrieval; assertions unchanged); the target is 5/5 deterministic at ~2.3s and the file is 54 passed + 3 xfailed twice. This was the fourth rig of this stack found searching the real web — the pattern (v050's adaptive lane, the recovery journey's daemon, this suite's fast path) is recorded in the evidence dir for the owner.

Validation

  • Local cumulative packs green at 67e0870: semantic replay 13/13 (full 252-turn corpus), capability-spec consumers 799, served payment journeys, pact families, council, c18, rename, launcher, API server 111, mobile journey end to end.
  • At 44a27a3/17f633c: both c18 served suites (10 + 8 subtests), the full served documents module (12), the CI verification and delivery contracts (13), and pinned ruff — green.
  • The gate is the full CI run on the final SHA (verify + macOS + 10 Linux shards + build). Run 35752689216's three shard failures are dispositioned above.
  • #31 note: f9e8276 touched answer_coverage, which that corpus pins — the CI run is the check; re-pin per that PR's own law only if the blob-pin tests say so.

Known limitations (unchanged by this PR)

  • Billing holds for unknown BYOK charges remain intentionally unresolved; no invoice reconciliation.
  • The native owner app has not been rebuilt/deployed; synthetic served passes are not live paid-autonomy proof.
  • The bwrap Linux confinement kernel proof rides on CI (583c4fa).

Main remains unchanged pending the completed verification and owner approval.

sls_0x added 30 commits September 21, 2026 07:42
The loader tried VOOL_KEY_PASSPHRASE first against any encrypted-seed
record, so an account-file-sealed record (written by an unattended boot)
hit InvalidTag on the next boot that carried an operator passphrase —
observed as the CI pollution-matrix child session failing all 96
default-home signer reads. The record's protection stamp now decides
which seal reopens it, and a user-passphrase record never falls back to
the account-file secret. key_storage_class() reuses the same reader.
…o this tree

The 101-row ACCEPTANCE_MATRIX.json never migrated into the public tree,
so the C12 join gate (tools/code_assistant_matrix_join.py) and its suite
had no document to join: 20 failures locally and in every CI shard that
carries the file pair. Restored from the pre-migration original (101
rows, identical lineage) with two release-critical authorities rebound
to the current tree: the read-provenance caller edge follows
CodeTaskRuntime._run_step (the _execute seam no longer exists), and the
permission refusal names _decide_tool_call as the producing function
(decide_tool_call is now a consuming wrapper; the edges are its two
public doors) with the split recorded in the authority note. Join
report: 101 rows, 8 typed authorities, release_critical_prose_only 0;
suite 26 passed.
network.signer freezes its record paths at first import, so a whole
pytest process shared ONE keys directory -- resolved against the default
home whenever no test had set VOOL_HOME yet. Any test that overrides the
passphrase in-process re-seals that shared record, and the next
suite-passphrase reader dies with InvalidTag: measured on CI as the
demand-ownership '(InvalidTag:)' demand failures and the pollution-matrix
child session, both surviving the loader-side seal fix alone. The
keychain pin fixture now repoints the signer paths into a per-test
directory and resets the cached keypair, so each test seals its own
record with whatever passphrase it uses and the default home is never
written by the suite again.
The execution gate's tightened hands-off law (only proven read-only
commands run unprompted outside Auto) means a modeless context is MANUAL,
so every workspace.run_tests / apply step in these suites refused with
user_action_required before the planner ever saw a failed validation --
16 operator-phase1 and 8 orchestration-phase1 failures locally and in CI,
with the planner honestly falling back to workspace_stop_after_read. The
green sibling (test_code_task_reviewed_base) already passes
operating_mode auto; these suites now do the same at every envelope and
source_context site. The approval law itself stays policed by the
permission-authority suites.
… gated write

The two manual-mode sabotage tests set manual BEFORE the journey, so the
tightened hands-off law refused the repro step itself (user_action_required)
and the drive never reached the assertion under test -- that manual mode
blocks the WRITE. The journey now runs in auto and the mode switches at
the mutate step, which is the behavior both tests actually pin.
…search fetch tests

record_runtime_tool_progress raised CheckpointTransitionRefused when a
tool-progress record arrived after the checkpoint finalized (measured:
the research tool loop's late recorder crashed three turn-contract
flows). The A7 monotone law's own pins cover downgrades and resumes; a
progress record on a finished turn carries no state meaning, so it is
now discarded with the durable row untouched -- final truth stays
byte-identical and the late recorder cannot crash its caller. The two
web-search backend tests that drive a real _fetch now open the owning
named_background_effect_scope, matching the effect-gateway law every
other fetch caller already follows.
…ules hid

The bare MEMORY.md/TOOLS.md personal-file rules match the public concept pages
docs/concepts/memory.md and docs/concepts/tools.md under core.ignoreCase=true
(the macOS default), so git add silently refused them and git status never
showed the loss -- the same silent-loss mode the memory/ negation documents.
Negate exactly those two tracked pages; every other MEMORY.md/TOOLS.md anywhere
stays ignored, on both ignoreCase settings (new probe test).

The restored memory page drops the absolutes the owning implementation
contradicts: memory lives in VOOL's data home (core/memory/files.py), not the
workspace; it is one store per home, not per-workspace; MEMORY.md is a mirror
of the entries store, so deleting the file is not erasure -- VOOL's forget
operation rewrites both and verifies.
The tools page said changes always ask first. The mode matrix contradicts
that: Auto allows creating and editing files and side-effecting commands to
run on their own, while deletes, overwrites, installs, git history, deploy,
messages, spending and settings still prompt (MODE_PERMISSION_MATRIX in
core/mode_permission_policy.py). Say which mode does what, and that the
workspace and sandbox checks stay underneath either way. Scope the workspace
claim to file tools -- public retrieval is read-only too and reaches outside
the workspace (PUBLIC_READ_ONLY_RETRIEVAL).

The ignore comment and probe docstring overstates the case-insensitive side:
with core.ignoreCase=false only the exact names are ignored; lookalike
lowercase files are merely untracked. Describe the matching per setting;
rules and assertions unchanged.
Measured on the runner (instrumented capture, run 35622837193, SQLite 3.45.1):
the writer's bare autocommit CREATE TABLE raised OperationalError SQLITE_SCHEMA
(17, "database schema has changed"), exactly once per round, in all four rounds;
runs 35615031134 and 35626506389 leg A showed the same failing assertion at the
pinned baseline. The interleaving was not traced directly: SQLITE_SCHEMA's
documented meaning is that the schema changed after the statement was prepared,
so "a concurrent first-use migration committed while the statement was in
flight" is an inference from that documented semantics, not a captured
timeline. storage.db's contract makes the caller owner of the transaction, so
the writer now opens BEGIN IMMEDIATE before its schema-touching work: the
iteration takes the database's write lock across CREATE and INSERT (documented
SQLite locking; the production stores already serialize their write paths on
it), so a migration commit lands entirely before or after the iteration. A
failed iteration rolls back its own statements and closes its handle,
recording rollback/close problems rather than swallowing them. A distinct
regression case pins that a failed caller transaction rolls back its own
statements while previously committed rows survive.
tests/test_legacy_migration_repair.py built its legacy database from
`git show 7ff50e8d...:storage/migrations.py` -- the reviewed tip whose
defining property was zero occurrences of retry_idempotency_key. That
hash does not exist in the public tree (history was rewritten at
migration; the public root is 78f818b), so git show exited 128 on every
clone this suite can run on and all five fixture-dependent cases failed
(CI run 35570948370, and locally: CalledProcessError in
_legacy_schema_sql; the three cases not touching the fixture passed).

The shape is the contract, not the hash -- the same repair the
store-upgrade fixtures already received. The fixture is now the current
SCHEMA_SQL minus exactly the retry-idempotency upgrade (its column and
its dependent unique index), which is what a real pre-upgrade
installation looks like to run_migrations(). Every original case and
assertion is kept, including both sabotage cases.

Adds FixtureContractTests so the fixture cannot silently rot: the built
database must contain runtime_attempts, lack the column and the index,
and the live SCHEMA_SQL must still define the column the synthesis
strips -- otherwise these cases would degrade into fresh current-schema
installs that can never catch the Final-Repair-1 defect class.
network.signer resolves _KEY_DIR = data_path("keys") once, at import.
pytest loads the root conftest and the args' directory conftests
(tests/conftest.py -> apps.vool_agent -> network.signer) as INITIAL
conftests, BEFORE pytest_configure runs, so pinning VOOL_HOME only in
pytest_configure never reached import-frozen paths: _KEY_DIR stayed at
the repository checkout's own .vool_local -- one key record shared by
every pytest session in a job.

Measured locally: a record created under that shared path by an
unattended no-passphrase persist (the random account-file secret) made
a later passphrase-pinned session fail 24/51
test_public_hive_bridge.py cases with cryptography InvalidTag -- the
exact CI signature of the hermetic gauntlet's child sessions (runs
35546610740 and 35570948370, shard tests (3): the pollution matrix
fails because its spawned pytest session's hive cases go red). The
parent session stayed green because its already-cached keypair never
re-read the disk. Which process wrote the mismatched record on the
runner was not identified; the sharing mechanism and the consequence
were both measured and are what this removes.

The root conftest now pins the session runtime home (and the
unattended key-storage modes) at MODULE IMPORT TIME, before any other
conftest or runtime module can load. Every session -- top-level or
spawned child, whose own root-conftest import re-pins to its own fresh
home -- resolves import-frozen AND runtime-resolved paths inside its
own private home. pytest_configure keeps re-asserting the same pins
idempotently.

tests/test_session_home_pins_import_frozen_paths.py guards the
ordering contract: the import-frozen signer key dir must sit inside
the session home and outside the repository checkout, and a SPAWNED
pytest session (the CI failure's shape) must resolve its own home --
not the parent's, not the checkout's.
google_html._fetch goes through open_remote, the one outbound door,
which fails closed outside any turn or background effect ledger --
denied before any socket (R2b). The five transport cases here called
_fetch with no scope at all, so every one died with
RemoteFetchRefusedError(no active turn or background effect ledger)
before the mocked urlopen could deliver the HTTP behavior under test
(4 CI failures on main run 35570948370, reproduced locally: 5 failed).

The production caller always has a ledger; the tests now open the same
sanctioned named_background_effect_scope at their own entry point --
attribution only, nothing granted -- and the retry/refusal semantics
are asserted exactly as before.

Adds the missing ceiling case for the retry contract: a SECOND
consecutive transient status must surface its HTTPError after exactly
two attempts and one backoff -- one retry, never a loop.

The scopeless-refusal law itself stays policed where it already lives
(test_effect_gateway, test_effect_identity_scope_r2b1,
test_live_search_is_one_governed_path); nothing here duplicates that.
configure_home and the provider_home fixtures pin VOOL_HOME, the
runtime-home override, and the db paths, but every test-side restore
was partial: configure_runtime_home(None) cleared the session home the
root conftest installed, and nothing restored the VOOL_HOME env write.
The race children seal their node signer record under the pinned home
with their own passphrase, so the next signer reload in the same pytest
process resolves into that home and fails with InvalidTag under the
suite passphrase. Measured 2026-09-21: shard tests(3) of PR run
35640946053 sent test_identity_lifecycle (2) and tests/legacy/* (2) red
this way; the same four-file order fails identically on main 8153a96
(shards merely did not collide them there).

money_race_probe gains runtime_state_snapshot/restore_runtime_state
(and pinned_runtime composing them) beside configure_home, the mutation
owner; the served-daemon journey, shared_home, and both provider_home
fixtures restore exactly what they pinned. A guard case directly after
the served-daemon journey pins the invariant.
_agent_node_emitter takes session_id as its documented per-session
parameter, but the closure never used it: the streaming seam persists
only what the source context names, so a turn whose context carries no
session key (the conductor hands the raw ask context) wrote its node
rows nowhere -- the blank-Agents-panel regression this emitter exists
to prevent. The emitter now captures a sink context once at creation,
defaulting session_id to the session it was built for, additive and
never overriding a session the caller already named.

The client-turn-id suite drove this seam through a bare object(), which
predates the streaming route and died with AttributeError; its emitter
helper now binds the factory to a carrier of exactly the two production
mixins the streaming route reads, so the real emission code still runs
without booting an agent. 4 CI failures (main run 35570948370, every
PR run since) -> 7 passed; the twelve node-event neighbor suites are
identical to clean main.
The suite still pinned the pre-migration single-job ops/verify.py gate:
the 'Run authoritative verification' step it demands has not existed
since the workflow became the ten-shard matrix + routed macOS job
(owner commits 9fd7ee7/006d874), so the gate case failed at the missing
step and the collect_only/step_disabled sabotage cases crashed mutating
a step that is not there. The ruff pin still asserted 0.15.16, two
versions behind the 0.16.7 the tree adopted with dependabot PR #5 and
that test_install_surface_contracts.py already pins.

The weakening law is restated against the current structure: exact lint
and manifest-collection commands in the verify job, the full ten-shard
matrix, the exact shard pytest prefix consuming the resolver's own file
list, unconditional hidden-file log uploads (PR #11's law) on both test
jobs, build gated on all three, and the same no-disabled-step,
no-swallowed-output scan. The sabotage cases mutate the shard RUN step
now -- a shard weakened to --collect-only executes nothing. 4 CI
failures (main run 35570948370, every PR run) -> 6 passed;
install-surface and delivery contracts unchanged and green.
run_once forwards the served turn's request identity to _run_once_inner
as turn_request (agent.py:1619, present since the public root); the two
lifecycle doubles still had the older three-parameter signature and
died with TypeError before the override's in-force/reset assertions
could run. The doubles now accept the kwarg; the override lifecycle
under test is unchanged. 2 CI failures (main run 35570948370) ->
5 passed; execution-gate neighbors green.
finalization calls gate_publishable_content with runtime_notice (the
gated-publication seam); the suite's double predated the kwarg, so the
gate crashed and finalization published UNGATED -- the exact corruption
the suite pins, silently: with ungated bytes every demand reads
satisfied and the withheld statement wrongly satisfies its slot. The
double accepts the kwarg; every assertion is unchanged. 3 CI failures
(main run 35570948370) -> 5 passed; the six grounding-publication
neighbor suites run identically apart from two pre-existing conductor
cases that fail the same on clean main.
The three direct-call cases (market-quote fallback through urlopen, the
nested wttr.in payload, the empty RSS feed) mock urllib one level BELOW
the canonical fetch door, so open_remote runs for real and the R2b law
denies the fetch before any socket -- the fallbacks silently stood down
(provider 'none') or surfaced the refusal. Their siblings that mock
http_fetch_text above the door never see this. The tests open the same
sanctioned named_background_effect_scope the web-search backend tests
adopted (PR #15/#23 pattern); every assertion is unchanged. 3 CI
failures (main run 35570948370) -> 21 passed; the 5 web-search backend
failures beside them are the cluster owned by open PR #15/#23.
gitlab.py aliased _forge_reads.json_payload -- the response PARSER
(json.loads(body.decode())) -- as _json and used it to SERIALIZE POST
and PUT request bodies. Every GitLab mutating call died at request
construction with AttributeError ('dict' object has no attribute
'decode'), surfaced as ForgeRefusedError(malformed_response): no
merge-request create, no text update, no comment could ever leave the
adapter, on any wire, since the public root. The two serialize sites
use json.dumps; the listing parse site keeps json_payload under its own
name. 3 CI failures (main run 35570948370, failing identically at the
public root) -> 28 passed; the whole tests/repoops package is green
(353 passed).
…ommit

The differential driver froze its turn universe as
git show c23257da...:ops/semantic_phase0_frozen_corpus.json -- a commit
that no longer exists in the public tree (history rewritten at
migration, public root 78f818b). Every public clone exited 128 and the
loader correctly refused, failing the three eligibility cases in CI
since the root. The corpus is now addressed by its content-addressed
BLOB id: the loader still reads the trusted repository's object
database, never the candidate worktree, a tampered corpus committed
anywhere mints a different blob id that the pin refuses, and the pinned
sha256 digest and count checks are unchanged. 3 CI failures
(35570948370) -> 30 passed; the package's remaining 4 failures are the
pre-existing replay/shadow/nonconsuming baseline clusters.
CI run 35665692856: the guard's module-import snapshot blamed a
runtime-home override that an UNRELATED earlier test in the shard had
cleared and never restored -- correct detection of drift, wrong
attribution. The journey now records the exact state it restored in its
finally, and the guard asserts the present state equals that give-back:
immune to earlier drift, still failing on any leak of the journey itself
(verified by removing the restore and watching the guard name the served
home). The default-db piece is excluded -- the package's own autouse
store fixture repoints it per test by design.
#22's guard compares live signer._KEY_DIR against the live session home.
#10's autouse fixture legitimately repoints _KEY_DIR into per-test
directories, so the live-containment assertion fails under the combined
tree even though the import-time pin it guards is intact. The guard now
snapshots _KEY_DIR and the active home at guard-module import (collection
time, before any fixture) and asserts containment against those; the
repo-checkout exclusion stays asserted against both the import-time and
live values. Compatibility fix for merging #10 + #22 on this candidate.

Verified: both guard cases + 16 signer-storage cases pass; the Cluster-7
poisoned order (money served journey + identity + legacy) passes 9/9.
sls_0x added 19 commits September 22, 2026 12:33
The prepaid-balance half of the composer preflight ran for every usepod
pin, including the accountless x402 lane, where no prepaid account
exists: the balance door answered credential_pair_unresolved and the
composer blocked every wallet-paid send before the payment card could
rise. The lane's own readiness (wallet_approval_required) already says
the wallet is the liquidity gate -- the money law mints x402 grants
with credit_liquidity not_required -- so the preflight stops demanding
a prepaid balance for that lane and lets the card ask the operator.

Proven by the served x402 chat journey (card, preview, approval,
receipt) passing again end to end.
A turn the operator stopped between model calls finalized as
failed/chat_model_unavailable_degraded at the HTTP front door, so the
sufficiency writer joined the completed first call with the trace's
success verdict and recorded a fabricated verified_success observation
for a provider the operator simply stopped using.

The terminal outcome now consults the same cancellation marker the
attempt spine already honors (a fired marker plus a non-fulfilled,
non-waiting outcome is CANCELLED), and the failure-stage taxonomy
gains operator_stopped so the trace names the stop instead of
"answer delivered" over text the stop prevented from being
delivered. operator_stopped maps to no learned outcome, so a stopped
turn writes nothing, in either direction.

Cumulative: stage-verdict, sufficiency (8 scenarios + restart),
fulfillment lifecycle, provider timeout, conductor wire and spine
cancellation suites all pass (350 tests).
The funded journey staged refusals the product no longer produces in
that order: accepting the price gate at pin time now binds the route
with the operator's own ceilings, the composer itself refuses a
budgetless paid pin (reason, spend panel, draft kept, nothing sent),
and the per-turn CONFIRM THIS TURN re-ask was removed with the
conversation-scope price acceptance. The journey now proves the real
order -- pin gate, budgetless composer refusal, money-law refusal
through the served door, one settled dispatch with a correlated
receipt, and that a disabled budget is not standing authority -- and
the tool-flow suite asserts the router's internal-tool-selection
narration instead of the removed refusal code. The wallet sheet test
asserts the labeled exact figures and the server's review line the
sheet actually renders.

Funded journey 6, x402 chat 3, tool flow 10, wallet sheet 2 -- all
passing against the served daemon.
Mutation anchor follows the permission seam's function signature after
its refactor; the research acceptance recognizes the current honest
could-not-ground refusal beside the older phrases; the tool-surface
golden records the two calendar-read actions as network reads (their
reviewed contracts in core/runtime_tool_contracts.py are read-only
network operations, effects unchanged); the tooling-context tests
follow the bounded initial catalog with expansion owning domain tools,
keeping the blocked-read refusal and recovery assertions.
…ness contracts

The negative controls "free up space in my schedule" and "free space in
my calendar" are owned by the operator's calendar lane now: it answers
with a real calendar when a provider is configured and an honest
unavailability refusal when none is. The corpus marks them calendar
cases and the acceptance asserts that ownership -- still no machine
intent, no model substitution.

The freshness pair follows the current truth guards: with the web
fallback disabled a value-asserting model answer about a live price is
replaced by the honest no-reading refusal (the stale figure never
reaches the user), and an empty fresh lookup that resolves to memory
degrades honestly through the memory-runtime guard whatever search seam
ran.

Routing acceptance 100 and freshness 25 pass.
…ixtures

A question phrased in local-currency units asks for the place's own
money: holding USD in an XAF jurisdiction is a coherent holding, but a
same-currency subtraction never answers "how many units of local
currency". The recognizer now treats that conversion as missing when
no supplied rate covers it, the request carries the actually-missing
pair, and the refusal names the local currency of the place beside the
holdings.

The meet-and-greet HTTP client test opens the named background effect
scope the outbound door law requires; the intent-arbiter test asserts
the manual-mode authorization the execution boundary now carries; the
retraction fixture keeps a live imperative continuation instead of a
prohibition clause the constraint analyzer now reads. CI's Linux shards
run under a virtual display so the headful wallet-handoff session can
open its window.

Currency lane 347, meet 15, arbiter, retrieval-obligation and delivery
contracts all pass.
A comparison distributed over coordinated attributes asks for EACH
attribute: merged into one unit, a partial answer closed the whole unit
and the missing dimensions silently vanished from the census (the CT-301
recorded run-on). The pure "compare X vs Y on A, B, C and D" shape now
mints one unit per attribute -- the compared subjects stay joined, the
colon-introduced facet list keeps its own one-demand contract, and an
explicit "..., A and so on" tail opens its coordinated item at the
comma.

A receipt-binding overreach is closed on the same seam: a one-typo
recovery now requires the first letter to survive, so "sold" is never
read as a mistyped "gold" and a gold receipt can no longer discharge a
units-sold demand (the CP3 census arithmetic reproduces exactly with the
content guard severed again). The CT-302 repros pin the law where it now
lives: a weather followup mints no inherited gold obligation at all,
with or without the content guard, and no gold needle binds any of its
units.

Demand-unit consumers (1329 tests), the live-data continuation lane
(360) and the test-kit census (37) all pass.
Under the Local Only composite a weather ask ran its contained lookup,
produced the deterministic "live web lookup is disabled" answer, and
then continued -- the frontdoor's whole-turn refusal declines to finalize
so other lanes can still serve the demand. But the composite blocks
every lane the continuation could reach: the research pass found no
certified author and marked the completed honest refusal as task-failed,
destroying it (the first-run denial demo measured exactly this shape).

The refusal now finalizes under the composite, and an attempt whose
every subtask failed while the policy blocks all egress closes as
REFUSED_POLICY -- a refusal is complete evidence about the policy, never
unfulfilled work the record admits -- so the turn's proof reads
RECORDED and the denial claim verifies against the genuinely contained
attempt with zero effect.

Pact family 58, live-data and attempt-continuity 571, grounded and
sufficiency 90 -- all pass.
The journey minted its two pending approvals in a sibling process AFTER
the daemon had already run its once-per-process pending-approval restore,
so the seeded approvals were invisible and the needs-approval leg failed.
The harness now mints both through the same permission gate BEFORE the
daemon boots and hands their ids to the journey, the daemon log goes to a
file instead of an undrained pipe, and the journey evidence lands under
the test's tmp_path -- the committed evidence copy only behind an
explicit VOOL_MOBILE_EVIDENCE_DIR opt-in.

The full journey passes end to end: pairing, both sabotages, attachment,
chat, proof chip, allow and refuse decisions, notifications, replay
refusal, revocation, and the receipt chain.
Sixteen unique failures over the eight test shards, each traced to the
contract that owns it and repaired there; no failure was skipped,
retried away, or had its assertion weakened.

- semantic replay (2): the run_once finalization spine (public tree)
  stashes per-turn identity records on every served result
  (_closure_verdict, _execution_identity, _presentation_selection,
  _semantic_admission, details' tool_call_id), so every one of the 252
  corpus turns failed its same-flag control and the proof covered
  nothing. Those records are now compared by content, identity keys
  dropped per field, in a dedicated test; the identity test's subject
  moved from "weather today" (now a task-bound tool-intent lane) to
  the corpus's own empty turns, which still mint turn ids per run.
- tool surface (2): runtime_tool_specs ignored its declared web policy
  for the contract-backed half of the catalog, so demo.plan and
  web.fetch flipped with the process-global policy cache mid-shard.
  The declared policy now governs both halves; a regression test
  poisons the ambient cache and pins the snapshot against it.
- council (2): _await_state returned at the store's word while the run
  thread still owed its hand-back (pin release, live->paused); CI
  measured the gap at 0.03s and the mid-finally thread re-registering
  after teardown. The wait now covers the full quiesce: state reached
  AND the run not live.
- mcp env allowlist: the API runtime started ComputeModeDaemon with no
  shutdown path; every booted runtime leaked a thread spawning an idle
  probe subprocess forever, and one such spawn clobbered a later
  test's Popen capture. RuntimeServices owns and stops the daemon; the
  pact rig shuts the runtime down.
- first-run pact wal: the file snapshot stat'd files mid-walk while
  sqlite removed a checkpointed -wal; a vanished file can only shrink
  a side, so it is skipped instead of raising.
- toolsmith parity: the blackbox record (public tree) carries the
  effect ledger's minted identities; they are stripped, with effect
  count and outcome multiset still compared.
- v050 remote attempt accounting: the notes seam followed the routing
  to _collect_live_web_notes; the synthetic ledger attempt and the
  accounting law are unchanged.
- swarm query overrides: the dispatch is research networking and fails
  closed without VOOL_RESEARCH_NETWORKING (its own boundary test
  proves that side); the positive test now runs under the same opt-in
  the research runners export.
- c18 multilingual: the planner consumes the repair demand itself
  (planned_code_task_start) and pre-opens the typed task through the
  tool door, so the model round seats the CONTINUATION control plane;
  step 1 asserts the journal's literal objective plus the
  continue-not-reopen law instead of the retired model-called-open
  flow.
- rename compatibility (3): the checks hardcoded the macOS state
  layout while vool_window resolves per-platform; they now read the
  paths the window module itself resolves.
- ci verification contract: the Linux shards run pytest under a
  virtual display for the headful wallet-handoff lane; the pinned
  xvfb-run prefix is accepted token for token, everything behind it
  unchanged.
- launcher ollama: the nohup'd fake server writes its log line from a
  background process; the assertion now waits briefly for that writer
  instead of racing it.
- c18 parity typo-heavy and the bundled-chromium render stay asserted
  exactly as they were; their CI-only failures now dump the recorded
  wire calls and the browser's stderr tail so the next run names the
  divergence instead of a bare count.
@Parad0x-Labs Parad0x-Labs changed the title Integrate runtime repair stack and fix cumulative delivery regressions Integrate runtime repair stack and close the cumulative CI census Sep 22, 2026
sls_0x added 7 commits September 22, 2026 19:13
The engine now captures the browser's stderr for its typed empty-DOM
diagnosis, so _run_chrome returns (returncode, stdout, stderr). The
test fakes that stub the seam still returned the 2-tuple and every
drive through them surfaced as browser_error:ValueError. The fakes
speak the same seam; no assertion changed.
…persona

Run 35752689216 census closure, shards 2 and 0, both failures at their owners:

Shard 2 (tests/test_keychain_unattended_preflight.py real bundled-chromium
render): browser_empty_dom:rc-5 with Chromium's own "SUID sandbox" refusal on
stderr. The workflow's AppArmor profile granted the userns right to bwrap
alone, so on Ubuntu 24.04 (kernel.apparmor_restrict_unprivileged_userns=1)
the playwright-cache chromium could not create its namespace sandbox and
refused to start -- a runner-confinement fact, not a product defect; the
render never ran. The chromium provisioning step now resolves the exact
(versioned) playwright-cache binaries and loads one userns-only profile per
binary -- Chromium's sandbox stays kernel-enforced and ON, --no-sandbox stays
out of the default argv -- with the same global-sysctl fallback the bwrap
step already carries and a loud probe that runs every binary the way the
render engine launches it (full build with --headless=new, headless shell
without) and fails the step on a refusal or empty DOM instead of letting
the render suites cascade. No error suppression: the workflow contract's
|| true ban holds (tests/test_ci_verification_contract.py green).

Shard 0 (tests/test_c18_language_parity_served.py typo-heavy English
anti-drift guard): 1 != 2 generations with the wire dump showing three
empty /api/show probes and one prompt-bearing /api/chat answered as "You are
VOOL...". Root cause is rig fidelity: the stub's answer_marker "You are
Atlas" matched the daemon persona only on a machine whose operator
registration (~/.openclaw) renamed the agent; first boot otherwise names it
from VOOL_AGENT_NAME, then that registration, then "VOOL". On the runner
the marker never matched, the queued CJK answer was never served, the guard
found nothing to repair, and the exact-spend law read the rig, not the
guard. The rig now pins VOOL_AGENT_NAME=Atlas for the daemon (the wire is
identical everywhere) and the stub pops scripted replies only for genuine
prompt-bearing chat-endpoint calls, so capability probes and auxiliary
lanes can structurally never drain the queue. The 2-generation assertion is
unchanged. Reproduced pre-fix under a registration-less HOME (identical
failure bytes), fixed code passes; both c18 suites 10 passed + 8 subtests;
ruff clean.
… lane

Run 35752689216 shard 4 census closure,
tests/test_chat_documents_ui.py::test_served_end_to_end_paste_door_retained_bytes_receipt_restart_retry_and_deletion
failed as "the retry never reached the runtime" (served.captured stayed 1).

Root cause, reproduced against the real served page: the answer bubble loses
its .pending class at the FIRST content chunk, but the run only ends and
releases the chat's slot when the NDJSON stream closes. The test's waits
(content painted + 500ms) can therefore pass while the chat is still busy,
and resendLastTurn -- which silently returns while isChatBusy or before
run.ended -- no-ops. The retry wait that follows is satisfied instantly by
the undisturbed DOM (one non-pending assistant, one user bubble), so the
assertion sampled a resend that never ran. On this machine the window
closes within the 500ms slack; on a loaded two-core CI runner it does not
have to.

The rig now waits for the page's own resend precondition -- run.ended AND
run.released AND !isChatBusy -- before driving resendLastTurn directly; a
user driving the ended-turn affordance meets the same bar. Nothing else
changes: the exact-2-captured law, same-turn identity, retained-bytes and
deletion assertions are untouched. Proven both ways: resend issued inside
the busy window no-ops with captured==1 (the CI failure bit for bit), and
with the precondition wait the same in-window start reaches the runtime
(captured==2). Full module 12 passed; ruff clean.
…le output

Run 35767154971 (cancelled at 84 minutes) never ran a single test: every
shard sat inside the new "Provision the served-browser lane" step from
18:29Z until cancel, and the job cleanup killed bash + chrome + two
chrome_crashpad_handler orphans. Two defects in the probe added in 44a27a3,
both now closed:

1. It launched the FULL Chrome-for-Testing build first (sorted order) with
   --headless=new on a fresh --user-data-dir and NO --virtual-time-budget
   or timeout -- the exact unbounded-launch/fresh-profile hang class the
   preflight's binary preference documents. The probe now runs ONLY the
   headless-shell build the render lane actually pins
   (select_bundled_chromium / VOOL_BROWSER_BINARY), carries the engine's
   own --virtual-time-budget so --dump-dom terminates deterministically,
   and is wrapped in timeout -k 5s 60s. The full build keeps its userns
   grant (identical profile mechanism) but is never launched here; its
   served lanes go through playwright's own launcher, green unmodified in
   35752689216.

2. Output was captured in a command-substitution PIPE. Chromium forks
   chrome_crashpad_handler helpers that inherit that pipe; when the parent
   is killed at the deadline the orphans hold the pipe open and the caller
   blocks forever -- a timeout cannot save a pipe the orphans own. The
   probe's stdout now goes to a file, so no orphan can block the step.

The DOM assertion is stronger, not weaker: the dumped DOM must contain the
probe page's own bytes (vool-probe), not merely be non-empty. All paths
verified in a sandboxed dry run against fake binaries: pass (0.4s), hang
with a pipe-holding orphan (bounded kill, loud error, step not blocked),
rc-5 refusal with stderr surfaced (the original 35752689216 failure shape),
empty DOM, and a hanging full build skipped. Contract tests 13 passed
(no || true, no | tail/tee); ruff clean; YAML valid.
…aptive lane

Run 35777904719 shard 8: test_actual_current_turn_remote_attempt_is_counted
failed as call_count 0 == 1 -- intermittently, ~50% measured locally, and
independently of this stack's commits (shard 8 was green at 53a0a4d; nothing
since touched this area).

Cause, demonstrated with an in-process diagnostic (since deleted): the
test's stated premise is that the sealed test network answers none of the
adaptive research fan-out's engines, but this rig seals nothing -- the
adaptive lane runs LIVE (20-30 real ledger attempts per run, which is also
why every invocation took 33-40s). When a real engine delivers a note, the
product behaves CORRECTLY: prefetch_current_evidence binds the pre-model
evidence (bound=True, ran=False), the turn keeps one governed retrieval,
and the ordinary path's notes seam is legitimately never called -- so the
assertion read the network, not the accounting law.

The test now pins its own premise the way the tree already does
everywhere else (test_agent_runtime_turn_reasoning and a dozen siblings):
_collect_adaptive_research returns the canonical empty double. The seam
assertion, the synthetic ledger attempt, and the web_calls == len(seen)
accounting are unchanged. Five consecutive lone runs pass at ~2.3s each;
full module 67 passed; ruff clean.
…TTP errors

Run 35777904719 census closure for shards 5 and 6.

Shard 5 (three failures in tests/test_provider_answer_recovery_served.py,
all one root): the journey's step turns came back as publication-gate
REFUSALS quoting live summarizer-tool marketing pages (scribbr.com,
quillbot.com) as the turn's retrieved sources, and the two price-axis
tests failed downstream because the journey's reviewed maxima were never
saved. Root cause: the rig's daemon leaves the live web lane open, and the
adaptive-research recognizer widened the ordinary summarization turn
(escalate_current_requirement); its live search then determined the
outcome -- where engines answer nothing the provisional widening is
retracted and the journey passes, which is exactly how the suite passed
before. The product behaved correctly throughout (escalate-on-found-
evidence, gate on support); the rig's premise is a sealed network whose
only remote peer is the synthetic UsePod service. The price_review_journey
daemon now runs with VOOL_DISABLE_WEB=1 via a scoped subclass -- the
sibling suites that share UsePodServedDaemon legitimately ride the web
lane and are untouched (verified: sealing the shared base broke three
conversation-intent tests; the scoped seal leaves them green). Recovery
module 5 passed.

Shard 6 (one failure): test_served_cancel_interrupts_a_running_command
died as a bare 'HTTP Error 500' on its first chat call -- the daemon's own
exception, whose traceback lived in the runner's ephemeral home and is
gone. Passed 4/4 locally at this commit and on CI at 53a0a4d; not
reproducible with the evidence available, so the repair is diagnosability,
not a blind mutation: the served rig's chat/chat_stream now raise the same
HTTPError with the daemon log tail in the message (failure path only; the
type is unchanged so callers that catch it keep their behavior -- the
module's own sabotage/claim lanes exercise that and stay green). The next
500 names itself.
Run 35790183687 shard 7, the run's ONLY failure (every other job green):
test_notes_append_whose_payload_reads_as_a_lookup_stays_with_notes
failed as route='' with the model lane answering a turn whose operator
intent parses fine (apple_note_append) -- intermittently, ~50% locally
across repeated runs of the same command, and at the 53a0a4d baseline too
(not caused by this stack's commits).

Root cause, traced through the failing turn's events: the live-info fast
path claimed the whole turn and its retrieval returned TWO REAL SOURCES
(domains discussions.apple.com and reddit.com) -- the rig patched
WebAdapter.search_query for weather queries only, and the lane searches
non-weather queries through WebAdapter.planned_search_query, which was
LIVE. Where the engines answer nothing the lane declines by its own
nothing-retrieved law and the turn stays with Notes, so this suite's
verdict rode on live search results (fourth rig of this stack found
searching the real web; the product behaved per its design throughout).

The fixture now answers planned_search_query with an empty list: the
weather arm above stays the one synthetic retrieval this rig serves,
routing and result publication remain real, and every assertion is
unchanged. Target test 5/5 deterministic at ~2.3s (was 13-22s of live
searching); full file 54 passed + 3 xfailed twice; ruff clean.
@Parad0x-Labs
Parad0x-Labs marked this pull request as ready for review September 23, 2026 03:47
@Parad0x-Labs
Parad0x-Labs merged commit a0a160a into main Sep 23, 2026
13 checks passed
@Parad0x-Labs
Parad0x-Labs deleted the integration/stack-20260922 branch September 23, 2026 03:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant