Skip to content

feat(autonomy): add C3 auto-merge cell with evidence predicate - #1694

Merged
kyle-sexton merged 9 commits into
mainfrom
feat/c3-auto-merge-path
Jul 27, 2026
Merged

feat(autonomy): add C3 auto-merge cell with evidence predicate#1694
kyle-sexton merged 9 commits into
mainfrom
feat/c3-auto-merge-path

Conversation

@kyle-sexton

Copy link
Copy Markdown
Contributor

Summary

Adds the C3 auto-merge path #1646 identified as resolution shape 1:

  • plugins/autonomy/reference/guardrails.md matrix: C3 merge-policy cell changes from human merge to auto-merge ELIGIBLE after per-class promotion trigger; ships human-gated — mirroring the C2 cell wording exactly; all other cells unchanged.
  • plugins/autonomy/reference/guardrails/work-classes.md promotion table: new C3 auto-merge evidence predicate (≥ 20 autonomous C2 merges over ≥ 14 days with 0 demotion events, plus ≥ 10 autonomous C3 completions with 100% deterministic-gate pass, 0 human-reverted merges, 0 human-confirmed missed-blocking AI-review findings).
  • prompts/loops/loop-lane-prompts.md: rung narrative updated — the "no C3 auto-merge promotion cell" and "stay at c2-mechanical (decision: raise babysit_loop_merge to c3-autonomous, or leave it — the guardrail matrix has no C3 auto-merge cell #1388)" claims are stale after this amendment; the existing "full-autonomy adds nothing over c3-autonomous" analysis is kept, still true.

Predicate thresholds are suggested defaults; the org may bind lower. Ratifying seam flips ahead of the suggested evidence is an operator choice the contract records; automatic fail-closed demotion (any post-merge gate failure, human revert, or verification divergence) still applies.

C4-structural / C5-untrusted-provenance never promote — unchanged.

Operator direction of 2026-07-27 supersedes #1388's "stay" decision, via the path #1388 itself prescribed: amend the guardrail contract first, then flip the seam.

Closes #1646.

Test plan

  • Markdown-only contract change; matrix and table render verified locally
  • Repo-wide sweep for stale "no C3 auto-merge" / "stay at c2-mechanical" claims — only the one loop-lane-prompts.md passage, updated here
  • C2/C4/C5 cells byte-identical to main

Related

🤖 Generated with Claude Code

https://claude.ai/code/session_01PfjSBcWkzNFCydZQYsfUc4

Closes #1646. Operator direction of 2026-07-27 supersedes the 2026-07-25
"stay at c2-mechanical" decision recorded in #1388, via the path #1388
itself prescribed: amend the guardrail contract first, then flip the seam.

- guardrails.md matrix: C3 merge policy becomes "auto-merge ELIGIBLE after
  per-class promotion trigger; ships human-gated" (mirrors the C2 cell).
- work-classes.md promotion table: new C3 auto-merge evidence predicate.
- loop-lane-prompts.md: rung narrative updated to the amended contract.

C4/C5 human-merge floor untouched; demotion remains automatic fail-closed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PfjSBcWkzNFCydZQYsfUc4
@claude

claude Bot commented Jul 27, 2026

Copy link
Copy Markdown

Claude encountered an error after 0s —— View job


I'll analyze this and get back to you.

@github-actions

github-actions Bot commented Jul 27, 2026

Copy link
Copy Markdown

Warning

Automated review did not complete — this is an infrastructure failure, not a review verdict.

Treat any Claude comment on this PR (including a placeholder like "I'll analyze this and get back to you") as incomplete, not "no findings."

Re-running the job, or pushing a new commit, will retry the review.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 393475d69b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread plugins/autonomy/reference/guardrails.md
Comment thread prompts/loops/loop-lane-prompts.md Outdated
…auto-merge cell

Codex review findings on the contract amendment:

- P1: schema documented only C2 auto-merge and the checker rejected both
  merge_policy.C3 "auto" and promotion_state.C3-auto-merge, so guided setup
  could not validate or activate the new cell. C3 joins AUTO_MERGE_ELIGIBLE
  and PROMOTABLE_CELLS, gets the same unratified-promotion gate as C2, and a
  c3-auto-unratified fixture exercises the gate (374 checks pass).
- P2: rung narrative claimed c3-autonomous while this repo's tracked seam is
  still c2-mechanical at this commit; reworded to tie the raise to the
  ratified seam flip (#1693) landing with this amendment, and updated the
  merge-lane copy-block rationale to the post-ratification state.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PfjSBcWkzNFCydZQYsfUc4
@claude

claude Bot commented Jul 27, 2026

Copy link
Copy Markdown

Claude encountered an error after 1s —— View job


I'll analyze this and get back to you.

@claude

claude Bot commented Jul 27, 2026

Copy link
Copy Markdown

Claude encountered an error after 0s —— View job


I'll analyze this and get back to you.

@github-actions

github-actions Bot commented Jul 27, 2026

Copy link
Copy Markdown

Warning

Automated security review did not complete — this is an infrastructure failure, not a review verdict.

Treat any Claude comment on this PR (including a placeholder like "I'll analyze this and get back to you") as incomplete, not "no findings."

Re-running the job, or pushing a new commit, will retry the review.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 902b87b004

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread prompts/loops/loop-lane-prompts.md Outdated
…lands

Codex P1 on the amendment: babysit-loop's rung partition derives merge
eligibility from tracked rung + work class only and never resolves the
effective promotion state, so directing operators to drop the override
over-promised fail-closed demotion. Retain the override, state the wiring
gap, and gate dropping the flag on #1695 plus the evidence predicate.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PfjSBcWkzNFCydZQYsfUc4
@claude

claude Bot commented Jul 27, 2026

Copy link
Copy Markdown

Claude encountered an error after 0s —— View job


I'll analyze this and get back to you.

@claude

claude Bot commented Jul 27, 2026

Copy link
Copy Markdown

Claude encountered an error after 0s —— View job


I'll analyze this and get back to you.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fae728bb91

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread prompts/loops/loop-lane-prompts.md Outdated
…ontract amendment

Codex flagged twice that the rung narrative described c3-autonomous while
the tracked seam still read c2-mechanical in this commit. Root cause was
splitting this repo's ratification across two PRs; fold the one-line
babysit_loop_merge flip into the amendment so contract, seam, and narrative
agree at every commit. Staged seam PR #1693 becomes superseded by this PR;
the other watched repos keep their seam PRs. Also rewraps a paragraph so a
"#1695" reference no longer starts a line (MD018).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PfjSBcWkzNFCydZQYsfUc4
@claude

claude Bot commented Jul 27, 2026

Copy link
Copy Markdown

Claude encountered an error after 0s —— View job


I'll analyze this and get back to you.

@claude

claude Bot commented Jul 27, 2026

Copy link
Copy Markdown

Claude encountered an error after 0s —— View job


I'll analyze this and get back to you.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0b492df439

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .claude/source-control.md
Comment thread prompts/loops/loop-lane-prompts.md
…d decision

The top-level {{MERGE}} guidance still cited #1388's decided-against-raising
as this repository's answer; point it at the 2026-07-27 raise instead, with
the same #1695 + evidence-predicate gate on dropping the override.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PfjSBcWkzNFCydZQYsfUc4
@claude

claude Bot commented Jul 27, 2026

Copy link
Copy Markdown

Claude encountered an error after 1s —— View job


I'll analyze this and get back to you.

@claude

claude Bot commented Jul 27, 2026

Copy link
Copy Markdown

Claude encountered an error after 1s —— View job


I'll analyze this and get back to you.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 890624ce81

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread plugins/autonomy/reference/guardrails/work-classes.md
…-merge cell

Codex P1: the C3 auto-merge predicate is earned on the C2 track record, but
evaluation filtered contrary evidence by exact cell id, leaving C3-auto-merge
effective-promoted after a C2 demotion event. Contrary evidence now also
matches a cell's predicate prerequisites (PROMOTION_DEPENDENCIES), the
demotion note names the prerequisite cell, work-classes.md documents the
cascade, and a promoted-c2c3 + C2-revert evidence fixture pair proves both
cells demote (376 checks pass).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PfjSBcWkzNFCydZQYsfUc4
@claude

claude Bot commented Jul 27, 2026

Copy link
Copy Markdown

Claude encountered an error after 1s —— View job


I'll analyze this and get back to you.

@claude

claude Bot commented Jul 27, 2026

Copy link
Copy Markdown

Claude encountered an error after 1s —— View job


I'll analyze this and get back to you.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0f3b8f4a67

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread plugins/autonomy/skills/setup/scripts/check-security-binding.mjs
…ound unpromoted

Codex P1: the cascade caught contrary EVIDENCE against the prerequisite but
not a prerequisite already BOUND unpromoted (post-demotion binding update),
so C3-auto-merge stayed effective-promoted over an empty evidence stream.
The resolver now lowers a promoted dependent cell whenever any prerequisite
entry is missing or not state "promoted"; a promoted-c3-only + empty
evidence fixture pair proves it (386 checks pass).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PfjSBcWkzNFCydZQYsfUc4
@claude

claude Bot commented Jul 27, 2026

Copy link
Copy Markdown

Claude encountered an error after 0s —— View job


I'll analyze this and get back to you.

@claude

claude Bot commented Jul 27, 2026

Copy link
Copy Markdown

Claude encountered an error after 1s —— View job


I'll analyze this and get back to you.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6931bef7ef

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread plugins/autonomy/skills/setup/scripts/check-security-binding.mjs Outdated
…ion to dependents

Codex P1 (mixed-epoch): a C2 contrary event landing after C2's ratified_at
but before C3's later ratified_at demoted C2 while being pre-epoch-ignored
for C3, leaving the dependent effective-promoted without its prerequisite.
The resolver is now two-pass: pass 1 resolves every cell's own effective
state in its own epoch; pass 2 lowers any promoted dependent whose
prerequisite is missing, bound unpromoted, or effective-unpromoted, naming
the reason. This subsumes the earlier event-scan cascade. Fixture pairs
cover direct cascade, bound-unpromoted prerequisite, and the mixed-epoch
case (392 checks pass).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PfjSBcWkzNFCydZQYsfUc4
@claude

claude Bot commented Jul 27, 2026

Copy link
Copy Markdown

Claude encountered an error after 1s —— View job


I'll analyze this and get back to you.

@claude

claude Bot commented Jul 27, 2026

Copy link
Copy Markdown

Claude encountered an error after 1s —— View job


I'll analyze this and get back to you.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0f3e25653d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread plugins/autonomy/skills/setup/scripts/check-security-binding.mjs
…ratified

Codex P1: with C3 ratified Jul 1, a C2 revert Jul 10, and C2 alone
re-ratified Jul 20, the revert became pre-epoch for C2 and the
current-state-only dependency check revived C3 without any C3 re-earn.
Prerequisite events are now also judged in the DEPENDENT's epoch during
pass 1, so the demotion sticks until the dependent itself is re-ratified;
pass-2 current-state propagation is unchanged. A promoted-c2reearned-c3 +
revert evidence fixture pair asserts C2 promoted, C3 unpromoted (398
checks pass).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PfjSBcWkzNFCydZQYsfUc4
@claude

claude Bot commented Jul 27, 2026

Copy link
Copy Markdown

Claude encountered an error after 0s —— View job


I'll analyze this and get back to you.

@claude

claude Bot commented Jul 27, 2026

Copy link
Copy Markdown

Claude encountered an error after 0s —— View job


I'll analyze this and get back to you.

@kyle-sexton
kyle-sexton merged commit ba789fe into main Jul 27, 2026
31 checks passed
@kyle-sexton
kyle-sexton deleted the feat/c3-auto-merge-path branch July 27, 2026 05:04

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b90f2b03ba

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

const VERIFICATION_STRENGTH = { "not-required": 0, advisory: 1, blocking: 2 };

const PROMOTABLE_CELLS = new Set(["C2-auto-merge", "C3-ai-review-blocking"]);
const PROMOTABLE_CELLS = new Set(["C2-auto-merge", "C3-auto-merge", "C3-ai-review-blocking"]);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Bump the autonomy plugin version to ship this cell

Existing autonomy-plugin installations will not receive the new C3 schema, validator, resolver, or guardrail references when users refresh the marketplace because plugins/autonomy/.claude-plugin/plugin.json remains at 0.11.3; this repository explicitly documents the manifest version as the plugin cache key and sole delivery vehicle (docs/MIGRATION-PLAYBOOK.md:371-375). Bump the autonomy manifest version and add the corresponding changelog entry so this newly accepted cell is actually delivered.

Useful? React with 👍 / 👎.

kyle-sexton added a commit to melodic-software/ci-workflows that referenced this pull request Jul 27, 2026
## Summary
Raises `babysit_loop_merge` from `c2-mechanical` to `c3-autonomous` in
the team-tracked loop-lane config. Per the loop-lane convention,
merge-rung raises are seam-only reviewed changes; merging this PR is the
ratification, per the C3 auto-merge contract amendment
(melodic-software/claude-code-plugins#1694) and operator direction of
2026-07-27. The C4-structural / C5-untrusted-provenance human-merge
floor is unconditional and unaffected.

## Test plan
Config-only change. Verified `c3-autonomous` is a valid rung name per
the plugin's config-resolution reference (`human-only` < `c2-mechanical`
< `c3-autonomous` < `full-autonomy`) and that only the one value line
changed.

## Related
- Contract amendment: melodic-software/claude-code-plugins#1694
- melodic-software/claude-code-plugins#1309
- Loop-lane convention:
https://github.com/melodic-software/claude-code-plugins/blob/main/docs/conventions/loop-lane/README.md

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01PfjSBcWkzNFCydZQYsfUc4

No linked issue in this repository — the operator-ratified rung raise is
tracked fleet-wide in melodic-software/claude-code-plugins#1309.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
kyle-sexton added a commit to melodic-software/standards that referenced this pull request Jul 27, 2026
## Summary
Raises `babysit_loop_merge` from `c2-mechanical` to `c3-autonomous` in
the team-tracked loop-lane config. Per the loop-lane convention,
merge-rung raises are seam-only reviewed changes; merging this PR is the
ratification, per the C3 auto-merge contract amendment
(melodic-software/claude-code-plugins#1694) and operator direction of
2026-07-27. The C4-structural / C5-untrusted-provenance human-merge
floor is unconditional and unaffected.

## Test plan
Config-only change. Verified `c3-autonomous` is a valid rung name per
the plugin's config-resolution reference (`human-only` < `c2-mechanical`
< `c3-autonomous` < `full-autonomy`) and that only the one value line
changed.

## Related
- Contract amendment: melodic-software/claude-code-plugins#1694
- melodic-software/claude-code-plugins#1309
- Loop-lane convention:
https://github.com/melodic-software/claude-code-plugins/blob/main/docs/conventions/loop-lane/README.md

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01PfjSBcWkzNFCydZQYsfUc4

No linked issue in this repository — the operator-ratified rung raise is
tracked fleet-wide in melodic-software/claude-code-plugins#1309.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
kyle-sexton added a commit that referenced this pull request Jul 29, 2026
…ite (#1690)

## Summary

Implements #1650: a deterministic, off-machine escalation notification
for loop lanes, composed entirely from documented first-party
mechanisms.

- **Escalation record write (loop-lane convention v4.0.0,
escalation-contract change → major bump).** Every escalation an
autonomous lane files (`work-loop`, `babysit-loop`) now also creates
`.claude/lane-escalations/<UTC-stamp>-<item>-<lane>.json` with the Write
tool, in the same step that posts the machine-marked escalation comment
and **immediately before** it — one new file per NEWLY filed escalation
(suppressed by the marker read the step already performs, so standing
escalations never re-fire), `loop-lane/escalation-record@1` shape,
summary restating only the already-public comment text.
- **Write ordering is contract.** The record write and the marker post
are not atomic. Record-first, a stop between them loses the tracker
comment, which the next cycle re-files — one duplicate notification,
recoverable. Marker-first loses the notification *permanently and
silently*, because the standing marker suppresses the record on every
later cycle. The convention states the ordering with that rationale;
both skills carry it at the site; both skills' evals assert it.
- **Ignoring the record directory is a lane-start preflight, not a
consumer obligation.** Nothing delivers a tracked ignore rule into a
consuming repo, so both lanes gain cycle-shape step 0: if `git
check-ignore -q .claude/lane-escalations/` reports the path unignored,
append it to the clone's untracked `$(git rev-parse
--git-common-dir)/info/exclude`. No consumer change, no tracked file
touched, a no-op where the repo's own `.gitignore` already carries the
rule, and it repairs an existing consumer that upgrades without
noticing. A tracked rule added through a repo's lane-enabling adoption
change stays the durable form.
- **Out-of-band notification seam (consuming-repo config with a
documented default).** The consuming repo's tracked
`.claude/settings.json` registers a `PostToolUse` hook — `matcher:
"Write"`, `if: "Edit(/.claude/lane-escalations/**)"`, `type: "http"` —
that POSTs the hook JSON to a repo-chosen endpoint, secret carried in a
header via `allowedEnvVars`. Deterministic (no model judgment), no
claude.ai subscription or Remote Control dependency. The seam documents
its real egress (full `PostToolUse` payload including session metadata —
consumer opt-in), its silent-failure mode with a wire-time verification
step, and its degradation (no hook → tracker + local notify unchanged;
record files are inert exhaust). `PushNotification` and `slack`-plugin
outbound are named as optional model-discretionary layers, never the
deterministic leg.
- **The seam binds to the session's project, never to the repository a
lane targets.** Stated as a requirement rather than a preference: a lane
scoped to another repository POSTs to the launching project's endpoint,
so running from the target's checkout is required whenever that
repository's endpoint must hear. Writing the record into the target's
tree was rejected and the reasoning recorded — the `if` rule anchors at
its own settings source, so such a record matches no loaded rule and
fires nothing, trading a wrong-endpoint notification for silence.
- **Stale-claim fix.** `plugins/autonomy/hooks/lane-notify.sh` no longer
claims "there is no remote/Slack/push transport … (none exists as a
marketplace primitive yet)"; comment-only change, behavior untouched
(contract test 10/10).
- **Fan-out grounding.**
`plugins/autonomy/reference/runner/escalation.md` binds the severity
fan-out's channel leg (deterministic http hook) and personal-push leg
(`PushNotification`, model-discretionary) to shipped first-party
transports.
- Version bumps: loop-lane convention 4.0.0; `work-items` 0.27.0;
`source-control` 0.35.0; `autonomy` 0.11.5. This repo also gitignores
`.claude/lane-escalations/` (it dogfoods the lanes).

## Open design question resolved (with citation)

**Does the harness support project-scoped `type:"http"` hooks configured
per consuming repo?** Yes. Per https://code.claude.com/docs/en/hooks
(fetched 2026-07-26): hooks are configurable in project
`.claude/settings.json` (and every other settings scope), and the `http`
handler type is supported on all hook events except
`SessionStart`/`Setup` — `PostToolUse` included. Header values
interpolate env vars only for names listed in `allowedEnvVars`; the
`url` field never interpolates, which is exactly why the seam is
consuming-repo settings rather than plugin-shipped config. Supporting
`if`-rule semantics (file rules in `Edit(...)` form covering the Write
tool; `/`-anchored at the settings source) per
https://code.claude.com/docs/en/permissions (fetched 2026-07-26). A
`FileChanged` hook was avoided as the issue directs: its matcher takes
literal filenames (no path globs) and firing on Claude-written files is
undocumented.

## Verification

- Fresh-context verifier (opus, rationale withheld) audited the diff
against the issue's acceptance criteria, the rejected-concept list, and
live official docs: initial round returned 6 findings (3 blocking —
egress disclosure, silent-failure mode, duplicate suppression), all
fixed; re-verification returned **PASS** (all findings resolved, every
new harness claim doc-supported verbatim, markdownlint clean), plus two
Low wording-only follow-ups, both applied.
- Three review findings from `chatgpt-codex-connector` fixed on this
branch (P1 marker-only partial write → write ordering; P2 ignore-rule
delivery → lane-start preflight; P2 webhook/target-repo binding →
requirement stated, target-aware path rejected with reasoning).
Preflight mechanics verified empirically in this checkout: `git
check-ignore -v` resolves through the worktree, and `--git-common-dir`
resolves to the clone's shared `.git`, whose `info/exclude` already
carries entries of the same shape.
- Gates: markdownlint-cli2 0 issues on all changed markdown; shellcheck
clean on `lane-notify.sh`; `lane-notify.test.sh` PASS=10 FAIL=0; all
three `plugin.json` manifests parse.

Closes #1650

## Related

- Refs #1619 — the `source-control` 0.33.2 pre-compute fix that landed
on `main`; its version lineage is the source of the recurring changelog
conflict resolved on this branch.
- Refs #1694 — C3 auto-merge cell landed on `main` this cycle, an
adjacent autonomy guardrails surface; no overlap with this PR's
escalation contract.
- Refs #1657 — the read-trust boundary and rung-partition changes that
landed on `main` as `work-items` 0.26.0 / `source-control` 0.34.0; this
branch composes above them (0.27.0 / 0.35.0), retaining both sides'
changelog entries.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
kyle-sexton added a commit that referenced this pull request Jul 30, 2026
…uests (#1781)

## Why

A review that lands **after** a merge has nowhere to go:

- the ruleset's `required_review_thread_resolution` is a **merge-time
predicate** that already passed;
- the babysit lane works *open* PRs, and a merged PR leaves that queue;
- nothing on a merged PR surfaces its open threads — GitHub shows the
merge, not the findings.

Six findings — one **P1** — posted **46 seconds after #1720 merged** and
sat unread for a day. They
surfaced only because a later session happened to audit that merge
batch. Nothing was bypassed; the
gate was satisfied *because the threads did not yet exist*.

The morning brief is the right home: read-only, unattended, and already
where attention signals land.

## What it does

Compares each unresolved thread's **first-comment timestamp** against
the PR's `mergedAt`, and
reports only threads the gate could never have seen. A thread that
predates the merge was visible to
the gate — that is an ordinary unresolved thread, not this failure mode,
and it stays out.

- **One line per PR, at that PR's worst severity, with a finding
count.** Several findings on one PR
are one thing to go look at; repeating the title per thread buries every
other PR. Collapsing on
the *worst* severity means a P0 sitting beside advisory findings can
never be softened.
- **Severity survives to the operator** — a stranded P1 must not read
like a P3.
- **`--stranded-days`** (default 3) — wide enough to cover slow bot
review *and* an operator-absent
  weekend.

## It fails loud, not clear

A GraphQL error document is well-formed JSON that simply carries no
`data`. The extraction would
yield an empty list and render **"every merged PR in the window is
clear"** — an all-clear asserted
from an answer never received, which is the same fail-open shape this
section exists to catch.

This is not hypothetical: a rate-limit error did exactly that during
development. An API error now
says explicitly that it is *not* an all-clear, and prints the message.
Covered by a regression case.

## This is a standing leak, not a one-off

Its **first live run** against this repository immediately surfaced four
more stranded findings on
other merged PRs — including a **P1 on #1694** (merged `05:04:45Z`,
finding posted `05:05:20Z`, 35
seconds later) recording that a shipped `autonomy` cell **never reached
installations**.

## Verification

- `morning-brief.test.sh`: **30 → 63 cases, 0 failures.**
- The **negative** cases carry the weight — a pre-merge thread, an
already-resolved post-merge
thread, and a merge outside the window must all stay silent, or the
section is noise rather than
signal. Plus: collapse-does-not-soften-severity, highest-severity-first,
window-widening, and the
  API-error case above.
- The fixture mirrors the real #1720 shape, including the 46-second gap.
- `shellcheck -x` on script and test — clean. One `SC2016` is declared,
not blanket-suppressed: the
`$owner`/`$name`/`$endCursor` in the GraphQL query are server-side
variables bound by `-F` and
  **must** reach the server unexpanded.
- `node scripts/validate-plugin-contracts.mjs` — 43 setup skills, 2153
files, pass.
- `npx markdownlint-cli2` on both changed markdown files — 0 errors.

### Live run — posted in full in the comments below

A live run on the current branch found **44 merged PRs carrying
post-merge findings in a five-day
window: 0 P0, 10 P1, 34 P2.** Among the P1s: **#1503**, a
guardrail-bypass fix whose own review
landed unread, and **#1322** with 5 findings.

Read the **second** comment for the authoritative figures — the first
was produced by the
pre-review severity logic and reported a false P0, which review then
caught. No truncation warning
fired, so the read is complete.

The five-day window filter was spot-checked against `mergedAt` (a PR
numbered #969 in a 5-day window
looks wrong until you check: it merged `2026-07-25`, 4.2 days before the
run).

This is a far larger leak than the six findings that exposed it.

## Related

Closes #1777
Refs #1720
Refs #1759

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
kyle-sexton added a commit that referenced this pull request Aug 9, 2026
…h an atomic claim (#2065)

## What

`plugins/autonomy/hooks/lane-stop-gate.sh` bound an arm record to its
first
presenting session with a read-then-write, and honored the record from
the
value read *before* that write. Two Stop invocations presenting the same
fresh
arm id both read it unclaimed, both wrote, and the last `mv -f` won — so
**both
honored the arm for that event**, while the loser, possibly the
legitimate
lane, was refused on every later stop and **ran ungated from then on**.

`mv -f` made the rename atomic; the read → modify → write around it was
not,
and `GATE_ARM_JSON` was assigned the pre-claim JSON unconditionally, so
the
record was honored without ever re-reading what actually persisted.

## How

- The claim is an **exclusive create** — `set -o noclobber` on a `>`
redirection, i.e. `O_CREAT|O_EXCL` — of a `<record>.claim` sidecar
holding the
owning session id. Same primitive `statusline-tee.sh` already uses, and
its
recorded reason for avoiding `flock` (absent on macOS) applies here too.
Both
the `umask` and the option are scoped inside a subshell; verified
empirically
  that neither leaks to the caller.
- `GATE_ARM_JSON` is assigned **only past the ownership verdict**. An
unowned
record contributes no config at all, which is what stops a replaying
session
  from being honored.
- A claim file exists only because some process won that create, so an
**empty**
one is that winner caught between its create and its write — not an
ownerless
  record. Reading it in that instant would hand one fresh arm to every
concurrent presenter and reopen the race a few microseconds wide, so the
owner
  read is retried over a bounded budget.
- **Fail direction preserved in both directions.** An unwritable store
leaves no
claim, and a claim whose owner never lands exhausts the budget; both
**honor**
the arm — the gate stays ON. A legitimate lane silently losing its gate
is the
harm, never an extra gated stop. Refusing a durably ownerless claim
would make
the record permanently unclaimable, which is the original harm in a new
shape.
- **Compatibility.** A record claimed before the sidecar existed carries
its
owner in the record itself and has no sidecar; that field stays
authoritative,
so an upgrade cannot let a second session claim a record already bound
to a
  live lane. Nothing writes it any more.
- `lane-stop-gate-arm.sh` clears the sidecar **before** it (re)writes a
record,
so a re-armed id starts unclaimed rather than staying bound to a dead
session.
The clear precedes the write deliberately: a crash between the two then
leaves
the old record with no claim (an extra gated stop) instead of a fresh
record
beside a stale claim, which would refuse the new lane on every stop
until the
record aged out. The record it writes is built fresh by `jq -n` and
never
carries an owner, so no owner can be orphaned. The gate's TTL sweep
drops
  record and sidecar together.
- The claim path carries **the record path's own `[[ -f ]]` asymmetry**.
It is a
second predictable name in the same store, and without a type guard a
planted
FIFO took the write with no reader and hung the entire Stop event —
which the
harness resolves by allowing the stop, i.e. an ungated lane on every
attempt.
Anything at that path this hook did not write now decides nothing and
the arm
  is honored.
- One spelling of the sidecar path (`gate_arm_claim_path` in
`lane-stop-gate-lib.sh`) so the gate and the arm helper cannot diverge.

## Verification

`bash plugins/autonomy/hooks/lane-stop-gate.test.sh` — **83 pass, 0
fail**,
including six new cases:

| Case | Asserts |
| --- | --- |
| 41 | a pre-claimed record is refused for a non-owner and honored for
its persisted owner |
| 42 | re-arming clears the previous lane's claim, and the relaunched
lane can claim it |
| 43 | a record claimed before the sidecar existed stays bound to its
legacy owner |
| 44 | six presenters racing one fresh arm id — exactly one is honored,
and the persisted claim names that session |
| 45 | an ownerless claim still honors the arm (fail direction: gate ON)
|
| 46 | a non-regular file at the claim path neither hangs the hook nor
loses the gate |

Every claim-ownership case pins the **exit code** as well as the
decision; a
stdout-only assertion would pass a hook that started exiting 127 in
silence,
which is the regression shape this effort has already hit once.

Nothing here was reasoned about where it could be measured:

- An **independent fresh-context verifier**, given the finding and the
branch
but not the author's rationale and told to refute, ran the *new* test
file
against `origin/main`'s hooks: **76 pass / 6 fail**, among them `6 of 6
concurrent presenters were honored for one fresh arm id`. The race
reproduces
on main and the new cases are genuine regression tests, not decoration.
It
also ran 150 × 6 function-level and 25 × 6 end-to-end concurrency trials
  against the fix: zero multi-winner, zero mismatch.
- The **empty-claim window** was demonstrated, not inferred: with a
pause
  injected between the exclusive create and the owner write, six of six
concurrent presenters were honored. With the bounded re-read, that same
  injected pause yields one of six across repeated runs, and a pause
deliberately exceeding the budget over-gates (four of four honored)
rather
  than leaving any lane ungated.
- The **FIFO hang** was demonstrated the same way: with the type guard
removed
from a scratch copy the hook never returns; with it, the hook completes
and
  the gate stays on.

Also green from the worktree root: changelog parity (`--check`,
`--check-order`,
`--check-bump` vs `origin/main`), shell-portability lint,
`check-silent-skips.sh`,
`check-changed-skills.sh origin/main`,
`check-contract-clause-coverage.py`,
`validate-plugins.sh`, ShellCheck, shfmt, markdownlint.

## Known and deliberate

- Exactly one session ends up with the arm, so a **leaked arm id still
strands
the loser** — that is the first-presenter-wins contract, not the race,
and it
is unchanged by this PR. What changes is that the binding is now decided
once,
  atomically, instead of by whichever writer happened to land last.
- A **mid-lane downgrade** to a version that predates the sidecar would
ignore a
live claim, since 0.13.1 records the owner only in the sidecar. The
upgrade
  direction is handled and pinned by case 43.

## Related

- Review finding `PRRT_kwDOTCGFQM6WACHN` (#1865), P1, verdict REAL.
- `PRRT_kwDOTCGFQM6T8HlP` (#1694) is already fixed and deliberately
**not**
folded in: its one open sub-ask (a missing C3 changelog line) harms no
install
  and is parked for the operator.

No linked issue

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
kyle-sexton added a commit that referenced this pull request Aug 13, 2026
…abysit-loop partition (#2566)

Closes #1695

Minimal in-repo peel implementing the frontier-consensus ruling: trusted
promotion-evidence resolution contract on the rung partition with
fail-closed behavior when evidence is unavailable, untrusted, partial,
or forgeable. Does not enable autonomous merge on unqualified evidence.
Full three-arm resolver deferred; `--merge human-only` launch pin stays
until the seam qualifies.

## Summary

- **Contract:**
`skills/babysit-loop/reference/promotion-evidence-resolution.md` —
promotable cells (`C2-auto-merge`, `C3-auto-merge`), trusted seam
requirement, fail-closed table, partition interaction
- **Partition:** cycle-shape step 3 resolves effective promotion state
before work-class eligibility; unavailable seam → every cell
effective-unpromoted → no C2/C3 autonomous merge
- **Config:** `config-resolution.md` notes the gate under merge
dimension
- **Gotcha:** SKILL.md documents that tracked rung alone is not merge
permission
- **Version:** `source-control` 0.53.24

## Tests

- Eval 10: promotion-evidence fail-closed at `c3-autonomous` tracked
rung
- Evals 2, 6–8 updated for promotion gate semantics
-
`test_skill_contract.py::test_babysit_loop_promotion_evidence_contract_is_wired`

## Related

- #1694 — C3 auto-merge cell (Codex review origin)
- #1682 — Finding 1 gotcha sequencing (tier-flooring vs invoke
babysit-prs); no gotcha text added here per minimal peel scope
- Frontier consensus ruling on #1695 (IMPLEMENT_NOW fail-closed
contract; defer three-arm resolver)

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Kyle Sexton <kyle-sexton@users.noreply.github.com>
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.

Merge-rung ladder reaches C3 but the guardrail matrix defines no C3 auto-merge path

1 participant