Skip to content

fix(workflows): build kernel + restore +x on preflight fixtures before build-1 (unblocks drive loop) - #64

Closed
kjgbot wants to merge 1 commit into
mainfrom
fix/drive-cloud-kernel-build
Closed

fix(workflows): build kernel + restore +x on preflight fixtures before build-1 (unblocks drive loop)#64
kjgbot wants to merge 1 commit into
mainfrom
fix/drive-cloud-kernel-build

Conversation

@kjgbot

@kjgbot kjgbot commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

Diagnosis

The autodrive loop has been stuck. PRs #60, #61, #62, and #63 all
shipped as NEEDS_HUMAN docs reporting "19 SDK test failures" — the
same 19, run after run, with the loop unable to make progress. Prior
attempts to fix sdk/src/ were the wrong direction. A clean checkout
run by hand shows the SDK suite is ACTUALLY GREEN:

188 passed / 9 skipped / 1 file failed only because
kernel/target/debug/relayflowd is not built.

The tests are correct. The environment is wrong.

Root cause: two sandbox faults in the cloud materialization

  1. Kernel binary is never built before build-1 runs npm test.
    The SDK's live-kernel cases exec kernel/target/debug/relayflowd,
    and cargo test does not produce that binary. verify-1 already
    builds the kernel, but that runs AFTER build-1. So build-1's
    npm test sees ENOENT on every live-kernel case.

  2. The sandbox strips +x from tracked scripts and preflight fixtures
    on materialization.
    verify-1 already documents and repairs the
    symptom for ops/cargo.sh (invokes via sh) and for
    sdk/node_modules/.bin (chmod after npm ci). But
    testdata/preflight/*-cli fixtures are untouched, so any test that
    execs a fixture as a CLI gets EACCES.

Together, these account for every one of the "19 SDK test failures"
seen on PRs #60-#63 — without a single change to sdk/src/ or any
test.

The fix

New deterministic step pre-build inserted between assess-gate and
build in workflows/drive.yaml. It:

  1. Builds the kernel: cd kernel && sh ../ops/cargo.sh build
    (bounded with the same run_bounded idiom verify-1 uses;
    failure here is fatal — no point running build-1 without a
    binary the SDK can exercise).
  2. Restores +x on testdata/preflight/*-cli fixtures (guarded so it
    is a no-op if the dir does not exist).
  3. Restores +x on ops/cargo.sh itself (the sandbox strips it).
  4. Restores +x on sdk/node_modules/.bin and esbuild binaries if
    node_modules is already present (guarded).
  5. Prints PRE_BUILD_READY on success so the step's contract is
    legible in logs.

build-1's dependsOn is retargeted from assess-gate-1 to
pre-build-1.

Generator change (required)

ops/gen-drive-cloud.py hardcodes the per-cycle step list as
BASE_STEPS = ["assess", "assess-gate", "build", "verify"]. Without
adding pre-build to that list, the new step never propagates to
workflows/drive-cloud.yaml — and the cloud is exactly where the
fault lives. This is a single-line change and it is required for the
fix to reach the sandbox. Cited here per the brief's rule about
modifying the generator.

Files changed

  • workflows/drive.yaml — authored the new pre-build step; retargeted
    build.dependsOn.
  • ops/gen-drive-cloud.py — added pre-build to BASE_STEPS.
  • workflows/drive-cloud.yaml — regenerated. Final step order:
    sync -> assess-1 -> assess-gate-1 -> pre-build-1 -> build-1 -> verify-1 -> commit-1 -> handoff (8 steps).

Validation

  • python3 -c "import yaml; yaml.safe_load(open('workflows/drive.yaml'))" — passes
  • python3 -c "import yaml; yaml.safe_load(open('workflows/drive-cloud.yaml'))" — passes
  • python3 ops/gen-drive-cloud.py — writes 8 steps, exit 0
  • sh -n on the extracted pre-build command — passes
  • Step DAG inspected: pre-build-1 is between assess-gate-1 and
    build-1, with build-1.dependsOn == ['pre-build-1'].

yamllint and actionlint were not installed in this environment.

Not touched

Per brief constraints: sdk/, kernel/, ops/AUTODRIVE_BRIEF.md,
.github/, docs/, and no tests. The generator was modified only for
the single-line BASE_STEPS update, which is required to propagate
the new step.

Not merging

Per brief: this PR is not merged, not force-pushed, not amended, not
rebased. A human owns the merge gate.

…e build-1

PRs #60-#63 all shipped as NEEDS_HUMAN docs reporting "19 SDK test
failures". A clean checkout run by hand shows the SDK suite is ACTUALLY
GREEN (188 passed / 9 skipped / 1 file failed only because
kernel/target/debug/relayflowd is not built). The prior agent's attempt
to fix sdk/src/ was the wrong direction: the tests are correct, the
environment was wrong.

Two sandbox faults explain every one of the "19 SDK test failures":

  1. The kernel binary the SDK's live-kernel cases exec is never built
     before build-1's `npm test` runs. verify-1 builds it, but that is
     AFTER build-1. The SDK cases fail with ENOENT.

  2. The sandbox strips +x from tracked scripts (ops/cargo.sh) and
     testdata/preflight/*-cli fixtures on materialization. Tests that
     exec a fixture as a CLI get EACCES. verify-1 already documents and
     repairs the ops/cargo.sh symptom (invoking via `sh`).

The fix adds a deterministic `pre-build` step between `assess-gate` and
`build` that:

  * builds the kernel (bounded, fatal on failure — no point continuing
    without a binary the SDK can exercise);
  * restores +x on ops/cargo.sh;
  * restores +x on testdata/preflight/*-cli fixtures;
  * restores +x on sdk/node_modules/.bin and esbuild binaries if
    node_modules is already present;
  * prints PRE_BUILD_READY on success.

Also updates ops/gen-drive-cloud.py's BASE_STEPS to include `pre-build`
so the new step propagates to workflows/drive-cloud.yaml. Without that
one-line change, the fix does not reach the cloud sandbox where the
fault actually lives — defeating the entire point of the PR.

Files changed:
  * workflows/drive.yaml       — authored the new `pre-build` step
  * ops/gen-drive-cloud.py     — added `pre-build` to BASE_STEPS
  * workflows/drive-cloud.yaml — regenerated (8 steps total)

Verified: both YAML files parse; the pre-build shell command passes
`sh -n` syntax check; step ordering is
sync -> assess-1 -> assess-gate-1 -> pre-build-1 -> build-1 ->
verify-1 -> commit-1 -> handoff.
@coderabbitai

coderabbitai Bot commented Aug 30, 2026

Copy link
Copy Markdown

Review Change Stack

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Free

Run ID: 6a1b0c36-777e-42ae-aede-ac3bbf83c037

📥 Commits

Reviewing files that changed from the base of the PR and between 7369f55 and e5dd4c1.

📒 Files selected for processing (3)
  • ops/gen-drive-cloud.py
  • workflows/drive-cloud.yaml
  • workflows/drive.yaml

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

The change adds a deterministic pre-build stage to drive workflows. The stage restores executable permissions, builds the kernel with a bounded timeout, reports status, and runs before the build step.

Changes

Pre-build workflow integration

Layer / File(s) Summary
Generated cloud step sequence
ops/gen-drive-cloud.py
The generated workflow now orders pre-build between assess-gate and build.
Pre-build execution and build wiring
workflows/drive.yaml, workflows/drive-cloud.yaml
The workflows restore executable permissions, build the kernel with a bounded timeout, report status, fail on kernel build errors, and make the build step depend on pre-build.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: ⚪ Minimal · up to e5dd4

The PR adds a bounded pre-build workflow step and updates its generator output; no actionable merge-blocking risk remains beyond normal checks and review.

Poem

A rabbit checks the build path bright

Permissions hop back into right
The kernel builds within its time
Then builders follow in a line
Pre-build thumps its green-marked sign


Note

🎁 Summarized by CodeRabbit Free

Your organization is on the Free plan. CodeRabbit will generate a high-level summary and a walkthrough for each pull request. For a comprehensive line-by-line review, please upgrade your subscription to CodeRabbit Pro by visiting https://app.coderabbit.ai/settings/billing.

Comment @coderabbitai help to get the list of available commands.

@kjgbot

kjgbot commented Aug 30, 2026

Copy link
Copy Markdown
Contributor Author

maintainability lens — PASS

Maintainability review — PR #64

Concerns

1. Kernel build + sandbox repair is now duplicated between pre-build and verify — no shared source of truth.
The new step in workflows/drive.yaml:271-370 copies four things verbatim from verify (workflows/drive.yaml:311-370): the run_bounded helper, the cd kernel && sh ../ops/cargo.sh build pattern, the chmod +x on ops/cargo.sh, and the esbuild bin repair. The comment says "verify-1 already builds the kernel; build-1 does not" — that reads as a design constraint, but nothing binds the two implementations together. A stranger changing the timeout, the timeout env var name (PRE_BUILD_TIMEOUT vs VERIFY_SUITE_TIMEOUT), or the repair set in six months will fix one and silently leave the other stale. The two steps' error tokens already diverge (PRE_BUILD_FAIL vs VERIFY_FAIL, PRE_BUILD_WARN vs VERIFY_WARN). Either factor this into ops/prepare-sandbox.sh and have both steps invoke it, or leave a # keep-in-sync-with: verify marker on both sides so the coupling is discoverable.

2. Implicit contract that the builder will not modify kernel/src.
pre-build builds the kernel once, then hands off to build-1 which has maxIterations: 3 and can edit anything in scope. If a future work package touches kernel/src, build-1's npm test will exercise the pre-build binary, not the edited one — a stale-binary test failure the builder cannot diagnose from its prompt. Nothing in workflows/drive.yaml:271-370 or the builder task at workflows/drive.yaml:276-286 names this constraint. One line saying "if you touch kernel/, rebuild it yourself" in the builder task would close the loop.

3. Silent chmod failures make the OK tokens misleading.
workflows/drive.yaml:342, 353-355 use chmod ... 2>/dev/null || true and unconditionally print PRE_BUILD_PREFLIGHT_BITS=ok / PRE_BUILD_NODE_BITS=ok regardless of outcome. The status token asserts something the code does not verify. Cheap fix: check $? or find ... -exec chmod return, or reword the token to attempted.

Notes

  • ops/gen-drive-cloud.py:39 update is the minimal correct change — the generator is authoritative and drive-cloud.yaml regenerated cleanly. Good.
  • The 20-line comment block at the top of pre-build (workflows/drive.yaml:275-295) mixes design rationale (PR drive: cloud run 1e488cee #60drive: cloud run 569d5183 #63 evidence, run IDs) with per-item commentary further down. Design rationale rots fastest; consider hoisting it to ops/DRIVE-LOG.md or leaving only the invariant ("build kernel + restore exec bits before the builder runs npm test") in the YAML.
  • Introducing PRE_BUILD_TIMEOUT at workflows/drive.yaml:302, 304 adds another undocumented env knob alongside VERIFY_SUITE_TIMEOUT. If both timeouts should track together, unify the name; otherwise document them where operators will look.
  • No test would fail if pre-build regressed to a no-op — this is inherent to embedded shell in YAML, but it means verify is the only backstop. Coupling reason gate1: kernel + sdk skeletons (bootstrap relayflow output) #1 to a shared script would at least let a shell test cover both.

Nothing here is a blocker: the change is a targeted environment repair that unblocks the drive loop, the generator regeneration is right, and the pre-build failure mode is loud where it matters (kernel build fatal, chmods best-effort).

REVIEW_PASSED

@kjgbot

kjgbot commented Aug 30, 2026

Copy link
Copy Markdown
Contributor Author

history lens — FAIL

Blockers

  • pre-build cannot prepare build as claimed. Every workflow step runs in its own sandbox, while ops/cargo.sh deliberately places the kernel binary outside the propagated tree (ops/cargo.sh:27-52, commit 5132079). Thus the binary built at workflows/drive.yaml:318-331 remains in the pre-build sandbox and is unavailable to the builder at :364-367. The chmod changes at :312-316 and :336-355 face the same boundary/materialization fault. This repeats the recorded mistake that “a repair in one [sandbox] does not help another” (ops/BACKLOG.md:688-707) and relies on behavior deliberately removed after kernel build artifacts caused HTTP 413 flushes and silent work loss.

  • The new step reports readiness after failed or absent prerequisites. Chmod failures are discarded with || true; a missing kernel/ is “skipped” despite the preceding fatality claim; missing fixtures and dependencies are also skipped, followed unconditionally by PRE_BUILD_READY (workflows/drive.yaml:312-361; generated equivalent workflows/drive-cloud.yaml:196-219). That contradicts the repository’s fail-closed rule and RFC-0001’s “no unexpected failures” covenant.

Concerns

Notes

  • ops/gen-drive-cloud.py:39 correctly includes the new step, and the generated dependency chain at workflows/drive-cloud.yaml:176-225 matches the authored YAML. No RFC-0001 settled decision is directly reversed; the blockers are historical sandbox-boundary and fail-closed regressions.

REVIEW_FAILED

@kjgbot

kjgbot commented Aug 30, 2026

Copy link
Copy Markdown
Contributor Author

structure lens — PASS

→ Read AGENTS.md
→ Read docs/RFC-0001-everything-is-a-relayflow.md
→ Read workflows/drive.yaml
→ Read workflows/drive-cloud.yaml
→ Read ops/gen-drive-cloud.py

Structure review — PR #64

Scope. Adds a pre-build deterministic step (workflows/drive.yaml:271-371, and the generated workflows/drive-cloud.yaml:176-189 via pre-build in ops/gen-drive-cloud.py:39). No kernel/ or sdk/ code touched, so the closed-kernel-vocabulary and journal-boundary covenants are unaffected.

Concerns

  1. Duplication, not extraction (the main finding). The pre-build body is a near-verbatim reslice of verify's environment-repair preamble (drive.yaml:311-370). run_bounded() is now defined twice in one file (verify:311-321, pre-build:~312-324), differing only in the env var (VERIFY_SUITE_TIMEOUT vs PRE_BUILD_TIMEOUT) and the _label/echo prefix. Every chmod repair (ops/cargo.sh, *-cli fixtures, esbuild .bin) is a third copy of logic verify already owns. RFC §5 decision 13 and AGENTS.md rule 6 say helpers over primitives: the structural answer is a single ops/prepare-sandbox.sh invoked by both steps, not a second inline copy that will drift.

  2. Kernel build happens twice. pre-build runs cargo.sh build (drive.yaml:~334) and verify runs the identical cargo.sh build again (drive.yaml:335). Cargo caches, so it's cheap, but the responsibility is now split across two steps with no single owner — a future edit to one copy leaves the other divergent.

  3. Root cause is patched symptom-by-symptom. The comment itself says the exec-bit strip's layer "is NOT established." This PR adds a fourth symptom repair site rather than locating the materialization fault or centralizing the repair. AGENTS.md rule 6 ("no speculative abstraction") cuts the other way here — this is the opposite risk: accretion of copies.

Notes

  • Step type deterministic matches RFC vocabulary; fail-closed on kernel-build failure is correct (exit 1, no || true on the fatal branch). Sound.
  • drive.yaml is now ~598 lines, past the 500-line smell. It's a YAML spec dominated by embedded shell/comments, not a code module, so I don't treat it as violating rule 1 — but the growth is a direct symptom of concern gate1: kernel + sdk skeletons (bootstrap relayflow output) #1.
  • gen-drive-cloud.py BASE_STEPS addition (line 39) is correct and propagates cleanly.
  • Naming pre-build vs the -n suffixing ("pre-build-1") is consistent.

No blockers: behavior is fail-closed and the intent (unblock build-1's SDK tests) is correct. The only material issue is shape — duplicated helper logic that belongs in a shared ops/ script.

REVIEW_PASSED

@kjgbot

kjgbot commented Aug 30, 2026

Copy link
Copy Markdown
Contributor Author

🎯 review-swarm: FAILED (M:pass H:fail S:pass)

Lens transcripts posted as sibling comments above.

@kjgbot

kjgbot commented Aug 30, 2026

Copy link
Copy Markdown
Contributor Author

Closing per swarm feedback: codex history lens correctly identified that cloud sandbox steps do NOT share filesystem state (per ops/BACKLOG.md:688-707). A kernel binary built in pre-build stays in the pre-build sandbox and is invisible to build-1. Respinning as an in-build-1 fix.

@kjgbot kjgbot closed this Aug 30, 2026
@kjgbot
kjgbot deleted the fix/drive-cloud-kernel-build branch August 30, 2026 20:08
kjgbot added a commit that referenced this pull request Aug 30, 2026
… drive loop, replaces #64/#65/#68) (#69)

* fix(sdk): build kernel + restore fixture +x before npm test (unblocks drive loop)

Root cause the drive loop has been stalling on since PR #63 (2026-08-30):
sdk/tests/live-kernel.test.ts requires a built relayflowd binary
(ops/cargo.sh's toolchain-external target), and the cloud sandbox
does not build it before running npm test. Result: the assessor observes
red tests, writes ops/NEEDS_HUMAN.md, assess-gate parks the run, and no
build/verify step ever fires.

Fix moves the prep INSIDE npm test itself so it's correct for every
caller — the drive assessor, drive builder, verify step, and humans on
a laptop.

Superseded PRs (all closed):
- #64: separate pre-build step — steps have per-step sandboxes, prep
  invisible to build (BACKLOG.md:688-707)
- #65, #68: prep in build's task prompt — assess parks first, so build
  never runs

This lands the prep at a lower layer that all three stages hit.

* fix(sdk): fail-closed on fixture chmod (address swarm blocker on #69)

Both lenses on #69 correctly flagged `2>/dev/null || true` as
failure-hiding: fixtures are tracked, chmod errors should surface.

Replaced with `[ ! -d ../testdata/preflight ] || find ...` — tolerant
of an absent dir, but any real error (missing find, permission denied,
typo in flag) fails test:prep loudly. Maintainability lens's exact
recommendation.

---------

Co-authored-by: kjgbot <kjgbot@agentrelay.dev>
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