Skip to content

refactor(reborn): clean up capability activity lifecycle - #5145

Merged
think-in-universe merged 44 commits into
mainfrom
codex/activity-gate-refactor
Jun 25, 2026
Merged

think-in-universe merged 44 commits into
mainfrom
codex/activity-gate-refactor

Conversation

@hanakannzashi

@hanakannzashi hanakannzashi commented Jun 23, 2026 •

Copy link
Copy Markdown
Contributor

Summary

This PR cleans up the Reborn capability activity lifecycle so activity rows, gate prompts, terminal states, and WebUI rendering all use the same stable identity instead of recovering state from UI order or active-run inference.

The three issues are different symptoms of the same contract gap:

  • Activity identity is now created with capability candidates and preserved through capability invocation, approval/auth parking, resume, and projection replay.
  • Gate prompts now carry rebuildable projection data (run_id, gate_ref, gate kind), so the WebUI can trust the read model instead of synthesizing rows from nearby run status.
  • User-declined gates now terminate the parked activity as gate_declined and render as a neutral declined state instead of red ERR/failed UI.
  • Tokenless auth-required edge cases now carry explicit parked activity identity, avoiding provider activity rows that stay running after denial.
  • The scheduler heartbeat path no longer self-deadlocks when heartbeat transitions contend with executor checkpoint/state writes.

Fixes

Fixes #5028
Fixes #5120
Fixes #5148

Checkpoint compatibility

The default loop checkpoint schema is intentionally bumped from reborn:default-loop-v1 / version 1 to reborn:default-loop-v2 / version 2.

The v2 payload makes parked activity_id required for pending approval/auth resumes. That is the clean contract this refactor relies on: a blocked gate must always know the exact activity row it will resume, decline, or fail. Older v1 checkpoints could omit this identity and sometimes derive it from a resume token; tokenless auth gates made that fallback impossible, which is the edge case that could leave activity running forever.

This PR does not migrate old v1 blocked checkpoints. A v1 checkpoint loaded under the v2 run profile is rejected at the checkpoint metadata boundary instead of being decoded as if it satisfied the new invariant. This matches the branch goal of prioritizing the v2 activity/gate identity model over old blocked-run compatibility.

Testing

  • cargo fmt --check
  • git diff --check
  • cargo check / cargo clippy for the touched Reborn, loop-support, agent-loop, host-runtime, hooks, and product-workflow crates
  • targeted activity/gate/auth/scheduler regression tests across ironclaw_agent_loop, ironclaw_loop_support, ironclaw_host_runtime, ironclaw_reborn_composition, ironclaw_turns, and WebUI JS
  • WebUI v2 bundle rebuilt with bash build.sh --no-vendor
  • CI-equivalent local suites for ironclaw_reborn_composition, ironclaw_memory, WASM channels, and first-party WASM builds
  • root full test suite with CI feature flags passed locally in serial mode: CARGO_PROFILE_DEV_DEBUG=0 CARGO_PROFILE_TEST_DEBUG=0 cargo test --no-default-features --features postgres,libsql,html-to-markdown,bedrock,import -- --nocapture --test-threads=1

Note: on local macOS, the same root full test command under default intra-binary parallelism can still abort at the process level with mach_msg failed before producing a Rust test failure. The serial full run passed, and the PR/CI runners remain the source of truth for Linux default-parallel execution.

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

contributor: core 20+ merged PRs risk: medium Business logic, config, or moderate-risk modules scope: channel/wasm WASM channel runtime scope: docs Documentation size: XL 500+ changed lines

Projects

None yet

3 participants