Skip to content

feat(runtime): execute the transactional parent merge of child changesets - #322

Merged
OBenner merged 3 commits into
developfrom
feat/subagent-parent-merge-develop
Jun 10, 2026
Merged

feat(runtime): execute the transactional parent merge of child changesets#322
OBenner merged 3 commits into
developfrom
feat/subagent-parent-merge-develop

Conversation

@OBenner

@OBenner OBenner commented Jun 10, 2026

Copy link
Copy Markdown
Owner

Re-landing #321 onto develop

#321 was stacked on feat/subagent-changeset-export and got merged into that branch — but #320 had already been squash-merged to develop before that, so PR-3's content never reached develop (the stacked branch was orphaned). This PR cherry-picks the same commit cleanly onto current develop. Content is identical to reviewed #321.

What it does (recap)

execute_subagent_changeset_merge — each mutating child is one transaction boundary:

  1. Scope revalidation of every changeset path (defense-in-depth).
  2. Baseline verification via the existing drift comparator; unverifiable baseline = refusal, same as drift.
  3. Atomic apply per child; mid-apply failure restores that child's baseline in reverse — siblings unaffected.
  4. One parent transaction per child (subagent_merge:<child-id>) — rollback_transaction undoes exactly one child's merge.
  5. Conflicts never auto-applied (conflicted_unresolved; deterministic AutoMerger routing is PR-4).

run_subagents action data carries merge_plan + merge_execution; ok only when all appliable changesets applied. Mutating delegation inside an open model-managed batch refused up front.

Tests

6 new (e2e parent-applies-child-changeset; baseline drift refused; mid-apply rollback; rollback_transaction undo; conflicted children kept unapplied; open-batch refusal) — 233 passed in the runtime file locally; ruff (CI-pinned 0.14.10) clean.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Subagents now support transactional parent-side changeset merging with enhanced baseline validation and rollback capabilities.
    • System prevents concurrent transaction conflicts and safely handles partial/failed merge applications.
  • Tests

    • Added comprehensive test coverage for end-to-end merge scenarios, drift detection, rollback restoration, and batch boundary enforcement.

…sets

Phase B / PR-3 of moving mutating parallel subagents toward `safe`
(stacked on #320's changeset export). The merge plan is no longer just
descriptive: after a run_subagents run whose plan requires a parent
merge, the parent now APPLIES each child's exported changeset
transactionally.

- execute_subagent_changeset_merge: each mutating child is one
  transaction boundary. Its changeset is scope-revalidated
  (defense-in-depth against a tampered payload), baseline-verified
  (every entry's preimage must still match the live workspace via the
  existing drift comparator — an unverifiable baseline refuses the merge
  just like real drift), then applied as a unit. A mid-apply failure
  restores that child's captured baseline in reverse order; siblings are
  unaffected. Conflicted children are NEVER auto-applied — they surface
  as conflicted_unresolved for explicit resolution (deterministic
  AutoMerger routing lands in PR-4).
- Each applied child is recorded as a parent mutation snapshot with
  transaction id subagent_merge:<child-id>, so the parent's existing
  rollback_transaction tool can undo exactly one child's merge.
- run_subagents now reports merge_plan + merge_execution in its action
  data; the action only stays ok when every appliable changeset applied
  (applied/noop). Mutating delegation inside an open model-managed batch
  is refused up front (mutating_subagents_in_open_batch) before any
  child spawns.

Tests: end-to-end parent run (real confined changeset child; file lands
on the shared workspace via the parent; merge_execution recorded with
the per-child transaction id), baseline drift refused with workspace
intact, mid-apply failure rolled back (first entry restored), applied
child undone via rollback_transaction, conflicted children kept
unapplied, and delegation refused inside an open parent batch.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Oleg Miagkov <mrobenner@gmail.com>
@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@OBenner, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 26 minutes and 26 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: cfa99425-e79b-4d4e-aa89-0dfb465e3afe

📥 Commits

Reviewing files that changed from the base of the PR and between ee6d179 and bbcd6cf.

📒 Files selected for processing (2)
  • apps/backend/agents/runtime/adapters/generic_edit.py
  • tests/test_agent_runtime.py
📝 Walkthrough

Walkthrough

This PR implements transactional parent-side merging of exported subagent changesets. The runtime now applies child staged changes to the parent workspace with baseline verification, write-scope enforcement, rollback-on-failure per child, and mutation snapshot recording. A pre-spawn guard rejects transactional_write subagents when a parent batch is open. Comprehensive test coverage validates the happy path, baseline drift handling, rollback behavior, conflict detection, and batch boundary enforcement.

Changes

Subagent changeset merge feature

Layer / File(s) Summary
Transaction ID infrastructure and constants
apps/backend/agents/runtime/adapters/generic_edit.py
Introduces SUBAGENT_MERGE_TRANSACTION_PREFIX namespace constant to record parent-side child merge transaction IDs separately, enabling per-child rollback tracking.
Parent batch boundary validation
apps/backend/agents/runtime/adapters/generic_edit.py
Adds pre-spawn check in run_subagents to reject transactional_write tasks when a model-managed batch is already open, returning batch-boundary error with active batch ID and recovery hint.
Core changeset merge execution pipeline
apps/backend/agents/runtime/adapters/generic_edit.py
Implements full parent-side transactional merge: derives per-child transaction IDs, verifies baseline against preimages (drift detection), applies entries with write-scope validation, rolls back on child-path failures via captured preimages, records snapshots with rollback metadata, and returns per-child and aggregate outcomes.
Run_subagents merge integration
apps/backend/agents/runtime/adapters/generic_edit.py
Extends run_subagents result handling to conditionally execute merge when required, compute success based on merge status, append merge-status message detail, and include merge_plan and merge_execution fields in action result.
Test infrastructure and end-to-end merge flow
tests/test_agent_runtime.py
Adds hashlib import and _changeset_child_payloads() helper; introduces async end-to-end test running full-autonomous parent session delegating to run_subagents, validating child staged changes are applied and merge execution status plus transaction metadata are recorded.
Merge failure scenarios and rollback coverage
tests/test_agent_runtime.py
Adds unit tests for baseline drift rejection, partial/failed application with per-child rollback, rollback transaction restoration to baseline, conflicting children remaining unapplied, and async validation that mutating subagent delegation is refused in open parent batch with specific error reason assertion.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • OBenner/Auto-Coding#319: Extends run_subagents by enforcing write_scope_guard for mutating child sessions, complementing this PR's parent-side transactional merge execution for exported changesets.
  • OBenner/Auto-Coding#232: Adds core mutation_snapshots-driven rollback behavior; this PR builds on that infrastructure by recording parent-side child merges into snapshots with rollback metadata.

Suggested labels

area/backend, size/L, feature

Poem

🐰 A rabbit merges changesets with care,
Verifying baselines, rolling back with flair,
Parent and child dance in transactional grace,
Each snapshot recorded, each failure replaced,
Boundaries guard against batch-time despair! 🌳

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 70.00% which is insufficient. The required threshold is 80.00%. 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 accurately captures the main change: implementing transactional parent merge execution for child changesets in the subagent runtime adapter.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/subagent-parent-merge-develop

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 and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/backend/agents/runtime/adapters/generic_edit.py`:
- Around line 4044-4051: The loop that revalidates entries uses entry["path"]
but the actual write uses postimage["path"] and allows empty write_scope, which
lets a child changeset mutate a different path or skip validation; update the
validation in the entries loop (around build_generic_edit_file_preimage and
similar blocks) to first require the parent changeset's write_scope is
present/non-empty, then for each entry ensure entry.get("path"),
preimage.get("path") and postimage.get("path") are all present and equal (e.g.,
entry_path == preimage_path == postimage_path) before calling
build_generic_edit_file_preimage or proceeding, and if any check fails return
"baseline_unverifiable" with drift_checks unchanged; also ensure downstream code
uses the validated postimage_path for the actual write instead of trusting
entry["path"].
- Around line 2521-2553: The ToolActionResult returned by run_subagents does not
include the parent mutation snapshot ids/paths that
execute_subagent_changeset_merge appends, causing build_generic_edit_transaction
to miss prior mutations; update the ToolActionResult (in the return for
run_subagents) to include the merged snapshot metadata from merge_execution
(e.g., add keys like "merged_mutation_snapshot_ids" and/or
"merged_mutation_paths" populated from merge_execution's applied/parent
snapshots) so downstream build_generic_edit_transaction can inspect result.data
for prior mutations; locate the merge_execution variable and the
ToolActionResult construction and add those fields when merge_execution is not
None.
- Around line 4125-4149: The appended subagent-merge snapshot dict created
around transaction_id = subagent_merge_transaction_id(result_id) and added to
mutation_snapshots lacks the mandatory workspace_guard field, causing
validate_generic_edit_checkpoint_mutation_snapshot_integrity() to reject resumed
sessions; fix by including a workspace_guard entry in that snapshot (using the
same guard value used for other checkpoint/transaction snapshots or deriving it
from the current context) when building the dict for
SUBAGENT_MERGE_TRANSACTION_PREFIX so rollback_transaction and later validation
succeed.

In `@tests/test_agent_runtime.py`:
- Around line 4299-4360: Update the
test_subagent_merge_rolls_back_failed_application to exercise a two-child merge:
keep the existing "broken" changeset as one SimpleNamespace (e.g., id="edit-b")
and add a separate successful child changeset (e.g., id="edit-a") that creates
"src/ok.txt"; call execute_subagent_changeset_merge with results containing both
entries and merge_plan["mutating_result_ids"] listing both ids; then assert
overall merge_execution["status"] is "failed", assert the failing child's
outcome (identify by id "edit-b" in outcomes) has status
"apply_failed_rolled_back" and failed_path "src/broken.txt", and assert the
successful sibling's file (from "edit-a") still exists while the broken file
does not; keep snapshots == [] to verify no leakage.
- Around line 4251-4297: Add a new pytest that mirrors
test_subagent_merge_refuses_on_baseline_drift but triggers the
_verify_changeset_baseline branch that returns "baseline_unverifiable": create a
changeset whose entry has a preimage that cannot be revalidated (e.g.,
preimage.exists True with a preimage.content or content_encoding that does not
match or cannot be verified against the workspace), call
execute_subagent_changeset_merge with that changeset (similar to
results=[SimpleNamespace(id="edit-a", changeset=changeset)] and empty snapshots)
and assert merge_execution["status"] == "failed" and
merge_execution["outcomes"][0]["status"] == "baseline_unverifiable" and that no
files were modified and snapshots remain []. Ensure the test references
execute_subagent_changeset_merge and the internal verification behavior
(_verify_changeset_baseline) so the intended branch is covered.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 5c268a72-1b74-44b6-8d77-1fa7bd083cce

📥 Commits

Reviewing files that changed from the base of the PR and between 7aaf9fd and ee6d179.

📒 Files selected for processing (2)
  • apps/backend/agents/runtime/adapters/generic_edit.py
  • tests/test_agent_runtime.py

Comment thread apps/backend/agents/runtime/adapters/generic_edit.py
Comment thread apps/backend/agents/runtime/adapters/generic_edit.py
Comment thread apps/backend/agents/runtime/adapters/generic_edit.py Outdated
Comment thread tests/test_agent_runtime.py
Comment thread tests/test_agent_runtime.py
Addresses all 5 CodeRabbit findings and the Windows test failure:

- Changesets are untrusted input at the parent boundary: the declared
  write_scope must be non-empty and normalizable (else scope_violation
  with reason missing_or_invalid_write_scope), and every entry's declared
  path must equal its preimage AND postimage paths (else
  invalid_changeset_path) — the postimage path is what actually gets
  written, so path mismatches could otherwise escape revalidation.
- subagent_merge snapshots now carry workspace_guard: checkpoint
  integrity validation treats it as mandatory, so a recoverable stop
  after a subagent_merge rollback no longer fails resume validation.
- run_subagents result data now surfaces mutation_snapshot_ids,
  mutated_paths, and affected_paths from applied outcomes (each applied
  outcome carries its mutation_snapshot_id), so transaction summaries
  record parent-side merge mutations and a later failing action in the
  same turn yields partial_failure with a recovery plan instead of plain
  failed.
- Windows CI: the rollback test hand-crafted a preimage with byte counts
  that broke under CRLF newline translation; it now captures the real
  preimage via build_generic_edit_file_preimage.
- New tests per review: baseline_unverifiable refusal; partial merge
  keeps the applied sibling while the failing child rolls back; malformed
  changesets (path mismatch, scope-less) rejected with nothing applied.

311 passed across agent_runtime / runtime_capabilities / runtime_modes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Oleg Miagkov <mrobenner@gmail.com>
OBenner added a commit that referenced this pull request Jun 10, 2026
Phase B / PR-4 of moving mutating parallel subagents toward `safe`
(stacked on #322's parent-merge executor). Conflicts stop being a dead
end: false positives auto-apply, real ones block finish until the parent
resolves them explicitly. No AI merging anywhere on this path.

- Real-conflict refinement: the merge plan flags children by DECLARED
  write-scope overlap; the executor now treats a child as conflicted only
  when its changeset's ACTUAL paths intersect another declared-conflicted
  child's actual paths. Overlapping scopes with disjoint edits — the
  common false positive — apply deterministically like any other child.
- Real conflicts surface as conflicted_unresolved (now with
  conflict_paths) and are registered as pending on the parent session.
  Finish is vetoed (stop_reason=unresolved_subagent_conflicts, recoverable)
  until every pending conflict is resolved.
- New local action resolve_subagent_conflict {result_id, resolution}:
  'apply' merges that child's changeset onto the CURRENT workspace through
  the same baseline-verified transactional executor (recorded as
  subagent_merge:<id>, so it still rolls back as one unit; a sibling that
  already changed the file makes the baseline check fail — reconcile and
  retry, or discard); 'discard' drops the changeset. Validation errors
  list the pending ids. The action is mutating (blocked inside open
  batches) and schema'd; both prompt templates teach the rule.

Tests: declared-overlap/disjoint-edit auto-apply; finishing with pending
conflicts terminates recoverably with nothing applied; apply+discard
resolutions land exactly the chosen child's content and unblock finish
(transaction id asserted); resolve-action input validation. 392 passed
across the affected surface.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Oleg Miagkov <mrobenner@gmail.com>
SonarCloud reliability gate flagged the unguarded snapshots[0] access;
assert the expected lengths before indexing.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Oleg Miagkov <mrobenner@gmail.com>
OBenner added a commit that referenced this pull request Jun 10, 2026
Phase B / PR-4 of moving mutating parallel subagents toward `safe`
(stacked on #322's parent-merge executor). Conflicts stop being a dead
end: false positives auto-apply, real ones block finish until the parent
resolves them explicitly. No AI merging anywhere on this path.

- Real-conflict refinement: the merge plan flags children by DECLARED
  write-scope overlap; the executor now treats a child as conflicted only
  when its changeset's ACTUAL paths intersect another declared-conflicted
  child's actual paths. Overlapping scopes with disjoint edits — the
  common false positive — apply deterministically like any other child.
- Real conflicts surface as conflicted_unresolved (now with
  conflict_paths) and are registered as pending on the parent session.
  Finish is vetoed (stop_reason=unresolved_subagent_conflicts, recoverable)
  until every pending conflict is resolved.
- New local action resolve_subagent_conflict {result_id, resolution}:
  'apply' merges that child's changeset onto the CURRENT workspace through
  the same baseline-verified transactional executor (recorded as
  subagent_merge:<id>, so it still rolls back as one unit; a sibling that
  already changed the file makes the baseline check fail — reconcile and
  retry, or discard); 'discard' drops the changeset. Validation errors
  list the pending ids. The action is mutating (blocked inside open
  batches) and schema'd; both prompt templates teach the rule.

Tests: declared-overlap/disjoint-edit auto-apply; finishing with pending
conflicts terminates recoverably with nothing applied; apply+discard
resolutions land exactly the chosen child's content and unblock finish
(transaction id asserted); resolve-action input validation. 392 passed
across the affected surface.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Oleg Miagkov <mrobenner@gmail.com>
@sonarqubecloud

Copy link
Copy Markdown

@OBenner
OBenner merged commit 65d10f6 into develop Jun 10, 2026
19 checks passed
OBenner added a commit that referenced this pull request Jun 10, 2026
Phase B / PR-4 of moving mutating parallel subagents toward `safe`
(stacked on #322's parent-merge executor). Conflicts stop being a dead
end: false positives auto-apply, real ones block finish until the parent
resolves them explicitly. No AI merging anywhere on this path.

- Real-conflict refinement: the merge plan flags children by DECLARED
  write-scope overlap; the executor now treats a child as conflicted only
  when its changeset's ACTUAL paths intersect another declared-conflicted
  child's actual paths. Overlapping scopes with disjoint edits — the
  common false positive — apply deterministically like any other child.
- Real conflicts surface as conflicted_unresolved (now with
  conflict_paths) and are registered as pending on the parent session.
  Finish is vetoed (stop_reason=unresolved_subagent_conflicts, recoverable)
  until every pending conflict is resolved.
- New local action resolve_subagent_conflict {result_id, resolution}:
  'apply' merges that child's changeset onto the CURRENT workspace through
  the same baseline-verified transactional executor (recorded as
  subagent_merge:<id>, so it still rolls back as one unit; a sibling that
  already changed the file makes the baseline check fail — reconcile and
  retry, or discard); 'discard' drops the changeset. Validation errors
  list the pending ids. The action is mutating (blocked inside open
  batches) and schema'd; both prompt templates teach the rule.

Tests: declared-overlap/disjoint-edit auto-apply; finishing with pending
conflicts terminates recoverably with nothing applied; apply+discard
resolutions land exactly the chosen child's content and unblock finish
(transaction id asserted); resolve-action input validation. 392 passed
across the affected surface.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Oleg Miagkov <mrobenner@gmail.com>
OBenner added a commit that referenced this pull request Jun 10, 2026
* feat(runtime): deterministic conflict path for subagent merges

Phase B / PR-4 of moving mutating parallel subagents toward `safe`
(stacked on #322's parent-merge executor). Conflicts stop being a dead
end: false positives auto-apply, real ones block finish until the parent
resolves them explicitly. No AI merging anywhere on this path.

- Real-conflict refinement: the merge plan flags children by DECLARED
  write-scope overlap; the executor now treats a child as conflicted only
  when its changeset's ACTUAL paths intersect another declared-conflicted
  child's actual paths. Overlapping scopes with disjoint edits — the
  common false positive — apply deterministically like any other child.
- Real conflicts surface as conflicted_unresolved (now with
  conflict_paths) and are registered as pending on the parent session.
  Finish is vetoed (stop_reason=unresolved_subagent_conflicts, recoverable)
  until every pending conflict is resolved.
- New local action resolve_subagent_conflict {result_id, resolution}:
  'apply' merges that child's changeset onto the CURRENT workspace through
  the same baseline-verified transactional executor (recorded as
  subagent_merge:<id>, so it still rolls back as one unit; a sibling that
  already changed the file makes the baseline check fail — reconcile and
  retry, or discard); 'discard' drops the changeset. Validation errors
  list the pending ids. The action is mutating (blocked inside open
  batches) and schema'd; both prompt templates teach the rule.

Tests: declared-overlap/disjoint-edit auto-apply; finishing with pending
conflicts terminates recoverably with nothing applied; apply+discard
resolutions land exactly the chosen child's content and unblock finish
(transaction id asserted); resolve-action input validation. 392 passed
across the affected surface.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Oleg Miagkov <mrobenner@gmail.com>

* fix(runtime): surface plural snapshot keys on resolve-apply result

The resolve_subagent_conflict apply path now reports
mutation_snapshot_ids / mutated_paths / affected_paths like an applied
run_subagents merge, so transaction summaries record the parent-side
mutation and later failures in the same turn become partial_failure.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Oleg Miagkov <mrobenner@gmail.com>

---------

Signed-off-by: Oleg Miagkov <mrobenner@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
OBenner added a commit that referenced this pull request Jun 10, 2026
Phase D / PR-7 — the final step of "mutating subagents -> safe" (stacked
on the PR-6 gate requirement). The protocol is no longer scaffolded:

- children are write-scope confined with runtime enforcement (#319),
- they stage mutations and export changesets without touching the shared
  workspace (#320),
- the parent applies each child transactionally with per-child rollback
  and baseline verification (#322),
- real conflicts are never auto-applied — they block finish until the
  parent resolves explicitly (#323),
- the whole mechanism is covered by the deterministic
  subagent_merge_probe (PR-5) which the promotion gate now requires
  (PR-6).

With that evidence chain in place, AutonomyLevel.SAFE now defaults
mutating_subagents_enabled=True. bold's remaining distinction is skipping
the evidence gate. The explicit AUTO_CODE_MUTATING_SUBAGENTS=false
override still opts out (covered by a new test), per ADR-006 precedence.

ADR-006's level table updated. The .env.example and UI level descriptions
live on the still-open #309/#318 branches and are updated there.

Tests: safe-level expectations flipped (autonomy level + direct-API
runtime policy grant); explicit env opt-out covered. 694 passed across
the affected surface.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Oleg Miagkov <mrobenner@gmail.com>
OBenner added a commit that referenced this pull request Jun 10, 2026
Phase D / PR-7 — the final step of "mutating subagents -> safe" (stacked
on the PR-6 gate requirement). The protocol is no longer scaffolded:

- children are write-scope confined with runtime enforcement (#319),
- they stage mutations and export changesets without touching the shared
  workspace (#320),
- the parent applies each child transactionally with per-child rollback
  and baseline verification (#322),
- real conflicts are never auto-applied — they block finish until the
  parent resolves explicitly (#323),
- the whole mechanism is covered by the deterministic
  subagent_merge_probe (PR-5) which the promotion gate now requires
  (PR-6).

With that evidence chain in place, AutonomyLevel.SAFE now defaults
mutating_subagents_enabled=True. bold's remaining distinction is skipping
the evidence gate. The explicit AUTO_CODE_MUTATING_SUBAGENTS=false
override still opts out (covered by a new test), per ADR-006 precedence.

ADR-006's level table updated. The .env.example and UI level descriptions
live on the still-open #309/#318 branches and are updated there.

Tests: safe-level expectations flipped (autonomy level + direct-API
runtime policy grant); explicit env opt-out covered. 694 passed across
the affected surface.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Oleg Miagkov <mrobenner@gmail.com>
OBenner added a commit that referenced this pull request Jun 10, 2026
…326)

* chore: retrigger CI after base retarget to develop

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Oleg Miagkov <mrobenner@gmail.com>

* feat(autonomy): enable mutating parallel subagents at the safe level

Phase D / PR-7 — the final step of "mutating subagents -> safe" (stacked
on the PR-6 gate requirement). The protocol is no longer scaffolded:

- children are write-scope confined with runtime enforcement (#319),
- they stage mutations and export changesets without touching the shared
  workspace (#320),
- the parent applies each child transactionally with per-child rollback
  and baseline verification (#322),
- real conflicts are never auto-applied — they block finish until the
  parent resolves explicitly (#323),
- the whole mechanism is covered by the deterministic
  subagent_merge_probe (PR-5) which the promotion gate now requires
  (PR-6).

With that evidence chain in place, AutonomyLevel.SAFE now defaults
mutating_subagents_enabled=True. bold's remaining distinction is skipping
the evidence gate. The explicit AUTO_CODE_MUTATING_SUBAGENTS=false
override still opts out (covered by a new test), per ADR-006 precedence.

ADR-006's level table updated. The .env.example and UI level descriptions
live on the still-open #309/#318 branches and are updated there.

Tests: safe-level expectations flipped (autonomy level + direct-API
runtime policy grant); explicit env opt-out covered. 694 passed across
the affected surface.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Oleg Miagkov <mrobenner@gmail.com>

* chore: retrigger CI after base retarget to develop

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Oleg Miagkov <mrobenner@gmail.com>

* chore: retrigger CI on develop base

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Oleg Miagkov <mrobenner@gmail.com>

---------

Signed-off-by: Oleg Miagkov <mrobenner@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant