wake suites: unguarded source of _wake-common.sh lets a suite exit 0 with zero assertions run #984
Closed
opened 2026-07-31 07:45:45 +00:00 by mos-dt-0
·
1 comment
No Branch/Tag Specified
main
remediation/state
feat/rm-02-gate-registry
fix/rm-01-reproducible-checkout
remediation/mission-setup
fix/hygiene-inert-format-gate
fix/1019-queue-guard-stdin
feat/mos-ste-writing-standard
fix/1007-suite-hermeticity
fix/991-comment-url-scheme-normalise
feat/push-guard-null-case-verification
mos-comms-live
docs/heartbeat-framework-layering-ms-lead
feat/869-c4-version-coupling
feat/869-c2-install-ordering-guard
feat/869-c5-doctor-activation-check
feat/per-agent-gitea-identity
fix/875-belongs-case-insensitive-slug
fix/ci-queue-wait-404-branch-absent
feat/869-c1-activation-probe
feat/869-c3-broker-supervisor
fix/865-tea-cli-comment-invocation
feat/glpi-skills
fix/860-deflake-mutator-lease-gate
fix/850-detect-platform-port-normalization
fix/856-worktree-deps-preflight
fix/835-pr-review-approve-reject-comment-flag
fix/848-truthful-evidence
fix/812-pr-review-comment
fix/849-recovery-runtime-fixture-race
docs/758-ledger-m5-001-sync
feat/834-tc-server-side-doc
feat/833-constrained-recovery-command
feat/827-gate0-probe
governance/gate0-probe3-amendment
fix/795-codex-pr-diff
fix/795-ci-base-jq
fix/795-ci-base-git
feat/791-pr3-fleet-regen
feat/791-pr2-snapshot-restore
fix/807-glpi-206
fix/808-agent-send-false-sender
feat/791-upgrade-config-protection
feat/790-mosaic-yolo-claudex-pr2
feat/790-mosaic-yolo-claudex
feat/758-v1-v2-migrator
fix/766-exact-fleet-comms
test/758-reconciler-lifecycle-gates
docs/771-kbn101-db-role-split
test/758-example-profile-dispositions
feat/758-shared-role-resolution
feat/mos-logical-identity-fencing
feat/769-kbn100-unified-schema
docs/753-kbn010-threat-gate
feat/758-roster-v2-compiler
feat/756-official-discord-plugin
docs/758-fleet-config-management
fix/mos-option2-qualification-format
docs/issue-758-m0
docs/mos-option2-qualification
mos-comms
feat/tess-interaction-agent
fix/tess-docs-format
next
draft/mosaic-platform-prd
fix/installer-provider-gate-and-local-gateway-redis
release/mosaic-cli-0.0.37
feat/framework-constitution-alpha
fix/git-wrapper-repo-detection
fix/woodpecker-wrapper-legacy-mosaic
fix/t-a292e96f-gitea-pr-metadata
fix/gitea-pr-metadata-login-t-a292e96f
fix/t_a292e96f-pr-metadata-gitea
fix/t_3a368a52-gitea-usc-login
fix/bootstrap-hotfix
fix/populate-known-packages-list
fix/idempotent-init
v0.0.39-alpha
mosaic-v0.0.31
fed-v0.2.0-m2
fed-v0.1.0-m1
mosaic-v0.0.29
mosaic-v0.0.28
mosaic-v0.0.27
mosaic-v0.0.26
mosaic-v0.0.25
mosaic-v0.0.24
v0.2.0
v0.1.0
v0.0.8
v0.0.7
v0.0.6
v0.0.5
v0.0.4
No labels
Milestone
No items
No Milestone
Projects
Clear projects
No projects
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: mosaicstack/stack#984
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Found during the #973 review (branch
feat/973-has-match, head5e98419d). Non-gating for#973 — it predates that branch in form and the branch does not make it worse. Filed separately
because it is the same defect class #973 exists to remove, sitting in the line that installs the
removal.
The defect
All ten wake suites integrate the loudness helpers with one line:
Every suite runs under
set -uo pipefail. None usesset -e. So if the source fails —file missing, unreadable, syntax error, wrong
SCRIPT_DIRafter a refactor — the&&short-circuits,
wake_assert_initnever runs, and the suite keeps going withhas_matchandcount_linesundefined.Measured reproduction
Reduced case, run locally:
_wake-common.shthat does not exist → source fails, rc≠0.wake_assert_initskipped via&&.has_match ... && fail) →has_match: command not found, rc=127,the
&&is not taken, the failure branch is silently skipped.Why it matters
.woodpecker/ci.yml:126→pnpm test→test:framework-shell, a 30-command&&chain whosepositions 21–30 are these ten suites. A suite that exits 0 having executed zero wake
assertions is indistinguishable, from the pipeline's colour, from one that executed all 261.
This is the umbrella shape exactly: an operation that returns a definite answer on a path
where the measurement did not happen, with the failure mode and the safe state producing the
same output.
Fix
Make the source failure fatal — one line per suite, e.g.
exit 97matches the abort convention already established in_wake_assert_abort.Bound on this report
I measured the reproduction in a reduced case, not by breaking the real tree. The four failure
causes listed (missing/unreadable/syntax/
SCRIPT_DIRdrift) are the class; I demonstrated themissing-file member of it. The behaviour after a failed source follows from the absence of
set -e, which I did verify in all ten suites.-- mos-dt (sb-it-1-dt). Signed in body; shared account on this host, so the signature is a
labelled claim, never provenance.
Correction to my own recommendation in this issue body. I wrote "
exit 97matches the abortconvention already established in
_wake_assert_abort." That is half the convention, and the halfI omitted is the load-bearing one.
Measured on
5e98419d:_wake-common.shproducesexit 97at three sites —:256(pinmktempfailure),
:273(BASH_LINENO convention violated),:305(_wake_assert_abort). All three emita wake-authored diagnostic naming that specific refusal first. 97 is not "something went wrong";
it is "the assert machinery refused, and here is which refusal."
So the condensed form
would add a fourth 97-producing path and the only one carrying no wake-authored line. Bash does
print its own
No such file or directory, so it is not silent — but it does not say the assertmachinery never loaded, and it does not say the suite ran zero assertions. An operator reading
97in a CI log currently learns "a site refused to answer, and the log says which"; after thatchange,
97could also mean "the harness never started," with nothing in the wake vocabulary toseparate them.
Second, a coupling hazard that is about the shape rather than today's code.
A && B || CbindsCto both
AandBfailing. Todaywake_assert_initcan onlyexit, neverreturnnon-zero,so the forms are equivalent — but that is a property of the current init, not of the idiom. If init
ever gains a
return 1path, the||swallows it into an undiagnosed 97.Recommended shape instead — guard bound to the source alone, diagnostic present:
Non-gating and non-blocking; the fatal-source fix is right either way and the difference is one
line of diagnostic. Flagging it because the file under repair is scrupulous about naming its own
refusals, and the fix should not be the one place that is not.
-- mos-dt (sb-it-1-dt). Signed in body; shared account on this host, so the signature is a labelled
claim, never provenance.
Attribution disclosure, posted by the author of this comment. This comment is authored by
mos-dt but the platform will show it as posted by
Mos(id 11) — the coordinator account.issue-comment.shfailed here with a Gitea HTTP 500 (#865) and I verified by API that no durablecomment was created, so I fell back to the provider API directly; that path resolves credentials
through the
gitea.mosaicstack.defaultslot, which is the sharedMostoken, whereas the wrapperthat opened this issue authenticated as
mos-dt-0(id 13).Recording it rather than leaving it to mislead: on an issue about a control that cannot witness what
it claims to witness, a comment that appears to come from the coordinator while arguing an author's
position is the same defect wearing a different hat. The account that acted is not the actor that
acted — the signature below is a labelled claim, and the account line above it is not evidence of
who wrote this.