Skip to content

feat(runtime): admit cross-epoch graph results - #2992

Merged
Astro-Han merged 21 commits into
apache:mainfrom
me2seeks:feat/2588-cross-epoch-results
Aug 19, 2026
Merged

feat(runtime): admit cross-epoch graph results#2992
Astro-Han merged 21 commits into
apache:mainfrom
me2seeks:feat/2588-cross-epoch-results

Conversation

@me2seeks

@me2seeks me2seeks commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Summary

  • persist typed selected_result_inputs with the source graph identity for scheduled work
  • admit only committed results selected by a finished earlier epoch of the same root Session
  • revalidate historical inputs during recovery and hydrate them with explicit graph provenance
  • page historical result discovery without reusing old operators, claims, routes, or control state

Historical results cross the epoch boundary as immutable data only. Runtime Host authorization verifies the root, epoch ordering, finished schedule selection, and exact RuntimeEvent-backed record before the schedule is committed; recovery performs the same resolution again. Input counts and discovery pages are bounded, and ambiguous current/historical record identities fail closed.

This completes the cross-epoch result-input slice of #2588 after the historical-read slice.

Depends on #2991
Refs #2588

This is intentionally opened as a Draft during the pre-Incubator stabilization window. It is not requesting merge until feature work resumes.

Verification

  • npm run build:test
  • npm run typecheck
  • Agent Graph authority, reconciliation, handoff, protocol, storage, Desktop, and TUI tests in the stacked latest-main run — 168 passed
  • Biome check on all changed files
  • git diff --check

Checklist

  • Tests cover the change and fail without it
  • Lint, format, typecheck and the affected suites pass locally

Does this PR entail a change in behavior?

  • Yes — a new Agent Graph epoch can explicitly consume selected results from an earlier finished epoch
  • No
中文说明

摘要

  • 为 schedule work 持久化带来源 graph 身份的 selected_result_inputs
  • 只允许引用同一 root Session 下、已结束旧 epoch 在 finish 中明确选择的已提交结果
  • 恢复时重新执行相同授权,并在传给新 operator 的输入中保留 graph 来源
  • 历史结果发现采用有界分页,不复用旧 operator、claim、route 或控制状态

跨 epoch 传递的只有不可变数据,不包含旧图的控制权。Runtime Host 会在 schedule 提交前验证 root、epoch 顺序、旧图的 finish 选择以及由 RuntimeEvent 支撑的精确 record;崩溃恢复时再次验证。输入数量与发现页都有上限,当前图和历史图的 record identity 若出现歧义会 fail closed。

这是 #2588 的跨 epoch 结果输入部分,接续前一项历史读取改动。

本 PR 在进入孵化器前的稳定期内以 Draft 打开;在 feature 合并恢复前不请求进入 main

AI disclosure / AI 披露

This PR was implemented by Codex under me2seeks’s direction and review. / 本 PR 由 Codex 在 me2seeks 的指导与审核下完成。

@me2seeks
me2seeks force-pushed the feat/2588-cross-epoch-results branch 2 times, most recently from dfdbaaf to 86d33c5 Compare August 17, 2026 16:04
@coderabbitai

coderabbitai Bot commented Aug 17, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@me2seeks, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 12 minutes

Limit details: You’ve used all 3 included reviews currently available.

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

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.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 88bb00c2-ddfb-4b24-8938-ecac0de115b5

📥 Commits

Reviewing files that changed from the base of the PR and between 58b3895 and 31b9faf.

📒 Files selected for processing (17)
  • apps/desktop/src/main/__tests__/agent-graph-panel.test.ts
  • apps/desktop/src/main/runtime-host-client.ts
  • apps/desktop/src/preload/bridge-contract.d.ts
  • apps/desktop/src/preload/preload.ts
  • apps/desktop/src/renderer/agent-graph-panel.tsx
  • apps/desktop/src/renderer/app-shell.tsx
  • apps/desktop/src/renderer/locales/shell-copy.ts
  • packages/cli/src/__tests__/pi-tui-runner.test.ts
  • packages/cli/src/pi-tui-runner.ts
  • packages/cli/src/runtime-host-tui-command.ts
  • packages/runtime-host/src/__tests__/agent-graph-coordinator.test.ts
  • packages/runtime-host/src/server/agent-graph-coordinator.ts
  • packages/runtime/src/__tests__/stream-graph-coordinator.test.ts
  • packages/runtime/src/__tests__/stream-graph-schedule-reconcile.test.ts
  • packages/runtime/src/stream-graph-coordinator.ts
  • packages/runtime/src/stream-graph-schedule-reconcile.ts
  • packages/storage/src/sqlite-session-metadata-store.ts

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 5b19d134-c97e-4bdc-9416-fa3e11706835

📥 Commits

Reviewing files that changed from the base of the PR and between 3428c3c and 58b3895.

📒 Files selected for processing (21)
  • apps/desktop/src/main/__tests__/agent-graph-panel.test.ts
  • apps/desktop/src/main/__tests__/agent-graph-refresh.test.ts
  • apps/desktop/src/main/__tests__/runtime-host-session-domains-ipc-main.test.ts
  • apps/desktop/src/main/runtime-host-session-domains-ipc-main.ts
  • apps/desktop/src/preload/bridge-contract.d.ts
  • apps/desktop/src/preload/preload.ts
  • apps/desktop/src/renderer/agent-graph-panel.tsx
  • apps/desktop/src/renderer/agent-graph-refresh.ts
  • packages/cli/src/__tests__/pi-tui-runner.test.ts
  • packages/cli/src/pi-tui-runner.ts
  • packages/cli/src/runtime-host-tui-context.ts
  • packages/core/src/agent-graph-epoch.ts
  • packages/runtime-host/src/__tests__/agent-graph-coordinator.test.ts
  • packages/runtime-host/src/__tests__/agent-graph-reader.test.ts
  • packages/runtime-host/src/client/agent-graph-reader.ts
  • packages/runtime-host/src/client/index.ts
  • packages/runtime-host/src/protocol/agent-graph.ts
  • packages/runtime/src/__tests__/stream-graph-coordinator.test.ts
  • packages/runtime/src/stream-graph-coordinator.ts
  • packages/storage/src/__tests__/agent-graph-epochs.test.ts
  • packages/storage/src/sqlite-session-metadata-store.ts
🚧 Files skipped from review as they are similar to previous changes (14)
  • apps/desktop/src/main/tests/runtime-host-session-domains-ipc-main.test.ts
  • apps/desktop/src/preload/bridge-contract.d.ts
  • packages/runtime-host/src/client/index.ts
  • packages/cli/src/runtime-host-tui-context.ts
  • packages/storage/src/tests/agent-graph-epochs.test.ts
  • packages/cli/src/pi-tui-runner.ts
  • apps/desktop/src/preload/preload.ts
  • packages/cli/src/tests/pi-tui-runner.test.ts
  • packages/storage/src/sqlite-session-metadata-store.ts
  • packages/runtime/src/tests/stream-graph-coordinator.test.ts
  • apps/desktop/src/main/runtime-host-session-domains-ipc-main.ts
  • packages/runtime-host/src/protocol/agent-graph.ts
  • apps/desktop/src/renderer/agent-graph-panel.tsx
  • packages/runtime/src/stream-graph-coordinator.ts

Included review availability: Your plan includes up to 3 reviews per rolling hour; 0 remain after this review.


📝 Walkthrough

Problem solved

This PR enables Agent Graph work to consume selected, committed results from completed earlier epochs of the same root Session.

It adds typed selected_result_inputs, provenance checks, recovery validation, bounded historical discovery, and historical graph browsing in the desktop panel and TUI.

Source of truth

The PR extends the existing schedule, epoch store, runtime coordinator, protocol, read-model, IPC, preload, and TUI paths.

It does not create a parallel execution path. Historical results use existing epoch bindings and RuntimeEvent-backed records. Historical snapshots use the selected graph identity without reusing prior operators, claims, routes, or control state.

Solution scope and complexity

The change is the smallest coherent solution shown by the supplied diff summary. Persisted provenance, graph identity checks, historical lookup, recovery validation, protocol support, and client presentation are required for safe cross-epoch inputs.

No clear deletion or simplification preserves the same behavior and regression coverage. The added fixtures and tests cover storage, runtime, runtime-host, desktop, and CLI boundaries.

Validation performed

The supplied changes add coverage for:

  • Selected-result validation, duplicates, overlaps, and input limits.
  • Same-root, earlier-epoch, completion, selection, and committed-record checks.
  • Recovery and schedule reconciliation.
  • Historical lineage and graph-specific snapshots.
  • Epoch pagination, ordering, cursors, and repeated-cursor rejection.
  • IPC, preload, desktop, and TUI history behavior.
  • Read-only historical rendering.
  • /graph history parsing and execution without starting an Agent Graph turn.
  • Refresh coalescing, invalidation fences, stale-read rejection, and disposal behavior.

Required check status remains unverified because direct check results were not provided.

Complexity delta

The PR adds historical epoch and graph-ID lookup, paginated discovery, selected-result resolution state, graph-specific query branches, optional fields across public boundaries, new epoch-listing APIs, refresh scheduling, and test fixtures across five packages and the desktop application.

It removes no existing authority or state. It reuses the existing schedule, epoch, record, and snapshot models.

Public surface and test-maintenance burden increase. The increase is bounded and justified by cross-epoch reuse, provenance, authorization, recovery, history inspection, and stale-refresh protection.

Review-relevant risks

  • User-visible behavior changes through graph-history browsing, read-only historical views, localized copy, /graph history, and refresh behavior.
  • Public contracts change across runtime-host, preload, IPC, schedule, read-model, and TUI APIs.
  • Security-sensitive authorization now permits historical result reuse after root, epoch, selection, completion, and record validation.
  • The new agent.graph.epochs.query operation may affect release and governance controls.

Material changes in these areas require independent human review under repository policy.

The person performing the merge reviews the final diff. A maintainer makes the final determination.

Walkthrough

Agent Graph history now supports paginated epoch discovery, graph-specific snapshots, historical result selection, and read-only desktop and CLI views. Runtime Host, IPC, preload, storage, and runtime layers carry graph identity through these flows.

Changes

Agent Graph history

Layer / File(s) Summary
Epoch and selected-result contracts
packages/core/..., packages/runtime-host/src/protocol/..., packages/storage/...
Adds epoch pagination contracts, graph-ID lookup, selected historical result references, validation, protocol decoding, and SQLite persistence.
Runtime history and historical result execution
packages/runtime/src/stream-graph-coordinator.ts, packages/runtime/src/stream-graph-schedule-reconcile.ts, packages/runtime/src/stream-graph-supervisor-tools.ts
Lists graph epochs, rebuilds graph-specific snapshots, validates historical result ownership and completion, and includes selected results in reconciliation and projections.
Runtime Host epoch transport
packages/runtime-host/src/client/..., packages/runtime-host/src/server/..., packages/runtime-host/src/protocol/...
Adds the epoch query operation, paginated epoch reading, graph-specific snapshot and operator queries, response validation, and related coverage.
Desktop graph bridge
apps/desktop/src/main/..., apps/desktop/src/preload/...
Exposes epoch listing and optional graphId values through Runtime Host, IPC, and preload APIs.
Desktop and CLI history views
apps/desktop/src/renderer/..., packages/cli/src/..., packages/core/src/graph-command.ts
Adds /graph history, epoch selectors, historical snapshot rendering, read-only controls, localized copy, refresh scheduling, and CLI history output. Tests cover epoch selection and no-turn behavior.

Estimated code review effort: 5 (Critical) | ~120 minutes

Merge Risk: 🔵 Low · up to 58b38

This PR enables later graph epochs to consume selected results from earlier finished epochs. It is mergeable with owner awareness of two bounded issues: the history command can show an inaccurate mode-change message, and repeated failed historical-source lookups can add unnecessary reconciliation work.

Sequence Diagram(s)

sequenceDiagram
  participant AgentGraphPanel
  participant MakaBridge
  participant RuntimeHost
  participant AgentGraphCoordinator
  AgentGraphPanel->>MakaBridge: list epochs and request graph snapshot
  MakaBridge->>RuntimeHost: query epochs and graph snapshot
  RuntimeHost->>AgentGraphCoordinator: read graph-specific data
  AgentGraphCoordinator-->>RuntimeHost: return epoch metadata and snapshot
  RuntimeHost-->>AgentGraphPanel: return read-only historical graph
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Ai Use Disclosure ⚠️ Warning The description discloses Codex implementation but selects neither required declaration; all 16 PR commits also lack a valid standalone Generated-by trailer. Select the generative-contribution declaration, name Codex and its scope, and add Generated-by: Codex to each material AI-authored commit; ensure it survives squash or amend. See CONTRIBUTING.md.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the primary change: allowing Agent Graph results to cross epochs.
Description check ✅ Passed The description covers the summary, verification, issue references, behavior change, checklist, and AI disclosure, with only minor template deviations.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@me2seeks
me2seeks marked this pull request as ready for review August 18, 2026 04:10
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Admit selected results across Agent Graph epochs

✨ Enhancement 🐞 Bug fix 🧪 Tests 🕐 40+ Minutes

Grey Divider

AI Description

• Persist and authorize selected immutable results from completed earlier Agent Graph epochs.
• Add bounded historical epoch discovery and exact graph-scoped reads across Runtime Host.
• Expose read-only graph history in Desktop and TUI with recovery-focused coverage.
Diagram

graph TD
  Desktop["Desktop UI"] --> Reader["Epoch Reader"] --> Protocol["Host Protocol"] --> Host["Host Coordinator"] --> Runtime["Graph Runtime"] --> Epochs["Epoch Store"]
  TUI["TUI History"] --> Reader
  Runtime --> Schedules["Schedule Store"] --> Recovery["Reconciliation"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Copy historical records into the current graph
  • ➕ Simplifies downstream input lookup
  • ➕ Avoids repeated historical projection reads during recovery
  • ➖ Blurs immutable lineage and current graph ownership
  • ➖ Duplicates data and risks stale or forged copies
  • ➖ Could accidentally recreate cross-graph control relationships
2. Use globally unique result IDs without graph provenance
  • ➕ Produces a smaller schedule contract
  • ➕ Reduces caller-supplied fields
  • ➖ Cannot fail closed on ambiguous identities
  • ➖ Weakens root and epoch authorization
  • ➖ Makes recovery provenance harder to verify
3. Return all epochs in one response
  • ➕ Simplifies Desktop and TUI clients
  • ➕ Avoids client-side pagination loops
  • ➖ Creates unbounded protocol responses
  • ➖ Scales poorly for long-lived sessions
  • ➖ Weakens resource-exhaustion protections

Recommendation: Keep the PR’s explicit sourceGraphId/resultId references, bounded epoch paging, and repeated RuntimeEvent-backed authorization. This preserves immutable data lineage without importing historical operators or control state, while failing closed on identity ambiguity; the alternatives trade away provenance, boundedness, or recovery safety.

Files changed (40) +1997 / -137

Enhancement (23) +991 / -102
runtime-host-client.tsExpose graph epoch listing from the Desktop client +6/-0

Expose graph epoch listing from the Desktop client

• Adds a guarded client method that collects Runtime Host Agent Graph epoch pages.

apps/desktop/src/main/runtime-host-client.ts

runtime-host-session-domains-ipc-main.tsAdd graph epoch and graph-scoped IPC reads +34/-6

Add graph epoch and graph-scoped IPC reads

• Registers the epoch-list IPC route and forwards optional graph identities for snapshot and operator inspection. Extends strict option validation accordingly.

apps/desktop/src/main/runtime-host-session-domains-ipc-main.ts

bridge-contract.d.tsExtend the Desktop graph bridge contract +4/-1

Extend the Desktop graph bridge contract

• Adds epoch listing and optional graph identities to snapshot and operator inspection methods.

apps/desktop/src/preload/bridge-contract.d.ts

preload.tsBridge historical graph reads through preload +14/-2

Bridge historical graph reads through preload

• Implements epoch listing and forwards graph identities through scoped Electron IPC calls.

apps/desktop/src/preload/preload.ts

agent-graph-panel.tsxAdd read-only Agent Graph epoch browsing +69/-8

Add read-only Agent Graph epoch browsing

• Adds localized epoch selection, graph-scoped refreshes, and stale-refresh protection. Historical runs remain visible but cannot expose current-graph stop or dismiss controls.

apps/desktop/src/renderer/agent-graph-panel.tsx

app-shell.tsxHandle the graph history command +4/-0

Handle the graph history command

• Recognizes '/graph history' and directs users to the Agent Graph panel.

apps/desktop/src/renderer/app-shell.tsx

shell-copy.tsLocalize graph history guidance +6/-0

Localize graph history guidance

• Adds English and Chinese titles and instructions for historical graph inspection.

apps/desktop/src/renderer/locales/shell-copy.ts

agent-graph.cssStyle the graph epoch selector +6/-0

Style the graph epoch selector

• Allows the graph heading to wrap and bounds the historical-run selector width.

apps/desktop/src/renderer/styles/agent-graph.css

pi-tui-runner.tsAdd Agent Graph history to the TUI +95/-0

Add Agent Graph history to the TUI

• Adds a read-only history surface, run picker, and formatted graph summaries. Routes the new graph command without submitting an agent prompt.

packages/cli/src/pi-tui-runner.ts

runtime-host-tui-command.tsWire graph history into TUI startup +1/-0

Wire graph history into TUI startup

• Passes the Runtime Host graph-history surface to the Pi TUI runner.

packages/cli/src/runtime-host-tui-command.ts

runtime-host-tui-context.tsCreate the Runtime Host graph-history client +21/-1

Create the Runtime Host graph-history client

• Provides epoch listing and graph-scoped snapshot reads to the TUI context.

packages/cli/src/runtime-host-tui-context.ts

agent-graph-epoch.tsExtend the graph epoch store contract +13/-0

Extend the graph epoch store contract

• Adds graph-identity lookup and bounded, cursor-based epoch page contracts.

packages/core/src/agent-graph-epoch.ts

agent-graph-schedule.tsModel typed cross-epoch result inputs +35/-3

Model typed cross-epoch result inputs

• Adds source-graph provenance to scheduled work and enforces per-work and per-update bounds. Decoding rejects duplicate or ambiguous record identities.

packages/core/src/agent-graph-schedule.ts

graph-command.tsParse the graph history command +2/-0

Parse the graph history command

• Introduces a dedicated lifecycle command variant for '/graph history'.

packages/core/src/graph-command.ts

agent-graph-reader.tsCollect bounded Agent Graph epoch pages +37/-0

Collect bounded Agent Graph epoch pages

• Adds a reusable Runtime Host reader with page-count and repeated-cursor safeguards.

packages/runtime-host/src/client/agent-graph-reader.ts

index.tsExport the graph epoch reader +5/-1

Export the graph epoch reader

• Publishes the epoch reader and capability-provider service type through the client entry point.

packages/runtime-host/src/client/index.ts

agent-graph.tsDefine historical Agent Graph protocol operations +184/-8

Define historical Agent Graph protocol operations

• Adds bounded epoch queries and optional graph-scoped snapshot and operator reads. Projects selected-result provenance and enforces ordering, uniqueness, cursor, and identity invariants.

packages/runtime-host/src/protocol/agent-graph.ts

agent-graph-coordinator.tsServe graph epochs and exact historical projections +50/-8

Serve graph epochs and exact historical projections

• Routes epoch pages and optional graph identities through the runtime authority. Includes selected-result provenance in client work projections.

packages/runtime-host/src/server/agent-graph-coordinator.ts

graph-mode.tsDocument historical inputs in the graph prompt +1/-0

Document historical inputs in the graph prompt

• Instructs supervisors to use graph-provenanced selected results only as immutable data lineage.

packages/runtime/src/graph-mode.ts

stream-graph-coordinator.tsAuthorize and resolve cross-epoch graph results +237/-63

Authorize and resolve cross-epoch graph results

• Adds exact historical graph reads, epoch paging, and finished-schedule result discovery. Revalidates root ownership, epoch ordering, finish selection, and RuntimeEvent-backed records during admission and reconciliation.

packages/runtime/src/stream-graph-coordinator.ts

stream-graph-read-model.tsProject selected historical inputs in graph snapshots +4/-0

Project selected historical inputs in graph snapshots

• Carries source graph and result identities into client scheduled-work projections.

packages/runtime/src/stream-graph-read-model.ts

stream-graph-supervisor-tools.tsExpose historical results to graph supervisors +110/-1

Expose historical results to graph supervisors

• Adds typed selected-result inputs and paged historical discovery to graph tools. Enforces combined input bounds, uniqueness, and current-versus-historical separation.

packages/runtime/src/stream-graph-supervisor-tools.ts

sqlite-session-metadata-store.tsPersist result provenance and page graph epochs +53/-0

Persist result provenance and page graph epochs

• Clones selected-result provenance when committing schedules. Adds validated graph-identity lookup and bounded SQL pagination for historical epochs.

packages/storage/src/sqlite-session-metadata-store.ts

Bug fix (2) +68 / -5
stream-graph-handoff.tsPreserve graph identity in handoff references +2/-0

Preserve graph identity in handoff references

• Adds source graph provenance to every rendered Agent Graph record reference.

packages/runtime/src/stream-graph-handoff.ts

stream-graph-schedule-reconcile.tsRevalidate historical inputs during reconciliation +66/-5

Revalidate historical inputs during reconciliation

• Resolves persisted cross-epoch references into immutable records and rejects incomplete, mismatched, ambiguous, or colliding results. Includes them in prompts and trigger lineage without topology reuse.

packages/runtime/src/stream-graph-schedule-reconcile.ts

Tests (14) +937 / -30
agent-graph-panel.test.tsTest read-only historical epoch selection +67/-8

Test read-only historical epoch selection

• Extends the renderer harness to model multiple graph epochs and graph-scoped snapshots. Verifies selecting history hides stop and dismiss controls.

apps/desktop/src/main/tests/agent-graph-panel.test.ts

runtime-host-session-domains-ipc-main.test.tsTest Desktop epoch IPC adaptation +64/-0

Test Desktop epoch IPC adaptation

• Covers epoch listing and exact graph identity forwarding through Desktop IPC. Adds a reusable graph snapshot fixture and client stub.

apps/desktop/src/main/tests/runtime-host-session-domains-ipc-main.test.ts

pi-tui-runner.test.tsTest TUI historical graph inspection +76/-0

Test TUI historical graph inspection

• Verifies '/graph history' opens the run picker, fetches the selected graph, and does not start a turn.

packages/cli/src/tests/pi-tui-runner.test.ts

agent-graph-schedule.test.tsTest selected historical result validation +50/-0

Test selected historical result validation

• Covers valid cross-epoch inputs plus aggregate bounds, duplicate identities, and current/historical ambiguity rejection.

packages/core/src/tests/agent-graph-schedule.test.ts

graph-command.test.tsTest graph history command parsing +14/-0

Test graph history command parsing

• Adds parser coverage distinguishing '/graph history' from one-shot graph tasks and unrelated commands.

packages/core/src/tests/graph-command.test.ts

agent-graph-coordinator.test.tsTest Host epoch paging and historical routing +109/-1

Test Host epoch paging and historical routing

• Covers epoch query projection, newest-first pagination, current identity, and stable failure mapping. Updates authority fixtures for graph-scoped reads.

packages/runtime-host/src/tests/agent-graph-coordinator.test.ts

agent-graph-protocol.test.tsTest epoch and graph identity protocol rules +58/-4

Test epoch and graph identity protocol rules

• Covers epoch page decoding, pagination correlation, graph-scoped queries, and fail-closed response identity checks.

packages/runtime-host/src/tests/agent-graph-protocol.test.ts

agent-graph-reader.test.tsTest paged graph epoch collection +51/-0

Test paged graph epoch collection

• Verifies newest-first page collection and rejection of repeated cursors.

packages/runtime-host/src/tests/agent-graph-reader.test.ts

agent-graph-two-client-uds.test.tsExtend two-client authority fixtures +31/-1

Extend two-client authority fixtures

• Implements epoch paging and graph-scoped snapshot and operator methods required by the expanded authority contract.

packages/runtime-host/src/tests/agent-graph-two-client-uds.test.ts

stream-graph-coordinator.test.tsTest cross-epoch authorization and exact projection recovery +270/-16

Test cross-epoch authorization and exact projection recovery

• Verifies only selected committed results from finished earlier epochs are admitted. Also covers historical projection rebuilding, root ownership, and current-graph isolation.

packages/runtime/src/tests/stream-graph-coordinator.test.ts

stream-graph-handoff.test.tsTest graph provenance in handoffs +2/-0

Test graph provenance in handoffs

• Asserts hydrated handoff references preserve their source graph identity.

packages/runtime/src/tests/stream-graph-handoff.test.ts

stream-graph-schedule-reconcile.test.tsTest historical result hydration during reconciliation +99/-0

Test historical result hydration during reconciliation

• Verifies selected historical records reach prompts and dispatch intents without creating cross-graph topology edges.

packages/runtime/src/tests/stream-graph-schedule-reconcile.test.ts

stream-graph-supervisor-tools.test.tsTest historical supervisor tool inputs and discovery +14/-0

Test historical supervisor tool inputs and discovery

• Covers selected-result compilation, schedule projection, bounded discovery output, and pagination metadata.

packages/runtime/src/tests/stream-graph-supervisor-tools.test.ts

agent-graph-epochs.test.tsTest SQLite epoch lookup and pagination +32/-0

Test SQLite epoch lookup and pagination

• Covers graph-identity lookup plus bounded newest-first epoch pages and continuation cursors.

packages/storage/src/tests/agent-graph-epochs.test.ts

Other (1) +1 / -0
operations.tsAuthorize remote epoch queries +1/-0

Authorize remote epoch queries

• Adds the read-only Agent Graph epoch operation to remote-owner grants.

packages/runtime-host/src/protocol/operations.ts

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/cli/src/pi-tui-runner.ts (1)

2337-2345: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Update the turn-running block message to cover the new history command.

editor.onSubmit's turn-running gate (unchanged in this diff) rejects every non-status Graph command with "Cannot change or start Graph Mode while a turn is running." history is a read-only inspection, not a mode change, so this message misdescribes the block for the new command added here.

✏️ Suggested wording fix
-        if (graphCommand.kind === 'status') {
+        if (graphCommand.kind === 'status' || graphCommand.kind === 'history') {
           showGraphStatus();
         } else {
           state.entries.push({
             kind: 'notice',
             level: 'error',
-            text: 'Cannot change or start Graph Mode while a turn is running.',
+            text: 'Cannot change Graph Mode while a turn is running.',
           });
           requestRender();
         }

Note: routing history to showGraphStatus() above is only a placeholder; if history viewing should stay blocked mid-turn, keep the block but correct the message text to something like "Graph history is unavailable while a turn is running."

🧹 Nitpick comments (4)
packages/core/src/agent-graph-epoch.ts (1)

25-35: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Optional: use the core epoch contract.

packages/runtime/src/stream-graph-coordinator.ts redeclares AgentGraphEpochPage and AgentGraphEpochStore at lines 31-51. Import the exported core types and delete the local declarations. This prevents pagination contract drift between runtime and storage.

Disposition: optional.
As per path instructions, consolidate duplicated authority and reuse the closest existing seam.

Also applies to: 48-49

Source: Path instructions

packages/runtime/src/__tests__/stream-graph-coordinator.test.ts (1)

48-239: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add coverage for the paginated historical cursor.

This test asserts nextHistoricalBeforeEpoch === null for a two-epoch root, so the continuation path never runs. #listHistoricalSelectedResults uses limit: 1 and beforeEpoch: Math.min(beforeEpoch ?? current.epoch, current.epoch). Two behaviors stay untested:

  • A root with three or more epochs returns a non-null nextHistoricalBeforeEpoch, and passing it back through historical_before_epoch advances to the next earlier epoch without repeating or skipping one.
  • An earlier epoch with no finish yields empty results while still returning a usable cursor.

The clamping and the epoch < beforeEpoch storage semantics are the parts most likely to regress into a stalled or looping cursor.

Disposition: optional. Behavior looks correct by inspection; the test would protect the cursor contract.

Source: Path instructions

packages/runtime/src/__tests__/stream-graph-schedule-reconcile.test.ts (1)

29-95: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add negative-path coverage for the resolver guards.

resolveSelectedResultInputs is injected here, so the new fail-closed checks in resolveSelectedResultRecords are cheap to exercise. None is covered today:

  • A resolver returning fewer records than requested must reject with "incomplete result set".
  • A resolver returning a record whose graphId or recordId differs from the request must reject with "mismatched record".
  • Two resolved records sharing one recordId must reject as ambiguous.
  • A resolved record whose recordId already exists in the current graph must reject as a collision (source line 201).

Each case is one stub variant plus one assert.rejects.

Disposition: optional. The guards protect against a compromised or buggy Runtime Host resolver, so they deserve tests.

Source: Path instructions

apps/desktop/src/renderer/agent-graph-panel.tsx (1)

177-222: 🚀 Performance & Scalability | 🔵 Trivial

Consider parallelizing listEpochs and getSnapshot.

This effect mounts for every session shown in the chat surface, not only Graph-mode sessions (see app-shell.tsx line 3084). The refresh now chains listEpochs then getSnapshot({ graphId }) sequentially, adding a second IPC round trip to every session render where a single getSnapshot call sufficed before.

getSnapshot(rootSessionId) without a graphId already resolves the current graph on the host side. When followCurrentRef.current is true, listEpochs and getSnapshot(rootSessionId) (no graphId) do not depend on each other and can run concurrently; reconcile next.graphId against nextEpochs afterward instead of awaiting listEpochs first. Disposition: optional — the result is correct today, but the extra latency lands on every session switch, not just Graph-mode sessions.

As per path instructions: "Choose remedies in this order: delete an unnecessary path, consolidate duplicated authority, reuse the closest existing seam, make the smallest local correction, then add new behavior only when the earlier options cannot satisfy the invariant."

♻️ Sketch of a parallel fetch
       task = window.maka.graphs
-        .listEpochs(props.rootSessionId)
-        .then(async (nextEpochs) => {
-          const current = nextEpochs.find((entry) => entry.current) ?? nextEpochs[0];
-          const selected = followCurrentRef.current
-            ? current
-            : nextEpochs.find((entry) => entry.graphId === selectedGraphIdRef.current);
-          const graphId = (selected ?? current)?.graphId;
-          if (!graphId) throw new Error('Agent graph epoch directory is empty');
-          selectedGraphIdRef.current = graphId;
-          const next = await window.maka.graphs.getSnapshot(props.rootSessionId, { graphId });
-          return { next, nextEpochs };
-        })
+        .then(async () => {
+          const knownGraphId = !followCurrentRef.current ? selectedGraphIdRef.current : undefined;
+          const [nextEpochs, next] = await Promise.all([
+            window.maka.graphs.listEpochs(props.rootSessionId),
+            window.maka.graphs.getSnapshot(
+              props.rootSessionId,
+              knownGraphId ? { graphId: knownGraphId } : undefined,
+            ),
+          ]);
+          selectedGraphIdRef.current = next.graphId;
+          return { next, nextEpochs };
+        })

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: e1bbd0a1-b1bb-40d3-ba5c-33b653944a6c

📥 Commits

Reviewing files that changed from the base of the PR and between 5d9ce0d and 86d33c5.

📒 Files selected for processing (40)
  • apps/desktop/src/main/__tests__/agent-graph-panel.test.ts
  • apps/desktop/src/main/__tests__/runtime-host-session-domains-ipc-main.test.ts
  • apps/desktop/src/main/runtime-host-client.ts
  • apps/desktop/src/main/runtime-host-session-domains-ipc-main.ts
  • apps/desktop/src/preload/bridge-contract.d.ts
  • apps/desktop/src/preload/preload.ts
  • apps/desktop/src/renderer/agent-graph-panel.tsx
  • apps/desktop/src/renderer/app-shell.tsx
  • apps/desktop/src/renderer/locales/shell-copy.ts
  • apps/desktop/src/renderer/styles/agent-graph.css
  • packages/cli/src/__tests__/pi-tui-runner.test.ts
  • packages/cli/src/pi-tui-runner.ts
  • packages/cli/src/runtime-host-tui-command.ts
  • packages/cli/src/runtime-host-tui-context.ts
  • packages/core/src/__tests__/agent-graph-schedule.test.ts
  • packages/core/src/__tests__/graph-command.test.ts
  • packages/core/src/agent-graph-epoch.ts
  • packages/core/src/agent-graph-schedule.ts
  • packages/core/src/graph-command.ts
  • packages/runtime-host/src/__tests__/agent-graph-coordinator.test.ts
  • packages/runtime-host/src/__tests__/agent-graph-protocol.test.ts
  • packages/runtime-host/src/__tests__/agent-graph-reader.test.ts
  • packages/runtime-host/src/__tests__/agent-graph-two-client-uds.test.ts
  • packages/runtime-host/src/client/agent-graph-reader.ts
  • packages/runtime-host/src/client/index.ts
  • packages/runtime-host/src/protocol/agent-graph.ts
  • packages/runtime-host/src/protocol/operations.ts
  • packages/runtime-host/src/server/agent-graph-coordinator.ts
  • packages/runtime/src/__tests__/stream-graph-coordinator.test.ts
  • packages/runtime/src/__tests__/stream-graph-handoff.test.ts
  • packages/runtime/src/__tests__/stream-graph-schedule-reconcile.test.ts
  • packages/runtime/src/__tests__/stream-graph-supervisor-tools.test.ts
  • packages/runtime/src/graph-mode.ts
  • packages/runtime/src/stream-graph-coordinator.ts
  • packages/runtime/src/stream-graph-handoff.ts
  • packages/runtime/src/stream-graph-read-model.ts
  • packages/runtime/src/stream-graph-schedule-reconcile.ts
  • packages/runtime/src/stream-graph-supervisor-tools.ts
  • packages/storage/src/__tests__/agent-graph-epochs.test.ts
  • packages/storage/src/sqlite-session-metadata-store.ts

Included review availability: Your plan includes up to 3 reviews per rolling hour; 0 remain after this review.

Comment thread packages/runtime/src/stream-graph-coordinator.ts
Comment thread packages/runtime/src/stream-graph-schedule-reconcile.ts
@qodo-code-review

qodo-code-review Bot commented Aug 18, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Remediation recommended

1. Combined work-item input bound bypassed ✓ Resolved 🐞 Bug ≡ Correctness
Description
decodeWork() caps inputIds and selectedResultInputs independently and only rejects identity
overlap, so a snapshot containing 64 of each can be accepted even though the durable schedule
contract caps their combined count at 64. This violates the core work-item invariant at the
client-facing protocol decode boundary and can expose downstream clients to as many as 128 inputs
for one work item.
Code

packages/runtime-host/src/protocol/agent-graph.ts[R904-926]

+function decodeSelectedResultInputs(
+  value: unknown,
+  currentInputIds: ReadonlySet<string>,
+): Array<{ sourceGraphId: string; resultId: string }> {
+  if (!Array.isArray(value) || value.length === 0 || value.length > AGENT_GRAPH_MAX_WORK_INPUTS) {
+    throw invalidProtocolFrame('Invalid selected graph result inputs');
+  }
+  const selected = value.map((item) => {
+    const record = requireExactRecord(item, 'selected graph result input', [
+      'sourceGraphId',
+      'resultId',
+    ]);
+    return {
+      sourceGraphId: requireOpaqueIdentity(record.sourceGraphId, 'sourceGraphId'),
+      resultId: requireOpaqueIdentity(record.resultId, 'resultId'),
+    };
+  });
+  assertUnique(selected, (item) => item.resultId, 'selected graph result');
+  if (selected.some((item) => currentInputIds.has(item.resultId))) {
+    throw invalidProtocolFrame('Graph input ids are ambiguous across current and historical data');
+  }
+  return selected;
+}
Relevance

●●● Strong

Accepted history favors enforcing explicit cross-field bounds and fail-closed protocol invariants.

PR-#2013
PR-#3128

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Snapshot work is decoded through decodeWork(), which limits current input IDs to 64 and then calls
decodeSelectedResultInputs() to permit up to another 64 selected-result inputs while checking only
for overlap with inputIds. In contrast, the core schedule validator in
packages/core/src/agent-graph-schedule.ts and supervisor-tool validation require `inputIds.length
+ selectedResultInputs.length` to remain at most 64, proving that the protocol layer is materially
more permissive than the existing invariant.

packages/runtime-host/src/protocol/agent-graph.ts[901-926]
packages/core/src/agent-graph-schedule.ts[298-314]
packages/runtime-host/src/protocol/agent-graph.ts[588-596]
packages/runtime-host/src/protocol/agent-graph.ts[873-925]
packages/core/src/agent-graph-schedule.ts[298-315]
packages/runtime/src/stream-graph-supervisor-tools.ts[136-163]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description

The Runtime Host protocol decoder validates `inputIds` and `selectedResultInputs` independently, allowing a decoded snapshot work item to exceed the durable schedule contract's combined maximum of 64 inputs. Update the decoder so `inputIds.length + selectedResultInputs.length` cannot exceed `AGENT_GRAPH_MAX_WORK_INPUTS`.

## Issue Context

`decodeWork()` decodes wire/materialized `AgentGraphClientScheduledWork` objects for client consumption. It computes `inputIds` first and then conditionally calls `decodeSelectedResultInputs(record.selectedResultInputs, new Set(inputIds))`; that helper only checks the selected array's own length and rejects identity overlap, so a snapshot containing 64 current IDs and 64 selected-result IDs is accepted even though core schedule and supervisor-tool validation cap the combined count at 64. Reuse `AGENT_GRAPH_MAX_WORK_INPUTS` to enforce the combined bound; no new schema, state, or public surface is needed, and protocol tests should cover rejection when the combined count exceeds the limit.

## Fix Focus Areas

- packages/runtime-host/src/protocol/agent-graph.ts[873-925]
- packages/runtime-host/src/__tests__/agent-graph-protocol.test.ts[84-146]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Stale current-epoch race in epoch paging ✓ Resolved 🐞 Bug ☼ Reliability
Description
Fix-now: listGraphEpochPage() resolves the current epoch and queries the epoch page through
independent, non-transactional reads, so a concurrent epoch advance can make the returned page
contain epoch N+1 while currentEpoch remains N. The Host may consequently mark a stale epoch as
current or emit no current entry, exposing incoherent data to clients or causing first-page protocol
validation to fail.
Code

packages/runtime/src/stream-graph-coordinator.ts[R316-338]

+  async listGraphEpochPage(
+    rootSessionId: string,
+    options: { readonly beforeEpoch?: number; readonly limit: number },
+  ): Promise<AgentGraphEpochPage & { readonly currentEpoch: number }> {
+    requireRootSessionId(rootSessionId);
+    const current = await this.currentGraphEpoch(rootSessionId);
+    if (!this.#input.epochStore) {
+      return {
+        epochs:
+          options.beforeEpoch === undefined || current.epoch < options.beforeEpoch ? [current] : [],
+        nextBeforeEpoch: null,
+        currentEpoch: current.epoch,
+      };
+    }
+    const page = await this.#input.epochStore.listAgentGraphEpochPage({
+      rootSessionId,
+      ...options,
+    });
+    if (page.epochs.length > 0 || options.beforeEpoch !== undefined) {
+      return { ...page, currentEpoch: current.epoch };
+    }
+    return { epochs: [current], nextBeforeEpoch: null, currentEpoch: current.epoch };
+  }
Relevance

●●● Strong

Accepted reliability history supports fixing race-sensitive state invariants and preventing
incoherent client-visible results.

PR-#2257
PR-#3128

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The coordinator resolves currentGraphEpoch() before separately awaiting
listAgentGraphEpochPage(), while epoch advancement commits through an independent transaction with
no shared snapshot. If that commit occurs between the reads, the descending page can include epoch
N+1 while page.currentEpoch still identifies N; HostAgentGraphCoordinator#queryEpochs determines
current solely through binding.epoch === page.currentEpoch, which can mark the wrong epoch or
leave the first page without exactly one current entry, violating protocol validation and affecting
Desktop and TUI decisions about which epoch is live and whether Stop or Dismiss actions are
available.

packages/runtime/src/stream-graph-coordinator.ts[316-338]
packages/runtime-host/src/server/agent-graph-coordinator.ts[132-156]
packages/runtime/src/stream-graph-coordinator.ts[316-337]
packages/storage/src/sqlite-session-metadata-store.ts[2673-2725]
packages/storage/src/sqlite-session-metadata-store.ts[2779-2804]
packages/runtime-host/src/server/agent-graph-coordinator.ts[132-150]
packages/runtime-host/src/protocol/agent-graph.ts[356-370]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description

`listGraphEpochPage()` reads the current epoch and the paged epoch listing through separate, unsynchronized storage operations. If an epoch advances between those reads, `currentEpoch` can be stale relative to the returned first page, causing the Runtime Host to mark an old epoch as current, emit no current entry, expose incoherent data to callers, or fail the protocol requirement that the first page identify exactly one current epoch.

## Issue Context

`HostAgentGraphCoordinator#queryEpochs` trusts `page.currentEpoch` and computes each entry's `current` flag using equality with the binding epoch. The protocol validates that an uncursorred first page has exactly one current entry, while Desktop and TUI consumers use that designation to determine which epoch is live and whether Stop or Dismiss actions should be available.

For an uncursorred first page, derive the current identity from the newest binding returned by the page, falling back to the separately resolved current binding only when the page is empty. This reuses the existing page result and avoids introducing new state or authority; add or update coverage for an epoch advancing between current resolution and the page read.

## Fix Focus Areas

- packages/runtime/src/stream-graph-coordinator.ts[316-338]
- packages/runtime/src/stream-graph-coordinator.ts[1291-1305]
- packages/runtime-host/src/server/agent-graph-coordinator.ts[132-150]
- packages/runtime/src/__tests__/stream-graph-coordinator.test.ts[998-1110]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Informational

3. Epoch-query invariant errors escape handler try/catch ✓ Resolved 🐞 Bug ☼ Reliability
Description
HostAgentGraphCoordinator#queryEpochs wraps only the authority call and result construction in
try/catch, but AGENT_GRAPH_OPERATION_SPECS['agent.graph.epochs.query'].assertOutputForInput runs
later in the connection's pending-request dispatch path outside this handler, so a
protocol-invariant violation (e.g. the stale-epoch race above producing zero or an inconsistent
current entry) surfaces as an unhandled exception in shared dispatch code rather than a controlled
per-request error response.
Code

packages/runtime-host/src/server/agent-graph-coordinator.ts[R132-156]

+  async #queryEpochs(
+    input: AgentGraphEpochListInput,
+  ): Promise<OperationOutcome<'agent.graph.epochs.query'>> {
+    try {
+      const page = await this.#authority.listGraphEpochPage(input.rootSessionId, {
+        ...(input.beforeEpoch === undefined ? {} : { beforeEpoch: input.beforeEpoch }),
+        limit: AGENT_GRAPH_EPOCH_PAGE_SIZE,
+      });
+      return {
+        ok: true,
+        result: {
+          rootSessionId: input.rootSessionId,
+          epochs: page.epochs.map((binding) => ({
+            epoch: binding.epoch,
+            graphId: binding.graphId,
+            createdAt: binding.createdAt,
+            current: binding.epoch === page.currentEpoch,
+          })),
+          nextBeforeEpoch: page.nextBeforeEpoch,
+        },
+      };
+    } catch (error) {
+      return graphQueryFailure(error);
+    }
+  }
Relevance

●● Moderate

Reliability concerns are plausible, but no close precedent confirms moving protocol assertions into
this handler.

PR-#2257

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
assertOutputForInput for 'agent.graph.epochs.query' is invoked by the client connection's
pending-request accept path, not inside HostAgentGraphCoordinator#queryEpochs's try/catch, so any
invariant failure caused by the stale-epoch race (see related finding) or other inconsistency
propagates as an unhandled exception rather than a graceful protocol error for that single request.

packages/runtime-host/src/server/agent-graph-coordinator.ts[132-156]
packages/runtime-host/src/protocol/agent-graph.ts[345-373]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
assertOutputForInput for agent.graph.epochs.query executes outside the request handler's own try/catch, in the shared connection dispatch code. If the underlying data becomes momentarily inconsistent (e.g. due to the current-epoch race described in the related finding), this throws an unhandled exception instead of a well-formed protocol error scoped to that request.

## Issue Context
This is a defense-in-depth/observability gap in the pre-existing dispatch pattern, now exercised by a new invariant-heavy operation (agent.graph.epochs.query) that asserts exactly one 'current' entry per page. It is non-blocking relative to this PR's core goal but worth follow-up given the new invariant surface.

## Fix Focus Areas
- packages/runtime-host/src/client/connection.ts (pending-request accept callback that invokes assertOutputForInput)
- packages/runtime-host/src/server/agent-graph-coordinator.ts[132-156]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
Review mode: 🧠 Deep: This is a broad, security-sensitive cross-epoch data-flow change spanning runtime authorization, recovery, persistence, protocol/API surfaces, UI/TUI, and many independent logic paths, making redundant review materially valuable.

Grey Divider

Tip of the day
💡 Did you know, you can show, collapse, or hide each part of a finding: code, evidence, and all

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

@coderabbitai coderabbitai 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.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 11dc6a9a-36be-4946-a5a4-692974480edf

📥 Commits

Reviewing files that changed from the base of the PR and between 86d33c5 and 3428c3c.

📒 Files selected for processing (2)
  • packages/runtime/src/__tests__/stream-graph-schedule-reconcile.test.ts
  • packages/runtime/src/stream-graph-schedule-reconcile.ts

Included review availability: Your plan includes up to 3 reviews per rolling hour; 2 remain after this review.

Comment thread packages/runtime/src/stream-graph-schedule-reconcile.ts

@Astro-Han Astro-Han 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.

I reviewed the updated head 3428c3caf5a9dfe5e154c1972378a940effc07ef, including the one-commit delta, its new reconciliation tests, the complete stack comparison, current CI, and all review threads.

The latest commit correctly addresses the two CodeRabbit findings: historical result resolution is cached per reconciliation, failures are isolated by source graph, and healthy sources can continue when another source is unavailable. I found no new P0–P2 in that delta.

The branch still has one P2 stack-consistency problem. It remains diverged from #2991’s current head a520f2c1, behind the two commits that fixed atomic epoch-page observation and bounded history collection. Consequently, this head still reads the current epoch and page through separate storage observations. A rollover between those reads can return epoch N+1 while reporting N as current, causing the first-page protocol invariant to reject a valid history request.

Please rebase this branch onto the latest #2991 head rather than recreating those fixes locally. That is the smallest and cleanest correction and will also remove the stale >2,048-epoch behavior.

Non-blocking contract follow-up: the Runtime Host decoder still allows 64 current inputs plus 64 selected historical inputs, while the durable schedule contract caps their combined count at 64. Aligning the decoder and adding one rejection test would close that P3 boundary.

CI is currently red on E2E and the PR has no approval. Recommendation: rebase onto the corrected #2991 stack, rerun CI, then re-review the resulting head.

Disclosure: Codex performed the read-only latest-head, stack, lifecycle, protocol, CI, and feedback analysis. The human contributor remains responsible for verifying the evidence and deciding whether to merge.

中文

最新 commit 正确修复了历史结果缓存和按 source 隔离失败,但分支仍落后 #2991 两个一致性修复。epoch page/current 非原子读取的 P2 仍存在。最干净方案是 rebase 最新 #2991,不要再补平行实现。

@me2seeks
me2seeks force-pushed the feat/2588-cross-epoch-results branch from 00b062d to 58b3895 Compare August 18, 2026 08:18
@me2seeks

Copy link
Copy Markdown
Contributor Author

Both follow-ups are on 58b3895fc:

  • Rebase onto feat(agent-graph): browse historical graph runs #2991 — the branch now sits on feat(agent-graph): browse historical graph runs #2991's corrected head (83371c455, including the atomic epoch-page observation and bounded history collection). No parallel fixes were recreated locally; the stale >2,048-epoch behavior is gone with the old base. The only adaptation needed after the rebase was rebuilding workspace deps against the new AgentGraphEpochPage.currentEpoch contract — no source changes in this branch's delta.
  • P3 decoder alignmentdecodeSelectedResultInputs now rejects frames where current inputIds + selectedResultInputs combined exceed AGENT_GRAPH_MAX_WORK_INPUTS (64), matching the durable schedule contract exactly. Regression test in agent-graph-coordinator.test.ts decodes a 64+1 frame (rejected) and a 63+1 frame (accepted); mutation check confirmed the rejection test fails without the cap.

Runtime 2885 green, runtime-host 962 green, biome clean. CI is re-running on the rebased head.

@Astro-Han Astro-Han 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.

The latest commits close most of the historical-result contract: the source graph is explicit, root/epoch/closed-graph/selected-result checks are fail-closed, and failed lookups are isolated and cached during reconciliation. One ownership boundary is still lost after authorization, however: historical tuples are flattened into a global record-id namespace shared by every scheduled work item.

The simplest first-principles fix is to keep two authorities throughout reconciliation: current-graph records keyed by recordId, and historical records keyed by each work's (sourceGraphId, resultId) selections. A global map may still detect collisions, but it must not authorize or render another work's inputs. This preserves provenance without adding a compatibility path.

Review performed with Codex reviewer agents and DeepSeek V4 Flash as advisory tools; I reproduced the failure against the latest head and verified live CI.

中文评论

最新提交已经补齐大部分历史结果契约:source graph 显式携带,root/epoch/closed graph/selected result 均 fail-closed,失败查询也在 reconciliation 中隔离并缓存。但授权之后仍丢失了一层所有权:历史 tuple 被压平成所有 work 共用的全局 record-id namespace。

更符合第一性原理的最小修复是让 reconciliation 始终保留两个权威:当前图记录按 recordId 管理;历史记录按每个 work 明确选择的 (sourceGraphId, resultId) 管理。全局 map 可以继续用于碰撞检测,但不能授权或渲染其他 work 的输入。这样无需兼容分支即可保留 provenance。

本次审查使用了 Codex reviewer agents 与 DeepSeek V4 Flash 作为辅助工具;我已在最新 head 上复现该失败,并复核实时 CI。

Comment thread packages/runtime/src/stream-graph-schedule-reconcile.ts Outdated
… observation

listGraphEpochPage resolved the current epoch and the page rows in two
separate reads, so a rollover between them produced a first page whose
current marker was not on the first row, which the protocol rejects —
Desktop and TUI history failed to open during an epoch transition. The
epoch-page storage seam now returns the current epoch observed by the
same read transaction as the rows, and the coordinator only falls back to
the legacy virtual identity when the store holds no durable rows.
- The shared epoch collector no longer throws away a valid directory when
  more pages exist past the 64-page bound; it returns a clearly truncated
  directory, and Desktop/TUI surface the cap instead of failing to open
  history for Sessions with more than 2,048 graph runs.
- Desktop resumes following the current epoch when the explicitly selected
  historical epoch leaves the bounded directory, instead of staying pinned
  on the fallback graph.
- The TUI stops the history picker flow when it shut down while page reads
  were in flight.
@me2seeks
me2seeks force-pushed the feat/2588-cross-epoch-results branch from 22a4ebe to ebedf52 Compare August 18, 2026 15:37

@Astro-Han Astro-Han 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.

Cross-epoch result admission belongs in the existing graph authority, and the PR correctly binds results to durable epoch identities instead of introducing another runtime state source. Two inherited history-surface gaps remain on this head. The smallest path is to rebase onto the corrected #2991 history foundation, then keep the selected graph identity as explicit UI state so controls cannot act through a stale snapshot during loading.

storybook is still running on the current head.

AI-assisted review disclosure: Codex verified the findings against the current head and traced epoch authority, root ownership, Desktop selection/refresh fencing, and root-scoped stop/dismiss actions. Two independent reviewer-agent passes and an OpenCode Go DeepSeek V4 Flash (high) adversarial pass were used as inputs. No local tests were run.

中文复核

跨 epoch result admission 应继续由现有 Graph 权威负责,这个 PR 正确地把结果绑定到持久 epoch identity,没有建立第二份 runtime 状态源。当前 head 还继承了历史浏览层的两个缺口。最小方案是先 rebase 到修正后的 #2991 foundation,再把 selected graph identity 作为明确 UI state,使加载期间的 control 不会通过旧 snapshot 作用到当前 Graph。当前 storybook 仍在运行。

本次为 AI 辅助审查:Codex 在最新 head 上追踪 epoch authority、root ownership、Desktop selection/refresh fencing 与 root-scoped stop/dismiss;另使用两次独立 reviewer 及一次 OpenCode Go DeepSeek V4 Flash(high)对抗审查。未运行本地测试。

Comment thread apps/desktop/src/renderer/agent-graph-panel.tsx
Comment thread packages/runtime/src/stream-graph-coordinator.ts Outdated
@me2seeks
me2seeks force-pushed the feat/2588-cross-epoch-results branch from ebedf52 to 0020615 Compare August 19, 2026 00:52
@me2seeks
me2seeks force-pushed the feat/2588-cross-epoch-results branch from 0020615 to 31b9faf Compare August 19, 2026 01:02

@Astro-Han Astro-Han 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.

This is now a coherent cross-epoch admission design. Historical results remain explicitly selected, same-root, earlier-epoch, source-finished, and RuntimeEvent-backed; (sourceGraphId, resultId) provenance survives authorization and reconciliation; current and historical records stay separated; and resolver failures defer only the affected source. Runtime Host and the durable schedule remain the existing authorities rather than introducing a parallel result store.

The test suite covers the important adversarial boundaries: cross-root and current/future epoch rejection, finish membership, recovery/reconciliation, provenance collisions, resolver failure caching, protocol limits, and read-only Desktop/TUI history. I found no concrete P0–P3 on the exact current head. Live required checks are green and merge state is clean.

Reviewed with Codex using three independent reviewer agents and OpenCode Go DeepSeek V4 Flash (high); I verified the exact head, current-main integration, authority boundaries, persistence/protocol contracts, and live CI.

中文

当前方案已经形成一致的跨 epoch admission 设计。历史结果必须显式选择、同 root、来自更早 epoch、source 已 finish,并由 RuntimeEvent 记录支撑;(sourceGraphId, resultId) provenance 在授权和 reconciliation 中都被保留;当前与历史 records 不混用;resolver 失败只延后受影响 source。Runtime Host 与 durable schedule 继续作为既有权威,没有新增并行结果存储。

测试覆盖了关键对抗边界:跨 root、当前/未来 epoch 拒绝、finish membership、恢复/reconciliation、provenance 冲突、resolver 失败缓存、协议上限,以及 Desktop/TUI 历史只读。当前精确 head 未发现具体 P0–P3;实时必需检查全绿,merge state clean。

本次由 Codex 配合三个独立 reviewer agent,以及 OpenCode Go DeepSeek V4 Flash(high)审查;我核验了精确 head、与当前 main 的集成、权威边界、持久化/协议契约和实时 CI。

@Astro-Han
Astro-Han merged commit 47fe0b4 into apache:main Aug 19, 2026
19 checks passed
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.

2 participants