Skip to content

feat: show live child session creation cards - #439

Merged
lodystage[bot] merged 12 commits into
mainfrom
feat/live-child-session-cards
Sep 7, 2026
Merged

lodystage[bot] merged 12 commits into
mainfrom
feat/live-child-session-cards

Conversation

@lodystage

@lodystage lodystage Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Related issue

Same-repository improvement; no linked issue.

Problem / pressure

MCP-created conversations and child Tabs were only discoverable from the parent conversation after the creating Operation completed. Long-running child work therefore had no immediate navigation card or visible progress.

Summary

  • Publish a stable, UI-only operation_progress system row once each create target is materialized, and update its exact target Turn status in place.
  • Render navigable cards with Created, Running, Completed successfully, Failed, and Cancelled states; batch targets update independently.
  • Preserve existing completion delivery and legacy completion cards, while linking new completions to their progress row to avoid duplicate target cards.
  • Keep progress out of agent replay/dispatch, preserve terminal state against stale updates, and make presentation writes independent of lifecycle success.
  • Add English/Chinese copy, deterministic regression coverage, and Storybook stories for all five states.

Before / after

Before After
No child card until the Operation finishes Card and View session button as soon as the target exists
Creation-only label In-place status updates for the creating target Turn
Batch visibility waits for all results Each materialized target appears and updates independently

Test plan

  • pnpm check passed (typechecks, lint, tests, i18n and repository boundary checks).
  • Final refinements were rechecked with 91 CLI/MCP tests, 32 component tests, 3 shared-schema tests, affected typechecks, and pnpm check:quick.
  • pnpm format passed; unrelated pre-existing Electron formatting was left unchanged.
  • Components regression tests cover immediate navigation, in-place status updates, batch targets, stream cache invalidation, and completion deduplication.
  • Playwright captured actual Storybook components in Chinese light/dark themes and a narrow viewport using synthetic fixtures. Stories: Sessions/SessionRelationCard/{Created,Running,Succeeded,Failed,Cancelled,AllCreationStates}.
  • Real authenticated cross-machine end-to-end creation was not exercised against the modified daemon; coordinator tests use deterministic target and history evidence.

Context handoff

Instructions for reviewing agents

  • Review focus: Check operation-progress-history.ts, coordinator reconciliation, and MCP materialization for stable target identity, progress durability, and lifecycle isolation.
  • Decisions to challenge: Progress is presentation-only system history; completion still owns the sole agent continuation and uses an optional progress link for UI deduplication.
  • Plausible failures / evidence gaps: Pay attention to stale batch snapshots, cancellation before materialization, and terminal progress while the requester is busy; live cross-machine integration was not run.

Authoring context

  • User goal / directives: Make newly created child conversations immediately reachable and display changing execution state, with screenshots and a PR.
  • Constraints / non-goals: Preserve execution permissions, Operation acceptance, completion scheduling, local/cloud boundaries, and unrelated changes.
  • Risk-bearing decisions: Target status is bound to the exact creating Turn rather than later Session activity; terminal progress cannot regress to an active state.
  • Destructive or irreversible behavior: No destructive actions, data migration, or lifecycle rollback is introduced; progress writes only add or update their own stable history row.
  • Deliberately not done or tested: No production credentials or live cross-machine agent work were used for visual verification; synthetic Storybook fixtures and coordinator tests provide bounded evidence.
  • Unknowns / confidence: Static and deterministic regression checks passed; deployed cross-machine timing remains an integration verification gap.

Publish stable creation progress rows with exact-target status updates and immediate navigation. Preserve completion delivery and keep UI progress independent of lifecycle outcomes.

Model: openai-codex/gpt-5.5

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fdb0b3934b

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

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

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

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +155 to +156
const merged = mergeOperationProgressContent(existingProgress, content);
const nextItems = [merged as MessageContent];

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Add operation_progress to the persisted history schema

When this updater runs against a real SessionDocument, Mirror.setState validates nextItems with historyMessageItemSchema; its switch in packages/shared/src/schema.ts has no operation_progress case and returns Unknown type. Consequently every MCP and coordinator progress write is rejected (and then intentionally swallowed), so no live creation card is ever persisted or rendered despite the unit tests passing with schema-free fake documents. Add this variant to the Loro history validator and cover a real Mirror round trip.

AGENTS.md reference: apps/cli/src/orchestration/AGENTS.md:L62-L68

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Confirmed and fixed in df78afe. A regression using upsertOperationProgressHistory with a real validating Loro Mirror reproduced Unknown type: operation_progress before the fix. The persisted history validator now accepts the variant, and snapshot reload tests cover created → running → succeeded/failed/cancelled on one stable row. Shared tests (1031), targeted CLI tests (79), typechecks, formatting, docs and boundary checks pass locally.

Register operation_progress in the persisted history schema and cover created, running, and terminal states with real Mirror snapshot round trips. Route creation-card explanations into the README to restore the document-size CI gate.

Model: openai-codex/gpt-5.5

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: df78afeb39

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

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

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

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +54 to +58
if (operation.completion?.type === 'cancelled') {
return targetStatus || item.inputDurable ? 'cancelled' : null;
}
if (operation.completion?.type === 'error') {
return targetStatus || item.inputDurable ? 'failed' : null;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Preserve the exact target state after root termination

When a materialized target keeps running because best-effort cancellation fails—or has already succeeded before cancellation is reconciled—targetStatus is running or succeeded, but this conditional converts every truthy value to cancelled; the error branch similarly converts it to failed. Since terminal progress is immutable, the card permanently misreports the exact target Turn even when that Session contains successful output. Preserve the collected target status when available and use the root result only when target evidence is unavailable.

AGENTS.md reference: apps/cli/src/orchestration/AGENTS.md:L62-L68

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Confirmed and fixed in 2942697. Fresh exact-target evidence now wins over root cancellation/error. Historical card state is kept separately as materialization evidence, not treated as a current status observation. Regression tests cover a target still running after root cancellation/error, subsequent success, and fallback to the root result when current evidence is unavailable. Targeted history/coordinator tests: 47 passed; CLI typecheck, docs and quick checks pass.

Preserve the updated main-branch sidebar invariants while moving ownership and layout explanations into the directory README. Restore the merged-tree document-size check.

Model: openai-codex/gpt-5.5
Prefer fresh exact-target evidence over root cancellation or coordinator failure. Keep historical materialization evidence separate from live status so unavailable targets still receive the root fallback.

Model: openai-codex/gpt-5.5

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 294269718e

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

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

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

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +1128 to +1129
entry.items?.some(
(item) => item.type === 'operation_progress' && item.operationId === operation.operationId

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Preserve fallback cards for partial progress rows

When a batch has already persisted a progress card for target A but a later progress write that should add target B fails, this predicate still links the completion merely because any matching progress row exists. OperationCompletionView treats that link as permission to suppress every legacy success card, and the delivery is subsequently consumed, so B permanently loses its navigable card instead of the failed progress write remaining repairable. Only set the link when the row covers every successful/materialized target, or deduplicate completion cards per target.

AGENTS.md reference: apps/cli/src/orchestration/AGENTS.md:L62-L68

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Confirmed and fixed. Completion now sets progressMessageId only if the persisted row covers every successful or durably materialized target (checked by both sessionId and userTurnId, including completion results). Partial rows retain legacy success cards, so a failed progress write cannot hide a batch target. Regression tests seed partial/complete batch rows, reject subsequent progress mutations, and verify completion still delivers with the appropriate fallback link. Targeted CLI tests: 83 passed.

Link completion to progress only when every successful or materialized target is represented. Cover partial batch history with injected progress-write failures while allowing completion delivery.

Model: openai-codex/gpt-5.5

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 81f4a05e66

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

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

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

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +53 to +55
if (item.status === 'succeeded') return item.status;
if (item.status === 'failed' || item.status === 'cancelled') {
return wasMaterialized ? item.status : null;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Preserve the exact target status at the deadline

When a create Operation reaches its deadline while the child Turn is still running, reconcileItem produces a failed/TARGET_TIMEOUT item even though collectOperationProgressTargetStatuses reports running; this branch nevertheless returns the item status. mergeProgressItem then freezes that failure as terminal, so the card remains failed even if the child later succeeds. Fresh evidence after the earlier root-termination fix is that the deadline path still overrides an available exact-target observation; prefer targetStatus here whenever it exists.

AGENTS.md reference: apps/cli/src/orchestration/AGENTS.md:L62-L66

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Confirmed and fixed: failed/cancelled item snapshots now prefer fresh targetStatus as well, including TARGET_TIMEOUT while the exact Turn is still running or has succeeded. Root/item fallback applies only without current evidence. Added explicit timeout regression cases.

Comment on lines +1142 to +1147
const complete = [...operation.items, ...results].every((item) =>
item.status === 'succeeded' || (item.status === 'active' && item.inputDurable)
? covered.has(getOperationProgressTargetKey(item.target))
: true
);
return complete ? progressMessageId : undefined;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Do not link completions to stale progress state

When a progress row already covers every target but its terminal upserts fail after it reached running, this coverage-only predicate still returns progressMessageId. The completion view consequently suppresses the successful fallback card, and once delivery is consumed there is no active Operation or pending Delivery left to repair the stale row, so the sole card can remain “Running” permanently. Fresh evidence after the earlier partial-row fix is that target coverage is now verified but terminal status freshness is not; link only after the row reflects the terminal results, or retain a durable repair obligation.

AGENTS.md reference: apps/cli/src/orchestration/AGENTS.md:L62-L70

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Confirmed and fixed: progress links now require each successful completion target to be persisted as succeeded, not merely present. Tests reject terminal progress writes against complete rows still marked created/running and verify completion retains fallback cards. Only a complete succeeded row is linked. Targeted history/coordinator tests: 53 passed.

Prefer observed target status to timeout results and only suppress success fallback cards after the persisted progress row reflects success. Extend deadline and failed-progress-write coverage.

Model: openai-codex/gpt-5.5

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cf5568ad60

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

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

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

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +899 to +902
// Progress is presentation-only, but pending Deliveries are the durable
// repair window after an Operation finished. Retry terminal progress here
// without letting failures block expiry, continuation, or consumption.
await this.writeOperationProgress(operation);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Continue reconciling running targets after delivery

When an Operation finishes at its deadline while the exact target Turn is still running, this pending-Delivery retry updates the card once and the Delivery can then be consumed while the target continues. Subsequent target-history wakes scan only active Operations and pending Deliveries, so the later terminal state is never written and the durable card remains “Running” even after the target succeeds or fails. Fresh evidence beyond the earlier deadline-snapshot fix is the loss of repair ownership after Delivery consumption; retain a durable reconciliation obligation until every published target is terminal.

AGENTS.md reference: apps/cli/src/orchestration/AGENTS.md:L62-L66

Useful? React with 👍 / 👎.

Independently ablate seven candidates against 104 regressions. Keep four equivalent simplifications; retain retry, no-op and freshness safeguards whose removal fails tests. Add transition coverage and results, and remove obsolete PR-generation artifacts while preserving screenshots.

Model: openai-codex/gpt-5.5

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a9453620d2

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

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

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

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

fileDiff: existing?.fileDiff ?? [],
finished: true,
};
if (existingIndex < 0) return [...history, entry];

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Serialize creation of the stable progress row

When markItemInputDurable wakes the daemon while the MCP process is also persisting progress, the two Loro replicas can both observe existingIndex < 0 and append this ID concurrently. Loro preserves both list inserts, so the merged history contains duplicate IDs; later upserts mutate only the first match while buildChatStreamItems renders only the first, allowing a stale Created/Running copy to remain visible even after the other copy reached Succeeded and the linked completion suppressed its fallback card. Serialize the initial insertion or merge/remove every same-ID row so there is actually one monotonic durable card.

AGENTS.md reference: apps/cli/src/orchestration/AGENTS.md:L62-L66

Useful? React with 👍 / 👎.

Track unsettled create progress independently of Delivery consumption, retry through restart and write failures, and acknowledge only after target termination and local Loro durability. Keep root timeout/cancellation separate from the target state.

Use the Host-lease Worker as the sole progress writer, fence late writes after stop, and recover duplicate Loro rows without losing terminal snapshots. Cover real replica merges, the root/target outcome matrix, retention and the executable race model.

Model: openai-codex/gpt-6-astra

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 13b0f8c0f5

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

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

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

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +562 to +564
WHERE workspace_id = ? AND owner_machine_id = ? AND state = 'finished'
AND kind IN ('session_create', 'session_create_many')
AND NOT EXISTS (SELECT 1 FROM operation_progress_settlements p

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Exclude pre-feature completions from progress backfill

On the first startup after this migration, every retained finished create Operation lacks a settlement row, so this query treats it as pending and appends a new progress card. Its already-persisted operation_completion was written by older code and cannot contain progressMessageId; for pre-upgrade Operations whose requester and target documents remain available, the UI therefore renders both the newly backfilled card and the legacy successful-target card permanently. Seed settlements for existing rows or otherwise avoid backfilling Operations whose completion turn predates this feature.

AGENTS.md reference: apps/cli/src/orchestration/AGENTS.md:L62-L70

Useful? React with 👍 / 👎.

const statuses = new Map<string, OperationProgressStatus>();
await this.mapItemsWithConcurrency(operation.items, 5, async (item) => {
if (!('target' in item) || !item.target) return;
if (item.status === 'active' && !item.inputDurable) return;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Recheck preallocated targets after operation cancellation

When cancellation wins after createSessionResult durably writes the target but before markItemInputDurable, the finished Operation retains an active item with inputDurable: false. This return prevents checking that preallocated exact target; with no previously published row, progressIsSettled then sees empty expected and published sets and permanently records the obligation as settled, so the materialized child never receives its navigation card. Finished snapshots with fixed target IDs still need their target evidence checked before settlement.

AGENTS.md reference: apps/cli/src/orchestration/AGENTS.md:L65-L75

Useful? React with 👍 / 👎.

Independently test nine removals against 149 regressions. Keep five simplifications, including duplicate Delivery/root-error progress writes, and restore terminal retry after a combined ablation exposes its dependency. Preserve native duplicate repair, local flush and published labels. Record results and full validation.

Model: openai-codex/gpt-6-astra

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5264add037

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

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

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

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

const statuses = new Map<string, OperationProgressStatus>();
await this.mapItemsWithConcurrency(operation.items, 5, async (item) => {
if (!('target' in item) || !item.target) return;
if (item.status === 'active' && !item.inputDurable) return;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Recheck preallocated targets after cancellation

When cancellation wins after createSessionResult durably writes the fixed target but before markItemInputDurable, store.cancel leaves that item active with inputDurable: false. Fresh evidence despite the earlier claimed fix is that the current collector still returns at this condition, while markItemInputDurable cannot update the now-finished Operation; with no prior card, progressIsSettled then compares two empty sets and permanently settles the obligation, so the materialized child never receives its navigation card. Inspect the fixed target evidence for finished snapshots before allowing settlement.

AGENTS.md reference: apps/cli/src/orchestration/AGENTS.md:L65-L75

Useful? React with 👍 / 👎.

Remove four screenshots and the temporary ablation report from the PR tree. Ignore workspace-local artifacts to prevent accidental recommits; retain implementation and regression tests.

Model: openai-codex/gpt-6-astra

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ce8c6c459c

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

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

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

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

return Array.isArray(v.commands) ? true : 'Missing commands';
case 'system_notice':
return typeof v.name === 'string' ? true : 'Missing name';
case 'operation_progress':

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Preserve compatibility with older session-history schemas

When a shared Session is opened by a peer running an older build, the new daemon can persist this discriminator unconditionally, but that peer's historyMessageItemSchema falls through to Unknown type: operation_progress; ignoreUnknownProperties only covers undeclared object properties, not values rejected by this custom list-item validator. The older peer then cannot perform its next Mirror state update in that Session. Encode progress using a history shape older clients accept, or gate persistence through an explicit compatibility mechanism; adding this case only repairs current-version readers.

Useful? React with 👍 / 👎.

@lodystage
lodystage Bot merged commit 4fa35d7 into main Sep 7, 2026
6 checks passed
@lodystage
lodystage Bot deleted the feat/live-child-session-cards branch September 7, 2026 01:35
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