@iceinvein/agent-skills 0.2.0 → 0.4.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/README.md +2 -2
- package/dist/cli/index.js +14 -10
- package/package.json +1 -1
- package/skills/index.json +4 -4
- package/skills/migrate/README.md +35 -23
- package/skills/migrate/SKILL.md +75 -15
- package/skills/migrate/bin/migrate.ts +90 -0
- package/skills/migrate/docs/architecture.md +61 -26
- package/skills/migrate/docs/reference.md +53 -8
- package/skills/migrate/fixtures/fake-gh.ts +113 -0
- package/skills/migrate/fixtures/flow-target/docs/WORK.md +12 -0
- package/skills/migrate/fixtures/flow-target/docs/modernisation/capability-map/.gitkeep +0 -0
- package/skills/migrate/fixtures/flow-target/tools/flow/src/cli.ts +156 -0
- package/skills/migrate/package.json +1 -1
- package/skills/migrate/references/phases/adjudicate.md +161 -0
- package/skills/migrate/references/phases/handoff.md +220 -0
- package/skills/migrate/references/phases/probe.md +2 -2
- package/skills/migrate/references/phases/queue.md +21 -14
- package/skills/migrate/references/run-ops.md +17 -13
- package/skills/migrate/scripts/__tests__/adapter-flow.test.ts +290 -0
- package/skills/migrate/scripts/__tests__/adapter-github.test.ts +232 -0
- package/skills/migrate/scripts/__tests__/adapter-markdown.test.ts +183 -0
- package/skills/migrate/scripts/__tests__/adjudicate.test.ts +332 -0
- package/skills/migrate/scripts/__tests__/assumptions.test.ts +179 -0
- package/skills/migrate/scripts/__tests__/coverage.test.ts +192 -0
- package/skills/migrate/scripts/__tests__/e2e-express.test.ts +167 -7
- package/skills/migrate/scripts/__tests__/e2e-webforms.test.ts +9 -4
- package/skills/migrate/scripts/__tests__/forecast.test.ts +280 -0
- package/skills/migrate/scripts/__tests__/gates-handoff.test.ts +309 -0
- package/skills/migrate/scripts/__tests__/handoff-cmd.test.ts +308 -0
- package/skills/migrate/scripts/__tests__/handoff-order.test.ts +156 -0
- package/skills/migrate/scripts/adapters/flow.ts +280 -0
- package/skills/migrate/scripts/adapters/github.ts +260 -0
- package/skills/migrate/scripts/adapters/markdown.ts +175 -0
- package/skills/migrate/scripts/adjudicate-cmd.ts +243 -0
- package/skills/migrate/scripts/assumptions.ts +188 -0
- package/skills/migrate/scripts/check.ts +119 -320
- package/skills/migrate/scripts/coverage-cmd.ts +86 -0
- package/skills/migrate/scripts/coverage.ts +151 -0
- package/skills/migrate/scripts/dates.ts +17 -0
- package/skills/migrate/scripts/forecast-cmd.ts +124 -0
- package/skills/migrate/scripts/forecast.ts +264 -0
- package/skills/migrate/scripts/gates/adjudication.ts +30 -0
- package/skills/migrate/scripts/gates/census.ts +107 -0
- package/skills/migrate/scripts/gates/citations.ts +11 -0
- package/skills/migrate/scripts/gates/context.ts +76 -0
- package/skills/migrate/scripts/gates/coverage.ts +22 -0
- package/skills/migrate/scripts/gates/deltas.ts +15 -0
- package/skills/migrate/scripts/gates/handoff.ts +145 -0
- package/skills/migrate/scripts/gates/leaks.ts +11 -0
- package/skills/migrate/scripts/gates/parity.ts +15 -0
- package/skills/migrate/scripts/gates/queue.ts +9 -0
- package/skills/migrate/scripts/gates/refs.ts +97 -0
- package/skills/migrate/scripts/gates/run-state.ts +67 -0
- package/skills/migrate/scripts/gates/source.ts +28 -0
- package/skills/migrate/scripts/handoff-cmd.ts +186 -0
- package/skills/migrate/scripts/handoff.ts +330 -0
- package/skills/migrate/scripts/paths.ts +4 -0
- package/skills/migrate/scripts/types.ts +43 -0
- package/skills/migrate/scripts/validate.ts +12 -0
- package/skills/migrate/skill.json +2 -2
- package/skills/migrate/templates/forecast-assumptions.md +59 -0
- package/skills/sluice/SKILL.md +20 -7
- package/skills/sluice/references/deep-channel.md +20 -0
- package/skills/sluice/references/finish.md +4 -2
- package/skills/sluice/references/meter.md +38 -0
- package/skills/sluice/scripts/run-stats.sh +236 -0
- package/skills/sluice/skill.json +4 -3
package/skills/sluice/SKILL.md
CHANGED
|
@@ -21,17 +21,20 @@ announcement is how your partner redirects you without being asked.
|
|
|
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
23
|
`bypass`, `fast`, and `main` proceed without stopping for approval; only
|
|
24
|
-
`deep` stops, for design sign-off before code
|
|
24
|
+
`deep` stops, for design sign-off before code, and again for the plan when
|
|
25
|
+
agents rather than you will carry it out.
|
|
25
26
|
|
|
26
27
|
Name the channel and the signal that actually routed you there. The strings above
|
|
27
28
|
are examples, not fixed copy, and a channel with a two-part signal should say
|
|
28
29
|
which part applied. `bypass` says nothing at all, because a question that gets
|
|
29
30
|
announced stops being a question.
|
|
30
31
|
|
|
31
|
-
**`root-cause` and `
|
|
32
|
-
triggers the first: a bug report, a red test, behaviour you cannot
|
|
33
|
-
for. An integration event, merging, pushing, or opening a PR, triggers
|
|
34
|
-
second.
|
|
32
|
+
**`root-cause`, `finish` and `meter` are not channel-assigned.** The code
|
|
33
|
+
misbehaving triggers the first: a bug report, a red test, behaviour you cannot
|
|
34
|
+
account for. An integration event, merging, pushing, or opening a PR, triggers
|
|
35
|
+
the second. Handing the work back triggers the third, whether or not it ever
|
|
36
|
+
reaches an integration event. The first two fire in every channel, `bypass`
|
|
37
|
+
included; `meter` cannot, because `bypass` announces nothing to measure from.
|
|
35
38
|
|
|
36
39
|
## The rules
|
|
37
40
|
|
|
@@ -56,6 +59,10 @@ yourself wanting to skip the rule, or arguing that this one is the exception.
|
|
|
56
59
|
yours. `references/review.md`
|
|
57
60
|
- **Finish** deliberately. Green suite first, then let your partner pick
|
|
58
61
|
merge, PR, or leave it. Never pick for them. `references/finish.md`
|
|
62
|
+
- **Meter the run** as you hand it back. `scripts/run-stats.sh` reads the
|
|
63
|
+
ledger out of the session transcript: elapsed, tools, tokens, and what each
|
|
64
|
+
dispatched agent cost. A summary you assemble from memory is the one that
|
|
65
|
+
flatters you. `references/meter.md`
|
|
59
66
|
|
|
60
67
|
## Changing channel
|
|
61
68
|
|
|
@@ -70,9 +77,15 @@ Design to `docs/specs/YYYY-MM-DD-<topic>.md`, plan to
|
|
|
70
77
|
`docs/plans/YYYY-MM-DD-<topic>.md`, unless the repo has a convention or
|
|
71
78
|
your partner states a preference. Get the design signed off before code.
|
|
72
79
|
|
|
80
|
+
The plan needs sign-off as well whenever agents will execute it, because each
|
|
81
|
+
one sees only its own task and so nobody ever reads the plan whole. Executing
|
|
82
|
+
it yourself makes it a worklist instead: write it and carry on.
|
|
83
|
+
|
|
73
84
|
Then read `references/deep-channel.md` for the plan format, the dispatch rules,
|
|
74
|
-
and when a task actually needs a reviewer.
|
|
75
|
-
two implementers at once,
|
|
85
|
+
and when a task actually needs a reviewer. Three that catch people out: never
|
|
86
|
+
run two implementers at once, review is tiered rather than automatic, and a
|
|
87
|
+
`deep` run that cannot dispatch has to replace the review tier with something,
|
|
88
|
+
not quietly ship without one.
|
|
76
89
|
|
|
77
90
|
## Conflicts
|
|
78
91
|
|
|
@@ -50,6 +50,26 @@
|
|
|
50
50
|
- Match model to task: cheap for mechanical work, stronger for judgment
|
|
51
51
|
and final review.
|
|
52
52
|
|
|
53
|
+
## When dispatch is unavailable
|
|
54
|
+
|
|
55
|
+
A session may forbid subagents outright. `deep` then loses most of the
|
|
56
|
+
machinery this file describes, and the place to say so is the routing
|
|
57
|
+
announcement, where your partner can still act on it, not the summary at the
|
|
58
|
+
end where it reads as an excuse.
|
|
59
|
+
|
|
60
|
+
Three things change. The plan becomes your own worklist and needs no sign-off,
|
|
61
|
+
since you are the only one who will ever read it. Task isolation is gone, so
|
|
62
|
+
`TaskCreate` now carries all of the state that outlives compaction and matters
|
|
63
|
+
more, not less. And fresh context is unavailable, which was the entire thing
|
|
64
|
+
review was buying.
|
|
65
|
+
|
|
66
|
+
One thing does not change: the work still owes a review. Reading your own diff
|
|
67
|
+
is not one, and the table below still names which tasks needed the stronger
|
|
68
|
+
tier. List those tasks when you hand back, as review outstanding rather than
|
|
69
|
+
review passed. A `deep` run that ships with nobody having read it has become a
|
|
70
|
+
`fast` run with a design document attached, and your partner is entitled to
|
|
71
|
+
know that before they decide anything.
|
|
72
|
+
|
|
53
73
|
## Review policy
|
|
54
74
|
|
|
55
75
|
A review costs about what the implementation cost, so reviewing every task
|
|
@@ -14,8 +14,10 @@ Confirm the base branch instead of assuming it; untangling a wrong merge
|
|
|
14
14
|
costs far more than asking would have.
|
|
15
15
|
|
|
16
16
|
With the suite green and the base confirmed, put exactly three options to
|
|
17
|
-
your partner
|
|
18
|
-
|
|
17
|
+
your partner, with the run ledger above them so the choice is made against
|
|
18
|
+
what the work actually cost rather than against your account of it;
|
|
19
|
+
`references/meter.md` owns that. The three: merge it locally, push it and
|
|
20
|
+
open a PR, or leave the branch as it stands. Those three exhaust what you may offer. Your partner may still
|
|
19
21
|
ask for something off the list, most notably scrapping the branch, but the
|
|
20
22
|
request has to originate with them and be unmistakable. Then stop. Which of
|
|
21
23
|
the three it is belongs to them, however obvious the choice looks from where
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Meter the run
|
|
2
|
+
|
|
3
|
+
Run `scripts/run-stats.sh` as part of the message that hands the work back,
|
|
4
|
+
and paste its output into that message unedited:
|
|
5
|
+
|
|
6
|
+
```
|
|
7
|
+
bash <skill-dir>/scripts/run-stats.sh --tests "<what the suite actually printed>"
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
It reads the session transcript, so it needs no state of its own and cannot
|
|
11
|
+
drift from what happened. `--tests` is the one field it cannot know: only you
|
|
12
|
+
watched the suite run. Fill it from the output you read in this session, and
|
|
13
|
+
leave it off entirely if no suite ran, which prints "not reported" rather
|
|
14
|
+
than a number nobody checked. `--base <ref>` overrides the diff base when the
|
|
15
|
+
merge-base with `main` or `master` is not where this branch actually began.
|
|
16
|
+
|
|
17
|
+
The run starts at your channel announcement, not at the session, so three
|
|
18
|
+
unrelated tasks in one session report as three runs. A previous ledger closes
|
|
19
|
+
the run before it. `bypass` announces nothing, so there is nothing to meter
|
|
20
|
+
and the script exits quietly.
|
|
21
|
+
|
|
22
|
+
What the ledger is for: the cost of a channel is otherwise invisible, and a
|
|
23
|
+
channel nobody can price is a channel nobody can choose between. Six agents
|
|
24
|
+
and four hours of agent wall-clock on a two-file change is the sort of thing
|
|
25
|
+
that only becomes obvious once it is written down next to the diff. Expect
|
|
26
|
+
some runs to make the case for a shallower channel next time. That is the
|
|
27
|
+
ledger working, not the ledger complaining.
|
|
28
|
+
|
|
29
|
+
Read it before you paste it. A row showing an agent that errored, or an agent
|
|
30
|
+
whose token count dwarfs every other row, is a finding about the run and
|
|
31
|
+
belongs in your prose, not left for your partner to spot in a table.
|
|
32
|
+
|
|
33
|
+
Exit 2 means there was no run to report. That is a fact about the work, not a
|
|
34
|
+
failure: do not synthesise a ledger to fill the gap.
|
|
35
|
+
|
|
36
|
+
The friction line: "I know roughly what this cost." Roughly is the problem.
|
|
37
|
+
Every number here is already on disk, and the remembered version is reliably
|
|
38
|
+
the flattering one.
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Print the run ledger: what this piece of work actually cost.
|
|
3
|
+
#
|
|
4
|
+
# The run starts at the channel announcement, not at the session, so a session
|
|
5
|
+
# holding three unrelated tasks reports each one separately. A previous ledger
|
|
6
|
+
# ends the run before it. `bypass` announces nothing and so prints nothing.
|
|
7
|
+
#
|
|
8
|
+
# Usage: run-stats.sh [--tests "<what the suite reported>"] [--base <git-ref>]
|
|
9
|
+
# [--transcript <path>]
|
|
10
|
+
#
|
|
11
|
+
# Exit 0 printed a ledger, 1 could not read a transcript, 2 no run to report.
|
|
12
|
+
|
|
13
|
+
set -uo pipefail
|
|
14
|
+
|
|
15
|
+
TESTS=""
|
|
16
|
+
BASE=""
|
|
17
|
+
TRANSCRIPT=""
|
|
18
|
+
|
|
19
|
+
while [ $# -gt 0 ]; do
|
|
20
|
+
case "$1" in
|
|
21
|
+
--tests) TESTS="${2-}"; shift 2 ;;
|
|
22
|
+
--base) BASE="${2-}"; shift 2 ;;
|
|
23
|
+
--transcript) TRANSCRIPT="${2-}"; shift 2 ;;
|
|
24
|
+
-h|--help) sed -n '2,11p' "$0" | cut -c3-; exit 0 ;;
|
|
25
|
+
*) echo "run-stats: unknown argument '$1'" >&2; exit 1 ;;
|
|
26
|
+
esac
|
|
27
|
+
done
|
|
28
|
+
|
|
29
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
30
|
+
echo "run-stats: jq is required and was not found on PATH" >&2
|
|
31
|
+
exit 1
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
if [ -z "$TRANSCRIPT" ]; then
|
|
35
|
+
sid="${CLAUDE_CODE_SESSION_ID:-}"
|
|
36
|
+
if [ -z "$sid" ]; then
|
|
37
|
+
echo "run-stats: no --transcript given and CLAUDE_CODE_SESSION_ID is unset" >&2
|
|
38
|
+
exit 1
|
|
39
|
+
fi
|
|
40
|
+
# The session id is unique across projects, so glob rather than guess the slug.
|
|
41
|
+
TRANSCRIPT="$(ls "$HOME"/.claude/projects/*/"$sid".jsonl 2>/dev/null | head -1)"
|
|
42
|
+
fi
|
|
43
|
+
|
|
44
|
+
if [ -z "$TRANSCRIPT" ] || [ ! -f "$TRANSCRIPT" ]; then
|
|
45
|
+
echo "run-stats: transcript not found (looked for '${TRANSCRIPT:-<unresolved>}')" >&2
|
|
46
|
+
exit 1
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
SUMMARY="$(jq -s '
|
|
50
|
+
# ---- what counts as a real turn ----------------------------------------
|
|
51
|
+
# Transcript stamps carry milliseconds, which fromdateiso8601 will not take.
|
|
52
|
+
def ts: sub("\\.[0-9]+Z$"; "Z") | fromdateiso8601;
|
|
53
|
+
def is_meta: (.isMeta == true) or (.isSidechain == true);
|
|
54
|
+
def texts: [ .message.content[]? | select(.type == "text") | .text ] | join("\n");
|
|
55
|
+
# The channel is stated in one line before proceeding, so the announcement
|
|
56
|
+
# opens the message. Anchoring there is what separates it from prose that
|
|
57
|
+
# merely discusses a channel, which a session about sluice is full of.
|
|
58
|
+
def marker: "^[*_#>[:space:]]*(?<c>fast|main|deep)[[:space:]]+channel";
|
|
59
|
+
def announces: (.type == "assistant") and (is_meta | not)
|
|
60
|
+
and (texts | test(marker; "i"));
|
|
61
|
+
def chan: texts | capture(marker; "i") | .c | ascii_downcase;
|
|
62
|
+
def is_stats_call: (.type == "assistant") and ([
|
|
63
|
+
.message.content[]? | select(.type == "tool_use" and .name == "Bash")
|
|
64
|
+
| select((.input.command // "") | test("run-stats\\.sh"))
|
|
65
|
+
] | length > 0);
|
|
66
|
+
# Waiting is any turn the partner had to take: a prompt, or an answer to a
|
|
67
|
+
# question you put to them. Leaving the latter out understates the wait on
|
|
68
|
+
# exactly the runs that stopped to ask, which are the ones worth pricing.
|
|
69
|
+
def is_prompt: (.type == "user") and (is_meta | not)
|
|
70
|
+
and (((.message.content | type) == "string"
|
|
71
|
+
or ((.message.content | type) == "array"
|
|
72
|
+
and ([ .message.content[]? | select(.type == "tool_result") ] | length == 0)))
|
|
73
|
+
or ((.toolUseResult | type) == "object" and (.toolUseResult | has("answers"))));
|
|
74
|
+
|
|
75
|
+
. as $all
|
|
76
|
+
| [ range(0; $all | length) ] as $ix
|
|
77
|
+
| [ $ix[] | select($all[.] | announces) ] as $ann
|
|
78
|
+
| if ($ann | length) == 0 then { empty: true } else
|
|
79
|
+
|
|
80
|
+
# A previous ledger closes the run before it. The call running right now has
|
|
81
|
+
# no announcement after it, so it is skipped rather than closing this run.
|
|
82
|
+
([ $ix[] | select($all[.] | is_stats_call) ]
|
|
83
|
+
| map(select(. < ($ann | max)))
|
|
84
|
+
| if length == 0 then -1 else max end) as $boundary
|
|
85
|
+
| [ $ann[] | select(. > $boundary) ] as $ann
|
|
86
|
+
| ($ann | min) as $from
|
|
87
|
+
| [ $all[$from:][] | select(.timestamp) ] as $run
|
|
88
|
+
|
|
89
|
+
# ---- channel, and the trail if it escalated ----------------------------
|
|
90
|
+
| ([ $ann[] | $all[.] | chan ]
|
|
91
|
+
| reduce .[] as $c ([]; if (. | last) == $c then . else . + [$c] end)) as $trail
|
|
92
|
+
|
|
93
|
+
# ---- clocks ------------------------------------------------------------
|
|
94
|
+
| ($run | map(.timestamp) | min) as $start
|
|
95
|
+
| ($run | map(.timestamp) | max) as $end
|
|
96
|
+
| (($end | ts) - ($start | ts)) as $elapsed
|
|
97
|
+
| ([ range(1; $run | length)
|
|
98
|
+
| select($run[.] | is_prompt)
|
|
99
|
+
| ($run[.].timestamp | ts) - ($run[. - 1].timestamp | ts) ]
|
|
100
|
+
| add // 0) as $waiting
|
|
101
|
+
|
|
102
|
+
# ---- tools and tokens, main loop only ----------------------------------
|
|
103
|
+
| [ $run[] | select((.type == "assistant") and (is_meta | not))
|
|
104
|
+
| .message.content[]? | select(.type == "tool_use") | .name ] as $tools
|
|
105
|
+
| ([ $run[] | select((.type == "assistant") and (is_meta | not))
|
|
106
|
+
| .message.usage.output_tokens // 0 ] | add // 0) as $out_tok
|
|
107
|
+
| ([ $run[] | select((.type == "assistant") and (is_meta | not))
|
|
108
|
+
| .message.usage.cache_read_input_tokens // 0 ] | add // 0) as $cache_tok
|
|
109
|
+
|
|
110
|
+
# ---- dispatched agents -------------------------------------------------
|
|
111
|
+
| ([ $run[] | select(.type == "assistant") | .message.content[]?
|
|
112
|
+
| select(.type == "tool_use" and (.name == "Agent" or .name == "Task"))
|
|
113
|
+
| { key: .id, value: (.input.description // .input.subagent_type // "agent") } ]
|
|
114
|
+
| from_entries) as $labels
|
|
115
|
+
# toolUseResult is whatever the tool returned: object, array or string.
|
|
116
|
+
| [ $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
|
+
tools: (.toolUseResult.totalToolUseCount // 0) } ] as $agents
|
|
123
|
+
|
|
124
|
+
| { empty: false,
|
|
125
|
+
trail: ($trail | join(" → ")),
|
|
126
|
+
elapsed: $elapsed, waiting: $waiting,
|
|
127
|
+
tool_total: ($tools | length),
|
|
128
|
+
tool_top: ([ $tools | group_by(.)[] | { n: length, name: (.[0] | ascii_downcase | split("__") | last) } ]
|
|
129
|
+
| sort_by(-.n) | .[0:3]),
|
|
130
|
+
out_tok: $out_tok, cache_tok: $cache_tok,
|
|
131
|
+
agents: $agents,
|
|
132
|
+
agent_tokens: ([ $agents[].tokens ] | add // 0),
|
|
133
|
+
agent_ms: ([ $agents[].ms ] | add // 0) }
|
|
134
|
+
end
|
|
135
|
+
' "$TRANSCRIPT" 2>/dev/null)"
|
|
136
|
+
|
|
137
|
+
if [ -z "$SUMMARY" ]; then
|
|
138
|
+
echo "run-stats: could not parse '$TRANSCRIPT'" >&2
|
|
139
|
+
exit 1
|
|
140
|
+
fi
|
|
141
|
+
|
|
142
|
+
if [ "$(jq -r '.empty' <<<"$SUMMARY")" = "true" ]; then
|
|
143
|
+
exit 2
|
|
144
|
+
fi
|
|
145
|
+
|
|
146
|
+
# ---- formatting -------------------------------------------------------------
|
|
147
|
+
|
|
148
|
+
dur() { # seconds -> 1h05m | 3m11s | 42s
|
|
149
|
+
local s=${1%.*} h m
|
|
150
|
+
h=$((s / 3600)); m=$(((s % 3600) / 60)); s=$((s % 60))
|
|
151
|
+
if [ "$h" -gt 0 ]; then printf '%dh%02dm' "$h" "$m"
|
|
152
|
+
elif [ "$m" -gt 0 ]; then printf '%dm%ds' "$m" "$s"
|
|
153
|
+
else printf '%ds' "$s"; fi
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
tok() { # tokens -> 1.2M | 313k | 51.0k | 350
|
|
157
|
+
local n=$1
|
|
158
|
+
if [ "$n" -ge 1000000 ]; then awk -v n="$n" 'BEGIN{printf "%.1fM", n/1000000}'
|
|
159
|
+
elif [ "$n" -ge 100000 ]; then awk -v n="$n" 'BEGIN{printf "%dk", n/1000}'
|
|
160
|
+
elif [ "$n" -ge 1000 ]; then awk -v n="$n" 'BEGIN{printf "%.1fk", n/1000}'
|
|
161
|
+
else printf '%d' "$n"; fi
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
g() { jq -r "$1" <<<"$SUMMARY"; }
|
|
165
|
+
|
|
166
|
+
printf '─── run %s\n' "$(printf '─%.0s' $(seq 1 36))"
|
|
167
|
+
printf 'channel %s\n' "$(g '.trail')"
|
|
168
|
+
|
|
169
|
+
elapsed=$(g '.elapsed'); waiting=$(g '.waiting')
|
|
170
|
+
if [ "${waiting%.*}" -gt 0 ]; then
|
|
171
|
+
printf 'elapsed %s · %s of that waiting on you\n' "$(dur "$elapsed")" "$(dur "$waiting")"
|
|
172
|
+
else
|
|
173
|
+
printf 'elapsed %s\n' "$(dur "$elapsed")"
|
|
174
|
+
fi
|
|
175
|
+
|
|
176
|
+
top="$(g '[.tool_top[] | "\(.n) \(.name)"] | join(" · ")')"
|
|
177
|
+
if [ -n "$top" ]; then
|
|
178
|
+
printf 'tools %s · %s\n' "$(g '.tool_total')" "$top"
|
|
179
|
+
else
|
|
180
|
+
printf 'tools %s\n' "$(g '.tool_total')"
|
|
181
|
+
fi
|
|
182
|
+
|
|
183
|
+
printf 'tokens %s out · %s cache read\n' "$(tok "$(g '.out_tok')")" "$(tok "$(g '.cache_tok')")"
|
|
184
|
+
printf 'tests %s\n' "${TESTS:-not reported}"
|
|
185
|
+
|
|
186
|
+
# The diff is the branch as a whole against where it left the base, working
|
|
187
|
+
# tree included, because uncommitted work is still work this run produced.
|
|
188
|
+
if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
|
189
|
+
if [ -z "$BASE" ]; then
|
|
190
|
+
for cand in main master; do
|
|
191
|
+
if git rev-parse --verify --quiet "$cand" >/dev/null 2>&1; then
|
|
192
|
+
BASE="$(git merge-base HEAD "$cand" 2>/dev/null)" && break
|
|
193
|
+
fi
|
|
194
|
+
done
|
|
195
|
+
[ -z "$BASE" ] && BASE="HEAD"
|
|
196
|
+
fi
|
|
197
|
+
stat="$(git diff --shortstat "$BASE" 2>/dev/null | sed 's/^ *//')"
|
|
198
|
+
files="$(git diff --name-only "$BASE" 2>/dev/null | wc -l | tr -d ' ')"
|
|
199
|
+
# awk, not sed: BSD sed has no \+ and silently matches nothing.
|
|
200
|
+
ins="$(awk '{for(i=1;i<=NF;i++) if($i ~ /^insertion/) print $(i-1)}' <<<"$stat")"
|
|
201
|
+
del="$(awk '{for(i=1;i<=NF;i++) if($i ~ /^deletion/) print $(i-1)}' <<<"$stat")"
|
|
202
|
+
ins=${ins:-0}; del=${del:-0}
|
|
203
|
+
|
|
204
|
+
# A file the run created is not in the diff until it is staged, and staging
|
|
205
|
+
# it here would be a side effect on someone else's index. Count it instead.
|
|
206
|
+
while IFS= read -r f; do
|
|
207
|
+
[ -n "$f" ] || continue
|
|
208
|
+
files=$((files + 1))
|
|
209
|
+
ins=$((ins + $(wc -l <"$f" 2>/dev/null || echo 0)))
|
|
210
|
+
done < <(git ls-files --others --exclude-standard 2>/dev/null)
|
|
211
|
+
|
|
212
|
+
[ "$files" -gt 0 ] && printf 'diff +%s −%s across %s files\n' "$ins" "$del" "$files"
|
|
213
|
+
fi
|
|
214
|
+
|
|
215
|
+
count=$(g '.agents | length')
|
|
216
|
+
if [ "$count" -eq 0 ]; then
|
|
217
|
+
printf 'agents none dispatched\n'
|
|
218
|
+
else
|
|
219
|
+
printf 'agents %s dispatched · %s tok · %s wall\n' \
|
|
220
|
+
"$count" "$(tok "$(g '.agent_tokens')")" "$(dur "$(( $(g '.agent_ms') / 1000 ))")"
|
|
221
|
+
|
|
222
|
+
# Up to a dozen rows read as the narrative of the plan. Past that the order
|
|
223
|
+
# stops helping, so show what the run actually spent on and say what is cut.
|
|
224
|
+
if [ "$count" -le 12 ]; then rows='.agents[]'; else rows='(.agents | sort_by(-.tokens) | .[0:10][])'; fi
|
|
225
|
+
while IFS=$'\t' read -r label model status tokens ms tools; do
|
|
226
|
+
model="${model#claude-}"; model="$(sed 's/-[0-9]\{8\}$//' <<<"$model")"
|
|
227
|
+
[ "$status" = "completed" ] && status="" || status=" ($status)"
|
|
228
|
+
printf ' %-22.22s %-10s %6s %7s %s tools%s\n' \
|
|
229
|
+
"$label" "$model" "$(tok "$tokens")" "$(dur "$((ms / 1000))")" "$tools" "$status"
|
|
230
|
+
done < <(g "$rows | [.label, .model, .status, .tokens, .ms, .tools] | @tsv")
|
|
231
|
+
|
|
232
|
+
if [ "$count" -gt 12 ]; then
|
|
233
|
+
printf ' +%s more · %s tok (dearest 10 shown)\n' \
|
|
234
|
+
"$((count - 10))" "$(tok "$(g '(.agents | sort_by(-.tokens) | .[10:] | map(.tokens) | add) // 0')")"
|
|
235
|
+
fi
|
|
236
|
+
fi
|
package/skills/sluice/skill.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sluice",
|
|
3
|
-
"version": "1.
|
|
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
|
|
3
|
+
"version": "0.1.1",
|
|
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",
|
|
7
7
|
"tools": [
|
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
},
|
|
13
13
|
"bundle": {
|
|
14
14
|
"include": [
|
|
15
|
-
"references"
|
|
15
|
+
"references",
|
|
16
|
+
"scripts"
|
|
16
17
|
]
|
|
17
18
|
},
|
|
18
19
|
"install": {
|