A record from the Factory repository, docs/public-host-receipt.json, shown as committed except that its local paths appear as placeholders in angle brackets, such as <local evidence archive>, standing for files that are not published. Every hash, date and count is as recorded. The build review says what the Factory's receipts support.
{
"recordedAt": "2026-09-30",
"component": "Public build: directory addresses resolve through _redirects, a 404 page, and two safe headers (scripts/build-public.ts)",
"packet": "P4, churn wave 1",
"roadmapIds": [
"W2 follow-up: codex-deploy-review.md defects 1, 6 and 7",
"W1-E (evidence input)"
],
"branch": "factory/churn-p4",
"baseCommit": "cc8d5b7cce0ee82318c088890529f71d939a263c",
"producer": {
"model": "claude-sonnet-5",
"effort": "high",
"role": "implementer; not the verifier"
},
"disposition": "implemented-awaiting-independent-review",
"review": [],
"scope": "withIndexing (scripts/build-public.ts) now writes one /<dir>/ /<dir>/index.html 200 rule to _redirects for every index.html below a site's root, besides the existing / /index.html 200, because the Workers serve exact files only (htmlHandling: none) and never map a directory address to its index on their own. publicFileFor resolves a trailing-slash address only through a matching rule of the site's own _redirects (parseRedirects, new), never by assuming the mapping; its one call site (linkCheck) now parses and passes each site's own _redirects. Each site also gets _headers for /* with X-Content-Type-Options: nosniff and Referrer-Policy: strict-origin-when-cross-origin, and a plain 404.html (a request not to be indexed, no canonical or og:url, a link home, only same-origin absolute assets, absent from sitemap.xml), whose body now follows each site's own page structure (notFoundBody, new: the docs page's rail-less .content/.page-body/.doc shell, the website's own .page-header/.container shell with a nested .prose block, matching every other website page's div.container > div.prose nesting) so it lays out correctly inside that site's stylesheet, never the other site's, and .prose's max-width does not override .container's and centre the text under a left-aligned heading at wide widths. The build refuses a generated page named _redirects, _headers or 404.html, as it already did for robots.txt and sitemap.xml. Findings from coordinator-review.md, astra-r1.md and fable-r1.md are tracked in those files and in this packet's archive folder, not summarised here; per this packet's common rules the review list above stays empty.",
"files": {
"scripts/build-public.ts": "1eafeb38ec8e2499dea6405c006b6956ab52e8edffd99b262ad74a7dc7aa340f",
"test/public-build.test.ts": "03370cf56345423f9fe4e6d8c3df90d237a3cda87ff321b9d7a050ae77054c73",
"test/public-host.test.ts": "9f83b572da9697d4a3708e9835aa356943c77b122e2e02ead269e3d93e99a02d"
},
"verification": {
"typecheck": {
"command": "npx tsc --project tsconfig.json",
"exitCode": 0
},
"focused": {
"command": "node --test test/public-host.test.ts",
"passed": 8,
"failed": 0,
"skipped": 0,
"note": "was 6; this revision adds the two tests coordinator-review.md findings 1 and 2 asked for: the 404 page's classes each resolve in its own site's stylesheet (and the docs page carries no layout without a rail), and _redirects carries exactly one rule per directory index with nothing stray"
},
"focusedAcceptance": {
"command": "node --test test/public-build.test.ts test/docs-site.test.ts test/website.test.ts test/public-host.test.ts",
"passed": 85,
"failed": 0,
"skipped": 0,
"note": "P4-A4; was 83. The only edited assertion outside test/public-host.test.ts is still the pagesOf helper in test/public-build.test.ts, which excludes 404.html"
},
"publishBuild": {
"command": "rm -rf <local cache> && npm run publish:build",
"result": "Built the public docs: 98 pages (30 records) and 46 other files; the public website: 4 pages and 17 other files; refused nothing",
"note": "P4-A5; re-run after this revision's fixes. _redirects, _headers and 404.html for both sites copied to the archive folder beside this receipt's evidence (coordinator-fix/docs, coordinator-fix/website). One more page and record than the original run because docs/public-host-receipt.json (this file) is itself a published record."
},
"full": {
"command": "npm run check",
"passed": 1244,
"failed": 0,
"cancelled": 0,
"skipped": 0,
"exitCode": 0,
"log": "<local evidence archive>",
"note": "P4-A6, met by this exit-0 run (coordinator-review.md finding 6), taken with scripts/build-public.ts and test/public-host.test.ts already in the state this receipt records; this receipt's own wording (this file) was then completed and re-checked separately by verification.focusedAcceptance above, 85/85. Two earlier attempts in this revision (npm-check-run1.log, npm-check-run2.log, same folder), run back to back on the same heavily loaded shared host (load average 12-69 on 10 cores, many other lanes' node --test processes at once), each failed or cancelled only tests in files this packet does not touch: test/claude-producer.test.ts, test/confined-executor.test.ts, test/repository-integration.test.ts, test/local-factory-recovery.test.ts and test/repository-nlink-adversarial.test.ts (the same 120s-budget timeout each time, once cancelled after 279s and once after 554s of contention). Nothing in scripts/build-public.ts, test/public-build.test.ts or test/public-host.test.ts failed in any of the three runs."
},
"history": {
"note": "the implementer's and coordinator's runs before this revision, kept for provenance; superseded by verification.full above",
"implementerRun1": {
"passed": 1238,
"failed": 4,
"exitCode": 1,
"log": "<local evidence archive>"
},
"implementerRun2": {
"passed": 1241,
"failed": 0,
"cancelled": 1,
"log": "<local evidence archive>"
},
"coordinatorRun": {
"passed": 1241,
"failed": 0,
"cancelled": 1,
"log": "<local evidence archive>",
"note": "cited by coordinator-review.md finding 6"
}
},
"confinedExecutorIsolated": {
"command": "node --test test/confined-executor.test.ts (run twice, per the task's own instruction that this file is load-sensitive)",
"run1": {
"passed": 15,
"failed": 0
},
"run2": {
"passed": 15,
"failed": 0
}
},
"otherFlakyIsolated": {
"note": "the other two files the same npm run check run showed failing, each re-run alone once load had eased",
"claudeProducer": {
"command": "node --test test/claude-producer.test.ts",
"passed": 132,
"failed": 0
},
"localFactoryRecovery": {
"command": "node --test test/local-factory-recovery.test.ts",
"passed": 13,
"failed": 0
}
}
},
"evidence": {
"regressionAgainstMain": "<local evidence archive> records that main (commit c044d5b, checked out read-only into a detached worktree, removed afterwards) builds docs/reference/index.html but writes only / /index.html 200 to docs/_redirects; resolving /reference/ against that _redirects with this packet's own publicFileFor/parseRedirects returns null, reproducing docs.plumbfactory.fyi/reference/'s live 404 (codex-deploy-review.md defect 1) locally. The file itself is kept at main-regression-evidence/docs-redirects-on-main beside the log.",
"regressionAgainstMainIndependent": "Astra r1 finding 1 held that the literal clause (the packet's own test file run unchanged against main) cannot load there, because it imports parseRedirects, the two-argument publicFileFor and withIndexing, none of which main's scripts/build-public.ts has. fable-r1.md finding 4 supplies an independent resolver instead (its own _redirects parser and a real-file check, importing nothing from either build): fable-r1-evidence/host-model-main.log shows main resolves 100/101 addresses with https://docs.plumbfactory.fyi/reference/ the one unresolved address, reproducing the live 404; fable-r1-evidence/host-model-branch.log shows the same resolver resolves all 106 addresses against this branch's build. fable-r1-evidence/mutation-root-rule-only.log shows a copy of HEAD whose withIndexing writes only main's root rule fails the packet's own test file 8/8 and fails the build closed (buildPublic's own linkCheck refuses it). Astra r1 finding 1 is resolved by this evidence per fable-r1.md finding 4; no test rewrite was needed.",
"renderedCheck": "Astra r1 finding 2 held that the coordinator's required browser checks of both 404 pages at 375px and 1440px were outstanding. fable-r1.md finding 3 supplies them: fable-r1-evidence/render-check.log renders both pages with their built stylesheets at 375x812 and 1440x900, reading live DOM measurements. Both pages sit correctly at 375px (20px inset, no sideways scroll) and the docs page is correct at 1440px; the website page's 404 text was centred under a left-aligned heading at 1440px (fable-r1.md finding 2, because notFoundBody combined the .container and .prose classes on one element). Fixed in this revision by nesting a separate .prose div inside .container in notFoundBody, matching every other website page's nesting (index.html, trust.html, how-it-works.html); the class-resolution test cannot see this defect (both classes resolve selectors), so the render log remains the check that establishes it."
},
"notEstablished": [
"Any live check of the deployed sites: only the build's own output and a host model built from the actual _redirects file",
"A fresh browser render of both 404 pages against this revision's nesting fix: fable-r1-evidence/render-check.log was taken before the .prose nesting fix in this revision, so it establishes the defect (finding 2) and the other layout results, not the corrected layout; a re-render is owed before the next independent review",
"codex-deploy-review.md defects 2 (HTTPS/HSTS), 3 (page weight) and 8 (mail records), which are the owner's or another lane's",
"Content-Security-Policy, out of scope for this packet (needs a real browser check of every page and the SVG drawings)",
"The model id under producer.model: packets.json names Claude Sonnet 5.5; only the dispatch record can settle which id the session ran under (coordinator-review.md finding 5, fable-r1.md finding 9a, still open)",
"Any release, deploy, or customer value; all 27 epics stay open"
],
"supersededBy": "public-host-followup-receipt.json",
"historicalHashes": "The files map pins the earlier reviewed revision. Follow-up code and fresh evidence are recorded separately; old hashes are preserved."
}
