Skip to content

Pipeline boundary docs, capability kill switches, and crediting for code the tree cannot reach - #10

Merged
stranske merged 1 commit into
mainfrom
claude/pipeline-boundary-docs
Aug 22, 2026
Merged

Pipeline boundary docs, capability kill switches, and crediting for code the tree cannot reach#10
stranske merged 1 commit into
mainfrom
claude/pipeline-boundary-docs

Conversation

@stranske

Copy link
Copy Markdown
Owner

Four commits, off main (06dff6a), fast-forward. Verified against the exact tree with verify.py:
343 passed, 0 failed, 0/24 max skipped, 81 selftests, 5/5 gates, activation audit 41/41, admission 5 enforced / 3 legacy debt.

Why this exists

Fleet-level conclusions were drawn from local artifacts alone — "the fleet has no work", "true_open: 1 is the ceiling", "something worked those issues without the opener". None were grounded in the pipeline's system-of-record, and the workspace CLAUDE.md already forbids exactly that, naming the same incident shape from 2026-04-29. Nothing in this repo's docs said the Orchestrator is one part of a larger pipeline, so the module rules read as the whole world.

What's here

docs: the boundary. CLAUDE.md gains a §−1 section ahead of §0 — the pipeline (approved-issue queue → opener lane → Actions keepalive → closer lane), this tool's three real interfaces to it, and the rule: before any fleet claim, read the owning Workflows doc and name it. ARCHITECTURE.md and orchestrator-loop.svg move together per the contract, and the SVG <desc> carries the same correction so a screen reader gets it. Two things that mislead if unstated are now stated: "Orchestrator" is overloaded (the keepalive contract's own "Orchestrator Invariants" means the GitHub Actions round orchestration), and double-dispatch is prevented by a coarse whole-round heartbeat, not a per-issue lock.

feat: kill switches and honest reporting. ORCH_DISABLE_STEPS is one mechanism for every step instead of a flag per capability — it announces every skip, touches no stamp, and warns on an unknown key so a typo can't leave a step running while you believe it's off. ORCH_OFFLOAD_DISABLED refuses before any spend. ORCH_REPO_PLAYBOOK=0 stops prompt injection on the next dispatch. Two declared admission exemptions (safety_guard, compute_only), the second requiring a control_point that known_controls() verifies exists in the tree. watch_sweep.py is deleted and stall-watcher credited from the sweep that actually runs hourly. _record_influence_edge_in_conn now refuses a null target unless the caller declares it. unblock() stops telling three different situations to "fix outcome linkage" when for two of them that work doesn't exist. collect() recovers an arm's diff from its exp/ branch when the worktree is gone.

fix: machine-local ledger state is a skip prerequisite. Three tests asserted on declaration-owned ledger fields, which are applied to the running instance and never shipped — green where applied, red on a fresh checkout with the code correct. env_prereq.ledger_declaration_absent() is the sibling that was missing; all three now skip with the missing thing named, bounded by the skip ceiling.

fix: partitioned-review credited. Registered with a real caller (dispatcher.py review-corpus), a kill switch and a dedup finding, but no heartbeat and no fixture — so the audit read it unreachable and caller_exists failed as a consequence. Not my feature; fixed because the gate was red against the shared ledger and the missing parts were two small ones.

Notes for review

  • Re-applied onto main rather than moved from codex/partitioned-review-reconciliation, which is behind main by 1317 lines. Nothing of main's is regressed and no other session's in-flight work travels.
  • aider's route entries are deliberately kept (owner decision): BACKUP_AGENTS already holds it out of routine selection, and --agent aider resolves through those entries. A new test pins all three directions.
  • Three tests I wrote this session were vacuous — each asserted a mechanism against itself rather than against behaviour. All three were caught by break→revert and replaced with behavioural assertions.

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented Aug 22, 2026

Copy link
Copy Markdown

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your current included review allowance is based on your included PR review attempts over the past 7 days.

Next review available in: 7 minutes

Limit details: You’ve used the included review currently available. Your 67 included PR review attempts over the past 7 days set your current allowance at 1 review per hour.

Your organization has reached its usage spending cap. Adjust your spending cap in the billing tab.

How can I continue?

Wait for the limit to reset, then comment @coderabbitai review or push new commits to the PR.

An organization admin can change what happens after included review limits in Billing.

How do review limits work?

CodeRabbit enforces per-developer PR review limits within each organization.

For paid Pro and Pro+ reviews, CodeRabbit uses a developer's included PR review attempts over the past 7 days to set the current hourly allowance. At typical activity levels, the full plan allowance applies. Higher sustained activity can lower the allowance until earlier attempts leave the 7-day window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 4e4b6dab-0af8-47fc-bf41-7374479f909d

📥 Commits

Reviewing files that changed from the base of the PR and between 1a4120c and ade581d.

⛔ Files ignored due to path filters (1)
  • orchestrator-loop.svg is excluded by !**/*.svg
📒 Files selected for processing (25)
  • .verify-floor.json
  • ARCHITECTURE.md
  • CLAUDE.md
  • README.md
  • agent_auth_check.py
  • backlog.py
  • cadence_registry.py
  • capabilities.py
  • capability_activation_audit.py
  • capability_admission.py
  • capability_outcome_bridge.py
  • dispatcher.py
  • env_prereq.py
  • exp_abcd.py
  • exploration_backfill.py
  • feedback.py
  • issue_readiness.py
  • orchestrate.sh
  • redirect_plan.py
  • redirect_shadow.py
  • redirect_sweep.py
  • repo_knowledge.py
  • test_capability_admission.py
  • test_model_tier_resolution.py
  • watch_sweep.py

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

…aware tests

Rebased onto current main and RECONCILED against PR #11, which landed overlapping
work while this was in flight. Three of my commits were dropped as superseded:
PR #11's partitioned-review registration, its test_gate_blocks_execution
correction, and — better placed than mine — its stall-watcher heartbeat, which it
put on `watch.classify_lane`, the shared primitive every driver calls, rather than
in one sweep. Only my truncation fix survives in redirect_sweep.

THE BOUNDARY. Fleet-level conclusions were drawn from local artifacts alone: "the
fleet has no work", "true_open: 1 is the ceiling", "something worked those issues
without the opener". None were grounded in the pipeline's system-of-record, and the
workspace CLAUDE.md forbids exactly that while naming the same incident shape from
2026-04-29. Nothing in THIS repo's docs said the Orchestrator is one part of a
larger pipeline, so the module rules read as the whole world. CLAUDE.md gains a §-1
section ahead of §0: the pipeline (approved-issue queue -> opener lane -> Actions
keepalive -> closer lane), this tool's three real interfaces to it, and the rule —
before any fleet claim, read the owning Workflows doc and NAME it. ARCHITECTURE.md
and orchestrator-loop.svg move together per the contract, and the SVG <desc>
carries the same correction so a screen reader gets it.

Two things that mislead if unstated, now stated: "Orchestrator" is overloaded — the
keepalive contract's own "Orchestrator Invariants" means the GitHub Actions
concurrency/round orchestration, a different system — and double-dispatch is
prevented by a coarse whole-round freshness heartbeat, not a per-issue lock, so no
new dispatch path may assume per-target locking.

backlog.json and issue_readiness's census now carry a `scope` field naming them
orchestrator-local. Prose in a docstring does not travel with the JSON, which is
how a 1-item list became "fleet starvation" twice, six weeks apart. backlog's
payload is extracted to build_payload() so the label is asserted against the real
artifact.

KILL SWITCHES. ORCH_DISABLE_STEPS is one mechanism for every step instead of a flag
per capability: it announces every skip (a silent disable IS the latched-gate
pattern), touches no stamp (deferring work, never faking completion), and warns on
an unknown key so a typo cannot leave a step running while you believe it is off.
Fails toward motion. ORCH_OFFLOAD_DISABLED refuses before provisioning, model
resolution or any ledger write — the selftest asserts the heartbeat is NOT reached,
which is what proves nothing was spent. ORCH_REPO_PLAYBOOK=0 stops playbook
injection on the next dispatch.

ADMISSION. Two declared exemptions, each needing a category AND a rationale:
safety_guard (a confinement's OFF state is more dangerous than its ON state) and
compute_only (stopping a computation blinds a consumer rather than halting an
action). The anti-abuse condition is the point — compute_only must NAME a
control_point and known_controls() verifies that switch exists in the tree, because
"read-only" is exactly what a capability would self-certify to clear a red. offload
is the control case for both: same complaint, real switch.

CREDITING CODE THE TREE CANNOT REACH. heartbeat_reachable asked whether a heartbeat
sits on the entrypoint's path, unanswerable for two shapes. Lane modules are prompt
SCHEMAS that never execute — every non-test reference is a template string — so
dispatcher.build_prompt is the real path. docs-drift-fix-agent lives in another
repository; the bridge observes that repo's completed workflow runs, idempotent on
the run id because this capability's deferral uses its invocation COUNT as a revisit
trigger. Both DECLARED from existing mappings, never inferred, each with a
narrowness control.

LEARNING INTEGRITY. _record_influence_edge_in_conn raises on a null target_event_id
unless the caller passes allow_unlinked — the sibling record_capability_consumption
already did, while this inserted silently and 296 such edges accumulated, 202 from
one backfill that reported plain success. unblock() stops telling three different
situations to "fix outcome linkage" when for two of them that work does not exist.
collect() recovers an arm's diff from its exp/ branch when the worktree is gone;
without it collect returned an empty diff and followup stamped followup-skip.json,
permanently recording "evidence lost" while the branch sat intact.

MACHINE STATE IS A SKIP PREREQUISITE, NOT A FAILURE. Tests asserting on
declaration-owned ledger fields were green where the declarations had been applied
and red on a fresh checkout with the code correct. env_prereq gains
ledger_declaration_absent(), the sibling missing next to ledger_rows_absent; the
skip ceiling rises 24 -> 26 for exactly the two tests that need it, with which and
why recorded in the floor file — because the alternative, asserting machine state as
a code expectation, is what made three tests red on a correct tree.

CONSOLIDATION. watch_sweep.py is DELETED (owner decision). Nothing consumed its
report — its only references outside itself were its own CLI strings and the cadence
registry entry — while redirect_sweep does the identical claims->classify_lane loop
every tick. With PR #11 crediting stall-watcher at watch.classify_lane, the deletion
loses nothing. Fixed in passing: max_reports truncated silently, so a sweep could
report "50 watched" of 300 live claims and read as complete.

HYGIENE. The three _slug helpers are renamed for their namespaces rather than
unified — nothing joins their outputs, and merging them would rewrite existing
entry_ids, prompt paths and backfill- exp_ids for no gain. Credential reads get a
bounded retry and a reason_class so a cloud-sync blip stops reading as a missing
credential. Log rotation is copytruncate, not rename, because a rename during a
running tick detaches the writer. aider's route entries are deliberately KEPT
(owner decision) with a test pinning all three directions.

Verified on current main: 343 passed, 0 failed, 0/26 max skipped, 81 selftests,
5/5 gates, activation audit 41/41, admission 5 enforced / 3 legacy debt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@stranske
stranske force-pushed the claude/pipeline-boundary-docs branch from f8cc6aa to ade581d Compare August 22, 2026 15:27
@stranske
stranske merged commit 5b04bb3 into main Aug 22, 2026
2 checks passed
@stranske
stranske deleted the claude/pipeline-boundary-docs branch August 22, 2026 15:37
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