Skip to content

Commit e0f4c13

Browse files
committed
Fill in the change log hash for the stage builder fixes
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent 0282f2c commit e0f4c13

1 file changed

Lines changed: 1 addition & 1 deletion

File tree

docs/changelog.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,7 @@ zero across these commits; several were pre-existing bugs the old markup had bee
365365
| `dd2ffba7b` | **Rollback #9, and the recovery tool could only see eleven of the thirteen files it put back.** Disk went to `548db78f6` again — 551 commits back, **0 differing paths**, so the restore was lossless and took a minute. The hour after it was worth more. `public/product_drive_participants.csv` and `public/vendors.csv` were on disk, absent from `HEAD`, and **in no `git status` output**: `.gitignore` gained `/public/*.csv` at `db64bbec9`, and **a rollback restores an old tree without consulting the ignore rules of the tree it overwrites**. The same file shadowed a route after rollback #8 and failed a CSV spec; the change log blamed a policy — "debris `workspace-restore` deliberately leaves alone" — where the truth was that the tool never saw it. That row and the decision-log passage are corrected in place rather than quietly fixed. It would have missed it twice over: the predicate was `git log --oneline -1 -- <path>`, and history simplification reports **0 commits** for that path. **Two wrong queries, both measured.** `--full-history` is required — the default prunes a file whose blob is plainly in the ancestor. And `--diff-filter=D`, which *sounds* like the definition of resurrected, **misses everything a merge removed**: over the whole history it yielded 7,815 paths, intersecting the disk to exactly one — the false positive — and none of the three real files. The result inverted. **The predicate that holds is content**: the bytes on disk are a version git once held *at that path*. It separates a reverted file from a runtime artifact squatting on a deleted path (`spec/example_failures.txt` has history *and* a deleting commit; rspec rewrites it every run), and matching bytes is the licence to delete, because git can give the file back. **Making it cheap took a wrong turn worth recording**: running the content test on everything took **156.7s** and timed `new_work` out, because Propshaft's digests in `public/assets/` are byte-identical to their sources so all 163 passed a "does git know this blob" filter and each cost a full-history walk. One command — `git log --full-history --name-only --format=`, 10,550 paths in 0.95s — cuts 212 candidates to **4** and the scan to **5.8s**. Ignored directories are expanded (`--ignored=matching` collapses `public/assets/`, which Rails serves before any route) under a **500-file bound**, `tmp/` holding 36,127; both scripts print what they skipped, because an unscanned directory nobody mentions is the same blind spot one level up. **Controls both ways**: before, `resurrected`=1 with both CSVs unseen; after, =3 with `example_failures.txt` and `tailwind.css` correctly rejected and `workspace-restore --yes` deleting all three end to end. The rollback count was stale in three places — `CLAUDE.md` said five, `skill-proposal-v2.md` and a skill reference said six — all now nine. `session-durability` gains both rules. rubocop clean; page-audit 0; `state.rb --check` up to date. |
366366
| `ed2ea85b0` | **`build-stage.rb` composes stage 1's Gemfile instead of taking it, which is what the fourth correction actually requires.** The refusal added the commit before was right to stop the build; it left the fix as prose. `main` still carries `gem 'bootstrap', '~> 5.2'` — single-quoted, which is why the first grep for it read 0 — along with `sass-rails` and `sprockets`, so **stage 1's Gemfile is main's plus one line**, `gem "tailwindcss-rails", "~> 4.6"`, and `cda053539`'s copy is not needed at all. `Gemfile` and `Gemfile.lock` leave the stage's `paths`; a `gems:` key replaces them; the build step appends the line to main's Gemfile, runs `bundle install`, and **prints the resolved Rails version beside main's** so a silent downgrade cannot happen twice. It also prints the `db:test:prepare` step, the other half of that 878-failure run. **The marker check had to move with it**: it read `#{source}:Gemfile`, and with the Gemfile no longer taken from the source that is a file the stage does not use. A `stage_content` resolver now answers "what will this stage's copy say" — composed where composed, source where taken — so the propshaft-absent and sprockets/sass-rails/bootstrap-present rules are checked against the Gemfile that will exist. Stage 1 `--check`: 54 files, markers clean, no stale shared files. **The hash on the row above was wrong for one commit**: the row went in still saying `TBD` and the fill step then claimed the next commit's hash. |
367367
| `539422c6d` | **Stage 1 assembled, run, and the suite found that its file list was a guess: 150 failures from five files nobody had listed.** It built, booted, and then failed with `Sprockets::Rails::Helper::AssetNotPrecompiledError` on `controllers/csv_download_controller.js` — an asset that is on `main`, is declared in `main`'s `manifest.js`, and has nothing to do with the design system. **The control made it tractable in minutes**: the same example passes on pristine `main`, so the stage caused it; asking Sprockets directly gave `manifest.js found: false` against `true` with 68 links on main, and one extra load path — `app/assets/tailwind`. Tailwind v4 source uses `@import "tailwindcss"`, Sprockets cannot parse it, **the whole manifest dies and every asset then reports as not precompiled**, so the error names whichever one the layout asked for first. `cda053539` had already solved this in `config/initializers/assets.rb`, with a comment saying Sprockets must serve the build and never the source — **and stage 1's paths listed no initializers at all.** Five files were missing: that initializer, `simple_form_essentials.rb`, `config.assets.css_compressor = nil` from `config/application.rb`, and two specs — `asset_resolution_spec.rb`, which pins which `application.css` wins and is the guard for precisely this, and `essentials_shell_spec.rb`. **Three rules, all now enforced by the builder rather than written down.** *A stage carries its own specs* — stage 1 listed none, and the spec that would have caught this was in the source commit, unlisted. *Additive by default, every overwrite named* — the stage silently replaced `confirmation_controller.js` and `donations_modal_controller.js`, both rewritten at `cda053539` from Bootstrap's modal to the native `<dialog>`; stage 1 migrates no views, so main's `<div class="modal">` would have reached `showModal()`, which is not a function on a div. `overwrite:` is an allowlist now and anything else is reverted and reported. *Some files are neither taken nor one-line composed* — `config/application.rb` at `cda053539` also switches the Devise layouts to `essentials_auth`, a later stage, so it is an `insert:` of anchor plus text. **Two environment traps** joined the checklist: main's lock omits `aarch64-linux` so `tailwindcss-ruby` has no executable (the builder adds the local platform), and **Sprockets caches its manifest in `tmp/cache` across branch switches**. Also found: `bin/rails` cannot run *any* rake task on this mount — it is case-insensitive, `File.exist?("rakefile")` answers true, and Rake loads the lowercase spelling and fails; `bundle exec rake -f Rakefile` works. Stage 1 `--check` now: 58 files. |
368-
| `TBD` | **Two fixes to the stage builder, both from watching it run.** The additive check reverted the script's *own* composition: its allowlist was only `overwrite:`, so the first run undid the `.gitignore` entry the `ignore:` step had written a moment earlier and the 120KB Tailwind build came back as an untracked artifact. The allowlist now includes what the script composed — the `insert:` targets and `.gitignore`. **And the builder commits the stage.** A stage left staged-but-uncommitted is a trap that has now sprung twice: the next `git checkout design` is *refused*, `-q` swallows the message, and the commit intended for `design` lands on the stage branch instead — the first time it looked as though `build-stage.rb` had vanished, the second time a builder fix was committed onto stage 1 under the wrong message. Both times `git checkout` had told the truth and nothing had read it. A built stage is meant to be a reviewable commit anyway, and a clean tree makes switching away work. Verified on the rebuild: 2 controllers reverted, `.gitignore` kept. |
368+
| `0282f2c71` | **Two fixes to the stage builder, both from watching it run.** The additive check reverted the script's *own* composition: its allowlist was only `overwrite:`, so the first run undid the `.gitignore` entry the `ignore:` step had written a moment earlier and the 120KB Tailwind build came back as an untracked artifact. The allowlist now includes what the script composed — the `insert:` targets and `.gitignore`. **And the builder commits the stage.** A stage left staged-but-uncommitted is a trap that has now sprung twice: the next `git checkout design` is *refused*, `-q` swallows the message, and the commit intended for `design` lands on the stage branch instead — the first time it looked as though `build-stage.rb` had vanished, the second time a builder fix was committed onto stage 1 under the wrong message. Both times `git checkout` had told the truth and nothing had read it. A built stage is meant to be a reviewable commit anyway, and a clean tree makes switching away work. Verified on the rebuild: 2 controllers reverted, `.gitignore` kept. |
369369

370370

371371

0 commit comments

Comments
 (0)