Skip to content

Land CI repair U2 + U3 on main (merged into stacked bases by #14/#15) - #16

Merged
Steel-tech merged 9 commits into
mainfrom
feat/ci-repair-engine
Sep 28, 2026
Merged

Steel-tech merged 9 commits into
mainfrom
feat/ci-repair-engine

Conversation

@Steel-tech

@Steel-tech Steel-tech commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

Why this PR exists

#14 (U2) and #15 (U3) were approved and merged, but they never reached main. They were merged seconds after #13, before GitHub retargeted them, so each merged into its stacked base branch (feat/ci-watch, feat/ci-repair-ledger) instead. main today has U1 only.

This PR carries exactly the reviewed commits of #14 and #15 to main. There is no new code:

The 9 commits are U2's 5 and U3's 4; see #14 and #15 for the full descriptions and verification.

Unit What Details
U2 Control-plane ledger of CI repair rounds, and the R6 rule for when a job counts as accepted #14
U3 The engine keeps an accepted chain alive as a continuation for repair rounds #15

Both units stay inert until U5: behaviour on main doesn't change.

Note for review: CodeRabbit skipped #14 and #15 because their base wasn't main. This is its first pass over U2 and U3.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added bounded CI repair rounds for eligible accepted attempts. Repair rounds can address reported CI failures and rerun the affected and subsequent phases.
    • Added tracking of repair results and safeguards to prevent acceptance based on a commit that a repair round found failing.
  • Reliability
    • Improved cleanup of temporary files and execution traces when repair continuations are retained or released.

Steel-tech and others added 9 commits September 27, 2026 20:29
A definition with publish.ci.on_fail may push fixes to its own branch
after CI goes red. Each fix is a round, authorized before the push and
recorded after it under the lease token, in a new publish_ci_repairs
table (migration 005): publish_records keeps one row per step by design,
and a second push is a new fact, not a replay.

The ledger enforces what makes a round trustworthy: the frozen
definition must declare on_fail, proof must be recorded, CI must not yet
be green, rounds are numbered in order within the frozen budget, and a
round repairs exactly the head jig last pushed, so a person's push in
between is refused rather than built on. Identical replays return the
stored round; different values conflict.

CompleteAttempt now refuses accepted when the green ci record names a
head any round found red. It does not require the last pushed head, so
a person's fix after the rounds run out stays acceptable on retry.

The worker client gains the three calls; nothing in the worker calls
them until the round loop (U5).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rded

A ci record is permanent, and no round is allowed once it exists, so a
green record naming a head a repair round found red left the job unable
ever to be accepted: CompleteAttempt refused it, and neither the ci row
nor the rounds could move. RecordPublishStep now refuses that record, and
CompleteAttempt keeps the rule as a backstop. Tests now cover two rounds
and a replay that changes only head_before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…r U3)

An accepted, unheld attempt whose definition declares publish.ci.on_fail
now returns a worker.Continuation with its outcome. RepairCI runs one
round: the on_fail phase receives the CI failure as its input envelope,
bounded and framed as data, then every phase after it runs again with
guards, gates, and repair edges live, and the round is judged by the same
acceptance and publish hold as the chain (run is split into run and
conclude so both end through one door).

A round carries the field view, results, gate reports, send count, and
deadline, so it can never buy the attempt more budget, and reports only
the paths it changed. It does not carry sessions or HOME: the HOME is
wiped when the chain ends and when each round ends, roles are re-seeded
on first use, and round sessions get their own key namespace. The
handoff directory is kept. A round that does not end accepted and unheld
spends the continuation.

Release destroys the scratch and is idempotent. The worker's attempt loop
and the direct run path release unconditionally; nothing uses a
continuation until the publishing runner does in U5.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d harden its HOME

Review of U3 found that jig worker's runner removed the attempt's scratch
and closed its trace stream as soon as Execute returned, before any
repair round could use them: a round would have lost the handoff notes
and emitted into a closed trace. worker.DeferToContinuation now moves a
host's cleanup into the continuation's Release, once, after the engine's
own Release, and cmd/jig/worker.go uses it. An unbound publishing runner
now releases the continuation it would otherwise drop.

Execute keeps a panic-safe defer that destroys the scratch unless a
continuation took ownership. A HOME that cannot be wiped (an agent can
make RemoveAll fail with a read-only directory) is never handed to a
round: no continuation after the chain, a spent one after a round. An
accepted round that changed nothing ends as ci_repair_no_change and
spends the continuation. The CI head is capped like every other CI field,
and the bounds, handoff survival, and panic path are now tested.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: f8e65af5-5e9d-4af4-93a4-aaa329edc1db

📥 Commits

Reviewing files that changed from the base of the PR and between b63d686 and bd5d83a.

📒 Files selected for processing (18)
  • cmd/jig/run.go
  • cmd/jig/worker.go
  • docs/plans/2026-09-27-001-feat-ci-repair-plan.md
  • internal/controlplane/ci_repair_ledger.go
  • internal/controlplane/ci_repair_ledger_test.go
  • internal/controlplane/migrate_test.go
  • internal/controlplane/publish_ledger.go
  • internal/controlplane/store.go
  • internal/engine/phase.go
  • internal/engine/resume.go
  • internal/engine/resume_test.go
  • internal/protocol/publish.go
  • internal/worker/claiming.go
  • internal/worker/publish.go
  • internal/worker/publish_ci_test.go
  • internal/worker/registration.go
  • internal/worker/worker_integration_test.go
  • migrations/005_publish_ci_repairs.sql

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


📝 Walkthrough

Walkthrough

The change adds CI repair rounds for accepted, unpublished attempts. The control plane authorizes and records bounded rounds, the engine runs repair phases and resumes later phases, and worker continuations manage scratch and trace cleanup.

Changes

CI repair rounds

Layer / File(s) Summary
Authorize and record repair rounds
internal/protocol/publish.go, migrations/005_publish_ci_repairs.sql, internal/controlplane/ci_repair_ledger.go, internal/controlplane/publish_ledger.go, internal/controlplane/store.go, internal/controlplane/*_test.go, docs/plans/2026-09-27-001-feat-ci-repair-plan.md
Adds protocol types and persistent round records. Authorization checks lease, branch, proof, round order, budget, and expected head. CI recording and attempt acceptance reject green CI on a head repaired by a round.
Run repair rounds in the engine
internal/engine/phase.go, internal/engine/resume.go, internal/engine/resume_test.go, docs/plans/2026-09-27-001-feat-ci-repair-plan.md
The engine attaches a continuation to eligible outcomes. Each round runs the configured repair phase and subsequent phases, resets round state, wipes HOME, and uses bounded CI failure input.
Transfer continuation and cleanup ownership
internal/worker/registration.go, internal/worker/claiming.go, internal/worker/publish.go, internal/worker/publish_ci_test.go, internal/worker/worker_integration_test.go, cmd/jig/run.go, cmd/jig/worker.go, docs/plans/2026-09-27-001-feat-ci-repair-plan.md
Adds worker continuation handling and control-plane client calls. Scratch and trace cleanup can be deferred to a continuation, which is released when no downstream component retains it.

Priority: ⬇️ Low

Estimated code review effort: 4 (Complex) | ~60 minutes

Change: Feature

Sequence Diagram(s)

sequenceDiagram
  participant CIFailure as worker.CIFailure
  participant Continuation as ciContinuation
  participant RepairPhase as configured repair phase
  participant Chain as Runner.runChain
  participant Home as ephemeral HOME
  CIFailure->>Continuation: RepairCI with CI failure
  Continuation->>RepairPhase: run with bounded failure envelope
  Continuation->>Chain: resume after repair phase
  Continuation->>Home: wipe after round
Loading

Suggested reviewers: claude

Merge Risk: ⚪ Minimal · up to bd5d8

This change adds CI repair-round records and engine continuations. They stay inactive until a later unit wires them in, so current behavior is unchanged. No blocking issues were found, and the change appears ready to merge.

Security Architecture Review

Security architecture risk: 🟡 Moderate · up to bd5d8

The new controls constrain repair rounds to an active attempt and limit when a repaired run can be accepted. Recovery after an interrupted or overlapping repair is less certain, and the eventual exposure of CI-supplied data to a repair agent needs scrutiny before the repair loop is enabled. No security exploit was verified.

Retained concerns

  • Medium · reliability · inferred: The repair ledger does not provide one consistent recovery result for all repeated requests: a concurrent identical recording can conflict, and authorization of an already recorded round does not compare its requested starting head. When repair publishing is enabled, these differences could complicate recovery after a remote push or an interrupted round; a demonstrated security bypass was not established.
Security review details

Security Blast Radius

  • inferred — Repair mutations are scoped by an active attempt lease and its publish branch; an eventual repair phase would run with the configured agent tools and worktree, so its potential effects extend beyond the ledger to that attempt's repository branch. Effective deployment-wide reachability was not established.

Security Findings and Attack Paths

  • inferred — No exploit is verified. GitHub check names, conclusions, and URLs can enter the repair phase's previous envelope and then its agent prompt; whether an adversary can supply those fields in an enabled deployment, or induce the agent to act on them, remains unproven.

Trust Boundaries and Controls

  • observed — The new mutation handlers use the shared Origin and request-size gate, then delegate to store methods that verify the active lease. The gate does not authenticate originless clients; the documented perimeter relies on loopback binding. The new read route has no lease check, as with the adjacent publish-record read surface.

Resilience and Maintainability Implications

  • observed — The engine caps the number and lengths of CI checks included in the envelope and labels their metadata as data rather than instructions. Prompt composition still supplies the serialized envelope to an agent; the cap and labeling do not establish an instruction-isolation boundary.

Hardening Proposals

  • proposed — Before enabling worker repair rounds, exercise interrupted and concurrent authorize–push–record recovery, verify the deployed listener perimeter and repair-ledger read policy, and assess how CI metadata is isolated from agent instructions and tools.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 76.79% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 56 functions across 16 files. (2 skipped:… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main change: landing CI repair units U2 and U3 on main. The reference to stacked bases adds process context but does not make the title misleading.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 76.79% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 56 functions across 16 files. (2 skipped: 2 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@Steel-tech
Steel-tech merged commit 4ead632 into main Sep 28, 2026
9 checks passed
@Steel-tech
Steel-tech deleted the feat/ci-repair-engine branch September 28, 2026 05:25
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