Skip to content

Port the CLI to orchestrator V2 (0.3.0) - #10

Merged
MajesteitBart merged 8 commits into
mainfrom
t3code/assess-orchestrator-cli-relevance
Oct 4, 2026
Merged

MajesteitBart merged 8 commits into
mainfrom
t3code/assess-orchestrator-cli-relevance

Conversation

@MajesteitBart

Copy link
Copy Markdown
Owner

Ports the CLI to T3 Code's orchestrator V2 and releases it as 0.3.0.

0.3 works only with T3 Code builds that include orchestrator V2. That means nightly 0.0.46-nightly.20261003.2610 or later. Stable T3 Code v0.0.45 and earlier run orchestrator V1 and need @bvdm/t3code-cli@0.2. 0.3 checks the server's protocol before it signs in and refuses anything other than protocol 2 with T3_PROTOCOL_UNSUPPORTED. The README, the npm description, --help, and both shipped skills say so.

Changes

  • Sign-in runs a t3 command whose version matches the server. The bundled t3 package is gone.
  • Handovers use one orchestration.launchThread call, gain --wait, and record the checkout's branch on the thread.
  • Thread reads, waits, and busy checks use V2 runs and runtime requests.
  • threads send --if-busy refuse|queue|steer|restart, provider switching through T3's handoff, and new commands: fork, merge-back, queue, search, pin, snooze, archive, rename, and schedules.
  • Every write is checked in T3's state before the CLI reports success.
  • The publish workflow skips GitHub prereleases, so betas stay off npm.

Breaking changes for scripts that read the JSON output are listed under "Upgrading from 0.2" in the README.

Testing

  • pnpm check passes on Windows: 249 tests, with 2 Linux-only tests skipped. CI runs both on Ubuntu with Node 22 and 24.
  • Full user tests against V2 nightlies: on Linux with beta.1 and on Windows 11 with beta.2. beta.2 was also checked live on Linux. Both betas are GitHub prereleases.

T3 Code's orchestrator V2 (orchestration protocol 2) removed the HTTP
dispatch and snapshot routes, moved its state to statev2.sqlite, and
requires protocol 2 on every orchestration request. CLI 0.2 could no
longer sign in or send anything to a V2 server.

- Speak protocol 2 only and refuse other servers with
  T3_PROTOCOL_UNSUPPORTED before signing in. 0.2 stays the release for
  T3 builds before orchestrator V2.
- Sign in through a `t3` whose version matches the server: the configured
  command, the installed desktop app's bundled server, a matching `t3` on
  PATH, or npx pinned to the server version. The bundled t3 package is
  gone.
- Launch handovers through orchestration.launchThread and send every
  other write through orchestration.dispatchCommand. Every write is
  verified in T3's projection before success is reported.
- Read threads as runs and runtime requests, including the history a fork
  inherits, and drop the V1 heuristics that guessed which turn a message
  belonged to.
- Add handover --wait, --if-busy queue|steer|restart, provider switches
  through threads set, threads fork, merge-back, queue, search, pin,
  snooze, archive, rename, and the schedules commands.
- Discover servers with Node's http client: two global fetch calls
  followed by process.exit crashed Node 26 on Windows at exit.
- Replace the V1 test suite with tests against an in-memory protocol 2
  server, and document the changes in README, AGENTS.md, and the skills.

BREAKING CHANGE: requires a T3 Code build with orchestrator V2. JSON
fields that described V1 sessions and turns changed; README lists them
under "Upgrading from 0.2".
A prerelease is a beta for testing, so the publish job skips it. README documents building, packing, and installing a beta from its GitHub release.
…tions

A user test of 0.3.0-beta.1 on Linux found three issues:

- Sign-in found no desktop install when T3 ran as an AppImage and fell
  back to npx, a 117 MB download. On Linux the CLI now uses the running
  server's own executable and entry, read from /proc through the pid in
  T3's runtime file. A relative entry resolves against the server's
  working directory.
- handover --thinking-effort wrote three effort option ids for a Codex
  model. Overrides now resolve through the model catalog, as threads set
  does, with the old behavior when T3 returns no catalog.
- The last message of an interrupted turn rendered as "assistant
  (final)". Only a completed turn has a final answer again.

Parallel version probes of several desktop installs could also lose a
cache entry; they now share one read and one write.
A handover from a linked worktree launched with existing_worktree and no
branch, so T3 recorded the thread without one. T3's own client sends the
branch for existing_worktree and root launches, and T3 uses it for pull
request discovery, settlement, and recreating a missing worktree.

The CLI now sends the checkout's branch on both. It leaves out a
temporary t3code/<hex> branch in a worktree: T3 renames such a branch
after the first message, even in an existing worktree, which would pull
it from under the thread that created it. Schedules are unchanged,
because a scheduled run happens later on whatever branch is checked out.

The fake server recorded "main" for a launch without a branch, which
hid the bug. It now records none, as T3 does.

The README also notes the Windows shells that change prompts: Windows
PowerShell 5.1 and PowerShell before 7.3 drop double quotes from
arguments, 5.1 sends stdin as ASCII, and Git Bash rewrites an argument
that starts with a slash into a Windows path.
The README opens with the requirement and maps T3 Code builds to CLI
versions: nightly 0.0.46-nightly.20261003.2610 or later needs 0.3, and
stable v0.0.45 or earlier needs 0.2. The npm description, the --help
text, and both shipped skills name the requirement and the 0.2
fallback too.
@clark-review

clark-review Bot commented Oct 4, 2026 •

Copy link
Copy Markdown

Mira PR Walkthrough

This PR ports the CLI to orchestrator V2 and releases version 0.3.0, requiring a compatible T3 Code build and rejecting older server protocols before sign-in. It expands thread and schedule commands, adds busy-handling policies and handover waiting, and verifies writes against server state before reporting success. The migration also replaces the bundled T3 dependency with server-matched sign-in execution and substantially updates test coverage.

graph LR
  cli["src/cli.ts"] --> cliV2["src/cliV2.ts"]
  cli --> shared["src/cliShared.ts"]
  cliV2 --> shared
  cliV2 --> commands["src/v2Commands.ts"]
  tests["src/v2Commands.test.ts"] --> commands
  tests --> fake["src/testing/fakeT3.ts"]
Loading
Confidence: 3/5   ◉◉◉○○   Moderate confidence
  • Reported automated and live cross-platform testing is encouraging, but metadata alone cannot verify correctness across this broad protocol migration and new command surface.

Key files to review:

  • src/v2Commands.ts:898 — Schedule verification accepts retained weekday restrictions and unexpected model options.

12 files reviewed · 1 comment (⚠️ 1 warning)


📋 Reviewed 12 of 34 files

This PR is large enough that some files were skipped to keep the review focused on the highest-priority changes. To review the rest, comment @miracodeai review-rest on this PR.

Skipped:

  • src/threads.test.ts
  • src/transcript.test.ts
  • src/service.ts
  • src/threadApi.test.ts
  • src/threadApi.ts
  • src/threadControls.test.ts
  • src/threadControls.ts
  • src/transcript.ts
  • …and 14 more

Comment @miracodeai help to get the list of available commands and usage tips.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 4, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-04T08:30:04.528485Z 17fff48 PR opened
🔒 Security Review ✅ Completed 2026-10-04T08:29:27.394064Z 17fff48 PR opened

Security findings

Advisory findings (1)

ℹ️ About Codex in GitHub

Your team has set up Codex to 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@clark-review clark-review 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.

Mira Review Summary

The schedule verification in src/v2Commands.ts:898 accepts schedules that retain weekday restrictions or contain unexpected model options. It should verify that cleared schedule fields and model options match the requested values exactly.

Key Issues

Issue Location
🔴 Schedule verification accepts retained weekday restrictions and unexpected model options. src/v2Commands.ts:898

Comment thread src/v2Commands.ts
};
const saved = taskOf(await scheduleRpc(api, "scheduledTasks.upsert", input), "scheduledTasks.upsert");
const expected = savedFields(input);
const task = await verifyTask(api, saved.id, (candidate) => includes(savedFields(candidate), expected), `T3 did not list scheduled task ${saved.id} as it was saved.`);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Bug
⚠️ Warning

Verify cleared schedule fields and model options exactly

includes only checks keys present in the expected object, so it accepts persisted settings that change the task's behavior. For example, an expected daily schedule omits weekdays, and a stored weekday-only schedule passes verification. Similarly, expected empty model options accept any stored options. The same comparison in updateSchedule reports success when --days daily fails to clear an existing weekday restriction. Normalize absent weekdays to an empty array and compare the normalized option maps exactly, while allowing unrelated server metadata.


Prompt for AI Agents
Fix scheduled-task verification in src/v2Commands.ts at line 898 and the equivalent updateSchedule check. Normalize fixed-time schedules so absent weekdays become an empty array, and compare normalized model option maps with exact key/value equality rather than recursive subset matching. Continue allowing unrelated server metadata. Add regression tests in src/v2Commands.test.ts where T3 retains weekday restrictions after --days daily and retains unexpected model options; both saves must fail verification.

Not useful? Reply @miracodeai reject to dismiss this suggestion.

@MajesteitBart
MajesteitBart merged commit a92548e into main Oct 4, 2026
4 checks passed

@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 Security Review · Automatically triggered

Here are some automated security review suggestions for this pull request.

Reviewed commit: 17fff48d19

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

Comment thread src/process.ts
const npx = process.platform === "win32" ? "npx.cmd" : "npx";
if (await commandExists(npx)) {
return { command: npx, argsPrefix: ["--yes", "t3@latest"], source: "npx", version: null };
const spec = serverVersion ? `t3@${serverVersion}` : "t3@latest";

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 Security Review · Automatically triggered

P1 Badge Security: Reject non-version server selectors before invoking npx

When a user or automation points --origin at an attacker-controlled T3 endpoint and no matching local t3 command is found, the endpoint can return a serverVersion such as https://attacker/evil.tgz. This line builds t3@<serverVersion> without validating that it is a version; npm accepts URLs, aliases, Git references, and file paths as package selectors, so npx --yes installs and executes the attacker's package before authentication. Restrict this value to the exact supported semver grammar or require an explicitly trusted installation mechanism.

Useful? React with 👍 / 👎.

@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: 17fff48d19

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/process.ts
if (configured && configured.length > 0) {
const [command, ...argsPrefix] = configured;
if (!command) throw new CliError("INVALID_T3_COMMAND", "Configured t3Command is empty.");
return { command, argsPrefix, source: "configured", version: 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.

P2 Badge Validate the configured T3 command version

When t3Command points to a different installed T3 version—such as after the server is upgraded—this branch returns it without probing --version, even if a matching server, desktop, PATH, or npx invocation is available. withT3Api then issues the session in the wrong version's database, causing every authenticated command to fail; validate the configured invocation against serverVersion before selecting it.

AGENTS.md reference: AGENTS.md:L15-L15

Useful? React with 👍 / 👎.

Comment thread src/service.ts
const dispatch = dryRun ? null : await api.dispatch(create.command);
return { project, created: true, command: create.command, dispatch };
if (dryRun) return { project: planned, created: true, command, dispatch: null };
const dispatch = await api.mutateProject(command);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Dispatch and verify project creation through V2

When projects ensure creates a missing project, this call bypasses orchestration.dispatchCommand and treats any successful HTTP response—even one without a project id—as success by returning the synthetic planned object without checking the projection. The analogous handover path does the same, so a dropped or unapplied mutation can be reported as created; route project.create through the V2 dispatcher and poll the project projection before returning success.

AGENTS.md reference: AGENTS.md:L18-L18

Useful? React with 👍 / 👎.

Comment thread src/service.ts
Comment on lines 209 to 210
messageCount: messages.length,
turnCount: transcript.view.totalTurns,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Avoid presenting bounded counts as totals

inspectThread obtains this projection through the /bounded detail endpoint, which intentionally contains only a recent message window, but these fields are displayed as the thread's total turn and message counts. Long threads therefore underreport messageCount, and migrated V1 threads without run records also underreport turnCount; use a full read or expose these values as bounded-window counts instead.

Useful? React with 👍 / 👎.

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.

1 participant