@markjaquith/agency 2.13.0 → 2.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -357,7 +357,7 @@ Inspect tasks:
357
357
  ```text
358
358
  agency task list [--json]
359
359
  agency task show <id> [--json]
360
- agency task status <id> <open|working|delegated|done|dropped> [--json]
360
+ agency task status <id> <open|done|dropped> [--json]
361
361
  ```
362
362
 
363
363
  To add a phase to an existing single-phase task, name the phase that will own
@@ -384,16 +384,48 @@ agency phase create <task-id> <phase-id>
384
384
 
385
385
  agency phase list <task-id> [--json]
386
386
  agency phase show <task-id> <phase-id> [--json]
387
- agency phase status <task-id> <phase-id> <open|working|delegated|done|dropped> [--json]
387
+ agency phase status <task-id> <phase-id> <open|done|dropped> [--json]
388
388
  ```
389
389
 
390
390
  Single-phase tasks and phases store status in YAML. New execution units start
391
391
  `open`, and `agency work` marks the selected execution unit `working` immediately
392
- before launch. Use the status subcommands to mark work `delegated`, `done`,
393
- `dropped`, or open it again. The interactive work selector displays status
394
- markers before execution units. Open, working, and delegated work may transition
395
- to any status. Done and dropped work are terminal and may only remain unchanged
396
- or transition to open; reopen terminal work before changing its outcome.
392
+ before launch. Use claims for coordinated ownership and the status subcommands
393
+ for manual lifecycle overrides. The interactive work selector displays status
394
+ markers before execution units. Existing working and delegated work may be
395
+ released to `open` or assigned a terminal outcome. Done and dropped work are
396
+ terminal and may only remain unchanged or transition to open; reopen terminal
397
+ work before changing its outcome.
398
+
399
+ `delegated` remains readable for existing workbases but cannot be newly assigned.
400
+ Delegation is now explicit: the claimant identifies the orchestrator and the
401
+ runner identifies the assigned agent.
402
+
403
+ ### Claims
404
+
405
+ Claim mutations require the SHA-256 revision exposed by `agency context` or
406
+ `agency graph`. Every operation compares that revision while holding an exclusive
407
+ document lock and atomically replaces the execution document.
408
+
409
+ ```text
410
+ agency claim <task-id> [phase-id] --claimant <id> --runner <id>
411
+ --session-id <id> --revision <sha256> [--expires-at <timestamp>] [--json]
412
+ agency release <task-id> [phase-id] --session-id <id>
413
+ --revision <sha256> [--json]
414
+ agency finish <task-id> [phase-id] --session-id <id>
415
+ --revision <sha256> --outcome <done|dropped> [--json]
416
+ ```
417
+
418
+ An active claim sets status to `working`. Release returns it to `open`; finish
419
+ sets the terminal outcome. Released and finished ownership metadata remains in
420
+ frontmatter. Conflicts return the current revision and complete ownership record
421
+ in the machine error envelope rather than overwriting it. Expired claims may be
422
+ replaced with a revision-guarded claim.
423
+
424
+ `agency work` claims an execution unit before launching its agent. Set
425
+ `AGENCY_CLAIMANT`, `AGENCY_RUNNER`, or `AGENCY_SESSION_ID` to supply orchestrator
426
+ identities; otherwise Agency derives them from the user, selected agent, and
427
+ process. The launched agent receives `AGENCY_SESSION_ID` and
428
+ `AGENCY_CLAIM_REVISION` for a later release or finish operation.
397
429
 
398
430
  ### Archive
399
431
 
package/cli.ts CHANGED
@@ -32,6 +32,13 @@ import { ArchiveService } from "./src/services/ArchiveService"
32
32
  import { IntegrationService } from "./src/services/IntegrationService"
33
33
  import { ContextService } from "./src/services/ContextService"
34
34
  import { GraphService } from "./src/services/GraphService"
35
+ import { ClaimService } from "./src/services/ClaimService"
36
+ import {
37
+ claimCommand,
38
+ claimHelp,
39
+ releaseHelp,
40
+ finishHelp,
41
+ } from "./src/commands/claim"
35
42
  import {
36
43
  collectCommandResult,
37
44
  errorEnvelope,
@@ -53,6 +60,7 @@ const CliLayer = Layer.mergeAll(
53
60
  IntegrationService.Default,
54
61
  ContextService.Default,
55
62
  GraphService.Default,
63
+ ClaimService.Default,
56
64
  )
57
65
 
58
66
  /**
@@ -99,6 +107,61 @@ const VERSION = packageJson.version
99
107
 
100
108
  // Define commands
101
109
  const commands: Record<string, Command> = {
110
+ claim: {
111
+ run: async (args: string[], options: Record<string, any>) => {
112
+ if (options.help) return console.log(claimHelp)
113
+ await runCommand(
114
+ claimCommand({
115
+ operation: "claim",
116
+ taskId: args[0],
117
+ phaseId: args[1],
118
+ claimant: options.claimant,
119
+ runner: options.runner,
120
+ sessionId: options["session-id"],
121
+ revision: options.revision,
122
+ expiresAt: options["expires-at"],
123
+ json: options.json,
124
+ silent: options.silent,
125
+ verbose: options.verbose,
126
+ }),
127
+ )
128
+ },
129
+ },
130
+ release: {
131
+ run: async (args: string[], options: Record<string, any>) => {
132
+ if (options.help) return console.log(releaseHelp)
133
+ await runCommand(
134
+ claimCommand({
135
+ operation: "release",
136
+ taskId: args[0],
137
+ phaseId: args[1],
138
+ sessionId: options["session-id"],
139
+ revision: options.revision,
140
+ json: options.json,
141
+ silent: options.silent,
142
+ verbose: options.verbose,
143
+ }),
144
+ )
145
+ },
146
+ },
147
+ finish: {
148
+ run: async (args: string[], options: Record<string, any>) => {
149
+ if (options.help) return console.log(finishHelp)
150
+ await runCommand(
151
+ claimCommand({
152
+ operation: "finish",
153
+ taskId: args[0],
154
+ phaseId: args[1],
155
+ sessionId: options["session-id"],
156
+ revision: options.revision,
157
+ outcome: options.outcome,
158
+ json: options.json,
159
+ silent: options.silent,
160
+ verbose: options.verbose,
161
+ }),
162
+ )
163
+ },
164
+ },
102
165
  init: {
103
166
  run: async (args: string[], options: Record<string, any>) => {
104
167
  if (options.help) {
@@ -375,6 +438,9 @@ Commands:
375
438
  integration <command> Inspect or sync managed integration files
376
439
  epic <subcommand> Manage epics
377
440
  phase <subcommand> Manage task phases
441
+ claim <task> [phase] Claim an execution unit
442
+ release <task> [phase] Release an execution unit
443
+ finish <task> [phase] Finish an execution unit
378
444
  archive <type> Archive a work item
379
445
  task <subcommand> Manage tasks
380
446
  work [directory|task] Work on an epic, task, or phase
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@markjaquith/agency",
3
- "version": "2.13.0",
3
+ "version": "2.14.0",
4
4
  "description": "Manage agentic work across repositories with durable workbases",
5
5
  "keywords": [
6
6
  "agents",
@@ -339,6 +339,7 @@
339
339
  "base": { "type": "string" },
340
340
  "pr": { "type": ["string", "null"] },
341
341
  "status": { "$ref": "#/$defs/status" },
342
+ "claim": { "$ref": "#/$defs/claim" },
342
343
  "sha256": { "type": "string" }
343
344
  }
344
345
  },
@@ -372,6 +373,7 @@
372
373
  "base": { "type": "string" },
373
374
  "pr": { "type": ["string", "null"] },
374
375
  "status": { "$ref": "#/$defs/status" },
376
+ "claim": { "$ref": "#/$defs/claim" },
375
377
  "sha256": { "type": "string" }
376
378
  }
377
379
  },
@@ -393,7 +395,32 @@
393
395
  "branch": { "type": "string" },
394
396
  "base": { "type": "string" },
395
397
  "pr": { "type": ["string", "null"] },
396
- "status": { "$ref": "#/$defs/status" }
398
+ "status": { "$ref": "#/$defs/status" },
399
+ "claim": { "$ref": "#/$defs/claim" }
400
+ }
401
+ },
402
+ "claim": {
403
+ "type": "object",
404
+ "additionalProperties": false,
405
+ "required": [
406
+ "claimant",
407
+ "runner",
408
+ "sessionId",
409
+ "startedAt",
410
+ "targetRevision",
411
+ "state"
412
+ ],
413
+ "properties": {
414
+ "claimant": { "type": "string", "minLength": 1 },
415
+ "runner": { "type": "string", "minLength": 1 },
416
+ "sessionId": { "type": "string", "minLength": 1 },
417
+ "startedAt": { "type": "string", "format": "date-time" },
418
+ "targetRevision": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
419
+ "expiresAt": { "type": "string", "format": "date-time" },
420
+ "state": { "enum": ["active", "released", "finished"] },
421
+ "releasedAt": { "type": "string", "format": "date-time" },
422
+ "finishedAt": { "type": "string", "format": "date-time" },
423
+ "outcome": { "enum": ["done", "dropped"] }
397
424
  }
398
425
  },
399
426
  "repositoryData": {
@@ -213,7 +213,9 @@ details explicitly with `--include bodies|workspace|git|pr`. For large workbases
213
213
  - Epic frontmatter owns the child-task dependency graph.
214
214
  - `pr` is either a GitHub PR URL string or `null`.
215
215
  - Execution-unit `status` is `open`, `working`, `delegated`, `done`, or `dropped`.
216
- New work starts open, and `agency work` marks it working before agent launch.
216
+ New work starts open, and an active claim sets it working before agent launch.
217
+ `delegated` is readable legacy state; distinct claimant and runner identities
218
+ now represent delegation.
217
219
  - Keep directory IDs stable; encode sequencing with `dependsOn`, not numeric
218
220
  directory prefixes.
219
221
  - Do not use YAML duplicate keys, anchors, aliases, or custom tags.
@@ -224,8 +226,17 @@ prose, preserve backlinks and run validation immediately afterward.
224
226
  Update execution status with:
225
227
 
226
228
  ```bash
227
- agency task status <task-id> <open|working|delegated|done|dropped>
228
- agency phase status <task-id> <phase-id> <open|working|delegated|done|dropped>
229
+ agency task status <task-id> <open|done|dropped>
230
+ agency phase status <task-id> <phase-id> <open|done|dropped>
231
+ ```
232
+
233
+ Coordinate execution ownership with a document revision from `agency context`
234
+ or `agency graph`:
235
+
236
+ ```bash
237
+ agency claim <task-id> [phase-id] --claimant <id> --runner <id> --session-id <id> --revision <sha256>
238
+ agency release <task-id> [phase-id] --session-id <id> --revision <sha256>
239
+ agency finish <task-id> [phase-id] --session-id <id> --revision <sha256> --outcome <done|dropped>
229
240
  ```
230
241
 
231
242
  ## Archive Completed Work
@@ -141,11 +141,92 @@ describe("strict CLI parsing", () => {
141
141
  [["validate", "one", "two"], "agency validate"],
142
142
  [["context", "one", "two"], "agency context"],
143
143
  [["graph", "extra"], "agency graph"],
144
+ [
145
+ [
146
+ "claim",
147
+ "one",
148
+ "two",
149
+ "three",
150
+ "--claimant",
151
+ "a",
152
+ "--runner",
153
+ "r",
154
+ "--session-id",
155
+ "s",
156
+ "--revision",
157
+ "0".repeat(64),
158
+ ],
159
+ "agency claim",
160
+ ],
161
+ [
162
+ [
163
+ "release",
164
+ "one",
165
+ "two",
166
+ "three",
167
+ "--session-id",
168
+ "s",
169
+ "--revision",
170
+ "0".repeat(64),
171
+ ],
172
+ "agency release",
173
+ ],
174
+ [
175
+ [
176
+ "finish",
177
+ "one",
178
+ "two",
179
+ "three",
180
+ "--session-id",
181
+ "s",
182
+ "--revision",
183
+ "0".repeat(64),
184
+ "--outcome",
185
+ "done",
186
+ ],
187
+ "agency finish",
188
+ ],
144
189
  ] as const) {
145
190
  expectUsageError([...args], usage)
146
191
  }
147
192
  })
148
193
 
194
+ test("validates revision-guarded claim operations", () => {
195
+ const revision = "0".repeat(64)
196
+ expect(
197
+ parseCli([
198
+ "claim",
199
+ "task",
200
+ "phase",
201
+ "--claimant",
202
+ "orchestrator",
203
+ "--runner",
204
+ "agent",
205
+ "--session-id",
206
+ "job-1",
207
+ "--revision",
208
+ revision,
209
+ "--expires-at",
210
+ "2026-07-17T13:00:00.000Z",
211
+ ]),
212
+ ).toMatchObject({ commandName: "claim", args: ["task", "phase"] })
213
+ expect(() =>
214
+ parseCli(["release", "task", "--session-id", "job-1"]),
215
+ ).toThrow("--revision' is required")
216
+ expect(() =>
217
+ parseCli([
218
+ "finish",
219
+ "task",
220
+ "--session-id",
221
+ "job-1",
222
+ "--revision",
223
+ revision,
224
+ "--outcome",
225
+ "working",
226
+ ]),
227
+ ).toThrow("must be 'done' or 'dropped'")
228
+ })
229
+
149
230
  test("accepts context projections and keeps compact command-local", () => {
150
231
  expect(parseCli(["context", ".", "--json", "--compact"])).toMatchObject({
151
232
  commandName: "context",
package/src/cli-parser.ts CHANGED
@@ -59,6 +59,21 @@ const phaseCreateOptions = {
59
59
  "first-phase": { type: "string" },
60
60
  } satisfies OptionConfig
61
61
 
62
+ const claimOptions = {
63
+ ...outputOptions,
64
+ claimant: { type: "string" },
65
+ runner: { type: "string" },
66
+ "session-id": { type: "string" },
67
+ revision: { type: "string" },
68
+ "expires-at": { type: "string" },
69
+ } satisfies OptionConfig
70
+
71
+ const ownedClaimOptions = {
72
+ ...outputOptions,
73
+ "session-id": { type: "string" },
74
+ revision: { type: "string" },
75
+ } satisfies OptionConfig
76
+
62
77
  const commands = {
63
78
  init: {
64
79
  usage: "agency init [path] [--json]",
@@ -258,6 +273,52 @@ const commands = {
258
273
  },
259
274
  },
260
275
  },
276
+ claim: {
277
+ usage: "agency claim <task-id> [phase-id] [options]",
278
+ options: claimOptions,
279
+ command: {
280
+ usage:
281
+ "agency claim <task-id> [phase-id] --claimant <id> --runner <id> --session-id <id> --revision <sha256> [--expires-at <timestamp>] [--json]",
282
+ minArgs: 1,
283
+ maxArgs: 2,
284
+ options: [
285
+ "claimant",
286
+ "runner",
287
+ "session-id",
288
+ "revision",
289
+ "expires-at",
290
+ "json",
291
+ ],
292
+ required: ["claimant", "runner", "session-id", "revision"],
293
+ },
294
+ },
295
+ release: {
296
+ usage: "agency release <task-id> [phase-id] [options]",
297
+ options: ownedClaimOptions,
298
+ command: {
299
+ usage:
300
+ "agency release <task-id> [phase-id] --session-id <id> --revision <sha256> [--json]",
301
+ minArgs: 1,
302
+ maxArgs: 2,
303
+ options: ["session-id", "revision", "json"],
304
+ required: ["session-id", "revision"],
305
+ },
306
+ },
307
+ finish: {
308
+ usage: "agency finish <task-id> [phase-id] [options]",
309
+ options: {
310
+ ...ownedClaimOptions,
311
+ outcome: { type: "string" },
312
+ },
313
+ command: {
314
+ usage:
315
+ "agency finish <task-id> [phase-id] --session-id <id> --revision <sha256> --outcome <done|dropped> [--json]",
316
+ minArgs: 1,
317
+ maxArgs: 2,
318
+ options: ["session-id", "revision", "outcome", "json"],
319
+ required: ["session-id", "revision", "outcome"],
320
+ },
321
+ },
261
322
  archive: {
262
323
  usage: "agency archive <epic|task|phase>",
263
324
  options: outputOptions,
@@ -653,6 +714,16 @@ export function parseCli(args: readonly string[]): ParsedCli {
653
714
  if (commandName === "graph") {
654
715
  validateGraphOptions(parsed.values, spec)
655
716
  }
717
+ if (
718
+ commandName === "finish" &&
719
+ parsed.values.outcome !== "done" &&
720
+ parsed.values.outcome !== "dropped"
721
+ ) {
722
+ throw usageError(
723
+ "Option '--outcome' must be 'done' or 'dropped'.",
724
+ spec.usage,
725
+ )
726
+ }
656
727
  if (commandName === "work") {
657
728
  const preparing = commandPositionals[0] === "prepare"
658
729
  if (
package/src/cli.test.ts CHANGED
@@ -81,6 +81,91 @@ describe("CLI", () => {
81
81
  expect(taggedError.stderr).not.toContain("An error has occurred")
82
82
  })
83
83
 
84
+ test("coordinates claims through revision-guarded machine commands", async () => {
85
+ const root = await createTempDir()
86
+ tempDirs.push(root)
87
+ await Bun.write(join(root, "agency.json"), '{"version":2}\n')
88
+ await mkdir(join(root, "repos", "agency"), { recursive: true })
89
+ parseJson(
90
+ await runCli(
91
+ ["task", "create", "claimed", "--repo", "agency", "--json"],
92
+ root,
93
+ ),
94
+ )
95
+ const context = parseJson(
96
+ await runCli(["context", "tasks/claimed", "--json"], root),
97
+ )
98
+ const revision = context.documents.task.sha256
99
+ const claimed = parseJson(
100
+ await runCli(
101
+ [
102
+ "claim",
103
+ "claimed",
104
+ "--claimant",
105
+ "orchestrator",
106
+ "--runner",
107
+ "agent",
108
+ "--session-id",
109
+ "job-1",
110
+ "--revision",
111
+ revision,
112
+ "--json",
113
+ ],
114
+ root,
115
+ ),
116
+ )
117
+ expect(claimed.claim).toMatchObject({
118
+ claimant: "orchestrator",
119
+ runner: "agent",
120
+ sessionId: "job-1",
121
+ state: "active",
122
+ })
123
+
124
+ const conflict = await runCli(
125
+ [
126
+ "claim",
127
+ "claimed",
128
+ "--claimant",
129
+ "other",
130
+ "--runner",
131
+ "other-agent",
132
+ "--session-id",
133
+ "job-2",
134
+ "--revision",
135
+ claimed.revision,
136
+ "--json",
137
+ ],
138
+ root,
139
+ )
140
+ expect(conflict.exitCode).toBe(1)
141
+ expect(JSON.parse(conflict.stdout)).toMatchObject({
142
+ ok: false,
143
+ error: {
144
+ code: "CLAIM_CONFLICT",
145
+ retryable: true,
146
+ fields: { claim: { runner: "agent", sessionId: "job-1" } },
147
+ },
148
+ })
149
+
150
+ const finished = parseJson(
151
+ await runCli(
152
+ [
153
+ "finish",
154
+ "claimed",
155
+ "--session-id",
156
+ "job-1",
157
+ "--revision",
158
+ claimed.revision,
159
+ "--outcome",
160
+ "done",
161
+ "--json",
162
+ ],
163
+ root,
164
+ ),
165
+ )
166
+ expect(finished.claim).toMatchObject({ state: "finished", outcome: "done" })
167
+ })
168
+
84
169
  test("emits one versioned error envelope for usage and command failures", async () => {
85
170
  const usage = await runCli(["unknown", "--json"])
86
171
  expect(usage.exitCode).toBe(1)
@@ -0,0 +1,97 @@
1
+ import { Effect } from "effect"
2
+ import { ClaimService } from "../services/ClaimService"
3
+ import type { BaseCommandOptions } from "../utils/command"
4
+ import { createLoggers } from "../utils/effect"
5
+
6
+ interface ClaimCommandOptions extends BaseCommandOptions {
7
+ readonly operation: "claim" | "release" | "finish"
8
+ readonly taskId?: string
9
+ readonly phaseId?: string
10
+ readonly claimant?: string
11
+ readonly runner?: string
12
+ readonly sessionId?: string
13
+ readonly revision?: string
14
+ readonly expiresAt?: string
15
+ readonly outcome?: string
16
+ readonly json?: boolean
17
+ }
18
+
19
+ export const claimCommand = (options: ClaimCommandOptions) =>
20
+ Effect.gen(function* () {
21
+ const claims = yield* ClaimService
22
+ const { log } = createLoggers(options)
23
+ const cwd = options.cwd ?? process.cwd()
24
+ if (!options.taskId || !options.sessionId || !options.revision) {
25
+ return yield* Effect.fail(new Error("Missing required claim arguments"))
26
+ }
27
+ if (
28
+ options.operation === "claim" &&
29
+ (!options.claimant || !options.runner)
30
+ ) {
31
+ return yield* Effect.fail(
32
+ new Error("Claimant and runner identities are required"),
33
+ )
34
+ }
35
+ if (
36
+ options.operation === "finish" &&
37
+ options.outcome !== "done" &&
38
+ options.outcome !== "dropped"
39
+ ) {
40
+ return yield* Effect.fail(
41
+ new Error("Finish outcome must be done or dropped"),
42
+ )
43
+ }
44
+
45
+ const common = {
46
+ taskId: options.taskId,
47
+ ...(options.phaseId ? { phaseId: options.phaseId } : {}),
48
+ sessionId: options.sessionId,
49
+ revision: options.revision,
50
+ }
51
+ const result =
52
+ options.operation === "claim"
53
+ ? yield* claims.claim(
54
+ {
55
+ ...common,
56
+ claimant: options.claimant!,
57
+ runner: options.runner!,
58
+ ...(options.expiresAt ? { expiresAt: options.expiresAt } : {}),
59
+ },
60
+ cwd,
61
+ )
62
+ : options.operation === "release"
63
+ ? yield* claims.release(common, cwd)
64
+ : yield* claims.finish(
65
+ {
66
+ ...common,
67
+ outcome: options.outcome as "done" | "dropped",
68
+ },
69
+ cwd,
70
+ )
71
+
72
+ const { data: _, ...output } = result
73
+ log(
74
+ options.json
75
+ ? JSON.stringify(output, null, 2)
76
+ : `${options.operation === "claim" ? "Claimed" : options.operation === "release" ? "Released" : "Finished"} ${result.target} at revision ${result.revision}`,
77
+ )
78
+ })
79
+
80
+ export const claimHelp = `
81
+ Usage: agency claim <task-id> [phase-id] --claimant <id> --runner <id> --session-id <id> --revision <sha256>
82
+
83
+ Claim an execution unit. Use distinct claimant and runner identities for delegated
84
+ work. --expires-at accepts an optional future ISO-8601 timestamp.
85
+ `
86
+
87
+ export const releaseHelp = `
88
+ Usage: agency release <task-id> [phase-id] --session-id <id> --revision <sha256>
89
+
90
+ Release an execution unit owned by the session.
91
+ `
92
+
93
+ export const finishHelp = `
94
+ Usage: agency finish <task-id> [phase-id] --session-id <id> --revision <sha256> --outcome <done|dropped>
95
+
96
+ Finish an execution unit owned by the session.
97
+ `
@@ -125,7 +125,7 @@ Subcommands:
125
125
  list <task> List task phases
126
126
  show <task> <phase> Show a phase
127
127
  status <task> <phase> <status>
128
- Set open, working, delegated, done, or dropped
128
+ Set open, done, or dropped
129
129
 
130
130
  Create options:
131
131
  --description <text> Short description of the phase
@@ -172,13 +172,13 @@ describe("task and phase command JSON output", () => {
172
172
  runTestEffect(
173
173
  phase({
174
174
  subcommand: "status",
175
- args: ["multi", "first", "delegated"],
175
+ args: ["multi", "first", "done"],
176
176
  cwd: root,
177
177
  json: true,
178
178
  }),
179
179
  ),
180
180
  )
181
- expect(JSON.parse(phaseLogs[0]!).data.status).toBe("delegated")
181
+ expect(JSON.parse(phaseLogs[0]!).data.status).toBe("done")
182
182
 
183
183
  await runTestEffect(
184
184
  task({
@@ -196,13 +196,13 @@ describe("task and phase command JSON output", () => {
196
196
  runTestEffect(
197
197
  task({
198
198
  subcommand: "status",
199
- args: ["single-status", "delegated"],
199
+ args: ["single-status", "done"],
200
200
  cwd: root,
201
201
  json: true,
202
202
  }),
203
203
  ),
204
204
  )
205
- expect(JSON.parse(taskLogs[0]!).data.status).toBe("delegated")
205
+ expect(JSON.parse(taskLogs[0]!).data.status).toBe("done")
206
206
  })
207
207
 
208
208
  test("converts a single-phase task with an explicit first phase ID", async () => {
@@ -269,7 +269,7 @@ Subcommands:
269
269
  create <id> Create a task without prompting
270
270
  list List tasks
271
271
  show <id> Show a task
272
- status <id> <status> Set open, working, delegated, done, or dropped
272
+ status <id> <status> Set open, done, or dropped
273
273
 
274
274
  Create options:
275
275
  --ticket-url <url> External ticket URL (optional)