@staff0rd/assist 0.224.0 → 0.225.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 +3 -1
- package/claude/commands/refine.md +4 -4
- package/dist/index.js +196 -11
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -111,8 +111,10 @@ The first backlog command in a repository that still has a local `.assist/backlo
|
|
|
111
111
|
- `assist backlog add` - Add a new backlog item interactively (prompts for type: story/bug)
|
|
112
112
|
- `assist backlog add --name <n> --type <t> --desc <d> --ac <criterion...>` - Add a backlog item from CLI options (used by `/draft`)
|
|
113
113
|
- `assist backlog add-phase <id> <name> --task <t...> [--manual-check <c...>] [--position <pos>]` - Add a phase (appends by default; `--position` inserts at a 1-indexed position)
|
|
114
|
-
- `assist backlog update <id> [--name <n>] [--desc <d>] [--type <t>] [--ac <criterion...>]` - Update fields on a backlog item
|
|
114
|
+
- `assist backlog update-field <id> [--name <n>] [--desc <d>] [--type <t>] [--ac <criterion...>]` - Update fields on a backlog item
|
|
115
|
+
- `assist backlog update-field <id> [--add-ac <text>] [--edit-ac <n> <text>] [--remove-ac <n>]` - Granular acceptance-criteria edits using 1-based indices matching `backlog show`: `--add-ac` appends (repeatable), `--edit-ac` replaces criterion n in place, `--remove-ac` deletes criterion n and renumbers the rest (cannot be combined with the whole-list `--ac`)
|
|
115
116
|
- `assist backlog update-phase <id> <phase> [--name <n>] [--task <t...>] [--manual-check <c...>]` - Modify a plan phase (name, tasks, or manual checks)
|
|
117
|
+
- `assist backlog update-phase <id> <phase> [--add-task <text>] [--edit-task <n> <text>] [--remove-task <n>] [--add-check <text>] [--edit-check <n> <text>] [--remove-check <n>]` - Granular task and manual-check edits using 1-based indices matching `backlog show`: `--add-*` appends (repeatable), `--edit-*` replaces entry n in place, `--remove-*` deletes entry n and renumbers the rest (task ops cannot be combined with `--task`; check ops cannot be combined with `--manual-check`)
|
|
116
118
|
- `assist backlog remove-phase <id> <phase>` - Remove a plan phase from a backlog item
|
|
117
119
|
- `assist backlog next` - Pick and run the next backlog item, or open `/draft` if none remain
|
|
118
120
|
- `assist backlog start <id>` - Set a backlog item to in-progress
|
|
@@ -35,10 +35,10 @@ Based on the user's input, apply changes using the appropriate commands. Always
|
|
|
35
35
|
|
|
36
36
|
**To update item fields:**
|
|
37
37
|
```
|
|
38
|
-
assist backlog update <id> --name "New name"
|
|
39
|
-
assist backlog update <id> --desc "New description"
|
|
40
|
-
assist backlog update <id> --type story
|
|
41
|
-
assist backlog update <id> --ac "criterion 1" --ac "criterion 2"
|
|
38
|
+
assist backlog update-field <id> --name "New name"
|
|
39
|
+
assist backlog update-field <id> --desc "New description"
|
|
40
|
+
assist backlog update-field <id> --type story
|
|
41
|
+
assist backlog update-field <id> --ac "criterion 1" --ac "criterion 2"
|
|
42
42
|
```
|
|
43
43
|
|
|
44
44
|
Note: `--ac` replaces all acceptance criteria, so include the full list (both existing and new).
|
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { Command } from "commander";
|
|
|
6
6
|
// package.json
|
|
7
7
|
var package_default = {
|
|
8
8
|
name: "@staff0rd/assist",
|
|
9
|
-
version: "0.
|
|
9
|
+
version: "0.225.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -909,11 +909,13 @@ function getDatabaseUrl() {
|
|
|
909
909
|
}
|
|
910
910
|
var _db;
|
|
911
911
|
var _connecting;
|
|
912
|
+
var _pool;
|
|
912
913
|
function getBacklogDb() {
|
|
913
914
|
if (_db) return Promise.resolve(_db);
|
|
914
915
|
if (_connecting) return _connecting;
|
|
915
916
|
_connecting = (async () => {
|
|
916
917
|
const pool = new Pool({ connectionString: getDatabaseUrl() });
|
|
918
|
+
_pool = pool;
|
|
917
919
|
const db = makeBacklogDb(
|
|
918
920
|
{ query: (sql2, params) => pool.query(sql2, params) },
|
|
919
921
|
pool
|
|
@@ -924,6 +926,14 @@ function getBacklogDb() {
|
|
|
924
926
|
})();
|
|
925
927
|
return _connecting;
|
|
926
928
|
}
|
|
929
|
+
async function closeBacklogDb() {
|
|
930
|
+
const pool = _pool;
|
|
931
|
+
if (!pool) return;
|
|
932
|
+
_pool = void 0;
|
|
933
|
+
_db = void 0;
|
|
934
|
+
_connecting = void 0;
|
|
935
|
+
await pool.end();
|
|
936
|
+
}
|
|
927
937
|
|
|
928
938
|
// src/commands/backlog/getCurrentOrigin.ts
|
|
929
939
|
import { execSync as execSync2 } from "child_process";
|
|
@@ -5587,6 +5597,78 @@ async function removePhase(id, phase) {
|
|
|
5587
5597
|
// src/commands/backlog/update/index.ts
|
|
5588
5598
|
import chalk67 from "chalk";
|
|
5589
5599
|
|
|
5600
|
+
// src/commands/backlog/update/parseListIndex.ts
|
|
5601
|
+
function parseListIndex(raw, length, label2) {
|
|
5602
|
+
if (!/^\d+$/.test(raw)) {
|
|
5603
|
+
return { ok: false, error: `${label2} must be a positive integer.` };
|
|
5604
|
+
}
|
|
5605
|
+
const index = Number.parseInt(raw, 10);
|
|
5606
|
+
if (index < 1 || index > length) {
|
|
5607
|
+
return {
|
|
5608
|
+
ok: false,
|
|
5609
|
+
error: `${label2} ${index} is out of range (1-${length}).`
|
|
5610
|
+
};
|
|
5611
|
+
}
|
|
5612
|
+
return { ok: true, index };
|
|
5613
|
+
}
|
|
5614
|
+
|
|
5615
|
+
// src/commands/backlog/update/applyListMutations.ts
|
|
5616
|
+
function hasListMutations(options2) {
|
|
5617
|
+
return Boolean(
|
|
5618
|
+
options2.add && options2.add.length > 0 || options2.edit || options2.remove
|
|
5619
|
+
);
|
|
5620
|
+
}
|
|
5621
|
+
function applyListMutations(current, options2, flags) {
|
|
5622
|
+
let items = [...current];
|
|
5623
|
+
if (options2.edit) {
|
|
5624
|
+
const [rawIndex, ...textParts] = options2.edit;
|
|
5625
|
+
if (rawIndex === void 0 || textParts.length === 0) {
|
|
5626
|
+
return {
|
|
5627
|
+
ok: false,
|
|
5628
|
+
error: `${flags.edit} requires an index and replacement text.`
|
|
5629
|
+
};
|
|
5630
|
+
}
|
|
5631
|
+
const parsed = parseListIndex(
|
|
5632
|
+
rawIndex,
|
|
5633
|
+
items.length,
|
|
5634
|
+
`${flags.edit} index`
|
|
5635
|
+
);
|
|
5636
|
+
if (!parsed.ok) return parsed;
|
|
5637
|
+
items[parsed.index - 1] = textParts.join(" ");
|
|
5638
|
+
}
|
|
5639
|
+
if (options2.remove) {
|
|
5640
|
+
const parsed = parseListIndex(
|
|
5641
|
+
options2.remove,
|
|
5642
|
+
items.length,
|
|
5643
|
+
`${flags.remove} index`
|
|
5644
|
+
);
|
|
5645
|
+
if (!parsed.ok) return parsed;
|
|
5646
|
+
items = items.filter((_, i) => i !== parsed.index - 1);
|
|
5647
|
+
}
|
|
5648
|
+
if (options2.add) {
|
|
5649
|
+
items.push(...options2.add);
|
|
5650
|
+
}
|
|
5651
|
+
return { ok: true, items };
|
|
5652
|
+
}
|
|
5653
|
+
|
|
5654
|
+
// src/commands/backlog/update/applyAcMutations.ts
|
|
5655
|
+
function hasAcMutations(options2) {
|
|
5656
|
+
return hasListMutations({
|
|
5657
|
+
add: options2.addAc,
|
|
5658
|
+
edit: options2.editAc,
|
|
5659
|
+
remove: options2.removeAc
|
|
5660
|
+
});
|
|
5661
|
+
}
|
|
5662
|
+
function applyAcMutations(current, options2) {
|
|
5663
|
+
const result = applyListMutations(
|
|
5664
|
+
current,
|
|
5665
|
+
{ add: options2.addAc, edit: options2.editAc, remove: options2.removeAc },
|
|
5666
|
+
{ add: "--add-ac", edit: "--edit-ac", remove: "--remove-ac" }
|
|
5667
|
+
);
|
|
5668
|
+
if (!result.ok) return result;
|
|
5669
|
+
return { ok: true, criteria: result.items };
|
|
5670
|
+
}
|
|
5671
|
+
|
|
5590
5672
|
// src/commands/backlog/update/buildUpdateSql.ts
|
|
5591
5673
|
import chalk66 from "chalk";
|
|
5592
5674
|
function buildUpdateSql(options2) {
|
|
@@ -5631,7 +5713,24 @@ function buildUpdateSql(options2) {
|
|
|
5631
5713
|
async function update(id, options2) {
|
|
5632
5714
|
const result = await loadAndFindItem(id);
|
|
5633
5715
|
if (!result) return;
|
|
5634
|
-
|
|
5716
|
+
let ac = options2.ac;
|
|
5717
|
+
if (hasAcMutations(options2)) {
|
|
5718
|
+
if (options2.ac) {
|
|
5719
|
+
console.log(
|
|
5720
|
+
chalk67.red("Cannot combine --ac with --add-ac/--edit-ac/--remove-ac.")
|
|
5721
|
+
);
|
|
5722
|
+
process.exitCode = 1;
|
|
5723
|
+
return;
|
|
5724
|
+
}
|
|
5725
|
+
const mutation = applyAcMutations(result.item.acceptanceCriteria, options2);
|
|
5726
|
+
if (!mutation.ok) {
|
|
5727
|
+
console.log(chalk67.red(mutation.error));
|
|
5728
|
+
process.exitCode = 1;
|
|
5729
|
+
return;
|
|
5730
|
+
}
|
|
5731
|
+
ac = mutation.criteria;
|
|
5732
|
+
}
|
|
5733
|
+
const built = buildUpdateSql({ ...options2, ac });
|
|
5635
5734
|
if (!built) return;
|
|
5636
5735
|
const db = await getBacklogDb();
|
|
5637
5736
|
const itemId = result.item.id;
|
|
@@ -5675,17 +5774,81 @@ async function applyPhaseUpdate(db, itemId, phaseIdx, fields) {
|
|
|
5675
5774
|
});
|
|
5676
5775
|
}
|
|
5677
5776
|
|
|
5777
|
+
// src/commands/backlog/update/resolveListUpdate.ts
|
|
5778
|
+
function resolveListUpdate(whole, current, mutations, wholeFlag, flags) {
|
|
5779
|
+
if (!hasListMutations(mutations)) return { ok: true, items: whole };
|
|
5780
|
+
if (whole) {
|
|
5781
|
+
return {
|
|
5782
|
+
ok: false,
|
|
5783
|
+
error: `Cannot combine ${wholeFlag} with ${flags.add}/${flags.edit}/${flags.remove}.`
|
|
5784
|
+
};
|
|
5785
|
+
}
|
|
5786
|
+
return applyListMutations(current, mutations, flags);
|
|
5787
|
+
}
|
|
5788
|
+
|
|
5789
|
+
// src/commands/backlog/resolvePhaseFields.ts
|
|
5790
|
+
var TASK_FLAGS = {
|
|
5791
|
+
add: "--add-task",
|
|
5792
|
+
edit: "--edit-task",
|
|
5793
|
+
remove: "--remove-task"
|
|
5794
|
+
};
|
|
5795
|
+
var CHECK_FLAGS = {
|
|
5796
|
+
add: "--add-check",
|
|
5797
|
+
edit: "--edit-check",
|
|
5798
|
+
remove: "--remove-check"
|
|
5799
|
+
};
|
|
5800
|
+
function resolveTasks(o, current) {
|
|
5801
|
+
return resolveListUpdate(
|
|
5802
|
+
o.task,
|
|
5803
|
+
(current?.tasks ?? []).map((t) => t.task),
|
|
5804
|
+
{ add: o.addTask, edit: o.editTask, remove: o.removeTask },
|
|
5805
|
+
"--task",
|
|
5806
|
+
TASK_FLAGS
|
|
5807
|
+
);
|
|
5808
|
+
}
|
|
5809
|
+
function resolveChecks(o, current) {
|
|
5810
|
+
return resolveListUpdate(
|
|
5811
|
+
o.manualCheck,
|
|
5812
|
+
current?.manualChecks ?? [],
|
|
5813
|
+
{ add: o.addCheck, edit: o.editCheck, remove: o.removeCheck },
|
|
5814
|
+
"--manual-check",
|
|
5815
|
+
CHECK_FLAGS
|
|
5816
|
+
);
|
|
5817
|
+
}
|
|
5818
|
+
function buildFields(name, tasks, checks) {
|
|
5819
|
+
const fields = {
|
|
5820
|
+
name,
|
|
5821
|
+
task: tasks.items,
|
|
5822
|
+
manualCheck: checks.items
|
|
5823
|
+
};
|
|
5824
|
+
if (!fields.name && !fields.task && !fields.manualCheck) {
|
|
5825
|
+
return {
|
|
5826
|
+
ok: false,
|
|
5827
|
+
error: "Nothing to update. Provide at least one flag."
|
|
5828
|
+
};
|
|
5829
|
+
}
|
|
5830
|
+
return { ok: true, fields };
|
|
5831
|
+
}
|
|
5832
|
+
function resolvePhaseFields(options2, current) {
|
|
5833
|
+
const tasks = resolveTasks(options2, current);
|
|
5834
|
+
if (!tasks.ok) return tasks;
|
|
5835
|
+
const checks = resolveChecks(options2, current);
|
|
5836
|
+
if (!checks.ok) return checks;
|
|
5837
|
+
return buildFields(options2.name, tasks, checks);
|
|
5838
|
+
}
|
|
5839
|
+
|
|
5678
5840
|
// src/commands/backlog/updatePhase.ts
|
|
5679
5841
|
async function updatePhase(id, phase, options2) {
|
|
5680
|
-
const
|
|
5681
|
-
if (!
|
|
5682
|
-
|
|
5842
|
+
const found = await findPhase(id, phase);
|
|
5843
|
+
if (!found) return;
|
|
5844
|
+
const { result, db, itemId, phaseIdx } = found;
|
|
5845
|
+
const resolved = resolvePhaseFields(options2, result.item.plan?.[phaseIdx]);
|
|
5846
|
+
if (!resolved.ok) {
|
|
5847
|
+
console.log(chalk68.red(resolved.error));
|
|
5683
5848
|
process.exitCode = 1;
|
|
5684
5849
|
return;
|
|
5685
5850
|
}
|
|
5686
|
-
const
|
|
5687
|
-
if (!found) return;
|
|
5688
|
-
const { db, itemId, phaseIdx } = found;
|
|
5851
|
+
const { name, task, manualCheck } = resolved.fields;
|
|
5689
5852
|
await applyPhaseUpdate(db, itemId, phaseIdx, { name, task, manualCheck });
|
|
5690
5853
|
const fields = [
|
|
5691
5854
|
name && "name",
|
|
@@ -5700,9 +5863,28 @@ async function updatePhase(id, phase, options2) {
|
|
|
5700
5863
|
}
|
|
5701
5864
|
|
|
5702
5865
|
// src/commands/backlog/registerUpdateCommands.ts
|
|
5866
|
+
function collect(value, previous) {
|
|
5867
|
+
return [...previous, value];
|
|
5868
|
+
}
|
|
5703
5869
|
function registerUpdateCommands(cmd) {
|
|
5704
|
-
cmd.command("update <id>").description("Update fields on a backlog item").option("--name <name>", "New item name").option("--desc <description>", "New description").option("--type <type>", "New type (story or bug)").option("--ac <criterion...>", "Replace acceptance criteria (repeatable)").
|
|
5705
|
-
|
|
5870
|
+
cmd.command("update-field <id>").description("Update fields on a backlog item").option("--name <name>", "New item name").option("--desc <description>", "New description").option("--type <type>", "New type (story or bug)").option("--ac <criterion...>", "Replace acceptance criteria (repeatable)").option(
|
|
5871
|
+
"--add-ac <text>",
|
|
5872
|
+
"Append one acceptance criterion (repeatable)",
|
|
5873
|
+
collect,
|
|
5874
|
+
[]
|
|
5875
|
+
).option(
|
|
5876
|
+
"--edit-ac <n> <text...>",
|
|
5877
|
+
"Replace acceptance criterion n (1-based) in place"
|
|
5878
|
+
).option("--remove-ac <n>", "Remove acceptance criterion n (1-based)").action(update);
|
|
5879
|
+
cmd.command("update-phase <id> <phase>").description("Modify a plan phase on a backlog item").option("--name <name>", "New phase name").option("--task <task...>", "Replace tasks (repeatable)").option("--manual-check <check...>", "Replace manual checks (repeatable)").option("--add-task <text>", "Append one task (repeatable)", collect, []).option("--edit-task <n> <text...>", "Replace task n (1-based) in place").option("--remove-task <n>", "Remove task n (1-based)").option(
|
|
5880
|
+
"--add-check <text>",
|
|
5881
|
+
"Append one manual check (repeatable)",
|
|
5882
|
+
collect,
|
|
5883
|
+
[]
|
|
5884
|
+
).option(
|
|
5885
|
+
"--edit-check <n> <text...>",
|
|
5886
|
+
"Replace manual check n (1-based) in place"
|
|
5887
|
+
).option("--remove-check <n>", "Remove manual check n (1-based)").action(updatePhase);
|
|
5706
5888
|
cmd.command("remove-phase <id> <phase>").description("Remove a plan phase from a backlog item").action(removePhase);
|
|
5707
5889
|
}
|
|
5708
5890
|
|
|
@@ -16440,4 +16622,7 @@ program.command("draft").alias("feat").description("Launch Claude in /draft mode
|
|
|
16440
16622
|
program.command("bug").description("Launch Claude in /bug mode, chain into next on /next signal").action(() => launchMode("bug"));
|
|
16441
16623
|
program.command("refine").argument("[id]", "Backlog item ID").description("Launch Claude in /refine mode to refine a backlog item").action((id) => refine(id));
|
|
16442
16624
|
registerSignal(program);
|
|
16443
|
-
program.
|
|
16625
|
+
program.parseAsync().catch((error) => {
|
|
16626
|
+
console.error(error);
|
|
16627
|
+
process.exitCode = 1;
|
|
16628
|
+
}).finally(() => closeBacklogDb());
|