@iceinvein/agent-skills 0.5.0 → 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 +1 -1
- package/skills/index.json +1 -1
- package/skills/sluice/SKILL.md +32 -15
- package/skills/sluice/references/deep-channel.md +19 -8
- package/skills/sluice/references/finish.md +4 -1
- package/skills/sluice/references/meter.md +14 -2
- package/skills/sluice/references/review.md +29 -0
- package/skills/sluice/scripts/run-stats.sh +103 -29
- package/skills/sluice/skill.json +1 -1
package/package.json
CHANGED
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.
|
|
286
|
+
"version": "0.3.0"
|
|
287
287
|
},
|
|
288
288
|
{
|
|
289
289
|
"name": "temporal-coupling-detector",
|
package/skills/sluice/SKILL.md
CHANGED
|
@@ -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
|
|
25
|
-
|
|
26
|
-
|
|
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
|
|
|
@@ -57,7 +63,8 @@ yourself wanting to skip the rule, or arguing that this one is the exception.
|
|
|
57
63
|
something anyone else can check. `references/verify.md`
|
|
58
64
|
- **Review** before merge. Dispatch a reviewer with fresh context and put the
|
|
59
65
|
diff on disk for it to read, so those bytes fill their context instead of
|
|
60
|
-
yours.
|
|
66
|
+
yours. Cannot dispatch one? Say so in the announcement and again at the
|
|
67
|
+
merge, and nowhere in between. `references/review.md`
|
|
61
68
|
- **Finish** deliberately. Green suite first, then let your partner pick
|
|
62
69
|
merge, PR, or leave it. Never pick for them. `references/finish.md`
|
|
63
70
|
- **Meter the run** as you hand it back. `scripts/run-stats.sh` reads the
|
|
@@ -78,18 +85,23 @@ Design to `docs/specs/YYYY-MM-DD-<topic>.md`, plan to
|
|
|
78
85
|
`docs/plans/YYYY-MM-DD-<topic>.md`, unless the repo has a convention or
|
|
79
86
|
your partner states a preference. Get the design signed off before code.
|
|
80
87
|
|
|
81
|
-
The plan
|
|
82
|
-
|
|
83
|
-
|
|
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.
|
|
84
92
|
|
|
85
93
|
Order the plan so the tasks that change nothing come first, and mark the one
|
|
86
94
|
task that turns the new behaviour on. Then a late re-baseline, re-blessed
|
|
87
95
|
snapshots, regenerated fixtures, attributes to that one point instead of to
|
|
88
96
|
the branch at large.
|
|
89
97
|
|
|
90
|
-
|
|
91
|
-
whether the work runs in a worktree. Ask
|
|
92
|
-
|
|
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
|
|
93
105
|
actionable while the plan can still change.
|
|
94
106
|
|
|
95
107
|
Read the plan as a graph rather than a list. `Needs` and `Offers` are
|
|
@@ -97,7 +109,7 @@ dependency edges and `Touches` says what cannot overlap, so which tasks may
|
|
|
97
109
|
run at once is derivable rather than guessed. Fan out wherever that graph
|
|
98
110
|
allows; serial is the fallback for where it doesn't, not the default.
|
|
99
111
|
|
|
100
|
-
Then read `references/deep-channel.md` for the plan format, that
|
|
112
|
+
Then read `references/deep-channel.md` for the plan format, that stop,
|
|
101
113
|
the dispatch rules, and when a task actually needs a reviewer. Three that
|
|
102
114
|
catch people out: concurrent implementers need a worktree each and the flip
|
|
103
115
|
runs alone, review is tiered rather than automatic, and a `deep` run that
|
|
@@ -106,7 +118,12 @@ ship without one.
|
|
|
106
118
|
|
|
107
119
|
## Conflicts
|
|
108
120
|
|
|
109
|
-
Sluice cannot run alongside the superpowers
|
|
110
|
-
own fixed
|
|
111
|
-
software does, not just code edits, and that
|
|
112
|
-
outright
|
|
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,
|
|
64
|
-
and settle two things with your partner. Ask them as questions with
|
|
65
|
-
not as a paragraph they have to reply to in prose: what you are after
|
|
66
|
-
decision, and a wall of considerations asks them to extract the decision
|
|
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
|
|
163
|
-
|
|
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.
|
|
@@ -170,7 +180,8 @@ is not one, and the table below still names which tasks needed the stronger
|
|
|
170
180
|
tier. Name those tasks at pre-flight, not at handback, so the choice of what
|
|
171
181
|
to do about them is still open: shrink the plan, take the flip on its own, or
|
|
172
182
|
accept the gap knowingly. Whatever is left then gets listed as review
|
|
173
|
-
outstanding rather than review passed
|
|
183
|
+
outstanding rather than review passed, and twice is the cap on saying so here
|
|
184
|
+
too: `references/review.md` has that rule. A `deep` run that ships with nobody
|
|
174
185
|
having read it has become a `fast` run with a design document attached, and
|
|
175
186
|
your partner is entitled to know that while it can still change the plan.
|
|
176
187
|
|
|
@@ -16,7 +16,10 @@ costs far more than asking would have.
|
|
|
16
16
|
With the suite green and the base confirmed, put exactly three options to
|
|
17
17
|
your partner, with the run ledger above them so the choice is made against
|
|
18
18
|
what the work actually cost rather than against your account of it;
|
|
19
|
-
`references/meter.md` owns that.
|
|
19
|
+
`references/meter.md` owns that. Say in one clause whether the work was
|
|
20
|
+
reviewed. Merging reviewed work and merging unreviewed work are different
|
|
21
|
+
decisions, and the ledger does not tell them apart: it counts the agents you
|
|
22
|
+
dispatched, not whether any of them read this diff. The three: merge it locally, push it and
|
|
20
23
|
open a PR, or leave the branch as it stands. Those three exhaust what you may offer. Your partner may still
|
|
21
24
|
ask for something off the list, most notably scrapping the branch, but the
|
|
22
25
|
request has to originate with them and be unmistakable. Then stop. Which of
|
|
@@ -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
|
|
41
|
-
|
|
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
|
|
@@ -45,6 +45,35 @@ only for substantial logic changes. While you are the one coordinating,
|
|
|
45
45
|
findings are not yours to fix: your patch would be the single patch nobody
|
|
46
46
|
reviews, and it spends context the plan still needs.
|
|
47
47
|
|
|
48
|
+
## When you cannot dispatch
|
|
49
|
+
|
|
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.
|
|
57
|
+
|
|
58
|
+
Say it twice, and only twice.
|
|
59
|
+
|
|
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.
|
|
67
|
+
|
|
68
|
+
The second is the integration event, where `references/finish.md` puts the
|
|
69
|
+
three options. Review status belongs beside them, because it is part of what
|
|
70
|
+
merging would be agreeing to.
|
|
71
|
+
|
|
72
|
+
Between those two points, stay quiet. An obligation restated on every handback
|
|
73
|
+
stops being information and turns into throat-clearing, and it buries the one
|
|
74
|
+
mention that mattered. Nothing changed between the announcement and the merge.
|
|
75
|
+
If something did, that is a new fact and earns a new sentence.
|
|
76
|
+
|
|
48
77
|
The friction line: "dispatching a reviewer for this is overkill." Skipping
|
|
49
78
|
the dispatch doesn't skip the cost, it just moves the cost onto you, and
|
|
50
79
|
self-review is not review.
|
|
@@ -46,7 +46,32 @@ if [ -z "$TRANSCRIPT" ] || [ ! -f "$TRANSCRIPT" ]; then
|
|
|
46
46
|
exit 1
|
|
47
47
|
fi
|
|
48
48
|
|
|
49
|
-
|
|
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 |
|
|
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 $
|
|
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
|
-
| ([ $
|
|
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
|
-
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
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
|
-
| ([ $
|
|
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
|
-
|
|
146
|
-
|
|
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 (([ $
|
|
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
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
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
|
-
|
|
248
|
-
|
|
249
|
-
|
|
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' \
|
package/skills/sluice/skill.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sluice",
|
|
3
|
-
"version": "0.
|
|
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",
|