Skip to content

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.

Two complementary mitigations:

  1. 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.
  2. 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.
  1. Audit the three sub-agent return contracts in plugin/skills/orchestrate/SKILL.md and confirm each names the exact verdict shape.
  2. 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]).
  3. Add required_phrases entries to plugin/skills/orchestrate/invariants.yaml for the truncation rule.
  4. Optional: a tiny fixture sub-agent that returns a verbose blob, used to verify the truncation rule by hand.
  • plugin/skills/orchestrate/SKILL.md — add Return contract and truncation rule.
  • plugin/skills/orchestrate/invariants.yaml — pin the new required phrases.
  • AC-1: SKILL.md describes the truncation rule explicitly and shows the one-liner parent-side parse.
  • AC-2: invariants.yaml includes a required phrase for the truncation rule; lint_skill_prose.py passes.
  • 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).
  • 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).

Spawned by /sdlc:task-work post-mortem of T-3OVF-add-orchestrate-skill on 2026-05-20.

Captured by /sdlc:task-work on 2026-05-20. PR: pending.

  • AC-1: auto — plugin/scripts/lint_skill_prose.py plugin/skills/orchestrate/SKILL.md verifies 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_phrases entries in invariants.yaml exercise the truncation-rule prose and the linter reports zero violations.
  • AC-3: auto — plugin/skills/orchestrate/tests/run_evals.py ships a five-line-blob-truncates-to-first case (plus 7 more invariant cases) and is wired into sdlc.yaml’s quality_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.
  • The existing invariants.yaml linter made AC-1 and AC-2 essentially free — adding new required_phrases entries 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’s quality_checks list made wiring the new eval into the project gate a one-line edit.
  • The task body cited plugin/validators/lint_skill_prose.py but the script actually lives at plugin/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 any plugin/... 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-level justfile (it’s a pure plugin/docs repo with only a site/package.json). The just invocation failed with “No justfile found” and I had to spot-skip the step. The worktree-init prose should either detect the presence of a justfile before invoking just, 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

← Back to Tasks