T-TJB3-orchestrate-enforces-one-line-verdict
Status: closed/done · Impact: medium · Complexity: small
Auto-generated from a /sdlc:task-work post-mortem. Review and
promote to open/ready before picking up.
/sdlc:orchestrate’s parent-transcript budget (AC-4 of
T-3OVF-add-orchestrate-skill) and “small parent transcript”
invariant both depend on sub-agents — /sdlc:pr-check,
/sdlc:task-close-out, /sdlc:task-work — returning exactly one
verdict line to the parent. The sub-agent prompts ask for that
shape, but the model has no hard cap; a sub-agent that monologues
silently violates the contract. Closing this gap moves
“one-line verdict” from a polite request to an enforced property,
either by tightening the prompts or by a parent-side truncation
guard.
From the originating post-mortem:
The cross-skill invariant “parent transcript stays small” depends on sub-agents returning ONE LINE only. The current prompts say “return one verdict line” but the model has no hard cap; a sub- agent that monologues would violate the contract silently. Worth a follow-up — either tighten the prompt phrasing further or add a parent-side guard that truncates verbose returns.
plugin/skills/orchestrate/SKILL.md describes each sub-agent’s
expected return shape (e.g. DONE pr=#N | BLOCKED reason=... | NEEDS-DEFINITION slug=...) but the parent body doesn’t validate or
truncate. If the sub-agent returns a paragraph, the whole paragraph
lands in the parent transcript.
Proposed
Section titled “Proposed”Two complementary mitigations:
- Prompt tightening — every
Agent(general-purpose)dispatch in the orchestrate skill body wraps its task prompt with a visible “Return exactly one line in this shape: … Anything else will be truncated.” preamble. - Parent-side truncation guard — orchestrate prose mandates
that the parent splits the sub-agent return on the first newline
and discards the rest before parsing. Encode this as an
invariant in
invariants.yaml.
Approach
Section titled “Approach”- Audit the three sub-agent return contracts in
plugin/skills/orchestrate/SKILL.mdand confirm each names the exact verdict shape. - Add a “Return contract” sub-section to the orchestrate body
stating the truncation rule, and an example showing parent
pseudocode (
verdict = return_text.splitlines()[0]). - Add
required_phrasesentries toplugin/skills/orchestrate/invariants.yamlfor the truncation rule. - Optional: a tiny fixture sub-agent that returns a verbose blob, used to verify the truncation rule by hand.
Files to touch
Section titled “Files to touch”plugin/skills/orchestrate/SKILL.md— add Return contract and truncation rule.plugin/skills/orchestrate/invariants.yaml— pin the new required phrases.
Acceptance criteria
Section titled “Acceptance criteria”- AC-1:
SKILL.mddescribes the truncation rule explicitly and shows the one-liner parent-side parse. - AC-2:
invariants.yamlincludes a required phrase for the truncation rule;lint_skill_prose.pypasses. - AC-3: A fixture sub-agent that returns a 5-line blob, when dispatched by a real tick, results in only the first line landing in the parent transcript (verifiable by reading the digest log for that tick).
Out of scope
Section titled “Out of scope”- Sub-agent-side hard caps (would require harness changes).
- Reformatting existing pr-check / task-close-out return shapes (those stay as-is; only orchestrate’s parsing rule changes).
Dependencies
Section titled “Dependencies”- T-3OVF-add-orchestrate-skill must merge first.
Discovery context
Section titled “Discovery context”Spawned by /sdlc:task-work post-mortem of T-3OVF-add-orchestrate-skill on 2026-05-20.
Post-mortem
Section titled “Post-mortem”Captured by /sdlc:task-work on 2026-05-20. PR: pending.
Acceptance criteria coverage
Section titled “Acceptance criteria coverage”- AC-1: auto —
plugin/scripts/lint_skill_prose.py plugin/skills/orchestrate/SKILL.mdverifies the “Return contract” subsection exists and contains the documented pseudocode (splitlines,first non-blank line,truncated by the parent,Return EXACTLY ONE LINE). - AC-2: auto — same lint run; the four new
required_phrasesentries ininvariants.yamlexercise the truncation-rule prose and the linter reports zero violations. - AC-3: auto —
plugin/skills/orchestrate/tests/run_evals.pyships afive-line-blob-truncates-to-firstcase (plus 7 more invariant cases) and is wired intosdlc.yaml’squality_checks. Note: the AC originally said “verifiable by reading the digest log for that tick” — since orchestrate is a SKILL.md procedure with no parent script, an executable shadow of the documented truncation guard is the closest automated equivalent. A live-tick fixture remains possible but would require harness support to inject a synthetic sub-agent.
What worked
Section titled “What worked”- The existing
invariants.yamllinter made AC-1 and AC-2 essentially free — adding newrequired_phrasesentries with section anchors was the natural way to lock the contract, no new tooling required. plugin/skills/task-ensure-ready/tests/run_evals.py’s “executable shadow of the spec” pattern transferred cleanly to orchestrate’s truncation guard; the test file is a near-template copy of that layout, README and all.sdlc.yaml’squality_checkslist made wiring the new eval into the project gate a one-line edit.
Friction and automation gaps
Section titled “Friction and automation gaps”- The task body cited
plugin/validators/lint_skill_prose.pybut the script actually lives atplugin/scripts/lint_skill_prose.py. The relevance check caught it, but the task spec slipped through /sdlc:task-ensure-ready because path-resolution against a tight glob only checks paths under “Files to touch” — symbol/tool references elsewhere in the body aren’t normalized. A small enhancement to ensure-ready: also fuzzy-locate anyplugin/...path mentioned in the body and flag drift if the basename matches but the parent dir doesn’t. → T-V8K4-task-ensure-ready-fuzzy-locates-cited-paths - The skill’s Step 4 mandates
mise trust && just setup-worktree, but this project has no top-leveljustfile(it’s a pure plugin/docs repo with only asite/package.json). Thejustinvocation failed with “No justfile found” and I had to spot-skip the step. The worktree-init prose should either detect the presence of ajustfilebefore invokingjust, or delegate to a per-project helper that knows whether the project has node/cargo/just. → T-K7FR-task-work-worktree-init-language-agnostic - The task’s AC-3 phrasing (“verifiable by reading the digest log for that tick”) implied a live-orchestrate test, but orchestrate is procedural prose — there is no parent process to invoke that emits a digest line in CI. A skill-author convention: when an AC asks for “live” verification of a SKILL.md procedure, /sdlc:task-define should prompt for a fallback executable-shadow test rather than letting the prose-only AC ship. → T-P4VB-task-define-prompts-for-executable-shadow
Spawned follow-up tasks
Section titled “Spawned follow-up tasks”- T-V8K4-task-ensure-ready-fuzzy-locates-cited-paths — new task; closes the cited-path-drift gap in ensure-ready.
- T-P4VB-task-define-prompts-for-executable-shadow — new task; surfaces the executable-shadow fallback at task-define time so live-only ACs stop shipping.
- T-K7FR-task-work-worktree-init-language-agnostic — linked existing task; covers the no-justfile gap.