saveTask: accept requires_filesystem; opt in for the onboarding kickoff task
- saveTask now takes an optional requiresFilesystem boolean. Omitted → column keeps its current value on updates, defaults to 0 on inserts. Explicit true/false → written through. - Onboarding kickoff (the CEO's very first task) sets requiresFilesystem=true. The task description already tells the agent to list directories and read README/package.json — that is filesystem work, so the task must hold the workspace exclusive. - Other saveTask call sites (automation reassign, routes-tasks patch, create_task, meetings) stay implicit — update paths preserve the existing column value, new user-created tasks default to 0 (safe cognitive default) and can be opted in later by the creator.
This commit is contained in:
1 parent
c3dd08ec65
commit
15e3863cba
2 files changed
+59
-20
No files matched your search
@@ -57,6 +57,16 @@ export function buildTaskCrudMethods(
|
||||
workspaceId?: string | null;
|
||||
priority: string;
|
||||
status: string;
|
||||
/**
|
||||
* Per-task filesystem lock policy (v52+). When omitted the
|
||||
* column defaults to 0 at the SQL layer for inserts, and the
|
||||
* existing value is preserved on updates. Callers opt in with
|
||||
* `true` when they know the task will read/write the working
|
||||
* tree (CEO kickoff reads the repo, CTO code changes mutate
|
||||
* it, etc.). Leaving it undefined is the safe default for
|
||||
* purely cognitive tasks.
|
||||
*/
|
||||
requiresFilesystem?: boolean;
|
||||
}): string {
|
||||
const id = ensureId(input.id ?? null);
|
||||
const ts = nowIso();
|
||||
@@ -68,29 +78,52 @@ export function buildTaskCrudMethods(
|
||||
.prepare("select id from tasks where id = ? and company_id = ?")
|
||||
.get(id, input.companyId) as { id: string } | undefined;
|
||||
if (existing) {
|
||||
getDb()
|
||||
.prepare(
|
||||
// eslint-disable-next-line no-restricted-syntax -- B2 Phase 1 grandfathered: saveTask upsert path writes the full row (including status) as a single atomic UPDATE. The status→phase trigger keeps the shadow phase column in sync; no lease is ever held by saveTask callers (lease writes live behind checkoutTask).
|
||||
"update tasks set project_id = ?, goal_id = ?, parent_id = ?, title = ?, description = ?, assignee_agent_id = ?, workspace_id = ?, priority = ?, status = ?, updated_at = ? where id = ? and company_id = ?",
|
||||
)
|
||||
.run(
|
||||
normalizeOptionalId(input.projectId),
|
||||
normalizeOptionalId(input.goalId),
|
||||
normalizeOptionalId(input.parentId),
|
||||
input.title,
|
||||
input.description,
|
||||
assigneeAgentId,
|
||||
normalizeOptionalId(input.workspaceId),
|
||||
input.priority,
|
||||
input.status,
|
||||
ts,
|
||||
id,
|
||||
input.companyId,
|
||||
);
|
||||
if (input.requiresFilesystem === undefined) {
|
||||
getDb()
|
||||
.prepare(
|
||||
// eslint-disable-next-line no-restricted-syntax -- B2 Phase 1 grandfathered: saveTask upsert path writes the full row (including status) as a single atomic UPDATE. The status→phase trigger keeps the shadow phase column in sync; no lease is ever held by saveTask callers (lease writes live behind checkoutTask).
|
||||
"update tasks set project_id = ?, goal_id = ?, parent_id = ?, title = ?, description = ?, assignee_agent_id = ?, workspace_id = ?, priority = ?, status = ?, updated_at = ? where id = ? and company_id = ?",
|
||||
)
|
||||
.run(
|
||||
normalizeOptionalId(input.projectId),
|
||||
normalizeOptionalId(input.goalId),
|
||||
normalizeOptionalId(input.parentId),
|
||||
input.title,
|
||||
input.description,
|
||||
assigneeAgentId,
|
||||
normalizeOptionalId(input.workspaceId),
|
||||
input.priority,
|
||||
input.status,
|
||||
ts,
|
||||
id,
|
||||
input.companyId,
|
||||
);
|
||||
} else {
|
||||
getDb()
|
||||
.prepare(
|
||||
// eslint-disable-next-line no-restricted-syntax -- B2 Phase 1 grandfathered: saveTask upsert path writes the full row (including status) as a single atomic UPDATE. The status→phase trigger keeps the shadow phase column in sync; no lease is ever held by saveTask callers (lease writes live behind checkoutTask).
|
||||
"update tasks set project_id = ?, goal_id = ?, parent_id = ?, title = ?, description = ?, assignee_agent_id = ?, workspace_id = ?, priority = ?, status = ?, requires_filesystem = ?, updated_at = ? where id = ? and company_id = ?",
|
||||
)
|
||||
.run(
|
||||
normalizeOptionalId(input.projectId),
|
||||
normalizeOptionalId(input.goalId),
|
||||
normalizeOptionalId(input.parentId),
|
||||
input.title,
|
||||
input.description,
|
||||
assigneeAgentId,
|
||||
normalizeOptionalId(input.workspaceId),
|
||||
input.priority,
|
||||
input.status,
|
||||
input.requiresFilesystem ? 1 : 0,
|
||||
ts,
|
||||
id,
|
||||
input.companyId,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
getDb()
|
||||
.prepare(
|
||||
"insert into tasks (id, company_id, project_id, goal_id, parent_id, title, description, assignee_agent_id, workspace_id, status, priority, created_at, updated_at) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||||
"insert into tasks (id, company_id, project_id, goal_id, parent_id, title, description, assignee_agent_id, workspace_id, status, priority, requires_filesystem, created_at, updated_at) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||||
)
|
||||
.run(
|
||||
id,
|
||||
@@ -104,6 +137,7 @@ export function buildTaskCrudMethods(
|
||||
normalizeOptionalId(input.workspaceId),
|
||||
input.status,
|
||||
input.priority,
|
||||
input.requiresFilesystem ? 1 : 0,
|
||||
ts,
|
||||
ts,
|
||||
);
|
||||
|
||||
Reference in new issue
Block a user