Skip to content

fix(workflows): two bug classes surfaced by apex 3064 dogfood - #224

Merged
PolyphonyRequiem merged 1 commit into
mainfrom
sdlc/dogfood-3064-yaml-fixes
May 9, 2026
Merged

fix(workflows): two bug classes surfaced by apex 3064 dogfood#224
PolyphonyRequiem merged 1 commit into
mainfrom
sdlc/dogfood-3064-yaml-fixes

Conversation

@PolyphonyRequiem

Copy link
Copy Markdown
Owner

Summary

Two distinct bug classes surfaced while walking apex AB#3064 end-to-end through
the dogfood pipeline. Both are workflow-YAML-only fixes (5 files, +6/-4).

Live verification: with these fixes applied, apex 3064 walked from preflight all
the way through the outer loop to a clean terminal_apex_blocked exit (exit 0).
Plan PR #223 had been merged in a prior iteration — these fixes covered the
post-merge cascade and the outer-loop evaluator that crashed in iter 4.

Class A — verb signature drift after Move #2 (PR #199)

Move #2 swept ~52 routing-style verbs to use RequiredInput.HaltIfMissing on
flag-form arguments. Two YAML call sites were still calling positionally and
silently emitting routing-error envelopes (rendered as ✓ by conductor), which
then caused downstream Jinja TemplateError: 'dict object' has no attribute 'total_stale' because the empty envelope was indexed for fields that only
exist on success.

File Site Fix
cascade-remedy.yaml:74 polyphony plan classify-stale-descendants positional {root_id}--root-id {root_id}
plan-level.yaml:1605 polyphony plan extract-renegotiation-flag positional {pr_number}--pr-number {pr_number}

Lint coverage gap: VERB001/002/003 (PR #197) did NOT catch these. The
two-pass positional-binding algorithm models ConsoleAppFramework's mixed
flag/positional binding but doesn't appear to flag positional drift to
flag-only verbs in workflow YAMLs. Followup tracked separately as a lint
extension; not in scope for this PR.

Class F — YAML folded-scalar (>-) trap

YAML >- (folded scalar) collapses every \n in the script body. This
destroys two PowerShell constructs that depend on real newlines:

  1. @'…\n…'@ here-strings — @' opener with text on same line is a fatal
    parser error: "No characters are allowed after a here-string header but before the end of the line."
  2. # comments — PowerShell comments extend to end-of-line. After folding, a
    comment swallows the entire rest of the script (including code that follows
    on later source lines, [type] accelerators, closing braces, and the
    result-emitting @{…} block).

The worst symptom: outer_loop_evaluator's # Apex satisfaction: comment
block ate the entire $decision = if (...) block, leaving conductor with
'dict object' has no attribute 'decision' because decision was never
defined in the rendered output.

Four sites converted from >- to | (literal block, preserves newlines):

File Agent Hazard
apex-driver.yaml:623 aggregate_renegotiation heredoc
apex-driver.yaml:713 outer_loop_evaluator heredoc + # comments (worst)
apex-wave-dispatch.yaml:179 aggregate_renegotiation heredoc + # comments
apex-item-dispatch.yaml:467 terminal_satisfied # comments inside } catch { … }

Audit complete across all 14 workflow YAMLs:

  • 0 remaining >- blocks contain @' heredocs.
  • 0 remaining >- blocks contain # comments after the first line.
  • All other >- blocks are single-line or multi-statement bodies separated
    by ; that fold safely.

Lint coverage gap: No existing lint catches >- + heredoc / >- + comment
combinations. Worth a future skill update + lint rule; deferred from this PR.

Verification

  • pwsh -File tests/lint-jinja-resolver.ps1 → PASS (no errors)
  • pwsh -File tests/lint-conductor-validate.ps1 → PASS (14/14 workflows)
  • ✅ Live dogfood apex AB#3064 walked end-to-end:
    • preflight → init_manifest → declare_root → outer_loop_init
    • build_worklist → check_conflicts → wave_dispatch_loop[1/1]
    • classify_lifecycle → spawn_worktree → plan_level_dispatch → …
    • state_detector → child_router → teardown_worktree → terminal_dispatched
    • aggregate_renegotiation → integrate_wave → wave_loop_summary
    • renegotiation_summary → outer_loop_evaluator → terminal_apex_blocked → ✓
    • Workflow exit 0; terminal "blocked" because no progress in iter 1 with
      apex tree of 14 items not yet seeded — expected outcome (the apex itself
      is dispatched but children aren't planned/seeded, so the loop's
      progress-counter caps at 0 and routes to blocked).

Five workflow YAMLs touched, two distinct bug classes — both surfaced by
walking apex AB#3064 end-to-end (PR #223 plan PR merged successfully,
then the post-merge cascade and outer-loop steps crashed in sequence).

## Class A — verb signature drift after Move #2 (PR #199)

Move #2 swept ~52 routing-style verbs to use `RequiredInput.HaltIfMissing`
on flag-form arguments. Two YAML call sites were still calling positionally
and silently emitting routing-error envelopes (rendered as ✓ by conductor),
which then caused downstream Jinja `TemplateError: 'dict object' has no
attribute 'total_stale'` because the empty envelope was indexed for fields
that only exist on success.

- `cascade-remedy.yaml:74` — `polyphony plan classify-stale-descendants`
  positional `{root_id}` → `--root-id {root_id}`.
- `plan-level.yaml:1605` — `polyphony plan extract-renegotiation-flag`
  positional `{pr_number}` → `--pr-number {pr_number}`.

Lint coverage gap: VERB001/002/003 (PR #197) did NOT catch these.
Followup tracked separately — see dogfood notes.

## Class F — YAML folded-scalar (`>-`) trap

YAML `>-` (folded scalar) collapses every `\n` → ` ` in the script body.
This destroys two PowerShell constructs that depend on real newlines:

- `@'…\n…'@` here-strings — `@'` opener with text on same line is a fatal
  parser error: "No characters are allowed after a here-string header but
  before the end of the line."
- `# comments` — PowerShell comments extend to end-of-line. After folding,
  a comment swallows the entire rest of the script (including code that
  follows on later source lines, `[type]` accelerators, closing braces,
  and the result-emitting `@{…}` block).

Three sites converted from `>-` to `|` (literal block, preserves newlines):

- `apex-driver.yaml:623` (`aggregate_renegotiation`) — has heredoc
- `apex-driver.yaml:713` (`outer_loop_evaluator`) — has heredoc + comments
  (with the worst symptom — `# Apex satisfaction:` ate the entire decision
  block, leaving conductor with `'dict object' has no attribute 'decision'`)
- `apex-wave-dispatch.yaml:179` (`aggregate_renegotiation`) — has heredoc
  + comments
- `apex-item-dispatch.yaml:467` (`terminal_satisfied`) — has comments
  inside `} catch { … }` block; folded would swallow the closing `}` and
  the whole `@{…} | ConvertTo-Json` payload

Audit done across all 14 workflow YAMLs:
- 0 remaining `>-` blocks contain `@'` heredocs (post-fix).
- 0 remaining `>-` blocks contain `#` comments after the first line.

## Verification

- `pwsh -File tests/lint-jinja-resolver.ps1` → PASS (no errors)
- `pwsh -File tests/lint-conductor-validate.ps1` → PASS (14/14 workflows)
- Live dogfood apex AB#3064 walked end-to-end through:
  preflight → init_manifest → declare_root → outer_loop_init →
  build_worklist → check_conflicts → wave_dispatch_loop[1/1] →
  classify_lifecycle → spawn_worktree → plan_level_dispatch → … →
  state_detector → child_router → teardown_worktree → terminal_dispatched →
  aggregate_renegotiation → integrate_wave → wave_loop_summary →
  renegotiation_summary → outer_loop_evaluator → terminal_apex_blocked → ✓
  (workflow exit 0; terminal "blocked" because no progress in iter 1
  with apex tree of 14 items not yet seeded — expected outcome)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@PolyphonyRequiem

Copy link
Copy Markdown
Owner Author

polyphony:approve

@PolyphonyRequiem
PolyphonyRequiem merged commit ebb95a2 into main May 9, 2026
1 check passed
@PolyphonyRequiem
PolyphonyRequiem deleted the sdlc/dogfood-3064-yaml-fixes branch May 9, 2026 04:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant