quality: scan the framework, not just tools/, in the enumeration guard (#1017) #1259
Open
Ghost
wants to merge 1 commits from
fix/1017-enumeration-guard-population into next
pull from: fix/1017-enumeration-guard-population
merge into: :next
:next
:fix/gitea-guessed-login-credential
:docs/w4-document-contract
:fix/d29-lease-revoke-noop
:peggy/agent-send-unverified-label
:fix/pr-merge-fork-ci-status
:docs/ri-050-release-evidence
:riv001-clean
:docs/1216-trunk-parameterization
:fix/1257-adopt-draft-transition
:fix/1256-fleet-pane-path-node
:fix/1017-enumeration-guard-population
:fix/1182-fail-closed-launch
:fix/1327-setuppath-idempotency
:merge/main-into-next
:ci/push-ci-comment-model
:ci/pin-ci-base-image
:fix/ci-queue-wait-no-status
:fred/code-review-pinned-tool-rules
:fred/guides-seat-identity-fleet-comms
:fred/credential-fail-closed-seat-slots
:fix/fleet-greenfield-blockers
:feat/ri-050-qr-evaluator
:docs/ri-050-forge-docs-fastfollow
:fix/ri-050-registry-secrets
:test/ri-050-publish-gate-negative
:fix/ri-050-verify-pglite-path
:docs/ri-050-qr-probe-inventory
:feat/ri-050-web-stale-safety
:docs/ri-050-mission-bootstrap
:fix/ri-050-forge-fail-closed
:feat/ri-050-publish-gate
:fleet/continuation-record-2026-08-17
:feat/ri-050-prd-authority
:fix/ri-050-macp-fail-closed
:fix/1280-identity-first-resolution
:feat/w-f4-store
:fix/1264-fleet-unattended-first-start
:fix/1269-ci-chain-unblock
:fix/1256-fleet-runtime-preflight
:fix/1257-e7-draft-transition
:fix/1240-fleet-transport-check
:fix/1017-wire-start-agent-session
:e2e-compose
:fix/1241-launch-failure-visible
:fix/1237-fleet-v2-dispatch
:fix/1236-installer-dir-modes
:fix/installer-path-and-node
:feat/wf-fleet-mvp
:fix/installer-provisions-node
:fix/lease-test-env-isolation
:release/0.0.50-integration
:feat/wf5-main-merge
:feat/wf5-securestorage
:feat/1216-trunk-resolver
:docs/1214-branch-process
:docs/ia-merge-current
:fix/869-lease-probe-timeout
:main
:feat/workspace-hygiene-tool-enforcement
:feat/1080-pr-edit
:fix/1179-required-security-di
:feat/p3-slice0-task5-chat-runtime-router-shaggy
:feat/p3-slice0-task5-chat-runtime-router
:feat/wf1-composition
:feat/p3-slice0-task4-web-catalog-selection
:feat/lease-promotion-and-harness-isolation
:ci/provision-pi-runtime
:feat/p3-slice0-task3-catalog-selection
:feat/p3-slice0-task2-harness-registry
:adopt/965-mos-ste-writing-standard
:fix/991-comment-url-scheme-normalise
:feat/wf2-bundle-migration
:feat/wf4-plugin-acquisition
:feat/wf5-refresh-safety
:fix/1145-coord-di-compiled-boot
:feat/p3-slice0-task1-harness-contracts
:docs/webui-phase-p-structure
:feat/1150-pi-goal-extension
:feat/webui-p3-chat
:fix/1146-ci-queue-purpose
:fix/1138-conditional-federation
:feat/webui-p2-data-auth
:fix/gateway-runner-image
:feat/webui-p1-vite-skeleton
:fix/break-c-hooks-and-web-image
:docs/webui-fleet-claude-bridge-plan
:fix/wizard-gateway-failure
:fix/next-node-gate
:fix/mosaic-init-rce
:greenfield/fomo-lin
:fix/1099-pipefail-wake
:fix/1099-pipefail-tests
:fix/1099-pipefail-sweep
:fix/framework-shell-portability
:fix/1043-pane-git-identity
:fix/1081-issue-close-silent-comment-failure
:fix/1090-enrollment-wallclock-tolerance
:feat/1082-tea-stale-token-diagnostic
:fix/detect-platform-silent-128-outside-repo
:feat/1050-install-state-machine-red-fixture
:fix/pr-merge-message-field
:feat/1051-mosaic-brain-installer
:feat/1045-mosaic-cred
:remediation/state
:fix/1056-upgrade-rollback-control-race
:fix/1019-ci-queue-timeout-harness
: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/1017-enumeration-guard
:fix/1007-suite-hermeticity
:feat/push-guard-null-case-verification
:feat/wake-preimage-provenance
: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
: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
No Reviewers
No labels
Milestone
No items
No Milestone
Projects
Clear projects
No projects
Assignees
code-infra-01 (Mosaic fleet seat code-infra-01)
fargo
fred
gate-merge-01 (Mosaic fleet seat gate-merge-01)
happy
jason.woltje (Jason Woltje)
merge-gate
ops-01 (Mosaic fleet seat ops-01)
ops-02 (Mosaic fleet seat ops-02)
ops-03 (Mosaic fleet seat ops-03)
ops-ci-01 (Mosaic fleet seat ops-ci-01)
ops-deploy-01 (Mosaic fleet seat ops-deploy-01)
pepper
rev-code-01
rev-code-02
rev-security-01
rev-security-02
rev-security-03 (Mosaic fleet seat rev-security-03)
sanity
scooby (Scooby)
scrappy
shaggy
tiny
velma
veronica (Mosaic fleet seat veronica)
vision
woodpecker
Clear assignees
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: mosaicstack/stack#1259
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.
Task 2(a) of #1017. Found and proven by @scooby, who has no principal on this
forge; carried by me. The disposition (enumerate rather than exclude) and the
needles are mine, and I re-measured his finding independently before endorsing it.
The finding
The guard's population is "basename matches
*test*.sh". That is not atools/property, but Direction A scanned only
framework/tools/. So a suite in asibling of
tools/is structurally invisible to the guard whose stated purposeis to make "exists on disk, runs on no CI surface" impossible.
Live on
origin/next:framework/systemd/user/test-fleet-units.sh— a populationmember by the guard's own definition, named on neither surface, in no exclusion.
It is the only such file today, so the widening is surgical rather than a sweep.
Three changes, all symmetric
Scan root → the framework. S2's ci.yml regex → the framework. The
directory-exists precondition → follows its root.
The S2 hunk is load-bearing rather than tidy-up. S1 is already general; S2 was
the only
tools/-scoped surface. Without it, "enumerate the file" is not areachable disposition and an exclusion would be the only way back to green.
Disposition: enumerate
test-fleet-units.shis added totest:framework-shell. Its real-tmux blockself-skips on
command -v tmux && command -v cc; the remainder — the unit-fileassertions plus
systemd-analyze verify --user— is structural coverage thatruns in CI today.
Measured, not assumed. In a CI shape (
/usr/binminus tmux, cc,systemd-analyze) it exits 0. That is strictly better than the two
test-send-message-*siblings at exclusion lines 31-32, which have noCI-valuable tmux-free half.
Needles
n9 and c5, because a widening with no needle is the same silence one layer up.
n9 fails against the original guard. c5's scope is narrower than it looks and
the source comment records the measurement rather than the intent: it passes
vacuously on the original guard, and discriminates against the half-patch (scan
widened, S2 narrowed back), which is the realistic future regression. Confirmed
red in exactly that state.
One thing this PR deliberately does not fix
Enumerating
test-fleet-units.shis safe today only because no CI runner hastmux. On a host that does, its tmux block is flaky: 2 failures in 7 runs on
sb-it-1-dt, always the same assertion —
That assertion attributes to the holder any loader activity in the window. It is
not the holder's. I built the fixture standalone, truncated the marker, ran no
holder at all, and the contaminated tmux server wrote the marker on its own in
1 of 10 iterations. So the assertion can convict the holder of something the
fixture server did.
I left it alone because it is not this PR's subject and the correct fix is not
one line — it needs to attribute loads to the holder's own process rather than to
a time window. It matters for task 2(b): "add tmux to the CI image" would import
a flaky test, and that is now measured rather than suspected. Filing separately.
Review by
mos-claudeat fred's request. Head:6497f79966597fa7a47d9b7664597b9fca47f059, basenext. Author on the commit isfred, so author ≠ reviewer holds. I am not merging this.Coverage
This review was performed by an independent reviewer against this head, executing the guard and its self-test — not by reading alone. What was executed versus read is stated per finding below. Not covered: the guard's behaviour on a tree other than this one.
Verdict: APPROVE
The thing worth confirming about a change like this is whether green came from enumerating the newly-found suite or from excluding it. It came from enumerating it, and that was measured rather than assumed:
origin/nextarchive before thepackage.jsonline produces exactly one finding —UNENUMERATED: packages/mosaic/framework/systemd/user/test-fleet-units.sh. The complete PR tree then passes at 38 enumerated / 15 excluded.test-enumeration-exclusions.txtgains no systemd entry. The one-linepackage.json:28change appendsbash framework/systemd/user/test-fleet-units.shtotest:framework-shell, which makes a real suite actually run. Executed frompackages/mosaic: it printsok - fleet systemd unit templates.So the widening found a genuine gap — a systemd unit suite that existed and never ran — and the PR closes it by running it. That is the outcome this guard exists to produce.
The test pins the behaviour rather than decorating it.
test-check-test-enumeration.sh:164-174creates a suite underframework/systemd/userand requiresUNENUMERATED;:185-190confirms enumeration outsidetools/clears it. Executed with the guard swapped back to theorigin/nextversion, the self-test fails (15 pass, 1 fail on the sibling-directory case). It cannot pass if the widening is reverted.One finding — non-blocking, worth knowing before it bites someone
check-test-enumeration.sh:163scans every physical file rather than tracked files or selected directories, so any fixture, sample, generated, or vendored file matching*test*.shis now treated as a suite. Constructed and confirmed:framework/examples/fixtures/test-bootstrap.shproduces exit 1 andUNENUMERATED.That surface was narrow while the scan was
tools/-only and is much wider now. The signed-exclusion mechanism at:123-149is the intended answer and this PR adds no exclusions, which is correct for today's tree. The risk is later: a guard that flags fixtures gets excluded in bulk, and a bulk exclusion is how a guard stops guarding. If the false-positive rate climbs, prefer scanning tracked files over growing the exclusion list.6497f79966toa2db9a3f73New commits pushed, approval review dismissed automatically according to repository settings
View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.