d571abbd8a1f4f340f76e85264440097de8552f0
8 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
9e37213cd4 |
fix(docs): re-record the four casts from a script, with no shell to leak
improvise-2oxt. All four casts under docs/casts/ opened and closed on `(0) Mac:<hostname> ~gf/u/edwlan/improvise` — a real hostname and home directory on what improvise-kh8 made the site root — and `formulas.cast` and `import.cast` showed that prompt as their visible OPENING frame. drill.cast also predated the records columns entirely, showing a single `Value` column where the current build draws a column per measure plus `+cat` and `+`. The repair is structural, not careful. `docs/record-casts.py` drives `improvise` on a pty it owns and writes asciicast v2 itself, so `improvise` is the pty's ONLY child and there is no shell for a prompt to leak from — nothing to remember to clean, and nothing that comes back when somebody re-records on another machine. Three other things stopped being accidents with it: the geometry is an input (120x37, the numbers docs/index.html already spelled, so they did not change), the pacing is a per-step table, and the header carries no `env` (which held $SHELL) and no `timestamp` (the recording machine's clock). Two decisions that each cost a re-record. No `:q` is typed at the end: the player loops, so the last frame is also the frame before the first, and a minibuffer reading `:q` is what it would show — the process is signalled instead. And each scenario had to be ARRANGED so the thing it names is visible: the drill cast drilled into a cell with no records behind it, and the pivot cast pressed `c` on a category already on the column axis. Both recorded cleanly and demonstrated nothing — true frames about the wrong thing — and neither was visible from the keystroke list. That is the method worth keeping: a cast can be replayed through a small ANSI reconstruction and READ AS TEXT, so "what does frame N show" has an answer rather than a guess. It is how the `+cat`/`+` columns in the new drill.cast were confirmed present, and how both dud scenarios were caught. The guard is `landing.spec.js`, asserted over the cast FILES: no header carries `env` or `timestamp`, the geometry is the one the page configures, and no chunk contains an OSC window-title sequence — the leak's signature, emitted by a shell once per prompt with the cwd in it and by `improvise` never. Asserted over the file rather than the rendering because a player draws a prompt as ordinary text, so a screenshot assertion would have to know what the hostname had been. BOTH clauses were injected separately, because the `env` one would otherwise mask the OSC one: the old cast fails on `env`, and the old cast with `env` stripped fails on the title sequence. docs/index.html loses the `p.dated` note admitting the drill cast was out of date, which is now false. Tests: 33 harness + 3 skipped (was 28 + 3). Rust and node unchanged. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FC2jVn8Au7E9JPkw6bwXXH |
||
|
|
9421eb207c |
fix(docs): the landing page's casts are legible on a phone
improvise-o31u. On a 390px viewport all four players computed a terminal font size of 4.83258px — reproduced to five digits before the fix. The player DERIVES its font size from the width it is given, and 120 columns into the ~356px inside the page's gutters gives about 3px per character. Since improvise-kh8 this page is the SITE ROOT, so that is the first thing a phone visitor sees. Under `max-width: 900px` the player is allowed to overflow INSIDE `.player` (`overflow-x: auto`, an 880px floor on its child) rather than being squeezed to fit. Measured after: 11.9457px, matching PR #47's reverted measurement. The instrument is the finding and is worth more than the CSS. `getBoundingClientRect` reports a height for a `content-visibility`-hidden child and heading text overflows its box without widening it, so neither "the element is present" nor a box measurement can see this. The COMPUTED FONT SIZE is what a reader sees, so that is what is asserted. Two guards on the trade this fix must not make: the document's own `scrollWidth - clientWidth` stays 0 — a page that scrolls sideways on a phone is worse than one unreadable section — and `#cast-pivot` must be the thing that scrolls, which separates "contained the overflow" from "removed it by shrinking something else". The desktop arm is not ceremony either: the same query written without a `max-width` bound, or with the floor on `.player` rather than its child, changes 1280px too. Tests: 4 landing tests (was 2). Rust and node unchanged. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FC2jVn8Au7E9JPkw6bwXXH |
||
|
|
f1011d7f6f |
feat(docs): publish the context/ prose as a site folded into Pages
The landing page is the site root and the app is /app/; the prose now sits at /docs/, assembled by the same web/assemble.sh the Pages job and the browser harness both run, so what ships and what is tested are one tree. Published: design-notes, design-principles, repo-map, the three ADRs, the seven context/code/ arguments, and the 501 test-evidence entries as their own clearly-labelled section. Not published: context/plan.md, which is an agent prompt about a launch rather than a description of the program, and context/cloud-agents.md, which is addressed to nobody who visits a website. Neither is referenced by a published document outside a code fence, so leaving them out dangles nothing. The reasoning is context/code/doc-site.md, which is itself published. Two things the corpus needed that a generator would not have given it. The ~190 improvise-xxxx citations resolve to a generated ticket index built from the already-public .beads/issues.jsonl rather than to an invented URL that would 404; an id the export does not yet carry stays plain text. And a code span that is wholly a repo path links to GitHub at the assembled ref, but only when the file exists on disk, so a stale citation degrades to text. The generator link-checks its own output and exits non-zero on a break, and assemble.sh runs under set -eu, so a dead cross-reference fails the assembly rather than shipping. It earned that on its first two runs: it caught a fence-close regex comparing a three-character marker to a one-character string, which swallowed every document from its first code block onward, and a list parser that ended the gotcha list at the first blank line, emitting 1 of the 48 anchors the jump strip links to. Proved by injection afterwards -- renaming the anchors reports 48 missing anchors, pointing the ticket links at an ungenerated page reports 763 missing pages. No framework, no node_modules for the site, no build step beyond one zero-dependency node script, matching the landing page's posture. improvise-djoo Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
757abf3b88 |
docs: REVERT the mobile fix (user ruling), caption the stale drill cast
Read the revert first, because this commit undoes the headline change of the
one before it and a subject line saying "caption" would have hidden that.
**REVERTED: 3fcb88b's `@media (max-width: 900px)` block.** User ruling: the
mobile defect is to be FILED, not fixed in this PR. It is improvise-o31u, P2,
carrying the measurement, the proposed fix (`overflow-x: auto` on `.player`
plus `fit: false` or an explicit `terminalFontSize`), and the note that a
working fix was written and measured here before being reverted, so the next
person starts from evidence. Measured both ways at 390x844, so the cost of the
revert is on the record rather than implied:
|
||
|
|
3fcb88b291 |
docs: the landing page on a phone, and two stale instructions in the plan
Review findings on PR #47. A 120-column cast shrunk into a 390px viewport computed a **4.83px** terminal font — measured in Chromium against the assembled tree. That was tolerable when the landing page sat at `/landing/`; since the user's ruling it is the first thing a phone visitor sees. Under 900px each player now scrolls sideways at a legible size instead: **11.95px**, measured the same way, with the page's own `scrollWidth` still equal to its `clientWidth` — the overflow is contained inside the player, so there is no horizontal PAGE scroll. That takes `docs/index.html` to 209 lines, past improvise-e61's "under 200". The criterion is reinterpreted rather than crammed to fit, and said so on the ticket: the number was a proxy for single file, vanilla, no build step, no framework, all of which hold. A limit met by one line and checked by nothing was never really met. `context/plan.md` carried two instructions that this PR made actively misleading: - §2.4 still told a re-recorder to use 100x30. That is the instruction whoever picks up improvise-2oxt would follow, and it disagrees with both the existing casts and the player. It now says 120x37, and says the two must be changed together. - §4.2 still said to set Pages to branch `main` / folder `/docs`. That used to fail loudly — there was no `docs/index.html`, so it was a 404 — and since improvise-e61 it fails QUIETLY: the landing page renders perfectly and its call to action 404s, because `app/` exists only in the assembled tree. It now says GitHub Actions, and says why the other setting is worse than it looks. Verified: 6/6 harness shell specs still pass against the assembled tree, the four casts still play 37 lines each at the root, and the call to action still resolves 200. cargo test 1311, both comment checkers clean. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
2ccd21f3e8 |
docs: the landing page is the front door, the app moves to /app/
User ruling on improvise-kh8, overturning the arrangement the previous commit
shipped: "The landing page should be served at the root of the repository and
link to the in-browser demo." The argument for the other arrangement is left
standing in the ticket rather than deleted — it is overruled, not wrong to have
considered — and the root is now `docs/index.html`.
The app moves under `app/` WHOLE, both bundle directories included. Every path
in `app.js` and `worker.js` is relative, so moving the bundle together keeps
every one of them correct and the wasm-pack generated glue untouched;
`worker.js`'s `fetch("demo.improv")` resolves against the worker's own URL, so
the seed follows for the same reason. The four `stamped` guards in
`assemble.sh` follow the files: they are the only check that the cache-bust
substitution worked, and a guard aimed at a path nothing writes fails in the
direction that looks like success.
`harness/tests/shell.spec.js` navigates to `/index.html` six times, including
the `?ws=` and `?doc=` variants, and every one of those now lands on the
landing page. All six are repointed at `/app/index.html`. That file is outside
this unit's declared scope and is the second deliberate stray in this PR.
VERIFIED AGAINST THE ASSEMBLED TREE, not against `docs/` directly, because a
path move is what re-arms the trap this page already caught once. With real
bundles from `web/build.sh`:
* `npx playwright test tests/shell.spec.js --project=chromium` — 6 passed,
with `/app/{index.html,app.js,style.css,worker.js,demo.improv}` and both
`?v=` stamped bundles all served 200;
* the four casts play 37 lines each at the site root, no failed request and
no page error;
* the full journey: load the root, click the call to action, land on `/app/`,
and the grid draws out of the in-page worker — 12 cells, all editable,
a "Revenue" header, `#status` reading "in-page worker · demo.improv".
The call-to-action check was proved able to fail by pointing the link at
`./aap/`: 404, while the page still looks entirely correct.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
3a32d1348c |
docs(landing): drop the duplicated idleTimeLimit
Every cast header already carries idle_time_limit 2.0; repeating it in the player config is a second answer to one question, and the one that drifts is whichever is not the cast. Found reviewing against design-principles "a derivation done twice is the defect". Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
161e36ea60 |
docs: a landing page, served beside the app rather than in front of it
improvise-e61. Vanilla, single file, 192 lines, no build step: the four casts improvise-d4w recorded, played by asciinema-player pinned from jsdelivr. improvise-kh8 recorded a collision to resolve before starting — Pages already serves the standalone web app at the root, so a landing page either replaces it, sits beside it, or is dropped. It sits beside it at `/landing/`, because kh8's own note is right that the live app is the better front door, and a page the deploy never copies is a file nobody can reach. `web/assemble.sh` copies it, so the browser harness serves the same tree the deploy publishes and there is still one answer to "what ships". The player config deviates from the tickets, deliberately. improvise-d4w's description and improvise-e61's criteria both say 100x30; every cast header says 120x37, so the recordings never complied with their own ticket. A 30-row player clips the bottom seven rows of a 37-row cast, which is exactly where the tile bar and the status line are, so the page declares the geometry the casts actually have. e61 also asked for the casts to be checked against the current UI before embedding. They were: the tile bar's short_label vocabulary and the mode line still match, but the casts predate improvise-2zq's `+cat` column by five months and every one of them opens on the recorder's shell prompt. Filed as improvise-2oxt rather than silently embedded as current. Verified by driving the page in Chromium: four players construct, each renders 37 terminal lines after play, no failed request and no page error — against both `docs/` directly and the assembled `site/landing/`. Counting the players alone was proved worthless first: with autoPlay false the cast is not fetched until the click, so a page whose every cast path 404s constructs four players and throws nothing. Breaking `./casts/` to `./cats/` passes the construction check and fails the play check with four 404s. improvise-bgtf carries that as a harness spec, since nothing in CI asserts any of it yet. README: `cargo install improvise` was false — the crate is not on crates.io — and the Pages description named two of the three gates a deploy waits on. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |