@lumoai/cli 1.58.0 → 1.59.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/assets/skill/SKILL.md +13 -16
- package/assets/skill/references/artifacts-figma.md +4 -3
- package/assets/skill/references/confirmation.md +131 -0
- package/assets/skill/references/criteria.md +12 -21
- package/assets/skill/references/doc-editing.md +11 -9
- package/assets/skill/references/docs.md +4 -3
- package/assets/skill/references/memory.md +4 -2
- package/assets/skill/references/milestones.md +3 -2
- package/assets/skill/references/outcome.md +1 -14
- package/assets/skill/references/plan-runs.md +5 -0
- package/assets/skill/references/sessions.md +3 -3
- package/assets/skill/references/sprints.md +18 -17
- package/assets/skill/references/task-deps.md +4 -3
- package/assets/skill/references/tasks.md +34 -2
- package/assets/skill/references/verify.md +46 -68
- package/assets/skill/references/worktree.md +13 -7
- package/dist/cli/src/commands/doc-delete.js +35 -23
- package/dist/cli/src/commands/doc-rebuild-source.js +16 -4
- package/dist/cli/src/commands/memory-rm.js +68 -10
- package/dist/cli/src/commands/milestone-delete.js +13 -10
- package/dist/cli/src/commands/outcome.js +0 -77
- package/dist/cli/src/commands/session-attach.js +8 -2
- package/dist/cli/src/commands/sprint-close.js +29 -9
- package/dist/cli/src/commands/sprint-delete.js +13 -10
- package/dist/cli/src/commands/sprint-show.js +3 -9
- package/dist/cli/src/commands/task-artifact-rm.js +58 -28
- package/dist/cli/src/commands/task-criteria-list.js +1 -4
- package/dist/cli/src/commands/task-criteria-set.js +3 -12
- package/dist/cli/src/commands/task-deps.js +20 -6
- package/dist/cli/src/commands/task-status.js +165 -110
- package/dist/cli/src/commands/task-update.js +129 -0
- package/dist/cli/src/commands/verify.js +22 -13
- package/dist/cli/src/commands/worktree-rm.js +35 -7
- package/dist/cli/src/index.js +47 -47
- package/dist/cli/src/lib/blocked-error.js +178 -0
- package/dist/cli/src/lib/confirmation.js +89 -0
- package/dist/cli/src/lib/hook-runner.js +23 -11
- package/dist/shared/src/referent-kind.js +31 -1
- package/dist/shared/src/security-scan.js +29 -0
- package/package.json +1 -1
- package/assets/skill/references/fidelity.md +0 -32
- package/dist/cli/src/commands/fidelity.js +0 -108
- package/dist/cli/src/commands/verdict.js +0 -189
package/assets/skill/SKILL.md
CHANGED
|
@@ -34,8 +34,7 @@ The command catalog below is a **map**: it lists every command grouped by domain
|
|
|
34
34
|
| `task criteria set/list`, drafting the acceptance contract | [references/criteria.md](references/criteria.md) |
|
|
35
35
|
| `verify`, `task status` — machine verification loop, claim-done flow, self-check/resume | [references/verify.md](references/verify.md) |
|
|
36
36
|
| `cost` — per-operation (per-tool) token cost read-out; `task lineage` Top-5 | [references/task-context.md](references/task-context.md) |
|
|
37
|
-
| `outcome show/
|
|
38
|
-
| `fidelity show` — per-delivery grounding + independence change-pattern read-out | [references/fidelity.md](references/fidelity.md) |
|
|
37
|
+
| `outcome show/rate` — post-hoc outcome well (falsifier oracle, rejection-only) | [references/outcome.md](references/outcome.md) |
|
|
39
38
|
| `priority [text]`, `priority list` — team priority declaration (append-only) | [references/priority.md](references/priority.md) |
|
|
40
39
|
| `project list`, `milestone*` | [references/milestones.md](references/milestones.md) |
|
|
41
40
|
| `doc create/update/list/move/bind/share/import` (CRUD) | [references/docs.md](references/docs.md) |
|
|
@@ -44,6 +43,7 @@ The command catalog below is a **map**: it lists every command grouped by domain
|
|
|
44
43
|
| `task/project memory`, `memory promote/rm` | [references/memory.md](references/memory.md) |
|
|
45
44
|
| `session attach/status`, git-suggest on start, Layer-2 review | [references/sessions.md](references/sessions.md) |
|
|
46
45
|
| `worktree add/rm/list` (local dev tooling) | [references/worktree.md](references/worktree.md) |
|
|
46
|
+
| `--confirm` / exit code 4 — the confirmation envelope every gated mutation speaks | [references/confirmation.md](references/confirmation.md) |
|
|
47
47
|
|
|
48
48
|
## Command catalog
|
|
49
49
|
|
|
@@ -67,7 +67,7 @@ The command catalog below is a **map**: it lists every command grouped by domain
|
|
|
67
67
|
### Tasks — see [tasks.md](references/tasks.md)
|
|
68
68
|
|
|
69
69
|
- `lumo task create <title> [flags]` — create a task. **Mid-task** (your session is bound to an in-flight task) it requires `--rework-of <id>` (redirects you to fix the existing task — creates nothing) or `--new-scope` (genuinely new, out-of-scope work). On a send-back, fix in place / amend the contract instead of spinning off a new task — see [verify.md](references/verify.md) and [criteria.md](references/criteria.md).
|
|
70
|
-
- `lumo task update <id> [flags]` — patch status/title/priority/assignee/milestone/sprint/tags; `--claimable`/`--not-claimable` set the agent-claimable marker (LUM-646)
|
|
70
|
+
- `lumo task update <id> [flags]` — patch status/title/priority/assignee/milestone/sprint/tags; `--claimable`/`--not-claimable` set the agent-claimable marker (LUM-646). `--status done` without `--confirm` exits 4 with a confirmation envelope (see [confirmation.md](references/confirmation.md))
|
|
71
71
|
- `lumo task list [flags]` — list tasks assigned to you
|
|
72
72
|
- `lumo next [--count N] [--claimable]` — recommend the next task to work on (read-only). `--claimable` restricts to the autonomy boundary: only tasks that are claimable ∩ unblocked (F3 topology) ∩ within milestone budget (F2); old server degrades gracefully to the standard ranking (LUM-646)
|
|
73
73
|
- `lumo task show <id>` — print one task's detail
|
|
@@ -97,7 +97,7 @@ The command catalog below is a **map**: it lists every command grouped by domain
|
|
|
97
97
|
- `lumo task deps add <id> --blocked-by <LUM-N>` — declare a manual hard dependency (CONFIRMED)
|
|
98
98
|
- `lumo task deps confirm <id> <edge> [--reverse]` — confirm a detected candidate (`--reverse` flips direction)
|
|
99
99
|
- `lumo task deps dismiss <id> <edge>` — dismiss a candidate (never re-suggested)
|
|
100
|
-
- `lumo task deps rm <id> <edge> --
|
|
100
|
+
- `lumo task deps rm <id> <edge> --confirm` — delete an edge (without `--confirm`: exit 4 + confirmation envelope; `--yes` is a legacy alias)
|
|
101
101
|
- `<edge>` = short edge-id prefix (≥6 chars) or the other task's identifier; ambiguous/unknown selectors list candidates and exit 1. See [tasks.md](references/tasks.md)
|
|
102
102
|
|
|
103
103
|
### Acceptance criteria (contract) — see [criteria.md](references/criteria.md)
|
|
@@ -107,9 +107,8 @@ The command catalog below is a **map**: it lists every command grouped by domain
|
|
|
107
107
|
|
|
108
108
|
### Verification (machine acceptance loop) — see [verify.md](references/verify.md)
|
|
109
109
|
|
|
110
|
-
- `lumo verify [task] --note "<self-report>" [--timeout <seconds>]` — run every MACHINE criterion's checkpointer locally and report a structured PASS/FAIL verdict per criterion.
|
|
111
|
-
- `lumo task status [task] [--json]` — read-only acceptance self-check (no LLM): the contract with each criterion's latest verdict,
|
|
112
|
-
- `lumo verdict [task] --pass | --fail` — acceptance verdicts. `--pass` deep-links to the human verdict bar (records nothing). `--fail --reason <enum> …` records an AGENT send-back → IN_PROGRESS. **An unresolved send-back blocks the DONE transition with 409.**
|
|
110
|
+
- `lumo verify [task] [--note "<self-report>"] [--timeout <seconds>]` — run every MACHINE criterion's checkpointer locally and report a structured PASS/FAIL verdict per criterion. `--note` is an optional one-line self-report ("我改了 X,因为 Y 可验收"), frozen as the task's claim (source AGENT) when the round passes into IN_REVIEW. The round cap is the workspace's `verificationMaxRounds` (default 3) — read the actual budget off the `Round N/M` line the command prints, never assume a number. All-pass → task to IN_REVIEW (agent stops); a fail on the last round → escalate to human. **Run this before claiming a task is done.**
|
|
111
|
+
- `lumo task status [task] [--full] [--json]` — read-only acceptance self-check (no LLM): the contract with each criterion's latest verdict, the current round, last failure reasons, `nextActions` (the unmet criteria, plus any undispositioned PR **security findings** as `SECURITY_FINDING` entries — `blocks DONE` vs `advisory`), a per-linked-PR **scan status line** (stage states incl. the L3 `hunt` layer, external-finding count, partial flag, external failure reason — LUM-735/739), and any OPEN boundary crossings; `--full` adds the dashboard sections (verification rollup, history, cost, struggle trail, trend) (fails closed — `null`/`⚠` means "could not confirm", not safe). **Run it first when resuming a task or after a round was rejected.**
|
|
113
112
|
- `lumo crossing explain <id> --note "<text>"` — append an agent self-explanation ("申辩") to a boundary crossing; append-only, **never clears the crossing or unblocks Done** (disposition stays web + human-only). A review aid, not a self-clear.
|
|
114
113
|
|
|
115
114
|
### Cost (per-operation token read-out) — see [task-context.md](references/task-context.md)
|
|
@@ -128,13 +127,8 @@ The command catalog below is a **map**: it lists every command grouped by domain
|
|
|
128
127
|
### Outcome well (post-hoc oracle) — see [outcome.md](references/outcome.md)
|
|
129
128
|
|
|
130
129
|
- `lumo outcome show <task>` — read the post-hoc outcome well: the **falsifier** verdict (`REJECTED` | `INCONCLUSIVE` — never a "pass") plus its backing rejection signals. `INCONCLUSIVE` = no rejection on record, **not** "satisfied".
|
|
131
|
-
- `lumo outcome record <task> --note "<what reality did>" [--kind <kind>]` — record a human-observed post-hoc **rejection** of a delivery (revert / rollback / CI regression / downstream redirect / bypass). Append-only; **there is no "mark satisfied" counterpart** — the well only asserts rejection. `--note` is required (the observed referent).
|
|
132
130
|
- `lumo outcome rate [--min N] [--json]` — workspace **trust × post-hoc-fate** join (LUM-603, LUM-606): per delivery-time **verification-friction** bucket (`no-verification` / `single-round` / `multi-round-or-sendback` — two raw counts frozen at delivery, replacing the saturating forecast-confidence axis), the post-hoc REJECTED rate from the well. Honest by construction — thin buckets read `insufficient` (no fabricated rate), the single-round-vs-multi comparison stays `inconclusive` until CIs separate, and the rate is a **lower bound** (no signal = INCONCLUSIVE, never satisfied). Bucket names are value-neutral — direction is decided by the correlation, never welded into the label. Under-sampled today by design — the skeleton produces real strata once the well fills.
|
|
133
131
|
|
|
134
|
-
### Fidelity read-out (mechanical change-pattern) — see [fidelity.md](references/fidelity.md)
|
|
135
|
-
|
|
136
|
-
- `lumo fidelity show <task> [--json]` — per delivery snapshot (LUM-609), a **composition table, not a single score**: (1) the **grounding** of the frozen contract — grounded (`EXTERNAL_FACT`, a machine-checkable upper bound) / self-confirming (`AGENT_CONSTRUCTED_STATE` + `UNVERIFIED_ASSERTION`) / inconclusive (`PENDING_OUTCOME` + `UNCLASSIFIED`, surfaced not swallowed) + the full effective-kind tally; (2) the **independence** signal — criteria `ADDED`/`UPDATED` at round>0 (after work started) that the delivery rode on = backward-inference suspects. Purely mechanical (timing + op + grounding) — **no direction verdict**. A no-snapshot task is reported explicitly (not a pass). Zero new storage — reads the snapshot + `CRITERION_CHANGED` trail.
|
|
137
|
-
|
|
138
132
|
### Artifacts & Figma — see [artifacts-figma.md](references/artifacts-figma.md)
|
|
139
133
|
|
|
140
134
|
- `lumo task artifact add/update/list/show/rm` — record spec/plan products on a task
|
|
@@ -174,7 +168,7 @@ The command catalog below is a **map**: it lists every command grouped by domain
|
|
|
174
168
|
|
|
175
169
|
- `lumo task memory add/list` · `lumo project memory add/list` — record/curate Memory (TASK vs PROJECT)
|
|
176
170
|
- `lumo memory show <id>` — show one memory's full card (category + content) by id (progressive disclosure from a one-line index entry)
|
|
177
|
-
- `lumo memory promote <id>` / `lumo memory rm <id> --
|
|
171
|
+
- `lumo memory promote <id>` / `lumo memory rm <id> --confirm` — TASK→PROJECT / delete (exit 4 + envelope without `--confirm`)
|
|
178
172
|
- `lumo memory sync [--dry-run] [--clean]` — downsync team memory into the local Claude Code store (`team/<id>.md` + a managed MEMORY.md block); only touches files it owns
|
|
179
173
|
- `lumo memory push [--dry-run]` — upsync locally-authored memories from `<memory-dir>/outbox/*.json` to the team
|
|
180
174
|
- `lumo memory fold [project-ref] --dry-run` — read-only PREVIEW of the autonomous topic-fold pass (folding runs via a daily cron; no manual apply, no `unfold`). See [memory.md](references/memory.md)
|
|
@@ -182,7 +176,7 @@ The command catalog below is a **map**: it lists every command grouped by domain
|
|
|
182
176
|
### Sessions — see [sessions.md](references/sessions.md)
|
|
183
177
|
|
|
184
178
|
- `lumo session attach <id>` — bind this session to a task (then run `task context`). **Lifetime lock**: re-attaching to the same task is a no-op; attaching to a _different_ task is refused with 409 — start a new Claude Code session instead. No `--force`, no `session detach`.
|
|
185
|
-
- `lumo session attach --steward <milestone>` — bind this session to a **milestone** as a **STEWARD (governance) session** (LUM-640): plan & accept only. Governance passes (task create/update, criteria set incl. `--human`, deps confirm/dismiss,
|
|
179
|
+
- `lumo session attach --steward <milestone>` — bind this session to a **milestone** as a **STEWARD (governance) session** (LUM-640): plan & accept only. Governance passes (task create/update, criteria set incl. `--human`, deps confirm/dismiss, milestone add/remove, milestone triage (LUM-646 claimable), all reads); implementation is gated (`lumo verify` → 409 **without burning a round**; moving a task to in_progress assigned to yourself → 409); commits/PRs produced anyway are recorded as milestone-scoped boundary crossings (fail-closed; disposition stays web+human-only, no CLI clear path). Same lifetime lock: same milestone idempotent, any other attach (a task, or a different milestone) → 409; multiple stewards per milestone are fine. See [sessions.md](references/sessions.md)
|
|
186
180
|
- `lumo session status` — show current binding (a task, or the milestone + STEWARD role)
|
|
187
181
|
- End-of-session housekeeping is fully automatic (no command). On DONE the server runs three best-effort silent passes: Layer-1 memory curation, fragment-usage audit, and blocked-tag automation. See [sessions.md](references/sessions.md)
|
|
188
182
|
- Git-suggest at session start (suggests `session attach`, never auto-binds) + Layer-2 project-memory review — see the reference
|
|
@@ -190,7 +184,7 @@ The command catalog below is a **map**: it lists every command grouped by domain
|
|
|
190
184
|
### Worktrees (local dev tooling) — see [worktree.md](references/worktree.md)
|
|
191
185
|
|
|
192
186
|
- `lumo worktree add <LUM-N> [slug]` — scaffold `.worktrees/<LUM-N>` + node_modules symlink off origin/main; run from the main checkout
|
|
193
|
-
- `lumo worktree rm <LUM-N> --
|
|
187
|
+
- `lumo worktree rm <LUM-N> --confirm` — remove a worktree (exit 4 + envelope without `--confirm`; dirty tree also needs `--force`; keeps the branch unless `--delete-branch`)
|
|
194
188
|
- `lumo worktree list` — list `.worktrees/` worktrees (task id, branch, dirty, node_modules link)
|
|
195
189
|
|
|
196
190
|
## Next-step hints (the trailing `Next:` block)
|
|
@@ -207,6 +201,7 @@ The block never replaces the acceptance-contract section: on `session attach` /
|
|
|
207
201
|
|
|
208
202
|
Don't guess these:
|
|
209
203
|
|
|
204
|
+
- No `lumo verdict`, `lumo fidelity`, or `lumo outcome record` (removed in LUM-733): send-backs and passes are human-only in the web verdict bar; outcome signals are derived automatically (git revert feed); the fidelity read-out is an internal API (`GET /api/tasks/<id>/fidelity`), not a CLI command
|
|
210
205
|
- No `lumo session start` — binding is `lumo session attach <LUM-N>`
|
|
211
206
|
- No `lumo session detach` — the session↔task binding is a lifetime lock; to work on a different task, start a new Claude Code session
|
|
212
207
|
- No steward "role switch" or un-steward — `session attach --steward` is the same lifetime lock on a milestone; a steward session never converts to an implementation session (and there is no CLI path to clear its boundary crossings)
|
|
@@ -217,7 +212,8 @@ Don't guess these:
|
|
|
217
212
|
- No `--content` on `task/project memory add` — memory is structured fields (`--category` + per-category flags), see [memory.md](references/memory.md)
|
|
218
213
|
- No global `--verbose` flag on any command
|
|
219
214
|
- `lumo task comments list` (plural) **reads** the thread; `lumo task comment` (singular) **writes** one
|
|
220
|
-
- Status updates: `lumo task update LUM-N --status done` is one direct call — do **not** walk `in_progress → in_review → done` step by step (see [tasks.md](references/tasks.md) for the transition matrix; under the verify flow you shouldn't be setting `in_review`/`done` yourself at all)
|
|
215
|
+
- Status updates: `lumo task update LUM-N --status done` is one direct call — do **not** walk `in_progress → in_review → done` step by step (see [tasks.md](references/tasks.md) for the transition matrix; under the verify flow you shouldn't be setting `in_review`/`done` yourself at all). `--status done` has no interactive prompt and no `--yes`: without `--confirm` it exits 4 with a confirmation envelope you relay to the user (see [confirmation.md](references/confirmation.md))
|
|
216
|
+
- No interactive yes/no prompts anywhere, and no `--yes` on `task update` — every gated mutation exits 4 with a `confirmation_required` envelope instead; `--yes` survives only as a legacy alias of `--confirm` on the delete/rm/close commands
|
|
221
217
|
|
|
222
218
|
## Core workflow
|
|
223
219
|
|
|
@@ -239,4 +235,5 @@ Don't guess these:
|
|
|
239
235
|
- **Evidence before "done".** Never claim done from reading code — run `lumo verify`. While a PR is open, the task is IN_REVIEW, not DONE.
|
|
240
236
|
- **Never set DONE yourself after a verify loop** — that adjudication is human-only. An unresolved send-back blocks the DONE transition with 409.
|
|
241
237
|
- **Status updates are one direct call** (`task update --status done`), not a step-by-step walk through `in_progress → in_review → done`.
|
|
238
|
+
- **Exit code 4 = the user must confirm — you may not.** A gated mutation (`--status done`, `sprint/milestone/doc delete`, `memory rm`, `task deps/artifact rm`, `sprint close --move-all/--backlog-all`, `worktree rm`, `doc rebuild-source` on an existing source) run without `--confirm` prints a `confirmation_required` envelope on stdout and does nothing. Show every line of its `changes` to the user, wait for their explicit approval, then run its `confirmCommand` verbatim. **Never add `--confirm` (or `--yes` / `--force`) yourself** — the flag means "the user has confirmed", and adding it on your own initiative is the exact failure the protocol exists to stop. **Exit code 5 = blocked by a human-only gate** (`DONE_BLOCKED`: a send-back, an undispositioned boundary crossing, a blocking security finding): relay its `blockers` and `remediation` to the user; nothing on the CLI clears it — no retry, no flag, no rewording a failed criterion. Details: [confirmation.md](references/confirmation.md)
|
|
242
239
|
- **Read the reference before composing a command** whose flags/edge-cases matter — don't run from memory.
|
|
@@ -46,12 +46,13 @@ Prints one artifact's key:value header (id, kind, title, agent, source, order, t
|
|
|
46
46
|
lumo task artifact show LUM-42 cma_xxx
|
|
47
47
|
```
|
|
48
48
|
|
|
49
|
-
#### `lumo task artifact rm <task> <artifact-id> --
|
|
49
|
+
#### `lumo task artifact rm <task> <artifact-id> --confirm`
|
|
50
50
|
|
|
51
|
-
Deletes an artifact from a task. Irreversible
|
|
51
|
+
Deletes an artifact from a task. Irreversible. Without `--confirm` the CLI fetches the artifact and exits **4** with a confirmation envelope naming it (`Will delete artifact cma_xxx "API spec" (SPEC) from LUM-42` · `Artifact deletion is irreversible`) — no DELETE is sent; relay `changes` to the user and re-run `confirmCommand` on approval ([confirmation.md](confirmation.md)). `--yes` is a legacy alias. On success prints `Removed <artifact-id> from <task>`. A 404 (task or artifact missing in this workspace) prints the server message and exits 1.
|
|
52
52
|
|
|
53
53
|
```bash
|
|
54
|
-
lumo task artifact rm LUM-42 cma_xxx
|
|
54
|
+
lumo task artifact rm LUM-42 cma_xxx # exit 4 + envelope
|
|
55
|
+
lumo task artifact rm LUM-42 cma_xxx --confirm # after the user approved
|
|
55
56
|
```
|
|
56
57
|
|
|
57
58
|
When to suggest: after running a spec/plan workflow in Claude Code, offer to record the product(s) with `task artifact add` (one call per artifact) — always pass `--source` with the framework you used. Use `task artifact list` to see what's already recorded, `task artifact show` to inspect a single artifact's content, `task artifact update` to fix a wrong kind/title/source without re-uploading, and `task artifact rm` to drop one that's wrong or stale.
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# Confirmation protocol (`--confirm`, exit code 4)
|
|
2
|
+
|
|
3
|
+
Some `lumo` commands change or destroy state that a human should sign off on first — deleting a sprint, milestone, document, memory, artifact or dependency edge; closing a sprint with unfinished tasks; removing a worktree; re-deriving a doc's markdown source; and moving a task to **DONE**. Since LUM-755 they all speak one protocol instead of prompting or hard-refusing:
|
|
4
|
+
|
|
5
|
+
1. You run the command **without `--confirm`**.
|
|
6
|
+
2. The CLI computes, from real server/local state, what it would do — and **does not do it**. It prints a **confirmation envelope on stdout** and exits **4**.
|
|
7
|
+
3. You show the envelope's `changes` to the user, verbatim.
|
|
8
|
+
4. The user approves or rejects.
|
|
9
|
+
5. Only on approval, you re-run the envelope's `confirmCommand` — the same invocation with `--confirm` appended.
|
|
10
|
+
|
|
11
|
+
There is no interactive yes/no prompt on a TTY either: a human and an agent walk the same steps.
|
|
12
|
+
|
|
13
|
+
## The envelope
|
|
14
|
+
|
|
15
|
+
When stdout is not a TTY (the agent path) the envelope is JSON:
|
|
16
|
+
|
|
17
|
+
```json
|
|
18
|
+
{
|
|
19
|
+
"status": "confirmation_required",
|
|
20
|
+
"command": "sprint delete",
|
|
21
|
+
"changes": [
|
|
22
|
+
"Will delete sprint #3 \"Sprint 3\"",
|
|
23
|
+
"12 tasks under it keep their data; only sprintId is cleared"
|
|
24
|
+
],
|
|
25
|
+
"confirmCommand": "lumo sprint delete 3 --confirm"
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
| Field | Meaning |
|
|
30
|
+
| ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
31
|
+
| `status` | Always `confirmation_required`. |
|
|
32
|
+
| `command` | The command path, e.g. `task update`, `worktree rm`. |
|
|
33
|
+
| `changes` | Human-readable lines describing exactly what would happen, computed from the current state (titles, counts, linked PRs, dirty files…). Never empty. |
|
|
34
|
+
| `confirmCommand` | Your original argv (flags and quoting preserved) plus `--confirm` — and, when a second gate applies, that gate's flag too (`--force --confirm`). |
|
|
35
|
+
|
|
36
|
+
On a TTY the same fields are rendered as text: a header line, one `-` bullet per change, then `Re-run with --confirm once the user has approved:` and the command on its own line.
|
|
37
|
+
|
|
38
|
+
Nothing goes to stderr; the envelope is the command's result, not an error. **Exit 4 is the only signal you need** — do not grep the text to decide whether a command "wants confirmation".
|
|
39
|
+
|
|
40
|
+
## Rules for an agent
|
|
41
|
+
|
|
42
|
+
- **Exit 4 → stop and relay.** Print every line of `changes` to the user. Do not paraphrase away a `⚠` line.
|
|
43
|
+
- **Wait for an explicit approval.** A user who asked you to "delete the sprint" earlier has not yet seen what the envelope says will happen; the envelope is what they approve.
|
|
44
|
+
- **Run `confirmCommand` unchanged.** Do not rebuild the command by hand, do not drop flags the envelope carried (`--force`, `--team`, `--project`…).
|
|
45
|
+
- **Never add `--confirm` (or `--yes`, or `--force`) on your own initiative.** `--confirm` means "the user has confirmed". Passing it without that approval is the one thing this protocol exists to prevent, and it is visible in the session trail.
|
|
46
|
+
- A rejected envelope is not an error to retry — report the user's decision and move on.
|
|
47
|
+
|
|
48
|
+
## Flags
|
|
49
|
+
|
|
50
|
+
- `--confirm` — the user approved. Present on every command in the table below.
|
|
51
|
+
- `--yes` — legacy alias of `--confirm` on the commands that took it before LUM-755. Prefer `--confirm` in new invocations. `task update` never had `--yes` and does not gain it.
|
|
52
|
+
- `--force` — a **second gate** that stays separate from `--confirm`: `worktree rm` uses it to acknowledge discarding uncommitted changes; `doc rebuild-source` uses it to acknowledge replacing an existing source. Missing `--force` also yields an envelope (exit 4) whose `confirmCommand` carries `--force --confirm`.
|
|
53
|
+
|
|
54
|
+
## Commands that use the protocol
|
|
55
|
+
|
|
56
|
+
| Command | `changes` describes | Notes |
|
|
57
|
+
| --------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
58
|
+
| `task update <id> --status done` | `Will move LUM-N "title" to DONE` · `Status: <current> → DONE` · one line per linked PR (`#926 merged title url`) or `Pull requests: none linked` · a trailing `⚠ N linked pull request(s) not merged: …` when any PR is open/closed/draft | Only `--status done` is gated; other statuses PATCH directly. The server's own DONE gates (unresolved send-back, open boundary crossing → 409) still apply after `--confirm`. See [tasks.md](tasks.md). |
|
|
59
|
+
| `task deps rm <id> <edge>` | the resolved edge (short id, direction, other task, status, source) | [task-deps.md](task-deps.md) |
|
|
60
|
+
| `task artifact rm <task> <artifact-id>` | artifact id, title, kind; "irreversible" | [artifacts-figma.md](artifacts-figma.md) |
|
|
61
|
+
| `memory rm <memoryId>` | memory id, `[CATEGORY]`, a one-line content summary | [memory.md](memory.md) |
|
|
62
|
+
| `doc delete <doc>` | doc id + title; nested documents are deleted with it | [docs.md](docs.md) |
|
|
63
|
+
| `sprint delete <ref>` | sprint number + name; task count (tasks keep their data) | [sprints.md](sprints.md) |
|
|
64
|
+
| `sprint close <ref> --move-all` / `--backlog-all` | sprint; every unfinished task and where it goes | Without a mode flag and with unfinished tasks the command is a plain exit-1 refusal (pick a mode). [sprints.md](sprints.md) |
|
|
65
|
+
| `milestone delete <ref>` | milestone name; task count (tasks keep their data) | [milestones.md](milestones.md) |
|
|
66
|
+
| `worktree rm <LUM-N>` | path + branch; `⚠ … uncommitted changes … discarded` when dirty; whether the branch is kept or deleted | Dirty tree → `confirmCommand` carries `--force --confirm`. [worktree.md](worktree.md) |
|
|
67
|
+
| `doc rebuild-source <doc>` (when a source already exists) | the server's 409 reason; what `--force` would replace | `confirmCommand` carries `--force --confirm`. [doc-editing.md](doc-editing.md) |
|
|
68
|
+
|
|
69
|
+
## When the gate is human-only: `DONE_BLOCKED`, exit code 5
|
|
70
|
+
|
|
71
|
+
Not every refusal is something the user can approve. The server's DONE gates — an **unresolved send-back**, an **undispositioned boundary crossing**, a **blocking security finding** — are verdicts on the agent's own work, and by design there is no CLI path to clear them (the interested party may not adjudicate itself). They are therefore **not** part of the confirmation protocol: no `--confirm`, no `--force`, nothing you can pass.
|
|
72
|
+
|
|
73
|
+
What the CLI does instead: when `task update <id> --status done --confirm` is refused by one of these gates, it re-reads the task's acceptance status and open crossings, prints a structured error on **stdout** and exits **5**:
|
|
74
|
+
|
|
75
|
+
```json
|
|
76
|
+
{
|
|
77
|
+
"status": "blocked",
|
|
78
|
+
"code": "DONE_BLOCKED",
|
|
79
|
+
"command": "task update",
|
|
80
|
+
"task": "LUM-48",
|
|
81
|
+
"message": "Cannot move this task to DONE — 1 undispositioned boundary-crossing (forbidden action taken during this task): 1 TEST_FILE_DELETED. …",
|
|
82
|
+
"blockers": [
|
|
83
|
+
{
|
|
84
|
+
"kind": "BOUNDARY_CROSSING",
|
|
85
|
+
"id": "cmtw…",
|
|
86
|
+
"severity": "MEDIUM",
|
|
87
|
+
"category": "TEST_FILE_DELETED",
|
|
88
|
+
"detail": "deleted __tests__/cli/old.test.ts"
|
|
89
|
+
}
|
|
90
|
+
],
|
|
91
|
+
"unconfirmed": [],
|
|
92
|
+
"remediation": [
|
|
93
|
+
"BOUNDARY_CROSSING: leave a rationale with `lumo crossing explain cmtw… --note \"…\"` (append-only; it does not clear anything). A human dispositions each crossing (false positive / confirmed) at https://…/my-tasks/LUM-48#boundary-crossings"
|
|
94
|
+
],
|
|
95
|
+
"dispositionUrl": "https://…/my-tasks/LUM-48#boundary-crossings"
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
| Field | Meaning |
|
|
100
|
+
| ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
101
|
+
| `message` | The server's 409 text, verbatim. |
|
|
102
|
+
| `blockers` | One entry per item holding the gate: `SEND_BACK` (criterionId, statement, failedAtRound, rejectionReason), `BOUNDARY_CROSSING` (id, severity, category, detail), `SECURITY_FINDING` (findingId, severity, ruleId, filePath, line, prNumber, statement). Built from the same read models as `lumo task status`. |
|
|
103
|
+
| `unconfirmed` | Enrichment reads that failed (`boundary-crossings read failed: HTTP 500`). Non-empty means the blocker list may be incomplete — it never silently shrinks. |
|
|
104
|
+
| `remediation` | One line per blocker kind present, naming only human-side or append-only paths: re-run `lumo verify`, `lumo crossing explain`, fix-and-push, the web disposition panel. |
|
|
105
|
+
|
|
106
|
+
**Exit 4 vs exit 5:** 4 means "the user must approve, then you can proceed"; 5 means "a human must adjudicate elsewhere — nothing on the CLI moves this". On exit 5, relay `blockers` and `remediation` to the user. Do not retry, do not look for a flag, and do not reword or delete a failed criterion to get past a send-back (that is tampering and is audited). A 409 that is not a DONE gate (e.g. a permission refusal) keeps the plain exit-1 text on stderr.
|
|
107
|
+
|
|
108
|
+
## Example exchange
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
lumo task update LUM-48 --status done
|
|
112
|
+
# exit 4, stdout:
|
|
113
|
+
# {
|
|
114
|
+
# "status": "confirmation_required",
|
|
115
|
+
# "command": "task update",
|
|
116
|
+
# "changes": [
|
|
117
|
+
# "Will move LUM-48 \"Panel refactor\" to DONE",
|
|
118
|
+
# "Status: IN_REVIEW → DONE",
|
|
119
|
+
# "#926 merged refactor: panel https://github.com/o/r/pull/926",
|
|
120
|
+
# "#930 open feat: wip https://github.com/o/r/pull/930",
|
|
121
|
+
# "⚠ 1 linked pull request not merged: #930 open"
|
|
122
|
+
# ],
|
|
123
|
+
# "confirmCommand": "lumo task update LUM-48 --status done --confirm"
|
|
124
|
+
# }
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Agent → user: "Moving LUM-48 to DONE would change IN_REVIEW → DONE. PR #926 is merged, but **#930 is still open**. Confirm?" — and only after a yes:
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
lumo task update LUM-48 --status done --confirm
|
|
131
|
+
```
|
|
@@ -9,7 +9,7 @@ The acceptance contract is a small set of structured criteria the task's work is
|
|
|
9
9
|
If `lumo task context` / session-start shows the draft reminder ("This task has no acceptance criteria yet. …") instead of a contract, you MUST draft and submit criteria before starting implementation:
|
|
10
10
|
|
|
11
11
|
1. Read the task description, comments, linked resources, and memory first — the contract distills what "done" means, so understand the task before writing it.
|
|
12
|
-
2. Draft **3–7 criteria** for a typical multi-file task (
|
|
12
|
+
2. Draft **3–7 criteria** for a typical multi-file task (drafting guidance only — the server enforces no count; if you genuinely need more, merge related checks instead). Scale the count down for small tasks (see "Scale the contract to the task size").
|
|
13
13
|
3. `lumo task criteria set <task> --file <criteria.json>` — submit.
|
|
14
14
|
|
|
15
15
|
### The reference-class block (outside view) — LUM-497
|
|
@@ -89,20 +89,15 @@ The 3–7 range is calibrated for typical multi-file tasks. Criterion count must
|
|
|
89
89
|
|
|
90
90
|
### judgeSteps — agent-drafted judging steps for HUMAN criteria
|
|
91
91
|
|
|
92
|
-
**`referentKind` —
|
|
92
|
+
**`referentKind` — derived by the system, not declared (LUM-733):**
|
|
93
93
|
|
|
94
|
-
|
|
94
|
+
You do not declare a referent kind. The server derives it from the checkpointer at write time and stores the result:
|
|
95
95
|
|
|
96
|
-
-
|
|
97
|
-
-
|
|
98
|
-
-
|
|
96
|
+
- MACHINE + a checkpointer that actually **consumes** an external tool (`git`/`gh`/`curl`/`psql`/`prisma migrate status`…, its exit or output reaching the verdict) → `EXTERNAL_FACT` — a fact the agent cannot author.
|
|
97
|
+
- MACHINE + anything else (`jest`/`vitest`/`tsc`/`node`/`tsx`, your own build or type-check) → `AGENT_CONSTRUCTED_STATE` — green is self-confirming, which is the honest kind for almost every code task's checks.
|
|
98
|
+
- HUMAN → no checkpointer to read; an optional `"referentKind": "EXTERNAL_FACT" | "AGENT_CONSTRUCTED_STATE"` is kept as-is, otherwise the row stays unclassified.
|
|
99
99
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
- at **`criteria set`** — stores it but returns a non-rejecting ⚠ warning naming the criterion (re-ground or re-declare);
|
|
103
|
-
- at **`lumo verify`** — a PASS on it is **blocked with 422 (no round burned)**; the round does not land and the task does not move to IN_REVIEW until you either re-ground the checkpointer against a real external fact, or honestly re-declare it `AGENT_CONSTRUCTED_STATE`. Both fixes are free (no round consumed).
|
|
104
|
-
|
|
105
|
-
Don't reach for `EXTERNAL_FACT` to look stronger — a jest test is `AGENT_CONSTRUCTED_STATE`, full stop. Reserve `EXTERNAL_FACT` for checks that truly read external state, or use a HUMAN criterion for "a person ran the real system and observed X" (HUMAN is never mechanically downgraded).
|
|
100
|
+
A `referentKind` on a MACHINE item is accepted for backward compatibility and ignored. `PENDING_OUTCOME` is no longer a task-criterion kind (it remains on milestone exit criteria only) — leave post-delivery truths out of the encoded contract. There is no verify-time gate to trip: because the kind follows the check, a jest-checked criterion can never be stored as an "external fact".
|
|
106
101
|
|
|
107
102
|
A HUMAN criterion is judged by a person, not a checkpointer — so don't hand them a bare assertion ("the copy reads naturally") and make them reverse-engineer what to do. Attach **`judgeSteps`**: short, human-readable instructions the adjudication card renders verbatim (light markdown, URLs made clickable). Structured labour is yours; the human just follows the steps.
|
|
108
103
|
|
|
@@ -142,14 +137,12 @@ Two real-repo invariant examples — `prisma/migrations/` files never deleted (t
|
|
|
142
137
|
{
|
|
143
138
|
"statement": "No file under prisma/migrations/ is deleted by this change (vs origin/main)",
|
|
144
139
|
"verifierType": "MACHINE",
|
|
145
|
-
"checkpointer": "bash -c \"test -z \\\"$(git diff --diff-filter=D --name-only origin/main -- prisma/migrations/)\\\"\""
|
|
146
|
-
"referentKind": "EXTERNAL_FACT"
|
|
140
|
+
"checkpointer": "bash -c \"test -z \\\"$(git diff --diff-filter=D --name-only origin/main -- prisma/migrations/)\\\"\""
|
|
147
141
|
},
|
|
148
142
|
{
|
|
149
143
|
"statement": "Live-doc keeps its table structure after the edit (no rows/headings dropped)",
|
|
150
144
|
"verifierType": "MACHINE",
|
|
151
|
-
"checkpointer": "npx tsx scripts/verify-live-doc.ts <docId> docs/live-docs/<file>.md"
|
|
152
|
-
"referentKind": "AGENT_CONSTRUCTED_STATE"
|
|
145
|
+
"checkpointer": "npx tsx scripts/verify-live-doc.ts <docId> docs/live-docs/<file>.md"
|
|
153
146
|
}
|
|
154
147
|
]
|
|
155
148
|
```
|
|
@@ -167,8 +160,7 @@ One invariant criterion is usually enough — it's the guardrail, not the whole
|
|
|
167
160
|
{
|
|
168
161
|
"statement": "PUT /api/tasks/[id]/criteria rejects a second AGENT_DRAFT submission with 409",
|
|
169
162
|
"verifierType": "MACHINE",
|
|
170
|
-
"checkpointer": "npx jest __tests__/task-criteria.service.test.ts -t 'agent lock'"
|
|
171
|
-
"referentKind": "AGENT_CONSTRUCTED_STATE"
|
|
163
|
+
"checkpointer": "npx jest __tests__/task-criteria.service.test.ts -t 'agent lock'"
|
|
172
164
|
},
|
|
173
165
|
{
|
|
174
166
|
"statement": "The criteria section reads naturally as part of the task statement",
|
|
@@ -180,7 +172,6 @@ One invariant criterion is usually enough — it's the guardrail, not the whole
|
|
|
180
172
|
"statement": "Session-start injection shows the contract ahead of memory",
|
|
181
173
|
"verifierType": "MACHINE",
|
|
182
174
|
"checkpointer": "npx jest __tests__/cli/hook-runner-session-start-stdout.test.ts",
|
|
183
|
-
"referentKind": "AGENT_CONSTRUCTED_STATE",
|
|
184
175
|
"evidenceRequired": true
|
|
185
176
|
}
|
|
186
177
|
]
|
|
@@ -191,7 +182,7 @@ Fields:
|
|
|
191
182
|
- `statement` — required, ≤2000 chars.
|
|
192
183
|
- `verifierType` — `"MACHINE"` | `"HUMAN"`.
|
|
193
184
|
- `checkpointer` — required for MACHINE.
|
|
194
|
-
- `referentKind` —
|
|
185
|
+
- `referentKind` — optional and advisory; the stored kind is derived from the checkpointer (see "referentKind" above). Only meaningful on a HUMAN criterion (`"EXTERNAL_FACT"` | `"AGENT_CONSTRUCTED_STATE"`).
|
|
195
186
|
- `evidenceRequired` — optional, default false.
|
|
196
187
|
- `judgeSteps` — optional, ≤2000 chars; agent-drafted human-judging steps for a HUMAN criterion (see "judgeSteps" above).
|
|
197
188
|
- `id` — only in `--human` revisions (see below).
|
|
@@ -263,7 +254,7 @@ lumo criteria audit
|
|
|
263
254
|
- `EXTERNAL_FACT` — declared as externally observable (git SHA, CI status, DB row) and the checkpointer invokes real external tooling
|
|
264
255
|
- `AGENT_CONSTRUCTED_STATE` — passes by checking output the agent itself produced
|
|
265
256
|
- `PENDING_OUTCOME` — deferred to post-hoc falsifier
|
|
266
|
-
- `UNVERIFIED_ASSERTION` — declared `EXTERNAL_FACT`
|
|
257
|
+
- `UNVERIFIED_ASSERTION` — a legacy row declared `EXTERNAL_FACT` (before LUM-733 derivation) whose checkpointer does **not** actually invoke external tooling (git/CI/HTTP); reported as-is. New rows can't land here — the kind is derived from the checkpointer at write time (see "referentKind")
|
|
267
258
|
- `UNCLASSIFIED` — legacy rows predating the `referentKind` field (null in DB)
|
|
268
259
|
|
|
269
260
|
2. **Self-confirming-green headline ratio** — `(AGENT_CONSTRUCTED_STATE + UNVERIFIED_ASSERTION) / classified`. Criteria in these two buckets pass by confirming only the agent's own work, not an independent external state.
|
|
@@ -121,24 +121,26 @@ lumo doc diff cmd_xxx --file docs/live-docs/research-intake-ledger.md
|
|
|
121
121
|
|
|
122
122
|
The **recovery path for a source-less doc**. When a doc has no stored `sourceMarkdown` — a web HTML-direct edit or revision restore nulled it, or the doc predates source storage — every markdown write path (`--raw`, `--section`, `doc patch`, `doc append --section`, `doc diff`) is locked. This regenerates a valid source by serializing the **stored HTML structure model** back to markdown with a **lossless serializer that round-trips tables/rows/headings** (the default `doc show` render flattens tables, so it was never a safe rebuild base). Only the `sourceMarkdown` column is backfilled; the rendered body is untouched, so the doc reads identically and you just regain the edit base.
|
|
123
123
|
|
|
124
|
-
| Flag | Type | Notes
|
|
125
|
-
| ------------------- | ------- |
|
|
126
|
-
| `--allow-shrink` | boolean | Commit even if the rebuilt source re-renders with fewer tables/rows/headings than the stored body (default: 422 reject).
|
|
127
|
-
| `--force` | boolean | Re-derive even when a source already exists
|
|
128
|
-
| `--
|
|
124
|
+
| Flag | Type | Notes |
|
|
125
|
+
| ------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
126
|
+
| `--allow-shrink` | boolean | Commit even if the rebuilt source re-renders with fewer tables/rows/headings than the stored body (default: 422 reject). |
|
|
127
|
+
| `--force` | boolean | Re-derive even when a source already exists. Without it an existing source yields exit 4 + a confirmation envelope whose `confirmCommand` carries `--force --confirm` ([confirmation.md](confirmation.md)). |
|
|
128
|
+
| `--confirm` | boolean | The user approved replacing the existing source; pair it with `--force` as the envelope instructs. |
|
|
129
|
+
| `--if-revision <n>` | int | Only apply if the body is still at this revision (from `doc show`). |
|
|
129
130
|
|
|
130
|
-
The rebuild is **structure-guarded** (the same guard as `doc update`/`doc patch`): if the serializer would drop any table/row/heading, it is rejected with **422** rather than silently committing a flattened source — `--allow-shrink` is the explicit escape hatch. A doc that already has a source is refused
|
|
131
|
+
The rebuild is **structure-guarded** (the same guard as `doc update`/`doc patch`): if the serializer would drop any table/row/heading, it is rejected with **422** rather than silently committing a flattened source — `--allow-shrink` is the explicit escape hatch. A doc that already has a source is refused by the server (409); the CLI turns that refusal into a **confirmation envelope** (exit 4, `changes` = the server's reason + what `--force` would replace) so the user sees it before anything is overwritten.
|
|
131
132
|
|
|
132
133
|
```bash
|
|
133
|
-
lumo doc rebuild-source cmd_xxx
|
|
134
|
-
lumo doc rebuild-source cmd_xxx
|
|
134
|
+
lumo doc rebuild-source cmd_xxx # restore a source-less doc; --raw works after
|
|
135
|
+
lumo doc rebuild-source cmd_xxx # source exists → exit 4 + envelope, nothing written
|
|
136
|
+
lumo doc rebuild-source cmd_xxx --force --confirm # re-derive after the user approved the envelope
|
|
135
137
|
```
|
|
136
138
|
|
|
137
139
|
### When to suggest `doc rebuild-source`
|
|
138
140
|
|
|
139
141
|
- A `--raw` / `--section` / `doc patch` / `doc diff` call errored with "no stored markdown source" — rebuild, then retry. This is the first thing to try, not a manual reconstruction.
|
|
140
142
|
- A table-heavy live doc (e.g. a `docs/live-docs/` registry) lost its source after a web operation and the markdown write path is locked.
|
|
141
|
-
- Do **not** run it on a doc that already has a good source unless the user explicitly wants to re-derive it (then
|
|
143
|
+
- Do **not** run it on a doc that already has a good source unless the user explicitly wants to re-derive it (then re-run the envelope's `confirmCommand`, i.e. `--force --confirm`) — it replaces the byte-faithful source with a serializer-derived one.
|
|
142
144
|
|
|
143
145
|
## Out of scope (CLI v1)
|
|
144
146
|
|
|
@@ -164,12 +164,13 @@ lumo doc move "Sub-doc" --root
|
|
|
164
164
|
- User says "move doc X under Y", "reparent X to root", "promote X to top level".
|
|
165
165
|
- After `doc create`, if the user realizes the new doc should live elsewhere — suggest `doc move` rather than recreating.
|
|
166
166
|
|
|
167
|
-
## `lumo doc delete <doc> --
|
|
167
|
+
## `lumo doc delete <doc> --confirm` — delete a document
|
|
168
168
|
|
|
169
|
-
|
|
169
|
+
Deletes the document **and every document nested under it**. Without `--confirm` the CLI looks the doc up and exits **4** with a confirmation envelope (`Will delete document cmd_xxx "Title"` + the nested-docs rule) — nothing is deleted; relay `changes` to the user and re-run `confirmCommand` on approval ([confirmation.md](confirmation.md)). `--yes` is a legacy alias.
|
|
170
170
|
|
|
171
171
|
```bash
|
|
172
|
-
lumo doc delete cmd_xxx
|
|
172
|
+
lumo doc delete cmd_xxx # exit 4 + envelope
|
|
173
|
+
lumo doc delete cmd_xxx --confirm # after the user approved
|
|
173
174
|
```
|
|
174
175
|
|
|
175
176
|
## `lumo doc bind <doc> <task>` / `lumo doc unbind <doc> <task>` — task linkage
|
|
@@ -32,7 +32,7 @@ lumo project memory add [<project>] --category convention --rule "..." --applies
|
|
|
32
32
|
# Single-memory ops (memoryId from `... memory list` column 1)
|
|
33
33
|
lumo memory show <memoryId> # show one memory's full card by id
|
|
34
34
|
lumo memory promote <memoryId> # TASK → PROJECT
|
|
35
|
-
lumo memory rm <memoryId> --
|
|
35
|
+
lumo memory rm <memoryId> --confirm # hard delete (without --confirm: exit 4 + envelope)
|
|
36
36
|
|
|
37
37
|
# Downsync team memory into the local Claude Code memory store
|
|
38
38
|
lumo memory sync # write team/<id>.md + a managed MEMORY.md block
|
|
@@ -68,9 +68,11 @@ lumo project memory add lumo --category procedural --workflow "Regenerate the CL
|
|
|
68
68
|
# Curate
|
|
69
69
|
lumo memory show cmpi19iqabc123
|
|
70
70
|
lumo memory promote cmpi19iqabc123
|
|
71
|
-
lumo memory rm cmpi19iqabc123 --
|
|
71
|
+
lumo memory rm cmpi19iqabc123 --confirm
|
|
72
72
|
```
|
|
73
73
|
|
|
74
|
+
`memory rm` is gated by the confirmation protocol ([confirmation.md](confirmation.md)): without `--confirm` it fetches the card and exits **4** with an envelope (`Will hard-delete memory <id> [TRAP]` · `Content: <first line>` · no undo) and deletes nothing. Show that to the user first; `--yes` is a legacy alias of `--confirm`.
|
|
75
|
+
|
|
74
76
|
### `lumo memory show <id>` (progressive disclosure)
|
|
75
77
|
|
|
76
78
|
Fetches one memory's full card by id from the server and prints its category tag
|
|
@@ -194,10 +194,11 @@ lumo milestone criteria verdict "Q3 Launch" cmexit0002 --unmet --note "read mode
|
|
|
194
194
|
|
|
195
195
|
### `lumo milestone delete <identifier>` — delete a milestone
|
|
196
196
|
|
|
197
|
-
|
|
197
|
+
Gated by the confirmation protocol ([confirmation.md](confirmation.md)): without `--confirm` the CLI exits **4** with an envelope (`Will delete milestone "Q3 Launch"` · `12 tasks under it keep their data; only milestoneId is cleared`) and deletes nothing — relay it to the user and re-run `confirmCommand` on approval. `--yes` is a legacy alias. Tasks under the milestone keep their data; their `milestoneId` is cleared.
|
|
198
198
|
|
|
199
199
|
```bash
|
|
200
|
-
lumo milestone delete "Q3 Launch"
|
|
200
|
+
lumo milestone delete "Q3 Launch" # exit 4 + envelope
|
|
201
|
+
lumo milestone delete "Q3 Launch" --confirm # after the user approved
|
|
201
202
|
```
|
|
202
203
|
|
|
203
204
|
### `lumo milestone archive <identifier>` — soft-archive a milestone
|
|
@@ -14,7 +14,7 @@ There is **no `SATISFIED` / `PASS`**. "N sprints and nobody touched it" is the _
|
|
|
14
14
|
## Collection (where signals come from)
|
|
15
15
|
|
|
16
16
|
- **Automatic** — a DONE task reopened (the lineage `REWORKED` transition) is folded into the well as a `REOPENED` signal. No action needed; it happens server-side.
|
|
17
|
-
- **
|
|
17
|
+
- **Git-derived** — a revert (or a content reversal) of the delivery's commits landing on the default branch is recorded from the push webhook as `REVERTED` / `DOWNSTREAM_REDIRECT` (LUM-607). No manual recording path exists any more: the former `lumo outcome record` command was removed in LUM-733 (it was never used — 0 MANUAL signals all-time); CI-derived signals (`CI_REGRESSION` / `ROLLED_BACK`) are a follow-up.
|
|
18
18
|
|
|
19
19
|
## `lumo outcome show <task>`
|
|
20
20
|
|
|
@@ -26,18 +26,6 @@ lumo outcome show LUM-42
|
|
|
26
26
|
|
|
27
27
|
An empty well prints `INCONCLUSIVE` with the reminder that silence is not a pass. A non-empty well prints `REJECTED` and lists each signal (date, kind, source, note).
|
|
28
28
|
|
|
29
|
-
## `lumo outcome record <task> --note "<what reality did>" [--kind <kind>]`
|
|
30
|
-
|
|
31
|
-
Record one human-observed post-hoc rejection. Append-only — every call inserts a new signal; nothing is ever mutated or cleared.
|
|
32
|
-
|
|
33
|
-
```bash
|
|
34
|
-
lumo outcome record LUM-42 --note "reverted in #812 after a prod incident" --kind reverted
|
|
35
|
-
lumo outcome record LUM-42 --note "downstream rewrote the API shape this task introduced" --kind downstream_redirect
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
- `--kind` (case-insensitive, default `manual`): `reverted | rolled_back | ci_regression | downstream_redirect | bypassed | manual`. `reopened` is **not** a manual kind — it is owned by the automatic lineage fold.
|
|
39
|
-
- `--occurred-at <iso>` — when the event actually happened (defaults to now).
|
|
40
|
-
|
|
41
29
|
## `lumo outcome rate [--min N] [--json]`
|
|
42
30
|
|
|
43
31
|
The workspace-level **trust × post-hoc-fate** join (LUM-603, LUM-606). For every delivery that has a frozen forecast snapshot, it buckets the delivery by its **delivery-time verification friction** — two raw counts (`verificationRounds`, `sendBackCount`) frozen at delivery from the append-only `VerificationRun` log, cut at `capturedAt`, then bucketed value-neutrally into `no-verification` / `single-round` / `multi-round-or-sendback` — and reports each bucket's post-hoc **REJECTED** rate from the well. The friction axis replaced the original sample-size forecast-confidence axis (LUM-606), which saturated: every mature-project delivery landed in `high`, so `high`-vs-`low` could never compare. The question it answers once data is sufficient: _do deliveries that took more verification friction get rejected by reality more (fragility) or less (scrutiny) often?_ The bucket names carry **no** good/bad direction — the correlation, not the label, decides.
|
|
@@ -59,7 +47,6 @@ This is the falsifier discipline applied at the **query layer** — it refuses t
|
|
|
59
47
|
|
|
60
48
|
## When to suggest
|
|
61
49
|
|
|
62
|
-
- A teammate says a shipped task **was reverted / rolled back / broke prod / got redone / was bypassed** — record it with `lumo outcome record` so the well carries reality's verdict.
|
|
63
50
|
- Auditing whether a "done" task actually held up — `lumo outcome show <task>` reads the well.
|
|
64
51
|
- Asking whether **verification friction predicts post-hoc fate** (do harder-to-verify deliveries fail more, or less?) — `lumo outcome rate`. Expect `inconclusive` until the well fills; it will never print a correlation the sample can't support.
|
|
65
52
|
- **Never** use it to mark something good: the well has no positive verdict by design. To assert a delivery met its contract, that is the acceptance loop (`lumo verify` / `lumo task status`), not the well.
|
|
@@ -16,6 +16,11 @@ Invoked bare (`lumo plan`) it starts a run; `lumo plan --abandon-active` clears
|
|
|
16
16
|
|
|
17
17
|
**When to suggest**: the user wants to turn the parked idea pool into a plan — "跑一下转换器", "start a planning run", "把想法变成计划".
|
|
18
18
|
|
|
19
|
+
```bash
|
|
20
|
+
lumo plan
|
|
21
|
+
lumo plan --abandon-active
|
|
22
|
+
```
|
|
23
|
+
|
|
19
24
|
## `lumo plan status`
|
|
20
25
|
|
|
21
26
|
Print the active run's current stage — either the working segment or the open `*_READY` gate — plus the deep-link to act on its next gate. With no active run, prompts to run `lumo plan`.
|
|
@@ -36,7 +36,7 @@ When the session is bound, session-start may inject a **"🆕 Review needed: pro
|
|
|
36
36
|
|
|
37
37
|
#### When to suggest
|
|
38
38
|
|
|
39
|
-
Briefly sanity-check each listed memory against the codebase/context. If one is wrong or over-generalized, remove it with `lumo memory rm <id
|
|
39
|
+
Briefly sanity-check each listed memory against the codebase/context. If one is wrong or over-generalized, remove it with `lumo memory rm <id>` — it exits 4 with a confirmation envelope; show it to the user and re-run with `--confirm` only on their approval ([confirmation.md](confirmation.md)). If they all look right, ignore the section and continue.
|
|
40
40
|
|
|
41
41
|
### Blocker alert injected at `session attach` / session-start
|
|
42
42
|
|
|
@@ -73,7 +73,7 @@ Detected 3 candidate dependencies awaiting confirmation: run `lumo task deps lis
|
|
|
73
73
|
Watch for EITHER the `## ⚠ Dependency alerts` header (form A) OR the standalone hint line (form B).
|
|
74
74
|
|
|
75
75
|
- `lumo task deps list <LUM-N>` — inspect the full edge list (run for any candidate hint, form A or B; confirm real SUGGESTED edges, dismiss false positives — unreviewed edges mean repeated hints every session).
|
|
76
|
-
- `lumo task deps rm <LUM-N> <edge> --
|
|
76
|
+
- `lumo task deps rm <LUM-N> <edge> --confirm` — drop a manually-added, now-obsolete edge (exit 4 + envelope without `--confirm`).
|
|
77
77
|
- `lumo task deps dismiss <LUM-N> <edge>` — dismiss a false positive from detection.
|
|
78
78
|
- Form A live blockers: evaluate whether to wait — overlapping work (same files, same API surface) risks rework; read the blocker's status and open-PR note before deciding.
|
|
79
79
|
- Do **not** blindly start work on a task whose live blocker is still IN_PROGRESS or IN_REVIEW unless the user explicitly decides to proceed in parallel.
|
|
@@ -134,7 +134,7 @@ lumo session attach --steward cmxyz123... # by milestone id
|
|
|
134
134
|
- **Multiple stewards per milestone are allowed** (acceptance is multi-round by nature); sessions don't conflict.
|
|
135
135
|
- **Prior-milestone learnings injected at attach (LUM-647):** the attach prints a `## Prior-milestone learnings (this project)` section — the **MILESTONE-scope** memories distilled from this project's earlier milestone-close retros (a cross-milestone learning unit), wrapped in the `<untrusted-team-memory>` boundary. Empty when the project has no prior distilled learnings; the current milestone's own rows are excluded. A resumed steward session re-gets it via the session-start hook. These memories are written automatically when a milestone closes and its retro is generated — there is no manual command to author them.
|
|
136
136
|
|
|
137
|
-
**Allowed (governance — pass through unchanged, with the session recorded as provenance):** `task create` / `task update`, `task criteria set` (incl. `--human`), `task deps confirm/dismiss`, `
|
|
137
|
+
**Allowed (governance — pass through unchanged, with the session recorded as provenance):** `task create` / `task update`, `task criteria set` (incl. `--human`), `task deps confirm/dismiss`, `milestone add/remove`, and **all read operations**.
|
|
138
138
|
|
|
139
139
|
**Blocked (implementation — first layer, API gate):**
|
|
140
140
|
|