fix(labels): pass bootstrap through the workflow_call boundary it was lost at
A called workflow cannot read the caller's dispatch inputs on this forge:
github.event.inputs is empty inside workflow_call even though the top-level
caller receives the value in both contexts (probe runs 6/7). The sweep's gate
read exactly that, so every dispatch-woken sweep bootstrapped — runs 459 and
523, ~20 label upserts per board event — while the trigger honestly logged
bootstrap=no.
The bridge, per the #6361 contract: labels-sweep.yml declares
workflow_call.inputs.bootstrap (string, default "no"); the dogfood caller and
the published CONSUMERS.md stub pass it via with.bootstrap with empty mapped
to "no" at the caller — kimi's edge: on schedule the top-level context is
empty, and an empty that slipped through would have turned every cron into a
bootstrap. The gate feeds the declared input to labels-reconcile unchanged,
so an invalid value meets the action's own yes|no refusal.
test/labels-bootstrap.test.sh pins every hop: the declared boundary, both
gates as the identity, no expression reading github.event.inputs (scoped to
${{ }} bodies — the file's prose names the context to explain it), the two
pass-throughs byte-exact, and the four value paths driven through the shipped
expressions into the action's real validator. Mutations: dropping the
declaration reds 4, dropping the pass-through reds 3, restoring the old gate
reds 2.
Refs #215
2026-08-05 21:06:29 +00:00
|
|
|
### Fixed
|
|
|
|
|
|
|
|
|
|
- The sweep's `bootstrap` value crosses the `workflow_call` boundary as a
|
2026-08-05 21:18:29 +00:00
|
|
|
declared input, explicitly passed by the caller — the one channel measured
|
|
|
|
|
to work; the called workflow did not see the caller's event inputs as an
|
|
|
|
|
implicit substitute on this instance (#215).
|
fix(labels): pass bootstrap through the workflow_call boundary it was lost at
A called workflow cannot read the caller's dispatch inputs on this forge:
github.event.inputs is empty inside workflow_call even though the top-level
caller receives the value in both contexts (probe runs 6/7). The sweep's gate
read exactly that, so every dispatch-woken sweep bootstrapped — runs 459 and
523, ~20 label upserts per board event — while the trigger honestly logged
bootstrap=no.
The bridge, per the #6361 contract: labels-sweep.yml declares
workflow_call.inputs.bootstrap (string, default "no"); the dogfood caller and
the published CONSUMERS.md stub pass it via with.bootstrap with empty mapped
to "no" at the caller — kimi's edge: on schedule the top-level context is
empty, and an empty that slipped through would have turned every cron into a
bootstrap. The gate feeds the declared input to labels-reconcile unchanged,
so an invalid value meets the action's own yes|no refusal.
test/labels-bootstrap.test.sh pins every hop: the declared boundary, both
gates as the identity, no expression reading github.event.inputs (scoped to
${{ }} bodies — the file's prose names the context to explain it), the two
pass-throughs byte-exact, and the four value paths driven through the shipped
expressions into the action's real validator. Mutations: dropping the
declaration reds 4, dropping the pass-through reds 3, restoring the old gate
reds 2.
Refs #215
2026-08-05 21:06:29 +00:00
|
|
|
|
|
|
|
|
- Before the bridge, `github.event.inputs` was empty inside the called
|
|
|
|
|
workflow, so every dispatch-woken sweep bootstrapped: ~20 label upserts on
|
|
|
|
|
each board event (#215).
|
|
|
|
|
|
|
|
|
|
- The caller maps an empty top-level value to `no` explicitly, so a
|
|
|
|
|
cron-woken sweep can never bootstrap; the declared input also defaults to
|
|
|
|
|
`no`, so a consumer that passes nothing gets the safe path (#215).
|
|
|
|
|
|
|
|
|
|
- The gate feeds the declared input to `labels-reconcile` unchanged, so an
|
|
|
|
|
invalid value meets the action's own `yes|no` refusal instead of being
|
|
|
|
|
silently coerced (#215).
|
|
|
|
|
|
|
|
|
|
- `docs/CONSUMERS.md`'s published sweep stub carries the same pass-through —
|
|
|
|
|
without it every consumer inherits the defect ceremony fixed for
|
|
|
|
|
itself (#215).
|
|
|
|
|
|
|
|
|
|
### Added
|
|
|
|
|
|
|
|
|
|
- `test/labels-bootstrap.test.sh` pins the bridge at every hop: the declared
|
|
|
|
|
boundary, both gate sites as the identity, no expression reading
|
2026-08-05 21:08:51 +00:00
|
|
|
`github.event.inputs`, and the caller and stub pass-throughs
|
|
|
|
|
byte-exact (#215).
|
|
|
|
|
|
|
|
|
|
- The same test drives the four value paths — schedule-empty, `no`, `yes`,
|
|
|
|
|
invalid — through the shipped expressions into the action's real
|
|
|
|
|
validator (#215).
|
2026-08-05 21:32:21 +00:00
|
|
|
|
|
|
|
|
- The taxonomy bootstrap keys on the `BOOTSTRAP` input, never the event name.
|
|
|
|
|
It tested `GITHUB_EVENT_NAME = workflow_dispatch` — correct while an
|
|
|
|
|
operator's manual dispatch was the only dispatch there was, inert-by-
|
|
|
|
|
construction from #209 on, when every machine wake became a dispatch
|
|
|
|
|
event (#215).
|
|
|
|
|
|
|
|
|
|
- The venue drill caught that: with the bridge delivering `no` perfectly,
|
|
|
|
|
drill runs 16/17 still bootstrapped, because the script never read the
|
|
|
|
|
input the whole chain existed to deliver (#215).
|
|
|
|
|
|
|
|
|
|
- `test/labels-reconcile.test.sh` pins the regression pair exactly: a
|
|
|
|
|
`workflow_dispatch` event with `BOOTSTRAP=no` (or unset) creates and
|
|
|
|
|
deletes nothing; only `BOOTSTRAP=yes` bootstraps (#215).
|