@lumoai/cli 1.35.0 → 1.37.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 +11 -5
- package/assets/skill/references/criteria.md +13 -0
- package/assets/skill/references/docs.md +3 -1
- package/assets/skill/references/memory.md +20 -0
- package/assets/skill/references/sessions.md +21 -32
- package/assets/skill/references/task-context.md +66 -3
- package/assets/skill/references/verify.md +57 -6
- package/dist/cli/src/commands/cost.js +107 -0
- package/dist/cli/src/commands/memory-show.js +57 -0
- package/dist/cli/src/commands/session-wrap.js +6 -9
- package/dist/cli/src/commands/task-create.js +23 -6
- package/dist/cli/src/commands/task-figma-context.js +4 -0
- package/dist/cli/src/commands/task-lineage.js +39 -2
- package/dist/cli/src/commands/task-slack-show.js +9 -4
- package/dist/cli/src/commands/task-status.js +12 -0
- package/dist/cli/src/commands/task-web-show.js +7 -2
- package/dist/cli/src/commands/verdict.js +13 -18
- package/dist/cli/src/commands/verify.js +8 -0
- package/dist/cli/src/index.js +21 -5
- package/dist/cli/src/lib/doc-input.js +7 -0
- package/dist/cli/src/lib/hook-runner.js +27 -46
- package/dist/cli/src/lib/report-pull.js +49 -0
- package/package.json +1 -1
- package/dist/cli/src/commands/wrap/progress-comment-section.js +0 -81
- package/dist/cli/src/lib/progress-comment-api.js +0 -47
package/assets/skill/SKILL.md
CHANGED
|
@@ -27,6 +27,7 @@ The command catalog below is a **map**: it lists every command grouped by domain
|
|
|
27
27
|
| `task artifact*`, `task figma*` | [references/artifacts-figma.md](references/artifacts-figma.md) |
|
|
28
28
|
| `task criteria set/list`, drafting the acceptance contract | [references/criteria.md](references/criteria.md) |
|
|
29
29
|
| `verify`, `task status` — machine verification loop, claim-done flow, self-check/resume | [references/verify.md](references/verify.md) |
|
|
30
|
+
| `cost` — per-operation (per-tool) token cost read-out; `task lineage` Top-5 | [references/task-context.md](references/task-context.md) |
|
|
30
31
|
| `project list`, `milestone*` | [references/milestones.md](references/milestones.md) |
|
|
31
32
|
| `doc*` | [references/docs.md](references/docs.md) |
|
|
32
33
|
| `sprint*` | [references/sprints.md](references/sprints.md) |
|
|
@@ -51,11 +52,11 @@ The command catalog below is a **map**: it lists every command grouped by domain
|
|
|
51
52
|
- `lumo task figma context <id> <linkId>` — Figma link metadata (v1)
|
|
52
53
|
- `lumo task comments list <id>` — comment thread, capped to the output budget (`--full` prints every comment; read-only; ≠ `task comment`)
|
|
53
54
|
- `lumo task pr show <id> <number>` — synced PR metadata (v1)
|
|
54
|
-
- `lumo task lineage <id>` — show the causal trail: fragments that fed the task + each one's outcome + the run's token/loop cost (read-only audit view); `lumo task lineage <id> --signal` also appends workspace-level usage signal-health (used distribution, per-session variance, used-vs-base merge rate)
|
|
55
|
+
- `lumo task lineage <id>` — show the causal trail: fragments that fed the task + each one's outcome (each fragment line shows its disclosure tag: `· INDEX pulled` / `· INDEX not-pulled` / `· FULL`) + the run's token/loop cost (read-only audit view); totals include a single-task disclosure-funnel summary (`- Disclosure funnel: N impressions · M INDEX (X%) · K pulled (Y% of INDEX) · J used (Z%)`) and a per-task **"Top operations by token cost"** Top-5 — the most expensive tools by attributed token cost, with a pointer to the full breakdown via `lumo cost --task <id>`; `lumo task lineage <id> --signal` also appends workspace-level usage signal-health (used distribution, per-session variance, used-vs-base merge rate via iteration-taint fold — tasks with a send-back/reopen/PR-close count as the negative class even if later merged; shows negative-class size per side; prints "metric cannot discriminate" when no failure outcomes exist yet; also prints a raw count of mid-flight `--new-scope` spinoffs (recorded, not yet judged — LUM-511 Phase 3)) and a workspace-wide disclosure funnel in the same shape as the single-task line
|
|
55
56
|
|
|
56
57
|
**Tasks** — see [tasks.md](references/tasks.md)
|
|
57
58
|
|
|
58
|
-
- `lumo task create <title> [flags]` — create a task
|
|
59
|
+
- `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).
|
|
59
60
|
- `lumo task update <id> [flags]` — patch status/title/priority/assignee/milestone/sprint/tags
|
|
60
61
|
- `lumo task list [flags]` — list tasks assigned to you
|
|
61
62
|
- `lumo next [--count N]` — recommend the next task to work on (read-only)
|
|
@@ -79,8 +80,12 @@ The command catalog below is a **map**: it lists every command grouped by domain
|
|
|
79
80
|
**Verification (machine acceptance loop)** — see [verify.md](references/verify.md)
|
|
80
81
|
|
|
81
82
|
- `lumo verify [task] [--timeout <seconds>]` — run every MACHINE criterion's checkpointer locally, report one structured PASS/FAIL verdict per criterion to the server, print next actions. Defaults to the session-bound task. Round cap 3: an all-pass round moves the task to IN_REVIEW (agent stops there); a round-3 fail escalates to a human (stop retrying). **Run this before claiming a task is done.**
|
|
82
|
-
- `lumo task status [task] [--json]` — read-only acceptance self-check (no LLM, milliseconds): the contract with each criterion's latest verdict (REVIEW_ADDED provenance visible), verification history, current round, last round's failure reasons, `nextActions` = the unmet criteria (the declarative "what's next" — no separate plan), and any OPEN (undispositioned) boundary crossings (count + per crossing category/severity/detail + a read-only attribution line `↳ by model=…·agent=…·session=…` naming who/what crossed, `unknown` when unresolved — LUM-469; `--json` adds an `openCrossings` field, each entry carrying an `attribution` object) — read-only awareness, disposition stays web + human-only (LUM-448). The crossings check fails closed (LUM-480): if the read errors, the block prints `⚠ Boundary-crossing check failed` instead of staying silent, and `--json` sets `openCrossings: null` (distinct from `[]` = a successful read with zero open — treat `null` as "could not confirm", not "safe"). Defaults to the session-bound task; `--json` emits a versioned payload (`version` field). **Run it first when resuming a task in a new session or after a verification round was rejected.**
|
|
83
|
-
- `lumo verdict [task] --pass | --
|
|
83
|
+
- `lumo task status [task] [--json]` — read-only acceptance self-check (no LLM, milliseconds): the contract with each criterion's latest verdict (REVIEW_ADDED provenance visible), verification history, current round, last round's failure reasons, a per-criterion **send-back lifecycle** line when applicable (`↳ send-back (rN) resolved in rM · PR #K` / `… open` — LUM-511 Phase 5), `nextActions` = the unmet criteria (the declarative "what's next" — no separate plan), and any OPEN (undispositioned) boundary crossings (count + per crossing category/severity/detail + a read-only attribution line `↳ by model=…·agent=…·session=…` naming who/what crossed, `unknown` when unresolved — LUM-469; `--json` adds an `openCrossings` field, each entry carrying an `attribution` object) — read-only awareness, disposition stays web + human-only (LUM-448). The crossings check fails closed (LUM-480): if the read errors, the block prints `⚠ Boundary-crossing check failed` instead of staying silent, and `--json` sets `openCrossings: null` (distinct from `[]` = a successful read with zero open — treat `null` as "could not confirm", not "safe"). Defaults to the session-bound task; `--json` emits a versioned payload (`version` field). **Run it first when resuming a task in a new session or after a verification round was rejected.**
|
|
84
|
+
- `lumo verdict [task] --pass | --fail` — acceptance verdicts (LUM-422). `--pass` opens the browser to the human verdict bar focused on Pass (a deep link — **records nothing**; a passing data row is only ever a human's own click). `--fail --reason <enum> [--note <text>] [--criterion <id>…]` records an **AGENT send-back** (verifierType=AGENT, verdict hard-coded FAIL) and bounces the task to IN_PROGRESS. Defaults to the session-bound task. **An unresolved send-back (machine/AGENT/human FAIL) blocks the agent/CLI DONE transition with 409** — clear it (re-verify) before `task update --status done`.
|
|
85
|
+
|
|
86
|
+
**Cost (per-operation token read-out)** — see [task-context.md](references/task-context.md)
|
|
87
|
+
|
|
88
|
+
- `lumo cost [--task <id>|--session <id>|--since <date>] [--by tool|model|member|session] [--json]` — per-operation (per-tool) token cost read-out. Attributes each model step's token delta to the tool(s) it ran (per-step where POST_TOOL_BATCH data exists, per-turn fallback otherwise), output vs cache_read shown separately, plus a per-step coverage line and a "heuristic" note (parallel tools split a step's tokens evenly). Scope is mutually exclusive: `--task` (one task) / `--session` (one Claude Code session) / `--since` (workspace window); default = workspace last-30-days. `--by` only changes which grouping is the headline (the others are still printed when non-trivial). For the per-task Top-5 inline, see `lumo task lineage`.
|
|
84
89
|
|
|
85
90
|
**Artifacts & Figma** — see [artifacts-figma.md](references/artifacts-figma.md)
|
|
86
91
|
|
|
@@ -120,13 +125,14 @@ The command catalog below is a **map**: it lists every command grouped by domain
|
|
|
120
125
|
**Memory** — see [memory.md](references/memory.md)
|
|
121
126
|
|
|
122
127
|
- `lumo task memory add/list` · `lumo project memory add/list` — record/curate Memory (TASK vs PROJECT)
|
|
128
|
+
- `lumo memory show <id>` — show one memory's full card (category + content) by id (progressive disclosure from a one-line index entry)
|
|
123
129
|
- `lumo memory promote <id>` / `lumo memory rm <id> --yes` — TASK→PROJECT / delete
|
|
124
130
|
|
|
125
131
|
**Sessions** — see [sessions.md](references/sessions.md)
|
|
126
132
|
|
|
127
133
|
- `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`.
|
|
128
134
|
- `lumo session status` — show current binding
|
|
129
|
-
- `lumo session wrap [--yes] [--dry-run] [--used <indices>]` — end-of-session panel:
|
|
135
|
+
- `lumo session wrap [--yes] [--dry-run] [--used <indices>]` — end-of-session panel: memory review + fragment-usage vote (`--used`, LUM-300) + blocked-tag prompt, then a read-only reminder when the bound task has ≥1 OPEN boundary crossing still undispositioned (silent only on a genuine empty read — no wrap-up noise; a crossings-check failure prints a "could not confirm" warning instead of staying silent, LUM-480; pointer is web + human-only, LUM-448). Usage is now also audited automatically when a task reaches DONE (evidence-gated, true-only — confident fragments marked used, the rest left NULL); `session wrap --used` remains the manual override and takes precedence for a session.
|
|
130
136
|
- Git-suggest at session start (suggests `session attach`, never auto-binds) + Layer-2 project-memory review — see the reference
|
|
131
137
|
|
|
132
138
|
**Worktrees (local dev tooling)** — see [worktree.md](references/worktree.md)
|
|
@@ -49,6 +49,19 @@ across all stages: a criterion that already has verification runs is
|
|
|
49
49
|
run-free criterion is hard-deleted. Either way, reword rather than delete when
|
|
50
50
|
possible.
|
|
51
51
|
|
|
52
|
+
### A send-back may mean the contract was wrong — amend it, don't spin off
|
|
53
|
+
|
|
54
|
+
If a send-back reveals the **contract itself** was wrong or incomplete, the right
|
|
55
|
+
move is to **amend the criteria on this task** (`lumo task criteria set <id>`,
|
|
56
|
+
and with `--human` annotate the reason via `--cause NEW_INFO | SCOPE_CHANGE |
|
|
57
|
+
DRAFT_BLIND_SPOT`) and re-verify — **not** to open a new task. Sharpening the
|
|
58
|
+
contract as understanding grows is expected; that's what the drift trail is
|
|
59
|
+
_for_, not something to avoid. **The line:** amending to reflect reality is
|
|
60
|
+
legitimate; **weakening a criterion you were just FAILed on, purely to make it
|
|
61
|
+
pass, is tampering** — it's audited and counts as a failure either way. Deleting
|
|
62
|
+
a failed criterion doesn't help: the DONE gate still blocks on its standing FAIL
|
|
63
|
+
(the run is soft-deleted, the verdict survives).
|
|
64
|
+
|
|
52
65
|
## Scale the contract to the task size
|
|
53
66
|
|
|
54
67
|
The 3–7 range is calibrated for typical multi-file tasks. The criterion count
|
|
@@ -82,7 +82,7 @@ The `Tags:` line is omitted when no tags were attached.
|
|
|
82
82
|
| `--title <text>` | string | New title (cannot be empty). |
|
|
83
83
|
| `--content <text>` | string | Replace content (inline). |
|
|
84
84
|
| `--file <path>` | string | Replace content from file. |
|
|
85
|
-
| (stdin) | — | Pipe to replace content.
|
|
85
|
+
| (stdin) | — | Pipe to replace content. Empty / whitespace-only stdin (a non-TTY shell with nothing piped — the common agent case) is treated as **no content channel**, not a body clear (LUM-505). |
|
|
86
86
|
| `--scope <scope>` | enum | `personal` / `workspace`. |
|
|
87
87
|
| `--project <ref>` | string | Project name/slug. `--project ""` clears the filing. |
|
|
88
88
|
| `--tag <name>` | string (repeatable) | **Bulk replace** the tag set by name. Creates tag if missing. Max 20. Mutually exclusive with `--add-tag*` / `--remove-tag*`. |
|
|
@@ -93,6 +93,8 @@ The `Tags:` line is omitted when no tags were attached.
|
|
|
93
93
|
| `--remove-tag-id <cuid>` | string (repeatable) | Detach tag by id. Unknown ids are a no-op (no side effects). Max 20. |
|
|
94
94
|
| `--allow-shrink` | boolean | Let a body update through even when it drops tables/rows/headings versus the stored body (see structure guard below). |
|
|
95
95
|
|
|
96
|
+
A **metadata-only update leaves the body untouched** (LUM-505): when no content channel is supplied (`--title`/`--scope`/`--project`/tag flags only), the body is omitted from the PATCH — it does not get blanked and the structure guard cannot fire. To deliberately clear or replace the body you must supply a content channel explicitly (`--content ""` to clear, which then hits the structure guard as a shrink → pair with `--allow-shrink`).
|
|
97
|
+
|
|
96
98
|
Optimistic concurrency (LUM-409): `--if-revision <n>` only applies the update if the doc body is still at revision `n` (from `doc show`). Mismatch → 409 conflict, nothing written — re-read, rebase, retry. `--if-revision` alone is not an update (still errors "no fields to update"); same for `--allow-shrink`.
|
|
97
99
|
|
|
98
100
|
**Structure guard (LUM-410), built into the server:** a body update whose new render has **fewer `table` / `tr` / heading elements than the stored body** is rejected with **422** before anything is written — the error names each shrunk category with old→new counts (e.g. `table 1→0, tr 4→0`). This is the `verify-live-doc.ts` reconciliation moved into the write path, so table flattening (LUM-349) and stale-base section loss (#460) fail loudly even when nobody remembers to run the script. When the deletion is intentional (you really are removing a section/table), re-run with `--allow-shrink`. On a 422: don't reach for `--allow-shrink` reflexively — first check whether your edit base is stale (`doc show <doc> --raw`) and rebase. Only markdown-path writes are guarded; web-editor edits and `doc sync` (Google authority) are not.
|
|
@@ -26,6 +26,7 @@ lumo project memory add [<project>] --category convention --rule "..." --applies
|
|
|
26
26
|
# Omitting --agent records the memory as produced by Claude Code.
|
|
27
27
|
|
|
28
28
|
# Single-memory ops (memoryId from `... memory list` column 1)
|
|
29
|
+
lumo memory show <memoryId> # show one memory's full card by id
|
|
29
30
|
lumo memory promote <memoryId> # TASK → PROJECT
|
|
30
31
|
lumo memory rm <memoryId> --yes # hard delete
|
|
31
32
|
```
|
|
@@ -47,10 +48,29 @@ lumo task memory add LUM-42 --category decision --what "Store doc content as Tip
|
|
|
47
48
|
lumo project memory add lumo --category procedural --workflow "Regenerate the CLI grammar snapshot" --trigger "any cli/src/commands change" --step "npx tsx scripts/analysis/lum392-cli-friction/emit-grammar.ts" --step "npx jest scripts/analysis/lum392-cli-friction" --agent claude-code
|
|
48
49
|
|
|
49
50
|
# Curate
|
|
51
|
+
lumo memory show cmpi19iqabc123
|
|
50
52
|
lumo memory promote cmpi19iqabc123
|
|
51
53
|
lumo memory rm cmpi19iqabc123 --yes
|
|
52
54
|
```
|
|
53
55
|
|
|
56
|
+
### `lumo memory show <id>` (progressive disclosure)
|
|
57
|
+
|
|
58
|
+
Fetches one memory's full card by id from the server and prints its category tag
|
|
59
|
+
(`[TRAP]`, `[DECISION]`, `[CONVENTION]`, `[WORKFLOW]`, …) followed by the
|
|
60
|
+
structured `content` body (pretty-printed JSON).
|
|
61
|
+
|
|
62
|
+
- **Arg**: `<memoryId>` (required) — the id you saw in `... memory list` column 1
|
|
63
|
+
or as a one-line index entry at session start. Without it the command errors
|
|
64
|
+
with a usage line and exits 1.
|
|
65
|
+
- **Errors**: not-logged-in (run `lumo auth login`), `401` invalid/revoked key,
|
|
66
|
+
`404` memory not found in your workspace (cross-workspace ids 404 too), other
|
|
67
|
+
non-2xx → generic HTTP error; all exit 1.
|
|
68
|
+
|
|
69
|
+
**When to suggest**: at session start memories arrive as one-line index entries.
|
|
70
|
+
When a specific entry looks relevant to the task at hand, run
|
|
71
|
+
`lumo memory show <id>` to pull its full body before acting on it — read the
|
|
72
|
+
detail on demand instead of carrying every memory's content in context.
|
|
73
|
+
|
|
54
74
|
### Reconcile-on-write & deduplication
|
|
55
75
|
|
|
56
76
|
`memory add` does **not** unconditionally insert a new row. Before writing it:
|
|
@@ -125,18 +125,11 @@ lumo session status
|
|
|
125
125
|
|
|
126
126
|
When to suggest: the user asks "which task am I on", "what's this session bound to", or you need to decide whether to suggest `session attach` for a mentioned task ID.
|
|
127
127
|
|
|
128
|
-
### `lumo session wrap [--yes] [--dry-run] [--used <indices>]` — wrap-up panel:
|
|
128
|
+
### `lumo session wrap [--yes] [--dry-run] [--used <indices>]` — wrap-up panel: memory review + fragment-usage vote + blocked-tag prompt
|
|
129
129
|
|
|
130
|
-
Session-end wrap-up panel with **
|
|
130
|
+
Session-end wrap-up panel with **three sections, run in order**:
|
|
131
131
|
|
|
132
|
-
**1.
|
|
133
|
-
`turnSummary` rows (the one-line summaries written each STOP), aggregates
|
|
134
|
-
every turn **since the last progress comment** into one bulleted body, and — after
|
|
135
|
-
a `[y] post / [e] edit / [s] skip` confirmation — posts it as a comment on the
|
|
136
|
-
session's bound task. A server-side watermark (`Session.lastProgressCommentAt`)
|
|
137
|
-
means re-running never re-posts the same turns.
|
|
138
|
-
|
|
139
|
-
**2. Memory review** — lists the Layer1 memories this session sedimented since the
|
|
132
|
+
**1. Memory review** — lists the Layer1 memories this session sedimented since the
|
|
140
133
|
last review (deduped by a per-session watermark `Session.lastMemoryReviewAt`).
|
|
141
134
|
Each new memory is shown as `[SCOPE] CATEGORY headline`, numbered from 1. You
|
|
142
135
|
curate with a single line: `d 1,3` deletes rows 1 and 3, `p 2` promotes row 2 to
|
|
@@ -147,7 +140,7 @@ Out-of-range indices are ignored. Deletes/promotes run server-side, scoped to
|
|
|
147
140
|
memories this session created (you can't touch other sessions' memories through
|
|
148
141
|
this panel). With no new memories the section prints "(no content)" and does nothing.
|
|
149
142
|
|
|
150
|
-
**
|
|
143
|
+
**2. Fragment-usage vote (LUM-300)** — lists the context
|
|
151
144
|
fragments this session **consumed** (its lineage edges: memory / slack / web /
|
|
152
145
|
figma / PR / review-todo / session), numbered from 1 with a content snippet
|
|
153
146
|
label. The agent records which it **actually used** via
|
|
@@ -161,7 +154,7 @@ upgrades the flywheel signal from "co-loaded" (constant, no information) to
|
|
|
161
154
|
fragment's usage-based merge rate, falling back to the weaker presence rate when
|
|
162
155
|
usage samples are thin. With no consumed fragments the section prints "(no content)".
|
|
163
156
|
|
|
164
|
-
**
|
|
157
|
+
**3. Blocked check (blocked-tag prompt, LUM-153)** — if the **same kind of failure
|
|
165
158
|
recurred ≥ 3 times** in this session (server-aggregated from
|
|
166
159
|
`POST_TOOL_USE_FAILURE` events grouped by tool name, plus `STOP_FAILURE`
|
|
167
160
|
turn-level failures), the section surfaces the dominant failure (`This session looks repeatedly stuck on <tool> (N failures).` + last error summary) and prompts `[y] tag / [s] skip` whether to
|
|
@@ -177,7 +170,7 @@ shared board requires an interactive `y`, so `--yes` (and non-TTY) prints the
|
|
|
177
170
|
suggestion and moves on rather than silently flipping board state. When there's
|
|
178
171
|
nothing to prompt, the section prints "(no content)".
|
|
179
172
|
|
|
180
|
-
**After the panel — open-crossings reminder (LUM-448).** Once the
|
|
173
|
+
**After the panel — open-crossings reminder (LUM-448).** Once the three sections
|
|
181
174
|
finish, `session wrap` prints a one-shot read-only reminder **if** the bound
|
|
182
175
|
task has ≥1 OPEN (undispositioned) boundary crossing: `⚠ N open boundary
|
|
183
176
|
crossing(s) on LUM-N still undispositioned:` then a line per crossing `• [SEVERITY]
|
|
@@ -194,31 +187,27 @@ clear its own crossing from the terminal.
|
|
|
194
187
|
|
|
195
188
|
```bash
|
|
196
189
|
lumo session wrap # interactive: preview each section, choose per-section
|
|
197
|
-
lumo session wrap --yes #
|
|
190
|
+
lumo session wrap --yes # memories kept; blocked tag NOT auto-applied (needs interactive y)
|
|
198
191
|
lumo session wrap --yes --used 1,3 # also record fragments 1 & 3 as used (the rest used=false)
|
|
199
192
|
lumo session wrap --used none # record that none of the injected fragments were used
|
|
200
|
-
lumo session wrap --dry-run # print all drafts only; never
|
|
193
|
+
lumo session wrap --dry-run # print all drafts only; never mutates, never advances watermarks
|
|
201
194
|
```
|
|
202
195
|
|
|
203
196
|
The usage vote is a two-step flow for agents: run `lumo session wrap` once to
|
|
204
197
|
see the numbered fragment list, decide which you actually used, then re-run with
|
|
205
198
|
`--used <indices>`. Re-running is safe — the other sections are watermark-guarded
|
|
206
|
-
(
|
|
199
|
+
(reviewed memories won't re-list).
|
|
207
200
|
|
|
208
201
|
- Requires `$CLAUDE_CODE_SESSION_ID` (must run inside Claude Code) and a bound
|
|
209
|
-
task (`lumo session attach <LUM-N>` first).
|
|
210
|
-
|
|
211
|
-
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
When to suggest: at the end of a working session on a bound task, to record what
|
|
223
|
-
was done as a progress comment — offer `lumo session wrap` rather than composing
|
|
224
|
-
a `task comment` by hand.
|
|
202
|
+
task (`lumo session attach <LUM-N>` first).
|
|
203
|
+
- `--yes` keeps all memories (no deletes/promotes) while advancing the
|
|
204
|
+
memory-review watermark; for the blocked-tag section it prints the suggestion
|
|
205
|
+
but does **not** apply the tag.
|
|
206
|
+
- `--dry-run` prints all drafts; never mutates memories/tags, never advances the
|
|
207
|
+
memory-review watermark.
|
|
208
|
+
- Non-TTY without `--yes`: prints the drafts and does **not** mutate or tag (safe
|
|
209
|
+
default).
|
|
210
|
+
|
|
211
|
+
When to suggest: at the end of a working session on a bound task, to review the
|
|
212
|
+
memories it sedimented, vote which injected fragments were actually used, and
|
|
213
|
+
flag the task `blocked` if it got repeatedly stuck — offer `lumo session wrap`.
|
|
@@ -132,20 +132,38 @@ identifier (`LUM-N`), prints the causal trail:
|
|
|
132
132
|
|
|
133
133
|
```bash
|
|
134
134
|
lumo task lineage LUM-42 # per-session causal trail + cost
|
|
135
|
-
lumo task lineage LUM-42 --signal # append workspace-level usage signal-health
|
|
135
|
+
lumo task lineage LUM-42 --signal # append workspace-level usage signal-health; used-vs-base merge rate uses iteration-taint fold (send-back/reopen/PR-close = negative class even if later merged); shows negative-class size per side; prints "metric cannot discriminate" when no failure outcomes exist yet
|
|
136
136
|
```
|
|
137
137
|
|
|
138
138
|
- **Totals banner** — distinct sessions, fragment count, edge count,
|
|
139
139
|
total tokens (input/output/cache split) and loops, and the outcome
|
|
140
|
-
distribution.
|
|
140
|
+
distribution. After the outcome summary, one funnel line is appended:
|
|
141
|
+
`- Disclosure funnel: N impressions · M INDEX (X%) · K pulled (Y% of INDEX) · J used (Z%)`
|
|
142
|
+
where impressions = edge count, INDEX% and used% are over impressions,
|
|
143
|
+
pull% is over INDEX only (FULL fragments have no pull opportunity).
|
|
144
|
+
Divide-by-zero is guarded (zero impressions or zero INDEX renders `0%`).
|
|
145
|
+
When per-fragment token weights have been collected (LUM-522), the line also
|
|
146
|
+
appends `· ~T tokens saved` = Σ(fullTokens − indexTokens) over un-pulled INDEX
|
|
147
|
+
edges (the token cost the index-only injection avoided); the suffix is omitted
|
|
148
|
+
cleanly when no edge carries token data yet (older edges predate the columns).
|
|
141
149
|
- **One block per session** — the group's cost shown **once** (token/loop),
|
|
142
150
|
the date it consumed context, then each context fragment as
|
|
143
|
-
`[OUTCOME] TYPE — <source label>`, plus a
|
|
151
|
+
`[OUTCOME] TYPE — <source label>`, plus a disclosure annotation suffix:
|
|
152
|
+
`· INDEX pulled` (INDEX fragment, `pulledAt` is set) /
|
|
153
|
+
`· INDEX not-pulled` (INDEX fragment, never pulled) /
|
|
154
|
+
`· FULL` (injected in full at session-start).
|
|
155
|
+
Per-group outcome summary follows.
|
|
144
156
|
|
|
145
157
|
Cost is attributed once per session (a session that injected many fragments is
|
|
146
158
|
not double-counted). Fragment ids are canonical — MEMORY fragments survive
|
|
147
159
|
consolidation drift.
|
|
148
160
|
|
|
161
|
+
**`--signal` workspace funnel:** the workspace-level usage signal-health block
|
|
162
|
+
appended by `--signal` ends with a workspace-wide disclosure funnel in the
|
|
163
|
+
same format: `- Disclosure funnel: N impressions · M INDEX (X%) · K pulled (Y% of INDEX) · J used (Z%)`
|
|
164
|
+
aggregated over all edges in the workspace (not just this task) — including the
|
|
165
|
+
same `· ~T tokens saved` suffix when token data exists (LUM-522).
|
|
166
|
+
|
|
149
167
|
**Cold start:** a task with no edges prints a friendly note (lineage is captured
|
|
150
168
|
when a session-bound run consumes the task's context), not an error.
|
|
151
169
|
|
|
@@ -154,3 +172,48 @@ use, and what did it cost" for a task / merged PR — CFO / compliance / trust
|
|
|
154
172
|
narratives.
|
|
155
173
|
|
|
156
174
|
Entry point is the task identifier only; PR-number lookup is a future addition.
|
|
175
|
+
|
|
176
|
+
**Top operations by token cost (LUM-523):** the lineage totals also append a
|
|
177
|
+
per-task **"Top operations by token cost"** Top-5 — the most expensive tools by
|
|
178
|
+
attributed token cost (`<tool> — N tokens`), ending with the pointer
|
|
179
|
+
`(full breakdown: lumo cost --task <id>)`. The block is omitted when no
|
|
180
|
+
per-operation cost has been attributed yet.
|
|
181
|
+
|
|
182
|
+
## `lumo cost`
|
|
183
|
+
|
|
184
|
+
Per-operation (per-tool) token cost read-out. Where `task lineage` answers
|
|
185
|
+
"what context fed this task and what did the run cost," `lumo cost` answers
|
|
186
|
+
"which _operations_ (tools) burned the tokens." It attributes each model step's
|
|
187
|
+
token delta to the tool(s) that ran in it — **per-step** where the
|
|
188
|
+
`POST_TOOL_BATCH` hook captured the tool list, **per-turn fallback** otherwise
|
|
189
|
+
(a parallel-tool step splits its tokens evenly across the tools, hence the
|
|
190
|
+
"heuristic" note). `output` (generation) and `cache_read` (~95%, structural —
|
|
191
|
+
turns × context) are shown in separate columns.
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
lumo cost --task LUM-42
|
|
195
|
+
lumo cost --session <session-id> --by model
|
|
196
|
+
lumo cost --since 2026-06-01 --by member --json
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
- **Scope (mutually exclusive)** — `--task <id>` scopes to one task,
|
|
200
|
+
`--session <id>` to one Claude Code session, `--since <ISO-date>` to a
|
|
201
|
+
workspace window from that date. With none given, the default is a
|
|
202
|
+
**workspace last-30-days** window. (If more than one is passed, the CLI
|
|
203
|
+
picks task > session > since.)
|
|
204
|
+
- **`--by tool|model|member|session`** (default `tool`) — only changes which
|
|
205
|
+
grouping is the **headline** table; the other groupings are still printed
|
|
206
|
+
below when non-trivial (member/session tables appear only when there is more
|
|
207
|
+
than one). Case-insensitive.
|
|
208
|
+
- **`--json`** — emit the versioned payload (`version: 1`, scope, grandTotal,
|
|
209
|
+
coverage, and `byTool` / `byModel` / `byMember` / `bySession` row arrays)
|
|
210
|
+
instead of the rendered tables.
|
|
211
|
+
- **Coverage line** — `Per-step attribution: X% of N tool-using turns` tells
|
|
212
|
+
you how much of the report is precise per-step attribution vs the per-turn
|
|
213
|
+
fallback. `n/a` when there were no tool-using turns.
|
|
214
|
+
|
|
215
|
+
**When to suggest:** the user asks where their tokens went _by operation_ —
|
|
216
|
+
"which tools are most expensive," cost attribution by model / teammate /
|
|
217
|
+
session, or a workspace cost window. For the quick per-task Top-5 inline, point
|
|
218
|
+
them at `lumo task lineage <id>` instead; reach for `lumo cost` for the full
|
|
219
|
+
breakdown or any non-task scope.
|
|
@@ -63,6 +63,18 @@ only).
|
|
|
63
63
|
them; the server rejects partial rounds.
|
|
64
64
|
- Criteria added during review (`REVIEW_ADDED`) appear in the contract and
|
|
65
65
|
are picked up automatically by the next round.
|
|
66
|
+
- **Session bound to a different task (LUM-459)** → the server returns 409,
|
|
67
|
+
which the command surfaces as an error. No advisory is printed; the verify
|
|
68
|
+
round is rejected outright.
|
|
69
|
+
- **Provably-unbound session** → the server includes `bindingAdvisory: 'unbound'`
|
|
70
|
+
in the round response, and the command prints:
|
|
71
|
+
`⚠ Working unbound — this verify ran from a Claude Code session not attached to the task.`
|
|
72
|
+
The run is recorded as a `SESSION_BINDING_MISSING` boundary crossing visible in
|
|
73
|
+
`lumo task status` open crossings. Run `lumo session attach <LUM-N>` before the
|
|
74
|
+
next verify to bind the session.
|
|
75
|
+
- **Unconfirmed session binding** → `bindingAdvisory: 'unconfirmed'` causes a
|
|
76
|
+
softer advisory: `⚠ Could not confirm this session is attached to the task.`
|
|
77
|
+
Same remediation: `lumo session attach <LUM-N>`.
|
|
66
78
|
|
|
67
79
|
## Round discipline
|
|
68
80
|
|
|
@@ -205,17 +217,17 @@ is ever agent-produced.**
|
|
|
205
217
|
|
|
206
218
|
```
|
|
207
219
|
lumo verdict --pass
|
|
208
|
-
lumo verdict LUM-42 --pass
|
|
220
|
+
lumo verdict LUM-42 --pass
|
|
209
221
|
lumo verdict --fail --reason CRITERION_UNMET --note "the retry path is still missing"
|
|
210
222
|
lumo verdict LUM-42 --fail --reason scope_mismatch --criterion c-abc123
|
|
211
223
|
```
|
|
212
224
|
|
|
213
|
-
### --pass
|
|
225
|
+
### --pass — a deep link, never a write
|
|
214
226
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
227
|
+
This resolves the task, then opens the browser to its verdict bar focused on
|
|
228
|
+
Pass. **The CLI writes nothing** — PASS only ever lands from a human's own click
|
|
229
|
+
(Clerk session). Use this to hand a finished task to a human for the final pass;
|
|
230
|
+
it carries them one click from recording it.
|
|
219
231
|
|
|
220
232
|
### --fail — the AGENT send-back
|
|
221
233
|
|
|
@@ -244,3 +256,42 @@ criteria were never adjudicated, transitions freely — the gate only blocks an
|
|
|
244
256
|
actual send-back, never an un-adjudicated criterion. When the machine loop has
|
|
245
257
|
left a task IN_REVIEW with no send-back standing, the agent may move it to DONE
|
|
246
258
|
directly; a human-PASS row is a provable manual override, not a required ticket.
|
|
259
|
+
|
|
260
|
+
## When a defect appears — fix in place, don't spin off a new task
|
|
261
|
+
|
|
262
|
+
On a send-back **or** a self-review finding: if the issue falls under any
|
|
263
|
+
existing acceptance criterion of **this** task, fix it in place and re-run
|
|
264
|
+
`lumo verify`. **Do not** `lumo task create` for it. New tasks are only for work
|
|
265
|
+
genuinely _outside_ this task's acceptance contract. Creating a task (and PR)
|
|
266
|
+
for in-scope rework launders a first-attempt failure — it bypasses the DONE
|
|
267
|
+
gate's send-back protection and corrupts the flywheel signal.
|
|
268
|
+
|
|
269
|
+
This is now enforced: when you're mid-task, `lumo task create` refuses the bare
|
|
270
|
+
form and makes you declare intent — `--rework-of <id>` (it redirects you back to
|
|
271
|
+
fix the existing task and creates nothing) or `--new-scope` (genuinely new,
|
|
272
|
+
separate work). If the send-back reveals the **contract itself** was wrong,
|
|
273
|
+
amend it on this task (`lumo task criteria set`) rather than opening a new
|
|
274
|
+
task — see criteria.md.
|
|
275
|
+
|
|
276
|
+
**Hard rule:** while THIS task has an unresolved send-back (any criterion's
|
|
277
|
+
latest verdict is FAIL — the same condition that blocks DONE), `lumo task create`
|
|
278
|
+
is refused with 409 **even with `--new-scope`**. A standing send-back means the
|
|
279
|
+
task can't be completed yet; resolve it (fix + `lumo verify`, or amend the
|
|
280
|
+
contract) before opening any new work. `--rework-of` still redirects you to it.
|
|
281
|
+
|
|
282
|
+
## Human-reported defects, once a task is submitted
|
|
283
|
+
|
|
284
|
+
When someone reports a defect in conversation, your action depends on whether the
|
|
285
|
+
task has **ever entered IN_REVIEW**:
|
|
286
|
+
|
|
287
|
+
- **Not yet** (still your first working pass) → just fix it and continue. No
|
|
288
|
+
verdict needed — nothing was claimed complete, so there's nothing to contradict.
|
|
289
|
+
- **Already submitted** (entered IN*REVIEW / DONE / merged) → **do not silently
|
|
290
|
+
fix and re-pass.** Either record your own send-back (`lumo verdict --fail`,
|
|
291
|
+
noting it was human-reported — this is \_your* honest concurrence, not a forged
|
|
292
|
+
human verdict), or ask the reporter to record a human FAIL via the web UI /
|
|
293
|
+
Slack (the only channel that can attribute it to a human). If the defect is a
|
|
294
|
+
**new requirement** not covered by any criterion, first transcribe it with
|
|
295
|
+
`lumo task criteria set --human`, then proceed. You can never write a human
|
|
296
|
+
_verdict_ — the terminal can't prove a human is behind the command
|
|
297
|
+
(attribution integrity, not anti-forgery).
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.formatOperationCost = formatOperationCost;
|
|
4
|
+
exports.cost = cost;
|
|
5
|
+
const config_1 = require("../lib/config");
|
|
6
|
+
const api_1 = require("../lib/api");
|
|
7
|
+
/** Deterministic thousands separator (no locale dependency, test-stable). */
|
|
8
|
+
function groupThousands(value) {
|
|
9
|
+
return Math.round(value)
|
|
10
|
+
.toString()
|
|
11
|
+
.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
|
12
|
+
}
|
|
13
|
+
function rankTable(title, rows) {
|
|
14
|
+
if (rows.length === 0)
|
|
15
|
+
return '';
|
|
16
|
+
const lines = [
|
|
17
|
+
title,
|
|
18
|
+
' operation output cache_read total',
|
|
19
|
+
];
|
|
20
|
+
for (const r of rows.slice(0, 20)) {
|
|
21
|
+
lines.push(` ${r.label.slice(0, 20).padEnd(20)} ${groupThousands(r.output).padStart(10)} ${groupThousands(r.cacheRead).padStart(12)} ${groupThousands(r.total).padStart(12)}`);
|
|
22
|
+
}
|
|
23
|
+
return lines.join('\n');
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Render an OperationCostResponse as the per-operation cost report. Pure
|
|
27
|
+
* function (no clock / env / network) so it is deterministic and unit-testable.
|
|
28
|
+
*/
|
|
29
|
+
function formatOperationCost(data, by) {
|
|
30
|
+
const primary = by === 'model'
|
|
31
|
+
? data.byModel
|
|
32
|
+
: by === 'member'
|
|
33
|
+
? data.byMember
|
|
34
|
+
: by === 'session'
|
|
35
|
+
? data.bySession
|
|
36
|
+
: data.byTool;
|
|
37
|
+
const pct = data.coverage.perStepPct == null
|
|
38
|
+
? 'n/a'
|
|
39
|
+
: `${Math.round(data.coverage.perStepPct * 100)}%`;
|
|
40
|
+
const out = [];
|
|
41
|
+
out.push(`Per-operation cost — ${data.scope.kind} ${data.scope.label}`);
|
|
42
|
+
out.push(`Total: output ${groupThousands(data.grandTotal.output)} · cache_read ${groupThousands(data.grandTotal.cacheRead)} · all ${groupThousands(data.grandTotal.total)} tokens`);
|
|
43
|
+
out.push(`Per-step attribution: ${pct} of ${data.coverage.toolTurns} tool-using turns (rest fall back to per-turn split)`);
|
|
44
|
+
out.push('');
|
|
45
|
+
out.push(rankTable(`By ${by}:`, primary));
|
|
46
|
+
if (by !== 'tool')
|
|
47
|
+
out.push('\n' + rankTable('By tool:', data.byTool));
|
|
48
|
+
if (by !== 'model')
|
|
49
|
+
out.push('\n' + rankTable('By model:', data.byModel));
|
|
50
|
+
if (by !== 'member' && data.byMember.length > 1)
|
|
51
|
+
out.push('\n' + rankTable('By member:', data.byMember));
|
|
52
|
+
if (by !== 'session' && data.bySession.length > 1)
|
|
53
|
+
out.push('\n' + rankTable('By session:', data.bySession));
|
|
54
|
+
out.push('');
|
|
55
|
+
out.push('Note: token→tool attribution is heuristic — a model step that fires several tools in parallel splits its tokens evenly across them; cache_read (~95%) is structural (turns × context), shown alongside output (generation).');
|
|
56
|
+
return out.join('\n');
|
|
57
|
+
}
|
|
58
|
+
async function cost(opts) {
|
|
59
|
+
const creds = (0, config_1.readCredentials)();
|
|
60
|
+
if (!creds) {
|
|
61
|
+
console.error('Error: not logged in. Run `lumo auth login` first.');
|
|
62
|
+
return 1;
|
|
63
|
+
}
|
|
64
|
+
const byArg = opts.by?.toLowerCase();
|
|
65
|
+
const by = byArg === 'model' || byArg === 'member' || byArg === 'session'
|
|
66
|
+
? byArg
|
|
67
|
+
: 'tool';
|
|
68
|
+
const params = new URLSearchParams();
|
|
69
|
+
if (opts.task)
|
|
70
|
+
params.set('task', opts.task);
|
|
71
|
+
else if (opts.session)
|
|
72
|
+
params.set('session', opts.session);
|
|
73
|
+
else if (opts.since)
|
|
74
|
+
params.set('since', opts.since);
|
|
75
|
+
const apiUrl = (0, api_1.resolveAuthedApiUrl)(creds.apiUrl);
|
|
76
|
+
const qs = params.toString();
|
|
77
|
+
const url = `${(0, api_1.trimTrailingSlash)(apiUrl)}/api/cost${qs ? `?${qs}` : ''}`;
|
|
78
|
+
let res;
|
|
79
|
+
try {
|
|
80
|
+
res = await fetch(url, {
|
|
81
|
+
headers: { Authorization: `Bearer ${creds.token}` },
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
catch (err) {
|
|
85
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
86
|
+
console.error(`Error: could not reach Lumo API at ${apiUrl} (${msg})`);
|
|
87
|
+
return 1;
|
|
88
|
+
}
|
|
89
|
+
if (res.status === 401) {
|
|
90
|
+
console.error('Error: API key invalid or revoked. Run `lumo auth login`.');
|
|
91
|
+
return 1;
|
|
92
|
+
}
|
|
93
|
+
if (res.status === 404) {
|
|
94
|
+
console.error(`Error: task ${opts.task ?? ''} not found in workspace ${creds.workspaceSlug}`);
|
|
95
|
+
return 1;
|
|
96
|
+
}
|
|
97
|
+
if (!res.ok) {
|
|
98
|
+
console.error(`Error: server returned HTTP ${res.status}`);
|
|
99
|
+
return 1;
|
|
100
|
+
}
|
|
101
|
+
const data = (await res.json());
|
|
102
|
+
if (opts.json) {
|
|
103
|
+
console.log(JSON.stringify(data, null, 2));
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
console.log(formatOperationCost(data, by));
|
|
107
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.memoryShow = memoryShow;
|
|
4
|
+
const config_1 = require("../lib/config");
|
|
5
|
+
const api_1 = require("../lib/api");
|
|
6
|
+
const sanitize_1 = require("../lib/sanitize");
|
|
7
|
+
const report_pull_1 = require("../lib/report-pull");
|
|
8
|
+
/**
|
|
9
|
+
* `lumo memory show <memory-id>`
|
|
10
|
+
*
|
|
11
|
+
* Progressive disclosure: fetch one memory's full card by id from
|
|
12
|
+
* `/api/memories/:id`. The agent sees memories as one-line index entries at
|
|
13
|
+
* session start; this pulls the body of a specific one on demand. Prints the
|
|
14
|
+
* category tag and the structured content.
|
|
15
|
+
*/
|
|
16
|
+
async function memoryShow(id) {
|
|
17
|
+
if (!id) {
|
|
18
|
+
console.error('Error: usage: lumo memory show <memory-id>');
|
|
19
|
+
return 1;
|
|
20
|
+
}
|
|
21
|
+
const creds = (0, config_1.readCredentials)();
|
|
22
|
+
if (!creds) {
|
|
23
|
+
console.error('Error: not logged in. Run `lumo auth login` first.');
|
|
24
|
+
return 1;
|
|
25
|
+
}
|
|
26
|
+
const apiUrl = (0, api_1.resolveAuthedApiUrl)(creds.apiUrl);
|
|
27
|
+
const base = (0, api_1.trimTrailingSlash)(apiUrl);
|
|
28
|
+
let res;
|
|
29
|
+
try {
|
|
30
|
+
res = await fetch(`${base}/api/memories/${encodeURIComponent(id)}`, {
|
|
31
|
+
headers: { Authorization: `Bearer ${creds.token}` },
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
36
|
+
console.error(`Error: could not reach Lumo API at ${apiUrl} (${msg})`);
|
|
37
|
+
return 1;
|
|
38
|
+
}
|
|
39
|
+
if (res.status === 401) {
|
|
40
|
+
console.error('Error: API key invalid or revoked. Run `lumo auth login`.');
|
|
41
|
+
return 1;
|
|
42
|
+
}
|
|
43
|
+
if (res.status === 404) {
|
|
44
|
+
console.error(`Error: memory ${id} not found in workspace ${creds.workspaceSlug}`);
|
|
45
|
+
return 1;
|
|
46
|
+
}
|
|
47
|
+
if (!res.ok) {
|
|
48
|
+
console.error(`Error: memory show failed (HTTP ${res.status})`);
|
|
49
|
+
return 1;
|
|
50
|
+
}
|
|
51
|
+
const { memory } = (await res.json());
|
|
52
|
+
console.log((0, sanitize_1.sanitizeField)(`[${memory.category}]`));
|
|
53
|
+
console.log((0, sanitize_1.sanitizeField)(JSON.stringify(memory.content, null, 2)));
|
|
54
|
+
// LUM-500: stamp the disclosure funnel. The arg id == lineage MEMORY
|
|
55
|
+
// fragmentId. Fire-and-forget — never blocks output, swallows failures.
|
|
56
|
+
await (0, report_pull_1.reportPull)({ fragmentType: 'MEMORY', fragmentId: id });
|
|
57
|
+
}
|
|
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.sessionWrap = sessionWrap;
|
|
4
4
|
const config_1 = require("../lib/config");
|
|
5
5
|
const wrap_panel_1 = require("../lib/wrap-panel");
|
|
6
|
-
const progress_comment_section_1 = require("./wrap/progress-comment-section");
|
|
7
6
|
const memory_review_section_1 = require("./wrap/memory-review-section");
|
|
8
7
|
const fragment_usage_section_1 = require("./wrap/fragment-usage-section");
|
|
9
8
|
const blocked_prompt_section_1 = require("./wrap/blocked-prompt-section");
|
|
@@ -11,13 +10,12 @@ const crossings_reminder_1 = require("./wrap/crossings-reminder");
|
|
|
11
10
|
/**
|
|
12
11
|
* `lumo session wrap [--yes] [--dry-run]`
|
|
13
12
|
*
|
|
14
|
-
* Session-end wrap-up panel with
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* (LUM-
|
|
20
|
-
* prompt whether to flag the bound task with a `blocked` tag (LUM-153).
|
|
13
|
+
* Session-end wrap-up panel with three sections, run in order: (1) review the
|
|
14
|
+
* Layer1 memories this session sedimented — keep/delete/promote, deduped by a
|
|
15
|
+
* per-session watermark; (2) vote which injected context fragments were
|
|
16
|
+
* actually used (LUM-300, via `--used`); (3) if the session repeatedly hit the
|
|
17
|
+
* same failure, prompt whether to flag the bound task with a `blocked` tag
|
|
18
|
+
* (LUM-153).
|
|
21
19
|
*/
|
|
22
20
|
async function sessionWrap(options) {
|
|
23
21
|
const sessionId = process.env.CLAUDE_CODE_SESSION_ID;
|
|
@@ -32,7 +30,6 @@ async function sessionWrap(options) {
|
|
|
32
30
|
return 1;
|
|
33
31
|
}
|
|
34
32
|
const sections = [
|
|
35
|
-
new progress_comment_section_1.ProgressCommentSection({ creds, sessionId }),
|
|
36
33
|
new memory_review_section_1.MemoryReviewSection({ creds, sessionId }),
|
|
37
34
|
new fragment_usage_section_1.FragmentUsageSection({ creds, sessionId, used: options.used }),
|
|
38
35
|
new blocked_prompt_section_1.BlockedPromptSection({ creds, sessionId }),
|