Summary
| Task |
Description |
Typecheck |
Key finding |
| 1 (reused) |
TS dead export finder |
✅ pass |
Initial as const on array literal caused TS1355 — replaced with plain return; otherwise solid p.glob + async defineTool pattern |
| 2 (reused) |
Pkg scripts documenter |
✅ pass |
Unused name param in handler caused TS6133 — destructured only command; p.read + p.write + s.enum category pattern works well |
| 3 (reused) |
Git diff stats summarizer |
✅ pass |
p.bash + sync defineTool + s.optional clean combination; s.enum for category |
| 4 (reused) |
Dotenv template generator |
✅ pass |
p.readOptional + p.glob + async defineTool + p.write — all four intent types in one agent, repair addon |
| 5 (reused) |
TS class hierarchy extractor |
✅ pass |
async defineTool + steering addon; s.record + s.optional(s.string) output structure |
| 6 (reused) |
Git bisect helper |
✅ pass |
steering addon with maxTurns:8 + sync defineTool selectMidpoint; s.enum confidence |
| 7 (new) |
Shell shebang validator |
✅ pass |
p.glob + async defineTool + s.record output with s.optional(s.string) for shebangLine; repair addon |
| 8 (new) |
Git log graph summarizer |
✅ pass |
p.bash + sync defineTool with s.enum return; steering addon |
| 9 (new) |
TS complexity scorer |
✅ pass |
p.glob + async defineTool computing s.number score + s.enum complexity; repair addon |
| 10 (new) |
Parallel multi-tool workflow |
✅ pass |
workflow() with Promise.all of two call() invocations + call.json for coordination; required two fixes |
Problems encountered
Task 1 — TS Dead Export Finder
as const applied to an array returned from an async handler caused TS1355 ("A 'const' assertion can only be applied to references to enum members, or string, number, boolean, array, or object literals"). Plain return works correctly.
Task 2 — Pkg Scripts Documenter
Unused parameter name in handler destructuring caused TS6133. Fixed by removing it from destructuring.
Task 10 — Parallel Multi-Tool Workflow
Two separate issues:
workflow() does not accept an output field — the body return type is inferred from TypeScript. Removed output from the spec.
parallel() from the workflow body context enforces uniform return types: using parallel([() => call(agentA, ...), () => call(agentB, ...)]) where A and B have different output schemas caused a type mismatch. Fixed by using Promise.all instead, which correctly resolves each typed call independently.
Improvement opportunities
Missing or undiscoverable schema helpers (s.*)
s.int vs s.number distinction is well-documented but generated code initially used s.number for count fields. A lint rule prompting s.int for integer counts would help.
Missing or undiscoverable prompt helpers (p.*)
- No issues;
p.glob, p.bash, p.read, p.readOptional, p.write all used correctly across the 10 programs.
Error message quality
- TS2559 ("Type has no properties in common") for
workflow({ output: ... }) is opaque. The error body mentions WorkflowSpec but doesn't say "output is not a valid workflow field". A custom diagnostic or lint rule saying "workflow() does not support an output field; the body return type is inferred" would save time.
- TS2322 from
parallel() with heterogeneous agent outputs is confusing — the error points to the second element of the tuple as mismatched. It is not obvious that parallel unifies types vs Promise.all which preserves each independently.
API ergonomics
parallel() in workflow bodies enforces a single result type across all thunks, which is surprising when using typed subagents with different output schemas. Promise.all works instead but loses the concurrency limiter integration. A parallel overload that accepts a typed tuple [() => Promise<A|null>, () => Promise<B|null>] and returns [A|null, B|null] would greatly improve ergonomics for heterogeneous parallel calls.
Candidate lint rules
Rule: no-workflow-output-field
- Invalid:
workflow({ meta, output: s.object({...}), body })
- Valid:
workflow({ meta, body }) — body return type is inferred
- Why confusing:
agent() has an output field, so models try the same for workflow(). The field is silently dropped (or causes a type error).
- Autofix: remove the
output property from the workflow() call.
Rule: prefer-s-int-for-counts
- Invalid:
totalFiles: s.number
- Valid:
totalFiles: s.int
- Why confusing:
s.number technically works but loses the integer semantic contract. Models use it for count fields.
- Autofix: replace
s.number with s.int when the field name ends in Count, Total, Lines, Steps, etc.
Documentation gaps
- SKILL.md composition invariants mention that
workflow() fields include meta, input, body but do not explicitly call out that output is absent (unlike agent()). Adding a one-liner "No output field — body return type is inferred" would prevent a common mistake.
parallel() type constraint behavior (uniform vs tuple) is not described in SKILL.md or the dynamic-workflows reference. Worth adding a note that heterogeneous parallel calls should use Promise.all instead.
Tasks run today
- (reused) TypeScript dead export finder — p.glob + async defineTool + steering + repair
- (reused) package.json scripts documenter — p.read + defineTool + p.write + repair
- (reused) Git diff stats summarizer — p.bash + defineTool + s.enum + repair
- (reused) Dotenv template generator — p.readOptional + p.glob + async defineTool + p.write + repair
- (reused) Multi-file TypeScript class hierarchy extractor — p.bash + async defineTool + steering
- (reused) Git bisect helper — p.bash + defineTool + steering maxTurns:8
- (new) Shell script glob validator — p.glob + async defineTool + repair + s.record
- (new) Git log graph summarizer — p.bash + sync defineTool + steering + s.enum
- (new) TypeScript complexity scorer — p.glob + async defineTool + s.number + repair
- (new) Workflow parallel multi-tool tester — workflow + Promise.all + call.json coordination
Generated by Daily Rig Task Generator · sonnet46 105.5 AIC · ⌖ 9.34 AIC · ⊞ 6.8K · ◷
Summary
as conston array literal caused TS1355 — replaced with plain return; otherwise solid p.glob + async defineTool patternnameparam in handler caused TS6133 — destructured onlycommand; p.read + p.write + s.enum category pattern works wellProblems encountered
Task 1 — TS Dead Export Finder
as constapplied to an array returned from an async handler caused TS1355 ("A 'const' assertion can only be applied to references to enum members, or string, number, boolean, array, or object literals"). Plain return works correctly.Task 2 — Pkg Scripts Documenter
Unused parameter
namein handler destructuring caused TS6133. Fixed by removing it from destructuring.Task 10 — Parallel Multi-Tool Workflow
Two separate issues:
workflow()does not accept anoutputfield — the body return type is inferred from TypeScript. Removedoutputfrom the spec.parallel()from the workflow body context enforces uniform return types: usingparallel([() => call(agentA, ...), () => call(agentB, ...)])where A and B have different output schemas caused a type mismatch. Fixed by usingPromise.allinstead, which correctly resolves each typed call independently.Improvement opportunities
Missing or undiscoverable schema helpers (
s.*)s.intvss.numberdistinction is well-documented but generated code initially useds.numberfor count fields. A lint rule promptings.intfor integer counts would help.Missing or undiscoverable prompt helpers (
p.*)p.glob,p.bash,p.read,p.readOptional,p.writeall used correctly across the 10 programs.Error message quality
workflow({ output: ... })is opaque. The error body mentionsWorkflowSpecbut doesn't say "output is not a valid workflow field". A custom diagnostic or lint rule saying "workflow() does not support anoutputfield; the body return type is inferred" would save time.parallel()with heterogeneous agent outputs is confusing — the error points to the second element of the tuple as mismatched. It is not obvious thatparallelunifies types vsPromise.allwhich preserves each independently.API ergonomics
parallel()in workflow bodies enforces a single result type across all thunks, which is surprising when using typed subagents with different output schemas.Promise.allworks instead but loses the concurrency limiter integration. Aparalleloverload that accepts a typed tuple[() => Promise<A|null>, () => Promise<B|null>]and returns[A|null, B|null]would greatly improve ergonomics for heterogeneous parallel calls.Candidate lint rules
Rule:
no-workflow-output-fieldworkflow({ meta, output: s.object({...}), body })workflow({ meta, body })— body return type is inferredagent()has anoutputfield, so models try the same forworkflow(). The field is silently dropped (or causes a type error).outputproperty from theworkflow()call.Rule:
prefer-s-int-for-countstotalFiles: s.numbertotalFiles: s.ints.numbertechnically works but loses the integer semantic contract. Models use it for count fields.s.numberwiths.intwhen the field name ends inCount,Total,Lines,Steps, etc.Documentation gaps
workflow()fields includemeta,input,bodybut do not explicitly call out thatoutputis absent (unlikeagent()). Adding a one-liner "Nooutputfield — body return type is inferred" would prevent a common mistake.parallel()type constraint behavior (uniform vs tuple) is not described in SKILL.md or the dynamic-workflows reference. Worth adding a note that heterogeneous parallel calls should usePromise.allinstead.Tasks run today