aitasks 1.4.5 → 1.4.6
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 +61 -1
- package/dist/index.js +86 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -67,6 +67,21 @@ export AITASKS_JSON=true
|
|
|
67
67
|
|
|
68
68
|
---
|
|
69
69
|
|
|
70
|
+
## Global Options
|
|
71
|
+
|
|
72
|
+
| Option | Description |
|
|
73
|
+
|---|---|
|
|
74
|
+
| `-C, --dir <path>` | Run as if `aitasks` were started in `<path>` instead of the current directory |
|
|
75
|
+
| `--json` | Output machine-readable JSON (available on most commands) |
|
|
76
|
+
| `--version` | Print the installed version |
|
|
77
|
+
| `--help` | Show help for any command, e.g. `aitasks update --help` |
|
|
78
|
+
|
|
79
|
+
```sh
|
|
80
|
+
aitasks -C /path/to/project board
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
70
85
|
## Commands
|
|
71
86
|
|
|
72
87
|
### Setup
|
|
@@ -75,6 +90,7 @@ export AITASKS_JSON=true
|
|
|
75
90
|
|---|---|
|
|
76
91
|
| `aitasks init` | Initialize a task database in the current project |
|
|
77
92
|
| `aitasks init --with-review` | Initialize with review enforcement (agents cannot mark done without a passing review) |
|
|
93
|
+
| `aitasks init --update` | Refresh the agent instructions block in an existing CLAUDE.md / AGENTS.md / GEMINI.md to the latest version |
|
|
78
94
|
| `aitasks onboard` | Print or inject agent protocol instructions into CLAUDE.md / AGENTS.md |
|
|
79
95
|
|
|
80
96
|
### Task Discovery
|
|
@@ -82,7 +98,7 @@ export AITASKS_JSON=true
|
|
|
82
98
|
| Command | Description |
|
|
83
99
|
|---|---|
|
|
84
100
|
| `aitasks list` | List all tasks, sorted by priority |
|
|
85
|
-
| `aitasks list --status ready` | Filter by status (`ready`, `in_progress`, `blocked`, `review`, `done`) |
|
|
101
|
+
| `aitasks list --status ready` | Filter by status (`backlog`, `ready`, `in_progress`, `blocked`, `review`, `done`) |
|
|
86
102
|
| `aitasks next` | Show the highest-priority unblocked ready task |
|
|
87
103
|
| `aitasks next --claim --agent <id>` | Auto-claim and start the best task |
|
|
88
104
|
| `aitasks show <id>` | Full detail on a specific task (includes time tracking) |
|
|
@@ -99,6 +115,7 @@ export AITASKS_JSON=true
|
|
|
99
115
|
| `aitasks start <id...> --agent <id>` | Begin active work on task(s) |
|
|
100
116
|
| `aitasks note <id> <text>` | Add an implementation note |
|
|
101
117
|
| `aitasks check <id> <n> --evidence <text>` | Verify acceptance criterion n |
|
|
118
|
+
| `aitasks update <id>` | Update task fields (title, description, priority, type, status, acceptance criteria) — see [`update` Flags](#update-flags) |
|
|
102
119
|
| `aitasks done <id...> --agent <id>` | Mark task(s) complete (all criteria must be verified; must be in `review` status if enforcement is on) |
|
|
103
120
|
| `aitasks review <id...> --agent <id>` | Submit task(s) for review (moves to `review` status) |
|
|
104
121
|
| `aitasks reject <id> --reason <text>` | Reject a task in review, send it back to `in_progress` with feedback |
|
|
@@ -148,6 +165,41 @@ aitasks create \
|
|
|
148
165
|
|
|
149
166
|
---
|
|
150
167
|
|
|
168
|
+
## `update` Flags
|
|
169
|
+
|
|
170
|
+
Change any field on an existing task:
|
|
171
|
+
|
|
172
|
+
```sh
|
|
173
|
+
aitasks update TASK-001 \
|
|
174
|
+
--title "New title" \ # Replace the title
|
|
175
|
+
--desc "New description" \ # Replace the description
|
|
176
|
+
--priority high \ # critical | high | medium | low
|
|
177
|
+
--type bug \ # feature | bug | chore | spike
|
|
178
|
+
--status ready # Manually override status (use with care)
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### Editing acceptance criteria
|
|
182
|
+
|
|
183
|
+
Criterion indices are **0-based**, matching what `aitasks show` and `aitasks check` display. Use **only one** of these flags per invocation:
|
|
184
|
+
|
|
185
|
+
| Flag | Effect |
|
|
186
|
+
|---|---|
|
|
187
|
+
| `--ac <text>` | **Append** a new criterion (repeatable). Does *not* replace existing ones — re-passing an existing criterion duplicates it. |
|
|
188
|
+
| `--set-ac <index>=<text>` | Replace just the criterion at `<index>` in place. |
|
|
189
|
+
| `--remove-ac <index>` | Delete the criterion at `<index>`. |
|
|
190
|
+
| `--replace-ac <list>` | Overwrite the **entire** list (newline-separated). |
|
|
191
|
+
|
|
192
|
+
```sh
|
|
193
|
+
aitasks update TASK-001 --ac "New criterion to append"
|
|
194
|
+
aitasks update TASK-001 --set-ac 1="Returns 404 with a JSON error body"
|
|
195
|
+
aitasks update TASK-001 --remove-ac 2
|
|
196
|
+
aitasks update TASK-001 --replace-ac $'First criterion\nSecond criterion\nThird criterion'
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
> **Re-verify after editing.** `--set-ac` clears any prior verification of that criterion (since the wording changed), and `--remove-ac` re-indexes the remaining verifications. Run `aitasks check` again for affected criteria before marking the task done.
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
151
203
|
## Agent Protocol
|
|
152
204
|
|
|
153
205
|
When you run `aitasks init`, it automatically injects a full agent protocol into `CLAUDE.md`, `AGENTS.md`, or `GEMINI.md` (whichever exists, or creates `AGENTS.md`). This tells the AI agent exactly how to use `aitasks`.
|
|
@@ -163,6 +215,14 @@ aitasks onboard --json # output as JSON string
|
|
|
163
215
|
|
|
164
216
|
The injected instructions automatically adapt to the project's review enforcement setting — if `--with-review` is enabled, agents receive the full review workflow (with `aitasks review`, sub-agent approval, and `aitasks reject`) instead of the standard completion flow.
|
|
165
217
|
|
|
218
|
+
**Updating after an upgrade:** Re-running `aitasks init` on a project whose agent file already contains instructions leaves them untouched (and prints a hint). To pull the latest protocol after upgrading `aitasks`, run:
|
|
219
|
+
|
|
220
|
+
```sh
|
|
221
|
+
aitasks init --update
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
This replaces only the block between the `<!-- aitasks:instructions -->` markers in place — the rest of your `CLAUDE.md` / `AGENTS.md` is preserved.
|
|
225
|
+
|
|
166
226
|
---
|
|
167
227
|
|
|
168
228
|
## Review Enforcement
|
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.4.
|
|
1893
|
+
version: "1.4.6",
|
|
1894
1894
|
description: "CLI task management tool built for AI agents",
|
|
1895
1895
|
type: "module",
|
|
1896
1896
|
bin: {
|
|
@@ -29402,6 +29402,18 @@ Creating subtasks:
|
|
|
29402
29402
|
aitasks create --title "Write unit tests for auth" --desc "Add unit tests covering all auth edge cases" --ac "All tests pass" --ac "Coverage \u2265 90%" --parent TASK-001 --priority high --type chore --agent $AITASKS_AGENT_ID
|
|
29403
29403
|
\`\`\`
|
|
29404
29404
|
|
|
29405
|
+
Editing acceptance criteria (if the requirements change or were worded wrong):
|
|
29406
|
+
\`\`\`bash
|
|
29407
|
+
aitasks update TASK-001 --ac "A brand-new criterion to append" # add one
|
|
29408
|
+
aitasks update TASK-001 --set-ac 1="Returns 404 with a JSON error body" # fix criterion #1 in place
|
|
29409
|
+
aitasks update TASK-001 --remove-ac 2 # delete criterion #2
|
|
29410
|
+
aitasks update TASK-001 --replace-ac $'first\\nsecond\\nthird' # replace the whole list
|
|
29411
|
+
\`\`\`
|
|
29412
|
+
Indices are 0-based (matching \`aitasks show\` and \`aitasks check\`). Use exactly one of these
|
|
29413
|
+
flags per call. \`--ac\` only APPENDS \u2014 re-passing existing criteria duplicates them; use
|
|
29414
|
+
\`--set-ac\` to correct one criterion or \`--replace-ac\` to rewrite all of them. After
|
|
29415
|
+
\`--set-ac\`, re-run \`aitasks check\` for that index since editing the wording clears its prior verification.
|
|
29416
|
+
|
|
29405
29417
|
If you discover your task is blocked by something:
|
|
29406
29418
|
\`\`\`bash
|
|
29407
29419
|
aitasks block TASK-001 --on TASK-002,TASK-003
|
|
@@ -29540,7 +29552,11 @@ aitasks show <id> Full task detail (includes time trac
|
|
|
29540
29552
|
aitasks search <query> Search titles, descriptions, notes
|
|
29541
29553
|
aitasks deps <id> Show dependency tree
|
|
29542
29554
|
aitasks create --title <t> --desc <d> --ac <c> [--ac <c> ...] --agent <id> Create a task
|
|
29543
|
-
aitasks update <id> [--status|--priority|--title|--desc|--
|
|
29555
|
+
aitasks update <id> [--status|--priority|--title|--desc|--type] Update task fields
|
|
29556
|
+
aitasks update <id> --ac <text> Append a new acceptance criterion
|
|
29557
|
+
aitasks update <id> --set-ac <n>=<text> Replace a single criterion at index n (0-based)
|
|
29558
|
+
aitasks update <id> --remove-ac <n> Remove a single criterion at index n (0-based)
|
|
29559
|
+
aitasks update <id> --replace-ac <list> Replace ALL criteria (newline-separated)
|
|
29544
29560
|
aitasks claim <id...> --agent <id> Claim task(s) - supports patterns like TASK-0*
|
|
29545
29561
|
aitasks start <id...> --agent <id> Begin work on task(s)
|
|
29546
29562
|
aitasks note <id> <text> --agent <id> Add implementation note
|
|
@@ -29587,7 +29603,7 @@ function injectOrCreateAgentFile(projectRoot, version, reviewRequired = false, f
|
|
|
29587
29603
|
return { filePath: existing, action: "skipped" };
|
|
29588
29604
|
const replaced = replaceInstructionsBlock(content, instructions);
|
|
29589
29605
|
writeFileSync2(existing, replaced, "utf8");
|
|
29590
|
-
return { filePath: existing, action: "
|
|
29606
|
+
return { filePath: existing, action: "updated" };
|
|
29591
29607
|
}
|
|
29592
29608
|
const separator = content.endsWith(`
|
|
29593
29609
|
`) ? `
|
|
@@ -29678,7 +29694,7 @@ function getVersion() {
|
|
|
29678
29694
|
}
|
|
29679
29695
|
|
|
29680
29696
|
// src/commands/init.ts
|
|
29681
|
-
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", `
|
|
29697
|
+
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").option("--update", "Refresh the agent instructions block in an existing CLAUDE.md/AGENTS.md/GEMINI.md to the latest version").addHelpText("after", `
|
|
29682
29698
|
Examples:
|
|
29683
29699
|
$ aitasks init
|
|
29684
29700
|
Initialize in current directory, inject agent instructions into CLAUDE.md/AGENTS.md.
|
|
@@ -29689,6 +29705,11 @@ Examples:
|
|
|
29689
29705
|
marked done. Running this on an existing project also updates the agent
|
|
29690
29706
|
instructions file with the review workflow.
|
|
29691
29707
|
|
|
29708
|
+
$ aitasks init --update
|
|
29709
|
+
Re-inject the latest agent instructions, replacing the existing block
|
|
29710
|
+
between the AITasks markers in place. The rest of the file is left
|
|
29711
|
+
untouched. Use after upgrading aitasks to pull new protocol docs.
|
|
29712
|
+
|
|
29692
29713
|
$ aitasks init --skip-agent-file
|
|
29693
29714
|
Initialize without touching any CLAUDE.md / AGENTS.md file.`).action(async (opts) => {
|
|
29694
29715
|
const root = findProjectRoot();
|
|
@@ -29701,7 +29722,8 @@ Examples:
|
|
|
29701
29722
|
console.log(source_default.green(" \u2713") + " Review enforcement enabled.");
|
|
29702
29723
|
}
|
|
29703
29724
|
if (!opts.skipAgentFile) {
|
|
29704
|
-
const
|
|
29725
|
+
const force = !!opts.withReview || !!opts.update;
|
|
29726
|
+
const result = injectOrCreateAgentFile(root, getVersion(), !!opts.withReview, force);
|
|
29705
29727
|
printAgentFileResult(result);
|
|
29706
29728
|
}
|
|
29707
29729
|
return;
|
|
@@ -29722,7 +29744,7 @@ Examples:
|
|
|
29722
29744
|
}
|
|
29723
29745
|
console.log("");
|
|
29724
29746
|
if (!opts.skipAgentFile) {
|
|
29725
|
-
const result = injectOrCreateAgentFile(root, getVersion(), !!opts.withReview);
|
|
29747
|
+
const result = injectOrCreateAgentFile(root, getVersion(), !!opts.withReview, !!opts.update);
|
|
29726
29748
|
printAgentFileResult(result);
|
|
29727
29749
|
}
|
|
29728
29750
|
console.log(source_default.dim(" Run `aitasks create` to add your first task."));
|
|
@@ -29737,8 +29759,12 @@ function printAgentFileResult(result) {
|
|
|
29737
29759
|
case "appended":
|
|
29738
29760
|
console.log(source_default.green(" \u2713") + ` Appended agent instructions to ${source_default.bold(rel)}`);
|
|
29739
29761
|
break;
|
|
29762
|
+
case "updated":
|
|
29763
|
+
console.log(source_default.green(" \u2713") + ` Updated agent instructions in ${source_default.bold(rel)}`);
|
|
29764
|
+
break;
|
|
29740
29765
|
case "skipped":
|
|
29741
29766
|
console.log(source_default.dim(` \u2500 ${rel} already contains AITasks instructions`));
|
|
29767
|
+
console.log(source_default.dim(` Run \`aitasks init --update\` to refresh them to the latest version.`));
|
|
29742
29768
|
break;
|
|
29743
29769
|
}
|
|
29744
29770
|
console.log("");
|
|
@@ -41672,7 +41698,20 @@ var nextCommand = new Command("next").description("Show the next best task to wo
|
|
|
41672
41698
|
});
|
|
41673
41699
|
|
|
41674
41700
|
// src/commands/update.ts
|
|
41675
|
-
var updateCommand = new Command("update").description("Update task fields").argument("<taskId>", "Task ID").option("-t, --title <title>", "New title").option("-d, --desc <description>", "New description").option("-a, --ac <criterion>", "Add an acceptance criterion (repeatable)", collect2, []).option("--replace-ac <criteria>", "Replace ALL acceptance criteria (newline-separated)").option("-p, --priority <priority>", "New priority: critical|high|medium|low").option("--type <type>", "New type: feature|bug|chore|spike").option("--status <status>", "Manually set status (use with care)").option("--json", "Output as JSON").
|
|
41701
|
+
var updateCommand = new Command("update").description("Update task fields").argument("<taskId>", "Task ID").option("-t, --title <title>", "New title").option("-d, --desc <description>", "New description").option("-a, --ac <criterion>", "Add an acceptance criterion (repeatable)", collect2, []).option("--replace-ac <criteria>", "Replace ALL acceptance criteria (newline-separated)").option("--set-ac <index=text>", 'Replace a single acceptance criterion by 0-based index, e.g. --set-ac 1="New text"').option("--remove-ac <index>", "Remove a single acceptance criterion by 0-based index").option("-p, --priority <priority>", "New priority: critical|high|medium|low").option("--type <type>", "New type: feature|bug|chore|spike").option("--status <status>", "Manually set status (use with care)").option("--json", "Output as JSON").addHelpText("after", `
|
|
41702
|
+
Acceptance criteria editing:
|
|
41703
|
+
--ac <text> Append a new criterion (repeatable). Does NOT replace existing ones.
|
|
41704
|
+
--set-ac <index=text> Replace just the criterion at <index> (0-based). Re-verify it afterward \u2014
|
|
41705
|
+
any prior verification of that criterion is cleared since the wording changed.
|
|
41706
|
+
--remove-ac <index> Delete the criterion at <index> (0-based). Verifications are re-indexed.
|
|
41707
|
+
--replace-ac <list> Overwrite the entire list (newline-separated).
|
|
41708
|
+
|
|
41709
|
+
Only one acceptance-criteria mode may be used per invocation.
|
|
41710
|
+
|
|
41711
|
+
Examples:
|
|
41712
|
+
$ aitasks update TASK-001 --set-ac 1="Returns 404 with a JSON error body"
|
|
41713
|
+
$ aitasks update TASK-001 --remove-ac 2
|
|
41714
|
+
$ aitasks update TASK-001 --ac "New criterion to append"`).action((taskId, opts) => {
|
|
41676
41715
|
requireInitialized();
|
|
41677
41716
|
const json = isJsonMode(opts.json);
|
|
41678
41717
|
const id = taskId.toUpperCase();
|
|
@@ -41690,11 +41729,39 @@ var updateCommand = new Command("update").description("Update task fields").argu
|
|
|
41690
41729
|
changes.type = opts.type;
|
|
41691
41730
|
if (opts.status)
|
|
41692
41731
|
changes.status = opts.status;
|
|
41693
|
-
|
|
41732
|
+
const acModes = [
|
|
41733
|
+
opts.ac.length > 0,
|
|
41734
|
+
opts.replaceAc !== undefined,
|
|
41735
|
+
opts.setAc !== undefined,
|
|
41736
|
+
opts.removeAc !== undefined
|
|
41737
|
+
].filter(Boolean).length;
|
|
41738
|
+
if (acModes > 1) {
|
|
41739
|
+
exitError("Use only one of --ac, --replace-ac, --set-ac, or --remove-ac per invocation.", json);
|
|
41740
|
+
}
|
|
41741
|
+
if (opts.replaceAc !== undefined) {
|
|
41694
41742
|
changes.acceptance_criteria = opts.replaceAc.split(`
|
|
41695
41743
|
`).map((s) => s.trim()).filter(Boolean);
|
|
41696
41744
|
} else if (opts.ac.length > 0) {
|
|
41697
41745
|
changes.acceptance_criteria = [...task.acceptance_criteria, ...opts.ac];
|
|
41746
|
+
} else if (opts.setAc !== undefined) {
|
|
41747
|
+
const eq = opts.setAc.indexOf("=");
|
|
41748
|
+
if (eq < 0) {
|
|
41749
|
+
exitError('--set-ac requires the format <index>=<text>, e.g. --set-ac 1="New criterion".', json);
|
|
41750
|
+
}
|
|
41751
|
+
const index = parseCriterionIndex(opts.setAc.slice(0, eq), task.acceptance_criteria.length, json);
|
|
41752
|
+
const text = opts.setAc.slice(eq + 1).trim();
|
|
41753
|
+
if (!text)
|
|
41754
|
+
exitError("--set-ac text cannot be empty.", json);
|
|
41755
|
+
const criteria = [...task.acceptance_criteria];
|
|
41756
|
+
criteria[index] = text;
|
|
41757
|
+
changes.acceptance_criteria = criteria;
|
|
41758
|
+
if (task.test_results.some((r2) => r2.index === index)) {
|
|
41759
|
+
changes.test_results = task.test_results.filter((r2) => r2.index !== index);
|
|
41760
|
+
}
|
|
41761
|
+
} else if (opts.removeAc !== undefined) {
|
|
41762
|
+
const index = parseCriterionIndex(opts.removeAc, task.acceptance_criteria.length, json);
|
|
41763
|
+
changes.acceptance_criteria = task.acceptance_criteria.filter((_2, i) => i !== index);
|
|
41764
|
+
changes.test_results = task.test_results.filter((r2) => r2.index !== index).map((r2) => r2.index > index ? { ...r2, index: r2.index - 1 } : r2);
|
|
41698
41765
|
}
|
|
41699
41766
|
if (Object.keys(changes).length === 0) {
|
|
41700
41767
|
exitError("No changes specified. Use --help to see available options.", json);
|
|
@@ -41716,6 +41783,16 @@ function collect2(val, acc) {
|
|
|
41716
41783
|
acc.push(val);
|
|
41717
41784
|
return acc;
|
|
41718
41785
|
}
|
|
41786
|
+
function parseCriterionIndex(raw, total, json) {
|
|
41787
|
+
const index = parseInt(raw.trim(), 10);
|
|
41788
|
+
if (isNaN(index) || index < 0) {
|
|
41789
|
+
exitError(`Invalid criterion index "${raw.trim()}". Use a non-negative integer: 0, 1, 2, \u2026`, json);
|
|
41790
|
+
}
|
|
41791
|
+
if (index >= total) {
|
|
41792
|
+
exitError(`Index ${index} out of range \u2014 task has ${total} criteria (0-based, so valid range is 0\u2013${total - 1}).`, json);
|
|
41793
|
+
}
|
|
41794
|
+
return index;
|
|
41795
|
+
}
|
|
41719
41796
|
|
|
41720
41797
|
// src/display/board.tsx
|
|
41721
41798
|
var import_react29 = __toESM(require_react(), 1);
|
|
@@ -43533,4 +43610,4 @@ program2.parseAsync(process.argv).catch((err) => {
|
|
|
43533
43610
|
process.exit(1);
|
|
43534
43611
|
});
|
|
43535
43612
|
|
|
43536
|
-
//# debugId=
|
|
43613
|
+
//# debugId=49CA369B086466F464756E2164756E21
|