summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhathach <[email protected]>2026-08-28 00:14:28 +0700
committerhathach <[email protected]>2026-08-28 00:16:26 +0700
commit09164de529cdde8aa4f454361a8dcd413bf43b32 (patch)
treef92a0047d042c0ee33b5fde5dc2fee7b650c6b1d
parent42db982e7c6e8ee7d2f80d15a93a7092d3b708c9 (diff)
pr-babysit: never edit HIL rig configs without user approvalclaude/pr-babysit-hil-guard
The workflow's fix lane once skipped two host tests in test/hil/tinyusb.json to green a check whose root cause was a failing fixture drive (reverted in 4b11d59a4). Rig rosters describe physical hardware: papering over a fixture fault hides it from the user who has to swap the part. Now fixAndVerify strips test/hil/*.json from every fix scope (a group left with no other files is withheld and logged), the code-writer prompt carries the constraint, and ok=false keeps such cycles from pushing. HIL stays red when the fix is a hardware swap - that red is the signal.
-rw-r--r--.claude/workflows/pr-babysit.js19
1 files changed, 18 insertions, 1 deletions
diff --git a/.claude/workflows/pr-babysit.js b/.claude/workflows/pr-babysit.js
index 2731ed254..3481e898e 100644
--- a/.claude/workflows/pr-babysit.js
+++ b/.claude/workflows/pr-babysit.js
@@ -200,11 +200,28 @@ const fixAndVerify = async (workIn) => {
}
work.push(g)
}
+ // HIL rig rosters (test/hil/*.json) describe physical hardware the user owns:
+ // never edit them autonomously — skipping/reshaping tests there papers over a
+ // failing fixture. A failure that needs hardware swapped or re-cabled stays RED
+ // for the user; roster edits happen only with the user's explicit approval.
+ const withheld = []
+ for (const w of work) {
+ for (const f of [...w.files]) if (/^test\/hil\/[^/]+\.json$/.test(f)) {
+ w.files.delete(f)
+ log(`fix for ${w.key}: ${f} is a HIL rig config — edits need user approval, dropped from scope`)
+ }
+ if (w.files.size === 0) {
+ withheld.push(w)
+ log(`fix for ${w.key}: only a HIL rig config edit would address it — leaving red for the user`)
+ }
+ }
+ for (const w of withheld) work.splice(work.indexOf(w), 1)
const scopeOf = (w) => [...w.files].join(', ')
const fixes = await pipeline(
work,
w => agent(
`Fix the following issues on the PR branch. ${IN_CHECKOUT}\n` +
+ 'Constraint: never modify test/hil/*.json (HIL rig hardware config) — a failure that needs hardware swapped/changed stays red for the user.\n' +
`Scope: ${scopeOf(w)}\nIssues:\n- ${w.notes.join('\n- ')}`,
{ label: `fix:${w.key}`, phase: 'Fix', agentType: 'code-writer', schema: DEV },
),
@@ -218,7 +235,7 @@ const fixAndVerify = async (workIn) => {
if (alive.length < work.length) log(`${work.length - alive.length} fix group(s) lost to dead workers`)
const unverified = alive.filter(f => f.addresses !== true)
for (const f of unverified) log(`fix for ${f.item}: failed verification — ${f.checkReason}`)
- return { ok: unscoped.length === 0 && alive.length === work.length && unverified.length === 0, fixes: alive }
+ return { ok: unscoped.length === 0 && withheld.length === 0 && alive.length === work.length && unverified.length === 0, fixes: alive }
}
// Verification gates every push: never push unverified or partial edits.