@lumoai/cli 1.58.0 โ 1.60.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 +15 -17
- package/assets/skill/references/artifacts-figma.md +4 -3
- package/assets/skill/references/confirmation.md +133 -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 +4 -4
- 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 +71 -71
- package/assets/skill/references/worktree.md +13 -7
- package/dist/cli/src/commands/crossing-disposition.js +342 -0
- package/dist/cli/src/commands/crossing-explain.js +10 -21
- 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 +196 -111
- 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 +60 -48
- package/dist/cli/src/lib/blocked-error.js +183 -0
- package/dist/cli/src/lib/bound-task.js +32 -0
- package/dist/cli/src/lib/confirmation.js +119 -0
- package/dist/cli/src/lib/hook-runner.js +23 -11
- package/dist/cli/src/lib/open-crossings.js +6 -6
- package/dist/shared/src/referent-kind.js +31 -1
- package/dist/shared/src/security-scan.js +125 -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
|
@@ -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
|
|
|
@@ -142,7 +142,7 @@ lumo session attach --steward cmxyz123... # by milestone id
|
|
|
142
142
|
- Moving a task to `in_progress` with **yourself as the effective assignee** (whether already assigned to you or assigned in the same call) โ 409. Dispatching to _someone else_ is planning and passes.
|
|
143
143
|
- Red line unchanged: a steward writes no PASS of any kind; DONE stays human-only.
|
|
144
144
|
|
|
145
|
-
**Backstop (second layer, detector):** commits / PR creations produced during a steward session anyway (the CLI can't stop local git) are recorded as **`STEWARD_IMPLEMENTATION_ARTIFACT` boundary crossings against the milestone** โ fail-closed (an unparseable Bash payload records an _unconfirmed_ crossing rather than nothing), disposition stays **web + human-only
|
|
145
|
+
**Backstop (second layer, detector):** commits / PR creations produced during a steward session anyway (the CLI can't stop local git) are recorded as **`STEWARD_IMPLEMENTATION_ARTIFACT` boundary crossings against the milestone** โ fail-closed (an unparseable Bash payload records an _unconfirmed_ crossing rather than nothing), disposition stays **web + human-only** โ `lumo crossing disposition` (LUM-769) is task-scoped and cannot reach a milestone crossing โ and there is **no CLI clear path** (`crossing explain` remains an appeal, never a clear).
|
|
146
146
|
|
|
147
147
|
#### When to suggest
|
|
148
148
|
|
|
@@ -42,15 +42,12 @@ When to suggest: user says "create a sprint", "new sprint", "start a new iterati
|
|
|
42
42
|
|
|
43
43
|
`<identifier>` accepts a sprint number (e.g. `3`) or a UUID. `--team` is required when using a number in a multi-team workspace.
|
|
44
44
|
|
|
45
|
-
Output: key:value header (number, name, status, dates, team), then a `Progress:` line, then a
|
|
45
|
+
Output: key:value header (number, name, status, dates, team), then a `Progress:` line, then a `Blockers:` section, then a task table listing every task in the sprint.
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
`Blockers:` lists the top offenders per category (`Overdue` / `Stalled` / `Agent fail` / `Stale PRs`) โ a task counts as stalled after 7 days untouched, a PR as stale after 3 days awaiting review. A sprint with nothing in any category prints no `Blockers:` section at all. (There is no risk score or `Health:` line โ LUM-709 removed the risk-assessment layer.)
|
|
48
48
|
|
|
49
49
|
```
|
|
50
50
|
Progress: 4 / 10
|
|
51
|
-
Health: AT-RISK
|
|
52
|
-
- 4/10 tasks overdue (40%)
|
|
53
|
-
- 3 tasks with no progress in 7 days
|
|
54
51
|
Blockers:
|
|
55
52
|
Overdue: LUM-1 Fix login, LUM-8 Wire API
|
|
56
53
|
Stalled: LUM-5 Add tests
|
|
@@ -63,7 +60,7 @@ lumo sprint show 3 --team backend
|
|
|
63
60
|
lumo sprint show 11111111-2222-3333-4444-555555555555
|
|
64
61
|
```
|
|
65
62
|
|
|
66
|
-
When to suggest: user asks "what's in sprint 3", "show me the current sprint", "what tasks are in this sprint", "
|
|
63
|
+
When to suggest: user asks "what's in sprint 3", "show me the current sprint", "what tasks are in this sprint", "what's blocking this sprint".
|
|
67
64
|
|
|
68
65
|
### `lumo sprint update <identifier> [flags]` โ patch a sprint
|
|
69
66
|
|
|
@@ -83,12 +80,13 @@ lumo sprint update 3 --end 2026-06-21
|
|
|
83
80
|
|
|
84
81
|
When to suggest: user wants to rename a sprint, extend dates, or fix sprint metadata.
|
|
85
82
|
|
|
86
|
-
### `lumo sprint delete <identifier> --
|
|
83
|
+
### `lumo sprint delete <identifier> --confirm` โ delete a sprint (DRAFT only)
|
|
87
84
|
|
|
88
|
-
|
|
85
|
+
Without `--confirm` the CLI exits **4** with a confirmation envelope (`Will delete sprint #3 "Sprint 3"` ยท `N tasks under it keep their data; only sprintId is cleared`) and deletes nothing โ relay it to the user, re-run `confirmCommand` on approval ([confirmation.md](confirmation.md)). `--yes` is a legacy alias. Server rejects with an error if the sprint is ACTIVE or CLOSED.
|
|
89
86
|
|
|
90
87
|
```bash
|
|
91
|
-
lumo sprint delete 3
|
|
88
|
+
lumo sprint delete 3 # exit 4 + envelope
|
|
89
|
+
lumo sprint delete 3 --confirm # after the user approved
|
|
92
90
|
```
|
|
93
91
|
|
|
94
92
|
When to suggest: user wants to remove a draft sprint that was created by mistake.
|
|
@@ -107,18 +105,21 @@ When to suggest: user says "start the sprint", "kick off sprint 3", "activate sp
|
|
|
107
105
|
|
|
108
106
|
Handles unfinished tasks based on flags. Without flags: closes only if all tasks are done; otherwise prints a list of unfinished tasks and refuses.
|
|
109
107
|
|
|
110
|
-
| Flag | Type | Notes
|
|
111
|
-
| --------------- | ------- |
|
|
112
|
-
| `--move-all` | boolean | Move all unfinished tasks to the next sprint.
|
|
113
|
-
| `--backlog-all` | boolean | Remove all unfinished tasks from the sprint (send to backlog).
|
|
114
|
-
| `--
|
|
108
|
+
| Flag | Type | Notes |
|
|
109
|
+
| --------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
110
|
+
| `--move-all` | boolean | Move all unfinished tasks to the next sprint. Gated by `--confirm`. |
|
|
111
|
+
| `--backlog-all` | boolean | Remove all unfinished tasks from the sprint (send to backlog). Gated by `--confirm`. |
|
|
112
|
+
| `--confirm` | boolean | The user approved the envelope. Without it a mode flag exits 4 with a confirmation envelope listing every task that would move (`--yes` is a legacy alias). |
|
|
115
113
|
|
|
116
114
|
```bash
|
|
117
|
-
lumo sprint close 3
|
|
118
|
-
lumo sprint close 3 --move-all
|
|
119
|
-
lumo sprint close 3 --
|
|
115
|
+
lumo sprint close 3 # fails (exit 1) if unfinished tasks exist โ pick a mode
|
|
116
|
+
lumo sprint close 3 --move-all # exit 4 + envelope: "2 unfinished tasks move to the next sprint: LUM-3, LUM-4"
|
|
117
|
+
lumo sprint close 3 --move-all --confirm # move unfinished to next sprint (after the user approved)
|
|
118
|
+
lumo sprint close 3 --backlog-all --confirm # send unfinished to backlog
|
|
120
119
|
```
|
|
121
120
|
|
|
121
|
+
See [confirmation.md](confirmation.md) for the envelope shape and the relay rules.
|
|
122
|
+
|
|
122
123
|
When to suggest: user says "close the sprint", "end sprint 3", "wrap up the sprint". If they haven't decided what to do with unfinished tasks, ask before adding `--move-all` or `--backlog-all`.
|
|
123
124
|
|
|
124
125
|
### `lumo sprint summary <identifier> [--retry]` โ fetch AI-generated sprint retro
|
|
@@ -82,12 +82,13 @@ lumo task deps dismiss LUM-42 e5f6a7b8
|
|
|
82
82
|
|
|
83
83
|
Use `dismiss` for false positives. Use `rm` only when you want the pair eligible for re-detection again.
|
|
84
84
|
|
|
85
|
-
## `lumo task deps rm <LUM-N> <edge> --
|
|
85
|
+
## `lumo task deps rm <LUM-N> <edge> --confirm` โ delete an edge
|
|
86
86
|
|
|
87
|
-
Hard-deletes the edge row.
|
|
87
|
+
Hard-deletes the edge row. Without `--confirm` it resolves the edge, then exits **4** with a confirmation envelope describing it (`Will delete dependency edge [a1b2c3d4] from LUM-42: blocked by LUM-9 "โฆ" (CONFIRMED, manual)`) and sends nothing โ relay `changes` to the user and re-run the envelope's `confirmCommand` on approval (see [confirmation.md](confirmation.md)). `--yes` is a legacy alias of `--confirm`.
|
|
88
88
|
|
|
89
89
|
```bash
|
|
90
|
-
lumo task deps rm LUM-42 a1b2c3d4
|
|
90
|
+
lumo task deps rm LUM-42 a1b2c3d4 # exit 4 + envelope, nothing deleted
|
|
91
|
+
lumo task deps rm LUM-42 a1b2c3d4 --confirm # after the user approved
|
|
91
92
|
# Removed [a1b2c3d4] from LUM-42
|
|
92
93
|
```
|
|
93
94
|
|
|
@@ -120,14 +120,46 @@ The server's transition matrix (`lib/task/state-machine.ts`):
|
|
|
120
120
|
|
|
121
121
|
Practical rules:
|
|
122
122
|
|
|
123
|
-
- **One call suffices.** `--status done` straight from TODO or IN_PROGRESS is legal โ never walk `in_progress โ in_review โ done` as a ritual; it just wastes calls.
|
|
123
|
+
- **One call suffices.** `--status done` straight from TODO or IN_PROGRESS is legal โ never walk `in_progress โ in_review โ done` as a ritual; it just wastes calls. That one call **walks the confirmation protocol** (see below): without `--confirm` it exits 4 with an envelope, never a prompt.
|
|
124
124
|
- **Under the verify flow you don't set `in_review`/`done` at all** โ `lumo verify` moves the task to IN_REVIEW on all-pass and the DONE adjudication is human-only.
|
|
125
125
|
- **A DONE task can be reopened** โ to IN_REVIEW, IN_PROGRESS, or TODO. Reopening is a plain status change and does not alter any recorded acceptance verdict; verdict adjudication is human-only and has no CLI path. To attach context without reopening, `lumo task comment` works.
|
|
126
126
|
|
|
127
|
+
### `--status done` requires `--confirm` โ the confirmation envelope (LUM-755)
|
|
128
|
+
|
|
129
|
+
DONE is the one status move that needs a human's sign-off. It no longer prompts (LUM-731's interactive yes/no question is gone): run without `--confirm`, the CLI looks the task up, prints a **confirmation envelope** on stdout and exits **4** with nothing sent โ no PATCH, and no tag resolution either. The envelope's `changes` carry everything the old prompt showed, including a trailing `โ ` line when a linked PR has not merged (that line replaces the old second prompt โ the protocol is one step, and you relay the whole block). Full protocol: [confirmation.md](confirmation.md).
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
lumo task update LUM-48 --status done
|
|
133
|
+
# exit 4, stdout (JSON when piped; the same lines as text on a TTY):
|
|
134
|
+
# {
|
|
135
|
+
# "status": "confirmation_required",
|
|
136
|
+
# "command": "task update",
|
|
137
|
+
# "changes": [
|
|
138
|
+
# "Will move LUM-48 \"Title\" to DONE",
|
|
139
|
+
# "Status: IN_REVIEW โ DONE",
|
|
140
|
+
# "#926 merged refactor: panel https://github.com/o/r/pull/926",
|
|
141
|
+
# "#930 open feat: wip https://github.com/o/r/pull/930",
|
|
142
|
+
# "โ 1 linked pull request not merged: #930 open"
|
|
143
|
+
# ],
|
|
144
|
+
# "confirmCommand": "lumo task update LUM-48 --status done --confirm"
|
|
145
|
+
# }
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
With no linked PR the PR lines collapse to `Pull requests: none linked` and there is no `โ ` line. Other flags on the same call (`--title`, `--add-tag`โฆ) are preserved in `confirmCommand`.
|
|
149
|
+
|
|
150
|
+
- **Show `changes` to the user and wait for an explicit yes**, then run `confirmCommand` unchanged. `--confirm` means the user confirmed โ never add it on your own.
|
|
151
|
+
- With `--confirm` the PATCH goes out directly. The server's own DONE gates still apply on top โ an unresolved send-back, an undispositioned boundary crossing or a blocking security finding refuses with **409**, which the CLI turns into a structured **`DONE_BLOCKED` error on stdout with exit 5**: the 409 text verbatim, a `blockers[]` with ids (built from `task status` + the crossings read model), and `remediation` lines that only name human-side or user-approved paths. Nothing on `task update` clears any of them โ relay, don't retry. A boundary crossing is the one blocker with a terminal path, `lumo crossing disposition <id> โฆ` (itself exit-4: the user rules, never you); once every blocker is cleared, re-run this `--confirm` call. See [confirmation.md](confirmation.md) "When the gate is human-only". Any other 409 stays plain text, exit 1.
|
|
152
|
+
- `--confirm` is the only flag: there is no `--yes` or `--force` on `task update`. Every other status (`todo` / `in_progress` / `in_review`) PATCHes directly and ignores `--confirm`.
|
|
153
|
+
- A failed lookup (404, network) exits 1 before any envelope.
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
lumo task update LUM-48 --status done --confirm # only after the user approved the envelope
|
|
157
|
+
```
|
|
158
|
+
|
|
127
159
|
### When to suggest `task update`
|
|
128
160
|
|
|
129
161
|
- The user describes a state change in natural language (e.g. "mark LUM-48 as in progress", "rename LUM-12 to ...", "assign LUM-30 to me", "bump the priority on LUM-7").
|
|
130
|
-
- After the agent finishes a task and the user confirms โ
|
|
162
|
+
- After the agent finishes a task and the user confirms โ tell the user to run `lumo task update LUM-N --status done` in their terminal (it prompts for confirmation; an agent shell is non-TTY and is refused).
|
|
131
163
|
- Multiple status changes in a row should each be a separate `update` invocation rather than batched.
|
|
132
164
|
|
|
133
165
|
### Sprint output format
|
|
@@ -21,22 +21,19 @@ lumo verify LUM-42 --note "โฆ" # explicit task (overrides the sessio
|
|
|
21
21
|
lumo verify --note "โฆ" --timeout 900 # per-checkpointer timeout in seconds (default 600)
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
-
**`--note` is
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
่ฎฉ post"); whether it is \_truthful* is the faithfulness audit's job โ so don't
|
|
31
|
-
under- or over-state it. A missing/blank note is refused **before** the round is
|
|
32
|
-
posted, so no round is burned; just re-run with one. (An old CLI that omits it
|
|
33
|
-
still verifies โ the claim degrades to the synthesized run-summary fallback.)
|
|
24
|
+
**`--note` is optional (LUM-733).** It is your one-line self-report โ what
|
|
25
|
+
you did and why it is ready ("ๆๆนไบ X,ๅ ไธบ Y ๅฏ้ชๆถ"). When given and the round
|
|
26
|
+
all-passes into IN_REVIEW, it is frozen as the task's claim (source `AGENT`) and
|
|
27
|
+
judged for faithfulness in the background; when omitted the round still posts
|
|
28
|
+
and the claim degrades to the synthesized run summary. It is never a
|
|
29
|
+
precondition for verifying โ don't hold a round back to word it.
|
|
34
30
|
|
|
35
31
|
## What one round does
|
|
36
32
|
|
|
37
33
|
1. Loads the task's acceptance contract and picks out MACHINE criteria.
|
|
38
|
-
2. Runs each checkpointer locally (shell, cwd = current directory
|
|
39
|
-
|
|
34
|
+
2. Runs each checkpointer locally (shell, cwd = current directory, env = the
|
|
35
|
+
CLI's own minus its private `LUMO_NO_HINTS` mute โ `--no-hints` never
|
|
36
|
+
reaches a checkpointer), one at a time, echoing PASS/FAIL as it goes.
|
|
40
37
|
3. POSTs the structured verdicts; the server records one VerificationRun per
|
|
41
38
|
criterion at round = previous max + 1 and mirrors each verdict as a
|
|
42
39
|
TaskActivity event.
|
|
@@ -64,16 +61,15 @@ errors.
|
|
|
64
61
|
|
|
65
62
|
## Edge cases
|
|
66
63
|
|
|
67
|
-
| Case | Behavior
|
|
68
|
-
| ----------------------------------------------- |
|
|
69
|
-
| **No contract yet** | Error pointing at `lumo task criteria set`; draft the contract first (criteria.md golden rule).
|
|
70
|
-
| **HUMAN-only contract** (zero MACHINE criteria) | Nothing to run; CLI says so and suggests `lumo task update <id> --status in_review` for human review. No server write happens.
|
|
71
|
-
| **Partial round** | A round must cover every MACHINE criterion; the CLI always runs all of them and the server rejects partial rounds.
|
|
72
|
-
| **`REVIEW_ADDED` criteria** | Criteria added during review appear in the contract and are picked up automatically by the next round.
|
|
73
|
-
| **Session bound to a different task** | Server returns 409, surfaced as an error. No advisory printed; the verify round is rejected outright.
|
|
74
|
-
| **
|
|
75
|
-
| **
|
|
76
|
-
| **Unconfirmed session binding** | `bindingAdvisory: 'unconfirmed'` โ softer advisory `โ Could not confirm this session is attached to the task.` Same remediation: `lumo session attach <LUM-N>`. |
|
|
64
|
+
| Case | Behavior |
|
|
65
|
+
| ----------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
66
|
+
| **No contract yet** | Error pointing at `lumo task criteria set`; draft the contract first (criteria.md golden rule). |
|
|
67
|
+
| **HUMAN-only contract** (zero MACHINE criteria) | Nothing to run; CLI says so and suggests `lumo task update <id> --status in_review` for human review. No server write happens. |
|
|
68
|
+
| **Partial round** | A round must cover every MACHINE criterion; the CLI always runs all of them and the server rejects partial rounds. |
|
|
69
|
+
| **`REVIEW_ADDED` criteria** | Criteria added during review appear in the contract and are picked up automatically by the next round. |
|
|
70
|
+
| **Session bound to a different task** | Server returns 409, surfaced as an error. No advisory printed; the verify round is rejected outright. |
|
|
71
|
+
| **Provably-unbound session** | Response carries `bindingAdvisory: 'unbound'`; prints `โ Working unbound โ this verify ran from a Claude Code session not attached to the task.` Recorded as a `SESSION_BINDING_MISSING` boundary crossing (visible in `lumo task status` open crossings). Run `lumo session attach <LUM-N>` before the next verify. |
|
|
72
|
+
| **Unconfirmed session binding** | `bindingAdvisory: 'unconfirmed'` โ softer advisory `โ Could not confirm this session is attached to the task.` Same remediation: `lumo session attach <LUM-N>`. |
|
|
77
73
|
|
|
78
74
|
## Round discipline
|
|
79
75
|
|
|
@@ -105,8 +101,9 @@ nothing and burns no round. Defaults to the session-bound task; an explicit
|
|
|
105
101
|
identifier overrides.
|
|
106
102
|
|
|
107
103
|
```bash
|
|
108
|
-
lumo task status # session-bound task
|
|
104
|
+
lumo task status # session-bound task (core: criteria / next actions / open crossings)
|
|
109
105
|
lumo task status LUM-42 # explicit task
|
|
106
|
+
lumo task status --full # + verification rollup, history, cost, struggle trail, trend
|
|
110
107
|
lumo task status --json # versioned machine-readable payload
|
|
111
108
|
```
|
|
112
109
|
|
|
@@ -125,19 +122,16 @@ what's unmet and why (the exact failure tails), and how many rounds are left.
|
|
|
125
122
|
### What it prints
|
|
126
123
|
|
|
127
124
|
- **Header** โ task identifier/title/status + `verification round N/M` (`M` = the workspace's `verificationMaxRounds`; round 0 = never verified) + an escalation warning when the machine loop is exhausted.
|
|
128
|
-
- **
|
|
129
|
-
|
|
130
|
-
- **Verification** โ what was actually _confirmed_ (measured): the machine-verification rollup `N machine-verified / M human override (of T MACHINE criteria)` over the active MACHINE criteria (relocated here from its old standalone line under `Criteria`), plus `X of Y criteria met by their latest verdict`. **Fail-closed**: before any round runs it prints `no verification has run yet โ the claim is unconfirmed` rather than implying a pass.
|
|
131
|
-
- **Faithfulness** โ the third state over the two columns: whether the CLAIM itself is _true_, read from the persisted faithfulness verdict (no LLM at read time), printed as `โธ Faithfulness โ does the claim match the delivery`. One of `faithful` / `overstated` (claim says more than the diff/PR shows) / `under-reported` (claim says less) / `unjudgeable`, with an `ยท evidence: PR #N ยท <sha>` pointer when the judge cited one. **Fail-closed**: `not yet judged` (no verdict โ distinct from a real `unjudgeable` verdict) and `โฆ (stale โ re-checked on the next batch)` (judged against an older claim snapshot, the verdict still shown) are surfaced explicitly. Omitted only against an older server that doesn't emit it.
|
|
132
|
-
- Carried in `--json` as `claim { text, source }` (`source: 'AGENT' | 'RUN_SUMMARY' | 'DIGEST' | null`; `AGENT` = the verify self-report, `RUN_SUMMARY`/`DIGEST` = the synthesized fallback; `text: null` = none generated) and `faithfulness { state, verdict, evidence, diffShas, prNumbers, judgedAt, judgedClaimAt }` (`state` adds `PENDING`/`STALE` over the four verdicts). Omitted only against an older server that doesn't emit the field. The machine-verification rollup is still carried top-level as `machineVerification`.
|
|
125
|
+
- **Default = the self-check core (LUM-733):** header, Criteria, Last round failures, Next actions, Open boundary crossings. The dashboard sections below (**Verification**, **History**, **Cost**, **Struggle**, **Trend**) print only with `--full` โ they are human-dashboard material and cost context. The claim text and faithfulness verdict are no longer rendered in the terminal (`--json` still carries `claim` / `faithfulness` for scripts).
|
|
126
|
+
- **Verification** (`--full`) โ the measured rollup `N machine-verified / M human override (of T MACHINE criteria)` plus `X of Y criteria met by their latest verdict`; before any round it prints `no verification has run yet`.
|
|
133
127
|
- **Criteria** โ every criterion as `<glyph> <id> [TYPE] SOURCE@rN statement` (โ latest verdict passed / โ failed / โ no verdict yet) with its checkpointer and latest verdict line (failure tail on fail). `REVIEW_ADDED@rN` provenance is visible per row.
|
|
134
128
|
- A passing **MACHINE** criterion's verdict line carries a machine-state tag derived from the read model's `machinePassed` flag, NOT the latest verdict: `ยท machine-verified` when a checkpointer actually passed it (even after a human later signs the task off), or `ยท human override (no machine pass)` when it passes only on a human sign-off with no machine run underneath. This keeps the terminal honest with web โ a machine-verified criterion that a human co-signed no longer reads as a plain human pass.
|
|
135
129
|
- A verdict's **evidence is drillable**, rendered as an indented `โณ evidence:` line under the verdict (PASS _and_ FAIL) instead of the inert raw pointer that used to ride the verdict line โ so a conclusion points at real proof you can act on, not just the `check:` command: a `cmd:` pointer prints the actual command + exit code (`ran \`โฆ\` โ exit N ยท re-run to reproduce`), a `file:`pointer prints a terminal-clickable`path:line`, and a `commit:` pointer prints a navigable web URL (`<repo>/commit/<hash>`, resolved from the local git `origin`remote) or a`git show <hash>`fallback when no remote resolves. A criterion that **requires evidence but has none recorded yet** (e.g. a HUMAN evidence criterion before sign-off) renders an explicit`โณ evidence: pending โ no reference recorded yet`(fail-closed) instead of a bare, dead`[evidence]` tag.
|
|
136
130
|
- A pass can carry a **`โ pre-edit version`** note: the criterion was changed after that verdict (reworded, or its checkpointer was swapped so the recorded evidence ran a different command). The pass still counts as met (a stale pass does not block DONE โ render-only signal), but it vouches for an older version โ **re-run `lumo verify` to re-confirm against the current criterion.** This is the habit whenever you edit a MACHINE criterion's checkpointer mid-task: change the check, then re-verify so the green is honest.
|
|
137
|
-
- **History** โ one line per recorded round: `rN ยท timestamp ยท X PASS / Y FAIL`.
|
|
131
|
+
- **History** (`--full`) โ one line per recorded round: `rN ยท timestamp ยท X PASS / Y FAIL`.
|
|
138
132
|
- **Last round failures** โ the most recent round's FAIL verdicts with their rejection reasons (why the last round bounced).
|
|
139
|
-
- **Cost** โ ่งๅพ 1: the costs a human should weigh, on the same report as the verdict instead of scattered across the web delivery card and `task lineage`. Three lines: **Tokens** (total input+output+cache across the task's sessions), **Active time** (non-idle agent seconds โ ฮฃ per-turn `STOP โ prompt`), and **Rework rounds** (verify rounds that recorded a FAIL). Read from the **same** server-side source the web delivery card consumes (`retrospectiveRepository.loadActuals`), so the two reports cannot drift. Token cost is **fail-closed**: when no session usage was recorded it prints `Tokens: not recorded (no session usage captured)`, kept distinct from a measured `0` (ๆฒกๆตๅฐ vs ่ฑไบ0). Carried in `--json` as `cost { tokenCost, activeTimeSec, reworkRounds }` (`tokenCost: null` = not measured). Omitted only against an older server that doesn't emit the field.
|
|
140
|
-
- **Struggle / rework / outstanding** โ the anti-mum-and-deaf block: **always printed when the contract exists, even on a clean 0-unmet task** so a passing task still shows its scars instead of wiping them to a single PASS count. Lists, when present:
|
|
133
|
+
- **Cost** (`--full`) โ ่งๅพ 1: the costs a human should weigh, on the same report as the verdict instead of scattered across the web delivery card and `task lineage`. Three lines: **Tokens** (total input+output+cache across the task's sessions), **Active time** (non-idle agent seconds โ ฮฃ per-turn `STOP โ prompt`), and **Rework rounds** (verify rounds that recorded a FAIL). Read from the **same** server-side source the web delivery card consumes (`retrospectiveRepository.loadActuals`), so the two reports cannot drift. Token cost is **fail-closed**: when no session usage was recorded it prints `Tokens: not recorded (no session usage captured)`, kept distinct from a measured `0` (ๆฒกๆตๅฐ vs ่ฑไบ0). Carried in `--json` as `cost { tokenCost, activeTimeSec, reworkRounds }` (`tokenCost: null` = not measured). Omitted only against an older server that doesn't emit the field.
|
|
134
|
+
- **Struggle / rework / outstanding** (`--full`) โ the anti-mum-and-deaf block: **always printed when the contract exists, even on a clean 0-unmet task** so a passing task still shows its scars instead of wiping them to a single PASS count. Lists, when present:
|
|
141
135
|
- **rework rounds** โ verify rounds that had a FAIL;
|
|
142
136
|
- **send-backs** โ criteria sent back by a human/agent verdict (a MACHINE verify-loop FAIL is not a ๆๅ), with their open/resolved lifecycle, preserved even for since-removed criteria;
|
|
143
137
|
- **leftover follow-ups** โ criteria whose latest verdict is `PASS_WITH_FOLLOWUP`;
|
|
@@ -146,11 +140,15 @@ what's unmet and why (the exact failure tails), and how many rounds are left.
|
|
|
146
140
|
|
|
147
141
|
When the trail is genuinely empty it states the **basis** (`None recorded โ N rounds run, 0 FAIL, no send-backs, no reopens, no leftover follow-ups`); when nothing has been verified yet it says so (`No verification has run yet โ cannot confirm there were no difficulties`) rather than rendering an implicitly-clean slate. Carried in `--json` as `struggleTrail` (incl. `pullRequests` + `reopens`).
|
|
148
142
|
|
|
149
|
-
- **Trend** โ ่งๅพ 7 ่ถๅฟ้ๅฟซ็
ง: the _movement_ of the key quantities across the task's attempts, not a single snapshot. Where History/Cost/Struggle list current values, this shows direction: **Pass rate** across verification rounds (`r1 60% โ r2 100% (โ +40pts)`), **Cost/session** across the task's sessions (`4.2K โ 1.1K tokens (โ), 5.3K total` โ per-session spend from the same source as the **Cost** total, so the trajectory's points sum to it), and **Rework** accrual (`3 accrued โ 1 FAIL round, 1 reopen, +1 PR cycle (โ from 0)`). **Honest about a single point:** with only one round and one session every quantity is one data point, so it prints `Single attempt so far โ no trajectory yet (a trend needs โฅ2 rounds or sessions)` rather than drawing a fake arrow off one value. When nothing was verified and no cost was measured it says `No verification rounds or measured cost yet โ nothing to trend`. Carried in `--json` as `trend { passRate[], cost[], rework{} }`. Omitted only against an older server.
|
|
143
|
+
- **Trend** (`--full`) โ ่งๅพ 7 ่ถๅฟ้ๅฟซ็
ง: the _movement_ of the key quantities across the task's attempts, not a single snapshot. Where History/Cost/Struggle list current values, this shows direction: **Pass rate** across verification rounds (`r1 60% โ r2 100% (โ +40pts)`), **Cost/session** across the task's sessions (`4.2K โ 1.1K tokens (โ), 5.3K total` โ per-session spend from the same source as the **Cost** total, so the trajectory's points sum to it), and **Rework** accrual (`3 accrued โ 1 FAIL round, 1 reopen, +1 PR cycle (โ from 0)`). **Honest about a single point:** with only one round and one session every quantity is one data point, so it prints `Single attempt so far โ no trajectory yet (a trend needs โฅ2 rounds or sessions)` rather than drawing a fake arrow off one value. When nothing was verified and no cost was measured it says `No verification rounds or measured cost yet โ nothing to trend`. Carried in `--json` as `trend { passRate[], cost[], rework{} }`. Omitted only against an older server.
|
|
150
144
|
|
|
151
|
-
- **Next actions** โ the unmet criteria (latest verdict is not a pass: failed or never verified, HUMAN ones included). This list IS the plan โ recomputed from the event log on every read, never maintained separately. Empty + rounds recorded = awaiting human adjudication.
|
|
152
|
-
- **
|
|
153
|
-
- **
|
|
145
|
+
- **Next actions** โ the unmet criteria (latest verdict is not a pass: failed or never verified, HUMAN ones included) followed by any **undispositioned PR security findings** (LUM-737) as `โข [SECURITY] [SEVERITY] PROVENANCE ruleId โ file:line โ title (PR #n ยท blocks DONE | advisory[ โ <cause>, downgraded])`. The trailing **downgrade cause** appears only on deterministic `secret:*` rows the scanner lowered to LOW โ `placeholder value` (the matched string looks like `โฆEXAMPLE`, `YOUR_โฆ`, `CHANGEME`โฆ) or `test/fixture/doc path`. Downgrading is **not** suppression: the row is still reported so a human decides, and the cause is what lets you tell a recognised test fixture from a real leak without opening the file. Absent on rows scanned before the cause was recorded, and on any row that was not downgraded โ silence means "not downgraded", never "cause unknown". This list IS the plan โ recomputed from the event log + the latest scan per linked PR on every read, never maintained separately. The header counts them separately: `Next actions (N unmet ยท M security findings)`. A finding is **not** a criterion: fix it and push (a fixed fingerprint disappears from the next scan) or a human dispositions it in the web delivery panel โ there is no CLI path to clear one, and a `blocks DONE` finding refuses DONE with 409. Empty + rounds recorded = awaiting human adjudication.
|
|
146
|
+
- **Per-PR scan status** (LUM-735): before the unconfirmed-PR lines, one line per linked PR that has a latest scan (open or closed alike): `PR #945 ยท scan CLEAN ยท Secrets: checked ยท Code scan: checked (2 external findings) ยท Dependencies: checked (1 dependency finding, 1 already on main) ยท AI review: checked ยท Exploit paths: โ incomplete` โ stage segments only for keys present, in secrets/external/supplyChain/judge/hunt order. **The stage keys are internal; what prints is their display label** (LUM-763, `shared/src/security-scan.ts`, shared with the GitHub PR summary so the two cannot drift): `secrets`โSecrets, `external`โCode scan, `supplyChain`โDependencies, `judge`โAI review, `hunt`โExploit paths; states render as `RAN`โchecked, `SKIPPED`โskipped, `NOT_CONFIGURED`โoff, `PENDING`โscanning, `PARTIAL`โโ incomplete, `SUPERSEDED`โโ superseded, `FAILED`โโ failed. "checked" means the layer completed, **not** that it found nothing โ findings are counted in their own segments and in the next-actions list (`hunt` = the L3 vulnerability hunt, LUM-739: absent when `LUMO_SECURITY_HUNT=off`, `SKIPPED` when no trigger fired, `PENDING` while the workflow runs, `RAN` / `PARTIAL` (budget hit, a planned task that never finished, or more surviving candidates than the falsifier cap) / `FAILED`; its findings are `LLM_JUDGE` advisory, never `blocks DONE`); `(N external findings)` (singular at 1) decorates only the Code scan segment, and only when N > 0; `(N dependency findings[, M already on main])` (LUM-738; singular at 1) decorates only the Dependencies segment, only when N > 0, and prints bare `Dependencies: <state>` against an older server without the counts; ` ยท partial` appended when the scan is partial; and, when `stages.external === 'FAILED'` and a **scrubbed scanner reason** was recorded (the `error` column carries the `external: ` provenance prefix), an appended ` โ <reason without the prefix, tail 200 chars>` โ an unprefixed `error` (stage A's own raw crash text) is never printed here, same P8 rule as the web panel and the PR summary (LUM-756). Fed by the additive `securityFindings.scans` array; omitted entirely (no lines) against an older server that doesn't send it.
|
|
147
|
+
- **Hunt coverage line** (LUM-762): indented under its scan line whenever the server sends the L3 hunt's per-category audit โ `Exploit paths 2/3 done ยท t1 idor 41.2s done ยท t2 injection 72.0s done (2 attempts) ยท t3 race skipped`. `<n>/N done` is how many planned tasks finished (where N is the number of tasks the planning step selected for this scan, typically 0โ3). Rows persisted before LUM-758 lack a planned-task count and fall back to the historical 6-category denominator (reading as `/6` instead). Each segment is `[taskId ]<category> <elapsed>s <stop>` โ the `taskId` prefix (`t1`, `t2`, โฆ) appears only on current rows where the task graph is present (post-LUM-758), and is omitted on pre-task-graph audit rows, so they render exactly as they always did. Elapsed is summed over the task's attempts; `(N attempts)` when the workflow retried it; no elapsed for a `skipped` task (the scan's budget ran out before its turn). Stop values: `done` ยท `steps` ยท `budget` ยท `timeout` ยท `error` ยท `skipped`. Headed by the same display label as the layer's own segment (LUM-763), so the detail line and the line above it never name the layer two different ways. This is the only surface that reads `huntAudit`, so it is where you answer "how long does a healthy task take" and "which tasks never ran" without paging through deploy logs. Absent on an older server and on scans with no usable audit (pre-LUM-739 rows, or a hunt that failed before its first batch) โ no line, never a guess.
|
|
148
|
+
- **Persisting findings** (LUM-738): a finding whose fingerprint is already on the repository's default-branch baseline (`persisting`) is not this PR's โ it never appears as a next action, is not counted in `openFindings`, and shows muted (_already on the default branch_) in the web panel. Dependency findings (`kind=DEPENDENCY`, from osv-scanner) are advisory: they never block DONE.
|
|
149
|
+
- **Fails closed:** `โ Security-scan check failed โ could not confirm โฆ` when the scan read errored, and one `โ PR #n: โฆ โ could not confirm it is clean.` line per open PR whose latest scan is missing / FAILED / still running. Silence means a successful read with nothing open, never a failed check.
|
|
150
|
+
- **Open boundary crossings** โ a trailing safety block when the task has โฅ1 OPEN (undispositioned) forbidden-action crossing: a count, then one line per crossing `โข [SEVERITY] CATEGORY โ <clipped detail>` (highest-severity first), each followed by a read-only **attribution** line `โณ by model=<m> ยท agent=<type>[/branch] ยท session=<8-char prefix>` (who/what crossed; any dimension that couldn't be resolved server-side prints `unknown`, never a fabricated value), then a pointer to `lumo crossing disposition` and the web acceptance panel. Silent when there are none, so it never overshadows the criteria.
|
|
151
|
+
- **Read-only awareness** โ this block surfaces crossings detected elsewhere and clears nothing itself. The ruling is the user's: `lumo crossing disposition <id> --false-positive | --confirmed` (exit-4 envelope you relay, LUM-769 โ see below) or the web panel. You never self-approve.
|
|
154
152
|
- **The check fails closed:** if the crossings read itself errors (network / server / parse), the block prints `โ Boundary-crossing check failed (network/server error) โ could not confirm whether any are undispositioned` instead of staying silent. Silence means a successful read with zero open crossings, never a failed check โ a hiccup can no longer masquerade as "all clear".
|
|
155
153
|
|
|
156
154
|
### Responding to an open crossing โ `lumo crossing explain`
|
|
@@ -166,11 +164,32 @@ lumo crossing explain <id> --note "this was a generated fixture, not a hand-edit
|
|
|
166
164
|
This is the **inverse** of dispositioning, but it is the agent/CLI path
|
|
167
165
|
(bearer-only; a clerk/human caller is refused). Behavior:
|
|
168
166
|
|
|
169
|
-
- it can **only append** an append-only note โ it **never clears the crossing or unblocks Done** (disposition
|
|
167
|
+
- it can **only append** an append-only note โ it **never clears the crossing or unblocks Done** (the user rules, via `lumo crossing disposition` or the web panel);
|
|
170
168
|
- the note is shown to the human reviewer at disposition time, kept for later review, and explicitly labeled _agent self-report ยท unverified_;
|
|
171
169
|
- `<id>` must be a crossing on the **session-bound task** (resolved from `$CLAUDE_CODE_SESSION_ID`; cross-task targets and unbound/mismatched sessions are rejected);
|
|
172
170
|
- earlier explanations are immutable โ a correction is a new note.
|
|
173
171
|
|
|
172
|
+
### Recording the user's ruling โ `lumo crossing disposition` (LUM-769)
|
|
173
|
+
|
|
174
|
+
When the user has ruled on a crossing โ in chat, after you relayed it โ record
|
|
175
|
+
that ruling from the terminal instead of sending them to the web panel:
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
lumo crossing disposition <id> --false-positive --note "covered by the run-outbound tests"
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
It is a gated mutation on the [confirmation protocol](confirmation.md), as a **three-step** handshake โ two envelopes, two separate approvals from the user, and the server enforces the order:
|
|
182
|
+
|
|
183
|
+
- **Step 1 โ no step flag.** Reads the crossing, obtains a server-signed stage-1 **read receipt**, and prints an exit-4 envelope โ severity, category, detail, `Seen รN` when it recurred, every explanation you left (labelled _agent self-report ยท unverified_), the note, a `โ ` line saying that approving clears this crossing's block on DONE (plus `โ HIGH severity` / `โ Irreversible category` when they apply), and `Step 1 of 2 โ read receipt issued โฆ valid until <time>`. Nothing is written. Relay every line and **ask the user to confirm they have read it** โ this envelope's `confirmCommand` ends in `--receipt <r1> --confirm-read`, not `--confirm`;
|
|
184
|
+
- **Step 2 โ `--confirm-read --receipt <r1>`**, only after the user says they read it. The server verifies r1 and returns the stage-2 receipt; the CLI prints a second exit-4 envelope for the ruling itself โ `Read acknowledged โฆ (shown <t1>, acknowledged <t2>)`, `Step 2 of 2 โ record the ruling: OPEN โ FALSE_POSITIVE`, the note, the โ consequence line. Still nothing written. Relay it and **ask the user to approve the ruling** โ its `confirmCommand` ends in `--receipt <r2> --confirm`;
|
|
185
|
+
- **Step 3 โ `--confirm --receipt <r2>`**, only after the user approves. POSTs the ruling (`FALSE_POSITIVE` | `CONFIRMED`, optional note, the stage-2 receipt); either value clears that crossing's DONE block, and the audit row records the shown / read-acknowledged / confirmed times. The web panel can still correct it later. **Never add `--confirm-read` or `--confirm` yourself** โ each is the user's approval of that step, and the server records the ruling as a CLI-channel disposition (shown as _via CLI_ in the panel) precisely because it cannot verify the in-chat approvals;
|
|
186
|
+
- **the receipts are the server's ordering check** (LUM-769): each is bound to the crossing, the ruling, your session/member and the crossing's state at read time, and expires after 10 minutes. Confirming the ruling with the stage-1 receipt (read not yet acknowledged) is refused โ locally before any request, and by the server with 409 โ and told to run `--confirm-read` first; a step flag without its receipt, or both step flags at once, is refused locally; a receipt that is forged, expired, for another reader/ruling, or older than the crossing's latest change (a recurrence, a new explanation, a ruling) is refused by the server with 409 and nothing is written โ re-run without a step flag for a fresh envelope. If the server cannot issue receipts (no signing secret configured) step 1 fails closed and no envelope is printed;
|
|
187
|
+
- the crossing is read first on both paths: a read that errors **fails closed** (exit 1, nothing written), an id not on the task is exit 1, and an already-matching ruling is a no-op (exit 0);
|
|
188
|
+
- `<id>` resolves against the **session-bound task**; `--task <LUM-N>` overrides the binding (e.g. from a terminal with no session, or after DONE unbinds you);
|
|
189
|
+
- **still web-only:** reverting a ruling to OPEN, repository suppression rules (LUM-751), and steward milestone crossings (`STEWARD_IMPLEMENTATION_ARTIFACT` has no task).
|
|
190
|
+
|
|
191
|
+
After the last blocker is cleared, re-run the original `lumo task update <id> --status done --confirm` โ its envelope was already approved.
|
|
192
|
+
|
|
174
193
|
### --json contract
|
|
175
194
|
|
|
176
195
|
`--json` emits the full read model with a top-level `version` field (currently
|
|
@@ -181,50 +200,33 @@ fields don't. Pin on `version` when scripting against it.
|
|
|
181
200
|
- the payload carries a top-level `machineVerification` aggregate `{ total, machineVerified, humanOverridden }` over the active MACHINE criteria โ read these, not `latestVerdict` alone, to tell a machine-verified criterion from a human override;
|
|
182
201
|
- open boundary crossings ride along as an additive top-level `openCrossings`, each entry `{ id, category, severity, detail, attribution }` where `attribution` is `{ workspaceMemberId, sessionId, agent, worktreeBranch, model }` with every field nullable โ null = unknown, never fabricated; the array length is the count. Same read-only awareness, no write path;
|
|
183
202
|
- **`openCrossings` is `null` when the crossings check failed** โ distinct from `[]` (a successful read with zero open crossings). Script consumers must treat `null` as "unknown / could not confirm", **not** "safe".
|
|
203
|
+
- `nextActions` entries carry a `kind` discriminator (LUM-737): `CRITERION` (the pre-737 shape: `criterionId`, `statement`, `verifierType`, `checkpointer`, `judgeSteps`, `source`, `addedAtRound`, `rejectionReason`) or `SECURITY_FINDING` (`findingId`, `statement`, `severity`, `provenance`, `blocking`, `prNumber`, `ruleId`, `filePath`, `line`). Additive โ a missing `kind` means `CRITERION`; do not index every entry by `criterionId`;
|
|
204
|
+
- a top-level `securityFindings` summary `{ open, blocking, unconfirmedPrs: [{ number, reason: NONE|FAILED|PENDING|RUNNING }], scans?: [{ prNumber, status, stages, partial, error, externalFindings, openFindings }] }`; **`null` means the scan read failed** โ treat as "unknown / could not confirm", not "safe". `scans` is additive (LUM-735) โ absent against an older server, one entry per linked PR with a latest scan otherwise.
|
|
184
205
|
|
|
185
206
|
`status` reads; `verify` judges. Running status never starts a round, never
|
|
186
207
|
escalates, and never changes task state โ loop rules (the workspace round cap,
|
|
187
208
|
IN_REVIEW on all-pass, human-only DONE) live entirely in `lumo verify` and the
|
|
188
209
|
server.
|
|
189
210
|
|
|
190
|
-
##
|
|
191
|
-
|
|
192
|
-
`lumo verify` is the MACHINE channel. `lumo verdict` covers the other two โ the
|
|
193
|
-
HUMAN pass and the AGENT send-back โ under one red line: **no passing data row is
|
|
194
|
-
ever agent-produced.**
|
|
195
|
-
|
|
196
|
-
```bash
|
|
197
|
-
lumo verdict --pass
|
|
198
|
-
lumo verdict LUM-42 --pass
|
|
199
|
-
lumo verdict --fail --reason CRITERION_UNMET --note "the retry path is still missing"
|
|
200
|
-
lumo verdict LUM-42 --fail --reason scope_mismatch --criterion c-abc123
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
### --pass โ a deep link, never a write
|
|
204
|
-
|
|
205
|
-
This resolves the task, then opens the browser to its verdict bar focused on
|
|
206
|
-
Pass. **The CLI writes nothing** โ PASS only ever lands from a human's own click
|
|
207
|
-
(Clerk session). Use this to hand a finished task to a human for the final pass;
|
|
208
|
-
it carries them one click from recording it.
|
|
209
|
-
|
|
210
|
-
### --fail โ the AGENT send-back
|
|
211
|
-
|
|
212
|
-
`--fail --reason <enum>` records a real verdict row server-side with
|
|
213
|
-
verifierType=AGENT (a channel distinct from MACHINE and HUMAN, so "machine
|
|
214
|
-
all-pass but human FAIL" stays an uncontaminated signal). The verdict is
|
|
215
|
-
hard-coded FAIL โ there is no agent path to a passing verdict. It:
|
|
211
|
+
## Verdict channels
|
|
216
212
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
213
|
+
`lumo verify` is the MACHINE channel. The only other channel is the **human**
|
|
214
|
+
one: a person records PASS or a send-back (FAIL) in the web verdict bar (Clerk
|
|
215
|
+
session). There is no agent-facing verdict command โ the former
|
|
216
|
+
`lumo verdict --fail` AGENT send-back was removed in LUM-733 (17 rows all-time,
|
|
217
|
+
none in the last 30 days); when the machine loop runs out of rounds the task is
|
|
218
|
+
escalated to a human instead. **No passing data row is ever agent-produced.**
|
|
221
219
|
|
|
222
220
|
### The DONE gate
|
|
223
221
|
|
|
224
|
-
Once any criterion's latest verdict is FAIL โ machine
|
|
222
|
+
Once any criterion's latest verdict is FAIL โ machine or human โ moving
|
|
225
223
|
the task to DONE on the agent/CLI path is refused with **409** and the unresolved
|
|
226
224
|
items listed. Clear the send-back (fix + re-verify, or a human PASS) before
|
|
227
|
-
`lumo task update <id> --status done
|
|
225
|
+
`lumo task update <id> --status done` โ which itself walks the confirmation
|
|
226
|
+
protocol: without `--confirm` it exits 4 with an envelope for the user to
|
|
227
|
+
approve, and when the server gate still refuses it exits 5 with a structured
|
|
228
|
+
`DONE_BLOCKED` error listing every blocker (LUM-755, see [tasks.md](tasks.md)
|
|
229
|
+
and [confirmation.md](confirmation.md)).
|
|
228
230
|
|
|
229
231
|
- A task with no criteria, or whose criteria were never adjudicated, transitions freely โ **the gate only blocks an actual send-back, never an un-adjudicated criterion.**
|
|
230
232
|
- When the machine loop has left a task IN_REVIEW with no send-back standing, the agent may move it to DONE directly; a human-PASS row is a provable manual override, not a required ticket.
|
|
@@ -259,9 +261,7 @@ When someone reports a defect in conversation, your action depends on whether th
|
|
|
259
261
|
task has **ever entered IN_REVIEW**:
|
|
260
262
|
|
|
261
263
|
- **Not yet** (still your first working pass) โ just fix it and continue. No verdict needed โ nothing was claimed complete, so there's nothing to contradict.
|
|
262
|
-
- **Already submitted** (entered IN_REVIEW / DONE / merged) โ **do not silently fix and re-pass.**
|
|
263
|
-
- record your own send-back `lumo verdict --fail` (noting it was human-reported โ this is _your_ honest concurrence, not a forged human verdict), or
|
|
264
|
-
- ask the reporter to record a human FAIL via the web UI / Slack (the only channel that can attribute it to a human).
|
|
264
|
+
- **Already submitted** (entered IN_REVIEW / DONE / merged) โ **do not silently fix and re-pass.** Ask the reporter to record a human send-back (FAIL) via the web verdict bar / Slack โ the only channel that can attribute it to a human โ then fix in place and re-run `lumo verify` so the fix lands as a fresh machine round on the record.
|
|
265
265
|
|
|
266
266
|
If the defect is a **new requirement** not covered by any criterion, first
|
|
267
267
|
transcribe it with `lumo task criteria set --human`, then proceed. You can never
|
|
@@ -55,15 +55,21 @@ Errors if the target dir already exists; reuses the branch if it already exists
|
|
|
55
55
|
|
|
56
56
|
## `lumo worktree rm <LUM-N>`
|
|
57
57
|
|
|
58
|
-
Removes the worktree for a task.
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
58
|
+
Removes the worktree for a task. Gated by the confirmation protocol
|
|
59
|
+
([confirmation.md](confirmation.md)): without `--confirm` โ or with
|
|
60
|
+
uncommitted changes and no `--force` โ it exits **4** with an envelope naming
|
|
61
|
+
the path and branch, a `โ โฆ uncommitted changes โฆ discarded` line when dirty,
|
|
62
|
+
and whether the branch is kept or deleted; nothing is removed. A dirty tree's
|
|
63
|
+
`confirmCommand` carries `--force --confirm`. `--yes` is a legacy alias of
|
|
64
|
+
`--confirm`. Keeps the branch by default (it may hold unpushed work / an open
|
|
65
|
+
PR); `--delete-branch` removes it with `git branch -d` (which itself refuses
|
|
66
|
+
an unmerged branch).
|
|
62
67
|
|
|
63
68
|
```bash
|
|
64
|
-
lumo worktree rm LUM-267
|
|
65
|
-
lumo worktree rm LUM-267 --
|
|
66
|
-
lumo worktree rm LUM-267 --
|
|
69
|
+
lumo worktree rm LUM-267 # exit 4 + envelope
|
|
70
|
+
lumo worktree rm LUM-267 --confirm # after the user approved (clean tree)
|
|
71
|
+
lumo worktree rm LUM-267 --force --confirm # dirty tree: discard uncommitted changes
|
|
72
|
+
lumo worktree rm LUM-267 --confirm --delete-branch # also delete lumo/LUM-267โฆ
|
|
67
73
|
```
|
|
68
74
|
|
|
69
75
|
## `lumo worktree list`
|