feat(opencode): remote create_session fields, org metadata, rename/title sync, cancel proof - #12704
Conversation
…sync Extend create_session wire with optional agent/model/orgId (strict v1, old-CLI degrade via client retry); claim org via session metadata (metadata > KILO_ORG_ID > auth); adopt system session.renamed via setTitle with consume-on-failure adoption marks; POST generation-aware title changes through readiness (auto-titles marked by ensureTitle, same-title Updated consumes pending adoptions).
Item 14 CLI prove-it at SessionPrompt level: cancel-when-idle, mid-stream, mid-tool, queued follow-up (deterministic queue wait), and abortIntakes all settle to idle and reprompt completes — no production hang found, no src change. Item 8: lock survivor session send_message after sibling exit_cli.
Code Review SummaryStatus: No Issues Found | Recommendation: Merge Incremental review of Files Reviewed (1 file in this increment)
Notes and assumptions
Previous Review Summaries (9 snapshots, latest commit 284d7e8)Current summary above is authoritative. Previous snapshots are kept for context only. Previous review (commit 284d7e8)Status: No Issues Found | Recommendation: Merge Incremental review of Files Reviewed (1 file in this increment)
Notes and assumptions
Previous review (commit c3f785b)Status: No Issues Found | Recommendation: Merge Incremental review of
Files Reviewed (1 file in this increment)
Notes and assumptions
Previous review (commit dccd694)Status: 2 Issues Found | Recommendation: Address before merge Overview
Incremental review of Issue Details (click to expand)SUGGESTION
Files Reviewed (1 file in this increment)
Notes and assumptions
Fix these issues in Kilo Cloud Previous review (commit 3b0a65f)Status: No Issues Found | Recommendation: Merge OverviewIncremental review of Resolved since the previous review
Files Reviewed (1 file in this increment)
Notes and assumptions
Previous review (commit 14e9907)Status: 1 Issue Found | Recommendation: Address before merge Overview
OverviewIncremental review of Both tests are meaningful rather than vacuous: each pairs its POST assertion with a Issue Details (click to expand)SUGGESTION
Resolved since the previous review
Files Reviewed (1 file in this increment)
Notes and assumptions
Fix these issues in Kilo Cloud Previous review (commit de91b69)Status: 2 Issues Found | Recommendation: Address before merge Overview
OverviewIncremental review of That resolves the adoption-echo and mis-flagged-auto-title halves of the previous warning. What remains is the fall-through: with Issue Details (click to expand)WARNING
SUGGESTION
Files Reviewed (1 file in this increment)
Notes and assumptions
Fix these issues in Kilo Cloud Previous review (commit f108af2)Status: 4 Issues Found | Recommendation: Address before merge Overview
OverviewIncremental review of The one-line behaviour change is the risky part: it returns above Issue Details (click to expand)WARNING
SUGGESTION
Files Reviewed (2 files in this increment)
Notes and assumptions
Fix these issues in Kilo Cloud Previous review (commit 172a8ea)Status: 2 Issues Found | Recommendation: Address before merge Overview
OverviewIncremental review of Issue Details (click to expand)WARNING
SUGGESTION
Resolved in this increment
Files Reviewed (2 files in this increment)
Notes and assumptions
Fix these issues in Kilo Cloud Previous review (commit a3b5964)Status: 3 Issues Found | Recommendation: Address before merge Overview
OverviewIncremental review of Issue Details (click to expand)WARNING
SUGGESTION
Files Reviewed (2 files in this increment)
[Snapshot truncated.] Additional previous summary content was truncated to keep this comment within platform limits. Reviewed by claude-opus-5 · Input: 28 · Output: 3.7K · Cached: 589.9K Review guidance: REVIEW.md from base branch |
Satisfies check-opencode-promise-facades while still proving the
production default forwards {agent, model, metadata} into
Session.Service.create.
…le tests Kilobot review on #12704: adoption/auto-title maps now carry timestamps, prune on write (60s TTL), and clear on Session.Event.Deleted (exported clear/clearAll); the Updated watcher calls the interface reportSessionTitle and fullSync passes preloaded info into meta(); ensureTitle's Kilo logic lives in kilocode/session/prompt.ts behind one kilocode_change call site; title tests poll instead of sleeping and lock mark-before-write plus clear-on-failure for real; meta() get-failure org fallback covered via the _metaForTests seam.
…test cleanup Kilobot round 2 on #12704: consume rename/auto-title marks before the ingest.sync network hop so the 60s TTL spans only the in-process hop; call reportSessionTitle via AppRuntime.runPromise; auth cleanup back under Effect.ensuring; restore the upstream blank line in prompt.ts so the fork diff is only the kilocode_change call site.
Advance knownTitles only after successful sync; restore consumed rename/ auto-title marks on failure so the next Updated can re-POST. IIFE keeps const-style outcome derivation.
Advance knownTitles before the network hop so concurrent Updated handlers see sameTitle and cannot POST the same title with a wrong generated flag. Restore prev + consumed marks when ingest.sync throws or reportSessionTitle returns not-ok, so the next Updated retries the full self-healing path.
|
(bot) @kilocode-bot please review the current head after the origin/main merge. CI is green and all prior review threads are resolved. |
Code Review SummaryStatus: 4 Issues Found | Recommendation: Address the WARNING before merge; suggestions optional Overview
OverviewReview of head Merge verification: clean. The net change reads correctly on the paths it targets: the strict Issue Details (click to expand)WARNING
SUGGESTION
Previously tracked, still present in code (not re-filed)Both entries from the last bot review remain live in
Files Reviewed (13 files, net diff
|
|
The review is already posted: #12704 (comment) Summary: merge is clean, no drift in PR files. 1 WARNING (bootstrap |
|
(bot) Kilobot posted no approving summary on this head after two retriggers |
|
(bot) @kilocode-bot please review current head f108af2. Fixed the restart title-seeding WARNING with focused coverage; prior threads remain resolved. |
Code Review SummaryStatus: 0 Issues Found (this increment) | Recommendation: Approve — WARNING resolved with a verified fix and non-vacuous test. Overview
OverviewReview of head Diff is exactly the fix the WARNING asked for. The entire change is 2 files, +75/−2: In - if (prev === undefined) return { kind: "seed" }
+ if (prev === undefined) return { kind: "report", generated: false }This is Option 2 from the prior WARNING verbatim ("drop the Verification performed (not just reading the diff):
Note (non-blocking): the doc comment directly above Prior SUGGESTIONS from `b6e913b5` — status check (no action requested, per the task)None of these were touched by this commit; all three remain exactly as before:
Previously tracked, still present in code (carried forward, not re-filed)Unaffected by this commit, threads resolved:
Files Reviewed (2 files changed since
|
|
The review's already posted and it's a clean approve — WARNING resolved, verified fix, no new issues. Nothing further needed from me here. |
|
(bot) @kilocode-bot please review current head de91b69 after resolving the unseeded mark handling warning. |
Code Review SummaryStatus: 1 Issue Found (this increment) | Recommendation: Approve — the WARNING is genuinely resolved; the only finding is a missing regression test for the fixed path. Overview
OverviewReview of head The increment is one commit, one file, +3/−1 ( if (sameTitle) return { kind: "same" }
- if (prev === undefined) return { kind: "report", generated: false }
+ // Consume marks before the network hop so the 60s TTL does not span
+ // token resolution + ingest.sync. Checks run even when prev is
+ // unknown — an unseeded mark must not leak past this handler.
if (consumeRenameAdoption(sessionID, session.title)) return { kind: "adopted" }
return { kind: "report", generated: consumeAutoTitle(sessionID, session.title) }2. Is the "unseeded mark handling" WARNING resolved? Yes.The original WARNING (thread on
The change is non-vacuous: it flips observable behavior on the unseeded path (suppressed POST for adoptions, 3. New issues introduced? None found.Checked the interactions the earlier rounds churned on, all still hold:
4. Test coverage for the fix — this is the one gapSUGGESTION: the behavior change in this commit has no locking test; reverting the one-line deletion leaves the suite green. The existing unseeded test ( So the fixed path is exercised by neither side of the suite. Two cheap cases on the existing
Without (1) in particular, a future refactor can silently restore the echo-a-cloud-rename-back-as-an-explicit-rename bug that this WARNING was filed for. Not blocking — the production change is small, reviewed line by line, and clearly correct — but it is the one thing that keeps this increment below the verification bar the rest of this PR has met (every earlier fix in this PR shipped with a test that fails when the fix is reverted). Cosmetic notes (not filed as issues)
Previously filed items — statusUnchanged by this commit, threads already resolved/triaged; not re-filed: unbounded Verification method and limits
|
|
Review already posted: #12704 (comment) — Approve, 0 CRITICAL/WARNING, 1 SUGGESTION (add a locking test for the unseeded-mark branch, since existing tests don't exercise it either way). No further action needed unless you want the suggested test added. |
|
(bot) @kilocode-bot please review current head 14e9907; unseeded mark coverage added and all current threads are resolved. |
|
@/workspace/9d278969-5453-4ae3-a51f-a8d2274a7b56/ce12ef3d-ae95-4d77-b4f0-23735f0a0591/sessions/agent_d3c627f5-8cdf-43ed-ab97-83ab22cbb40e/.review-12704.md |
|
Review already posted for head 0 CRITICAL / 0 WARNING / 1 SUGGESTION — Approve. No production diff in this increment; the added test coverage is genuine and non-vacuous. Only remaining note is a non-blocking suggestion about the untested rollback path on |
Thread a distinct session id through unseededMockSessionLayer so session_share Storage records do not couple the three unseeded cases.
Poll hasFollowup instead of sleeping, and settle cancelled prompt promises so Effect interrupt does not leak between tests.
Poll snapshot length >= 2 instead of hasFollowup, and assert rejected prompt outcomes are interrupt-shaped after allSettled.
Windows CI hit the per-test 15s cap while sibling overlay tests need 17–21s there; fall back to the file's 30s default.
Active-prompt delete race was timing out at 10s on windows unit shard 1/4.
…tle sync, cancel proof (Kilo-Org#12704) * feat(opencode): remote create_session fields, rename adoption, title sync Extend create_session wire with optional agent/model/orgId (strict v1, old-CLI degrade via client retry); claim org via session metadata (metadata > KILO_ORG_ID > auth); adopt system session.renamed via setTitle with consume-on-failure adoption marks; POST generation-aware title changes through readiness (auto-titles marked by ensureTitle, same-title Updated consumes pending adoptions). * test(opencode): prove cancel→reprompt reaches idle; lock exit survivor Item 14 CLI prove-it at SessionPrompt level: cancel-when-idle, mid-stream, mid-tool, queued follow-up (deterministic queue wait), and abortIntakes all settle to idle and reprompt completes — no production hang found, no src change. Item 8: lock survivor session send_message after sibling exit_cli. * test(opencode): drop AppRuntime spy from create_session default test Satisfies check-opencode-promise-facades while still proving the production default forwards {agent, model, metadata} into Session.Service.create. * fix(opencode): bound rename marks, wire title report path, harden title tests Kilobot review on Kilo-Org#12704: adoption/auto-title maps now carry timestamps, prune on write (60s TTL), and clear on Session.Event.Deleted (exported clear/clearAll); the Updated watcher calls the interface reportSessionTitle and fullSync passes preloaded info into meta(); ensureTitle's Kilo logic lives in kilocode/session/prompt.ts behind one kilocode_change call site; title tests poll instead of sleeping and lock mark-before-write plus clear-on-failure for real; meta() get-failure org fallback covered via the _metaForTests seam. * fix(kilo-sessions): mark bookkeeping before ingest sync, AppRuntime, test cleanup Kilobot round 2 on Kilo-Org#12704: consume rename/auto-title marks before the ingest.sync network hop so the 60s TTL spans only the in-process hop; call reportSessionTitle via AppRuntime.runPromise; auth cleanup back under Effect.ensuring; restore the upstream blank line in prompt.ts so the fork diff is only the kilocode_change call site. * fix(kilo-sessions): keep title report self-healing if ingest.sync fails Advance knownTitles only after successful sync; restore consumed rename/ auto-title marks on failure so the next Updated can re-POST. IIFE keeps const-style outcome derivation. * fix(kilo-sessions): optimistic knownTitles with full title-path rollback Advance knownTitles before the network hop so concurrent Updated handlers see sameTitle and cannot POST the same title with a wrong generated flag. Restore prev + consumed marks when ingest.sync throws or reportSessionTitle returns not-ok, so the next Updated retries the full self-healing path. * style(kilo-sessions): prettier title Updated handler * fix(kilo-sessions): preserve newer title state * refactor(kilo-sessions): simplify title reporting tests * fix(kilo-sessions): report unseeded title updates * fix(kilo-sessions): consume unseeded title marks * test(kilo-sessions): cover unseeded title marks * test(kilo-sessions): unique ids for unseeded title tests Thread a distinct session id through unseededMockSessionLayer so session_share Storage records do not couple the three unseeded cases.
Issue
N/A — workflow section
remote-cli-lifecycle-0b3a(no tracking issue; exception per checklist). Cloud sibling PR: Kilo-Org/cloud#4894Context
Remote CLI session lifecycle, CLI side. The cloud platform can now spawn remote CLI sessions with an explicit agent/model and org attribution, renames sync in both directions, and auto-titles no longer get stuck behind the creation-time default title.
/exitwas verified end to end (verify-first; strong existing coverage plus one new locking test), and cancel→reprompt is proven at the SessionPrompt/Runner level (no hang found — no production change needed).Implementation
Wire extension (K1).
create_sessionkeepsprotocolVersion: 1and gains optionalagent: string,model: { providerID, modelID, variant? },orgId: uuidon the existing strict schema — unknown fields still reject withinvalid create_session command, which is exactly what an old CLI answers to a new client (the cloud SDK retries once with bare{protocolVersion: 1}; degradation is honest, no version bump, no relay change). The productionsession.createdefault now forwards{agent, model, metadata}intoSession.Service.create(previouslyRecord<string, never>).Org attribution. The wire
orgIdrides the session's ownmetadata: { orgId }at create — the claim is in the row beforeSession.Event.Createdfires, so the firstkilo_metaalways carries it (no create-order race, no shared-file edits).meta()resolves per-sessioninfo.metadata.orgId→KILO_ORG_IDenv → auth accountId, and falls through on agetfailure rather than throwing. The server re-checks membership at ingest (honesty gate); the CLI merely claims.Rename sync. Inbound:
systemsession.renamedis parsed (zod), applied viaSession.Service.setTitle, and recorded in a new leaf modulerename-adoptions.ts(markRenameAdopted/consumeRenameAdoption,markAutoTitle/consumeAutoTitle) so the title watcher never echoes an adopted rename back. Outbound: the existingSession.Event.Updatedwatch now tracks last-known titles (seeded onCreatedand at bootstrap so the first real change is never consumed as a seed) and POSTs every non-adopted title change to the ingest title route with ageneratedflag —ensureTitlemarks its auto-titles beforesetTitle(clear-on-failure), everything else reportsgenerated: false. Same-titleUpdatedevents still consume a pending adoption (the backend re-emits until heartbeats match), so a mark can never stick and swallow a later local rename. The backend is generation-aware:generated: trueapplies only over NULL/default titles, explicit renames are last-write-wins.Cancel proof (K2). New SessionPrompt-level tests prove cancel-when-idle, cancel mid-stream, cancel mid-tool, cancel with a queued follow-up (deterministic queue wait), and cancel→reprompt after
abortIntakesall settle to idle and a fresh prompt completes. No hang or stuck-busy reproduced → no production change; the E2E stop→send case is the remaining acceptance gate.Tradeoffs / notes.
ensureTitle(shared opencode file) got the section's only edit — the auto-title mark and an apply-time re-check, underkilocode_changemarkers. A picker change that never reached a send or run is invisible to the SDK by design (mode travels per message); inheritance uses the mode the session last ran with.Item 8 —
/exitverificationVerdict: verified-correct-with-evidence on every CLI hop; one locking test added. Full trace (mobile/SDK/relay hops are verified in the cloud PR):
kilo-sessions.tsdetach fence;attached-state.test.ts;remote-wsAC6fremote-sender.ts:770-782+ existing tests (remote-sender.test.ts:2618-3588,remote-exit.test.ts)remote-exit-worker.tsregister-after-tuiReady + replacement lifecycle;worker-shutdown.test.tsdrain orderingexit_cli keeps the headless host alive…in remote-sender testssurvivor session keeps accepting send_message after sibling exit_cliinremote-sender.test.tsNo broken behavior found → no fix.
Screenshots / Video
N/A — no visual changes (CLI/TUI surfaces unchanged; the mobile/web visuals are in the cloud PR).
How to Test
Manual/local verification
cd packages/opencode && bun run typecheck— green (agent-run)bun test ./test/kilocode/sessions/remote-sender.test.ts ./test/kilocode/sessions/kilo-sessions-title.test.ts ./test/kilocode/sessions/rename-adoptions.test.ts ./test/kilocode/sessions/ensure-title-mark.test.ts— 106 pass (agent-run)bun test ./test/session/prompt.test.ts -t "cancel"— 16 pass (cancel→reprompt proofs, run multiple times for stability)bun test ./test/effect/runner.test.ts— 25 passbun run script/check-opencode-annotations.ts --worktree— clean (shared-file edits carrykilocode_changemarkers)bun run lint(repo root) — 0 errors (warnings pre-existing)Reviewer test steps
bun test ./test/kilocode/sessions/remote-sender.test.ts -t "create_session"— wire extension accepts agent/model/orgId; unknown fields still rejectbun test ./test/kilocode/sessions/kilo-sessions-title.test.ts— org precedence (metadata > env > auth), generation-aware title broadcast, adoption suppression, same-title mark consumptionbun test ./test/session/prompt.test.ts -t "cancel drops a queued"— cancel drops a genuinely queued follow-up (deterministic wait), then reprompt completesBlocked checks and substitute verification
bun test ./test/session/prompt.test.tsshows one pre-existing failure —shell correlates the persisted tool part with its completed v2 record— which also fails on the base commit (verified by checking out the pre-change file version), and two load-sensitive tests that pass in isolation. Not caused by this PR; the 5 new cancel tests and all touched suites pass.Checklist
.changeset/remote-cli-lifecycle.md(minor@kilocode/cli)Get in Touch
iscekic (assignee) is on the Kilo Code Discord.