1. script/test now uses the conditional verbose rerun pattern. REPO_POLICIES.md: "make test should use the conditional verbose rerun
pattern. Run tests without -v (verbose) first. If tests fail, automatically
rerun with -v to show full output. ... The exit 1 ensures the target always
fails after a rerun — the first run already proved the tests are broken, so the
build must not pass even if a flaky test happens to succeed on the second
attempt." The verbose form of the existing jest --forceExit is added as the test:verbose package script. The 30-second timeout is kept on both runs.
2. build.js no longer shells out to npx.REPO_POLICIES.md: "Use yarn, not npm." npx resolves from the registry when the local binary is
absent, which is an unpinned network fetch mid-build; it is now the explicit node_modules/.bin/tailwindcss path (the bin @tailwindcss/cli provides), with
the paths quoted.
3. make install uses --frozen-lockfile.REPO_POLICIES.md: "Always use
Makefile targets (make fmt, make test, make lint, etc.) instead of
invoking the underlying tools directly. The Makefile is the single source of
truth for how these operations are run." script/bootstrap was already frozen,
so the Makefile shim was the one path that could silently rewrite yarn.lock.
CI is unaffected — the workflow runs script/cibuild -> docker build -> script/bootstrap, which was already yarn install --frozen-lockfile.
4. README Getting Started directs new users to make setup. REPO_POLICIES.md defines setup as "make the repo ready for development after
a fresh clone: runs bootstrap, then install-precommit". Following the old make install + make build block left a fresh clone with no pre-commit hook.
5. Makefile-only targets documented.REPO_POLICIES.md: "The Makefile is
authoritative documentation for how the repo is used. ... A new contributor
should be able to understand the entire development workflow by reading the
Makefile." make install, make hooks, make build, make build-debug, make clean and make dev are now listed in the README Entrypoints section.
Reconciled in both directions: all 16 Makefile targets are now documented, and
all 14 documented script/ entrypoints exist on disk.
6. .dockerignore records why .git is deliberately not excluded — build.js shells out to git rev-parse for build-info stamping and the
Dockerfile runs make build, so excluding it would stamp every extension with commitHash: "unknown".
Deferred: SCRIPT_DIR in script/check, script/precommit, script/setup
Not changed. The issue conditions the fix on it not forking a shared file, and
all three are byte-identical to the canonical upstream templates
(https://git.eeqj.de/sneak/prompts/raw/branch/main/script/{check,precommit,setup},
fetched and diffed during this work — zero difference). They dispatch only to
sibling scripts, each of which cds to the root itself. Fixing it here would
create a local fork of a shared file; it belongs upstream in prompts.
Evidence
Frozen lockfile.package.json was drifted by adding a dependency
(left-pad@^1.3.0) without touching yarn.lock:
$ make install
yarn install v1.22.22
[1/4] Resolving packages...
error Your lockfile needs to be updated, but yarn was run with `--frozen-lockfile`.
make: *** [Makefile:14: install] Error 1
The same drift under the pre-fix bare yarn install absorbed it silently:
package.json and yarn.lock were then restored; git diff on this branch
shows the one intended test:verbose line in package.json and no change to yarn.lock.
Verbose rerun. A deliberately failing test was added to tests/, then
removed:
$ make test
Running tests...
● deliberate failure to demonstrate the verbose rerun
Tests: 1 failed, 143 passed, 144 total
--- Rerunning with --verbose for details ---
✕ deliberate failure to demonstrate the verbose rerun (4 ms)
● deliberate failure to demonstrate the verbose rerun
Tests: 1 failed, 143 passed, 144 total
$ script/test; echo $?
1
The per-case ✕ line appears only in the second run — that is the verbose
output. script/test exits 1, make test exits 2 (make's failed-recipe code).
On success there is no rerun and the target takes 2.8s, well inside the 30s
timeout.
Build.make clean && make build compiles Tailwind through the local binary
(≈ tailwindcss v4.2.1, Done in 225ms) and emits dist/chrome/ and dist/firefox/, each with a 12120-byte src/popup/styles.css; script/verify-build reports 4 bundles verified autistmask-build-debug=off.
script/cibuild (the CI path, run uncached on the changed layers — RUN make check and RUN make build both executed, 6.7s for the build step, not CACHED): exit 0.
make check on the rebased branch head: exit 0, 8 test suites / 149 tests
passed, prettier --check . clean twice (lint + fmt-check), and git status --short empty afterwards, so it modifies no files.
Closes [#166](https://git.eeqj.de/sneak/AutistMask/issues/166).
## Divergences fixed
**1. `script/test` now uses the conditional verbose rerun pattern.**
`REPO_POLICIES.md`: "**`make test` should use the conditional verbose rerun
pattern.** Run tests without `-v` (verbose) first. If tests fail, automatically
rerun with `-v` to show full output. ... The `exit 1` ensures the target always
fails after a rerun — the first run already proved the tests are broken, so the
build must not pass even if a flaky test happens to succeed on the second
attempt." The verbose form of the existing `jest --forceExit` is added as the
`test:verbose` package script. The 30-second `timeout` is kept on both runs.
**2. `build.js` no longer shells out to `npx`.** `REPO_POLICIES.md`: "Use
`yarn`, not `npm`." `npx` resolves from the registry when the local binary is
absent, which is an unpinned network fetch mid-build; it is now the explicit
`node_modules/.bin/tailwindcss` path (the bin `@tailwindcss/cli` provides), with
the paths quoted.
**3. `make install` uses `--frozen-lockfile`.** `REPO_POLICIES.md`: "Always use
Makefile targets (`make fmt`, `make test`, `make lint`, etc.) instead of
invoking the underlying tools directly. The Makefile is the single source of
truth for how these operations are run." `script/bootstrap` was already frozen,
so the Makefile shim was the one path that could silently rewrite `yarn.lock`.
CI is unaffected — the workflow runs `script/cibuild` -> `docker build` ->
`script/bootstrap`, which was already `yarn install --frozen-lockfile`.
**4. README Getting Started directs new users to `make setup`.**
`REPO_POLICIES.md` defines `setup` as "make the repo ready for development after
a fresh clone: runs `bootstrap`, then `install-precommit`". Following the old
`make install` + `make build` block left a fresh clone with no pre-commit hook.
**5. Makefile-only targets documented.** `REPO_POLICIES.md`: "The Makefile is
authoritative documentation for how the repo is used. ... A new contributor
should be able to understand the entire development workflow by reading the
Makefile." `make install`, `make hooks`, `make build`, `make build-debug`,
`make clean` and `make dev` are now listed in the README Entrypoints section.
Reconciled in both directions: all 16 Makefile targets are now documented, and
all 14 documented `script/` entrypoints exist on disk.
**6. `.dockerignore` records why `.git` is deliberately not excluded** —
`build.js` shells out to `git rev-parse` for build-info stamping and the
Dockerfile runs `make build`, so excluding it would stamp every extension with
`commitHash: "unknown"`.
## Deferred: `SCRIPT_DIR` in `script/check`, `script/precommit`, `script/setup`
Not changed. The issue conditions the fix on it not forking a shared file, and
all three are byte-identical to the canonical upstream templates
(`https://git.eeqj.de/sneak/prompts/raw/branch/main/script/{check,precommit,setup}`,
fetched and diffed during this work — zero difference). They dispatch only to
sibling scripts, each of which `cd`s to the root itself. Fixing it here would
create a local fork of a shared file; it belongs upstream in `prompts`.
## Evidence
**Frozen lockfile.** `package.json` was drifted by adding a dependency
(`left-pad@^1.3.0`) without touching `yarn.lock`:
```
$ make install
yarn install v1.22.22
[1/4] Resolving packages...
error Your lockfile needs to be updated, but yarn was run with `--frozen-lockfile`.
make: *** [Makefile:14: install] Error 1
```
The same drift under the pre-fix bare `yarn install` absorbed it silently:
```
$ yarn install
success Saved lockfile.
Done in 1.53s.
$ git diff --stat yarn.lock
yarn.lock | 5 +++++
```
`package.json` and `yarn.lock` were then restored; `git diff` on this branch
shows the one intended `test:verbose` line in `package.json` and no change to
`yarn.lock`.
**Verbose rerun.** A deliberately failing test was added to `tests/`, then
removed:
```
$ make test
Running tests...
● deliberate failure to demonstrate the verbose rerun
Tests: 1 failed, 143 passed, 144 total
--- Rerunning with --verbose for details ---
✕ deliberate failure to demonstrate the verbose rerun (4 ms)
● deliberate failure to demonstrate the verbose rerun
Tests: 1 failed, 143 passed, 144 total
$ script/test; echo $?
1
```
The per-case `✕` line appears only in the second run — that is the verbose
output. `script/test` exits 1, `make test` exits 2 (make's failed-recipe code).
On success there is no rerun and the target takes 2.8s, well inside the 30s
timeout.
**Build.** `make clean && make build` compiles Tailwind through the local binary
(`≈ tailwindcss v4.2.1`, `Done in 225ms`) and emits `dist/chrome/` and
`dist/firefox/`, each with a 12120-byte `src/popup/styles.css`;
`script/verify-build` reports 4 bundles verified `autistmask-build-debug=off`.
**`script/cibuild`** (the CI path, run uncached on the changed layers — `RUN
make check` and `RUN make build` both executed, 6.7s for the build step, not
`CACHED`): exit 0.
**`make check`** on the rebased branch head: exit 0, 8 test suites / 149 tests
passed, `prettier --check .` clean twice (lint + fmt-check), and
`git status --short` empty afterwards, so it modifies no files.
- script/test runs the suite quietly, then reruns it with --verbose on
failure and always exits 1 (REPO_POLICIES.md conditional verbose rerun
pattern). New package.json script test:verbose is the -v form of the
existing jest --forceExit invocation.
- build.js calls node_modules/.bin/tailwindcss instead of npx, which
would fetch from the registry unpinned if the binary were absent.
- make install uses --frozen-lockfile, so a stale yarn.lock fails the
target instead of being silently rewritten.
- README Getting Started uses make setup (which also installs the
pre-commit hook); the Makefile-only targets (install, hooks, build,
build-debug, clean, dev) are now documented in Entrypoints.
- .dockerignore records why .git is deliberately not excluded.
Not mergeable into next.TODO.md conflicts: this branch's merge-base is b882cede, and next has since landed 19cb1ca (#163), which added its own entry at the top of # Completed Steps. git merge origin/next → CONFLICT (content): Merge conflict in TODO.md. Rebase onto origin/next and keep both bullets.
Everything else in the change verified and passes: all DoD items of #166 satisfied against the policy text; single commit titled (closes #166); base next; no attribution trailers.
Disclosures, none blocking:
CI on d9808df is pending / "Waiting to run" — queued, never executed, not red. I ran script/cibuild locally instead: exit 0 with RUN make check (24.7s, 149 tests actually executed) and RUN make build (10.8s, Tailwind v4.2.1 via the new local bin path) both uncached, proving the node_modules/.bin/tailwindcss path resolves inside the container too. The rebase will re-trigger CI regardless.
Failing-test probe (the item that mattered most): I added a deliberately failing test to tests/. script/test exits 1, make check exits 2, the rerun banner appears exactly once, verbose per-case output is present only in the second run, and script/check aborts before lint/fmt-check. The unconditional exit 1 after || true correctly prevents a flaky second-run pass from turning the build green. Test removed; tree left clean.
Timeout probe: a hanging suite exits 1 in 60s, not misreported as a pass. Worst case is now two 30s windows rather than one; the success path is 2s, well inside the policy's 20s. Matches the canonical Go pattern, which likewise applies the timeout per run. Noting, not objecting.
SCRIPT_DIR deferral is legitimate, independently verified: script/check, script/precommit, script/setup are byte-identical to prompts/script/{check,precommit,setup} (fetched and diffed here, zero difference).
--frozen-lockfile confirmed on every install path — Makefile:14, script/bootstrap:124,126, Dockerfile via script/bootstrap, and CI via script/cibuild → docker build → script/bootstrap. No bare yarn install remains anywhere.
README Entrypoints reconciles in both directions: 14/14 script/ files documented and existing, 16/16 Makefile targets documented.
make setup from this fresh clone, then make clean && make build: exit 0, both dist/chrome/ and dist/firefox/ emit a 12120-byte src/popup/styles.css, verify-build reports 4 bundles autistmask-build-debug=off. make check exit 0 in 13s, git status --short empty afterwards.
FAIL — `needs-rebase`.
**Not mergeable into `next`.** `TODO.md` conflicts: this branch's merge-base is `b882cede`, and `next` has since landed `19cb1ca` ([#163](https://git.eeqj.de/sneak/AutistMask/issues/163)), which added its own entry at the top of `# Completed Steps`. `git merge origin/next` → `CONFLICT (content): Merge conflict in TODO.md`. Rebase onto `origin/next` and keep both bullets.
Everything else in the change verified and passes: all DoD items of [#166](https://git.eeqj.de/sneak/AutistMask/issues/166) satisfied against the policy text; single commit titled ` (closes #166)`; base `next`; no attribution trailers.
Disclosures, none blocking:
- CI on `d9808df` is `pending` / "Waiting to run" — queued, never executed, not red. I ran `script/cibuild` locally instead: exit 0 with `RUN make check` (24.7s, 149 tests actually executed) and `RUN make build` (10.8s, Tailwind v4.2.1 via the new local bin path) both uncached, proving the `node_modules/.bin/tailwindcss` path resolves inside the container too. The rebase will re-trigger CI regardless.
- Failing-test probe (the item that mattered most): I added a deliberately failing test to `tests/`. `script/test` exits **1**, `make check` exits **2**, the rerun banner appears exactly once, verbose per-case output is present only in the second run, and `script/check` aborts before `lint`/`fmt-check`. The unconditional `exit 1` after `|| true` correctly prevents a flaky second-run pass from turning the build green. Test removed; tree left clean.
- Timeout probe: a hanging suite exits **1** in 60s, not misreported as a pass. Worst case is now two 30s windows rather than one; the success path is 2s, well inside the policy's 20s. Matches the canonical Go pattern, which likewise applies the timeout per run. Noting, not objecting.
- `SCRIPT_DIR` deferral is legitimate, independently verified: `script/check`, `script/precommit`, `script/setup` are byte-identical to `prompts/script/{check,precommit,setup}` (fetched and diffed here, zero difference).
- `--frozen-lockfile` confirmed on every install path — `Makefile:14`, `script/bootstrap:124,126`, Dockerfile via `script/bootstrap`, and CI via `script/cibuild` → `docker build` → `script/bootstrap`. No bare `yarn install` remains anywhere.
- README Entrypoints reconciles in both directions: 14/14 `script/` files documented and existing, 16/16 Makefile targets documented.
- `make setup` from this fresh clone, then `make clean && make build`: exit 0, both `dist/chrome/` and `dist/firefox/` emit a 12120-byte `src/popup/styles.css`, `verify-build` reports 4 bundles `autistmask-build-debug=off`. `make check` exit 0 in 13s, `git status --short` empty afterwards.
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.
Closes #166.
Divergences fixed
1.
script/testnow uses the conditional verbose rerun pattern.REPO_POLICIES.md: "make testshould use the conditional verbose rerunpattern. Run tests without
-v(verbose) first. If tests fail, automaticallyrerun with
-vto show full output. ... Theexit 1ensures the target alwaysfails after a rerun — the first run already proved the tests are broken, so the
build must not pass even if a flaky test happens to succeed on the second
attempt." The verbose form of the existing
jest --forceExitis added as thetest:verbosepackage script. The 30-secondtimeoutis kept on both runs.2.
build.jsno longer shells out tonpx.REPO_POLICIES.md: "Useyarn, notnpm."npxresolves from the registry when the local binary isabsent, which is an unpinned network fetch mid-build; it is now the explicit
node_modules/.bin/tailwindcsspath (the bin@tailwindcss/cliprovides), withthe paths quoted.
3.
make installuses--frozen-lockfile.REPO_POLICIES.md: "Always useMakefile targets (
make fmt,make test,make lint, etc.) instead ofinvoking the underlying tools directly. The Makefile is the single source of
truth for how these operations are run."
script/bootstrapwas already frozen,so the Makefile shim was the one path that could silently rewrite
yarn.lock.CI is unaffected — the workflow runs
script/cibuild->docker build->script/bootstrap, which was alreadyyarn install --frozen-lockfile.4. README Getting Started directs new users to
make setup.REPO_POLICIES.mddefinessetupas "make the repo ready for development aftera fresh clone: runs
bootstrap, theninstall-precommit". Following the oldmake install+make buildblock left a fresh clone with no pre-commit hook.5. Makefile-only targets documented.
REPO_POLICIES.md: "The Makefile isauthoritative documentation for how the repo is used. ... A new contributor
should be able to understand the entire development workflow by reading the
Makefile."
make install,make hooks,make build,make build-debug,make cleanandmake devare now listed in the README Entrypoints section.Reconciled in both directions: all 16 Makefile targets are now documented, and
all 14 documented
script/entrypoints exist on disk.6.
.dockerignorerecords why.gitis deliberately not excluded —build.jsshells out togit rev-parsefor build-info stamping and theDockerfile runs
make build, so excluding it would stamp every extension withcommitHash: "unknown".Deferred:
SCRIPT_DIRinscript/check,script/precommit,script/setupNot changed. The issue conditions the fix on it not forking a shared file, and
all three are byte-identical to the canonical upstream templates
(
https://git.eeqj.de/sneak/prompts/raw/branch/main/script/{check,precommit,setup},fetched and diffed during this work — zero difference). They dispatch only to
sibling scripts, each of which
cds to the root itself. Fixing it here wouldcreate a local fork of a shared file; it belongs upstream in
prompts.Evidence
Frozen lockfile.
package.jsonwas drifted by adding a dependency(
left-pad@^1.3.0) without touchingyarn.lock:The same drift under the pre-fix bare
yarn installabsorbed it silently:package.jsonandyarn.lockwere then restored;git diffon this branchshows the one intended
test:verboseline inpackage.jsonand no change toyarn.lock.Verbose rerun. A deliberately failing test was added to
tests/, thenremoved:
The per-case
✕line appears only in the second run — that is the verboseoutput.
script/testexits 1,make testexits 2 (make's failed-recipe code).On success there is no rerun and the target takes 2.8s, well inside the 30s
timeout.
Build.
make clean && make buildcompiles Tailwind through the local binary(
≈ tailwindcss v4.2.1,Done in 225ms) and emitsdist/chrome/anddist/firefox/, each with a 12120-bytesrc/popup/styles.css;script/verify-buildreports 4 bundles verifiedautistmask-build-debug=off.script/cibuild(the CI path, run uncached on the changed layers —RUN make checkandRUN make buildboth executed, 6.7s for the build step, notCACHED): exit 0.make checkon the rebased branch head: exit 0, 8 test suites / 149 testspassed,
prettier --check .clean twice (lint + fmt-check), andgit status --shortempty afterwards, so it modifies no files.FAIL —
needs-rebase.Not mergeable into
next.TODO.mdconflicts: this branch's merge-base isb882cede, andnexthas since landed19cb1ca(#163), which added its own entry at the top of# Completed Steps.git merge origin/next→CONFLICT (content): Merge conflict in TODO.md. Rebase ontoorigin/nextand keep both bullets.Everything else in the change verified and passes: all DoD items of #166 satisfied against the policy text; single commit titled
(closes #166); basenext; no attribution trailers.Disclosures, none blocking:
d9808dfispending/ "Waiting to run" — queued, never executed, not red. I ranscript/cibuildlocally instead: exit 0 withRUN make check(24.7s, 149 tests actually executed) andRUN make build(10.8s, Tailwind v4.2.1 via the new local bin path) both uncached, proving thenode_modules/.bin/tailwindcsspath resolves inside the container too. The rebase will re-trigger CI regardless.tests/.script/testexits 1,make checkexits 2, the rerun banner appears exactly once, verbose per-case output is present only in the second run, andscript/checkaborts beforelint/fmt-check. The unconditionalexit 1after|| truecorrectly prevents a flaky second-run pass from turning the build green. Test removed; tree left clean.SCRIPT_DIRdeferral is legitimate, independently verified:script/check,script/precommit,script/setupare byte-identical toprompts/script/{check,precommit,setup}(fetched and diffed here, zero difference).--frozen-lockfileconfirmed on every install path —Makefile:14,script/bootstrap:124,126, Dockerfile viascript/bootstrap, and CI viascript/cibuild→docker build→script/bootstrap. No bareyarn installremains anywhere.script/files documented and existing, 16/16 Makefile targets documented.make setupfrom this fresh clone, thenmake clean && make build: exit 0, bothdist/chrome/anddist/firefox/emit a 12120-bytesrc/popup/styles.css,verify-buildreports 4 bundlesautistmask-build-debug=off.make checkexit 0 in 13s,git status --shortempty afterwards.d9808df919to9e209e27bd9e209e27bdtod749ed9212d749ed9212toc631cc7626