Tier A #1 — the strongest case in the set. Zero refutations across all three adversarial lenses.
Source: docs/plans/dynamic-workflow-migration.md §1 (merged in #2162).
Why this one wins
Agent count is identical before and after. REFERENCE.md already ships the JS skeleton and the skill already runs this shape — so there is no token-cost objection to answer. What the harness buys is that the gate
['still-present','partially-fixed'].includes(verdict) && duplicateFound === 'no'
stops being a boolean the model re-derives from prose on every run.
Shape: composite — fan-out (verify ∥ search per candidate) → generate-and-filter (draft → cold-read → batch dedup).
Two caveats the adversarial pass added
- Waves of ≤5. The skill paces its writes at 70 s but left reads unbounded. A 24-candidate manifest would fire 48 concurrent agents at an instance the skill itself calls aggressively rate-limiting.
DRAFT_SCHEMA carries the body, not a path. Batch-dedup cannot merge on a file path a workflow script has no filesystem to read.
Sketch
export const meta = { name: 'verify-before-filing',
phases: [{title:'Verify'},{title:'Search'},{title:'Draft'},{title:'ColdRead'},{title:'Revise'},{title:'BatchDedup'}] }
const CANDIDATES = (typeof args === 'string') ? JSON.parse(args) : args.candidates
const WAVE = 5 // pace reads like Phase 3 paces writes
const triaged = []
for (let i = 0; i < CANDIDATES.length; i += WAVE) {
phase(`Verify + dedup — candidates ${i + 1}..${Math.min(i + WAVE, CANDIDATES.length)}`)
const wave = await pipeline(CANDIDATES.slice(i, i + WAVE),
async (item) => {
const [verify, search] = await parallel([ // BARRIER (intra-candidate): the gate needs BOTH
() => agent(VERIFY_PROMPT(item), {label:`verify:${item.id}`, phase:'Verify', schema:VERIFY_SCHEMA}),
() => agent(SEARCH_PROMPT(item), {label:`search:${item.id}`, phase:'Search', schema:SEARCH_SCHEMA}),
])
if (!verify || !search) return {...item, disposition:'agent-error'}
const passes = ['still-present','partially-fixed'].includes(verify.verdict)
&& search.duplicateFound === 'no' // gate precedence: a duplicate kills regardless of verdict
return {...item, verify, search, disposition: passes ? 'draft'
: (search.duplicateFound !== 'no' ? `duplicate: ${search.wave1Overlap}` : verify.verdict)}
},
async (c) => { // draft only survivors; schema carries body, not just path
if (c.disposition !== 'draft') return c
const draft = await agent(DRAFT_PROMPT(c), {label:`draft:${c.id}`, phase:'Draft', schema:DRAFT_SCHEMA})
return draft ? {...c, draft} : {...c, disposition:'draft-failed'}
},
async (c) => { // adversarial gate — NEVER the drafter
if (!c.draft) return c
let cold = await agent(COLDREAD_PROMPT(c.draft.body),
{label:`coldread:${c.id}`, phase:'ColdRead', model:'haiku', schema:COLD_SCHEMA})
if (cold?.verdict === 'needs-revision') {
const rev = await agent(REVISE_PROMPT(c.draft, cold.critique), {label:`revise:${c.id}`, phase:'Revise', schema:DRAFT_SCHEMA})
if (rev) c = {...c, draft: rev}
cold = await agent(COLDREAD_PROMPT(c.draft.body),
{label:`recoldread:${c.id}`, phase:'ColdRead', model:'haiku', schema:COLD_SCHEMA})
} // exactly ONE revise round — a fixed gate, not a loop
return {...c, cold, disposition:'file'}
})
triaged.push(...wave)
}
phase('Batch dedup — BARRIER: survivors compared to EACH OTHER, not just to the tracker')
const filing = triaged.filter(c => c.disposition === 'file')
const batch = await agent(BATCH_DEDUP_PROMPT(filing), {label:'batch-dedup', phase:'BatchDedup', schema:BATCH_SCHEMA})
return { file: batch.keep, merged: batch.merged, // Phase 3 (scripts/file-wave.sh) consumes this
dispositions: triaged.map(c => ({id:c.id, slug:c.slug, disposition:c.disposition})) }
SKILL.md delta
Under ## The Pipeline, add the standard template framing, then:
Phases 1–2 ship as verify-before-filing.workflow.js. Non-negotiable across any adaptation: the closed verdict vocabulary; the gate expression (a duplicate kills the filing regardless of verdict); the cold-read agent being a different agent from the drafter; the batch-dedup barrier; and the ≤5 read wave. A 24-candidate run is roughly 100–140 agents — if your run has one candidate, skip the workflow and do Phase 1 inline.
Acceptance
Blocked by #2166 (extract scripts/file-wave.sh — the harness returns the shape that script consumes) and #2163 (layout convention).
Tier A #1 — the strongest case in the set. Zero refutations across all three adversarial lenses.
Source:
docs/plans/dynamic-workflow-migration.md§1 (merged in #2162).Why this one wins
Agent count is identical before and after.
REFERENCE.mdalready ships the JS skeleton and the skill already runs this shape — so there is no token-cost objection to answer. What the harness buys is that the gatestops being a boolean the model re-derives from prose on every run.
Shape: composite — fan-out (verify ∥ search per candidate) → generate-and-filter (draft → cold-read → batch dedup).
Two caveats the adversarial pass added
DRAFT_SCHEMAcarries the body, not a path. Batch-dedup cannot merge on a file path a workflow script has no filesystem to read.Sketch
SKILL.md delta
Under
## The Pipeline, add the standard template framing, then:Acceptance
workflows/verify-before-filing.workflow.jsbeside SKILL.md## Workflow harness (template)framing present, incl.not a script to run verbatimDRAFT_SCHEMAboth presentdocs-currency.md)Blocked by #2166 (extract
scripts/file-wave.sh— the harness returns the shape that script consumes) and #2163 (layout convention).