Commit 47aff09
fix(devx): refuse a console injection stamp whose
`check:console-injection --require-stamp` passed on a well-formed stamp with an
empty `packages` array. readStamp's `Array.isArray` shape check accepts `[]`,
evaluate() fell through to "Nothing assertable in this stamp" and exited 0 — so
the flag whose entire purpose is to refuse a vacuous pass was satisfied by a
stamp that asserts nothing.
Measured: all three of the gate's substantive verdicts — the published-only
detector present in the bundle, the stamp's own fresh witness missing from it,
and probe expiry — are derived per package entry inside the loop over that
array. An empty array silences every one of them. A dist literally carrying the
PUBLISHED spec, the objectstack#8134 defect this gate exists to end, exited 0
under --require-stamp.
That is strictly MORE vacuous than the state objectstack#10428 refused one input
over: an unbuilt spec skips only the expiry re-check and leaves the two bundle
assertions standing. Refusing the lesser vacuity while tolerating the greater
one is incoherent, so this refuses on the same terms — exit 1 under
--require-stamp, advisory when bare, matching the no-dist and no-stamp verdicts.
Two layers, and they are not redundant:
- PRODUCER: writeStamp now refuses to write an empty entries array. It is the
one call site every producer passes, and the array shape exists to be GROWN
(objectstack#9659), so the day entries are derived from a package list
instead of a literal, a filter matching nothing becomes producible. The
caller downgrades the throw to a warning and writes no stamp, landing the
build in the missing-stamp state the gate already refuses.
- CONSUMER: the gate refuses it too, because its input crosses a cache
boundary the producer guard cannot reach. The dist is RESTORED FROM CACHE
from another run and may be partially restored or modified after it was
proved — the gate's own existing failure text says so. Producer and consumer
are deliberately not in one trust domain, which is why this gate exists as a
separate script at all.
Scoped to `packages.length === 0`, NOT to the `asserted === 0` notice: a no-skew
entry also leaves `asserted` at 0 but is a positive record that the build looked
and found nothing to tell the specs apart. Keying on `asserted` would fail every
no-skew run, which objectstack#10428 deliberately kept passing.
Reachability re-verified on main: writeStamp has exactly one call site, with a
hard-coded single-element array, reached from both stamping paths. No stamp this
repo produces can be empty today. The refusal covers hand-assembled, truncated
and partially-restored dists, and the derived-entries future the shape invites.
Self-test 27 -> 36 assertions. objectstack#10428's four-row table (spec not
built / built unchanged / built moved forward / built caught up, both flag
modes) is unmoved, as are the no-skew, no-stamp and published-spec controls.
Claude-Session: https://claude.ai/code/session_01DdCnBGcHeufjrq7drTD3wt
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>packages array is empty (#10621)1 parent e396cd0 commit 47aff09
2 files changed
Lines changed: 139 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
164 | 164 | | |
165 | 165 | | |
166 | 166 | | |
| 167 | + | |
167 | 168 | | |
168 | 169 | | |
169 | 170 | | |
| |||
257 | 258 | | |
258 | 259 | | |
259 | 260 | | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
260 | 301 | | |
261 | 302 | | |
262 | 303 | | |
| |||
600 | 641 | | |
601 | 642 | | |
602 | 643 | | |
| 644 | + | |
| 645 | + | |
| 646 | + | |
| 647 | + | |
| 648 | + | |
| 649 | + | |
| 650 | + | |
| 651 | + | |
| 652 | + | |
| 653 | + | |
| 654 | + | |
| 655 | + | |
| 656 | + | |
| 657 | + | |
| 658 | + | |
| 659 | + | |
| 660 | + | |
| 661 | + | |
| 662 | + | |
| 663 | + | |
| 664 | + | |
| 665 | + | |
| 666 | + | |
| 667 | + | |
| 668 | + | |
| 669 | + | |
| 670 | + | |
| 671 | + | |
| 672 | + | |
| 673 | + | |
| 674 | + | |
| 675 | + | |
| 676 | + | |
| 677 | + | |
| 678 | + | |
| 679 | + | |
| 680 | + | |
| 681 | + | |
| 682 | + | |
| 683 | + | |
| 684 | + | |
| 685 | + | |
| 686 | + | |
| 687 | + | |
| 688 | + | |
| 689 | + | |
| 690 | + | |
| 691 | + | |
| 692 | + | |
| 693 | + | |
| 694 | + | |
| 695 | + | |
| 696 | + | |
| 697 | + | |
| 698 | + | |
| 699 | + | |
| 700 | + | |
| 701 | + | |
| 702 | + | |
| 703 | + | |
| 704 | + | |
| 705 | + | |
| 706 | + | |
| 707 | + | |
| 708 | + | |
| 709 | + | |
| 710 | + | |
| 711 | + | |
| 712 | + | |
| 713 | + | |
| 714 | + | |
| 715 | + | |
| 716 | + | |
| 717 | + | |
| 718 | + | |
| 719 | + | |
| 720 | + | |
| 721 | + | |
| 722 | + | |
| 723 | + | |
603 | 724 | | |
604 | 725 | | |
605 | 726 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
146 | 146 | | |
147 | 147 | | |
148 | 148 | | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
149 | 167 | | |
150 | 168 | | |
151 | 169 | | |
| |||
0 commit comments