fix(workflows): actionable error messages for common workflow authoring mistakes#1388
Conversation
…ng mistakes Benchmark analysis showed 35% of agent turns (9 of 26) were spent on workflow authoring errors that could have been caught or guided by better error messages. This fixes the five most impactful failure modes: - Detect `arguments:` in step tasks and suggest `inputs:` (the correct field) - Detect string `dependsOn` entries and show the required object format - "Workflow not found" now suggests `swamp workflow create` and `swamp doctor workflows --json` - "Skipping broken workflow" warnings now suggest `swamp doctor workflows --json` - Rename method "Arguments:" to "Inputs:" in type describe log output to align with workflow YAML terminology - Add `inputs` field alongside `arguments` in type describe JSON output for backward-compatible terminology alignment Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
CLI UX Review
Blocking
-
swamp model method describestill shows "Arguments:" — inconsistent with the PR's stated goalsrc/presentation/renderers/model_method_describe.ts:53still emitsbold(cyan("Arguments:")). The PR updatedmodel_get.ts(used byswamp model getand, via the sharedformatMethodLines,swamp type describe), but missed the separate renderer forswamp model method describe, which has its own rendering path.After this PR:
swamp model get→ Inputs: ✅swamp type describe→ Inputs: ✅ (inherits viaformatMethodLines)swamp model method describe→ Arguments: ❌ (unchanged)
The PR description says the root cause was `swamp model type describe` showing "Arguments:" — but `swamp model method describe` is the most focused command for inspecting a single method's signature and it still shows the old label. Any agent or user reading that output will still see "Arguments:" and may copy it into YAML.
Fix: In
src/presentation/renderers/model_method_describe.ts:53, change:lines.push(bold(cyan("Arguments:")));
to:
lines.push(bold(cyan("Inputs:")));
Suggestions
-
The
workflowNotFoundmessage is now two sentences long and will appear inline (no line break) in log output. Consider putting the guidance on a new line for readability, e.g.\nCreate it with ...— same information, easier to scan quickly. -
In
model_method_describe.ts, the schema is formatted viadata.method.arguments(the old field name). That still works sinceargumentsis preserved for backward compat, but it would be cleaner to switch the renderer todata.method.inputsonce the label is updated, so the field name and displayed label agree.
Verdict
NEEDS CHANGES — the swamp model method describe renderer was not updated, leaving "Arguments:" in the output of the command most likely to be used when authoring workflow YAML. The fix is a one-line change.
There was a problem hiding this comment.
Code Review
Clean, well-motivated PR. The benchmark-driven approach to identifying the top 5 agent failure modes is solid, and the fixes are appropriately scoped. DDD layering is correct: validation logic lives in domain schemas, terminology alignment touches the presentation layer, and the libswamp import boundary is respected throughout.
Blocking Issues
None.
Suggestions
-
Missing test for Step-level string
dependsOndetection —StepDependencyFieldSchemainsrc/domain/workflows/step.ts:60-79has the same string detection logic asJobDependencyFieldSchemainjob.ts, but only the Job variant has a test (job_test.ts:254-273). Consider adding a parallel test instep_test.tsfor completeness — CLAUDE.md calls for comprehensive unit test coverage. The logic is identical so this isn't blocking, but it's a gap. -
Import placement in
job_test.ts—import { JobSchema } from "./job.ts"is added at line 252, after existing test code. Convention is to place imports at the top of the file.Jobis already imported on line 21;JobSchemacould be added to that existing import. -
argumentsfield check instep_task.ts:66— The condition"arguments" in d && !("inputs" in d)means that if a user provides bothargumentsandinputs, theargumentskey is silently ignored (stripped by Zod since it's not in the raw schema). This is probably fine for the intended use case (agents won't provide both), but worth noting for edge-case awareness.
There was a problem hiding this comment.
Adversarial Review
Critical / High
None found.
Medium
-
Inconsistent terminology rename —
src/presentation/renderers/model_method_describe.ts:53The PR's stated goal is terminology alignment: rename "Arguments:" to "Inputs:" in log output to prevent agents from copying the wrong field name into workflow YAML.
model_get.ts:96was updated to"Inputs:", butmodel_method_describe.ts:53still readsbold(cyan("Arguments:")). This meansswamp model getdisplays "Inputs:" whileswamp model method describedisplays "Arguments:" — exactly the inconsistency this PR is supposed to fix.Breaking scenario: An agent runs
swamp model method describe <model> run(the more targeted command), sees "Arguments:", and writesarguments:in its workflow YAML — the exact failure this PR is designed to prevent.Suggested fix: Change line 53 of
model_method_describe.tsfrom"Arguments:"to"Inputs:".
Low
-
argumentsdetection in step_task.ts fires for all task types —src/domain/workflows/step_task.ts:66The check
if ("arguments" in d && !("inputs" in d))runs before thetype === "model_method"guard, so it fires fortype: "workflow"tasks too. The error message example showsmodel_methodformat (modelIdOrName,methodName), which could be misleading for someone writing a workflow-type task with a typo. Not harmful sinceinputsis the correct field for both types, but the example could confuse. -
No test for
StepSchemastringdependsOndetectionThe PR adds a test for
JobSchemastringdependsOndetection (job_test.ts) but not forStepSchema(step_test.ts), despite adding identical preprocess logic to both. The step-level logic is duplicated (not shared), so a regression in one wouldn't be caught by the other's test.
Verdict
PASS — The logic changes are sound and well-tested. The medium finding (inconsistent "Arguments:" → "Inputs:" rename) weakens the PR's stated goal but doesn't cause incorrect behavior or data loss. Worth fixing before or shortly after merge.
- Fix inconsistent terminology in model_method_describe.ts: rename "Arguments:" to "Inputs:" to match model_get.ts and type_describe.ts - Switch renderers to read method.inputs instead of method.arguments - Add newline in workflowNotFound message for readability - Move JobSchema import to top of job_test.ts - Add missing StepSchema string dependsOn test in step_test.ts - Update model skill JSON example to show new inputs field Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Code Review
Clean, well-focused PR that adds actionable error messages to reduce agent workflow-authoring iterations. No blocking issues found.
Blocking Issues
None.
Suggestions
- Minor duplication in
dependsOnvalidation —JobDependencyFieldSchema(src/domain/workflows/job.ts:45-64) andStepDependencyFieldSchema(src/domain/workflows/step.ts:60-79) are nearly identical, differing only in thejob:vsstep:key in the example output. Per project conventions ("three similar lines is better than a premature abstraction"), this is fine as-is, but noting it in case the pattern spreads further.
What looks good
- DDD placement: Validation logic sits in the domain-layer Zod schemas (value objects/entities), exactly where it belongs. The
workflowNotFoundguidance is in the application service layer — also appropriate. - Libswamp import boundary: All presentation files correctly import from
../../libswamp/mod.ts, not internal paths. - Backward compatibility: JSON output adds
inputsalongsideargumentswithout breaking existing consumers. Theargumentscheck instep_task.tscorrectly allows both fields present simultaneously (line 66:"arguments" in d && !("inputs" in d)). - Test coverage: Every new behavior has a corresponding test —
argumentsdetection, stringdependsOnfor both Job and Step schemas, and updatedworkflowNotFoundmessage. - Scope discipline: Changes are minimal and focused — no unrelated refactoring or feature creep.
There was a problem hiding this comment.
CLI UX Review
Blocking
None.
Suggestions
-
workflowNotFoundmessage in JSON mode — theerrorfield now contains a multi-line string with an embedded\n. Scripts doingjq -r .errorget a two-line string, which is unexpected if they're expecting a single-line message. Thecode: "workflow_not_found"field is there for machine consumers to key on, so this isn't breaking, but splitting the guidance into a separatehintkey (alongsideerror) would be cleaner for scripts. Not blocking since thecodefield already gives scripts a stable identifier. -
"Skipping broken workflow" warning structure — when the Zod error message is multi-line (as the new
arguments → inputsandstring dependsOnerrors are),errorMsgis a JSON dump of the ZodError issues, and the doctor guidance (. Run 'swamp doctor workflows --json' to see all errors.) gets appended after that blob. The result is that the guidance is visually buried at the end of a potentially long JSON string. The new guidance is still helpful — it's better than nothing — but the placement makes it hard to spot in practice. Consider logging the doctor suggestion as a separatewarnline so it stands out. -
Terminology note for help text —
swamp model getandswamp model method describeboth previously showedArguments:in their output. Any user documentation or AI agent prompts that reference that label will now seeInputs:instead. The JSON output addsinputsalongside the existingargumentsfield (backward compatible), so JSON consumers are fine. Just worth noting the log-mode label change is not backward compatible for users screen-scraping output.
Verdict
PASS — all referenced commands (swamp workflow create, swamp doctor workflows --json) are verified to exist, JSON output is backward compatible, and the error messages are specific and actionable with correct YAML examples.
There was a problem hiding this comment.
Adversarial Review
Critical / High
None found.
Medium
- Inconsistent terminology alignment in Ink TUI renderers —
src/presentation/renderers/model_search.tsx:216,254andsrc/presentation/renderers/type_search.tsx:205,231still usemethod.argumentsand display the header"Arguments:", while the log-mode renderers (model_get.ts:91-96,model_method_describe.ts:50-53) were updated to usemethod.inputsand"Inputs:". This means the same command (e.g.swamp model search) displays "Inputs:" in log mode but "Arguments:" in the interactive TUI picker. Not a correctness bug since both fields contain the same data, but it undermines the stated PR goal of terminology alignment. Agents using the TUI output could still learn the wrong term.
Low
- Mixed string/object
dependsOnarrays produce slightly misleading error —src/domain/workflows/job.ts:47-48: FordependsOn: ["build", { job: "test", condition: { type: "succeeded" } }](mixed array), the error says "dependsOn entries must be objects, not strings" implying all entries are strings. The message is still helpful, and a mixed array is an unlikely mistake, so this is cosmetic.
Verdict
PASS — The changes are correct and well-tested. The z.preprocess throw pattern is consistent with existing precedent in step_task.ts. Backward compatibility is properly maintained via the dual arguments/inputs fields on MethodDescribeData. All error paths have test coverage. The Ink TUI terminology inconsistency (Medium #1) is worth a follow-up but doesn't block.
Summary
Benchmark analysis (k8s-debug-v2) showed 35% of agent turns were spent on
workflow authoring errors that could have been caught or guided by better error
messages. The agent hit 6 sequential errors before succeeding — each one
discoverable only by running the workflow and parsing failure output.
This PR adds actionable error messages at the point of failure:
arguments→inputsdetection — step task preprocessing now catchesarguments:(wrong) and suggestsinputs:(correct) with an example. Rootcause:
swamp model type describeshowed "Arguments:" which agentscopy into workflow YAML.
dependsOndetection — job and step schemas now detect barestrings in
dependsOnarrays and show the required{ job, condition }object format instead of a raw Zod validation dump.
swamp workflow createand
swamp doctor workflows --jsonso agents can self-recover.swamp doctor workflows --jsonto see all errors at once."Arguments:" to "Inputs:" in log output;
inputsfield added alongsideargumentsin JSON output (backward compatible).Test plan
argumentsin step task throws clear errordependsOnin job throws clear errorworkflowNotFoundmessage includes create + doctor guidancedeno checkclean,deno lintclean1-step recovery;
inputsfield in JSON output prevented the arguments/inputsconfusion entirely
🤖 Generated with Claude Code