[codex] Improve workspace runtime and navigation ergonomics (#3680)
## Thinking Path
> - Paperclip orchestrates AI agents for zero-human companies
> - That operator experience depends not just on issue chat, but also on
how workspaces, inbox groups, and navigation state behave over
long-running sessions
> - The current branch included a separate cluster of workspace-runtime
controls, inbox grouping, sidebar ordering, and worktree lifecycle fixes
> - Those changes cross server, shared contracts, database state, and UI
navigation, but they still form one coherent operator workflow area
> - This pull request isolates the workspace/runtime and navigation
ergonomics work into one standalone branch
> - The benefit is better workspace recovery and navigation persistence
without forcing reviewers through the unrelated issue-detail/chat work
## What Changed
- Improved execution workspace and project workspace controls, request
wiring, layout, and JSON editor ergonomics
- Hardened linked worktree reuse/startup behavior and documented the
`worktree repair` flow for recovering linked worktrees safely
- Added inbox workspace grouping, mobile collapse, archive undo,
keyboard navigation, shared group-header styling, and persisted
collapsed-group behavior
- Added persistent sidebar order preferences with the supporting DB
migration, shared/server contracts, routes, services, hooks, and UI
integration
- Scoped issue-list preferences by context and added targeted UI/server
tests for workspace controls, inbox behavior, sidebar preferences, and
worktree validation
## Verification
- `pnpm vitest run
server/src/__tests__/sidebar-preferences-routes.test.ts
ui/src/pages/Inbox.test.tsx
ui/src/components/ProjectWorkspaceSummaryCard.test.tsx
ui/src/components/WorkspaceRuntimeControls.test.tsx
ui/src/api/workspace-runtime-control.test.ts`
- `server/src/__tests__/workspace-runtime.test.ts` was attempted, but
the embedded Postgres suite self-skipped/hung on this host after
reporting an init-script issue, so it is not counted as a local pass
here
## Risks
- Medium: this branch includes migration-backed preference storage plus
worktree/runtime behavior, so merge review should pay attention to state
persistence and worktree recovery semantics
- The sidebar preference migration is standalone, but it should still be
watched for conflicts if another migration lands first
## Model Used
- OpenAI Codex coding agent (GPT-5-class runtime in Codex CLI; exact
deployed model ID is not exposed in this environment), reasoning
enabled, tool use and local code execution enabled
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [ ] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [ ] If this change affects the UI, I have included before/after
screenshots
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge
---------
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-14 12:57:11 -05:00
|
|
|
import { Router, type Request, type Response } from "express";
|
2026-03-03 08:45:26 -06:00
|
|
|
import type { Db } from "@paperclipai/db";
|
2026-02-25 08:38:46 -06:00
|
|
|
import {
|
|
|
|
|
createProjectSchema,
|
|
|
|
|
createProjectWorkspaceSchema,
|
[codex] Improve workspace runtime and navigation ergonomics (#3680)
## Thinking Path
> - Paperclip orchestrates AI agents for zero-human companies
> - That operator experience depends not just on issue chat, but also on
how workspaces, inbox groups, and navigation state behave over
long-running sessions
> - The current branch included a separate cluster of workspace-runtime
controls, inbox grouping, sidebar ordering, and worktree lifecycle fixes
> - Those changes cross server, shared contracts, database state, and UI
navigation, but they still form one coherent operator workflow area
> - This pull request isolates the workspace/runtime and navigation
ergonomics work into one standalone branch
> - The benefit is better workspace recovery and navigation persistence
without forcing reviewers through the unrelated issue-detail/chat work
## What Changed
- Improved execution workspace and project workspace controls, request
wiring, layout, and JSON editor ergonomics
- Hardened linked worktree reuse/startup behavior and documented the
`worktree repair` flow for recovering linked worktrees safely
- Added inbox workspace grouping, mobile collapse, archive undo,
keyboard navigation, shared group-header styling, and persisted
collapsed-group behavior
- Added persistent sidebar order preferences with the supporting DB
migration, shared/server contracts, routes, services, hooks, and UI
integration
- Scoped issue-list preferences by context and added targeted UI/server
tests for workspace controls, inbox behavior, sidebar preferences, and
worktree validation
## Verification
- `pnpm vitest run
server/src/__tests__/sidebar-preferences-routes.test.ts
ui/src/pages/Inbox.test.tsx
ui/src/components/ProjectWorkspaceSummaryCard.test.tsx
ui/src/components/WorkspaceRuntimeControls.test.tsx
ui/src/api/workspace-runtime-control.test.ts`
- `server/src/__tests__/workspace-runtime.test.ts` was attempted, but
the embedded Postgres suite self-skipped/hung on this host after
reporting an init-script issue, so it is not counted as a local pass
here
## Risks
- Medium: this branch includes migration-backed preference storage plus
worktree/runtime behavior, so merge review should pay attention to state
persistence and worktree recovery semantics
- The sidebar preference migration is standalone, but it should still be
watched for conflicts if another migration lands first
## Model Used
- OpenAI Codex coding agent (GPT-5-class runtime in Codex CLI; exact
deployed model ID is not exposed in this environment), reasoning
enabled, tool use and local code execution enabled
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [ ] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [ ] If this change affects the UI, I have included before/after
screenshots
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge
---------
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-14 12:57:11 -05:00
|
|
|
findWorkspaceCommandDefinition,
|
2026-03-02 16:43:59 -06:00
|
|
|
isUuidLike,
|
[codex] Improve workspace runtime and navigation ergonomics (#3680)
## Thinking Path
> - Paperclip orchestrates AI agents for zero-human companies
> - That operator experience depends not just on issue chat, but also on
how workspaces, inbox groups, and navigation state behave over
long-running sessions
> - The current branch included a separate cluster of workspace-runtime
controls, inbox grouping, sidebar ordering, and worktree lifecycle fixes
> - Those changes cross server, shared contracts, database state, and UI
navigation, but they still form one coherent operator workflow area
> - This pull request isolates the workspace/runtime and navigation
ergonomics work into one standalone branch
> - The benefit is better workspace recovery and navigation persistence
without forcing reviewers through the unrelated issue-detail/chat work
## What Changed
- Improved execution workspace and project workspace controls, request
wiring, layout, and JSON editor ergonomics
- Hardened linked worktree reuse/startup behavior and documented the
`worktree repair` flow for recovering linked worktrees safely
- Added inbox workspace grouping, mobile collapse, archive undo,
keyboard navigation, shared group-header styling, and persisted
collapsed-group behavior
- Added persistent sidebar order preferences with the supporting DB
migration, shared/server contracts, routes, services, hooks, and UI
integration
- Scoped issue-list preferences by context and added targeted UI/server
tests for workspace controls, inbox behavior, sidebar preferences, and
worktree validation
## Verification
- `pnpm vitest run
server/src/__tests__/sidebar-preferences-routes.test.ts
ui/src/pages/Inbox.test.tsx
ui/src/components/ProjectWorkspaceSummaryCard.test.tsx
ui/src/components/WorkspaceRuntimeControls.test.tsx
ui/src/api/workspace-runtime-control.test.ts`
- `server/src/__tests__/workspace-runtime.test.ts` was attempted, but
the embedded Postgres suite self-skipped/hung on this host after
reporting an init-script issue, so it is not counted as a local pass
here
## Risks
- Medium: this branch includes migration-backed preference storage plus
worktree/runtime behavior, so merge review should pay attention to state
persistence and worktree recovery semantics
- The sidebar preference migration is standalone, but it should still be
watched for conflicts if another migration lands first
## Model Used
- OpenAI Codex coding agent (GPT-5-class runtime in Codex CLI; exact
deployed model ID is not exposed in this environment), reasoning
enabled, tool use and local code execution enabled
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [ ] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [ ] If this change affects the UI, I have included before/after
screenshots
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge
---------
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-14 12:57:11 -05:00
|
|
|
matchWorkspaceRuntimeServiceToCommand,
|
2026-02-25 08:38:46 -06:00
|
|
|
updateProjectSchema,
|
|
|
|
|
updateProjectWorkspaceSchema,
|
[codex] Improve workspace runtime and navigation ergonomics (#3680)
## Thinking Path
> - Paperclip orchestrates AI agents for zero-human companies
> - That operator experience depends not just on issue chat, but also on
how workspaces, inbox groups, and navigation state behave over
long-running sessions
> - The current branch included a separate cluster of workspace-runtime
controls, inbox grouping, sidebar ordering, and worktree lifecycle fixes
> - Those changes cross server, shared contracts, database state, and UI
navigation, but they still form one coherent operator workflow area
> - This pull request isolates the workspace/runtime and navigation
ergonomics work into one standalone branch
> - The benefit is better workspace recovery and navigation persistence
without forcing reviewers through the unrelated issue-detail/chat work
## What Changed
- Improved execution workspace and project workspace controls, request
wiring, layout, and JSON editor ergonomics
- Hardened linked worktree reuse/startup behavior and documented the
`worktree repair` flow for recovering linked worktrees safely
- Added inbox workspace grouping, mobile collapse, archive undo,
keyboard navigation, shared group-header styling, and persisted
collapsed-group behavior
- Added persistent sidebar order preferences with the supporting DB
migration, shared/server contracts, routes, services, hooks, and UI
integration
- Scoped issue-list preferences by context and added targeted UI/server
tests for workspace controls, inbox behavior, sidebar preferences, and
worktree validation
## Verification
- `pnpm vitest run
server/src/__tests__/sidebar-preferences-routes.test.ts
ui/src/pages/Inbox.test.tsx
ui/src/components/ProjectWorkspaceSummaryCard.test.tsx
ui/src/components/WorkspaceRuntimeControls.test.tsx
ui/src/api/workspace-runtime-control.test.ts`
- `server/src/__tests__/workspace-runtime.test.ts` was attempted, but
the embedded Postgres suite self-skipped/hung on this host after
reporting an init-script issue, so it is not counted as a local pass
here
## Risks
- Medium: this branch includes migration-backed preference storage plus
worktree/runtime behavior, so merge review should pay attention to state
persistence and worktree recovery semantics
- The sidebar preference migration is standalone, but it should still be
watched for conflicts if another migration lands first
## Model Used
- OpenAI Codex coding agent (GPT-5-class runtime in Codex CLI; exact
deployed model ID is not exposed in this environment), reasoning
enabled, tool use and local code execution enabled
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [ ] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [ ] If this change affects the UI, I have included before/after
screenshots
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge
---------
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-14 12:57:11 -05:00
|
|
|
workspaceRuntimeControlTargetSchema,
|
2026-03-03 08:45:26 -06:00
|
|
|
} from "@paperclipai/shared";
|
2026-04-03 07:32:54 -05:00
|
|
|
import { trackProjectCreated } from "@paperclipai/shared/telemetry";
|
2026-02-16 13:31:58 -06:00
|
|
|
import { validate } from "../middleware/validate.js";
|
2026-04-06 09:34:15 -05:00
|
|
|
import { projectService, logActivity, secretService, workspaceOperationService } from "../services/index.js";
|
2026-03-02 16:43:59 -06:00
|
|
|
import { conflict } from "../errors.js";
|
Add server routes for companies, approvals, costs, and dashboard
New routes: companies, approvals, costs, dashboard, authz. New
services: companies, approvals, costs, dashboard, heartbeat,
activity-log. Add auth middleware and structured error handling.
Expand existing agent and issue routes with richer CRUD operations.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 09:07:27 -06:00
|
|
|
import { assertCompanyAccess, getActorInfo } from "./authz.js";
|
[codex] Improve workspace runtime and navigation ergonomics (#3680)
## Thinking Path
> - Paperclip orchestrates AI agents for zero-human companies
> - That operator experience depends not just on issue chat, but also on
how workspaces, inbox groups, and navigation state behave over
long-running sessions
> - The current branch included a separate cluster of workspace-runtime
controls, inbox grouping, sidebar ordering, and worktree lifecycle fixes
> - Those changes cross server, shared contracts, database state, and UI
navigation, but they still form one coherent operator workflow area
> - This pull request isolates the workspace/runtime and navigation
ergonomics work into one standalone branch
> - The benefit is better workspace recovery and navigation persistence
without forcing reviewers through the unrelated issue-detail/chat work
## What Changed
- Improved execution workspace and project workspace controls, request
wiring, layout, and JSON editor ergonomics
- Hardened linked worktree reuse/startup behavior and documented the
`worktree repair` flow for recovering linked worktrees safely
- Added inbox workspace grouping, mobile collapse, archive undo,
keyboard navigation, shared group-header styling, and persisted
collapsed-group behavior
- Added persistent sidebar order preferences with the supporting DB
migration, shared/server contracts, routes, services, hooks, and UI
integration
- Scoped issue-list preferences by context and added targeted UI/server
tests for workspace controls, inbox behavior, sidebar preferences, and
worktree validation
## Verification
- `pnpm vitest run
server/src/__tests__/sidebar-preferences-routes.test.ts
ui/src/pages/Inbox.test.tsx
ui/src/components/ProjectWorkspaceSummaryCard.test.tsx
ui/src/components/WorkspaceRuntimeControls.test.tsx
ui/src/api/workspace-runtime-control.test.ts`
- `server/src/__tests__/workspace-runtime.test.ts` was attempted, but
the embedded Postgres suite self-skipped/hung on this host after
reporting an init-script issue, so it is not counted as a local pass
here
## Risks
- Medium: this branch includes migration-backed preference storage plus
worktree/runtime behavior, so merge review should pay attention to state
persistence and worktree recovery semantics
- The sidebar preference migration is standalone, but it should still be
watched for conflicts if another migration lands first
## Model Used
- OpenAI Codex coding agent (GPT-5-class runtime in Codex CLI; exact
deployed model ID is not exposed in this environment), reasoning
enabled, tool use and local code execution enabled
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [ ] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [ ] If this change affects the UI, I have included before/after
screenshots
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge
---------
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-14 12:57:11 -05:00
|
|
|
import {
|
|
|
|
|
buildWorkspaceRuntimeDesiredStatePatch,
|
|
|
|
|
listConfiguredRuntimeServiceEntries,
|
|
|
|
|
runWorkspaceJobForControl,
|
|
|
|
|
startRuntimeServicesForWorkspaceControl,
|
|
|
|
|
stopRuntimeServicesForProjectWorkspace,
|
|
|
|
|
} from "../services/workspace-runtime.js";
|
2026-04-03 07:32:54 -05:00
|
|
|
import { getTelemetryClient } from "../telemetry.js";
|
2026-02-16 13:31:58 -06:00
|
|
|
|
|
|
|
|
export function projectRoutes(db: Db) {
|
|
|
|
|
const router = Router();
|
|
|
|
|
const svc = projectService(db);
|
2026-04-06 09:34:15 -05:00
|
|
|
const secretsSvc = secretService(db);
|
2026-03-28 16:46:43 -05:00
|
|
|
const workspaceOperations = workspaceOperationService(db);
|
2026-04-06 09:34:15 -05:00
|
|
|
const strictSecretsMode = process.env.PAPERCLIP_SECRETS_STRICT_MODE === "true";
|
2026-02-16 13:31:58 -06:00
|
|
|
|
2026-03-02 16:43:59 -06:00
|
|
|
async function resolveCompanyIdForProjectReference(req: Request) {
|
|
|
|
|
const companyIdQuery = req.query.companyId;
|
|
|
|
|
const requestedCompanyId =
|
|
|
|
|
typeof companyIdQuery === "string" && companyIdQuery.trim().length > 0
|
|
|
|
|
? companyIdQuery.trim()
|
|
|
|
|
: null;
|
|
|
|
|
if (requestedCompanyId) {
|
|
|
|
|
assertCompanyAccess(req, requestedCompanyId);
|
|
|
|
|
return requestedCompanyId;
|
|
|
|
|
}
|
|
|
|
|
if (req.actor.type === "agent" && req.actor.companyId) {
|
|
|
|
|
return req.actor.companyId;
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function normalizeProjectReference(req: Request, rawId: string) {
|
|
|
|
|
if (isUuidLike(rawId)) return rawId;
|
|
|
|
|
const companyId = await resolveCompanyIdForProjectReference(req);
|
|
|
|
|
if (!companyId) return rawId;
|
|
|
|
|
const resolved = await svc.resolveByReference(companyId, rawId);
|
|
|
|
|
if (resolved.ambiguous) {
|
|
|
|
|
throw conflict("Project shortname is ambiguous in this company. Use the project ID.");
|
|
|
|
|
}
|
|
|
|
|
return resolved.project?.id ?? rawId;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
router.param("id", async (req, _res, next, rawId) => {
|
|
|
|
|
try {
|
|
|
|
|
req.params.id = await normalizeProjectReference(req, rawId);
|
|
|
|
|
next();
|
|
|
|
|
} catch (err) {
|
|
|
|
|
next(err);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
Add server routes for companies, approvals, costs, and dashboard
New routes: companies, approvals, costs, dashboard, authz. New
services: companies, approvals, costs, dashboard, heartbeat,
activity-log. Add auth middleware and structured error handling.
Expand existing agent and issue routes with richer CRUD operations.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 09:07:27 -06:00
|
|
|
router.get("/companies/:companyId/projects", async (req, res) => {
|
|
|
|
|
const companyId = req.params.companyId as string;
|
|
|
|
|
assertCompanyAccess(req, companyId);
|
|
|
|
|
const result = await svc.list(companyId);
|
2026-02-16 13:31:58 -06:00
|
|
|
res.json(result);
|
|
|
|
|
});
|
|
|
|
|
|
Add server routes for companies, approvals, costs, and dashboard
New routes: companies, approvals, costs, dashboard, authz. New
services: companies, approvals, costs, dashboard, heartbeat,
activity-log. Add auth middleware and structured error handling.
Expand existing agent and issue routes with richer CRUD operations.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 09:07:27 -06:00
|
|
|
router.get("/projects/:id", async (req, res) => {
|
2026-02-16 13:31:58 -06:00
|
|
|
const id = req.params.id as string;
|
|
|
|
|
const project = await svc.getById(id);
|
|
|
|
|
if (!project) {
|
|
|
|
|
res.status(404).json({ error: "Project not found" });
|
|
|
|
|
return;
|
|
|
|
|
}
|
Add server routes for companies, approvals, costs, and dashboard
New routes: companies, approvals, costs, dashboard, authz. New
services: companies, approvals, costs, dashboard, heartbeat,
activity-log. Add auth middleware and structured error handling.
Expand existing agent and issue routes with richer CRUD operations.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 09:07:27 -06:00
|
|
|
assertCompanyAccess(req, project.companyId);
|
2026-02-16 13:31:58 -06:00
|
|
|
res.json(project);
|
|
|
|
|
});
|
|
|
|
|
|
Add server routes for companies, approvals, costs, and dashboard
New routes: companies, approvals, costs, dashboard, authz. New
services: companies, approvals, costs, dashboard, heartbeat,
activity-log. Add auth middleware and structured error handling.
Expand existing agent and issue routes with richer CRUD operations.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 09:07:27 -06:00
|
|
|
router.post("/companies/:companyId/projects", validate(createProjectSchema), async (req, res) => {
|
|
|
|
|
const companyId = req.params.companyId as string;
|
|
|
|
|
assertCompanyAccess(req, companyId);
|
2026-03-02 14:21:03 -06:00
|
|
|
type CreateProjectPayload = Parameters<typeof svc.create>[1] & {
|
|
|
|
|
workspace?: Parameters<typeof svc.createWorkspace>[1];
|
2026-03-02 13:32:31 -06:00
|
|
|
};
|
2026-03-02 14:21:03 -06:00
|
|
|
|
|
|
|
|
const { workspace, ...projectData } = req.body as CreateProjectPayload;
|
2026-04-06 09:34:15 -05:00
|
|
|
if (projectData.env !== undefined) {
|
|
|
|
|
projectData.env = await secretsSvc.normalizeEnvBindingsForPersistence(
|
|
|
|
|
companyId,
|
|
|
|
|
projectData.env,
|
|
|
|
|
{ strictMode: strictSecretsMode, fieldPath: "env" },
|
|
|
|
|
);
|
|
|
|
|
}
|
2026-03-02 13:32:31 -06:00
|
|
|
const project = await svc.create(companyId, projectData);
|
|
|
|
|
let createdWorkspaceId: string | null = null;
|
|
|
|
|
if (workspace) {
|
|
|
|
|
const createdWorkspace = await svc.createWorkspace(project.id, workspace);
|
|
|
|
|
if (!createdWorkspace) {
|
|
|
|
|
await svc.remove(project.id);
|
|
|
|
|
res.status(422).json({ error: "Invalid project workspace payload" });
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
createdWorkspaceId = createdWorkspace.id;
|
|
|
|
|
}
|
|
|
|
|
const hydratedProject = workspace ? await svc.getById(project.id) : project;
|
|
|
|
|
|
Add server routes for companies, approvals, costs, and dashboard
New routes: companies, approvals, costs, dashboard, authz. New
services: companies, approvals, costs, dashboard, heartbeat,
activity-log. Add auth middleware and structured error handling.
Expand existing agent and issue routes with richer CRUD operations.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 09:07:27 -06:00
|
|
|
const actor = getActorInfo(req);
|
|
|
|
|
await logActivity(db, {
|
|
|
|
|
companyId,
|
|
|
|
|
actorType: actor.actorType,
|
|
|
|
|
actorId: actor.actorId,
|
|
|
|
|
agentId: actor.agentId,
|
|
|
|
|
action: "project.created",
|
|
|
|
|
entityType: "project",
|
|
|
|
|
entityId: project.id,
|
2026-03-02 13:32:31 -06:00
|
|
|
details: {
|
|
|
|
|
name: project.name,
|
|
|
|
|
workspaceId: createdWorkspaceId,
|
2026-04-06 09:34:15 -05:00
|
|
|
envKeys: project.env ? Object.keys(project.env).sort() : [],
|
2026-03-02 13:32:31 -06:00
|
|
|
},
|
Add server routes for companies, approvals, costs, and dashboard
New routes: companies, approvals, costs, dashboard, authz. New
services: companies, approvals, costs, dashboard, heartbeat,
activity-log. Add auth middleware and structured error handling.
Expand existing agent and issue routes with richer CRUD operations.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 09:07:27 -06:00
|
|
|
});
|
2026-04-03 07:32:54 -05:00
|
|
|
const telemetryClient = getTelemetryClient();
|
|
|
|
|
if (telemetryClient) {
|
|
|
|
|
trackProjectCreated(telemetryClient);
|
|
|
|
|
}
|
2026-03-02 13:32:31 -06:00
|
|
|
res.status(201).json(hydratedProject ?? project);
|
2026-02-16 13:31:58 -06:00
|
|
|
});
|
|
|
|
|
|
Add server routes for companies, approvals, costs, and dashboard
New routes: companies, approvals, costs, dashboard, authz. New
services: companies, approvals, costs, dashboard, heartbeat,
activity-log. Add auth middleware and structured error handling.
Expand existing agent and issue routes with richer CRUD operations.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 09:07:27 -06:00
|
|
|
router.patch("/projects/:id", validate(updateProjectSchema), async (req, res) => {
|
2026-02-16 13:31:58 -06:00
|
|
|
const id = req.params.id as string;
|
Add server routes for companies, approvals, costs, and dashboard
New routes: companies, approvals, costs, dashboard, authz. New
services: companies, approvals, costs, dashboard, heartbeat,
activity-log. Add auth middleware and structured error handling.
Expand existing agent and issue routes with richer CRUD operations.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 09:07:27 -06:00
|
|
|
const existing = await svc.getById(id);
|
|
|
|
|
if (!existing) {
|
|
|
|
|
res.status(404).json({ error: "Project not found" });
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
assertCompanyAccess(req, existing.companyId);
|
2026-03-16 19:48:04 -05:00
|
|
|
const body = { ...req.body };
|
|
|
|
|
if (typeof body.archivedAt === "string") {
|
|
|
|
|
body.archivedAt = new Date(body.archivedAt);
|
|
|
|
|
}
|
2026-04-06 09:34:15 -05:00
|
|
|
if (body.env !== undefined) {
|
|
|
|
|
body.env = await secretsSvc.normalizeEnvBindingsForPersistence(existing.companyId, body.env, {
|
|
|
|
|
strictMode: strictSecretsMode,
|
|
|
|
|
fieldPath: "env",
|
|
|
|
|
});
|
|
|
|
|
}
|
2026-03-16 19:48:04 -05:00
|
|
|
const project = await svc.update(id, body);
|
2026-02-16 13:31:58 -06:00
|
|
|
if (!project) {
|
|
|
|
|
res.status(404).json({ error: "Project not found" });
|
|
|
|
|
return;
|
|
|
|
|
}
|
Add server routes for companies, approvals, costs, and dashboard
New routes: companies, approvals, costs, dashboard, authz. New
services: companies, approvals, costs, dashboard, heartbeat,
activity-log. Add auth middleware and structured error handling.
Expand existing agent and issue routes with richer CRUD operations.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 09:07:27 -06:00
|
|
|
|
|
|
|
|
const actor = getActorInfo(req);
|
|
|
|
|
await logActivity(db, {
|
|
|
|
|
companyId: project.companyId,
|
|
|
|
|
actorType: actor.actorType,
|
|
|
|
|
actorId: actor.actorId,
|
|
|
|
|
agentId: actor.agentId,
|
|
|
|
|
action: "project.updated",
|
|
|
|
|
entityType: "project",
|
|
|
|
|
entityId: project.id,
|
2026-04-06 09:34:15 -05:00
|
|
|
details: {
|
|
|
|
|
changedKeys: Object.keys(req.body).sort(),
|
|
|
|
|
envKeys:
|
|
|
|
|
body.env && typeof body.env === "object" && !Array.isArray(body.env)
|
|
|
|
|
? Object.keys(body.env as Record<string, unknown>).sort()
|
|
|
|
|
: undefined,
|
|
|
|
|
},
|
Add server routes for companies, approvals, costs, and dashboard
New routes: companies, approvals, costs, dashboard, authz. New
services: companies, approvals, costs, dashboard, heartbeat,
activity-log. Add auth middleware and structured error handling.
Expand existing agent and issue routes with richer CRUD operations.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 09:07:27 -06:00
|
|
|
});
|
|
|
|
|
|
2026-02-16 13:31:58 -06:00
|
|
|
res.json(project);
|
|
|
|
|
});
|
|
|
|
|
|
2026-02-25 08:38:46 -06:00
|
|
|
router.get("/projects/:id/workspaces", async (req, res) => {
|
|
|
|
|
const id = req.params.id as string;
|
|
|
|
|
const existing = await svc.getById(id);
|
|
|
|
|
if (!existing) {
|
|
|
|
|
res.status(404).json({ error: "Project not found" });
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
assertCompanyAccess(req, existing.companyId);
|
|
|
|
|
const workspaces = await svc.listWorkspaces(id);
|
|
|
|
|
res.json(workspaces);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
router.post("/projects/:id/workspaces", validate(createProjectWorkspaceSchema), async (req, res) => {
|
|
|
|
|
const id = req.params.id as string;
|
|
|
|
|
const existing = await svc.getById(id);
|
|
|
|
|
if (!existing) {
|
|
|
|
|
res.status(404).json({ error: "Project not found" });
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
assertCompanyAccess(req, existing.companyId);
|
|
|
|
|
const workspace = await svc.createWorkspace(id, req.body);
|
|
|
|
|
if (!workspace) {
|
2026-02-25 21:35:33 -06:00
|
|
|
res.status(422).json({ error: "Invalid project workspace payload" });
|
2026-02-25 08:38:46 -06:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const actor = getActorInfo(req);
|
|
|
|
|
await logActivity(db, {
|
|
|
|
|
companyId: existing.companyId,
|
|
|
|
|
actorType: actor.actorType,
|
|
|
|
|
actorId: actor.actorId,
|
|
|
|
|
agentId: actor.agentId,
|
|
|
|
|
action: "project.workspace_created",
|
|
|
|
|
entityType: "project",
|
|
|
|
|
entityId: id,
|
|
|
|
|
details: {
|
|
|
|
|
workspaceId: workspace.id,
|
|
|
|
|
name: workspace.name,
|
|
|
|
|
cwd: workspace.cwd,
|
|
|
|
|
isPrimary: workspace.isPrimary,
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
res.status(201).json(workspace);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
router.patch(
|
|
|
|
|
"/projects/:id/workspaces/:workspaceId",
|
|
|
|
|
validate(updateProjectWorkspaceSchema),
|
|
|
|
|
async (req, res) => {
|
|
|
|
|
const id = req.params.id as string;
|
|
|
|
|
const workspaceId = req.params.workspaceId as string;
|
|
|
|
|
const existing = await svc.getById(id);
|
|
|
|
|
if (!existing) {
|
|
|
|
|
res.status(404).json({ error: "Project not found" });
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
assertCompanyAccess(req, existing.companyId);
|
2026-02-25 21:35:33 -06:00
|
|
|
const workspaceExists = (await svc.listWorkspaces(id)).some((workspace) => workspace.id === workspaceId);
|
|
|
|
|
if (!workspaceExists) {
|
|
|
|
|
res.status(404).json({ error: "Project workspace not found" });
|
|
|
|
|
return;
|
|
|
|
|
}
|
2026-02-25 08:38:46 -06:00
|
|
|
const workspace = await svc.updateWorkspace(id, workspaceId, req.body);
|
|
|
|
|
if (!workspace) {
|
2026-02-25 21:35:33 -06:00
|
|
|
res.status(422).json({ error: "Invalid project workspace payload" });
|
2026-02-25 08:38:46 -06:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const actor = getActorInfo(req);
|
|
|
|
|
await logActivity(db, {
|
|
|
|
|
companyId: existing.companyId,
|
|
|
|
|
actorType: actor.actorType,
|
|
|
|
|
actorId: actor.actorId,
|
|
|
|
|
agentId: actor.agentId,
|
|
|
|
|
action: "project.workspace_updated",
|
|
|
|
|
entityType: "project",
|
|
|
|
|
entityId: id,
|
|
|
|
|
details: {
|
|
|
|
|
workspaceId: workspace.id,
|
|
|
|
|
changedKeys: Object.keys(req.body).sort(),
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
res.json(workspace);
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
|
[codex] Improve workspace runtime and navigation ergonomics (#3680)
## Thinking Path
> - Paperclip orchestrates AI agents for zero-human companies
> - That operator experience depends not just on issue chat, but also on
how workspaces, inbox groups, and navigation state behave over
long-running sessions
> - The current branch included a separate cluster of workspace-runtime
controls, inbox grouping, sidebar ordering, and worktree lifecycle fixes
> - Those changes cross server, shared contracts, database state, and UI
navigation, but they still form one coherent operator workflow area
> - This pull request isolates the workspace/runtime and navigation
ergonomics work into one standalone branch
> - The benefit is better workspace recovery and navigation persistence
without forcing reviewers through the unrelated issue-detail/chat work
## What Changed
- Improved execution workspace and project workspace controls, request
wiring, layout, and JSON editor ergonomics
- Hardened linked worktree reuse/startup behavior and documented the
`worktree repair` flow for recovering linked worktrees safely
- Added inbox workspace grouping, mobile collapse, archive undo,
keyboard navigation, shared group-header styling, and persisted
collapsed-group behavior
- Added persistent sidebar order preferences with the supporting DB
migration, shared/server contracts, routes, services, hooks, and UI
integration
- Scoped issue-list preferences by context and added targeted UI/server
tests for workspace controls, inbox behavior, sidebar preferences, and
worktree validation
## Verification
- `pnpm vitest run
server/src/__tests__/sidebar-preferences-routes.test.ts
ui/src/pages/Inbox.test.tsx
ui/src/components/ProjectWorkspaceSummaryCard.test.tsx
ui/src/components/WorkspaceRuntimeControls.test.tsx
ui/src/api/workspace-runtime-control.test.ts`
- `server/src/__tests__/workspace-runtime.test.ts` was attempted, but
the embedded Postgres suite self-skipped/hung on this host after
reporting an init-script issue, so it is not counted as a local pass
here
## Risks
- Medium: this branch includes migration-backed preference storage plus
worktree/runtime behavior, so merge review should pay attention to state
persistence and worktree recovery semantics
- The sidebar preference migration is standalone, but it should still be
watched for conflicts if another migration lands first
## Model Used
- OpenAI Codex coding agent (GPT-5-class runtime in Codex CLI; exact
deployed model ID is not exposed in this environment), reasoning
enabled, tool use and local code execution enabled
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [ ] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [ ] If this change affects the UI, I have included before/after
screenshots
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge
---------
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-14 12:57:11 -05:00
|
|
|
async function handleProjectWorkspaceRuntimeCommand(req: Request, res: Response) {
|
2026-03-28 16:46:43 -05:00
|
|
|
const id = req.params.id as string;
|
|
|
|
|
const workspaceId = req.params.workspaceId as string;
|
|
|
|
|
const action = String(req.params.action ?? "").trim().toLowerCase();
|
[codex] Improve workspace runtime and navigation ergonomics (#3680)
## Thinking Path
> - Paperclip orchestrates AI agents for zero-human companies
> - That operator experience depends not just on issue chat, but also on
how workspaces, inbox groups, and navigation state behave over
long-running sessions
> - The current branch included a separate cluster of workspace-runtime
controls, inbox grouping, sidebar ordering, and worktree lifecycle fixes
> - Those changes cross server, shared contracts, database state, and UI
navigation, but they still form one coherent operator workflow area
> - This pull request isolates the workspace/runtime and navigation
ergonomics work into one standalone branch
> - The benefit is better workspace recovery and navigation persistence
without forcing reviewers through the unrelated issue-detail/chat work
## What Changed
- Improved execution workspace and project workspace controls, request
wiring, layout, and JSON editor ergonomics
- Hardened linked worktree reuse/startup behavior and documented the
`worktree repair` flow for recovering linked worktrees safely
- Added inbox workspace grouping, mobile collapse, archive undo,
keyboard navigation, shared group-header styling, and persisted
collapsed-group behavior
- Added persistent sidebar order preferences with the supporting DB
migration, shared/server contracts, routes, services, hooks, and UI
integration
- Scoped issue-list preferences by context and added targeted UI/server
tests for workspace controls, inbox behavior, sidebar preferences, and
worktree validation
## Verification
- `pnpm vitest run
server/src/__tests__/sidebar-preferences-routes.test.ts
ui/src/pages/Inbox.test.tsx
ui/src/components/ProjectWorkspaceSummaryCard.test.tsx
ui/src/components/WorkspaceRuntimeControls.test.tsx
ui/src/api/workspace-runtime-control.test.ts`
- `server/src/__tests__/workspace-runtime.test.ts` was attempted, but
the embedded Postgres suite self-skipped/hung on this host after
reporting an init-script issue, so it is not counted as a local pass
here
## Risks
- Medium: this branch includes migration-backed preference storage plus
worktree/runtime behavior, so merge review should pay attention to state
persistence and worktree recovery semantics
- The sidebar preference migration is standalone, but it should still be
watched for conflicts if another migration lands first
## Model Used
- OpenAI Codex coding agent (GPT-5-class runtime in Codex CLI; exact
deployed model ID is not exposed in this environment), reasoning
enabled, tool use and local code execution enabled
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [ ] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [ ] If this change affects the UI, I have included before/after
screenshots
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge
---------
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-14 12:57:11 -05:00
|
|
|
if (action !== "start" && action !== "stop" && action !== "restart" && action !== "run") {
|
|
|
|
|
res.status(404).json({ error: "Workspace command action not found" });
|
2026-03-28 16:46:43 -05:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const project = await svc.getById(id);
|
|
|
|
|
if (!project) {
|
|
|
|
|
res.status(404).json({ error: "Project not found" });
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
assertCompanyAccess(req, project.companyId);
|
|
|
|
|
|
|
|
|
|
const workspace = project.workspaces.find((entry) => entry.id === workspaceId) ?? null;
|
|
|
|
|
if (!workspace) {
|
|
|
|
|
res.status(404).json({ error: "Project workspace not found" });
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const workspaceCwd = workspace.cwd;
|
|
|
|
|
if (!workspaceCwd) {
|
[codex] Improve workspace runtime and navigation ergonomics (#3680)
## Thinking Path
> - Paperclip orchestrates AI agents for zero-human companies
> - That operator experience depends not just on issue chat, but also on
how workspaces, inbox groups, and navigation state behave over
long-running sessions
> - The current branch included a separate cluster of workspace-runtime
controls, inbox grouping, sidebar ordering, and worktree lifecycle fixes
> - Those changes cross server, shared contracts, database state, and UI
navigation, but they still form one coherent operator workflow area
> - This pull request isolates the workspace/runtime and navigation
ergonomics work into one standalone branch
> - The benefit is better workspace recovery and navigation persistence
without forcing reviewers through the unrelated issue-detail/chat work
## What Changed
- Improved execution workspace and project workspace controls, request
wiring, layout, and JSON editor ergonomics
- Hardened linked worktree reuse/startup behavior and documented the
`worktree repair` flow for recovering linked worktrees safely
- Added inbox workspace grouping, mobile collapse, archive undo,
keyboard navigation, shared group-header styling, and persisted
collapsed-group behavior
- Added persistent sidebar order preferences with the supporting DB
migration, shared/server contracts, routes, services, hooks, and UI
integration
- Scoped issue-list preferences by context and added targeted UI/server
tests for workspace controls, inbox behavior, sidebar preferences, and
worktree validation
## Verification
- `pnpm vitest run
server/src/__tests__/sidebar-preferences-routes.test.ts
ui/src/pages/Inbox.test.tsx
ui/src/components/ProjectWorkspaceSummaryCard.test.tsx
ui/src/components/WorkspaceRuntimeControls.test.tsx
ui/src/api/workspace-runtime-control.test.ts`
- `server/src/__tests__/workspace-runtime.test.ts` was attempted, but
the embedded Postgres suite self-skipped/hung on this host after
reporting an init-script issue, so it is not counted as a local pass
here
## Risks
- Medium: this branch includes migration-backed preference storage plus
worktree/runtime behavior, so merge review should pay attention to state
persistence and worktree recovery semantics
- The sidebar preference migration is standalone, but it should still be
watched for conflicts if another migration lands first
## Model Used
- OpenAI Codex coding agent (GPT-5-class runtime in Codex CLI; exact
deployed model ID is not exposed in this environment), reasoning
enabled, tool use and local code execution enabled
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [ ] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [ ] If this change affects the UI, I have included before/after
screenshots
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge
---------
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-14 12:57:11 -05:00
|
|
|
res.status(422).json({ error: "Project workspace needs a local path before Paperclip can run workspace commands" });
|
2026-03-28 16:46:43 -05:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const runtimeConfig = workspace.runtimeConfig?.workspaceRuntime ?? null;
|
[codex] Improve workspace runtime and navigation ergonomics (#3680)
## Thinking Path
> - Paperclip orchestrates AI agents for zero-human companies
> - That operator experience depends not just on issue chat, but also on
how workspaces, inbox groups, and navigation state behave over
long-running sessions
> - The current branch included a separate cluster of workspace-runtime
controls, inbox grouping, sidebar ordering, and worktree lifecycle fixes
> - Those changes cross server, shared contracts, database state, and UI
navigation, but they still form one coherent operator workflow area
> - This pull request isolates the workspace/runtime and navigation
ergonomics work into one standalone branch
> - The benefit is better workspace recovery and navigation persistence
without forcing reviewers through the unrelated issue-detail/chat work
## What Changed
- Improved execution workspace and project workspace controls, request
wiring, layout, and JSON editor ergonomics
- Hardened linked worktree reuse/startup behavior and documented the
`worktree repair` flow for recovering linked worktrees safely
- Added inbox workspace grouping, mobile collapse, archive undo,
keyboard navigation, shared group-header styling, and persisted
collapsed-group behavior
- Added persistent sidebar order preferences with the supporting DB
migration, shared/server contracts, routes, services, hooks, and UI
integration
- Scoped issue-list preferences by context and added targeted UI/server
tests for workspace controls, inbox behavior, sidebar preferences, and
worktree validation
## Verification
- `pnpm vitest run
server/src/__tests__/sidebar-preferences-routes.test.ts
ui/src/pages/Inbox.test.tsx
ui/src/components/ProjectWorkspaceSummaryCard.test.tsx
ui/src/components/WorkspaceRuntimeControls.test.tsx
ui/src/api/workspace-runtime-control.test.ts`
- `server/src/__tests__/workspace-runtime.test.ts` was attempted, but
the embedded Postgres suite self-skipped/hung on this host after
reporting an init-script issue, so it is not counted as a local pass
here
## Risks
- Medium: this branch includes migration-backed preference storage plus
worktree/runtime behavior, so merge review should pay attention to state
persistence and worktree recovery semantics
- The sidebar preference migration is standalone, but it should still be
watched for conflicts if another migration lands first
## Model Used
- OpenAI Codex coding agent (GPT-5-class runtime in Codex CLI; exact
deployed model ID is not exposed in this environment), reasoning
enabled, tool use and local code execution enabled
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [ ] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [ ] If this change affects the UI, I have included before/after
screenshots
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge
---------
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-14 12:57:11 -05:00
|
|
|
const target = req.body as { workspaceCommandId?: string | null; runtimeServiceId?: string | null; serviceIndex?: number | null };
|
|
|
|
|
const configuredServices = runtimeConfig ? listConfiguredRuntimeServiceEntries({ workspaceRuntime: runtimeConfig }) : [];
|
|
|
|
|
const workspaceCommand = runtimeConfig
|
|
|
|
|
? findWorkspaceCommandDefinition(runtimeConfig, target.workspaceCommandId ?? null)
|
|
|
|
|
: null;
|
|
|
|
|
if (target.workspaceCommandId && !workspaceCommand) {
|
|
|
|
|
res.status(404).json({ error: "Workspace command not found for this project workspace" });
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (target.runtimeServiceId && !(workspace.runtimeServices ?? []).some((service) => service.id === target.runtimeServiceId)) {
|
|
|
|
|
res.status(404).json({ error: "Runtime service not found for this project workspace" });
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const matchedRuntimeService =
|
|
|
|
|
workspaceCommand?.kind === "service" && !target.runtimeServiceId
|
|
|
|
|
? matchWorkspaceRuntimeServiceToCommand(workspaceCommand, workspace.runtimeServices ?? [])
|
|
|
|
|
: null;
|
|
|
|
|
const selectedRuntimeServiceId = target.runtimeServiceId ?? matchedRuntimeService?.id ?? null;
|
|
|
|
|
const selectedServiceIndex =
|
|
|
|
|
workspaceCommand?.kind === "service"
|
|
|
|
|
? workspaceCommand.serviceIndex
|
|
|
|
|
: target.serviceIndex ?? null;
|
|
|
|
|
if (
|
|
|
|
|
selectedServiceIndex !== undefined
|
|
|
|
|
&& selectedServiceIndex !== null
|
|
|
|
|
&& (selectedServiceIndex < 0 || selectedServiceIndex >= configuredServices.length)
|
|
|
|
|
) {
|
|
|
|
|
res.status(422).json({ error: "Selected runtime service is not defined in this project workspace runtime config" });
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (workspaceCommand?.kind === "job" && action !== "run") {
|
|
|
|
|
res.status(422).json({ error: `Workspace job "${workspaceCommand.name}" can only be run` });
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (workspaceCommand?.kind === "service" && action === "run") {
|
|
|
|
|
res.status(422).json({ error: `Workspace service "${workspaceCommand.name}" should be started or restarted, not run` });
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (action === "run" && !workspaceCommand) {
|
|
|
|
|
res.status(422).json({ error: "Select a workspace job to run" });
|
|
|
|
|
return;
|
|
|
|
|
}
|
2026-03-28 16:46:43 -05:00
|
|
|
if ((action === "start" || action === "restart") && !runtimeConfig) {
|
[codex] Improve workspace runtime and navigation ergonomics (#3680)
## Thinking Path
> - Paperclip orchestrates AI agents for zero-human companies
> - That operator experience depends not just on issue chat, but also on
how workspaces, inbox groups, and navigation state behave over
long-running sessions
> - The current branch included a separate cluster of workspace-runtime
controls, inbox grouping, sidebar ordering, and worktree lifecycle fixes
> - Those changes cross server, shared contracts, database state, and UI
navigation, but they still form one coherent operator workflow area
> - This pull request isolates the workspace/runtime and navigation
ergonomics work into one standalone branch
> - The benefit is better workspace recovery and navigation persistence
without forcing reviewers through the unrelated issue-detail/chat work
## What Changed
- Improved execution workspace and project workspace controls, request
wiring, layout, and JSON editor ergonomics
- Hardened linked worktree reuse/startup behavior and documented the
`worktree repair` flow for recovering linked worktrees safely
- Added inbox workspace grouping, mobile collapse, archive undo,
keyboard navigation, shared group-header styling, and persisted
collapsed-group behavior
- Added persistent sidebar order preferences with the supporting DB
migration, shared/server contracts, routes, services, hooks, and UI
integration
- Scoped issue-list preferences by context and added targeted UI/server
tests for workspace controls, inbox behavior, sidebar preferences, and
worktree validation
## Verification
- `pnpm vitest run
server/src/__tests__/sidebar-preferences-routes.test.ts
ui/src/pages/Inbox.test.tsx
ui/src/components/ProjectWorkspaceSummaryCard.test.tsx
ui/src/components/WorkspaceRuntimeControls.test.tsx
ui/src/api/workspace-runtime-control.test.ts`
- `server/src/__tests__/workspace-runtime.test.ts` was attempted, but
the embedded Postgres suite self-skipped/hung on this host after
reporting an init-script issue, so it is not counted as a local pass
here
## Risks
- Medium: this branch includes migration-backed preference storage plus
worktree/runtime behavior, so merge review should pay attention to state
persistence and worktree recovery semantics
- The sidebar preference migration is standalone, but it should still be
watched for conflicts if another migration lands first
## Model Used
- OpenAI Codex coding agent (GPT-5-class runtime in Codex CLI; exact
deployed model ID is not exposed in this environment), reasoning
enabled, tool use and local code execution enabled
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [ ] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [ ] If this change affects the UI, I have included before/after
screenshots
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge
---------
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-14 12:57:11 -05:00
|
|
|
res.status(422).json({ error: "Project workspace has no workspace command configuration" });
|
2026-03-28 16:46:43 -05:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const actor = getActorInfo(req);
|
|
|
|
|
const recorder = workspaceOperations.createRecorder({ companyId: project.companyId });
|
|
|
|
|
let runtimeServiceCount = workspace.runtimeServices?.length ?? 0;
|
|
|
|
|
const stdout: string[] = [];
|
|
|
|
|
const stderr: string[] = [];
|
|
|
|
|
|
|
|
|
|
const operation = await recorder.recordOperation({
|
|
|
|
|
phase: action === "stop" ? "workspace_teardown" : "workspace_provision",
|
[codex] Improve workspace runtime and navigation ergonomics (#3680)
## Thinking Path
> - Paperclip orchestrates AI agents for zero-human companies
> - That operator experience depends not just on issue chat, but also on
how workspaces, inbox groups, and navigation state behave over
long-running sessions
> - The current branch included a separate cluster of workspace-runtime
controls, inbox grouping, sidebar ordering, and worktree lifecycle fixes
> - Those changes cross server, shared contracts, database state, and UI
navigation, but they still form one coherent operator workflow area
> - This pull request isolates the workspace/runtime and navigation
ergonomics work into one standalone branch
> - The benefit is better workspace recovery and navigation persistence
without forcing reviewers through the unrelated issue-detail/chat work
## What Changed
- Improved execution workspace and project workspace controls, request
wiring, layout, and JSON editor ergonomics
- Hardened linked worktree reuse/startup behavior and documented the
`worktree repair` flow for recovering linked worktrees safely
- Added inbox workspace grouping, mobile collapse, archive undo,
keyboard navigation, shared group-header styling, and persisted
collapsed-group behavior
- Added persistent sidebar order preferences with the supporting DB
migration, shared/server contracts, routes, services, hooks, and UI
integration
- Scoped issue-list preferences by context and added targeted UI/server
tests for workspace controls, inbox behavior, sidebar preferences, and
worktree validation
## Verification
- `pnpm vitest run
server/src/__tests__/sidebar-preferences-routes.test.ts
ui/src/pages/Inbox.test.tsx
ui/src/components/ProjectWorkspaceSummaryCard.test.tsx
ui/src/components/WorkspaceRuntimeControls.test.tsx
ui/src/api/workspace-runtime-control.test.ts`
- `server/src/__tests__/workspace-runtime.test.ts` was attempted, but
the embedded Postgres suite self-skipped/hung on this host after
reporting an init-script issue, so it is not counted as a local pass
here
## Risks
- Medium: this branch includes migration-backed preference storage plus
worktree/runtime behavior, so merge review should pay attention to state
persistence and worktree recovery semantics
- The sidebar preference migration is standalone, but it should still be
watched for conflicts if another migration lands first
## Model Used
- OpenAI Codex coding agent (GPT-5-class runtime in Codex CLI; exact
deployed model ID is not exposed in this environment), reasoning
enabled, tool use and local code execution enabled
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [ ] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [ ] If this change affects the UI, I have included before/after
screenshots
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge
---------
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-14 12:57:11 -05:00
|
|
|
command: workspaceCommand?.command ?? `workspace command ${action}`,
|
2026-03-28 16:46:43 -05:00
|
|
|
cwd: workspace.cwd,
|
|
|
|
|
metadata: {
|
|
|
|
|
action,
|
|
|
|
|
projectId: project.id,
|
|
|
|
|
projectWorkspaceId: workspace.id,
|
[codex] Improve workspace runtime and navigation ergonomics (#3680)
## Thinking Path
> - Paperclip orchestrates AI agents for zero-human companies
> - That operator experience depends not just on issue chat, but also on
how workspaces, inbox groups, and navigation state behave over
long-running sessions
> - The current branch included a separate cluster of workspace-runtime
controls, inbox grouping, sidebar ordering, and worktree lifecycle fixes
> - Those changes cross server, shared contracts, database state, and UI
navigation, but they still form one coherent operator workflow area
> - This pull request isolates the workspace/runtime and navigation
ergonomics work into one standalone branch
> - The benefit is better workspace recovery and navigation persistence
without forcing reviewers through the unrelated issue-detail/chat work
## What Changed
- Improved execution workspace and project workspace controls, request
wiring, layout, and JSON editor ergonomics
- Hardened linked worktree reuse/startup behavior and documented the
`worktree repair` flow for recovering linked worktrees safely
- Added inbox workspace grouping, mobile collapse, archive undo,
keyboard navigation, shared group-header styling, and persisted
collapsed-group behavior
- Added persistent sidebar order preferences with the supporting DB
migration, shared/server contracts, routes, services, hooks, and UI
integration
- Scoped issue-list preferences by context and added targeted UI/server
tests for workspace controls, inbox behavior, sidebar preferences, and
worktree validation
## Verification
- `pnpm vitest run
server/src/__tests__/sidebar-preferences-routes.test.ts
ui/src/pages/Inbox.test.tsx
ui/src/components/ProjectWorkspaceSummaryCard.test.tsx
ui/src/components/WorkspaceRuntimeControls.test.tsx
ui/src/api/workspace-runtime-control.test.ts`
- `server/src/__tests__/workspace-runtime.test.ts` was attempted, but
the embedded Postgres suite self-skipped/hung on this host after
reporting an init-script issue, so it is not counted as a local pass
here
## Risks
- Medium: this branch includes migration-backed preference storage plus
worktree/runtime behavior, so merge review should pay attention to state
persistence and worktree recovery semantics
- The sidebar preference migration is standalone, but it should still be
watched for conflicts if another migration lands first
## Model Used
- OpenAI Codex coding agent (GPT-5-class runtime in Codex CLI; exact
deployed model ID is not exposed in this environment), reasoning
enabled, tool use and local code execution enabled
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [ ] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [ ] If this change affects the UI, I have included before/after
screenshots
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge
---------
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-14 12:57:11 -05:00
|
|
|
workspaceCommandId: workspaceCommand?.id ?? target.workspaceCommandId ?? null,
|
|
|
|
|
workspaceCommandKind: workspaceCommand?.kind ?? null,
|
|
|
|
|
workspaceCommandName: workspaceCommand?.name ?? null,
|
|
|
|
|
runtimeServiceId: selectedRuntimeServiceId,
|
|
|
|
|
serviceIndex: selectedServiceIndex,
|
2026-03-28 16:46:43 -05:00
|
|
|
},
|
|
|
|
|
run: async () => {
|
[codex] Improve workspace runtime and navigation ergonomics (#3680)
## Thinking Path
> - Paperclip orchestrates AI agents for zero-human companies
> - That operator experience depends not just on issue chat, but also on
how workspaces, inbox groups, and navigation state behave over
long-running sessions
> - The current branch included a separate cluster of workspace-runtime
controls, inbox grouping, sidebar ordering, and worktree lifecycle fixes
> - Those changes cross server, shared contracts, database state, and UI
navigation, but they still form one coherent operator workflow area
> - This pull request isolates the workspace/runtime and navigation
ergonomics work into one standalone branch
> - The benefit is better workspace recovery and navigation persistence
without forcing reviewers through the unrelated issue-detail/chat work
## What Changed
- Improved execution workspace and project workspace controls, request
wiring, layout, and JSON editor ergonomics
- Hardened linked worktree reuse/startup behavior and documented the
`worktree repair` flow for recovering linked worktrees safely
- Added inbox workspace grouping, mobile collapse, archive undo,
keyboard navigation, shared group-header styling, and persisted
collapsed-group behavior
- Added persistent sidebar order preferences with the supporting DB
migration, shared/server contracts, routes, services, hooks, and UI
integration
- Scoped issue-list preferences by context and added targeted UI/server
tests for workspace controls, inbox behavior, sidebar preferences, and
worktree validation
## Verification
- `pnpm vitest run
server/src/__tests__/sidebar-preferences-routes.test.ts
ui/src/pages/Inbox.test.tsx
ui/src/components/ProjectWorkspaceSummaryCard.test.tsx
ui/src/components/WorkspaceRuntimeControls.test.tsx
ui/src/api/workspace-runtime-control.test.ts`
- `server/src/__tests__/workspace-runtime.test.ts` was attempted, but
the embedded Postgres suite self-skipped/hung on this host after
reporting an init-script issue, so it is not counted as a local pass
here
## Risks
- Medium: this branch includes migration-backed preference storage plus
worktree/runtime behavior, so merge review should pay attention to state
persistence and worktree recovery semantics
- The sidebar preference migration is standalone, but it should still be
watched for conflicts if another migration lands first
## Model Used
- OpenAI Codex coding agent (GPT-5-class runtime in Codex CLI; exact
deployed model ID is not exposed in this environment), reasoning
enabled, tool use and local code execution enabled
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [ ] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [ ] If this change affects the UI, I have included before/after
screenshots
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge
---------
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-14 12:57:11 -05:00
|
|
|
if (action === "run") {
|
|
|
|
|
if (!workspaceCommand || workspaceCommand.kind !== "job") {
|
|
|
|
|
throw new Error("Workspace job selection is required");
|
|
|
|
|
}
|
|
|
|
|
return await runWorkspaceJobForControl({
|
|
|
|
|
actor: {
|
|
|
|
|
id: actor.agentId ?? null,
|
|
|
|
|
name: actor.actorType === "user" ? "Board" : "Agent",
|
|
|
|
|
companyId: project.companyId,
|
|
|
|
|
},
|
|
|
|
|
issue: null,
|
|
|
|
|
workspace: {
|
|
|
|
|
baseCwd: workspaceCwd,
|
|
|
|
|
source: "project_primary",
|
|
|
|
|
projectId: project.id,
|
|
|
|
|
workspaceId: workspace.id,
|
|
|
|
|
repoUrl: workspace.repoUrl,
|
|
|
|
|
repoRef: workspace.repoRef,
|
|
|
|
|
strategy: "project_primary",
|
|
|
|
|
cwd: workspaceCwd,
|
|
|
|
|
branchName: workspace.defaultRef ?? workspace.repoRef ?? null,
|
|
|
|
|
worktreePath: null,
|
|
|
|
|
warnings: [],
|
|
|
|
|
created: false,
|
|
|
|
|
},
|
|
|
|
|
command: workspaceCommand.rawConfig,
|
|
|
|
|
adapterEnv: {},
|
|
|
|
|
recorder,
|
|
|
|
|
metadata: {
|
|
|
|
|
action,
|
|
|
|
|
projectId: project.id,
|
|
|
|
|
projectWorkspaceId: workspace.id,
|
|
|
|
|
workspaceCommandId: workspaceCommand.id,
|
|
|
|
|
},
|
|
|
|
|
}).then((nestedOperation) => ({
|
|
|
|
|
status: "succeeded" as const,
|
|
|
|
|
exitCode: 0,
|
|
|
|
|
metadata: {
|
|
|
|
|
nestedOperationId: nestedOperation?.id ?? null,
|
|
|
|
|
runtimeServiceCount,
|
|
|
|
|
},
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-28 16:46:43 -05:00
|
|
|
const onLog = async (stream: "stdout" | "stderr", chunk: string) => {
|
|
|
|
|
if (stream === "stdout") stdout.push(chunk);
|
|
|
|
|
else stderr.push(chunk);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (action === "stop" || action === "restart") {
|
|
|
|
|
await stopRuntimeServicesForProjectWorkspace({
|
|
|
|
|
db,
|
|
|
|
|
projectWorkspaceId: workspace.id,
|
[codex] Improve workspace runtime and navigation ergonomics (#3680)
## Thinking Path
> - Paperclip orchestrates AI agents for zero-human companies
> - That operator experience depends not just on issue chat, but also on
how workspaces, inbox groups, and navigation state behave over
long-running sessions
> - The current branch included a separate cluster of workspace-runtime
controls, inbox grouping, sidebar ordering, and worktree lifecycle fixes
> - Those changes cross server, shared contracts, database state, and UI
navigation, but they still form one coherent operator workflow area
> - This pull request isolates the workspace/runtime and navigation
ergonomics work into one standalone branch
> - The benefit is better workspace recovery and navigation persistence
without forcing reviewers through the unrelated issue-detail/chat work
## What Changed
- Improved execution workspace and project workspace controls, request
wiring, layout, and JSON editor ergonomics
- Hardened linked worktree reuse/startup behavior and documented the
`worktree repair` flow for recovering linked worktrees safely
- Added inbox workspace grouping, mobile collapse, archive undo,
keyboard navigation, shared group-header styling, and persisted
collapsed-group behavior
- Added persistent sidebar order preferences with the supporting DB
migration, shared/server contracts, routes, services, hooks, and UI
integration
- Scoped issue-list preferences by context and added targeted UI/server
tests for workspace controls, inbox behavior, sidebar preferences, and
worktree validation
## Verification
- `pnpm vitest run
server/src/__tests__/sidebar-preferences-routes.test.ts
ui/src/pages/Inbox.test.tsx
ui/src/components/ProjectWorkspaceSummaryCard.test.tsx
ui/src/components/WorkspaceRuntimeControls.test.tsx
ui/src/api/workspace-runtime-control.test.ts`
- `server/src/__tests__/workspace-runtime.test.ts` was attempted, but
the embedded Postgres suite self-skipped/hung on this host after
reporting an init-script issue, so it is not counted as a local pass
here
## Risks
- Medium: this branch includes migration-backed preference storage plus
worktree/runtime behavior, so merge review should pay attention to state
persistence and worktree recovery semantics
- The sidebar preference migration is standalone, but it should still be
watched for conflicts if another migration lands first
## Model Used
- OpenAI Codex coding agent (GPT-5-class runtime in Codex CLI; exact
deployed model ID is not exposed in this environment), reasoning
enabled, tool use and local code execution enabled
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [ ] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [ ] If this change affects the UI, I have included before/after
screenshots
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge
---------
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-14 12:57:11 -05:00
|
|
|
runtimeServiceId: selectedRuntimeServiceId,
|
2026-03-28 16:46:43 -05:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (action === "start" || action === "restart") {
|
|
|
|
|
const startedServices = await startRuntimeServicesForWorkspaceControl({
|
|
|
|
|
db,
|
|
|
|
|
actor: {
|
|
|
|
|
id: actor.agentId ?? null,
|
|
|
|
|
name: actor.actorType === "user" ? "Board" : "Agent",
|
|
|
|
|
companyId: project.companyId,
|
|
|
|
|
},
|
|
|
|
|
issue: null,
|
|
|
|
|
workspace: {
|
|
|
|
|
baseCwd: workspaceCwd,
|
|
|
|
|
source: "project_primary",
|
|
|
|
|
projectId: project.id,
|
|
|
|
|
workspaceId: workspace.id,
|
|
|
|
|
repoUrl: workspace.repoUrl,
|
|
|
|
|
repoRef: workspace.repoRef,
|
|
|
|
|
strategy: "project_primary",
|
|
|
|
|
cwd: workspaceCwd,
|
|
|
|
|
branchName: workspace.defaultRef ?? workspace.repoRef ?? null,
|
|
|
|
|
worktreePath: null,
|
|
|
|
|
warnings: [],
|
|
|
|
|
created: false,
|
|
|
|
|
},
|
|
|
|
|
config: { workspaceRuntime: runtimeConfig },
|
|
|
|
|
adapterEnv: {},
|
|
|
|
|
onLog,
|
[codex] Improve workspace runtime and navigation ergonomics (#3680)
## Thinking Path
> - Paperclip orchestrates AI agents for zero-human companies
> - That operator experience depends not just on issue chat, but also on
how workspaces, inbox groups, and navigation state behave over
long-running sessions
> - The current branch included a separate cluster of workspace-runtime
controls, inbox grouping, sidebar ordering, and worktree lifecycle fixes
> - Those changes cross server, shared contracts, database state, and UI
navigation, but they still form one coherent operator workflow area
> - This pull request isolates the workspace/runtime and navigation
ergonomics work into one standalone branch
> - The benefit is better workspace recovery and navigation persistence
without forcing reviewers through the unrelated issue-detail/chat work
## What Changed
- Improved execution workspace and project workspace controls, request
wiring, layout, and JSON editor ergonomics
- Hardened linked worktree reuse/startup behavior and documented the
`worktree repair` flow for recovering linked worktrees safely
- Added inbox workspace grouping, mobile collapse, archive undo,
keyboard navigation, shared group-header styling, and persisted
collapsed-group behavior
- Added persistent sidebar order preferences with the supporting DB
migration, shared/server contracts, routes, services, hooks, and UI
integration
- Scoped issue-list preferences by context and added targeted UI/server
tests for workspace controls, inbox behavior, sidebar preferences, and
worktree validation
## Verification
- `pnpm vitest run
server/src/__tests__/sidebar-preferences-routes.test.ts
ui/src/pages/Inbox.test.tsx
ui/src/components/ProjectWorkspaceSummaryCard.test.tsx
ui/src/components/WorkspaceRuntimeControls.test.tsx
ui/src/api/workspace-runtime-control.test.ts`
- `server/src/__tests__/workspace-runtime.test.ts` was attempted, but
the embedded Postgres suite self-skipped/hung on this host after
reporting an init-script issue, so it is not counted as a local pass
here
## Risks
- Medium: this branch includes migration-backed preference storage plus
worktree/runtime behavior, so merge review should pay attention to state
persistence and worktree recovery semantics
- The sidebar preference migration is standalone, but it should still be
watched for conflicts if another migration lands first
## Model Used
- OpenAI Codex coding agent (GPT-5-class runtime in Codex CLI; exact
deployed model ID is not exposed in this environment), reasoning
enabled, tool use and local code execution enabled
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [ ] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [ ] If this change affects the UI, I have included before/after
screenshots
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge
---------
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-14 12:57:11 -05:00
|
|
|
serviceIndex: selectedServiceIndex,
|
2026-03-28 16:46:43 -05:00
|
|
|
});
|
|
|
|
|
runtimeServiceCount = startedServices.length;
|
|
|
|
|
} else {
|
[codex] Improve workspace runtime and navigation ergonomics (#3680)
## Thinking Path
> - Paperclip orchestrates AI agents for zero-human companies
> - That operator experience depends not just on issue chat, but also on
how workspaces, inbox groups, and navigation state behave over
long-running sessions
> - The current branch included a separate cluster of workspace-runtime
controls, inbox grouping, sidebar ordering, and worktree lifecycle fixes
> - Those changes cross server, shared contracts, database state, and UI
navigation, but they still form one coherent operator workflow area
> - This pull request isolates the workspace/runtime and navigation
ergonomics work into one standalone branch
> - The benefit is better workspace recovery and navigation persistence
without forcing reviewers through the unrelated issue-detail/chat work
## What Changed
- Improved execution workspace and project workspace controls, request
wiring, layout, and JSON editor ergonomics
- Hardened linked worktree reuse/startup behavior and documented the
`worktree repair` flow for recovering linked worktrees safely
- Added inbox workspace grouping, mobile collapse, archive undo,
keyboard navigation, shared group-header styling, and persisted
collapsed-group behavior
- Added persistent sidebar order preferences with the supporting DB
migration, shared/server contracts, routes, services, hooks, and UI
integration
- Scoped issue-list preferences by context and added targeted UI/server
tests for workspace controls, inbox behavior, sidebar preferences, and
worktree validation
## Verification
- `pnpm vitest run
server/src/__tests__/sidebar-preferences-routes.test.ts
ui/src/pages/Inbox.test.tsx
ui/src/components/ProjectWorkspaceSummaryCard.test.tsx
ui/src/components/WorkspaceRuntimeControls.test.tsx
ui/src/api/workspace-runtime-control.test.ts`
- `server/src/__tests__/workspace-runtime.test.ts` was attempted, but
the embedded Postgres suite self-skipped/hung on this host after
reporting an init-script issue, so it is not counted as a local pass
here
## Risks
- Medium: this branch includes migration-backed preference storage plus
worktree/runtime behavior, so merge review should pay attention to state
persistence and worktree recovery semantics
- The sidebar preference migration is standalone, but it should still be
watched for conflicts if another migration lands first
## Model Used
- OpenAI Codex coding agent (GPT-5-class runtime in Codex CLI; exact
deployed model ID is not exposed in this environment), reasoning
enabled, tool use and local code execution enabled
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [ ] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [ ] If this change affects the UI, I have included before/after
screenshots
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge
---------
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-14 12:57:11 -05:00
|
|
|
runtimeServiceCount = selectedRuntimeServiceId ? Math.max(0, (workspace.runtimeServices?.length ?? 1) - 1) : 0;
|
2026-03-28 16:46:43 -05:00
|
|
|
}
|
|
|
|
|
|
[codex] Improve workspace runtime and navigation ergonomics (#3680)
## Thinking Path
> - Paperclip orchestrates AI agents for zero-human companies
> - That operator experience depends not just on issue chat, but also on
how workspaces, inbox groups, and navigation state behave over
long-running sessions
> - The current branch included a separate cluster of workspace-runtime
controls, inbox grouping, sidebar ordering, and worktree lifecycle fixes
> - Those changes cross server, shared contracts, database state, and UI
navigation, but they still form one coherent operator workflow area
> - This pull request isolates the workspace/runtime and navigation
ergonomics work into one standalone branch
> - The benefit is better workspace recovery and navigation persistence
without forcing reviewers through the unrelated issue-detail/chat work
## What Changed
- Improved execution workspace and project workspace controls, request
wiring, layout, and JSON editor ergonomics
- Hardened linked worktree reuse/startup behavior and documented the
`worktree repair` flow for recovering linked worktrees safely
- Added inbox workspace grouping, mobile collapse, archive undo,
keyboard navigation, shared group-header styling, and persisted
collapsed-group behavior
- Added persistent sidebar order preferences with the supporting DB
migration, shared/server contracts, routes, services, hooks, and UI
integration
- Scoped issue-list preferences by context and added targeted UI/server
tests for workspace controls, inbox behavior, sidebar preferences, and
worktree validation
## Verification
- `pnpm vitest run
server/src/__tests__/sidebar-preferences-routes.test.ts
ui/src/pages/Inbox.test.tsx
ui/src/components/ProjectWorkspaceSummaryCard.test.tsx
ui/src/components/WorkspaceRuntimeControls.test.tsx
ui/src/api/workspace-runtime-control.test.ts`
- `server/src/__tests__/workspace-runtime.test.ts` was attempted, but
the embedded Postgres suite self-skipped/hung on this host after
reporting an init-script issue, so it is not counted as a local pass
here
## Risks
- Medium: this branch includes migration-backed preference storage plus
worktree/runtime behavior, so merge review should pay attention to state
persistence and worktree recovery semantics
- The sidebar preference migration is standalone, but it should still be
watched for conflicts if another migration lands first
## Model Used
- OpenAI Codex coding agent (GPT-5-class runtime in Codex CLI; exact
deployed model ID is not exposed in this environment), reasoning
enabled, tool use and local code execution enabled
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [ ] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [ ] If this change affects the UI, I have included before/after
screenshots
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge
---------
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-14 12:57:11 -05:00
|
|
|
const currentDesiredState: "running" | "stopped" =
|
|
|
|
|
workspace.runtimeConfig?.desiredState
|
|
|
|
|
?? ((workspace.runtimeServices ?? []).some((service) => service.status === "starting" || service.status === "running")
|
|
|
|
|
? "running"
|
|
|
|
|
: "stopped");
|
|
|
|
|
const nextRuntimeState: {
|
|
|
|
|
desiredState: "running" | "stopped";
|
|
|
|
|
serviceStates: Record<string, "running" | "stopped"> | null | undefined;
|
|
|
|
|
} = selectedRuntimeServiceId && (selectedServiceIndex === undefined || selectedServiceIndex === null)
|
|
|
|
|
? {
|
|
|
|
|
desiredState: currentDesiredState,
|
|
|
|
|
serviceStates: workspace.runtimeConfig?.serviceStates ?? null,
|
|
|
|
|
}
|
|
|
|
|
: buildWorkspaceRuntimeDesiredStatePatch({
|
|
|
|
|
config: { workspaceRuntime: runtimeConfig },
|
|
|
|
|
currentDesiredState,
|
|
|
|
|
currentServiceStates: workspace.runtimeConfig?.serviceStates ?? null,
|
|
|
|
|
action,
|
|
|
|
|
serviceIndex: selectedServiceIndex,
|
|
|
|
|
});
|
2026-03-28 16:46:43 -05:00
|
|
|
await svc.updateWorkspace(project.id, workspace.id, {
|
|
|
|
|
runtimeConfig: {
|
[codex] Improve workspace runtime and navigation ergonomics (#3680)
## Thinking Path
> - Paperclip orchestrates AI agents for zero-human companies
> - That operator experience depends not just on issue chat, but also on
how workspaces, inbox groups, and navigation state behave over
long-running sessions
> - The current branch included a separate cluster of workspace-runtime
controls, inbox grouping, sidebar ordering, and worktree lifecycle fixes
> - Those changes cross server, shared contracts, database state, and UI
navigation, but they still form one coherent operator workflow area
> - This pull request isolates the workspace/runtime and navigation
ergonomics work into one standalone branch
> - The benefit is better workspace recovery and navigation persistence
without forcing reviewers through the unrelated issue-detail/chat work
## What Changed
- Improved execution workspace and project workspace controls, request
wiring, layout, and JSON editor ergonomics
- Hardened linked worktree reuse/startup behavior and documented the
`worktree repair` flow for recovering linked worktrees safely
- Added inbox workspace grouping, mobile collapse, archive undo,
keyboard navigation, shared group-header styling, and persisted
collapsed-group behavior
- Added persistent sidebar order preferences with the supporting DB
migration, shared/server contracts, routes, services, hooks, and UI
integration
- Scoped issue-list preferences by context and added targeted UI/server
tests for workspace controls, inbox behavior, sidebar preferences, and
worktree validation
## Verification
- `pnpm vitest run
server/src/__tests__/sidebar-preferences-routes.test.ts
ui/src/pages/Inbox.test.tsx
ui/src/components/ProjectWorkspaceSummaryCard.test.tsx
ui/src/components/WorkspaceRuntimeControls.test.tsx
ui/src/api/workspace-runtime-control.test.ts`
- `server/src/__tests__/workspace-runtime.test.ts` was attempted, but
the embedded Postgres suite self-skipped/hung on this host after
reporting an init-script issue, so it is not counted as a local pass
here
## Risks
- Medium: this branch includes migration-backed preference storage plus
worktree/runtime behavior, so merge review should pay attention to state
persistence and worktree recovery semantics
- The sidebar preference migration is standalone, but it should still be
watched for conflicts if another migration lands first
## Model Used
- OpenAI Codex coding agent (GPT-5-class runtime in Codex CLI; exact
deployed model ID is not exposed in this environment), reasoning
enabled, tool use and local code execution enabled
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [ ] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [ ] If this change affects the UI, I have included before/after
screenshots
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge
---------
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-14 12:57:11 -05:00
|
|
|
desiredState: nextRuntimeState.desiredState,
|
|
|
|
|
serviceStates: nextRuntimeState.serviceStates,
|
2026-03-28 16:46:43 -05:00
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
status: "succeeded",
|
|
|
|
|
stdout: stdout.join(""),
|
|
|
|
|
stderr: stderr.join(""),
|
|
|
|
|
system:
|
|
|
|
|
action === "stop"
|
|
|
|
|
? "Stopped project workspace runtime services.\n"
|
|
|
|
|
: action === "restart"
|
|
|
|
|
? "Restarted project workspace runtime services.\n"
|
|
|
|
|
: "Started project workspace runtime services.\n",
|
|
|
|
|
metadata: {
|
|
|
|
|
runtimeServiceCount,
|
[codex] Improve workspace runtime and navigation ergonomics (#3680)
## Thinking Path
> - Paperclip orchestrates AI agents for zero-human companies
> - That operator experience depends not just on issue chat, but also on
how workspaces, inbox groups, and navigation state behave over
long-running sessions
> - The current branch included a separate cluster of workspace-runtime
controls, inbox grouping, sidebar ordering, and worktree lifecycle fixes
> - Those changes cross server, shared contracts, database state, and UI
navigation, but they still form one coherent operator workflow area
> - This pull request isolates the workspace/runtime and navigation
ergonomics work into one standalone branch
> - The benefit is better workspace recovery and navigation persistence
without forcing reviewers through the unrelated issue-detail/chat work
## What Changed
- Improved execution workspace and project workspace controls, request
wiring, layout, and JSON editor ergonomics
- Hardened linked worktree reuse/startup behavior and documented the
`worktree repair` flow for recovering linked worktrees safely
- Added inbox workspace grouping, mobile collapse, archive undo,
keyboard navigation, shared group-header styling, and persisted
collapsed-group behavior
- Added persistent sidebar order preferences with the supporting DB
migration, shared/server contracts, routes, services, hooks, and UI
integration
- Scoped issue-list preferences by context and added targeted UI/server
tests for workspace controls, inbox behavior, sidebar preferences, and
worktree validation
## Verification
- `pnpm vitest run
server/src/__tests__/sidebar-preferences-routes.test.ts
ui/src/pages/Inbox.test.tsx
ui/src/components/ProjectWorkspaceSummaryCard.test.tsx
ui/src/components/WorkspaceRuntimeControls.test.tsx
ui/src/api/workspace-runtime-control.test.ts`
- `server/src/__tests__/workspace-runtime.test.ts` was attempted, but
the embedded Postgres suite self-skipped/hung on this host after
reporting an init-script issue, so it is not counted as a local pass
here
## Risks
- Medium: this branch includes migration-backed preference storage plus
worktree/runtime behavior, so merge review should pay attention to state
persistence and worktree recovery semantics
- The sidebar preference migration is standalone, but it should still be
watched for conflicts if another migration lands first
## Model Used
- OpenAI Codex coding agent (GPT-5-class runtime in Codex CLI; exact
deployed model ID is not exposed in this environment), reasoning
enabled, tool use and local code execution enabled
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [ ] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [ ] If this change affects the UI, I have included before/after
screenshots
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge
---------
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-14 12:57:11 -05:00
|
|
|
workspaceCommandId: workspaceCommand?.id ?? target.workspaceCommandId ?? null,
|
|
|
|
|
runtimeServiceId: selectedRuntimeServiceId,
|
|
|
|
|
serviceIndex: selectedServiceIndex,
|
2026-03-28 16:46:43 -05:00
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const updatedWorkspace = (await svc.listWorkspaces(project.id)).find((entry) => entry.id === workspace.id) ?? workspace;
|
|
|
|
|
|
|
|
|
|
await logActivity(db, {
|
|
|
|
|
companyId: project.companyId,
|
|
|
|
|
actorType: actor.actorType,
|
|
|
|
|
actorId: actor.actorId,
|
|
|
|
|
agentId: actor.agentId,
|
|
|
|
|
action: `project.workspace_runtime_${action}`,
|
|
|
|
|
entityType: "project",
|
|
|
|
|
entityId: project.id,
|
|
|
|
|
details: {
|
|
|
|
|
projectWorkspaceId: workspace.id,
|
|
|
|
|
runtimeServiceCount,
|
[codex] Improve workspace runtime and navigation ergonomics (#3680)
## Thinking Path
> - Paperclip orchestrates AI agents for zero-human companies
> - That operator experience depends not just on issue chat, but also on
how workspaces, inbox groups, and navigation state behave over
long-running sessions
> - The current branch included a separate cluster of workspace-runtime
controls, inbox grouping, sidebar ordering, and worktree lifecycle fixes
> - Those changes cross server, shared contracts, database state, and UI
navigation, but they still form one coherent operator workflow area
> - This pull request isolates the workspace/runtime and navigation
ergonomics work into one standalone branch
> - The benefit is better workspace recovery and navigation persistence
without forcing reviewers through the unrelated issue-detail/chat work
## What Changed
- Improved execution workspace and project workspace controls, request
wiring, layout, and JSON editor ergonomics
- Hardened linked worktree reuse/startup behavior and documented the
`worktree repair` flow for recovering linked worktrees safely
- Added inbox workspace grouping, mobile collapse, archive undo,
keyboard navigation, shared group-header styling, and persisted
collapsed-group behavior
- Added persistent sidebar order preferences with the supporting DB
migration, shared/server contracts, routes, services, hooks, and UI
integration
- Scoped issue-list preferences by context and added targeted UI/server
tests for workspace controls, inbox behavior, sidebar preferences, and
worktree validation
## Verification
- `pnpm vitest run
server/src/__tests__/sidebar-preferences-routes.test.ts
ui/src/pages/Inbox.test.tsx
ui/src/components/ProjectWorkspaceSummaryCard.test.tsx
ui/src/components/WorkspaceRuntimeControls.test.tsx
ui/src/api/workspace-runtime-control.test.ts`
- `server/src/__tests__/workspace-runtime.test.ts` was attempted, but
the embedded Postgres suite self-skipped/hung on this host after
reporting an init-script issue, so it is not counted as a local pass
here
## Risks
- Medium: this branch includes migration-backed preference storage plus
worktree/runtime behavior, so merge review should pay attention to state
persistence and worktree recovery semantics
- The sidebar preference migration is standalone, but it should still be
watched for conflicts if another migration lands first
## Model Used
- OpenAI Codex coding agent (GPT-5-class runtime in Codex CLI; exact
deployed model ID is not exposed in this environment), reasoning
enabled, tool use and local code execution enabled
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [ ] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [ ] If this change affects the UI, I have included before/after
screenshots
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge
---------
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-14 12:57:11 -05:00
|
|
|
workspaceCommandId: workspaceCommand?.id ?? target.workspaceCommandId ?? null,
|
|
|
|
|
workspaceCommandKind: workspaceCommand?.kind ?? null,
|
|
|
|
|
workspaceCommandName: workspaceCommand?.name ?? null,
|
|
|
|
|
runtimeServiceId: selectedRuntimeServiceId,
|
|
|
|
|
serviceIndex: selectedServiceIndex,
|
2026-03-28 16:46:43 -05:00
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
res.json({
|
|
|
|
|
workspace: updatedWorkspace,
|
|
|
|
|
operation,
|
|
|
|
|
});
|
[codex] Improve workspace runtime and navigation ergonomics (#3680)
## Thinking Path
> - Paperclip orchestrates AI agents for zero-human companies
> - That operator experience depends not just on issue chat, but also on
how workspaces, inbox groups, and navigation state behave over
long-running sessions
> - The current branch included a separate cluster of workspace-runtime
controls, inbox grouping, sidebar ordering, and worktree lifecycle fixes
> - Those changes cross server, shared contracts, database state, and UI
navigation, but they still form one coherent operator workflow area
> - This pull request isolates the workspace/runtime and navigation
ergonomics work into one standalone branch
> - The benefit is better workspace recovery and navigation persistence
without forcing reviewers through the unrelated issue-detail/chat work
## What Changed
- Improved execution workspace and project workspace controls, request
wiring, layout, and JSON editor ergonomics
- Hardened linked worktree reuse/startup behavior and documented the
`worktree repair` flow for recovering linked worktrees safely
- Added inbox workspace grouping, mobile collapse, archive undo,
keyboard navigation, shared group-header styling, and persisted
collapsed-group behavior
- Added persistent sidebar order preferences with the supporting DB
migration, shared/server contracts, routes, services, hooks, and UI
integration
- Scoped issue-list preferences by context and added targeted UI/server
tests for workspace controls, inbox behavior, sidebar preferences, and
worktree validation
## Verification
- `pnpm vitest run
server/src/__tests__/sidebar-preferences-routes.test.ts
ui/src/pages/Inbox.test.tsx
ui/src/components/ProjectWorkspaceSummaryCard.test.tsx
ui/src/components/WorkspaceRuntimeControls.test.tsx
ui/src/api/workspace-runtime-control.test.ts`
- `server/src/__tests__/workspace-runtime.test.ts` was attempted, but
the embedded Postgres suite self-skipped/hung on this host after
reporting an init-script issue, so it is not counted as a local pass
here
## Risks
- Medium: this branch includes migration-backed preference storage plus
worktree/runtime behavior, so merge review should pay attention to state
persistence and worktree recovery semantics
- The sidebar preference migration is standalone, but it should still be
watched for conflicts if another migration lands first
## Model Used
- OpenAI Codex coding agent (GPT-5-class runtime in Codex CLI; exact
deployed model ID is not exposed in this environment), reasoning
enabled, tool use and local code execution enabled
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [ ] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [ ] If this change affects the UI, I have included before/after
screenshots
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge
---------
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-14 12:57:11 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
router.post("/projects/:id/workspaces/:workspaceId/runtime-services/:action", validate(workspaceRuntimeControlTargetSchema), handleProjectWorkspaceRuntimeCommand);
|
|
|
|
|
router.post("/projects/:id/workspaces/:workspaceId/runtime-commands/:action", validate(workspaceRuntimeControlTargetSchema), handleProjectWorkspaceRuntimeCommand);
|
2026-03-28 16:46:43 -05:00
|
|
|
|
2026-02-25 08:38:46 -06:00
|
|
|
router.delete("/projects/:id/workspaces/:workspaceId", async (req, res) => {
|
|
|
|
|
const id = req.params.id as string;
|
|
|
|
|
const workspaceId = req.params.workspaceId as string;
|
|
|
|
|
const existing = await svc.getById(id);
|
|
|
|
|
if (!existing) {
|
|
|
|
|
res.status(404).json({ error: "Project not found" });
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
assertCompanyAccess(req, existing.companyId);
|
|
|
|
|
const workspace = await svc.removeWorkspace(id, workspaceId);
|
|
|
|
|
if (!workspace) {
|
|
|
|
|
res.status(404).json({ error: "Project workspace not found" });
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const actor = getActorInfo(req);
|
|
|
|
|
await logActivity(db, {
|
|
|
|
|
companyId: existing.companyId,
|
|
|
|
|
actorType: actor.actorType,
|
|
|
|
|
actorId: actor.actorId,
|
|
|
|
|
agentId: actor.agentId,
|
|
|
|
|
action: "project.workspace_deleted",
|
|
|
|
|
entityType: "project",
|
|
|
|
|
entityId: id,
|
|
|
|
|
details: {
|
|
|
|
|
workspaceId: workspace.id,
|
|
|
|
|
name: workspace.name,
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
res.json(workspace);
|
|
|
|
|
});
|
|
|
|
|
|
Add server routes for companies, approvals, costs, and dashboard
New routes: companies, approvals, costs, dashboard, authz. New
services: companies, approvals, costs, dashboard, heartbeat,
activity-log. Add auth middleware and structured error handling.
Expand existing agent and issue routes with richer CRUD operations.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 09:07:27 -06:00
|
|
|
router.delete("/projects/:id", async (req, res) => {
|
2026-02-16 13:31:58 -06:00
|
|
|
const id = req.params.id as string;
|
Add server routes for companies, approvals, costs, and dashboard
New routes: companies, approvals, costs, dashboard, authz. New
services: companies, approvals, costs, dashboard, heartbeat,
activity-log. Add auth middleware and structured error handling.
Expand existing agent and issue routes with richer CRUD operations.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 09:07:27 -06:00
|
|
|
const existing = await svc.getById(id);
|
|
|
|
|
if (!existing) {
|
|
|
|
|
res.status(404).json({ error: "Project not found" });
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
assertCompanyAccess(req, existing.companyId);
|
2026-02-16 13:31:58 -06:00
|
|
|
const project = await svc.remove(id);
|
|
|
|
|
if (!project) {
|
|
|
|
|
res.status(404).json({ error: "Project not found" });
|
|
|
|
|
return;
|
|
|
|
|
}
|
Add server routes for companies, approvals, costs, and dashboard
New routes: companies, approvals, costs, dashboard, authz. New
services: companies, approvals, costs, dashboard, heartbeat,
activity-log. Add auth middleware and structured error handling.
Expand existing agent and issue routes with richer CRUD operations.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 09:07:27 -06:00
|
|
|
|
|
|
|
|
const actor = getActorInfo(req);
|
|
|
|
|
await logActivity(db, {
|
|
|
|
|
companyId: project.companyId,
|
|
|
|
|
actorType: actor.actorType,
|
|
|
|
|
actorId: actor.actorId,
|
|
|
|
|
agentId: actor.agentId,
|
|
|
|
|
action: "project.deleted",
|
|
|
|
|
entityType: "project",
|
|
|
|
|
entityId: project.id,
|
|
|
|
|
});
|
|
|
|
|
|
2026-02-16 13:31:58 -06:00
|
|
|
res.json(project);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return router;
|
|
|
|
|
}
|