Skip to content

feat(agent-org): enforce the formal Task FSM and owner permissions - #869

Draft
ShiboSheng wants to merge 3 commits into
codex/issue-758-turn-context-fifofrom
codex/issue-759-pr4-task-fsm
Draft

feat(agent-org): enforce the formal Task FSM and owner permissions#869
ShiboSheng wants to merge 3 commits into
codex/issue-758-turn-context-fifofrom
codex/issue-759-pr4-task-fsm

Conversation

@ShiboSheng

@ShiboSheng ShiboSheng commented Aug 22, 2026

Copy link
Copy Markdown
Collaborator

Problem

Fixes #759

Depends on #841 and is intentionally based on codex/issue-758-turn-context-fifo.

Formal Agent Org Tasks did not have one complete lifecycle and authority contract. Creation, graph mutation, owner execution, recovery, debug helpers, and UI projection could apply overlapping rules, so invalid initial states, coordinator ownership/output, structural mutation by an owner, terminal rewrites, stale owner callbacks, and recovery-budget resets were not all rejected at the same authoritative boundary.

The root cause was that the SQLite Task Store did not own the full field-level state machine with persisted actor and Turn identity. Tool and wake paths could validate only part of the contract, while task history/results were projected without a bounded Current Work/History contract.

Solution

  • Make the Task Store the final authority for the canonical five states: pending, in_progress, completed, failed, and cancelled.
  • Force every new Task to pending; require structured output for completion and structured reasons for failure/cancellation.
  • Separate typed graph-administrator, owner-execution, and system recovery actors. Revalidate run, snapshot member, owner, session, persisted Turn binding, and generation inside each transaction.
  • Freeze terminal Task structure and results. Only completed satisfies dependencies; goal/owner/dependency changes after execution starts use atomic cancel-and-replace.
  • Make recovery attempts durable and per Task: the first three runtime failures requeue, the fourth becomes terminal, and owner/session generations cannot reset the budget.
  • Add bounded Current Work and paginated History projections with demand-loaded detail/annotations.
  • Exercise the real Provider → Tool dispatcher → Task Store path in deterministic E2E support, and replace delivery-phase labels in code/tests with stable Task Store / Task FSM domain names.

This preserves the issue boundary: it does not add new Task states, coordinator-owned formal Tasks, Member-private graphs, Writer-capability resolution, or forced cancellation of an already running old execution.

Potential risks

  • Stack dependency: this Draft PR is stacked on feat(agent-org): add transactional turn context and member FIFO #841 because PR 3 is not yet in develop. It must be retargeted/revalidated after the dependency merges.
  • Persistence compatibility: this changes the canonical Task schema and intentionally does not add a backward migration for pre-contract runtime fixtures. Acceptance used a fresh isolated ORGII_HOME and left the existing ~/.orgii/sessions.db untouched. Do not mix binaries across incompatible Task schemas.
  • Concurrency/lifecycle: owner completion can race cancellation/replacement or recovery. Transactions, persisted Turn/generation checks, rollback tests, and late-callback rejection cover the known races, but this remains the highest-risk area.
  • UI/pagination: Current Work/History behavior and lazy detail loading changed across all locales; large-history keyset tests and rendered scenarios cover the main path.
  • Platform coverage: packaged real-app acceptance ran on macOS. Windows and Linux packaged behavior was not manually exercised.
  • Latest commit evidence: the final commit only renamed phase-derived files, symbols, fixtures, comments, diagnostics, and E2E markers. Full packaged E2E was not repeated after that mechanical cleanup; affected Rust tests, frontend tests, typecheck, lint, formatting, and Clippy were rerun.
  • Rollback/recovery: revert this PR together with its stacked dependency state. For persisted data, restore a pre-cutover backup or use a fresh compatible ORGII_HOME; do not downgrade a database after opening it with the new canonical schema.

Dependency and scope

Why this is much larger than the original design estimate

The planning snapshot copied into Issue #759 estimated 2,200 P50 / 3,800 P90 review lines across 17–27 substantive files. That estimate treated the work primarily as a Task enum/Store FSM change plus a small set of Tool and UI adapters.

The implementation-time impact spike in the design document later revised PR 4 to 10,800 P50 / 13,000 P90 review lines and 58–62 substantive files plus up to 13 locale files. The final diff is 16,985 review lines (+10,392 / -6,593) across 121 files, but the net growth is only +3,799 lines. The gap is therefore mostly the review cost of replacing an old cross-layer contract, deleting obsolete tests, and proving the replacement—not 16,985 lines of new product surface.

Path-based, rename-aware partition against the PR 3 base:

Category Files Additions Deletions Review lines What it represents
Production and wiring 76 6,041 2,598 8,639 Store FSM/actors, persisted Turn binding, Tool/wake/recovery consumers, wire DTOs, UI projection
Tests, E2E, and test support 32 4,117 3,982 8,099 contract/race/rollback tests, deterministic Provider→Tool→Store driver, rendered Task scenarios
Locale/mechanical 13 234 13 247 synchronized Current Work/History/result copy
Total 121 10,392 6,593 16,985

The specific underestimates were:

  1. This had to be a canonical replacement, not an additive FSM. The old generic task_update path and its three-state/whole-row-patch assumptions could bypass any new Store gate. In task_tests.rs alone, 3,099 old lines were deleted and 391 replacement lines added; the dedicated Task Store contract suite adds another 1,169 lines. Those two files account for 4,659 review lines while removing more old code than they add.
  2. The Store invariant was consumed by more production owners than the estimate counted. A legal owner transition depends on the PR 3 persisted Turn context, task-bound Inbox drain, wake-mode resolution, Plan Approval continuation, run finality, watchdog recovery, prompt projection, Task tools, Tauri DTOs, and Current Work/History readers. Leaving any one of those on the old assumptions would preserve an authority or stale-callback bypass.
  3. Recovery required a separate correctness correction. The approved recovery plan added a durable per-Task budget, exact failed-Turn-to-Task binding, replay idempotency, atomic reserve/mutate/refund behavior, non-reset across owner/session generation, and terminal fourth-failure semantics. That plan independently estimated 650 P50 / 1,200 P90 review lines and became the second commit.
  4. The wire/UI change was a contract, not a label swap. Structured output/failure/cancellation/provenance, bounded Current Work, keyset-paginated History, lazy details/annotations, corrupt-row handling, and all 13 locales had to agree with the Store schema in the same runnable state.
  5. Real-path evidence exposed and then covered bypasses. The deterministic fake provider, rendered WDIO scenario, debug-helper restrictions, 10,000-Task history fixture, transaction fault injection, duplicate/concurrent replay, and negative late-callback assertions are why tests/E2E are almost half of the review lines. They prove Provider → Tool dispatcher → persisted CallContext → Task Store rather than a helper-only path.
  6. The final 3,985 lines above the revised 13,000 P90 came after the 70% impact gate. They are mainly the completed recovery correction, real-path E2E/test-support hardening, final Current/History coverage, and removal/replacement of remaining old-contract tests. They did not add PR 5–10 features.

This remains one PR because canonical DDL, typed Store actors, Tool wire, recovery behavior, and five-state read projection must agree at every runnable point. Splitting them into independently mergeable PRs would require a temporary old/new schema compatibility layer, retain the generic mutation bypass, or expose a half-three-state/half-five-state wire contract. Those intermediate states are explicitly forbidden by the design. The size is a reviewability cost, so the PR keeps focused commits and the review map below; it is not an expansion into Pause/Archive, multi-Writer, or UserDirectedWork scope.

Review map

Contract Owning implementation Primary proof
Five-state FSM and field authority Task Store FSM/create/update/validation Task Store contract tests
Coordinator vs Owner authority Typed actors + Task Tool adapters Tool adapter authority tests
Persisted owner Turn identity Turn contexts + task-bound inbox drain/wake stale Turn/generation and inbox tests
Recovery budget/finality watchdog budget + Store requeue transaction per-Task budget, rollback, replay tests
Current Work / History task page commands + Task panel keyset history tests + rendered UI scenario
Real dispatch path deterministic fake provider + packaged Tool path focused WDIO and BuildFast acceptance

Verification

  • cargo test -p agent_core — 3,154 passed, 0 failed, 2 ignored on the completed implementation.
  • cargo test -p agent_core task_store_contract_tests — 14 passed after the final naming cleanup.
  • cargo test -p agent_core core::providers::e2e_fake::tests — 12 passed after the final naming cleanup.
  • cargo test -p agent_core core::tools::impls::orchestration::agent_org::tasks::task_tests — 8 passed after the final naming cleanup.
  • ./node_modules/.bin/vitest run src/engines/ChatPanel/InputArea/components/AgentOrgTaskPanel.test.ts — 4 passed.
  • cargo check -p agent_core --all-targets — passed.
  • cargo check -p e2e-test — passed.
  • cargo clippy -p agent_core --all-targets -- -D warnings — passed; commit hook also passed scoped agent_core and org2 Clippy.
  • ./node_modules/.bin/tsc --noEmit --pretty false — passed.
  • pnpm run lint — 0 errors; 5 pre-existing warnings outside this diff.
  • ./node_modules/.bin/eslint src/engines/ChatPanel/InputArea/components/AgentOrgTaskPanel.test.ts — passed.
  • cargo fmt --all -- --check, focused Prettier checks, git diff --check, and E2E script node --check — passed.
  • Focused rendered Agent Org Task FSM WDIO scenarios — passed on the frozen implementation before the final naming-only commit.
  • pnpm run tauri:build:fast packaged-app acceptance — deterministic fake-provider batches and one live-provider pending → in_progress → completed flow passed.
  • Fresh temporary ORGII_HOME packaged-app smoke — launched the existing app, created/opened an Agent Org Team, completed a Task, relaunched, and read the Team/Task back; the existing database was not deleted or modified.
  • pnpm run check:circular — blocked by two baseline ?raw imports unchanged from PR 3; the commit hook reported zero new circular findings in staged files.

Visual evidence

No screenshot is attached because this PR changes lifecycle authority, persisted state, and pagination behavior rather than visual styling. Rendered UI assertions and packaged-app interaction were used together with direct Task/database state checks.

Make SQLite the final authority for Task creation, mutation, and lifecycle transitions. Add the canonical five-state model, typed actors, durable provenance and results, recovery behavior, and bounded task history reads.

Separate coordinator graph administration from Owner lifecycle operations, validate persisted Turn bindings inside each transaction, and expose Current Work and History without eagerly loading full results or annotations.

Verification:
- cargo test -p agent_core: 3154 passed, 0 failed, 2 ignored
- cargo test -p agent_core section_tests -- --nocapture: 12 passed after the final mechanical fix
- cargo clippy -p agent_core --all-targets -- -D warnings: passed
- pnpm run typecheck: passed
- pnpm run lint: 0 errors; 5 pre-existing warnings outside this diff
- cargo check -p e2e-test and focused Vitest/WDIO PR4 suites: passed
- BuildFast fake-provider batches and one live-provider pending -> in_progress -> completed smoke: passed
- pnpm run check:circular: blocked by two baseline ?raw imports unchanged from PR3

Pre-commit hook ran. Total eslint: 5, total circular: 0
Pre-commit hook ran. Total eslint: 5, total circular: 0
Pre-commit hook ran. Total eslint: 5, total circular: 0
@ShiboSheng

Copy link
Copy Markdown
Collaborator Author

orgii://cloud/session/ref?v=1&org=bfa7b134-2486-45fa-81ad-a369441fafb4&owner=776dbd69-ac1d-4f72-a0d4-69cb4f2667dd&session=codexapp-rollout-2026-08-20T01-27-48-01a01b10-9b52-7f00-8af2-39711a442d02

@ShiboSheng

Copy link
Copy Markdown
Collaborator Author

orgii://cloud/session/ref?v=1&org=bfa7b134-2486-45fa-81ad-a369441fafb4&owner=776dbd69-ac1d-4f72-a0d4-69cb4f2667dd&session=codexapp-rollout-2026-08-22T12-17-41-01a027b0-5225-7080-aa68-d96e8cefdc14

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.

feat(agent-org): [4/10] enforce the formal Task FSM and owner permissions

1 participant