Archilyzer · Source

archilyzer

Archilyzer
git clone https://archilyzer.pages.dev/source/archilyzer.git
Log | Files | Refs | README | LICENSE

commit 31c4cfd2d150e2f89d7d3c6ef1d5289c0ac79f40
parent ce0dc5e1989551fb882224bf931f6283c520bb65
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date:   Fri,  9 Oct 2026 14:49:26 -0400

plans: release 22 — Track E as shipped (E1–E5), the overview ruling confirmed; export changelog; PUBLISH.md's exports name the slides

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

Diffstat:
MPUBLISH.md | 12+++++++++---
Mexport/CHANGELOG.md | 2++
Mplans/release-22.md | 112+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 121 insertions(+), 5 deletions(-)

diff --git a/PUBLISH.md b/PUBLISH.md @@ -83,7 +83,12 @@ resolve it, to `.export-index/sites/<id>/report-exports/<report>/` as `report.ht (one self-contained file — inline style, no script, its stills and post screenshots inlined; clips linked on the site), `report.pdf` (that page printed by headless Chromium; skipped with a note on a host without Playwright's browser), `report.md` -(plain Markdown with numbered references) and `evidence-pack.zip` (the page with its +(plain Markdown with numbered references), `slides.html` (the report as slides — the +same slides the page's Slides view shows, `common/lib/report/slides.ts` — one +self-contained file: the site's slide stylesheet in its accent, every picture inlined, +a few lines of script for the keys), `slides.pdf` (those slides printed, one 1280 × 720 +page per slide; skipped like `report.pdf`; neither slides file for a report whose +`slides.hide` says so) and `evidence-pack.zip` (the page and the slides with its clips, stills and screenshots as files, so the clips play offline, plus the Markdown and the citations; packed by the system `zip`, which a host must have), with an `export.json` naming each file's size and checksum and the hash of the report.json it @@ -106,7 +111,8 @@ and `export.json` records it. The build's compose then writes the reports from what prepare left (`common/publish/composeReports.ts`): each report's page, its citations as `citations.json` and `citations.csv`, its exports (`report.html`, `report.pdf`, -`report.md`, `evidence-pack.zip` — only those made from the report.json as it is now, +`report.md`, `slides.html`, `slides.pdf`, `evidence-pack.zip` — only those made from the +report.json as it is now, and only a file of at most 24 MiB: a larger pack stays on the host; the page's download line lists what was published), its cited stills (never a saved source copy), one page per cited moment with the transcript lines around it, the prepared clips @@ -283,7 +289,7 @@ the same lock. | The source mirror alone | — (every homepage build runs it) | — | `source publish [--force] [--check] [--keep-scratch]`, `source audit [<git dir>]` | | Fetch the clip windows a site's reports cite and the disk lacks | its **Reports** tab → *Fetch missing evidence* (*Preview missing evidence* lists them) | `fetch-windows` (`{"siteId", "dryRun"?}`) | — | | A site's report evidence media (then its exports) | its **Reports** tab → *Prepare evidence media* | `reports-prepare` (`{"siteId"}`) | `reports prepare <id>` | -| A site's report exports (HTML, PDF, Markdown, evidence pack) | its **Reports** tab → *Export reports* | `reports-export` (`{"siteId", "reportId"?, "formats"?}`) | `reports export <id> [--report <rid>] [--formats html,pdf,md,zip]` | +| A site's report exports (HTML, PDF, Markdown, slides, evidence pack) | its **Reports** tab → *Export reports* | `reports-export` (`{"siteId", "reportId"?, "formats"?}`) | `reports export <id> [--report <rid>] [--formats html,pdf,md,slides,slides-pdf,zip]` | | A report from a /sweep report, an /ask answer or a report-to-video manifest, and a starter manifest from a report | — | — | `reports convert <sweep\|ask\|manifest> <in> --out <report.json> [--channels-dir <dir>]`, `reports to-manifest <report.json> --out <manifest.json>` | **The editor.** The /sites **Publish** panel has a row per site, then the hub and the diff --git a/export/CHANGELOG.md b/export/CHANGELOG.md @@ -1,6 +1,8 @@ # Changelog ## [Unreleased] +- **A report reads as an article, as slides, or in an overview of both.** A report page's header has a switch, **Article · Slides · Overview**. **Slides** shows the report one 16:9 slide at a time, fitted to the screen in the site's accent and light or dark: a title slide, In brief, What the check found, one slide per section and per claim — its verdict, its finding and the evidence it rests on (a clip's still, a post's screenshot, the article's sentence, with its quote) — and a sources slide. ← → (and Page Up, Page Down, Home, End) or a swipe step through them; a citation's number opens its card; every slide has **Read this in the article**, and Esc goes back to the article where the slide stands. On a phone a slide reads top to bottom, its evidence under its words. **Overview** lays the article's parts and their slides side by side on one tilted plane, each part beside its slide: ↑ ↓ walk them, a part opens the article there and a slide opens the slides there; with reduced motion, on a narrow screen, arriving by keyboard or with **Flat**, the same pairs lie flat. Switching keeps your place: the part of the article on screen opens its slide, and back. The view and the place are in the address (`?rv=slides#s-4`, `?rv=iso#<part>`), so a shared link opens the same slide; the article itself is unchanged for search engines and readers without script. A report's author can shape its slides in `report.json` (`slides`, and a section's or claim's `slide`: its own title, up to five short points, which evidence to show, a layout, or hidden); a report without them still has slides, made from its text. Needs a rebuild and deploy of each site with reports. +- **A report can be saved as slides.** The download line adds **Slides** (`slides.html`, one file that opens with no network: the slides with their pictures inside, the arrow keys stepping through them, each citation numbered to a reference list) and **Slides PDF** (one page per slide), and the evidence pack carries the slides too. Needs `reports export` (or prepare) and a rebuild and deploy of each site with reports. - **Posts withdrawn from a site leave a stand-in, not a stale copy.** When an X channel's posts stop being published on a site — while X posts are private, say — the site's build ships an empty posts manifest and an empty page at every address they were served from, sent with `Cache-Control: no-store`, so a reader (or the hub) asking for them gets "no posts" instead of the copy Cloudflare's edge kept for up to a week. The hub does the same for every X channel a public site carries. - **A quote with an editorial insertion is still a citation.** An inline citation whose quoted words hold brackets, `[“told [the mayor] so”](cite:id)`, is numbered, previews and links like any other, is listed in the reference list and its section's, and validation names its id when the report lacks it; it used to render as plain text. A label with a lone `]` is still not a link. The MCP's report reader counts it too. Needs `reports prepare` and a rebuild and deploy of each site with reports. - **A report can carry a video.** `report.json` `video` (`{ "src": "video.mp4", "poster": "poster.jpg", "caption": "…" }`, files in the report's directory: an mp4, a png/jpg/webp poster, a one-line caption) plays at the head of the report's page, under its header. Composing the site refuses a report whose video or poster is missing, or whose video is over the 24 MiB publish limit. Needs a rebuild and deploy of the site. diff --git a/plans/release-22.md b/plans/release-22.md @@ -7,8 +7,8 @@ so a reader sees the same article both ways and enters whichever they prefer at ## Rulings (operator, 2026-10-09) - Articles may be **built a bit differently** to make this work: `report.json` gains authoring fields for slides. -- *Assumption, open to correction:* "isometric render" is the overview described here (a tilted plane pairing - each article section with its slide, click either to enter that view), not a separate visual style. +- **"Isometric render" is the overview described here** (operator confirmed 2026-10-09): a tilted plane pairing + each article section with its slide; click either to enter that view. ## What is there (verified) @@ -111,6 +111,114 @@ when a site is rebuilt — nothing here rewrites a report.json in the corpus. ### Track E +Branch `worktree-agent-a4ec71c7c593a80e5`, off `fdbdd370` (`r19/integration` with this plan). Not pushed, not merged. + +#### E1, as shipped — the slide fields and the builder + +`report.json` gains `slides` (`hide`, `title`, `points`, `closing` — `points` added to the plan's three: the +plan's "the quick take: summary's first paragraph (or `points`)" needs a place for them) and a section's or +claim's `slide` (`title`, `points`, `cite`, `layout`, `hide`); `version` stays 1. The limits are one pure module, +`common/lib/report/slideRules.ts` (5 points, 140 visible characters each — a citation counts as its label —, 160 +for a line), with the report page's own anchor ids (`REPORT_PAGE_ANCHOR_IDS`: `report-head`, `in-brief`, `found`, +`claims`, `references`, `downloads`, `report-end`). The validator checks lines (one line, not blank, not too +long), points (count, length, inline cites that name a citation the report cites ELSEWHERE — a slide never brings +evidence of its own, which would have no number), a `cite` of the slide's own section or claim, an +`evidence`/`quote` layout with something to show, and refuses a section or claim id that is one of the page's own +anchors (a counts-only scan of the 26 published `report.json` files: 0 of 322 ids collide). `lib/report/slides.ts` +`buildReportSlides(view)` is the deck (title, In brief, What the check found, each section and claim, sources), +each slide anchored to an id the article page carries (`reportPageAnchorIds`), plus `slideForAnchor`, +`slideIndexForPlace`, `slideLint` (umtool) and the URL place (`parseReaderPlace`/`readerPlaceUrl`: `rv`, `#s-<n>` +or an anchor). The page view carries the fields through `buildReportPageView` (compose) and umtool's lenient +fallback (which also now gives a claim's `sourceQuote` as its id, as the strict view does). REPORT.md regenerated +(a Slides section, the two key tables); the demo fixture report gains `slides`, a section's points and cite, a +claim's title and points, a claim's quote layout. + +#### E2, as shipped — the slides view + +`common/components/report/slides/`: `Slide` (one slide per kind and layout; its left edge the colour of what it +says — a claim's verdict, else the accent; "Read this in the article" to its anchor), `ReportSlides` (a 1280 × 720 +canvas scaled as one piece to its box, reflowed on a narrow portrait box; ← → PgUp PgDn Home End, Esc, swipe; a +region with an `aria-live` "Slide n of N: <kind> — <title>" label; a rail), `ViewSwitch` (a `role="group"` of +`aria-pressed` toggles), `SlidesHost` (what differs by host: markdown, a citation's marker, the way back, a badge), +`useReaderPlace` (`rv` + hash; a switch pushes, a step replaces). Styles are plain CSS, `common/styles/slides.css` +(`.rs-*`, unlayered so it wins over a shared component's utilities), coloured from the host's tokens through +`--rs-*`. The export site's report header carries `ReportReader`: the other views are laid over the static page, +built in the browser from `page.json` (fetched on demand); the article behind is `inert` and still; the place is +kept both ways (the part in view opens its slide; Esc / "Read this" land on the anchor, scrolled to and focused); a +citation number's click inside a slide opens its card instead of jumping to the reference list behind. +`CitationCard`'s `heading` is exported as `citationHeading`. + +#### E3, as shipped — the overview + +`ReportOverview`: the pairs as one ordered list; tilted (`rotateX(55deg) rotateZ(-45deg)`, the plane's box sized +from the tilt's geometry so it scrolls whole, the scroller alone moved to the pair in force — never the article +behind) or flat (two columns; stacked under 780 px of box, a container query so umtool's column stacks too). Flat +for reduced motion, a box under 900 px, a keyboard arrival, or the **Flat** toggle (localStorage, try/catch). ↑ ↓ +Home End walk, ← → block/card, Enter opens, Esc back to the article; roving tabindex (only the pair in force is +tabbable); a thumbnail is the real slide, `inert`, its words as text. The e2e specs were split: `slides.spec.ts`, +`overview.spec.ts`. + +#### E4, as shipped — umtool + +`ArticleReader` gets the switch over its lenient view; `ArticleShapes` renders the shared slides/overview in the +reading column (the text stays mounted, hidden, its note marks with it; the notes rail beside). A slide's markdown +is umtool's `Md` (a citation opens the evidence rail), its badge the open notes on its part (`openNotesBySlide`: +a section's on its slide, title/subtitle on the title slide, a citation's on each slide showing it). The source +tab lists slide lint and the validator's slide problems (`data-slide-lint`), each linked to its slide. umtool's +globals.css imports slides.css, sources `common/components/report`, and maps `--rs-*` to its bench palette (`sel` +the accent). The sites fixture's draft `polemic-beta` gains a long body (its slide lint's case). +`umtool/e2e/article-slides.spec.ts` (4 tests). + +#### E5, as shipped — exports + +`slides` (`slides.html`) and `slides-pdf` (`slides.pdf`) join `REPORT_EXPORT_FORMATS` (order html, pdf, md, +slides, slides-pdf, zip), so the downloads line, compose, the cited audit's allowlist (`REPORT_EXPORT_FILENAMES`), +the revision commit's `exports.json`, the CLI and the ops job take them unchanged. `lib/report/exportSlidesHtml.ts` +is the slides as one file (slides.css inline, the light base in the site's accent — `resolveAccent(site.accent) +.light` —, every picture a data: URI, a few lines of script to fit and step, numbers to a reference list under the +deck, each slide's way back to the site, the footer line on the sources slide). It is a STRING mirror of +`Slide.tsx`: reportExports.ts is bundled into the editor's server (its "use server" export action), where +`react-dom/server` is not imported; `exportSlides.test.ts` holds the two to the same `rs-` classes per slide and +every class to a rule in the stylesheet. `slides.pdf` prints it at 1280 × 720 (`PdfPrinter.print(html, size?)`, +`playwrightRuntime`'s `pdf` type gains width/height). A poster only the slides show is inlined or packed when local, +never a problem. A report with `slides.hide` exports neither (a log line). CLI usage, ops usage and COMMANDS.md +updated. + +#### E6 — records + +This section; `export/CHANGELOG.md` `[Unreleased]` (two bullets); PUBLISH.md's exports paragraphs and table row; +the ruling line above reworded as on `r19/integration`. umtool has no CHANGELOG.md (none written); the editor is +unchanged (no editor changelog). + +| commit | what | +|---|---| +| `2734b22b` | E1 schema, validator, slideRules, buildReportSlides + tests, REPORT.md, fixture | +| `12691d03` | E2 shared slides components, slides.css, ReportReader, article anchors, slides.spec | +| `75f0205d` | E3 ReportOverview, the switch's Overview, overview.spec | +| `5d0b4fbc` | E4 umtool switch, ArticleShapes, note counts, source-tab slide lint, article-slides.spec | +| `e9ea4cdc` | E5 slides.html / slides.pdf exports, downloads, pack, tests, CLI text | +| (this) | E6 record, changelog, PUBLISH.md | + +**Gates.** `pnpm -r --no-bail --workspace-concurrency=1 exec tsc --noEmit` clean at E1 and at E5 (E2–E4 per +package: common, export, umtool `tsc --noEmit` clean). Unit: `common/lib/report/*.test.ts` 111/111 (slides.test 26, +exportSlides.test 6, report.test 17 with the new slide/anchor cases); `publish/composeReports.test.ts` + +`reportMedia.test.ts` 23/23 (export expectations updated for the two new files and the second skipped-PDF note); +`lib/builtExport.test.ts` + `bin/cli-docs.test.ts` + `bin/_cli.test.ts` + exportSlides 62/62; +`pnpm --filter export test` 116/116; mcp 292/292 (at E1), `mcp/src/reports.test.ts` 5/5 (at E5); +`scripts/archilyzer-ops.test.mjs` 46/46. **Not run — the operator's P1 hold (no e2e, no builds until the +all-clear):** the export report suite (`e2e:report`, planned at E3 and E5: `slides.spec.ts` 10, `overview.spec.ts` +3, the downloads/audit changes), umtool's article specs (`article-slides.spec.ts` + the three existing), the umtool +capped build, and the full common suite. The views were checked visually instead, with no build: slides.html of the +fixture rendered and screenshotted in headless Chromium (every slide kind), and the shared components bundled with +esbuild over the fixture's page.json (slides at 1440 × 900 and 390 × 844, the overview tilted, flat under reduced +motion, stacked on a phone, light and dark). + +**Found and left.** (1) A claim's slide shows its gist when it has no points; a claim with neither shows only its +title and text. (2) The overview's thumbnails render every slide (fine at the fixture's 11; a report of 100+ claims +would render 100+ small slides — not measured). (3) The keyboard-arrival heuristic is the last input before the +overview mounted (a keydown anywhere counts). (4) `report.json`'s change summary (revision history) does not name a +slide-field edit ("Other edits"). (5) slides.html's light base only (no dark variant), as report.html. + ## Rollout Rebuild and deploy each site with reports (the slides view is in the bundle, and `reports prepare` re-exports to