Lane 2b review — encoding, alignment, D21 and a licence way out (#659) #683

Closed
claude-bot wants to merge 0 commits from redesign/lane2b-review into main
Collaborator

Refs #659. Owner review of lane 2b — five things.

The page was double-encoded (my fault)

I inserted the closing section with PowerShell Get-Content -Raw + Set-Content -Encoding utf8. PS 5.1 reads a BOM-less UTF-8 file as the Windows ANSI codepage, so every non-ASCII character came back one layer too deep — Pathfinder 2e · 214 creatures, an administrator’s — plus a BOM on the front.

Repaired by re-encoding only the runs that are genuinely double-encoded. A mojibake run re-encodes to valid UTF-8, because that is precisely what it is; a correct run does not — a lone é becomes the single byte 0xE9, which is not a valid UTF-8 sequence on its own — so it fails the test and is left untouched. That property matters here, because the file was mixed: the edits I made after the bad write were correct, and a blanket transform would have corrupted them. My first two attempts at a blanket repair both aborted on their own guard rails, which is how I found that out.

Guarded by a test, which CI now runs: every prototype file must be valid UTF-8, carry no BOM, and contain none of the mojibake markers.

Settings → General did not line up

.form__two stretched its cells, and each cell is itself a grid of label/field/hint with auto rows — so the spare height was distributed between those rows, and the moment one side's hint wrapped to two lines the other side's field slid down. align-items: start. This fixes lane 2's General too, which has the same pair.

Same class of fault in the new stat-conversion list: the type chips differ in width, so on a flex row every title started at a different x. Now a grid with a fixed first column.

D21 — settled

The Contents opens into the nine. The back bar is kept for the phone, where there is no rail on screen to go back through. Recorded in the intro and on CAMP-9; the page no longer presents it as a choice.

A pack with no licence is no longer a dead end

New row IS-315. export_service.decide() withholds anything whose licence is not redistributable and nothing can add one afterwards — which lands hardest on exactly the wrong pack: the house rules a group wrote themselves, and therefore certainly own, are the ones the product refuses to give back. The block now carries the way past it, written as a question about use rather than a licence picker ("We wrote it" is the common answer and is not a licence anyone has heard of), and a licence a GM sets is marked as theirs rather than the file's.

Foundry copy corrected

"Most groups do not run Foundry" was wrong — the integration is unbuilt because it is large, not because it is unwanted. The empty state now reads as an invitation rather than as a feature that is missing.

Also

The CAMP-11 rename was labelled D21 in headers.md, which is the navigation decision's number. It gets its own, D26.

Verification

  • Catalogue rebuilt: 1,584 rows on 102 surfaces.
  • 86 tests pass (85 + the new encoding guard).
  • Re-rendered and read: the mojibake is gone, the General pair aligns, the conversion list aligns, and the licence flow reads correctly.

🤖 Generated with Claude Code

Refs #659. Owner review of lane 2b — five things. ## The page was double-encoded (my fault) I inserted the closing section with PowerShell `Get-Content -Raw` + `Set-Content -Encoding utf8`. PS 5.1 reads a BOM-less UTF-8 file as the Windows ANSI codepage, so every non-ASCII character came back one layer too deep — `Pathfinder 2e · 214 creatures`, `an administrator’s` — plus a BOM on the front. Repaired by re-encoding **only the runs that are genuinely double-encoded**. A mojibake run re-encodes to valid UTF-8, because that is precisely what it is; a correct run does not — a lone `é` becomes the single byte `0xE9`, which is not a valid UTF-8 sequence on its own — so it fails the test and is left untouched. That property matters here, because the file was *mixed*: the edits I made after the bad write were correct, and a blanket transform would have corrupted them. My first two attempts at a blanket repair both aborted on their own guard rails, which is how I found that out. **Guarded by a test**, which CI now runs: every prototype file must be valid UTF-8, carry no BOM, and contain none of the mojibake markers. ## Settings → General did not line up `.form__two` stretched its cells, and each cell is itself a grid of label/field/hint with auto rows — so the spare height was distributed *between those rows*, and the moment one side's hint wrapped to two lines the other side's field slid down. `align-items: start`. **This fixes lane 2's General too**, which has the same pair. Same class of fault in the new stat-conversion list: the type chips differ in width, so on a flex row every title started at a different x. Now a grid with a fixed first column. ## D21 — settled **The Contents opens into the nine.** The back bar is kept for the phone, where there is no rail on screen to go back through. Recorded in the intro and on CAMP-9; the page no longer presents it as a choice. ## A pack with no licence is no longer a dead end New row `IS-315`. `export_service.decide()` withholds anything whose licence is not redistributable and nothing can add one afterwards — which lands hardest on exactly the wrong pack: the house rules a group wrote themselves, and therefore certainly own, are the ones the product refuses to give back. The block now carries the way past it, written as a question about *use* rather than a licence picker ("We wrote it" is the common answer and is not a licence anyone has heard of), and a licence a GM sets is marked as **theirs** rather than the file's. ## Foundry copy corrected "Most groups do not run Foundry" was wrong — the integration is unbuilt because it is large, not because it is unwanted. The empty state now reads as an invitation rather than as a feature that is missing. ## Also The CAMP-11 rename was labelled **D21** in `headers.md`, which is the navigation decision's number. It gets its own, **D26**. ## Verification - Catalogue rebuilt: **1,584 rows on 102 surfaces**. - **86 tests pass** (85 + the new encoding guard). - Re-rendered and read: the mojibake is gone, the General pair aligns, the conversion list aligns, and the licence flow reads correctly. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
fix(feedback-site): lane 2b review — encoding, alignment, and D21 (#659)
All checks were successful
CI / Docker image build (pull_request) Successful in 40s
CI / Bot/backend version sync (pull_request) Successful in 56s
CI / Backend lint (ruff) (pull_request) Successful in 59s
CI / Summarisation accuracy eval harness (stub provider) (pull_request) Successful in 1m1s
CI / Feedback site tests (pull_request) Successful in 1m12s
CI / Frontend tests, audit, and build (pull_request) Successful in 2m29s
CI / Bot tests and audit (pull_request) Successful in 2m32s
CI / Backend migration, tests, and audit (pull_request) Successful in 8m37s
CI / Synthetic session harness (no GPU, no LLM) (pull_request) Successful in 21m28s
6060fe04f2
Owner review of lane 2b. Five things.

**The page was double-encoded.** I inserted the closing section with
PowerShell Get-Content -Raw + Set-Content -Encoding utf8; PS 5.1 reads a
BOM-less UTF-8 file as the Windows ANSI codepage, so every non-ASCII
character came back one layer too deep -- "Pathfinder 2e · 214 creatures",
"an administrator’s" -- plus a BOM on the front.

Repaired by re-encoding only the runs that are genuinely double-encoded: a
mojibake run re-encodes to valid UTF-8, because that is what it is, while a
correct run does not (a lone e-acute becomes the single byte 0xE9, which is
not a valid UTF-8 sequence on its own) and is left untouched. That test
matters here because the file was mixed -- edits made after the bad write
were correct, and a blanket transform would have corrupted them.

Guarded by a test, which CI now runs: every prototype file must be valid
UTF-8, carry no BOM, and contain none of the mojibake markers.

**Settings -> General did not line up.** .form__two stretched its cells, and
each cell is itself a grid of label/field/hint with auto rows, so the spare
height was distributed between those rows -- the moment one side's hint
wrapped to two lines, the other side's field slid down. align-items: start.
This fixes lane 2's General too, which had the same pair.

Same class of fault in the new stat-conversion list: the type chips differ
in width, so on a flex row every title started at a different place. Now a
grid with a fixed first column.

**D21 is settled: the Contents opens into the nine.** The back bar is kept
for the phone, where there is no rail on screen to go back through. Recorded
in the intro and on CAMP-9.

**A pack with no licence is no longer a dead end** (IS-315, new row). Today
export_service.decide() withholds anything whose licence is not
redistributable and nothing can add one afterwards -- which lands hardest on
exactly the wrong pack, the house rules a group wrote themselves and
therefore certainly own. The block now carries the way past it, and a licence
a GM sets is marked as theirs rather than the file's.

**Foundry copy corrected.** "Most groups do not run Foundry" was wrong; the
integration is unbuilt because it is large, not because it is unwanted.

Also: the CAMP-11 rename was labelled D21 in headers.md, which is the
navigation decision. It gets its own number, D26.

Catalogue rebuilt: 1,584 rows on 102 surfaces. 86 tests pass.

Refs #659.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Author
Collaborator

Merged to main in b2e4675, and deployed. Closing by hand — merged by pushing the merge commit rather than through the API, which does not auto-close the PR.

Verified on the live page afterwards: no mojibake, the General field pair aligns, and the licence flow and settled D21 copy are both serving.

Merged to `main` in b2e4675, and deployed. Closing by hand — merged by pushing the merge commit rather than through the API, which does not auto-close the PR. Verified on the live page afterwards: no mojibake, the General field pair aligns, and the licence flow and settled D21 copy are both serving.
claude-bot closed this pull request 2026-09-17 21:22:11 +00:00
All checks were successful
CI / Docker image build (pull_request) Successful in 40s
Required
Details
CI / Bot/backend version sync (pull_request) Successful in 56s
Required
Details
CI / Backend lint (ruff) (pull_request) Successful in 59s
Required
Details
CI / Summarisation accuracy eval harness (stub provider) (pull_request) Successful in 1m1s
Required
Details
CI / Feedback site tests (pull_request) Successful in 1m12s
Required
Details
CI / Frontend tests, audit, and build (pull_request) Successful in 2m29s
Required
Details
CI / Bot tests and audit (pull_request) Successful in 2m32s
Required
Details
CI / Backend migration, tests, and audit (pull_request) Successful in 8m37s
Required
Details
CI / Synthetic session harness (no GPU, no LLM) (pull_request) Successful in 21m28s
Required
Details

Pull request closed

Sign in to join this conversation.
No description provided.