Skip to content

feat(configure-plugin): ship configure-all parallel check harness template #2168

Description

@laurigates

Tier A #2. Zero refutations.

Source: docs/plans/dynamic-workflow-migration.md §2 (merged in #2162).

Why this one wins

The fan-out width is already deterministiclist-components.sh emits the roster. 34 of 38 components have no script of their own, so the checks are genuinely agent-shaped rather than script-shaped. And unlike most candidates, configure-all does not hold context: fork, so its context-pressure problem is live and unaddressed.

Shape: fan-out-and-synthesize, one check agent per applicable roster row.

Design decisions from the adversarial pass

  • The classify agent is deleted. Applicability is types === 'all' || types.split(',').includes(projectType) over a field the script already emits. No agent decides this.
  • --fix never enters the workflow. Pre-commit and linting both write .pre-commit-config.yaml; parallel fixers would race.
  • A floor, not just a ceiling. Below ~15 applicable components the sequential path is cheaper than 15 agent preambles.

Sketch

export const meta = { name:'configure-all-check', phases:[{title:'Check'},{title:'Synthesize'}] }
const { roster, projectType, ambiguous = [] } = (typeof args === 'string') ? JSON.parse(args) : args
if (!roster?.length) { log('empty roster — list-components.sh returned STATUS=ERROR; abort'); return { abort:true } }

// TYPES is manifest data, not a judgement. No agent decides this.
const applicable = roster.filter(r => r.types === 'all' || r.types.split(',').includes(projectType))
const skipped    = roster.filter(r => !applicable.includes(r)).map(r => ({...r, reason:`TYPES=${r.types}`}))
if (applicable.length < 15) { log(`${applicable.length} components — sequential path is cheaper; abort`); return { abort:true } }

phase(`Check — ${applicable.length} components, READ-ONLY, ≤5 in flight`)
const checks = []
for (let i = 0; i < applicable.length; i += 5) {
  const wave = applicable.slice(i, i + 5)
  const got = await parallel(wave.map(c => () => agent(
    `Invoke /configure:${c.component} --check-only via SlashCommand. READ-ONLY — report findings, write nothing.`,
    { label:`check:${c.component}`, phase:'Check', schema: CHECK_SCHEMA })))
  checks.push(...got.map((r, j) => r || { component: wave[j].component, status:'ERROR', issues:['agent returned null'], files:[] }))
}

phase('Synthesize — BARRIER: the fix plan must see every component at once')
const report = await agent(SYNTH_PROMPT(checks, skipped),   // groups components contending for the same file
  { label:'synthesize', phase:'Synthesize', schema: REPORT_SCHEMA })
return { report, fixPlan: report.fixPlan }                  // --fix applied OUTSIDE, sequentially, by the skill

Two hard prerequisites the design omitted

  1. allowed-tools currently has no Task/Agent — add it, or the skill cannot dispatch at all.
  2. Each check agent's toolset must include SlashCommand, or it will re-derive a component check from scratch instead of invoking /configure:<component>.

SKILL.md delta

New ### Step 3b: Heavy path — parallel check fan-out (optional) between Steps 3 and 4, with the template framing and the explicit floor. Step 5 gains:

--fix never runs inside the workflow. Several components mutate the same files; parallel fixers would race. Apply the fixPlan sequentially.

Replace the hardcoded four-way ## Agent Teams (Optional) table with a pointer to the harness. Note that exitCode cannot come from a workflow — the skill converts the report to a process exit code.

Acceptance

  • workflows/configure-all-check.workflow.js beside SKILL.md
  • allowed-tools gains Task/Agent; check agents get SlashCommand
  • <15 floor and read-only-check invariant present
  • ## Agent Teams (Optional) table replaced, not left to drift

Blocked by #2163 (layout convention).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions