Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions .codex/prompts/restart-t3code.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
description: Rebuild and restart the PM2-managed t3code app for this repo.
argument-hint: optional target: web or dev
---

# Restart T3 Code

Rebuild and restart the PM2-managed `t3code` processes for this repository.

When you run this command:

1. Work from the repo root.
2. Inspect the optional argument.
3. If no argument is provided, or the argument is `web`, run `bun run rebuild:restart -- web`.
4. If the argument is `dev`, run `bun run rebuild:restart -- dev`.
5. Report which target was restarted and include the relevant PM2 process names.

Target meanings:

- `web`: rebuilds `apps/web` and restarts the Cloudflare/tunnel-backed PM2 app `t3code-web`
- `dev`: restarts the local PM2 dev apps `t3code-dev-server` and `t3code-dev-web`

Do not make unrelated code changes as part of this command.
1 change: 1 addition & 0 deletions apps/server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"@effect/language-service": "catalog:",
"@effect/vitest": "catalog:",
"@t3tools/contracts": "workspace:*",
"@t3tools/plugin-sdk": "workspace:*",
"@t3tools/shared": "workspace:*",
"@t3tools/web": "workspace:*",
"@types/bun": "catalog:",
Expand Down
87 changes: 87 additions & 0 deletions apps/server/src/difitManager.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { describe, expect, it } from "vitest";

import { ProjectId, ThreadId, type OrchestrationReadModel } from "@t3tools/contracts";
import { resolveDifitThreadCwd } from "./difitManager";

function makeSnapshot(): OrchestrationReadModel {
return {
snapshotSequence: 1,
updatedAt: "2026-03-23T00:00:00.000Z",
projects: [
{
id: ProjectId.makeUnsafe("project-1"),
title: "Project",
workspaceRoot: "/repo/root",
defaultModel: null,
scripts: [],
createdAt: "2026-03-23T00:00:00.000Z",
updatedAt: "2026-03-23T00:00:00.000Z",
deletedAt: null,
},
],
threads: [
{
id: ThreadId.makeUnsafe("thread-1"),
projectId: ProjectId.makeUnsafe("project-1"),
title: "Thread",
model: "gpt-5-codex",
runtimeMode: "full-access",
interactionMode: "default",
branch: null,
worktreePath: "/repo/worktrees/feature-a",
latestTurn: null,
createdAt: "2026-03-23T00:00:00.000Z",
updatedAt: "2026-03-23T00:00:00.000Z",
deletedAt: null,
messages: [],
proposedPlans: [],
activities: [],
checkpoints: [],
session: null,
},
{
id: ThreadId.makeUnsafe("thread-2"),
projectId: ProjectId.makeUnsafe("project-1"),
title: "Thread 2",
model: "gpt-5-codex",
runtimeMode: "full-access",
interactionMode: "default",
branch: null,
worktreePath: null,
latestTurn: null,
createdAt: "2026-03-23T00:00:00.000Z",
updatedAt: "2026-03-23T00:00:00.000Z",
deletedAt: null,
messages: [],
proposedPlans: [],
activities: [],
checkpoints: [],
session: null,
},
],
};
}

describe("resolveDifitThreadCwd", () => {
it("prefers thread worktree paths", () => {
expect(resolveDifitThreadCwd(makeSnapshot(), "thread-1")).toEqual({
cwd: "/repo/worktrees/feature-a",
source: "worktree",
});
});

it("falls back to project workspace root", () => {
expect(resolveDifitThreadCwd(makeSnapshot(), "thread-2")).toEqual({
cwd: "/repo/root",
source: "project",
});
});

it("returns thread_not_found for unknown threads", () => {
expect(resolveDifitThreadCwd(makeSnapshot(), "thread-404")).toEqual({
cwd: null,
source: "none",
reason: "thread_not_found",
});
});
});
Loading