@iceinvein/agent-skills 0.18.0 → 0.18.2

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/dist/cli/index.js CHANGED
@@ -468,6 +468,7 @@ async function wireSessionStartHook(settingsPath, skillName, directive, scriptPa
468
468
  const legacy = `echo ${shq(directive)}`;
469
469
  let adopted = false;
470
470
  let custom = false;
471
+ let customRunsScript = false;
471
472
  let changed = false;
472
473
  for (const group of settings.hooks.SessionStart) {
473
474
  const kept = [];
@@ -479,6 +480,8 @@ async function wireSessionStartHook(settingsPath, skillName, directive, scriptPa
479
480
  const plain = hook.skill !== undefined || hook.command === legacy;
480
481
  if (!plain) {
481
482
  custom = true;
483
+ if (scriptPath && hook.command?.includes(scriptPath))
484
+ customRunsScript = true;
482
485
  kept.push(hook);
483
486
  continue;
484
487
  }
@@ -499,7 +502,7 @@ async function wireSessionStartHook(settingsPath, skillName, directive, scriptPa
499
502
  }
500
503
  settings.hooks.SessionStart = settings.hooks.SessionStart.filter((group) => !group.hooks || group.hooks.length > 0);
501
504
  if (adopted || custom) {
502
- if (custom && !adopted && scriptPath) {
505
+ if (custom && !adopted && scriptPath && !customRunsScript) {
503
506
  console.warn(`${skillName}: a hand-edited SessionStart hook already carries its directive, so it was left as is and ${scriptPath} was not wired; add it to that entry yourself if you want it.`);
504
507
  }
505
508
  if (changed) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iceinvein/agent-skills",
3
- "version": "0.18.0",
3
+ "version": "0.18.2",
4
4
  "description": "Install agent skills into AI coding tools",
5
5
  "author": "iceinvein",
6
6
  "license": "MIT",
package/skills/index.json CHANGED
@@ -283,7 +283,7 @@
283
283
  "name": "sluice",
284
284
  "description": "Routes work by change shape into four channels (bypass, fast, main, deep) and applies only the rules each channel needs, so a one-line fix does not pay the cost of a multi-subsystem build. Carries seven rules as one-liners in the router and the full treatment in references read only on friction. Checks the finished plan with plan.sh validate rather than trusting it to memory, seeds the run state from it, keeps a deep run's task breakdown in .sluice/run.json so a statusline segment, one status command and a SessionStart hook can answer where the run is (the hook prints a live run at every session start, compaction included), and closes each run with a ledger read out of the session transcript: elapsed, tools, tokens, and what each dispatched agent cost where the transcript recorded it. Claude Code only; stands down where the superpowers pipeline governs the repo.",
285
285
  "type": "prompt",
286
- "version": "0.19.0"
286
+ "version": "0.19.2"
287
287
  },
288
288
  {
289
289
  "name": "temporal-coupling-detector",
@@ -180,8 +180,15 @@ your sign-off and Task 1 begins.
180
180
  **Review.** Name the tasks the table below sends to a reviewer, each with the
181
181
  trigger that qualified it, and say how many of the rest skip with a ledger
182
182
  line. Then offer the choice: dispatch a reviewer at each of them, dispatch
183
- only at tier 3, or hand back with those tasks listed as
184
- review outstanding. The options are what makes the cost legible.
183
+ only at tier 3, or hand back with the whole tier table skipped. The options are
184
+ what makes the cost legible.
185
+
186
+ Whichever comes back, record it with `status.sh preflight --review`. That row is
187
+ what turns the tasks it skips into a coverage level rather than a debt: the count
188
+ stays, because the code is the same either way, but `show`, the bar and `close`
189
+ then name it as the level your partner chose. Unrecorded,
190
+ the same tasks read as unreviewed to the end of the run, which is a nag about a
191
+ decision that was already made. `references/status.md` has the two readings.
185
192
  "Four of nine need a reviewer" is a decision your partner can price; "I will
186
193
  review where appropriate" is not.
187
194
 
@@ -251,9 +258,10 @@ intending to, and the questions are still cheap here and unaskable an hour from
251
258
  now.
252
259
 
253
260
  A session that forbids subagents does not skip this; it changes what the
254
- review options are. Skipping it is how "review outstanding" first appears in
261
+ review options are. Skipping it is how the unreviewed count first appears in
255
262
  the closing summary, at the one moment your partner can no longer do anything
256
- about it.
263
+ about it, and with no answer on file it stays worded as a debt rather than as
264
+ the level anyone chose.
257
265
 
258
266
  ## Dispatch rules
259
267
 
@@ -285,8 +293,10 @@ reads the run state rather than the plan: it sees what has actually landed.
285
293
  implementer back into them. `done --commit <sha> --reviewed` when the review
286
294
  clears, or `done --commit <sha>` alone for a tier 0 task, which was owed a
287
295
  stat read and no dispatch, and for a task whose dispatch pre-flight declined;
288
- the debt count counts the second kind and not the first. That state outlives
289
- compaction; your memory doesn't.
296
+ the count counts the second kind and not the first. A declined dispatch is
297
+ meant to show up there, because the count describes the artifact rather than
298
+ the decision, and the recorded pre-flight answer is what makes it read as
299
+ coverage rather than debt. That state outlives compaction; your memory doesn't.
290
300
  - Each task goes to a fresh agent carrying the brief below and nothing this
291
301
  session accumulated. What you hold is yours to hold, not theirs.
292
302
  - **The run never ends a turn between pre-flight and the handback.** A
@@ -405,9 +415,10 @@ One thing does not change: the work still owes a review. Reading your own diff
405
415
  is not one, and the table below still names which tasks needed the stronger
406
416
  tier. Name those tasks at pre-flight, not at handback, so the choice of what
407
417
  to do about them is still open: shrink the plan, take the flip on its own, or
408
- accept the gap knowingly. Whatever is left then gets listed as review
409
- outstanding rather than review passed, and twice is the cap on saying so here
410
- too: `references/review.md` has that rule. A `deep` run that ships with nobody
418
+ accept the gap knowingly. Record the answer with `preflight --review` and say at
419
+ the handback what was covered and how, rather than claiming those tasks passed a
420
+ review; twice is the cap on saying so here too, and `references/review.md` has
421
+ that rule. A `deep` run that ships with nobody
411
422
  having read it has become a `fast` run with a design document attached, and
412
423
  your partner is entitled to know that while it can still change the plan.
413
424
 
@@ -471,12 +482,17 @@ dispatch, the tasks are interleaved rather than ordered, and reordering them
471
482
  is cheaper than reviewing them.
472
483
 
473
484
  **Mark each review with `status.sh task <id> --reviewed` when it comes back.**
474
- What that buys is a count of what this table promised and nobody delivered: tasks
475
- that are done, that qualified for a dispatch, and that carry no mark. `show` and
476
- the statusline both carry it from the moment it exists, which is the whole point.
477
- Unmarked, the count sits permanently non-zero and stops being a signal, and
478
- "review outstanding" goes back to first appearing in the closing summary, at the
479
- one moment your partner can no longer do anything about it.
485
+ What that buys is a count of the tasks this table sent to a reviewer and nobody
486
+ marked: done, qualified for a dispatch, and carrying no mark. `show` and the
487
+ statusline both carry it from the moment it exists, which is the whole point.
488
+ Unmarked, the count sits permanently non-zero and stops being a signal, and it
489
+ goes back to first appearing in the closing summary, at the one moment your
490
+ partner can no longer do anything about it.
491
+
492
+ With the pre-flight answer on file the same count is the coverage this run
493
+ bought, worded as such and drawn dim. Without it the count is a debt and stays in
494
+ the warning colour. Neither wording shrinks it: what changes is whether the
495
+ number reads as spent or as owed.
480
496
 
481
497
  Reviews are reads, so they are always parallel. Every review a wave earned
482
498
  goes out in one message, and they run while the next wave's implementers work:
@@ -43,12 +43,16 @@ the one list of them. In order:
43
43
  2. The ledger, `scripts/run-stats.sh --tests "<that result>"`, pasted
44
44
  unedited. `references/meter.md`
45
45
  3. In `deep`, `status.sh show`, pasted, so "four of nine, task five blocked,
46
- two unreviewed, final review pending" is on the page rather than in your
47
- account of it. `references/status.md`
46
+ two done at tier 1+ with no dispatch, final review pending" is on the page
47
+ rather than in your account of it. `references/status.md`
48
48
  4. One clause on review: dispatched and clear, dispatched with findings still
49
49
  open, or not dispatched and why. In `deep` that clause covers the per-task
50
- tiers and the final review separately, because the debt count carries one
51
- and not the other.
50
+ tiers and the final review separately, because the count carries one and not
51
+ the other. Where pre-flight priced the level, say what was covered and how,
52
+ not that review is outstanding: "reviewed at the level you chose, a
53
+ controller stat read plus the final whole-plan pass rather than a per-task
54
+ dispatch" is the accurate line, and it is a coverage level rather than a
55
+ debt. Where nothing was priced, it is a debt and says so.
52
56
  5. The three options, and nothing after them.
53
57
 
54
58
  A `deep` run closes when the work stops being yours to act on: after a local
@@ -36,16 +36,20 @@ worktree>` finds nothing. Statuses
36
36
  are `todo`, `active`, `review`, `done` and `blocked`. A new id needs `--name`;
37
37
  after that every call is a bare flip, so keeping it current costs one command
38
38
  per transition rather than a paragraph. `close` archives the run under
39
- `.sluice/archive/`, prints one line saying what it archived, progress, review
40
- debt and whether the final review landed, and frees the tree for the next one.
39
+ `.sluice/archive/`, prints one line saying what it archived, progress, how many
40
+ tasks shipped without a dispatch and whether the final review landed, and frees
41
+ the tree for the next one.
41
42
 
42
43
  The controller writes every row. An implementer reports its SHA in its reply
43
44
  and touches nothing under `.sluice/`; the brief in `references/deep-channel.md`
44
45
  says so to it. `active` is the dispatch, `review` is the commit in and a
45
46
  reviewer out, with the task's paths still held because a finding may send the
46
47
  implementer back into them, and `done` is the end: with `--reviewed` when a
47
- review cleared it, without when the tier owed one and pre-flight declined it,
48
- which is the row the debt count counts.
48
+ review cleared it, without when the tier qualified for one and pre-flight
49
+ declined it, which is the row the no-dispatch count counts. Declining is meant
50
+ to show up there: the count describes the artifact, not the decision, and a
51
+ chosen skip that erased itself would leave a number that only ever recorded
52
+ accidents.
49
53
 
50
54
  A task going `active` with no `--base` takes the HEAD of the tree the command
51
55
  is pointed at, `--dir` if given and the current tree otherwise, once; a base
@@ -148,8 +152,8 @@ have gone that way. Those are different claims.
148
152
  ## Reading it back
149
153
 
150
154
  `show` prints the whole run: channel, topic, how many tasks are done, the plan
151
- and record paths, how long it has sat idle once that passes a day, the review
152
- debt, the final review, the pre-flight answers, and a row per task with its
155
+ and record paths, how long it has sat idle once that passes a day, the tasks
156
+ that shipped without a dispatch, the final review, the pre-flight answers, and a row per task with its
153
157
  base, commit, tier and model. Run it after compaction instead of reconstructing the
154
158
  run from what you remember, and run it in the message that hands the work back,
155
159
  where "four of nine, task five blocked" is a fact your partner can act on.
@@ -170,9 +174,9 @@ from what the whole bar would occupy, gaps included, rather than from the task
170
174
  count: keyed off the count alone the schedule was not monotonic, and thirty tasks
171
175
  at two cells each ran wider than twelve at three.
172
176
 
173
- **A done task still owed a review trails the review glyph**, `▰▰▨` against
174
- `▰▰▰`. Debt then reads in position rather than only as a count at the end of the
175
- row, which is the difference between knowing how much there is and knowing where.
177
+ **A done task that got no dispatch trails the review glyph**, `▰▰▨` against
178
+ `▰▰▰`. The gap then reads in position rather than only as a count at the end of
179
+ the row, which is the difference between knowing how much there is and knowing where.
176
180
  Tier 0 was never owed a dispatch, so it reads as plainly done. On a plan long
177
181
  enough to narrow cells to one, there is no trailing cell to give up and the
178
182
  positional reading stops: the count in the third row is then the only carrier,
@@ -186,16 +190,40 @@ flips and `import` clears a stale one, so the bar is only ever asked to draw the
186
190
  single legal case.
187
191
 
188
192
  The third row carries the progress count, whichever task wants attention, and the
189
- review debt. A blocked task displaces the active one there, being the one of the
190
- two worth interrupting for, and a `+n` follows when more than one task shares that
191
- state, since a plan running four wide has four actives by design.
193
+ no-dispatch count. A blocked task displaces the active one there, being the one of
194
+ the two worth interrupting for, and a `+n` follows when more than one task shares
195
+ that state, since a plan running four wide has four actives by design.
192
196
 
193
197
  Mark a review with `task <id> --reviewed` when a reviewer comes back. What that
194
- buys is the debt count: a task that is done, that the tier table owed a dispatch,
195
- and that nobody marked. Tier 0 is excluded, having only ever been owed a stat
196
- read. Without it "review outstanding" first appears in the closing summary, at
197
- the one moment your partner can no longer do anything about it, and `show` and
198
- the statusline both carry it from the moment it exists.
198
+ buys is the count: a task that is done, that the tier table qualified for a
199
+ dispatch, and that nobody marked. Tier 0 is excluded, having only ever been owed
200
+ a stat read. Without it that count first appears in the closing summary, at the
201
+ one moment your partner can no longer do anything about it, and `show` and the
202
+ statusline both carry it from the moment it exists.
203
+
204
+ ## Coverage against debt
205
+
206
+ The same count reads two ways, and which one it gets turns on whether
207
+ `preflight --review` has an answer on file.
208
+
209
+ With an answer, the level was priced at the stop and the tasks it skipped were
210
+ spent rather than forgotten. `show` calls it `coverage`, with the answer itself
211
+ on the `pre-flight` row three lines below rather than repeated beside the count;
212
+ the bar says `⟲ 9 at the chosen level` dim rather than in the warning colour, and
213
+ `close` says `9 at the chosen review level`. That is a fact about how
214
+ far review reached, not a thing still to do, and a run that keeps calling it
215
+ outstanding is nagging your partner about a decision they already made.
216
+
217
+ With no answer on file, nobody priced anything. `show` calls it `unreviewed`, the
218
+ bar and `close` say the same, and the warning colour stays: the dispatches the
219
+ tier table promised are genuinely owed, and the absence of a pre-flight answer is
220
+ the evidence that nobody weighed them.
221
+
222
+ What never changes is the number. Nine tasks that shipped without a second pair
223
+ of eyes carry the same risk whether the skip was chosen or forgotten, and the
224
+ count is there to say how far coverage reached. Erasing a chosen skip would turn
225
+ it into a measure of diligence, which is not what anyone reads it for. So the
226
+ word moves and the number does not.
199
227
 
200
228
  ## The next wave
201
229
 
@@ -31,6 +31,52 @@ CONFIGURED="$(jq -r '.statusLine.command // empty' "$SETTINGS" 2>/dev/null || tr
31
31
  [ -n "$CONFIGURED" ] || exit 0
32
32
 
33
33
  RENDER="$(cd "$(dirname "$RENDER")" && pwd)/$(basename "$RENDER")"
34
+ # Physical, and so is every candidate below it: a tmpdir or a home reached
35
+ # through a symlink resolves one way from here and the other way out of a
36
+ # settings string, and the containment check below compares the two.
37
+ CONFIG="$(cd "$BUNDLE/../.." && pwd -P)"
38
+
39
+ # Someone who pasted the two lines a release ago has nothing left to do, and
40
+ # saying it again on every update is the one thing they cannot switch off. So
41
+ # the script the slot runs is read before anything is printed.
42
+ #
43
+ # It is recovered rather than known: settings.json holds a shell command, so
44
+ # every token carrying a slash is tried as a path, with the two variables a
45
+ # config path is ever written through expanded by substitution. Not by eval,
46
+ # which on a settings file means running its contents. A token that resolves to
47
+ # nothing is skipped and the instructions print as they did before, so a command
48
+ # this cannot read costs a notice rather than a wrong silence.
49
+ #
50
+ # Only paths inside the config directory this skill installed into are opened.
51
+ # The slot is someone elses shell string and may name anything; a postinstall
52
+ # that followed it wherever it pointed would be reading arbitrary files off a
53
+ # line it does not control.
54
+ statusline_script() {
55
+ local tok path dir
56
+ for tok in $(printf '%s' "$1" | tr -s "\"'| \t" '\n'); do
57
+ case "$tok" in */*) ;; *) continue ;; esac
58
+ path="$tok"
59
+ path="${path//\$\{CLAUDE_CONFIG_DIR:-\$HOME\/.claude\}/$CONFIG}"
60
+ path="${path//\$\{CLAUDE_CONFIG_DIR\}/$CONFIG}"
61
+ path="${path//\$CLAUDE_CONFIG_DIR/$CONFIG}"
62
+ path="${path//\$\{HOME\}/$HOME}"
63
+ path="${path//\$HOME/$HOME}"
64
+ case "$path" in "~/"*) path="$HOME/${path#\~/}" ;; esac
65
+ [ -f "$path" ] || continue
66
+ dir="$(cd "$(dirname "$path")" 2>/dev/null && pwd -P)"
67
+ [ -n "$dir" ] || continue
68
+ path="$dir/$(basename "$path")"
69
+ case "$path" in "$CONFIG"/*) ;; *) continue ;; esac
70
+ printf '%s\n' "$path"
71
+ return 0
72
+ done
73
+ return 1
74
+ }
75
+
76
+ SLOT_SCRIPT="$(statusline_script "$CONFIGURED" || true)"
77
+ if [ -n "$SLOT_SCRIPT" ] && grep -q "skills/sluice/scripts/statusline.sh" "$SLOT_SCRIPT" 2>/dev/null; then
78
+ exit 0
79
+ fi
34
80
 
35
81
  # The slot points at the bundled command: the install claimed it and there is
36
82
  # nothing for anyone to paste. Say so rather than print instructions that would
@@ -189,22 +189,23 @@ if [ "$SUB" = "line" ]; then
189
189
  def clean: if type == "string" then gsub("[\u0000-\u001f\u007f]"; "") else . end;
190
190
  def paint($c; $t): "\($esc)[\($c)m\($t)\($esc)[0m";
191
191
  def join_parts: map(select(. != null and . != "")) | join(" \($esc)[2m·\($esc)[0m ");
192
- # Done splits in two. A task that is done and was owed a review nobody has
193
- # marked keeps the done shape but trails the review glyph, so the debt reads
194
- # in position rather than only as a count. Tier 0 was never owed a dispatch,
195
- # so it is plainly done.
196
- def cellgroup($w):
192
+ # Done splits in two. A task that is done and got no dispatch keeps the done
193
+ # shape but trails the review glyph, so where the gap is reads in position
194
+ # rather than only as a count. Tier 0 was never owed a dispatch, so it is
195
+ # plainly done. $mark is the marker colour: a level pre-flight chose is a
196
+ # fact about coverage and draws dim, one nobody priced is a warning.
197
+ def cellgroup($w; $mark):
197
198
  (.status == "done"
198
199
  and (.tier // 0) >= 1
199
- and (.reviewed // false) == false) as $owed
200
+ and (.reviewed // false) == false) as $nodispatch
200
201
  | (if .status == "done" then ["32", "▰"]
201
202
  elif .status == "active" then ["96", "◈"]
202
203
  elif .status == "review" then ["33", "▨"]
203
204
  elif .status == "blocked" then ["91", "▮"]
204
205
  else ["2", "▱"]
205
206
  end) as $s
206
- | if $owed and $w > 1
207
- then paint($s[0]; ($s[1] * ($w - 1))) + paint("33"; "▨")
207
+ | if $nodispatch and $w > 1
208
+ then paint($s[0]; ($s[1] * ($w - 1))) + paint($mark; "▨")
208
209
  else paint($s[0]; ($s[1] * $w))
209
210
  end;
210
211
 
@@ -219,7 +220,12 @@ if [ "$SUB" = "line" ]; then
219
220
  else 1 end) as $w
220
221
  | (if $w > 1 then " " else "" end) as $gap
221
222
  | ([.tasks[]? | select(.status == "done")] | length) as $done
222
- | ([.tasks[]? | select(.status == "done" and (.tier // 0) >= 1 and (.reviewed // false) == false)] | length) as $debt
223
+ | ([.tasks[]? | select(.status == "done" and (.tier // 0) >= 1 and (.reviewed // false) == false)] | length) as $nodispatch
224
+ # A pre-flight review answer on file means the stop happened and the level
225
+ # was priced, so the tasks it skipped were spent rather than forgotten. The
226
+ # count is the same either way, because the gap in the code is the same; the
227
+ # word is not, and "unreviewed" on a level someone chose reads as a nag.
228
+ | (((.preflight.review // "") | length) > 0) as $priced
223
229
  | [.tasks[]? | select(.status == "blocked")] as $blockedAll
224
230
  | [.tasks[]? | select(.status == "active")] as $activeAll
225
231
  | ($blockedAll | first) as $blocked
@@ -257,14 +263,17 @@ if [ "$SUB" = "line" ]; then
257
263
  # what the flip means, and a name in the header could not say it.
258
264
  ( " " + ([ .tasks[]?
259
265
  | (if .flips then paint("95"; "┃") + $gap else "" end)
260
- + cellgroup($w)
266
+ + cellgroup($w; (if $priced then "2" else "33" end))
261
267
  ] | join($gap)) ),
262
268
  ( " " + ([ paint("1"; "\($done)/\(.tasks | length)") + " done",
263
269
  (if $blocked then paint("1;91"; "!T\($blocked.id) \($blocked.name // "" | clean)")
264
270
  elif $active then paint("96"; "▸T\($active.id)") + " " + ($active.name // "" | clean)
265
271
  else "" end)
266
272
  + (if $attn > 1 then paint("2"; " +\($attn - 1)") else "" end),
267
- (if $debt > 0 then paint("33"; "⟲ \($debt) unreviewed") else "" end)
273
+ (if $nodispatch == 0 then ""
274
+ elif $priced then paint("2"; "⟲ \($nodispatch) at the chosen level")
275
+ else paint("33"; "⟲ \($nodispatch) unreviewed")
276
+ end)
268
277
  ] | join_parts)
269
278
  )
270
279
  ' "$STATE" 2>/dev/null || exit 0
@@ -607,8 +616,17 @@ case "$SUB" in
607
616
  end
608
617
  end)
609
618
  + (if .paused then ["paused \(.paused | clean)"] else [] end)
610
- + (([.tasks[]? | select(.status == "done" and (.tier // 0) >= 1 and (.reviewed // false) == false)] | length) as $debt
611
- | if $debt == 0 then [] else ["unreviewed \($debt) done, owed a review the tier table promised"] end)
619
+ # Same count, two readings. A pre-flight review answer on file says the
620
+ # level was priced at the stop, so what it skipped is the coverage of this
621
+ # run. With no answer on file nobody priced anything and the dispatches in
622
+ # the tier table are still owed. The answer itself is not repeated here:
623
+ # the pre-flight row below carries it, three lines down.
624
+ + (([.tasks[]? | select(.status == "done" and (.tier // 0) >= 1 and (.reviewed // false) == false)] | length) as $nodispatch
625
+ | if $nodispatch == 0 then []
626
+ elif ((.preflight.review // "") | length) > 0
627
+ then ["coverage \($nodispatch) done at tier 1+, no dispatch"]
628
+ else ["unreviewed \($nodispatch) done at tier 1+, owed a review and no pre-flight answer"]
629
+ end)
612
630
  + ["final review " + (if .final_review then "done" else "pending" end)]
613
631
  + ["pre-flight " + (
614
632
  if (.preflight // {} | length) == 0 then "not recorded"
@@ -793,9 +811,13 @@ case "$SUB" in
793
811
  # allowed to stop the archive.
794
812
  summary="$(jq -r '
795
813
  ([.tasks[]? | select(.status == "done")] | length) as $done
796
- | ([.tasks[]? | select(.status == "done" and (.tier // 0) >= 1 and (.reviewed // false) == false)] | length) as $debt
814
+ | ([.tasks[]? | select(.status == "done" and (.tier // 0) >= 1 and (.reviewed // false) == false)] | length) as $nodispatch
815
+ | (((.preflight.review // "") | length) > 0) as $priced
797
816
  | [ "closed \(.topic // "run"): \($done)/\(.tasks | length) done",
798
- (if $debt > 0 then "\($debt) unreviewed" else empty end),
817
+ (if $nodispatch == 0 then empty
818
+ elif $priced then "\($nodispatch) at the chosen review level"
819
+ else "\($nodispatch) unreviewed"
820
+ end),
799
821
  "final review \(if .final_review then "done" else "pending" end)"
800
822
  ] | join(" · ")
801
823
  ' "$STATE" 2>/dev/null || true)"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sluice",
3
- "version": "0.19.0",
3
+ "version": "0.19.2",
4
4
  "description": "Routes work by change shape into four channels (bypass, fast, main, deep) and applies only the rules each channel needs, so a one-line fix does not pay the cost of a multi-subsystem build. Carries seven rules as one-liners in the router and the full treatment in references read only on friction. Checks the finished plan with plan.sh validate rather than trusting it to memory, seeds the run state from it, keeps a deep run's task breakdown in .sluice/run.json so a statusline segment, one status command and a SessionStart hook can answer where the run is (the hook prints a live run at every session start, compaction included), and closes each run with a ledger read out of the session transcript: elapsed, tools, tokens, and what each dispatched agent cost where the transcript recorded it. Claude Code only; stands down where the superpowers pipeline governs the repo.",
5
5
  "author": "iceinvein",
6
6
  "type": "prompt",