aitasks 1.3.1 → 1.3.2

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.
Files changed (3) hide show
  1. package/README.md +8 -5
  2. package/dist/index.js +90 -32
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -174,14 +174,17 @@ aitasks init --with-review
174
174
  aitasks init --with-review # safe to re-run; updates DB setting and rewrites agent file
175
175
  ```
176
176
 
177
+ **A task is only complete when its status is `done`.** No other status — verified criteria, `review`, `in_progress` — counts as complete. Agents must reach `done` to consider a task finished.
178
+
177
179
  **How it works:**
178
180
 
179
- 1. Agent completes work and checks all acceptance criteria
181
+ 1. Agent completes work and verifies all acceptance criteria with evidence
180
182
  2. Agent submits for review — task moves to `review` status:
181
183
  ```sh
182
184
  aitasks review TASK-001 --agent $AITASKS_AGENT_ID
183
185
  ```
184
- 3. A separate review sub-agent inspects the implementation and either:
186
+ The command output explicitly instructs the agent to immediately spawn a review sub-agent. The task is **not complete** at this point.
187
+ 3. The agent **immediately spawns a review sub-agent** to inspect the implementation:
185
188
  - **Approves** — moves task to done:
186
189
  ```sh
187
190
  aitasks done TASK-001 --agent review-agent
@@ -190,11 +193,11 @@ aitasks init --with-review # safe to re-run; updates DB setting and rewrites ag
190
193
  ```sh
191
194
  aitasks reject TASK-001 --reason "Missing error handling for 404 case" --agent review-agent
192
195
  ```
193
- 4. If rejected, the agent addresses feedback, re-verifies criteria, and repeats from step 2.
196
+ 4. If rejected, the original agent addresses the feedback, re-verifies criteria, and repeats from step 2.
194
197
 
195
- **Enforcement:** When review is required, `aitasks done` and `aitasks update --status done` both block if the task is not already in `review` status. The gate cannot be bypassed.
198
+ **Enforcement:** `aitasks done` and `aitasks update --status done` both block if the task isn't already in `review` status. The gate cannot be bypassed.
196
199
 
197
- **Board:** Tasks in `review` status appear in the **IN PROGRESS** section with a `◈` magenta indicator so they're visually distinct from actively worked tasks.
200
+ **Board:** Tasks in `review` status appear in the **IN PROGRESS** section with a `◈` magenta indicator so they're visually distinct from actively-worked tasks.
198
201
 
199
202
  ---
200
203
 
package/dist/index.js CHANGED
@@ -1890,7 +1890,7 @@ var require_commander = __commonJS((exports) => {
1890
1890
  var require_package = __commonJS((exports, module) => {
1891
1891
  module.exports = {
1892
1892
  name: "aitasks",
1893
- version: "1.3.1",
1893
+ version: "1.3.2",
1894
1894
  description: "CLI task management tool built for AI agents",
1895
1895
  type: "module",
1896
1896
  bin: {
@@ -29290,7 +29290,12 @@ function getAgentInstructions(version, opts = {}) {
29290
29290
  return `${INSTRUCTIONS_START_MARKER}
29291
29291
 
29292
29292
  ## AITasks \u2014 Agent Task Protocol (v${version})
29293
-
29293
+ ${reviewRequired ? `
29294
+ > \u26A0\uFE0F **REVIEW ENFORCEMENT IS ENABLED ON THIS PROJECT**
29295
+ > You cannot mark any task done directly. Every task requires a review step:
29296
+ > \`aitasks review\` \u2192 spawn review sub-agent \u2192 \`aitasks done\`
29297
+ > Tasks are only complete when their status is \`done\`. All other statuses mean work is still in progress.
29298
+ ` : ""}
29294
29299
  You have access to the \`aitasks\` CLI. This is your single source of truth for
29295
29300
  all work in this project. Follow this protocol without exception.
29296
29301
 
@@ -29347,7 +29352,7 @@ This finds the best task, claims it, and starts it in one command.
29347
29352
  aitasks start TASK-001 --agent $AITASKS_AGENT_ID
29348
29353
  \`\`\`
29349
29354
 
29350
- **Bulk operations:** You can claim, start, review, or complete multiple tasks at once:
29355
+ **Bulk operations:** You can claim, start, or complete multiple tasks at once:
29351
29356
  \`\`\`bash
29352
29357
  aitasks claim TASK-001 TASK-002 TASK-003 --agent $AITASKS_AGENT_ID
29353
29358
  aitasks start TASK-001 TASK-002 --agent $AITASKS_AGENT_ID
@@ -29395,6 +29400,8 @@ aitasks deps TASK-001 # Shows what this task is blocked by and what it blocks
29395
29400
 
29396
29401
  ### Completing a Task${reviewRequired ? " \u26A0\uFE0F REVIEW REQUIRED" : ""}
29397
29402
 
29403
+ > **A task is only complete when its status is \`done\`. Verified criteria, implementation notes, and \`review\` status do NOT mean the task is done. You have not finished a task until \`aitasks done\` has succeeded.**
29404
+
29398
29405
  You MUST verify every acceptance criterion before marking done.
29399
29406
 
29400
29407
  1. View all criteria:
@@ -29414,7 +29421,8 @@ ${reviewRequired ? `3. Submit for review \u2014 you CANNOT mark done directly:
29414
29421
  aitasks review TASK-001 --agent $AITASKS_AGENT_ID
29415
29422
  \`\`\`
29416
29423
 
29417
- 4. Spawn a review sub-agent to inspect the implementation and either:
29424
+ 4. **IMMEDIATELY spawn a review sub-agent** \u2014 do NOT move to other tasks until review resolves.
29425
+ The task is still incomplete. The review sub-agent must either:
29418
29426
  - **Approve** (moves task to done):
29419
29427
  \`\`\`bash
29420
29428
  aitasks done TASK-001 --agent <review-agent-id>
@@ -29424,15 +29432,14 @@ ${reviewRequired ? `3. Submit for review \u2014 you CANNOT mark done directly:
29424
29432
  aitasks reject TASK-001 --reason "<specific feedback>" --agent <review-agent-id>
29425
29433
  \`\`\`
29426
29434
 
29427
- 5. If rejected: address the feedback, re-check criteria, and repeat from step 3.` : `3. Mark done (will FAIL if any criterion is unchecked):
29435
+ 5. If rejected: address the feedback, re-check criteria, and repeat from step 3.
29436
+
29437
+ > The task is only done when \`aitasks done\` completes successfully. \`review\` status means awaiting approval \u2014 it is not done.` : `3. Mark done (will FAIL if any criterion is unchecked):
29428
29438
  \`\`\`bash
29429
29439
  aitasks done TASK-001 --agent $AITASKS_AGENT_ID
29430
29440
  \`\`\`
29431
29441
 
29432
- If review is needed:
29433
- \`\`\`bash
29434
- aitasks review TASK-001 --agent $AITASKS_AGENT_ID
29435
- \`\`\``}
29442
+ > The task is only done when \`aitasks done\` completes successfully. Do not treat a task as finished until you see the done confirmation.`}
29436
29443
 
29437
29444
  ---
29438
29445
 
@@ -29446,8 +29453,8 @@ aitasks undo TASK-001 # Undoes the last action (claim, start, done, check, no
29446
29453
  Undoable actions:
29447
29454
  - claimed \u2192 unclaims the task
29448
29455
  - started \u2192 reverts to ready status
29449
- - completed \u2192 reverts to in_progress
29450
- - review_requested \u2192 reverts to in_progress
29456
+ - completed \u2192 reverts to in_progress${reviewRequired ? `
29457
+ - review_requested \u2192 reverts to in_progress` : ""}
29451
29458
  - criterion_checked \u2192 removes the verification
29452
29459
  - note_added \u2192 removes the implementation note
29453
29460
 
@@ -29464,14 +29471,15 @@ aitasks unclaim TASK-001 --agent $AITASKS_AGENT_ID --reason "Blocked on missing
29464
29471
 
29465
29472
  ### Rules
29466
29473
 
29467
- 1. Never mark a task done without checking EVERY acceptance criterion with evidence.
29468
- 2. Never start a task you haven't claimed.
29469
- 3. Never silently abandon a task \u2014 always unclaim with a reason.
29470
- 4. Add implementation notes continuously, not just at the end.
29471
- 5. If a task needs splitting, create subtasks BEFORE marking parent done.
29472
- 6. Your evidence strings must be concrete and verifiable \u2014 not vague affirmations.
29473
- 7. Always provide --desc and at least one --ac when creating a task. Both are required.${reviewRequired ? `
29474
- 8. NEVER move a task to done directly. Always submit for review first with \`aitasks review\`, then spawn a review sub-agent to approve or reject. Tasks cannot be marked done without a passing review.` : ""}
29474
+ 1. **A task is only complete when its status is \`done\`.** No other status \u2014 not criteria-verified, not \`review\`, not \`in_progress\` \u2014 counts as complete. Your work on a task is not finished until \`aitasks done\` succeeds.
29475
+ 2. Never mark a task done without checking EVERY acceptance criterion with evidence.
29476
+ 3. Never start a task you haven't claimed.
29477
+ 4. Never silently abandon a task \u2014 always unclaim with a reason.
29478
+ 5. Add implementation notes continuously, not just at the end.
29479
+ 6. If a task needs splitting, create subtasks BEFORE marking parent done.
29480
+ 7. Your evidence strings must be concrete and verifiable \u2014 not vague affirmations.
29481
+ 8. Always provide --desc and at least one --ac when creating a task. Both are required.${reviewRequired ? `
29482
+ 9. NEVER move a task to done directly. Always submit for review first with \`aitasks review\`, then IMMEDIATELY spawn a review sub-agent. Do NOT work on other tasks until the review resolves. A task is only complete when its status is \`done\`.` : ""}
29475
29483
 
29476
29484
  ---
29477
29485
 
@@ -29488,8 +29496,9 @@ aitasks claim <id...> --agent <id> Claim task(s) - supports patterns li
29488
29496
  aitasks start <id...> --agent <id> Begin work on task(s)
29489
29497
  aitasks note <id> <text> --agent <id> Add implementation note
29490
29498
  aitasks check <id> <n> --evidence <text> Verify acceptance criterion n
29491
- aitasks done <id...> --agent <id> Mark task(s) complete
29492
- aitasks review <id...> --agent <id> Request human review
29499
+ aitasks done <id...> --agent <id> Mark task(s) complete (only valid completion)${reviewRequired ? `
29500
+ aitasks review <id...> --agent <id> Submit for review \u2014 then spawn review sub-agent immediately
29501
+ aitasks reject <id> --reason <r> Reject review \u2014 sends back to in_progress` : ""}
29493
29502
  aitasks block <id> --on <id,...> Mark as blocked
29494
29503
  aitasks unblock <id> --from <id> Remove a blocker
29495
29504
  aitasks unclaim <id> --agent <id> Release task
@@ -29583,7 +29592,19 @@ function appendToSpecificFile(filePath, version, reviewRequired = false) {
29583
29592
  }
29584
29593
 
29585
29594
  // src/commands/init.ts
29586
- var initCommand = new Command("init").description("Initialize AITasks in the current project").option("--skip-agent-file", "Skip injecting agent instructions into CLAUDE.md/AGENTS.md/GEMINI.md").option("--with-review", "Enforce review gate: agents cannot mark tasks done without a passing review").action(async (opts) => {
29595
+ var initCommand = new Command("init").description("Initialize AITasks in the current project").option("--skip-agent-file", "Skip injecting agent instructions into CLAUDE.md/AGENTS.md/GEMINI.md").option("--with-review", "Enforce review gate: agents cannot mark tasks done without a passing review").addHelpText("after", `
29596
+ Examples:
29597
+ $ aitasks init
29598
+ Initialize in current directory, inject agent instructions into CLAUDE.md/AGENTS.md.
29599
+
29600
+ $ aitasks init --with-review
29601
+ Same as above, but enable the review enforcement gate. Agents must run
29602
+ \`aitasks review\` and spawn a review sub-agent before any task can be
29603
+ marked done. Running this on an existing project also updates the agent
29604
+ instructions file with the review workflow.
29605
+
29606
+ $ aitasks init --skip-agent-file
29607
+ Initialize without touching any CLAUDE.md / AGENTS.md file.`).action(async (opts) => {
29587
29608
  const root = findProjectRoot();
29588
29609
  const taskieDir = join5(root, ".aitasks");
29589
29610
  if (existsSync5(join5(taskieDir, "db.sqlite"))) {
@@ -41082,6 +41103,7 @@ var startCommand = new Command("start").description("Start working on task(s) (t
41082
41103
  console.error("");
41083
41104
  process.exit(1);
41084
41105
  }
41106
+ const reviewRequired = getReviewRequired();
41085
41107
  const results = [];
41086
41108
  let allSuccess = true;
41087
41109
  for (const taskId of resolvedIds) {
@@ -41095,18 +41117,21 @@ var startCommand = new Command("start").description("Start working on task(s) (t
41095
41117
  }
41096
41118
  continue;
41097
41119
  }
41098
- results.push({ id: taskId, success: true });
41120
+ results.push({ id: taskId, success: true, review_required: reviewRequired });
41099
41121
  if (!json) {
41100
41122
  console.log("");
41101
41123
  console.log(source_default.green(" \u25B6") + ` Started ${source_default.bold(task.id)} \u2014 ${task.title}`);
41102
41124
  if (task.acceptance_criteria.length > 0) {
41103
41125
  console.log(source_default.dim(` ${task.acceptance_criteria.length} acceptance criteria to verify before done`));
41104
41126
  }
41127
+ if (reviewRequired) {
41128
+ console.log(source_default.yellow(" \u26A0 ") + source_default.bold("Review required.") + source_default.dim(` When done: aitasks review ${task.id} \u2192 spawn review sub-agent \u2192 aitasks done ${task.id}`));
41129
+ }
41105
41130
  console.log(source_default.dim(` Add notes as you go: aitasks note ${task.id} "<your note>"`));
41106
41131
  }
41107
41132
  }
41108
41133
  if (json) {
41109
- return jsonOut(allSuccess, { results });
41134
+ return jsonOut(allSuccess, { results, review_required: reviewRequired });
41110
41135
  }
41111
41136
  console.log("");
41112
41137
  if (!allSuccess) {
@@ -41278,6 +41303,7 @@ var reviewCommand = new Command("review").description("Request human review for
41278
41303
  console.error("");
41279
41304
  process.exit(1);
41280
41305
  }
41306
+ const reviewRequired = getReviewRequired();
41281
41307
  const results = [];
41282
41308
  let allSuccess = true;
41283
41309
  for (const taskId of resolvedIds) {
@@ -41291,13 +41317,37 @@ var reviewCommand = new Command("review").description("Request human review for
41291
41317
  }
41292
41318
  continue;
41293
41319
  }
41294
- results.push({ id: taskId, success: true });
41320
+ if (reviewRequired) {
41321
+ results.push({
41322
+ id: taskId,
41323
+ success: true,
41324
+ status: "review",
41325
+ next_action: "REQUIRED: Spawn a review sub-agent immediately. This task is NOT complete until the review agent approves it.",
41326
+ review_commands: {
41327
+ approve: `aitasks done ${taskId} --agent <review-agent-id>`,
41328
+ reject: `aitasks reject ${taskId} --reason "<specific feedback>" --agent <review-agent-id>`
41329
+ }
41330
+ });
41331
+ } else {
41332
+ results.push({ id: taskId, success: true, status: "review" });
41333
+ }
41295
41334
  if (!json) {
41296
41335
  console.log("");
41297
41336
  console.log(source_default.magenta(" \u25C8") + ` ${source_default.bold(task.id)} submitted for review`);
41298
- console.log(source_default.dim(` Spawn a review sub-agent to inspect the implementation.`));
41299
- console.log(source_default.dim(` Approve: aitasks done ${task.id} --agent <review-agent-id>`));
41300
- console.log(source_default.dim(` Reject: aitasks reject ${task.id} --reason "<feedback>"`));
41337
+ if (reviewRequired) {
41338
+ console.log(source_default.yellow(" \u26A0 ") + source_default.bold(" This task is NOT complete yet."));
41339
+ console.log("");
41340
+ console.log(` You MUST ${source_default.bold("immediately spawn a review sub-agent")} to inspect the implementation.`);
41341
+ console.log(source_default.dim(" The task remains incomplete until the review agent moves it to done."));
41342
+ console.log("");
41343
+ console.log(source_default.dim(" Review sub-agent steps:"));
41344
+ console.log(source_default.dim(` 1. Examine implementation and verify all acceptance criteria`));
41345
+ console.log(source_default.dim(` 2. Approve: aitasks done ${task.id} --agent <review-agent-id>`));
41346
+ console.log(source_default.dim(` Reject: aitasks reject ${task.id} --reason "<feedback>" --agent <review-agent-id>`));
41347
+ } else {
41348
+ console.log(source_default.dim(` Approve: aitasks done ${task.id} --agent <review-agent-id>`));
41349
+ console.log(source_default.dim(` Reject: aitasks reject ${task.id} --reason "<feedback>"`));
41350
+ }
41301
41351
  }
41302
41352
  }
41303
41353
  if (json) {
@@ -41378,9 +41428,10 @@ var nextCommand = new Command("next").description("Show the next best task to wo
41378
41428
  }
41379
41429
  const aid = opts.claim ? requireAgentId(opts.agent, "next --claim") : agentId(opts.agent) ?? undefined;
41380
41430
  const task = getNextTask(aid);
41431
+ const reviewRequired = getReviewRequired();
41381
41432
  if (!task) {
41382
41433
  if (json)
41383
- return jsonOut(true, null);
41434
+ return jsonOut(true, { task: null, review_required: reviewRequired });
41384
41435
  console.log("");
41385
41436
  console.log(source_default.dim(" No ready tasks available. Check backlog with: aitasks list"));
41386
41437
  console.log("");
@@ -41403,17 +41454,24 @@ var nextCommand = new Command("next").description("Show the next best task to wo
41403
41454
  }
41404
41455
  const updatedTask = startResult.task;
41405
41456
  if (json)
41406
- return jsonOut(true, updatedTask);
41457
+ return jsonOut(true, { ...updatedTask, review_required: reviewRequired });
41407
41458
  console.log("");
41408
41459
  console.log(source_default.green(" \u2713") + ` Claimed and started ${source_default.bold(updatedTask.id)}: ${updatedTask.title}`);
41409
41460
  console.log(source_default.dim(` Priority: ${updatedTask.priority} \xB7 Type: ${updatedTask.type}`));
41410
41461
  console.log(source_default.dim(` Agent: ${aid}`));
41462
+ if (reviewRequired) {
41463
+ console.log("");
41464
+ console.log(source_default.yellow(" \u26A0 ") + source_default.bold(" Review enforcement is ON.") + source_default.dim(" When done: aitasks review \u2192 spawn review sub-agent \u2192 aitasks done"));
41465
+ }
41411
41466
  console.log("");
41412
41467
  return;
41413
41468
  }
41414
41469
  if (json)
41415
- return jsonOut(true, task);
41470
+ return jsonOut(true, { ...task, review_required: reviewRequired });
41416
41471
  console.log(renderTaskDetail(task));
41472
+ if (reviewRequired) {
41473
+ console.log(source_default.yellow(" \u26A0 ") + source_default.bold(" Review enforcement is ON.") + source_default.dim(" When done: aitasks review \u2192 spawn review sub-agent \u2192 aitasks done"));
41474
+ }
41417
41475
  console.log(source_default.dim(` Claim it: aitasks claim ${task.id} --agent <your-id>`));
41418
41476
  console.log("");
41419
41477
  });
@@ -43222,4 +43280,4 @@ program2.parseAsync(process.argv).catch((err) => {
43222
43280
  process.exit(1);
43223
43281
  });
43224
43282
 
43225
- //# debugId=B0EAB2DE4FE47CF564756E2164756E21
43283
+ //# debugId=3AB57D11F115EBBB64756E2164756E21
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aitasks",
3
- "version": "1.3.1",
3
+ "version": "1.3.2",
4
4
  "description": "CLI task management tool built for AI agents",
5
5
  "type": "module",
6
6
  "bin": {