Route goal kickoffs through task policy and revive waiting goals on hire

Adversarial review of the kickoff feature surfaced two gaps. First, the
kickoff task was inserted with raw SQL, so a workspace-bound kickoff
carried requires_filesystem without the execution approval every other
task receives - manual runs failed and review-mode orgs had no approval
trail. Kickoffs (in-app and onboarding) now go through createTask and
its policy gates. Second, a goal created before any agent existed
stayed inert forever; creating an agent now operationalizes every
active goal that has no task yet. Goal owners must be active agents:
an archived owner falls back to the top-level agent and the owner
dropdown only offers active agents.
This commit is contained in:
ZacharyZhang-NY committed 2026-06-09 20:38:35 -04:00
1 parent cfbe5e1c8e
commit 4e47da4d6b
5 files changed
+125 -104

No files matched your search

@@ -643,8 +643,9 @@ describe("domain services", () => {
});
// Without any agent there is nobody to operationalize the goal yet.
let waitingGoalId = "";
connection.transaction(() => {
organization.createGoal({ orgId, title: "Open the Berlin market", description: "Win the first ten customers.", ownerAgentId: null });
waitingGoalId = organization.createGoal({ orgId, title: "Open the Berlin market", description: "Win the first ten customers.", ownerAgentId: null });
});
expect(connection.db.prepare("select count(*) as n from tasks where org_id = ?").get(orgId)).toMatchObject({ n: 0 });
@@ -674,6 +675,12 @@ describe("domain services", () => {
});
});
// The first hire operationalizes the goal that was waiting, exactly once.
expect(connection.db.prepare("select count(*) as n from tasks where goal_id = ?").get(waitingGoalId)).toMatchObject({ n: 1 });
const revived = connection.db.prepare("select status, assignee_agent_id from tasks where goal_id = ?")
.get(waitingGoalId) as { status: string; assignee_agent_id: string };
expect(revived).toMatchObject({ status: TASK_STATUS.BACKLOG, assignee_agent_id: ceoId });
// Ownerless goals land with the top-level agent; the kickoff re-enables its heartbeat.
let ceoGoalId = "";
connection.transaction(() => {