@iceinvein/agent-skills 0.23.7 → 0.23.9

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.
Files changed (65) hide show
  1. package/package.json +1 -1
  2. package/skills/index.json +3 -3
  3. package/skills/magpie/README.md +1 -1
  4. package/skills/magpie/SKILL.md +2 -2
  5. package/skills/magpie/evals/README.md +22 -8
  6. package/skills/magpie/evals/bare-invocation-goes-local/case.yaml +4 -0
  7. package/skills/magpie/evals/bare-invocation-goes-local/fixture.sh +159 -0
  8. package/skills/magpie/evals/bare-invocation-goes-local/graders/branch-was-reachable.md +5 -0
  9. package/skills/magpie/evals/bare-invocation-goes-local/graders/never-went-to-a-pr.md +7 -0
  10. package/skills/magpie/evals/bare-invocation-goes-local/graders/setup-ran-local.md +6 -0
  11. package/skills/magpie/evals/bare-invocation-goes-local/prompt.md +11 -0
  12. package/skills/magpie/evals/baselines/claude-opus-5-5.json +27 -3
  13. package/skills/magpie/evals/rules.json +8 -0
  14. package/skills/magpie/scripts/__tests__/skill-lint.test.ts +8 -0
  15. package/skills/magpie/skill.json +1 -1
  16. package/skills/sluice/SKILL.md +21 -0
  17. package/skills/sluice/evals/README.md +6 -2
  18. package/skills/sluice/evals/deep-plan-checks-the-intent/case.yaml +4 -0
  19. package/skills/sluice/evals/deep-plan-checks-the-intent/fixture.sh +124 -0
  20. package/skills/sluice/evals/deep-plan-checks-the-intent/graders/announces-deep-channel.md +12 -0
  21. package/skills/sluice/evals/deep-plan-checks-the-intent/graders/checker-dispatched.md +12 -0
  22. package/skills/sluice/evals/deep-plan-checks-the-intent/graders/no-source-edit.md +11 -0
  23. package/skills/sluice/evals/deep-plan-checks-the-intent/graders/no-source-write.md +11 -0
  24. package/skills/sluice/evals/deep-plan-checks-the-intent/graders/signoff-reports-the-check.md +16 -0
  25. package/skills/sluice/evals/deep-plan-checks-the-intent/graders/sluice-fired.md +5 -0
  26. package/skills/sluice/evals/deep-plan-checks-the-intent/graders/spec-has-an-intent-map.md +19 -0
  27. package/skills/sluice/evals/deep-plan-checks-the-intent/graders/stopped-for-signoff.md +8 -0
  28. package/skills/sluice/evals/deep-plan-checks-the-intent/prompt.md +20 -0
  29. package/skills/sluice/evals/deep-plan-checks-the-plan/case.yaml +4 -0
  30. package/skills/sluice/evals/deep-plan-checks-the-plan/fixture.sh +178 -0
  31. package/skills/sluice/evals/deep-plan-checks-the-plan/graders/announces-deep-channel.md +12 -0
  32. package/skills/sluice/evals/deep-plan-checks-the-plan/graders/every-decision-built.md +15 -0
  33. package/skills/sluice/evals/deep-plan-checks-the-plan/graders/no-source-edit.md +11 -0
  34. package/skills/sluice/evals/deep-plan-checks-the-plan/graders/no-source-write.md +11 -0
  35. package/skills/sluice/evals/deep-plan-checks-the-plan/graders/plan-checker-dispatched.md +11 -0
  36. package/skills/sluice/evals/deep-plan-checks-the-plan/graders/plan-cites-the-spec.md +7 -0
  37. package/skills/sluice/evals/deep-plan-checks-the-plan/graders/sluice-fired.md +5 -0
  38. package/skills/sluice/evals/deep-plan-checks-the-plan/graders/stops-at-preflight.md +14 -0
  39. package/skills/sluice/evals/deep-plan-checks-the-plan/graders/validate-ran.md +9 -0
  40. package/skills/sluice/evals/deep-plan-checks-the-plan/prompt.md +12 -0
  41. package/skills/sluice/evals/deep-plan-reads-the-prior-spec/case.yaml +4 -0
  42. package/skills/sluice/evals/deep-plan-reads-the-prior-spec/fixture.sh +125 -0
  43. package/skills/sluice/evals/deep-plan-reads-the-prior-spec/graders/announces-deep-channel.md +12 -0
  44. package/skills/sluice/evals/deep-plan-reads-the-prior-spec/graders/context-cites-the-prior-spec.md +6 -0
  45. package/skills/sluice/evals/deep-plan-reads-the-prior-spec/graders/design-follows-the-prior-spec.md +21 -0
  46. package/skills/sluice/evals/deep-plan-reads-the-prior-spec/graders/design-written-to-docs.md +5 -0
  47. package/skills/sluice/evals/deep-plan-reads-the-prior-spec/graders/no-source-edit.md +11 -0
  48. package/skills/sluice/evals/deep-plan-reads-the-prior-spec/graders/no-source-write.md +11 -0
  49. package/skills/sluice/evals/deep-plan-reads-the-prior-spec/graders/sluice-fired.md +5 -0
  50. package/skills/sluice/evals/deep-plan-reads-the-prior-spec/prompt.md +17 -0
  51. package/skills/sluice/evals/deep-plan-traces-the-example/case.yaml +4 -0
  52. package/skills/sluice/evals/deep-plan-traces-the-example/fixture.sh +151 -0
  53. package/skills/sluice/evals/deep-plan-traces-the-example/graders/announces-deep-channel.md +12 -0
  54. package/skills/sluice/evals/deep-plan-traces-the-example/graders/design-written-to-docs.md +5 -0
  55. package/skills/sluice/evals/deep-plan-traces-the-example/graders/no-source-edit.md +11 -0
  56. package/skills/sluice/evals/deep-plan-traces-the-example/graders/no-source-write.md +11 -0
  57. package/skills/sluice/evals/deep-plan-traces-the-example/graders/sluice-fired.md +5 -0
  58. package/skills/sluice/evals/deep-plan-traces-the-example/graders/spec-has-a-trace.md +7 -0
  59. package/skills/sluice/evals/deep-plan-traces-the-example/graders/stopped-for-signoff.md +8 -0
  60. package/skills/sluice/evals/deep-plan-traces-the-example/graders/trace-finds-no-accepted-slide.md +27 -0
  61. package/skills/sluice/evals/deep-plan-traces-the-example/prompt.md +17 -0
  62. package/skills/sluice/evals/rules.json +36 -2
  63. package/skills/sluice/references/deep-channel.md +180 -5
  64. package/skills/sluice/scripts/plan.sh +115 -4
  65. package/skills/sluice/skill.json +2 -2
@@ -13,6 +13,11 @@
13
13
  #
14
14
  # validate prints one line per finding. An error means the plan cannot be
15
15
  # dispatched as written; a warning is a judgement call left to its author.
16
+ # Besides the plan's own skeleton, it reads the spec the plan's **Spec:** line
17
+ # names (a relative path from the plan's repo root, or from the plan's own
18
+ # directory outside a repo) and checks every "### D<n>." decision
19
+ # there is built by some task's **Builds:** line, and that no task builds one the
20
+ # spec does not have.
16
21
  # import seeds the run state's task rows from the plan, so the ids, names, the
17
22
  # flip, the effort marks and the tiers come from the file rather than from a
18
23
  # dozen hand-typed commands. It is safe to re-run: a status, a review mark or a
@@ -57,10 +62,19 @@ usage() {
57
62
  # than free markdown. Fenced blocks are skipped: a plan carries signatures and
58
63
  # commands in them, and a `- [ ]` inside a fence is an example, not a step.
59
64
  PARSER='
60
- BEGIN { SEP = sprintf("%c", 31) }
65
+ BEGIN {
66
+ SEP = sprintf("%c", 31)
67
+ # The one form a Builds line takes, said once for every message that asks for it.
68
+ BUILDS_HINT = "write D<n>, or none, <why>"
69
+ }
61
70
 
62
71
  function trim(s) { gsub(/^[ \t]+|[ \t]+$/, "", s); return s }
63
72
 
73
+ # Single-quoted for system(). The quote is built rather than written because
74
+ # this program is itself a single-quoted shell string, and an embedded quote
75
+ # becomes '"'"' because a backslash in a gsub replacement differs between awks.
76
+ function shq(s, q) { q = sprintf("%c", 39); gsub(q, q "\"" q "\"" q, s); return q s q }
77
+
64
78
  # Symbols on one side of a Contract line. The two sides are read differently
65
79
  # because a mistake costs differently on each.
66
80
  #
@@ -145,6 +159,17 @@ fenced { next }
145
159
 
146
160
  /^# Plan:/ { has_title = 1 }
147
161
 
162
+ # Before the first task only: a Spec line inside a task is that task naming a
163
+ # file, not the plan naming its design.
164
+ ntasks == 0 && /^\*\*Spec:\*\*/ {
165
+ spec_path = trim(substr($0, length("**Spec:**") + 1))
166
+ # Older plans write the path as code with prose after it, so a backticked
167
+ # span is the path and the rest is commentary.
168
+ if (match(spec_path, /`[^`]+`/)) spec_path = trim(substr(spec_path, RSTART + 1, RLENGTH - 2))
169
+ has_spec = 1
170
+ next
171
+ }
172
+
148
173
  /^## / {
149
174
  in_rules = (tolower($0) ~ /^## ground rules/) ? 1 : 0
150
175
  if (in_rules) has_rules_heading = 1
@@ -249,6 +274,27 @@ in_rules && /^- / { nrules++ }
249
274
  next
250
275
  }
251
276
 
277
+ /^\*\*Builds:\*\*/ {
278
+ has_builds[cur] = 1
279
+ body = trim(substr($0, length("**Builds:**") + 1))
280
+ # Validate-only, like the spec coverage below: a plan that imported before
281
+ # Builds lines existed must not be refused over one it cannot parse.
282
+ if (body == "") {
283
+ if (check_spec) finding("error", "task " cur " has an empty Builds line; " BUILDS_HINT)
284
+ next
285
+ }
286
+ if (tolower(body) ~ /^none([ \t,.;:]|$)/) next
287
+ n = split(body, parts, /[, \t]+/)
288
+ for (i = 1; i <= n; i++) {
289
+ # Authors write the line as prose, so "D2." closing a sentence is D2.
290
+ sub(/[.;:]+$/, "", parts[i])
291
+ if (parts[i] == "") continue
292
+ if (parts[i] ~ /^D[0-9]+$/) builds[cur] = builds[cur] " " parts[i]
293
+ else if (check_spec) finding("error", "task " cur " Builds " parts[i] ", which is not a decision id; " BUILDS_HINT)
294
+ }
295
+ next
296
+ }
297
+
252
298
  /^\*\*Flips:\*\*/ { has_flips[cur] = 1; nflips++; flips_list = flips_list (flips_list == "" ? "" : ", ") cur; next }
253
299
  /^\*\*Review:\*\*/ { has_review[cur] = 1; next }
254
300
  /^\*\*Model:\*\*/ { has_model[cur] = 1; next }
@@ -323,6 +369,62 @@ END {
323
369
  }
324
370
  }
325
371
 
372
+ # Gated, because only validate reads the spec. Import is run from wherever
373
+ # the run state lives, so a relative Spec path need not resolve there, and a
374
+ # plan already validated should not be refused over it.
375
+ if (check_spec) {
376
+ spec_file = spec_path
377
+ if (spec_path != "" && spec_path !~ /^\//) spec_file = ENVIRON["SLUICE_SPEC_BASE"] "/" spec_path
378
+ if (!has_spec) {
379
+ finding("error", "no **Spec:** line, so nothing ties the plan to the design it builds")
380
+ } else if (spec_path == "") {
381
+ # Checked before the read: getline on an empty filename is a fatal
382
+ # awk error, which would surface as the plan being unreadable.
383
+ finding("error", "the **Spec:** line names no path")
384
+ } else if (system("test -e " shq(spec_file)) != 0) {
385
+ finding("error", "**Spec:** names " spec_path ", which does not exist")
386
+ } else if (system("test -d " shq(spec_file)) == 0) {
387
+ # Asked before the read: BSD awk aborts on getline from a directory,
388
+ # which would surface as the plan being unreadable.
389
+ finding("error", "**Spec:** names " spec_path ", which is a directory, not a file")
390
+ } else if ((getline line < spec_file) < 0) {
391
+ finding("error", "**Spec:** names " spec_path ", which exists but cannot be read")
392
+ } else {
393
+ # The first line is already in hand from the existence probe above.
394
+ sfenced = 0; ndec = 0
395
+ do {
396
+ if (line ~ /^[ \t]*```/) { sfenced = 1 - sfenced; continue }
397
+ if (sfenced || line !~ /^### D[0-9]+\./) continue
398
+ match(line, /D[0-9]+/)
399
+ d = substr(line, RSTART, RLENGTH)
400
+ if (!(d in decision)) { decision[d] = 1; dec_order[++ndec] = d }
401
+ } while ((getline line < spec_file) > 0)
402
+ close(spec_file)
403
+ if (ndec == 0)
404
+ finding("error", "the spec " spec_path " has no \"### D<n>.\" decisions, so no task can say which one it builds")
405
+ }
406
+ for (i = 1; i <= ntasks; i++) {
407
+ id = order[i]
408
+ if (!(id in has_builds)) {
409
+ # An error, not a warning: `none, <why>` is how a task says it
410
+ # builds nothing, so a task without the line has left it unsaid.
411
+ finding("error", "task " id " has no Builds line; " BUILDS_HINT)
412
+ continue
413
+ }
414
+ n = split(builds[id], cited, " ")
415
+ for (j = 1; j <= n; j++) {
416
+ if (cited[j] == "") continue
417
+ built[cited[j]] = 1
418
+ if (ndec > 0 && !(cited[j] in decision))
419
+ finding("error", "task " id " Builds " cited[j] ", which the spec does not have")
420
+ }
421
+ }
422
+ if (ntasks > 0)
423
+ for (i = 1; i <= ndec; i++)
424
+ if (!(dec_order[i] in built))
425
+ finding("error", "spec decision " dec_order[i] " is built by no task")
426
+ }
427
+
326
428
  for (p in owners) {
327
429
  n = split(owners[p], who, " ")
328
430
  if (n < 2) continue
@@ -389,8 +491,17 @@ END {
389
491
  # FINDINGS (newline-separated sev\tmsg), TASKROWS (newline-separated), NERR,
390
492
  # NWARN.
391
493
  parse_plan() {
392
- local plan="$1" raw
393
- raw="$(awk "$PARSER" "$plan")" || { err "could not read $plan"; exit 4; }
494
+ local plan="$1" check_spec="${2-0}" raw
495
+ # A relative Spec path names a file from the plan's repo root, the way plans
496
+ # write it (docs/specs/...), so validate means the same thing from any cwd.
497
+ # Outside a repo there is no root, and the plan's own directory stands in.
498
+ # CDPATH is cleared because a cd it steers prints where it went, which would
499
+ # land in plan_dir. The base reaches awk through the environment: a -v value
500
+ # has its backslash escapes processed, and a path may hold a backslash.
501
+ local plan_dir spec_base
502
+ plan_dir="$(CDPATH= cd -- "$(dirname -- "$plan")" && pwd)" || { err "could not read $plan"; exit 4; }
503
+ spec_base="$(git -C "$plan_dir" rev-parse --show-toplevel 2>/dev/null)" || spec_base="$plan_dir"
504
+ raw="$(SLUICE_SPEC_BASE="$spec_base" awk -v check_spec="$check_spec" "$PARSER" "$plan")" || { err "could not read $plan"; exit 4; }
394
505
 
395
506
  local summary
396
507
  summary="$(printf '%s\n' "$raw" | grep "^summary$SEP" | head -1)"
@@ -421,7 +532,7 @@ case "$SUB" in
421
532
  shift
422
533
  [ $# -eq 0 ] || { err "unknown argument: $1"; exit 4; }
423
534
 
424
- parse_plan "$PLAN"
535
+ parse_plan "$PLAN" 1
425
536
 
426
537
  head="$(basename "$PLAN"): $(plural "$NTASKS" task)"
427
538
  [ "$FLIP" != "0" ] && head="$head, flip at task $FLIP"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "sluice",
3
- "version": "0.26.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 nine 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), lists every live deep run and routed fast or main session on the machine in one board.sh view (drawn once, watched, or as JSON), 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. Two Stop hooks hold a handback: one refuses a tree that moved since its last recorded check, the other refuses a changed existing test not proven to fail on the session's starting code (or recorded with a reason). Claude Code only; stands down where the superpowers pipeline governs the repo.",
3
+ "version": "0.28.0",
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 nine rules as one-liners in the router and the full treatment in references read only on friction. Deep runs read the repo before designing, map the spec's intent to its decisions, and check spec against intent and plan against spec with a fresh reader, with plan.sh validate enforcing that every decision is covered. 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), lists every live deep run and routed fast or main session on the machine in one board.sh view (drawn once, watched, or as JSON), 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. Two Stop hooks hold a handback: one refuses a tree that moved since its last recorded check, the other refuses a changed existing test not proven to fail on the session's starting code (or recorded with a reason). Claude Code only; stands down where the superpowers pipeline governs the repo.",
5
5
  "author": "iceinvein",
6
6
  "type": "prompt",
7
7
  "tools": [