@iceinvein/agent-skills 0.5.1 → 0.6.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iceinvein/agent-skills",
3
- "version": "0.5.1",
3
+ "version": "0.6.0",
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, and closes each run with a ledger read out of the session transcript: elapsed, tools, tokens, and what every dispatched agent cost. Claude Code only; conflicts with the superpowers plugin.",
285
285
  "type": "prompt",
286
- "version": "0.2.1"
286
+ "version": "0.3.0"
287
287
  },
288
288
  {
289
289
  "name": "temporal-coupling-detector",
@@ -20,10 +20,13 @@ announcement is how your partner redirects you without being asked.
20
20
  | `main` | Adds an interface, or crosses subsystems | + agree intent, review before merge | "Main channel, new interface. Agreeing the shape first." |
21
21
  | `deep` | Several subsystems, or a plan was asked for | + written design and plan | "Deep channel, several subsystems. Design before code." |
22
22
 
23
+ Two subsystems is `main`; the third is what makes it `deep`.
24
+
23
25
  `bypass`, `fast`, and `main` proceed without stopping for approval; only
24
- `deep` stops. It stops for design sign-off before code, again for the plan
25
- when agents rather than you will carry it out, and once more at pre-flight
26
- before Task 1, to settle review and workspace.
26
+ `deep` stops: once for design sign-off before code, once for the plan and
27
+ pre-flight together before Task 1. A stop ends your turn. Asking a question
28
+ with a tool is not one, however many options it carried: the answer comes
29
+ back to you and the run never left your hands.
27
30
 
28
31
  Name the channel and the signal that actually routed you there. The strings above
29
32
  are examples, not fixed copy, and a channel with a two-part signal should say
@@ -36,6 +39,9 @@ account for. An integration event, merging, pushing, or opening a PR, triggers
36
39
  the second. Handing the work back triggers the third, whether or not it ever
37
40
  reaches an integration event. The first two fire in every channel, `bypass`
38
41
  included; `meter` cannot, because `bypass` announces nothing to measure from.
42
+ A question that turns on how something looks is triggered the same way and in
43
+ any channel: `references/show-or-say.md` decides whether to show it or say it,
44
+ and `bypass` is where it comes up most.
39
45
 
40
46
  ## The rules
41
47
 
@@ -79,18 +85,23 @@ Design to `docs/specs/YYYY-MM-DD-<topic>.md`, plan to
79
85
  `docs/plans/YYYY-MM-DD-<topic>.md`, unless the repo has a convention or
80
86
  your partner states a preference. Get the design signed off before code.
81
87
 
82
- The plan needs sign-off as well whenever agents will execute it, because each
83
- one sees only its own task and so nobody ever reads the plan whole. Executing
84
- it yourself makes it a worklist instead: write it and carry on.
88
+ The plan gets a stop of its own, whoever executes it. Dispatched agents each
89
+ see only their own task, so nobody reads it whole; executing it yourself is
90
+ the weaker case rather than the exempt one, because then nobody reads it but
91
+ its author.
85
92
 
86
93
  Order the plan so the tasks that change nothing come first, and mark the one
87
94
  task that turns the new behaviour on. Then a late re-baseline, re-blessed
88
95
  snapshots, regenerated fixtures, attributes to that one point instead of to
89
96
  the branch at large.
90
97
 
91
- Before Task 1, stop once and ask which flagged tasks get a reviewer and
92
- whether the work runs in a worktree. Ask it as a choice with the counts in
93
- it, never as a paragraph. Review that turns out to be missing is only
98
+ Pre-flight rides in the plan's stop: which flagged tasks get a reviewer, and
99
+ whether the work runs in a worktree. Ask them as choices with the counts in
100
+ them, never as a paragraph, then end the turn on the answers rather than
101
+ opening Task 1 with them. A session that dispatches only when asked has not
102
+ ruled dispatch out, it has made this question the place to ask. Genuine
103
+ unavailability is the tool not being there at all, which is a different case
104
+ and a different paragraph. Review that turns out to be missing is only
94
105
  actionable while the plan can still change.
95
106
 
96
107
  Read the plan as a graph rather than a list. `Needs` and `Offers` are
@@ -98,7 +109,7 @@ dependency edges and `Touches` says what cannot overlap, so which tasks may
98
109
  run at once is derivable rather than guessed. Fan out wherever that graph
99
110
  allows; serial is the fallback for where it doesn't, not the default.
100
111
 
101
- Then read `references/deep-channel.md` for the plan format, that checkpoint,
112
+ Then read `references/deep-channel.md` for the plan format, that stop,
102
113
  the dispatch rules, and when a task actually needs a reviewer. Three that
103
114
  catch people out: concurrent implementers need a worktree each and the flip
104
115
  runs alone, review is tiered rather than automatic, and a `deep` run that
@@ -107,7 +118,12 @@ ship without one.
107
118
 
108
119
  ## Conflicts
109
120
 
110
- Sluice cannot run alongside the superpowers plugin. Superpowers requires its
111
- own fixed pipeline up front for anything that adds to or changes what the
112
- software does, not just code edits, and that pipeline overrides this router
113
- outright, so the two cannot be installed together.
121
+ Sluice cannot run alongside the superpowers pipeline. Superpowers requires its
122
+ own fixed sequence up front for anything that adds to or changes what the
123
+ software does, not just code edits, and that sequence overrides this router
124
+ outright.
125
+
126
+ The test is whether that pipeline governs the work in front of you, not whether
127
+ a plugin is installed. A repo whose own instructions mandate the sequence rules
128
+ this router out exactly as the plugin does, with the plugin disabled or absent.
129
+ Stand down and say so once, in the same breath you would have named a channel.
@@ -60,11 +60,20 @@ Split it. A plan with none is not a `deep` plan: nothing in it does anything.
60
60
 
61
61
  ## Pre-flight
62
62
 
63
- Design signed off, plan written, nothing built yet. Before Task 1, stop once
64
- and settle two things with your partner. Ask them as questions with options,
65
- not as a paragraph they have to reply to in prose: what you are after is a
66
- decision, and a wall of considerations asks them to extract the decision from
67
- it first.
63
+ Design signed off, plan written, nothing built yet. Before Task 1, hand back
64
+ once and settle two things with your partner. Ask them as questions with
65
+ options, not as a paragraph they have to reply to in prose: what you are after
66
+ is a decision, and a wall of considerations asks them to extract the decision
67
+ from it first.
68
+
69
+ This handback is the plan's sign-off as well, so it ends your turn, and a
70
+ question tool does not end it for you. That tool returns an answer without
71
+ returning control: two options came back, the plan itself did not, and your
72
+ partner reads the summary of it in the same message as Task 1's first edit,
73
+ by which point their only remaining move is to interrupt. Ask the questions,
74
+ then end the turn on the answers and let the next instruction start the
75
+ build. If the answers arrive with that instruction already attached, you have
76
+ your sign-off and Task 1 begins.
68
77
 
69
78
  **Review.** Name the tasks the table below sends to a reviewer, each with the
70
79
  trigger that qualified it, and say how many of the rest skip with a ledger
@@ -159,8 +168,9 @@ unavailable, where there is nothing to ask.
159
168
  say so is the routing announcement, where your partner can still act on it,
160
169
  not the summary at the end where it reads as an excuse.
161
170
 
162
- Three things change. The plan becomes your own worklist and needs no sign-off,
163
- since you are the only one who will ever read it. Task isolation is gone, so
171
+ Three things change. The plan stops being a brief for strangers and becomes
172
+ your own worklist, which makes its handback the only outside read it will ever
173
+ get rather than a formality on the way to dispatch. Task isolation is gone, so
164
174
  `TaskCreate` now carries all of the state that outlives compaction and matters
165
175
  more, not less. And fresh context is unavailable, which was the entire thing
166
176
  review was buying.
@@ -33,12 +33,24 @@ chain and a finding for one whose graph was not, so read it against the plan
33
33
  rather than on its own. Nine agents at 1.0× on a plan with four independent
34
34
  tasks in it is a run that took four times longer than it needed to.
35
35
 
36
+ An agent dispatched into the background is handed back before it runs, so the
37
+ result the session sees carries no cost at all. The ledger reads that agent's
38
+ own transcript instead, which is why a plan run entirely on dispatched agents
39
+ still prices. Agent rows count output tokens, the same unit the run reports for
40
+ itself, so they can be read against each other and against the run.
41
+
42
+ Where that log has been cleaned up the row reads "cost not reported", the
43
+ totals leave it out, and the agent line carries the count. That is a gap in
44
+ what could be measured rather than a cheap run, and it needs a sentence from
45
+ you: a smaller total must not be allowed to stand for the whole.
46
+
36
47
  Read it before you paste it. A row showing an agent that errored, or an agent
37
48
  whose token count dwarfs every other row, is a finding about the run and
38
49
  belongs in your prose, not left for your partner to spot in a table.
39
50
 
40
- Exit 2 means there was no run to report. That is a fact about the work, not a
41
- failure: do not synthesise a ledger to fill the gap.
51
+ Exit 2 means neither an announcement nor an invocation of this skill was found,
52
+ so there was no run to report. That is a fact about the work, not a failure: do
53
+ not synthesise a ledger to fill the gap.
42
54
 
43
55
  The friction line: "I know roughly what this cost." Roughly is the problem.
44
56
  Every number here is already on disk, and the remembered version is reliably
@@ -47,18 +47,23 @@ reviews, and it spends context the plan still needs.
47
47
 
48
48
  ## When you cannot dispatch
49
49
 
50
- A session may withhold subagents, or grant them only on request. The review is
51
- owed either way. `deep` has its own treatment in `references/deep-channel.md`,
52
- where there is a plan to shrink and a tier table to argue from; this is the
53
- `main` case, which has neither.
50
+ Separate the two cases before you say anything. A session that grants subagents
51
+ only on request has not withheld them: asking is the whole procedure, and a
52
+ claim that you cannot dispatch is false there. A session that withholds them
53
+ outright is the one this section is about. The review is owed either way.
54
+ `deep` has its own treatment in `references/deep-channel.md`, where there is a
55
+ plan to shrink and a tier table to argue from; this is the `main` case, which
56
+ has neither.
54
57
 
55
58
  Say it twice, and only twice.
56
59
 
57
- The first time is the routing announcement, in the same breath as the channel:
58
- "Main channel, new interface. I cannot dispatch a reviewer in this session, so
59
- this merges unreviewed unless you want one." That is the moment it is still a
60
- decision. Your partner can authorise the dispatch, split the change, or accept
61
- the gap knowingly. The same words at the end are a disclaimer.
60
+ The first time is the routing announcement, in the same breath as the channel.
61
+ Withheld: "Main channel, new interface. I cannot dispatch a reviewer in this
62
+ session, so this merges unreviewed unless you want one." On request: "Main
63
+ channel, new interface. A reviewer is one dispatch away if you want one, and
64
+ without it this merges unreviewed." Either way, that is the moment it is still
65
+ a decision. Your partner can authorise the dispatch, split the change, or
66
+ accept the gap knowingly. The same words at the end are a disclaimer.
62
67
 
63
68
  The second is the integration event, where `references/finish.md` puts the
64
69
  three options. Review status belongs beside them, because it is part of what
@@ -46,7 +46,32 @@ if [ -z "$TRANSCRIPT" ] || [ ! -f "$TRANSCRIPT" ]; then
46
46
  exit 1
47
47
  fi
48
48
 
49
- SUMMARY="$(jq -s '
49
+ # An agent handed back before it ran leaves no cost on its tool result, but it
50
+ # keeps a transcript of its own beside the session. That file is the only place
51
+ # a backgrounded agent's cost is ever written down, so read it rather than
52
+ # reporting the work as free.
53
+ SUBS="$(dirname "$TRANSCRIPT")/$(basename "$TRANSCRIPT" .jsonl)/subagents"
54
+ COSTS='{}'
55
+ if [ -d "$SUBS" ]; then
56
+ COSTS="$(
57
+ for f in "$SUBS"/agent-*.jsonl; do
58
+ [ -e "$f" ] || continue
59
+ id="$(basename "$f" .jsonl)"; id="${id#agent-}"
60
+ jq -s --arg id "$id" '
61
+ def ts: sub("\\.[0-9]+Z$"; "Z") | fromdateiso8601;
62
+ [ .[] | select(.timestamp) ] as $t
63
+ | { ($id): {
64
+ tokens: ([ .[] | .message.usage.output_tokens // 0 ] | add // 0),
65
+ tools: ([ .[] | .message.content[]? | select(.type == "tool_use") ] | length),
66
+ model: ([ .[] | .message.model // empty ] | last // "?"),
67
+ starts: (if ($t | length) > 0 then ($t[0].timestamp | ts) else 0 end),
68
+ ends: (if ($t | length) > 0 then ($t[-1].timestamp | ts) else 0 end) } }' "$f"
69
+ done | jq -s 'add // {}'
70
+ )"
71
+ fi
72
+ [ -n "$COSTS" ] || COSTS='{}'
73
+
74
+ SUMMARY="$(jq -s --argjson costs "$COSTS" '
50
75
  # ---- what counts as a real turn ----------------------------------------
51
76
  # Transcript stamps carry milliseconds, which fromdateiso8601 will not take.
52
77
  def ts: sub("\\.[0-9]+Z$"; "Z") | fromdateiso8601;
@@ -56,9 +81,20 @@ SUMMARY="$(jq -s '
56
81
  # opens the message. Anchoring there is what separates it from prose that
57
82
  # merely discusses a channel, which a session about sluice is full of.
58
83
  def marker: "^[*_#>[:space:]]*(?<c>fast|main|deep)[[:space:]]+channel";
84
+ # Real announcements carry a lead-in the anchor above misses: "Sluice: **deep
85
+ # channel**", "Tier 2 (new contract surface) = **deep channel**". Emphasis is
86
+ # what still separates one from prose naming a channel, and holding it to the
87
+ # opening line keeps a session reviewing sluice from starting a run per quote.
88
+ def emph: "\\*\\*[[:space:]]*(?<c>fast|main|deep)[[:space:]]+channel";
89
+ def head_line: texts | split("\n") | (.[0] // "");
59
90
  def announces: (.type == "assistant") and (is_meta | not)
60
- and (texts | test(marker; "i"));
61
- def chan: texts | capture(marker; "i") | .c | ascii_downcase;
91
+ and ((texts | test(marker; "i")) or (head_line | test(emph; "i")));
92
+ def chan: (if (texts | test(marker; "i")) then (texts | capture(marker; "i"))
93
+ else (head_line | capture(emph; "i")) end) | .c | ascii_downcase;
94
+ def invokes_sluice: (.type == "assistant") and (is_meta | not) and ([
95
+ .message.content[]? | select(.type == "tool_use" and .name == "Skill")
96
+ | select((.input.skill // "") == "sluice")
97
+ ] | length > 0);
62
98
  def is_stats_call: (.type == "assistant") and ([
63
99
  .message.content[]? | select(.type == "tool_use" and .name == "Bash")
64
100
  | select((.input.command // "") | test("run-stats\\.sh"))
@@ -74,7 +110,11 @@ SUMMARY="$(jq -s '
74
110
 
75
111
  . as $all
76
112
  | [ range(0; $all | length) ] as $ix
77
- | [ $ix[] | select($all[.] | announces) ] as $ann
113
+ | [ $ix[] | select($all[.] | announces) ] as $said
114
+ # A run whose announcement never matched is still a run when the skill was
115
+ # invoked by name. Anchoring there beats reporting the work as nothing.
116
+ | [ $ix[] | select($all[.] | invokes_sluice) ] as $called
117
+ | (if ($said | length) > 0 then $said else $called end) as $ann
78
118
  | if ($ann | length) == 0 then { empty: true } else
79
119
 
80
120
  # A previous ledger closes the run before it. The call running right now has
@@ -87,7 +127,7 @@ SUMMARY="$(jq -s '
87
127
  | [ $all[$from:][] | select(.timestamp) ] as $run
88
128
 
89
129
  # ---- channel, and the trail if it escalated ----------------------------
90
- | ([ $ann[] | $all[.] | chan ]
130
+ | ([ $said[] | select(. >= $from) | $all[.] | chan ]
91
131
  | reduce .[] as $c ([]; if (. | last) == $c then . else . + [$c] end)) as $trail
92
132
 
93
133
  # ---- clocks ------------------------------------------------------------
@@ -114,20 +154,39 @@ SUMMARY="$(jq -s '
114
154
  | from_entries) as $labels
115
155
  # toolUseResult is whatever the tool returned: object, array or string.
116
156
  | [ $run[] | select((.toolUseResult | type) == "object") | select(.toolUseResult.agentId)
117
- | { label: ($labels[[ .message.content[]? | select(.type == "tool_result") | .tool_use_id ][0]] // "agent"),
118
- model: (.toolUseResult.resolvedModel // "?"),
119
- status: (.toolUseResult.status // "?"),
120
- tokens: (.toolUseResult.totalTokens // 0),
121
- ms: (.toolUseResult.totalDurationMs // 0),
122
- # The transcript timestamps when an agent returned, not when it began,
123
- # so the start is back-derived from its own duration.
124
- ends: (.timestamp | ts),
125
- starts: ((.timestamp | ts) - ((.toolUseResult.totalDurationMs // 0) / 1000)),
126
- tools: (.toolUseResult.totalToolUseCount // 0) } ] as $agents
157
+ | . as $e
158
+ # Inline cost when the agent ran to completion here, its own transcript
159
+ # when it was handed back before it ran, and neither only when the file
160
+ # has been cleaned up. Priced at zero it would understate the run and drag
161
+ # the concurrency factor to a number the ledger has no meaning for.
162
+ | ($costs[$e.toolUseResult.agentId] // null) as $c
163
+ # The log wins where there is one. The two sources count different things,
164
+ # the inline total being the harness accounting and the log being output
165
+ # tokens, and rows drawn from different bases cannot be read against each
166
+ # other. Output tokens is also the unit the run reports for itself.
167
+ | (if $c == null then $e.toolUseResult.totalDurationMs
168
+ else (($c.ends - $c.starts) * 1000) end) as $ms
169
+ | ($c.tokens // $e.toolUseResult.totalTokens) as $tokens
170
+ | { label: ($labels[[ $e.message.content[]? | select(.type == "tool_result") | .tool_use_id ][0]]
171
+ // $e.toolUseResult.commandName // "agent"),
172
+ model: ($c.model // $e.toolUseResult.resolvedModel // "?"),
173
+ status: ($e.toolUseResult.status // "?"),
174
+ measured: (($ms != null) or ($tokens != null)),
175
+ tokens: ($tokens // 0),
176
+ ms: ($ms // 0),
177
+ # The session transcript timestamps when an agent returned, not when
178
+ # it began, so that start is back-derived from its own duration. An
179
+ # agent log of its own carries both ends directly.
180
+ ends: (if $c != null then $c.ends else ($e.timestamp | ts) end),
181
+ starts: (if $c != null then $c.starts
182
+ else (($e.timestamp | ts) - (($ms // 0) / 1000)) end),
183
+ tools: ($c.tools // $e.toolUseResult.totalToolUseCount // 0) } ] as $agents
184
+
185
+ | [ $agents[] | select(.measured) ] as $priced
127
186
 
128
187
  # Union of the agent intervals: sum the merged runs rather than the raw ones,
129
188
  # so overlapping agents are counted once against the clock they shared.
130
- | ([ $agents[] | { s: .starts, e: .ends } ] | sort_by(.s)
189
+ | ([ $priced[] | { s: .starts, e: .ends } ] | sort_by(.s)
131
190
  | reduce .[] as $i ([];
132
191
  if (length == 0) or (.[-1].e < $i.s)
133
192
  then . + [$i]
@@ -135,17 +194,18 @@ SUMMARY="$(jq -s '
135
194
  | map(.e - .s) | add // 0) as $agent_span
136
195
 
137
196
  | { empty: false,
138
- trail: ($trail | join(" → ")),
197
+ trail: (if ($trail | length) == 0 then "not announced" else ($trail | join(" → ")) end),
139
198
  elapsed: $elapsed, waiting: $waiting,
140
199
  tool_total: ($tools | length),
141
200
  tool_top: ([ $tools | group_by(.)[] | { n: length, name: (.[0] | ascii_downcase | split("__") | last) } ]
142
201
  | sort_by(-.n) | .[0:3]),
143
202
  out_tok: $out_tok, cache_tok: $cache_tok,
144
203
  agents: $agents,
145
- agent_tokens: ([ $agents[].tokens ] | add // 0),
146
- agent_ms: ([ $agents[].ms ] | add // 0),
204
+ unmeasured: (($agents | length) - ($priced | length)),
205
+ agent_tokens: ([ $priced[].tokens ] | add // 0),
206
+ agent_ms: ([ $priced[].ms ] | add // 0),
147
207
  concurrency: (if $agent_span > 0
148
- then (([ $agents[].ms ] | add // 0) / 1000) / $agent_span
208
+ then (([ $priced[].ms ] | add // 0) / 1000) / $agent_span
149
209
  else 0 end) }
150
210
  end
151
211
  ' "$TRANSCRIPT" 2>/dev/null)"
@@ -229,24 +289,38 @@ if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
229
289
  fi
230
290
 
231
291
  count=$(g '.agents | length')
292
+ unmeasured=$(g '.unmeasured')
232
293
  if [ "$count" -eq 0 ]; then
233
294
  printf 'agents none dispatched\n'
234
295
  else
235
- # 1.0× means every agent had the clock to itself. On a plan whose graph had
236
- # independent tasks in it, that number is the finding.
237
- printf 'agents %s dispatched · %s tok · %s wall · %s× concurrent\n' \
238
- "$count" "$(tok "$(g '.agent_tokens')")" "$(dur "$(( $(g '.agent_ms') / 1000 ))")" \
239
- "$(printf '%.1f' "$(g '.concurrency')")"
296
+ if [ "$count" -eq "$unmeasured" ]; then
297
+ # Every agent was handed back before it ran, so there is no cost to report
298
+ # and none to invent. Saying so beats a row of zeroes that reads as a total.
299
+ printf 'agents %s dispatched · cost not reported\n' "$count"
300
+ else
301
+ # 1.0× means every agent had the clock to itself. On a plan whose graph had
302
+ # independent tasks in it, that number is the finding.
303
+ printf 'agents %s dispatched · %s tok · %s wall · %s× concurrent' \
304
+ "$count" "$(tok "$(g '.agent_tokens')")" "$(dur "$(( $(g '.agent_ms') / 1000 ))")" \
305
+ "$(printf '%.1f' "$(g '.concurrency')")"
306
+ [ "$unmeasured" -gt 0 ] && printf ' · %s unmeasured' "$unmeasured"
307
+ printf '\n'
308
+ fi
240
309
 
241
310
  # Up to a dozen rows read as the narrative of the plan. Past that the order
242
311
  # stops helping, so show what the run actually spent on and say what is cut.
243
312
  if [ "$count" -le 12 ]; then rows='.agents[]'; else rows='(.agents | sort_by(-.tokens) | .[0:10][])'; fi
244
- while IFS=$'\t' read -r label model status tokens ms tools; do
313
+ while IFS=$'\t' read -r label model status tokens ms tools measured; do
245
314
  model="${model#claude-}"; model="$(sed 's/-[0-9]\{8\}$//' <<<"$model")"
246
315
  [ "$status" = "completed" ] && status="" || status=" ($status)"
247
- printf ' %-22.22s %-10s %6s %7s %s tools%s\n' \
248
- "$label" "$model" "$(tok "$tokens")" "$(dur "$((ms / 1000))")" "$tools" "$status"
249
- done < <(g "$rows | [.label, .model, .status, .tokens, .ms, .tools] | @tsv")
316
+ if [ "$measured" = "true" ]; then
317
+ printf ' %-22.22s %-10s %6s %7s %s tools%s\n' \
318
+ "$label" "$model" "$(tok "$tokens")" "$(dur "$((ms / 1000))")" "$tools" "$status"
319
+ else
320
+ printf ' %-22.22s %-10s %6s %7s %s%s\n' \
321
+ "$label" "$model" "-" "-" "cost not reported" "$status"
322
+ fi
323
+ done < <(g "$rows | [.label, .model, .status, .tokens, .ms, .tools, .measured] | @tsv")
250
324
 
251
325
  if [ "$count" -gt 12 ]; then
252
326
  printf ' +%s more · %s tok (dearest 10 shown)\n' \
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sluice",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
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, and closes each run with a ledger read out of the session transcript: elapsed, tools, tokens, and what every dispatched agent cost. Claude Code only; conflicts with the superpowers plugin.",
5
5
  "author": "iceinvein",
6
6
  "type": "prompt",