@lumoai/cli 1.29.0 → 1.29.1
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/assets/skill/SKILL.md +163 -0
- package/assets/skill/references/artifacts-figma.md +124 -0
- package/assets/skill/references/criteria.md +160 -0
- package/assets/skill/references/docs.md +405 -0
- package/assets/skill/references/memory.md +103 -0
- package/assets/skill/references/milestones.md +244 -0
- package/assets/skill/references/onboarding.md +102 -0
- package/assets/skill/references/sessions.md +225 -0
- package/assets/skill/references/sprints.md +157 -0
- package/assets/skill/references/task-context.md +136 -0
- package/assets/skill/references/tasks.md +357 -0
- package/assets/skill/references/verify.md +148 -0
- package/dist/cli/src/commands/doc-list.js +2 -2
- package/dist/cli/src/index.js +19 -19
- package/package.json +1 -1
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# lumo verify — machine verification loop
|
|
2
|
+
|
|
3
|
+
`lumo verify` is the machine half of the acceptance system (Acceptance v1,
|
|
4
|
+
LUM-343). It executes every **MACHINE** criterion's checkpointer in the local
|
|
5
|
+
repo, reports one structured PASS/FAIL verdict per criterion to the server,
|
|
6
|
+
and prints what to do next. The judge lives server-side: round numbering, the
|
|
7
|
+
3-round cap, escalation, and the IN_REVIEW transition all happen there
|
|
8
|
+
(execution on the client, adjudication on the server).
|
|
9
|
+
|
|
10
|
+
## The claim-done rule
|
|
11
|
+
|
|
12
|
+
**Before claiming a task is complete — in conversation, in a wrap-up, or by
|
|
13
|
+
touching its status — run `lumo verify`.** The loop replaces "I read the code
|
|
14
|
+
and it looks done" with executed evidence.
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
lumo verify # session-bound task
|
|
18
|
+
lumo verify LUM-42 # explicit task (overrides the session binding)
|
|
19
|
+
lumo verify --timeout 900 # per-checkpointer timeout in seconds (default 600)
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## What one round does
|
|
23
|
+
|
|
24
|
+
1. Loads the task's acceptance contract and picks out MACHINE criteria.
|
|
25
|
+
2. Runs each checkpointer locally (shell, cwd = current directory), one at a
|
|
26
|
+
time, echoing PASS/FAIL as it goes.
|
|
27
|
+
3. POSTs the structured verdicts; the server records one VerificationRun per
|
|
28
|
+
criterion at round = previous max + 1 and mirrors each verdict as a
|
|
29
|
+
TaskActivity event.
|
|
30
|
+
4. Prints the round outcome:
|
|
31
|
+
- **All PASS** → the task transitions to **IN_REVIEW** (existing state
|
|
32
|
+
machine + TASK_IN_REVIEW notification). **Stop here.** Human
|
|
33
|
+
adjudication and any HUMAN criteria take over; never set DONE yourself.
|
|
34
|
+
- **Any FAIL** → task status is untouched; the unmet criteria are printed
|
|
35
|
+
as next actions (statement, checkpointer, failure tail). Fix and re-run.
|
|
36
|
+
- **Round 3 still failing** → the loop escalates: a human is notified
|
|
37
|
+
(AGENT_VERIFY, requires action) and further `lumo verify` rounds are
|
|
38
|
+
rejected with 409. **Stop retrying**; fix only what the human directs.
|
|
39
|
+
|
|
40
|
+
Exit code 0 = all passed (or nothing to run); 1 = failures, escalation, or
|
|
41
|
+
errors.
|
|
42
|
+
|
|
43
|
+
## Verdict semantics (what the CLI sends)
|
|
44
|
+
|
|
45
|
+
- checkpointer exits 0 → `PASS` with evidence `cmd:<command>#exit=0`
|
|
46
|
+
- non-zero exit → `FAIL`, reason = output tail, enum `CRITERION_UNMET`
|
|
47
|
+
- spawn failure / timeout → `FAIL`, enum `CHECK_EXECUTION_ERROR`
|
|
48
|
+
|
|
49
|
+
evidencePointer is **not free text** — the server only accepts
|
|
50
|
+
`commit:<hash>`, `file:<path>:<line>`, or `cmd:<command>#exit=<code>`.
|
|
51
|
+
Verdicts are PASS|FAIL only; the agent path cannot write HUMAN verdicts or
|
|
52
|
+
`PASS_WITH_FOLLOWUP` (red line — those enter via human-initiated UI paths
|
|
53
|
+
only).
|
|
54
|
+
|
|
55
|
+
## Edge cases
|
|
56
|
+
|
|
57
|
+
- **No contract yet** → error pointing at `lumo task criteria set`; draft the
|
|
58
|
+
contract first (criteria.md golden rule).
|
|
59
|
+
- **HUMAN-only contract (zero MACHINE criteria)** → nothing to run; the CLI
|
|
60
|
+
says so and suggests handing off for human review
|
|
61
|
+
(`lumo task update <id> --status in_review`). No server write happens.
|
|
62
|
+
- **A round must cover every MACHINE criterion** — the CLI always runs all of
|
|
63
|
+
them; the server rejects partial rounds.
|
|
64
|
+
- Criteria added during review (`REVIEW_ADDED`) appear in the contract and
|
|
65
|
+
are picked up automatically by the next round.
|
|
66
|
+
|
|
67
|
+
## Round discipline
|
|
68
|
+
|
|
69
|
+
Rounds are a hard budget of 3, not a retry loop. Between rounds, actually fix
|
|
70
|
+
the failures — re-running without changes burns a round and (at round 3)
|
|
71
|
+
pages a human. A FAIL round never changes task status; only an all-pass round
|
|
72
|
+
moves it (to IN_REVIEW, never further).
|
|
73
|
+
|
|
74
|
+
## Review-time drift habits (gap findings)
|
|
75
|
+
|
|
76
|
+
A problem discovered during acceptance/review that the contract does NOT
|
|
77
|
+
cover is a **gap finding** — record it in the contract, never just fix it
|
|
78
|
+
silently:
|
|
79
|
+
|
|
80
|
+
1. **Append it on the spot.** Transcribe the human's finding as a criterion
|
|
81
|
+
via `lumo task criteria set <task> --file <desired-final-list> --human` —
|
|
82
|
+
the review-added semantics: the gap surfaced at review time, at the
|
|
83
|
+
current round.
|
|
84
|
+
2. **Tag why the contract drifted** with `--cause
|
|
85
|
+
<NEW_INFO|SCOPE_CHANGE|DRAFT_BLIND_SPOT|GRANULARITY|OTHER>`. Gap findings
|
|
86
|
+
are usually `DRAFT_BLIND_SPOT` (the draft missed it) or `NEW_INFO`
|
|
87
|
+
(information that didn't exist at drafting time).
|
|
88
|
+
3. **Then bounce.** The appended criterion shows up in `lumo task status`
|
|
89
|
+
nextActions and the next verify round picks it up automatically — no
|
|
90
|
+
side-channel to-do list.
|
|
91
|
+
|
|
92
|
+
How to read drift: information-lag and requirement-movement drift
|
|
93
|
+
(`NEW_INFO`, `SCOPE_CHANGE`) is healthy — don't optimize it away.
|
|
94
|
+
`DRAFT_BLIND_SPOT` clusters feed back into the drafting guide. **Zero drift
|
|
95
|
+
across many tasks is a red flag, not a trophy** — it usually means contracts
|
|
96
|
+
are too thin or state only sure-win clauses that can never be found wanting.
|
|
97
|
+
|
|
98
|
+
## lumo task status — the read half (self-check entry point)
|
|
99
|
+
|
|
100
|
+
`lumo task status [task] [--json]` is the read-only counterpart of the loop
|
|
101
|
+
(LUM-344): pure read, milliseconds, no LLM, never writes — running it costs
|
|
102
|
+
nothing and burns no round. Defaults to the session-bound task; an explicit
|
|
103
|
+
identifier overrides.
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
lumo task status # session-bound task
|
|
107
|
+
lumo task status LUM-42 # explicit task
|
|
108
|
+
lumo task status --json # versioned machine-readable payload
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### When to run it
|
|
112
|
+
|
|
113
|
+
**Status-first recovery:** run it FIRST — before re-reading code or
|
|
114
|
+
planning — whenever you:
|
|
115
|
+
|
|
116
|
+
- resume a task in a new session (yours or another agent's earlier work);
|
|
117
|
+
- come back after a verification round was rejected (`lumo verify` failed);
|
|
118
|
+
- were told the task bounced in review (REVIEW_ADDED criteria may have been
|
|
119
|
+
appended at the round they surfaced — they show up here automatically).
|
|
120
|
+
|
|
121
|
+
It answers "where does the loop stand": what already passed (don't redo it),
|
|
122
|
+
what's unmet and why (the exact failure tails), and how many rounds are left.
|
|
123
|
+
|
|
124
|
+
### What it prints
|
|
125
|
+
|
|
126
|
+
- Header: task identifier/title/status + `verification round N/3` (round 0 =
|
|
127
|
+
never verified) + an escalation warning when the machine loop is exhausted.
|
|
128
|
+
- **Criteria** — every criterion as `<glyph> <id> [TYPE] SOURCE@rN
|
|
129
|
+
statement` (✓ latest verdict passed / ✗ failed / ○ no verdict yet) with its
|
|
130
|
+
checkpointer and latest verdict line (evidence pointer on pass, failure
|
|
131
|
+
tail on fail). `REVIEW_ADDED@rN` provenance is visible per row.
|
|
132
|
+
- **History** — one line per recorded round: `rN · timestamp · X PASS / Y FAIL`.
|
|
133
|
+
- **Last round failures** — the most recent round's FAIL verdicts with their
|
|
134
|
+
rejection reasons (why the last round bounced).
|
|
135
|
+
- **Next actions** — the unmet criteria (latest verdict is not a pass:
|
|
136
|
+
failed or never verified, HUMAN ones included). This list IS the plan —
|
|
137
|
+
it is recomputed from the event log on every read, never maintained
|
|
138
|
+
separately. Empty + rounds recorded = awaiting human adjudication.
|
|
139
|
+
|
|
140
|
+
### --json contract
|
|
141
|
+
|
|
142
|
+
`--json` emits the full read model with a top-level `version` field
|
|
143
|
+
(currently `1`). The schema is versioned: breaking shape changes bump the
|
|
144
|
+
major; additive fields don't. Pin on `version` when scripting against it.
|
|
145
|
+
|
|
146
|
+
`status` reads; `verify` judges. Running status never starts a round, never
|
|
147
|
+
escalates, and never changes task state — loop rules (cap 3, IN_REVIEW on
|
|
148
|
+
all-pass, human-only DONE) live entirely in `lumo verify` and the server.
|
|
@@ -51,7 +51,7 @@ async function docList(opts) {
|
|
|
51
51
|
}
|
|
52
52
|
else {
|
|
53
53
|
const params = new URLSearchParams();
|
|
54
|
-
if (opts.scope && opts.scope !== 'all') {
|
|
54
|
+
if (opts.scope && opts.scope.toLowerCase() !== 'all') {
|
|
55
55
|
const v = (0, doc_create_1.normalizeScope)(opts.scope);
|
|
56
56
|
if (!v) {
|
|
57
57
|
console.error(`Error: invalid scope "${opts.scope}". Allowed: personal, workspace, all`);
|
|
@@ -74,7 +74,7 @@ async function docList(opts) {
|
|
|
74
74
|
}
|
|
75
75
|
const { documents } = (await res.json());
|
|
76
76
|
let rows = documents;
|
|
77
|
-
if (opts.task && opts.scope && opts.scope !== 'all') {
|
|
77
|
+
if (opts.task && opts.scope && opts.scope.toLowerCase() !== 'all') {
|
|
78
78
|
const v = (0, doc_create_1.normalizeScope)(opts.scope);
|
|
79
79
|
if (v)
|
|
80
80
|
rows = rows.filter(r => r.visibility === v);
|
package/dist/cli/src/index.js
CHANGED
|
@@ -256,7 +256,7 @@ task
|
|
|
256
256
|
task
|
|
257
257
|
.command('list')
|
|
258
258
|
.description('List tasks assigned to you. Filter with --status, --project, --milestone, --limit.')
|
|
259
|
-
.option('-s, --status <value>', 'Filter by status: todo | in_progress | in_review | done')
|
|
259
|
+
.option('-s, --status <value>', 'Filter by status: todo | in_progress | in_review | done (case-insensitive)')
|
|
260
260
|
.option('-p, --project <ref>', 'Filter by project name (case-insensitive)')
|
|
261
261
|
.option('-n, --limit <count>', 'Show only the first N tasks')
|
|
262
262
|
.option('-m, --milestone <ref>', 'Filter by milestone name or UUID (scopes to my tasks under that milestone)')
|
|
@@ -278,7 +278,7 @@ task
|
|
|
278
278
|
.command('create <title>')
|
|
279
279
|
.description('Create a task. --project required when workspace has >1 project; defaults: priority=low, assignee=me.')
|
|
280
280
|
.option('-d, --description <text>', 'Task description')
|
|
281
|
-
.option('-p, --priority <level>', 'Priority: low | medium | high | urgent (default: low)')
|
|
281
|
+
.option('-p, --priority <level>', 'Priority: low | medium | high | urgent (case-insensitive; default: low)')
|
|
282
282
|
.option('-a, --assignee <ref>', 'Assignee email, name, or "me" (default: me)')
|
|
283
283
|
.option('--project <ref>', 'Project name or slug')
|
|
284
284
|
.option('--milestone <ref>', 'Milestone name (case-insensitive)')
|
|
@@ -377,7 +377,7 @@ const taskMemory = task
|
|
|
377
377
|
taskMemory
|
|
378
378
|
.command('list [task]')
|
|
379
379
|
.description("List a task's memories. <task> defaults to the session-bound task.")
|
|
380
|
-
.option('--category <cat>', 'Filter by trap|decision|convention|procedural')
|
|
380
|
+
.option('--category <cat>', 'Filter by trap|decision|convention|procedural (case-insensitive)')
|
|
381
381
|
.option('-n, --limit <count>', 'Cap output to the first N rows')
|
|
382
382
|
.action(wrap((taskArg, opts) => (0, memory_task_list_1.memoryTaskList)(taskArg, opts)));
|
|
383
383
|
taskMemory
|
|
@@ -385,7 +385,7 @@ taskMemory
|
|
|
385
385
|
.description('Record a memory on a task (<task> defaults to the bound session). ' +
|
|
386
386
|
'Record only knowledge invisible in the codebase (the why, a runtime gotcha, a non-obvious failure, a non-trivial workflow); skip routine work. ' +
|
|
387
387
|
'Pick --category then its fields.')
|
|
388
|
-
.requiredOption('--category <cat>', 'trap | decision | convention | procedural')
|
|
388
|
+
.requiredOption('--category <cat>', 'trap | decision | convention | procedural (case-insensitive)')
|
|
389
389
|
.option('--trigger <text>', 'trap/procedural: the situation that triggers it')
|
|
390
390
|
.option('--outcome <text>', 'trap: what goes wrong')
|
|
391
391
|
.option('--workaround <text>', 'trap: optional fix')
|
|
@@ -397,7 +397,7 @@ taskMemory
|
|
|
397
397
|
.option('--applies <text>', 'convention: where the rule applies')
|
|
398
398
|
.option('--workflow <text>', 'procedural: the workflow name')
|
|
399
399
|
.option('--step <text>', 'procedural: a step (repeatable)', collect, [])
|
|
400
|
-
.option('--agent <agent>', 'Producing agent: claude-code | codex | cursor | gemini-cli | github-copilot | windsurf (default claude-code)')
|
|
400
|
+
.option('--agent <agent>', 'Producing agent: claude-code | codex | cursor | gemini-cli | github-copilot | windsurf (case-insensitive; default claude-code)')
|
|
401
401
|
.action(wrap((taskArg, opts) => (0, memory_task_add_1.memoryTaskAdd)(taskArg, opts)));
|
|
402
402
|
const taskCriteria = task
|
|
403
403
|
.command('criteria')
|
|
@@ -407,7 +407,7 @@ taskCriteria
|
|
|
407
407
|
.description('Submit the whole acceptance contract from a JSON file. Default = initial agent draft (locked once submitted); --human records a HUMAN_EDIT revision (desired final list; items with "id" keep/update, missing ones are deleted).')
|
|
408
408
|
.requiredOption('--file <path>', 'JSON array of criteria: [{"statement","verifierType":"MACHINE"|"HUMAN","checkpointer?","evidenceRequired?","id?"}]')
|
|
409
409
|
.option('--human', 'Record a human contract revision (HUMAN_EDIT) transcribed from the conversation, with session provenance')
|
|
410
|
-
.option('--cause <tag>', 'Why the contract drifted (with --human): NEW_INFO | SCOPE_CHANGE | DRAFT_BLIND_SPOT | GRANULARITY | OTHER')
|
|
410
|
+
.option('--cause <tag>', 'Why the contract drifted (with --human): NEW_INFO | SCOPE_CHANGE | DRAFT_BLIND_SPOT | GRANULARITY | OTHER (case-insensitive)')
|
|
411
411
|
.action(wrap((taskId, options) => (0, task_criteria_set_1.taskCriteriaSet)(taskId, options)));
|
|
412
412
|
taskCriteria
|
|
413
413
|
.command('list <task>')
|
|
@@ -423,7 +423,7 @@ taskArtifact
|
|
|
423
423
|
.requiredOption('--title <title>', 'Artifact title')
|
|
424
424
|
.requiredOption('--file <path>', 'File whose contents become the artifact body')
|
|
425
425
|
.requiredOption('--source <source>', 'Spec-gen framework, formal name e.g. Superpowers | "Spec Kit" | BMad | OpenSpec | GSD (opaque; quote names with spaces)')
|
|
426
|
-
.requiredOption('--agent <agent>', 'Coding tool that produced the artifact: claude-code | codex | cursor | gemini-cli | github-copilot | windsurf')
|
|
426
|
+
.requiredOption('--agent <agent>', 'Coding tool that produced the artifact: claude-code | codex | cursor | gemini-cli | github-copilot | windsurf (case-insensitive)')
|
|
427
427
|
.action(wrap((taskId, options) => (0, task_artifact_add_1.taskArtifactAdd)(taskId, options)));
|
|
428
428
|
taskArtifact
|
|
429
429
|
.command('update <task> <artifact-id>')
|
|
@@ -431,7 +431,7 @@ taskArtifact
|
|
|
431
431
|
.option('--kind <kind>', 'New artifact kind (opaque)')
|
|
432
432
|
.option('--title <title>', 'New artifact title')
|
|
433
433
|
.option('--source <source>', 'New spec-gen framework, formal name e.g. Superpowers | "Spec Kit" | BMad | OpenSpec | GSD (quote names with spaces)')
|
|
434
|
-
.option('--agent <agent>', 'New coding tool: claude-code | codex | cursor | gemini-cli | github-copilot | windsurf')
|
|
434
|
+
.option('--agent <agent>', 'New coding tool: claude-code | codex | cursor | gemini-cli | github-copilot | windsurf (case-insensitive)')
|
|
435
435
|
.action(wrap((taskId, artifactId, options) => (0, task_artifact_update_1.taskArtifactUpdate)(taskId, artifactId, options)));
|
|
436
436
|
taskArtifact
|
|
437
437
|
.command('list <task>')
|
|
@@ -459,13 +459,13 @@ const projectMemory = projectCmd
|
|
|
459
459
|
projectMemory
|
|
460
460
|
.command('list [project]')
|
|
461
461
|
.description("List a project's PROJECT-scope memories. <project> defaults to the bound task's project.")
|
|
462
|
-
.option('--category <cat>', 'Filter by trap|decision|convention|procedural')
|
|
462
|
+
.option('--category <cat>', 'Filter by trap|decision|convention|procedural (case-insensitive)')
|
|
463
463
|
.option('-n, --limit <count>', 'Cap output to the first N rows')
|
|
464
464
|
.action(wrap((p, opts) => (0, memory_project_list_1.memoryProjectList)(p, opts)));
|
|
465
465
|
projectMemory
|
|
466
466
|
.command('add [project]')
|
|
467
467
|
.description("Record a PROJECT-scope memory. Use PROJECT scope only when the lesson helps any task in the project. <project> defaults to the bound task's project.")
|
|
468
|
-
.requiredOption('--category <cat>', 'trap | decision | convention | procedural')
|
|
468
|
+
.requiredOption('--category <cat>', 'trap | decision | convention | procedural (case-insensitive)')
|
|
469
469
|
.option('--trigger <text>', 'trap/procedural trigger')
|
|
470
470
|
.option('--outcome <text>', 'trap outcome')
|
|
471
471
|
.option('--workaround <text>', 'trap optional workaround')
|
|
@@ -477,7 +477,7 @@ projectMemory
|
|
|
477
477
|
.option('--applies <text>', 'convention: where it applies')
|
|
478
478
|
.option('--workflow <text>', 'procedural workflow')
|
|
479
479
|
.option('--step <text>', 'procedural step (repeatable)', collect, [])
|
|
480
|
-
.option('--agent <agent>', 'Producing agent: claude-code | codex | cursor | gemini-cli | github-copilot | windsurf (default claude-code)')
|
|
480
|
+
.option('--agent <agent>', 'Producing agent: claude-code | codex | cursor | gemini-cli | github-copilot | windsurf (case-insensitive; default claude-code)')
|
|
481
481
|
.action(wrap((p, opts) => (0, memory_project_add_1.memoryProjectAdd)(p, opts)));
|
|
482
482
|
const memoryCmd = program
|
|
483
483
|
.command('memory')
|
|
@@ -521,7 +521,7 @@ milestoneCmd
|
|
|
521
521
|
.option('--project <ref>', 'Project name or slug (when identifier is a name)')
|
|
522
522
|
.option('-n, --name <text>', 'New name')
|
|
523
523
|
.option('-d, --description <text>', 'New description (empty string to clear)')
|
|
524
|
-
.option('-s, --status <value>', 'New status: planned | active | completed | cancelled')
|
|
524
|
+
.option('-s, --status <value>', 'New status: planned | active | completed | cancelled (case-insensitive)')
|
|
525
525
|
.option('--start <date>', 'Start date YYYY-MM-DD (empty string to clear)')
|
|
526
526
|
.option('--target <date>', 'Target date YYYY-MM-DD (empty string to clear)')
|
|
527
527
|
.action(wrap((identifier, options) => (0, milestone_update_1.milestoneUpdate)(identifier, options)));
|
|
@@ -641,7 +641,7 @@ doc
|
|
|
641
641
|
.description('Create a new document. Body comes from --content, --file, or piped stdin (pick one). --scope defaults to personal. Use --task LUM-N to bind the new doc to a task, --parent to file it under another doc.')
|
|
642
642
|
.option('--content <text>', 'Inline markdown content')
|
|
643
643
|
.option('--file <path>', 'Read markdown content from file')
|
|
644
|
-
.option('--scope <scope>', 'personal | workspace (default: personal)')
|
|
644
|
+
.option('--scope <scope>', 'personal | workspace (case-insensitive; default: personal)')
|
|
645
645
|
.option('--project <ref>', 'Project name or slug to file under')
|
|
646
646
|
.option('--task <LUM-N>', 'Bind to this task after creation')
|
|
647
647
|
.option('--parent <doc>', 'File under this parent doc (cuid or title)')
|
|
@@ -651,7 +651,7 @@ doc
|
|
|
651
651
|
doc
|
|
652
652
|
.command('import-gdoc <url>')
|
|
653
653
|
.description('Import a Google Doc as a Lumo doc (one-way Google → Lumo)')
|
|
654
|
-
.option('--scope <scope>', 'personal | workspace (default: personal)')
|
|
654
|
+
.option('--scope <scope>', 'personal | workspace (case-insensitive; default: personal)')
|
|
655
655
|
.option('--task <LUM-N>', 'Bind the imported doc to this task')
|
|
656
656
|
.action(wrap((url, opts) => (0, doc_import_gdoc_1.docImportGdoc)(url, opts)));
|
|
657
657
|
doc
|
|
@@ -664,7 +664,7 @@ doc
|
|
|
664
664
|
.option('--title <text>', 'New title')
|
|
665
665
|
.option('--content <text>', 'Replace content (inline)')
|
|
666
666
|
.option('--file <path>', 'Replace content from file')
|
|
667
|
-
.option('--scope <scope>', 'personal | workspace')
|
|
667
|
+
.option('--scope <scope>', 'personal | workspace (case-insensitive)')
|
|
668
668
|
.option('--project <ref>', 'Project name/slug; pass "" to clear')
|
|
669
669
|
.option('--tag <name>', 'Set tags by name (bulk replace, repeatable)', collect, [])
|
|
670
670
|
.option('--tag-id <cuid>', 'Set tags by id (bulk replace, repeatable)', collect, [])
|
|
@@ -704,7 +704,7 @@ doc
|
|
|
704
704
|
doc
|
|
705
705
|
.command('list')
|
|
706
706
|
.description('List documents visible to the current user')
|
|
707
|
-
.option('--scope <scope>', 'personal | workspace | all (default: all)')
|
|
707
|
+
.option('--scope <scope>', 'personal | workspace | all (case-insensitive; default: all)')
|
|
708
708
|
.option('--project <ref>', 'Filter by project name/slug')
|
|
709
709
|
.option('--task <LUM-N>', 'Only docs bound to this task')
|
|
710
710
|
.option('--limit <n>', 'Cap output to first N rows')
|
|
@@ -732,7 +732,7 @@ doc
|
|
|
732
732
|
doc
|
|
733
733
|
.command('share <doc> <member>')
|
|
734
734
|
.description('Share a document with a workspace member. PRIVATE docs are auto-promoted to SHARED. <member> accepts "me", an email, or a display name.')
|
|
735
|
-
.option('--role <role>', 'viewer | editor | manager (default: viewer)')
|
|
735
|
+
.option('--role <role>', 'viewer | editor | manager (case-insensitive; default: viewer)')
|
|
736
736
|
.action(wrap((docRef, member, opts) => (0, doc_share_1.docShare)(docRef, member, opts)));
|
|
737
737
|
doc
|
|
738
738
|
.command('unshare <doc> <member>')
|
|
@@ -747,8 +747,8 @@ task
|
|
|
747
747
|
.description('Update a task. Provide at least one of --title, --description, --status, --priority, --assignee, --milestone, --sprint, or tag flags. Use "" to clear description, assignee, milestone, or sprint binding. --tag/--tag-id (bulk replace) cannot be combined with --add-tag/--add-tag-id/--remove-tag/--remove-tag-id.')
|
|
748
748
|
.option('-t, --title <text>', 'New title')
|
|
749
749
|
.option('-d, --description <text>', 'New description (empty string to clear)')
|
|
750
|
-
.option('-s, --status <value>', 'New status: todo | in_progress | in_review | done')
|
|
751
|
-
.option('-p, --priority <level>', 'New priority: low | medium | high | urgent')
|
|
750
|
+
.option('-s, --status <value>', 'New status: todo | in_progress | in_review | done (case-insensitive)')
|
|
751
|
+
.option('-p, --priority <level>', 'New priority: low | medium | high | urgent (case-insensitive)')
|
|
752
752
|
.option('-a, --assignee <ref>', 'New assignee: email, name, or "me" (empty string to clear)')
|
|
753
753
|
.option('--milestone <ref>', 'Milestone name (case-insensitive); empty string to unbind')
|
|
754
754
|
.option('--sprint <ref>', 'Sprint number or UUID to bind the task to; empty string to unbind from current sprint')
|