Make the dev server say "npm install" instead of blaming read.tsx - #24

Merged
AndresL230 merged 2 commits into
mainfrom
fix/dev-dependency-preflight
Aug 17, 2026
Merged

Make the dev server say "npm install" instead of blaming read.tsx#24
AndresL230 merged 2 commits into
mainfrom
fix/dev-dependency-preflight

Conversation

@Darkest-Teddy

Copy link
Copy Markdown
Contributor

The report

Opening a document in Read & mark threw this:

[plugin:vite:import-analysis] Failed to resolve import "pdfjs-dist"
from "src/read.tsx". Does the file exist?

Nothing was wrong with read.tsx. pdfjs-dist is declared by apps/deliberation and recorded in package-lock.json — it was simply never installed, because that checkout's node_modules predated the merge that added it.

The overlay names a correct file, a correct line and a correct import, and asks whether a file the author never wrote exists. Every fact in it points away from the cause, so it sends you reading application source. It cost a round trip.

Why a preflight and not just an install

The trigger isn't this package. It's any npm install older than the last dependency added on any branch — which is every collaborator after every pull, forever. Installing once fixes today; this fixes the class.

tools/check-deps.mjs walks the workspaces the root manifest declares and checks that what they declare is actually on disk, hoisted or nested:

Dependencies on disk do not match the manifests:
- pdfjs-dist (4.10.38) declared by @arbiter/deliberation — not installed
Fix: npm install

Same trade dev-all.mjs already makes with --strictPort: fail loudly at startup rather than proceed into a state whose symptom names the wrong cause.

Exact pins are version-checked, ranges are not. A bare version means somebody needed a specific one — pdfjs-dist is pinned at 4.10.38 because 5.x needs Node ≥ 22.13 and crashes on 20. A stale hoisted 5.x would satisfy a directory check and then fail at runtime talking about something else, which is the exact failure mode this file exists to end. Ranges would need a semver implementation to say anything the range doesn't already say.

Wiring

  • npm run dev — in-process, before a single server is spawned
  • npm run deliberate:dev
  • npm run check:deps — standalone

Tests

A guard's own failure mode is passing while checking nothing, so the suite builds broken fixture trees rather than running against this repo. Gutting checkDeps to return [] fails four of the eight.

Two places this could have gone quietly no-op are closed:

  • the standalone-entry check uses pathToFileURL rather than interpolating argv[1] into a file:// string, which on Windows never matches — the script would have exited 0 having checked nothing
  • an unexpandable workspace pattern throws rather than skipping that workspace and still reporting ok

Verified

  • npm run dev on a tree with the package hidden: exits 1, no server spawned
  • restored: dependencies ok
  • 829 tests / 59 files, typecheck clean, lint clean

Based on feat/product-in-the-atmosphere so it can be merged into the branch being tested locally, without disturbing #22.

🤖 Generated with Claude Code

Opening a document threw:
[plugin:vite:import-analysis] Failed to resolve import "pdfjs-dist"
from "src/read.tsx". Does the file exist?
Nothing was wrong with read.tsx. `pdfjs-dist` is declared by
apps/deliberation and recorded in the lockfile; it was simply not
installed, because that node_modules predated the merge that added it.
The overlay names a correct file, a correct line and a correct import,
and asks whether a file the author never wrote exists - every fact in it
points away from the cause.
The trigger is not this package. It is any install older than the last
dependency added on any branch, which is every collaborator after every
pull, so the fix is not another install: it is a preflight that fails
where the cause is legible.
tools/check-deps.mjs walks the workspaces the root manifest declares and
checks that what they declare is on disk, hoisted or nested. Exact pins
are also version-checked, ranges are not: a bare version means somebody
needed a specific one, and pdfjs-dist is pinned at 4.10.38 because 5.x
needs node >= 22.13 and crashes on 20 - a stale hoisted 5.x would pass a
directory check and then fail at runtime talking about something else.
Ranges would need a semver implementation to say anything ranges do not
already say.
Wired into `npm run dev` in-process before any server is spawned, and
into `deliberate:dev`; also `npm run check:deps` on its own.
A guard that passes while checking nothing is the failure mode here, so
the tests build broken fixture trees rather than running against this
repo - gutting checkDeps to `return []` fails four of the eight. Two
places where this could have gone quietly no-op are handled: the
standalone-entry check uses pathToFileURL rather than interpolating
argv[1], which on Windows never matches, and an unexpandable workspace
pattern throws instead of skipping a workspace and still reporting ok.
Verified: `npm run dev` exits 1 without spawning a server on a tree
missing the package. 829 tests, typecheck and lint clean.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitaiBot commented Aug 16, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 92099a55-0191-40cb-b0de-e3e6b55e3690

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Darkest-Teddy added a commit that referenced this pull request Aug 16, 2026
Written so the next session does not have to reconstruct this from a
terminal. Sibling to HANDOFF-evaluation.md, added to this branch the same
day from another session: that one owns the numbers, this one owns Read &
mark, the environment behind it, and the dev-server preflight.
WHAT IT CARRIES. The three load-bearing decisions in the reading surface
and why each is easy to break: seats are stored rather than derived from
participant order, because that order is a sorted set and adding anybody
silently recoloured every existing highlight below them; the finding join
is sourceDocumentId and not the filename, because real data holds
"FDA NDA 211810" where the file is turalio-211810-multidiscipline.pdf and
a filename join matches nothing while looking like a rendering bug; and
blindness is enforced by the server not returning positions, so a new
endpoint outside the read guard silently ends the blind stage.
THE ONE PIECE OF THE DESIGN THAT IS NOT BUILT is written up as such - the
top-level Read entry in the rail. It is no longer blocked on the scene,
which now exists, and what it actually needs is a launcher route, because
a NAV entry has no caseId to bind to.
The seat palette question is left as a decision for a human rather than
settled quietly in code. Re-fitting the seats to this branch's blue wedge
separates them mostly by lightness, and 3 to 5 are close at badge size
with six people on a case. Three ways out, all design-system calls.
AN INDEX IN HANDOVER.md, because there were three branch handoffs and
nothing pointed at any of them. HANDOVER.md is the file somebody opens
first and it is only updated at merge, so work in flight was reachable
only by knowing it existed.
Corrected two claims while checking them rather than shipping them: the
suite here is 821 tests across 58 files, not the 829/59 measured with
PR #24's own tests included, and measure_pdf.py is in data/prep, not
tools. Every file:line pointer in the document was verified against the
tree.
PR #24 is named as the first thing to do. It is not merged.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Darkest-Teddy added a commit that referenced this pull request Aug 16, 2026
A second session is writing the reading-surface handoff on this same branch, and its
first line is one this document was missing: HANDOVER.md records the submission as due
16 Aug 2026, which is today. A handoff that opens with a forty-minute measurement and
says nothing about the deadline invites someone to start the EMA EPAR corpus work in
section 8 instead, which has no chance of landing. So the deadline is now above section
0, with the note that the ordering survives it either way - after the date, the EPAR
work stops being out of reach and becomes worth doing properly.
Cross-referenced the sibling both directions. It owns the reading surface, the scene and
the preflight; this one owns the numbers. Its first instruction is that PR #24 is open
against this branch and unmerged, which matters to anyone arriving here cold and is not
otherwise discoverable from this file.
Section 13 gains what CI actually enforces, which is more than the three commands this
document was quoting. The one that catches you is the manifest diff: a reported figure
that moves fails the build until the move is committed and explained. Also that this
branch has two sessions on it and the last push was rejected for exactly that - fetch
before pushing.
HANDOVER.md's index row for this file said "three times a metric looked broken". It is
four; the fourth was my own fixture labels being wrong while the model was right, which
is the one of the four most likely to repeat.
Typecheck, lint and 821 tests pass.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…gful
This branch's checks last ran against a base where npm test could not
pass, so its red X was never about the preflight. Taking the base in so
the run says something.
@AndresL230
AndresL230 changed the base branch from feat/product-in-the-atmosphere to mainAugust 17, 2026 04:24
@AndresL230
AndresL230 merged commit 94ed8e4 into mainAug 17, 2026
3 checks passed
AndresL230 added a commit that referenced this pull request Aug 17, 2026
The doc was written an hour before the merge it describes. Also note the
gap it opened: #24 went to main alone, so feat/product-in-the-atmosphere
is one merge behind again.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
AndresL230 added a commit that referenced this pull request Aug 17, 2026
main moved 42 commits under this branch - #33 (Postgres/Supabase), #24, #29,
#32 and the logo - and rewrote the three files this touches most.
THE RECONCILIATION #33 DEFERRED. `ShareStore` was written against the pattern
this branch had: a synchronous `new ShareStore(path)` beside `AuthStore` and
`InviteStore`. That layer is gone. So the store joins the new one the way the
other four did:
- `ShareStoreApi` in postgres-share.ts, where `AuthStoreApi` and
`InviteStoreApi` live, for the reason stated there: the second
implementation is what needs a name for the shape.
- `ShareStore.open(path)`, async, private constructor.
- `PostgresShareStore`, and supabase/migrations/0002_share_links.sql.
- Both branches of `buildStores`, and `Stores.shares`.
- The behaviour is ONE suite over both implementations
(test/share-store-contract.ts), as with auth and invites.
`shareSecret` deliberately stayed OUT of `buildStores`: which backing holds the
links is a storage decision, whether the deployment can publish at all is not.
THE TABLE HOLDS NO TOKEN, and the migration says so at length because that is
the feature's whole security argument - the URL is
HMAC(secret, "caseId:version"), derivable from two columns that are not secret,
so a stolen dump yields nothing. `publish` omits `version` from its upsert's
SET list on purpose: assigning it would reset a revoked case to 1 and re-mint
the token revoke had just killed. A test reads the column list back out of
information_schema, because that property fails silently.
WHAT THE CONFLICTS COST. server.ts kept main's static serving whole and its
`/api/health` route; the branch's "NO STATIC-FILE SERVING HERE" comment was
true when written and is now a lie, so it is replaced by an accurate one:
`/r/:caseId/:token` is still not served in production, a scanned QR 404s on a
deployed host, and the two decisions that has to wait on are written down
beside `staticRoot()`. Adding it here was out of scope and stayed out.
`handleReport` and `handleShare` became async; `handleReport` fetches the people
in one `auth.list()` rather than a lookup per name, because `auth.get` is
asynchronous now and `buildCaseReport` takes a synchronous `person`.
ONE THING THE MERGE HAD TO DECIDE. docs/HANDOFF-open-prs.md predicted that #30
and main each carried a provenance rule and that they would auto-merge without
conflict. They did, and both were live: `view`'s read any unrecognised actor as
`live`, the report's read only "model" as `live`. Two surfaces describing one
signed safety adjudication, disagreeing about whether a model produced it.
Closed with one module-level `sourceOf`, failing toward `stub`; every writer
passes "stub" or "model" so nothing observable changed, and the test pins that
both readers agree on a third actor neither was written for.
The postgres test fixture now applies every migration in filename order. Pinned
to 0001, it built a database that was correct on the day it was written and
silently lacked share_links.
Verified: lint, typecheck, 1267 tests with DATABASE_URL set (1179 without),
both builds, harness + metrics + golden + an unchanged verdict-manifest, e2e.
The public bundle still carries no auth code: only main's own entry chunk
matches AUTO_PASSWORD or /api/auth/login, and public.html references neither.
HANDOFF-pr34.md is deleted - the job it describes is this commit, and what
happened is recorded in docs/HANDOFF-open-prs.md and the spec.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
AndresL230 added a commit that referenced this pull request Aug 17, 2026
…, three fixes
What this session actually did, and how each claim in it was checked.
#25 reviewed from scratch, which nothing had done - its entry was a placeholder that said
so. The ten numbers are sound: every headline re-derived from the raw rows rather than
trusted, Wilson checked against the standard interval, the Ask/retrieval same-fixture
cross-check confirmed real. Three defects in the instrument, all fixed: one headline was
read from a summary field in the file that promises it never does that, one cross-check
could not fire because the results file predates the field it keys off, and a product
change to extraction retrieval rode along unmeasured by any of the ten and untested.
#27 split; the good half is prepared. Also records a third blocker nobody had noted - it
reverts SHAPE_ASK from 64000 to 16000 - and corrects "four eval scripts" to six.
#28 verified empty against current main rather than asserted: five conflicts, all in files
main has superseded. Two corrections to this document's own account of it, both from the
same mistake - reading `git diff main PR` as if it were a merge. It is not: neither merge
base contains `responseSchemaFor`, so main ADDED it and a merge keeps it.
Corrects the no-database baseline, which was wrong by 7. 1055 + 76 = 1131 is the Postgres
total; the recorded 1048 + 76 = 1124 was #33's merge-commit figure carried into a row it
had stopped belonging to. New baselines at 1c25747 measured in both environments.
Corrects the Node-20 note: CI pins node-version 22, and the real item is the action
runtime. Records the dependabot triage, the two #24 risks now fixed, the withTransaction
fix, and the .gitignore hole that let a venv symlink be committed during this session.
Adds the two things this document keeps getting wrong: origin/main moves mid-session, and
the open-PR count must come from `gh pr list` rather than from a sentence - it has now
been miscounted twice in opposite directions, the second time omitting #34.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@Darkest-Teddy@AndresL230
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Make the dev server say "npm install" instead of blaming read.tsx - #24

Merged
AndresL230 merged 2 commits into
mainfrom
fix/dev-dependency-preflight
Aug 17, 2026
Merged

Make the dev server say "npm install" instead of blaming read.tsx#24
AndresL230 merged 2 commits into
mainfrom
fix/dev-dependency-preflight

Conversation

@Darkest-Teddy

Copy link
Copy Markdown
Contributor

The report

Opening a document in Read & mark threw this:

[plugin:vite:import-analysis] Failed to resolve import "pdfjs-dist"
from "src/read.tsx". Does the file exist?

Nothing was wrong with read.tsx. pdfjs-dist is declared by apps/deliberation and recorded in package-lock.json — it was simply never installed, because that checkout's node_modules predated the merge that added it.

The overlay names a correct file, a correct line and a correct import, and asks whether a file the author never wrote exists. Every fact in it points away from the cause, so it sends you reading application source. It cost a round trip.

Why a preflight and not just an install

The trigger isn't this package. It's any npm install older than the last dependency added on any branch — which is every collaborator after every pull, forever. Installing once fixes today; this fixes the class.

tools/check-deps.mjs walks the workspaces the root manifest declares and checks that what they declare is actually on disk, hoisted or nested:

Dependencies on disk do not match the manifests:
- pdfjs-dist (4.10.38) declared by @arbiter/deliberation — not installed
Fix: npm install

Same trade dev-all.mjs already makes with --strictPort: fail loudly at startup rather than proceed into a state whose symptom names the wrong cause.

Exact pins are version-checked, ranges are not. A bare version means somebody needed a specific one — pdfjs-dist is pinned at 4.10.38 because 5.x needs Node ≥ 22.13 and crashes on 20. A stale hoisted 5.x would satisfy a directory check and then fail at runtime talking about something else, which is the exact failure mode this file exists to end. Ranges would need a semver implementation to say anything the range doesn't already say.

Wiring

  • npm run dev — in-process, before a single server is spawned
  • npm run deliberate:dev
  • npm run check:deps — standalone

Tests

A guard's own failure mode is passing while checking nothing, so the suite builds broken fixture trees rather than running against this repo. Gutting checkDeps to return [] fails four of the eight.

Two places this could have gone quietly no-op are closed:

  • the standalone-entry check uses pathToFileURL rather than interpolating argv[1] into a file:// string, which on Windows never matches — the script would have exited 0 having checked nothing
  • an unexpandable workspace pattern throws rather than skipping that workspace and still reporting ok

Verified

  • npm run dev on a tree with the package hidden: exits 1, no server spawned
  • restored: dependencies ok
  • 829 tests / 59 files, typecheck clean, lint clean

Based on feat/product-in-the-atmosphere so it can be merged into the branch being tested locally, without disturbing #22.

🤖 Generated with Claude Code

Opening a document threw:
[plugin:vite:import-analysis] Failed to resolve import "pdfjs-dist"
from "src/read.tsx". Does the file exist?
Nothing was wrong with read.tsx. `pdfjs-dist` is declared by
apps/deliberation and recorded in the lockfile; it was simply not
installed, because that node_modules predated the merge that added it.
The overlay names a correct file, a correct line and a correct import,
and asks whether a file the author never wrote exists - every fact in it
points away from the cause.
The trigger is not this package. It is any install older than the last
dependency added on any branch, which is every collaborator after every
pull, so the fix is not another install: it is a preflight that fails
where the cause is legible.
tools/check-deps.mjs walks the workspaces the root manifest declares and
checks that what they declare is on disk, hoisted or nested. Exact pins
are also version-checked, ranges are not: a bare version means somebody
needed a specific one, and pdfjs-dist is pinned at 4.10.38 because 5.x
needs node >= 22.13 and crashes on 20 - a stale hoisted 5.x would pass a
directory check and then fail at runtime talking about something else.
Ranges would need a semver implementation to say anything ranges do not
already say.
Wired into `npm run dev` in-process before any server is spawned, and
into `deliberate:dev`; also `npm run check:deps` on its own.
A guard that passes while checking nothing is the failure mode here, so
the tests build broken fixture trees rather than running against this
repo - gutting checkDeps to `return []` fails four of the eight. Two
places where this could have gone quietly no-op are handled: the
standalone-entry check uses pathToFileURL rather than interpolating
argv[1], which on Windows never matches, and an unexpandable workspace
pattern throws instead of skipping a workspace and still reporting ok.
Verified: `npm run dev` exits 1 without spawning a server on a tree
missing the package. 829 tests, typecheck and lint clean.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitaiBot commented Aug 16, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 92099a55-0191-40cb-b0de-e3e6b55e3690

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Darkest-Teddy added a commit that referenced this pull request Aug 16, 2026
Written so the next session does not have to reconstruct this from a
terminal. Sibling to HANDOFF-evaluation.md, added to this branch the same
day from another session: that one owns the numbers, this one owns Read &
mark, the environment behind it, and the dev-server preflight.
WHAT IT CARRIES. The three load-bearing decisions in the reading surface
and why each is easy to break: seats are stored rather than derived from
participant order, because that order is a sorted set and adding anybody
silently recoloured every existing highlight below them; the finding join
is sourceDocumentId and not the filename, because real data holds
"FDA NDA 211810" where the file is turalio-211810-multidiscipline.pdf and
a filename join matches nothing while looking like a rendering bug; and
blindness is enforced by the server not returning positions, so a new
endpoint outside the read guard silently ends the blind stage.
THE ONE PIECE OF THE DESIGN THAT IS NOT BUILT is written up as such - the
top-level Read entry in the rail. It is no longer blocked on the scene,
which now exists, and what it actually needs is a launcher route, because
a NAV entry has no caseId to bind to.
The seat palette question is left as a decision for a human rather than
settled quietly in code. Re-fitting the seats to this branch's blue wedge
separates them mostly by lightness, and 3 to 5 are close at badge size
with six people on a case. Three ways out, all design-system calls.
AN INDEX IN HANDOVER.md, because there were three branch handoffs and
nothing pointed at any of them. HANDOVER.md is the file somebody opens
first and it is only updated at merge, so work in flight was reachable
only by knowing it existed.
Corrected two claims while checking them rather than shipping them: the
suite here is 821 tests across 58 files, not the 829/59 measured with
PR #24's own tests included, and measure_pdf.py is in data/prep, not
tools. Every file:line pointer in the document was verified against the
tree.
PR #24 is named as the first thing to do. It is not merged.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Darkest-Teddy added a commit that referenced this pull request Aug 16, 2026
A second session is writing the reading-surface handoff on this same branch, and its
first line is one this document was missing: HANDOVER.md records the submission as due
16 Aug 2026, which is today. A handoff that opens with a forty-minute measurement and
says nothing about the deadline invites someone to start the EMA EPAR corpus work in
section 8 instead, which has no chance of landing. So the deadline is now above section
0, with the note that the ordering survives it either way - after the date, the EPAR
work stops being out of reach and becomes worth doing properly.
Cross-referenced the sibling both directions. It owns the reading surface, the scene and
the preflight; this one owns the numbers. Its first instruction is that PR #24 is open
against this branch and unmerged, which matters to anyone arriving here cold and is not
otherwise discoverable from this file.
Section 13 gains what CI actually enforces, which is more than the three commands this
document was quoting. The one that catches you is the manifest diff: a reported figure
that moves fails the build until the move is committed and explained. Also that this
branch has two sessions on it and the last push was rejected for exactly that - fetch
before pushing.
HANDOVER.md's index row for this file said "three times a metric looked broken". It is
four; the fourth was my own fixture labels being wrong while the model was right, which
is the one of the four most likely to repeat.
Typecheck, lint and 821 tests pass.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…gful
This branch's checks last ran against a base where npm test could not
pass, so its red X was never about the preflight. Taking the base in so
the run says something.
@AndresL230
AndresL230 changed the base branch from feat/product-in-the-atmosphere to mainAugust 17, 2026 04:24
@AndresL230
AndresL230 merged commit 94ed8e4 into mainAug 17, 2026
3 checks passed
AndresL230 added a commit that referenced this pull request Aug 17, 2026
The doc was written an hour before the merge it describes. Also note the
gap it opened: #24 went to main alone, so feat/product-in-the-atmosphere
is one merge behind again.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
AndresL230 added a commit that referenced this pull request Aug 17, 2026
main moved 42 commits under this branch - #33 (Postgres/Supabase), #24, #29,
#32 and the logo - and rewrote the three files this touches most.
THE RECONCILIATION #33 DEFERRED. `ShareStore` was written against the pattern
this branch had: a synchronous `new ShareStore(path)` beside `AuthStore` and
`InviteStore`. That layer is gone. So the store joins the new one the way the
other four did:
- `ShareStoreApi` in postgres-share.ts, where `AuthStoreApi` and
`InviteStoreApi` live, for the reason stated there: the second
implementation is what needs a name for the shape.
- `ShareStore.open(path)`, async, private constructor.
- `PostgresShareStore`, and supabase/migrations/0002_share_links.sql.
- Both branches of `buildStores`, and `Stores.shares`.
- The behaviour is ONE suite over both implementations
(test/share-store-contract.ts), as with auth and invites.
`shareSecret` deliberately stayed OUT of `buildStores`: which backing holds the
links is a storage decision, whether the deployment can publish at all is not.
THE TABLE HOLDS NO TOKEN, and the migration says so at length because that is
the feature's whole security argument - the URL is
HMAC(secret, "caseId:version"), derivable from two columns that are not secret,
so a stolen dump yields nothing. `publish` omits `version` from its upsert's
SET list on purpose: assigning it would reset a revoked case to 1 and re-mint
the token revoke had just killed. A test reads the column list back out of
information_schema, because that property fails silently.
WHAT THE CONFLICTS COST. server.ts kept main's static serving whole and its
`/api/health` route; the branch's "NO STATIC-FILE SERVING HERE" comment was
true when written and is now a lie, so it is replaced by an accurate one:
`/r/:caseId/:token` is still not served in production, a scanned QR 404s on a
deployed host, and the two decisions that has to wait on are written down
beside `staticRoot()`. Adding it here was out of scope and stayed out.
`handleReport` and `handleShare` became async; `handleReport` fetches the people
in one `auth.list()` rather than a lookup per name, because `auth.get` is
asynchronous now and `buildCaseReport` takes a synchronous `person`.
ONE THING THE MERGE HAD TO DECIDE. docs/HANDOFF-open-prs.md predicted that #30
and main each carried a provenance rule and that they would auto-merge without
conflict. They did, and both were live: `view`'s read any unrecognised actor as
`live`, the report's read only "model" as `live`. Two surfaces describing one
signed safety adjudication, disagreeing about whether a model produced it.
Closed with one module-level `sourceOf`, failing toward `stub`; every writer
passes "stub" or "model" so nothing observable changed, and the test pins that
both readers agree on a third actor neither was written for.
The postgres test fixture now applies every migration in filename order. Pinned
to 0001, it built a database that was correct on the day it was written and
silently lacked share_links.
Verified: lint, typecheck, 1267 tests with DATABASE_URL set (1179 without),
both builds, harness + metrics + golden + an unchanged verdict-manifest, e2e.
The public bundle still carries no auth code: only main's own entry chunk
matches AUTO_PASSWORD or /api/auth/login, and public.html references neither.
HANDOFF-pr34.md is deleted - the job it describes is this commit, and what
happened is recorded in docs/HANDOFF-open-prs.md and the spec.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
AndresL230 added a commit that referenced this pull request Aug 17, 2026
…, three fixes
What this session actually did, and how each claim in it was checked.
#25 reviewed from scratch, which nothing had done - its entry was a placeholder that said
so. The ten numbers are sound: every headline re-derived from the raw rows rather than
trusted, Wilson checked against the standard interval, the Ask/retrieval same-fixture
cross-check confirmed real. Three defects in the instrument, all fixed: one headline was
read from a summary field in the file that promises it never does that, one cross-check
could not fire because the results file predates the field it keys off, and a product
change to extraction retrieval rode along unmeasured by any of the ten and untested.
#27 split; the good half is prepared. Also records a third blocker nobody had noted - it
reverts SHAPE_ASK from 64000 to 16000 - and corrects "four eval scripts" to six.
#28 verified empty against current main rather than asserted: five conflicts, all in files
main has superseded. Two corrections to this document's own account of it, both from the
same mistake - reading `git diff main PR` as if it were a merge. It is not: neither merge
base contains `responseSchemaFor`, so main ADDED it and a merge keeps it.
Corrects the no-database baseline, which was wrong by 7. 1055 + 76 = 1131 is the Postgres
total; the recorded 1048 + 76 = 1124 was #33's merge-commit figure carried into a row it
had stopped belonging to. New baselines at 1c25747 measured in both environments.
Corrects the Node-20 note: CI pins node-version 22, and the real item is the action
runtime. Records the dependabot triage, the two #24 risks now fixed, the withTransaction
fix, and the .gitignore hole that let a venv symlink be committed during this session.
Adds the two things this document keeps getting wrong: origin/main moves mid-session, and
the open-PR count must come from `gh pr list` rather than from a sentence - it has now
been miscounted twice in opposite directions, the second time omitting #34.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@Darkest-Teddy@AndresL230
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Make the dev server say "npm install" instead of blaming read.tsx - #24

Merged
AndresL230 merged 2 commits into
mainfrom
fix/dev-dependency-preflight
Aug 17, 2026
Merged

Make the dev server say "npm install" instead of blaming read.tsx#24
AndresL230 merged 2 commits into
mainfrom
fix/dev-dependency-preflight

Conversation

@Darkest-Teddy

Copy link
Copy Markdown
Contributor

The report

Opening a document in Read & mark threw this:

[plugin:vite:import-analysis] Failed to resolve import "pdfjs-dist"
from "src/read.tsx". Does the file exist?

Nothing was wrong with read.tsx. pdfjs-dist is declared by apps/deliberation and recorded in package-lock.json — it was simply never installed, because that checkout's node_modules predated the merge that added it.

The overlay names a correct file, a correct line and a correct import, and asks whether a file the author never wrote exists. Every fact in it points away from the cause, so it sends you reading application source. It cost a round trip.

Why a preflight and not just an install

The trigger isn't this package. It's any npm install older than the last dependency added on any branch — which is every collaborator after every pull, forever. Installing once fixes today; this fixes the class.

tools/check-deps.mjs walks the workspaces the root manifest declares and checks that what they declare is actually on disk, hoisted or nested:

Dependencies on disk do not match the manifests:
- pdfjs-dist (4.10.38) declared by @arbiter/deliberation — not installed
Fix: npm install

Same trade dev-all.mjs already makes with --strictPort: fail loudly at startup rather than proceed into a state whose symptom names the wrong cause.

Exact pins are version-checked, ranges are not. A bare version means somebody needed a specific one — pdfjs-dist is pinned at 4.10.38 because 5.x needs Node ≥ 22.13 and crashes on 20. A stale hoisted 5.x would satisfy a directory check and then fail at runtime talking about something else, which is the exact failure mode this file exists to end. Ranges would need a semver implementation to say anything the range doesn't already say.

Wiring

  • npm run dev — in-process, before a single server is spawned
  • npm run deliberate:dev
  • npm run check:deps — standalone

Tests

A guard's own failure mode is passing while checking nothing, so the suite builds broken fixture trees rather than running against this repo. Gutting checkDeps to return [] fails four of the eight.

Two places this could have gone quietly no-op are closed:

  • the standalone-entry check uses pathToFileURL rather than interpolating argv[1] into a file:// string, which on Windows never matches — the script would have exited 0 having checked nothing
  • an unexpandable workspace pattern throws rather than skipping that workspace and still reporting ok

Verified

  • npm run dev on a tree with the package hidden: exits 1, no server spawned
  • restored: dependencies ok
  • 829 tests / 59 files, typecheck clean, lint clean

Based on feat/product-in-the-atmosphere so it can be merged into the branch being tested locally, without disturbing #22.

🤖 Generated with Claude Code

Opening a document threw:
[plugin:vite:import-analysis] Failed to resolve import "pdfjs-dist"
from "src/read.tsx". Does the file exist?
Nothing was wrong with read.tsx. `pdfjs-dist` is declared by
apps/deliberation and recorded in the lockfile; it was simply not
installed, because that node_modules predated the merge that added it.
The overlay names a correct file, a correct line and a correct import,
and asks whether a file the author never wrote exists - every fact in it
points away from the cause.
The trigger is not this package. It is any install older than the last
dependency added on any branch, which is every collaborator after every
pull, so the fix is not another install: it is a preflight that fails
where the cause is legible.
tools/check-deps.mjs walks the workspaces the root manifest declares and
checks that what they declare is on disk, hoisted or nested. Exact pins
are also version-checked, ranges are not: a bare version means somebody
needed a specific one, and pdfjs-dist is pinned at 4.10.38 because 5.x
needs node >= 22.13 and crashes on 20 - a stale hoisted 5.x would pass a
directory check and then fail at runtime talking about something else.
Ranges would need a semver implementation to say anything ranges do not
already say.
Wired into `npm run dev` in-process before any server is spawned, and
into `deliberate:dev`; also `npm run check:deps` on its own.
A guard that passes while checking nothing is the failure mode here, so
the tests build broken fixture trees rather than running against this
repo - gutting checkDeps to `return []` fails four of the eight. Two
places where this could have gone quietly no-op are handled: the
standalone-entry check uses pathToFileURL rather than interpolating
argv[1], which on Windows never matches, and an unexpandable workspace
pattern throws instead of skipping a workspace and still reporting ok.
Verified: `npm run dev` exits 1 without spawning a server on a tree
missing the package. 829 tests, typecheck and lint clean.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitaiBot commented Aug 16, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 92099a55-0191-40cb-b0de-e3e6b55e3690

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Darkest-Teddy added a commit that referenced this pull request Aug 16, 2026
Written so the next session does not have to reconstruct this from a
terminal. Sibling to HANDOFF-evaluation.md, added to this branch the same
day from another session: that one owns the numbers, this one owns Read &
mark, the environment behind it, and the dev-server preflight.
WHAT IT CARRIES. The three load-bearing decisions in the reading surface
and why each is easy to break: seats are stored rather than derived from
participant order, because that order is a sorted set and adding anybody
silently recoloured every existing highlight below them; the finding join
is sourceDocumentId and not the filename, because real data holds
"FDA NDA 211810" where the file is turalio-211810-multidiscipline.pdf and
a filename join matches nothing while looking like a rendering bug; and
blindness is enforced by the server not returning positions, so a new
endpoint outside the read guard silently ends the blind stage.
THE ONE PIECE OF THE DESIGN THAT IS NOT BUILT is written up as such - the
top-level Read entry in the rail. It is no longer blocked on the scene,
which now exists, and what it actually needs is a launcher route, because
a NAV entry has no caseId to bind to.
The seat palette question is left as a decision for a human rather than
settled quietly in code. Re-fitting the seats to this branch's blue wedge
separates them mostly by lightness, and 3 to 5 are close at badge size
with six people on a case. Three ways out, all design-system calls.
AN INDEX IN HANDOVER.md, because there were three branch handoffs and
nothing pointed at any of them. HANDOVER.md is the file somebody opens
first and it is only updated at merge, so work in flight was reachable
only by knowing it existed.
Corrected two claims while checking them rather than shipping them: the
suite here is 821 tests across 58 files, not the 829/59 measured with
PR #24's own tests included, and measure_pdf.py is in data/prep, not
tools. Every file:line pointer in the document was verified against the
tree.
PR #24 is named as the first thing to do. It is not merged.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Darkest-Teddy added a commit that referenced this pull request Aug 16, 2026
A second session is writing the reading-surface handoff on this same branch, and its
first line is one this document was missing: HANDOVER.md records the submission as due
16 Aug 2026, which is today. A handoff that opens with a forty-minute measurement and
says nothing about the deadline invites someone to start the EMA EPAR corpus work in
section 8 instead, which has no chance of landing. So the deadline is now above section
0, with the note that the ordering survives it either way - after the date, the EPAR
work stops being out of reach and becomes worth doing properly.
Cross-referenced the sibling both directions. It owns the reading surface, the scene and
the preflight; this one owns the numbers. Its first instruction is that PR #24 is open
against this branch and unmerged, which matters to anyone arriving here cold and is not
otherwise discoverable from this file.
Section 13 gains what CI actually enforces, which is more than the three commands this
document was quoting. The one that catches you is the manifest diff: a reported figure
that moves fails the build until the move is committed and explained. Also that this
branch has two sessions on it and the last push was rejected for exactly that - fetch
before pushing.
HANDOVER.md's index row for this file said "three times a metric looked broken". It is
four; the fourth was my own fixture labels being wrong while the model was right, which
is the one of the four most likely to repeat.
Typecheck, lint and 821 tests pass.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…gful
This branch's checks last ran against a base where npm test could not
pass, so its red X was never about the preflight. Taking the base in so
the run says something.
@AndresL230
AndresL230 changed the base branch from feat/product-in-the-atmosphere to mainAugust 17, 2026 04:24
@AndresL230
AndresL230 merged commit 94ed8e4 into mainAug 17, 2026
3 checks passed
AndresL230 added a commit that referenced this pull request Aug 17, 2026
The doc was written an hour before the merge it describes. Also note the
gap it opened: #24 went to main alone, so feat/product-in-the-atmosphere
is one merge behind again.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
AndresL230 added a commit that referenced this pull request Aug 17, 2026
main moved 42 commits under this branch - #33 (Postgres/Supabase), #24, #29,
#32 and the logo - and rewrote the three files this touches most.
THE RECONCILIATION #33 DEFERRED. `ShareStore` was written against the pattern
this branch had: a synchronous `new ShareStore(path)` beside `AuthStore` and
`InviteStore`. That layer is gone. So the store joins the new one the way the
other four did:
- `ShareStoreApi` in postgres-share.ts, where `AuthStoreApi` and
`InviteStoreApi` live, for the reason stated there: the second
implementation is what needs a name for the shape.
- `ShareStore.open(path)`, async, private constructor.
- `PostgresShareStore`, and supabase/migrations/0002_share_links.sql.
- Both branches of `buildStores`, and `Stores.shares`.
- The behaviour is ONE suite over both implementations
(test/share-store-contract.ts), as with auth and invites.
`shareSecret` deliberately stayed OUT of `buildStores`: which backing holds the
links is a storage decision, whether the deployment can publish at all is not.
THE TABLE HOLDS NO TOKEN, and the migration says so at length because that is
the feature's whole security argument - the URL is
HMAC(secret, "caseId:version"), derivable from two columns that are not secret,
so a stolen dump yields nothing. `publish` omits `version` from its upsert's
SET list on purpose: assigning it would reset a revoked case to 1 and re-mint
the token revoke had just killed. A test reads the column list back out of
information_schema, because that property fails silently.
WHAT THE CONFLICTS COST. server.ts kept main's static serving whole and its
`/api/health` route; the branch's "NO STATIC-FILE SERVING HERE" comment was
true when written and is now a lie, so it is replaced by an accurate one:
`/r/:caseId/:token` is still not served in production, a scanned QR 404s on a
deployed host, and the two decisions that has to wait on are written down
beside `staticRoot()`. Adding it here was out of scope and stayed out.
`handleReport` and `handleShare` became async; `handleReport` fetches the people
in one `auth.list()` rather than a lookup per name, because `auth.get` is
asynchronous now and `buildCaseReport` takes a synchronous `person`.
ONE THING THE MERGE HAD TO DECIDE. docs/HANDOFF-open-prs.md predicted that #30
and main each carried a provenance rule and that they would auto-merge without
conflict. They did, and both were live: `view`'s read any unrecognised actor as
`live`, the report's read only "model" as `live`. Two surfaces describing one
signed safety adjudication, disagreeing about whether a model produced it.
Closed with one module-level `sourceOf`, failing toward `stub`; every writer
passes "stub" or "model" so nothing observable changed, and the test pins that
both readers agree on a third actor neither was written for.
The postgres test fixture now applies every migration in filename order. Pinned
to 0001, it built a database that was correct on the day it was written and
silently lacked share_links.
Verified: lint, typecheck, 1267 tests with DATABASE_URL set (1179 without),
both builds, harness + metrics + golden + an unchanged verdict-manifest, e2e.
The public bundle still carries no auth code: only main's own entry chunk
matches AUTO_PASSWORD or /api/auth/login, and public.html references neither.
HANDOFF-pr34.md is deleted - the job it describes is this commit, and what
happened is recorded in docs/HANDOFF-open-prs.md and the spec.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
AndresL230 added a commit that referenced this pull request Aug 17, 2026
…, three fixes
What this session actually did, and how each claim in it was checked.
#25 reviewed from scratch, which nothing had done - its entry was a placeholder that said
so. The ten numbers are sound: every headline re-derived from the raw rows rather than
trusted, Wilson checked against the standard interval, the Ask/retrieval same-fixture
cross-check confirmed real. Three defects in the instrument, all fixed: one headline was
read from a summary field in the file that promises it never does that, one cross-check
could not fire because the results file predates the field it keys off, and a product
change to extraction retrieval rode along unmeasured by any of the ten and untested.
#27 split; the good half is prepared. Also records a third blocker nobody had noted - it
reverts SHAPE_ASK from 64000 to 16000 - and corrects "four eval scripts" to six.
#28 verified empty against current main rather than asserted: five conflicts, all in files
main has superseded. Two corrections to this document's own account of it, both from the
same mistake - reading `git diff main PR` as if it were a merge. It is not: neither merge
base contains `responseSchemaFor`, so main ADDED it and a merge keeps it.
Corrects the no-database baseline, which was wrong by 7. 1055 + 76 = 1131 is the Postgres
total; the recorded 1048 + 76 = 1124 was #33's merge-commit figure carried into a row it
had stopped belonging to. New baselines at 1c25747 measured in both environments.
Corrects the Node-20 note: CI pins node-version 22, and the real item is the action
runtime. Records the dependabot triage, the two #24 risks now fixed, the withTransaction
fix, and the .gitignore hole that let a venv symlink be committed during this session.
Adds the two things this document keeps getting wrong: origin/main moves mid-session, and
the open-PR count must come from `gh pr list` rather than from a sentence - it has now
been miscounted twice in opposite directions, the second time omitting #34.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@Darkest-Teddy@AndresL230
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Make the dev server say "npm install" instead of blaming read.tsx - #24

Merged
AndresL230 merged 2 commits into
mainfrom
fix/dev-dependency-preflight
Aug 17, 2026
Merged

Make the dev server say "npm install" instead of blaming read.tsx#24
AndresL230 merged 2 commits into
mainfrom
fix/dev-dependency-preflight

Conversation

@Darkest-Teddy

Copy link
Copy Markdown
Contributor

The report

Opening a document in Read & mark threw this:

[plugin:vite:import-analysis] Failed to resolve import "pdfjs-dist"
from "src/read.tsx". Does the file exist?

Nothing was wrong with read.tsx. pdfjs-dist is declared by apps/deliberation and recorded in package-lock.json — it was simply never installed, because that checkout's node_modules predated the merge that added it.

The overlay names a correct file, a correct line and a correct import, and asks whether a file the author never wrote exists. Every fact in it points away from the cause, so it sends you reading application source. It cost a round trip.

Why a preflight and not just an install

The trigger isn't this package. It's any npm install older than the last dependency added on any branch — which is every collaborator after every pull, forever. Installing once fixes today; this fixes the class.

tools/check-deps.mjs walks the workspaces the root manifest declares and checks that what they declare is actually on disk, hoisted or nested:

Dependencies on disk do not match the manifests:
- pdfjs-dist (4.10.38) declared by @arbiter/deliberation — not installed
Fix: npm install

Same trade dev-all.mjs already makes with --strictPort: fail loudly at startup rather than proceed into a state whose symptom names the wrong cause.

Exact pins are version-checked, ranges are not. A bare version means somebody needed a specific one — pdfjs-dist is pinned at 4.10.38 because 5.x needs Node ≥ 22.13 and crashes on 20. A stale hoisted 5.x would satisfy a directory check and then fail at runtime talking about something else, which is the exact failure mode this file exists to end. Ranges would need a semver implementation to say anything the range doesn't already say.

Wiring

  • npm run dev — in-process, before a single server is spawned
  • npm run deliberate:dev
  • npm run check:deps — standalone

Tests

A guard's own failure mode is passing while checking nothing, so the suite builds broken fixture trees rather than running against this repo. Gutting checkDeps to return [] fails four of the eight.

Two places this could have gone quietly no-op are closed:

  • the standalone-entry check uses pathToFileURL rather than interpolating argv[1] into a file:// string, which on Windows never matches — the script would have exited 0 having checked nothing
  • an unexpandable workspace pattern throws rather than skipping that workspace and still reporting ok

Verified

  • npm run dev on a tree with the package hidden: exits 1, no server spawned
  • restored: dependencies ok
  • 829 tests / 59 files, typecheck clean, lint clean

Based on feat/product-in-the-atmosphere so it can be merged into the branch being tested locally, without disturbing #22.

🤖 Generated with Claude Code

Opening a document threw:
[plugin:vite:import-analysis] Failed to resolve import "pdfjs-dist"
from "src/read.tsx". Does the file exist?
Nothing was wrong with read.tsx. `pdfjs-dist` is declared by
apps/deliberation and recorded in the lockfile; it was simply not
installed, because that node_modules predated the merge that added it.
The overlay names a correct file, a correct line and a correct import,
and asks whether a file the author never wrote exists - every fact in it
points away from the cause.
The trigger is not this package. It is any install older than the last
dependency added on any branch, which is every collaborator after every
pull, so the fix is not another install: it is a preflight that fails
where the cause is legible.
tools/check-deps.mjs walks the workspaces the root manifest declares and
checks that what they declare is on disk, hoisted or nested. Exact pins
are also version-checked, ranges are not: a bare version means somebody
needed a specific one, and pdfjs-dist is pinned at 4.10.38 because 5.x
needs node >= 22.13 and crashes on 20 - a stale hoisted 5.x would pass a
directory check and then fail at runtime talking about something else.
Ranges would need a semver implementation to say anything ranges do not
already say.
Wired into `npm run dev` in-process before any server is spawned, and
into `deliberate:dev`; also `npm run check:deps` on its own.
A guard that passes while checking nothing is the failure mode here, so
the tests build broken fixture trees rather than running against this
repo - gutting checkDeps to `return []` fails four of the eight. Two
places where this could have gone quietly no-op are handled: the
standalone-entry check uses pathToFileURL rather than interpolating
argv[1], which on Windows never matches, and an unexpandable workspace
pattern throws instead of skipping a workspace and still reporting ok.
Verified: `npm run dev` exits 1 without spawning a server on a tree
missing the package. 829 tests, typecheck and lint clean.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitaiBot commented Aug 16, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 92099a55-0191-40cb-b0de-e3e6b55e3690

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Darkest-Teddy added a commit that referenced this pull request Aug 16, 2026
Written so the next session does not have to reconstruct this from a
terminal. Sibling to HANDOFF-evaluation.md, added to this branch the same
day from another session: that one owns the numbers, this one owns Read &
mark, the environment behind it, and the dev-server preflight.
WHAT IT CARRIES. The three load-bearing decisions in the reading surface
and why each is easy to break: seats are stored rather than derived from
participant order, because that order is a sorted set and adding anybody
silently recoloured every existing highlight below them; the finding join
is sourceDocumentId and not the filename, because real data holds
"FDA NDA 211810" where the file is turalio-211810-multidiscipline.pdf and
a filename join matches nothing while looking like a rendering bug; and
blindness is enforced by the server not returning positions, so a new
endpoint outside the read guard silently ends the blind stage.
THE ONE PIECE OF THE DESIGN THAT IS NOT BUILT is written up as such - the
top-level Read entry in the rail. It is no longer blocked on the scene,
which now exists, and what it actually needs is a launcher route, because
a NAV entry has no caseId to bind to.
The seat palette question is left as a decision for a human rather than
settled quietly in code. Re-fitting the seats to this branch's blue wedge
separates them mostly by lightness, and 3 to 5 are close at badge size
with six people on a case. Three ways out, all design-system calls.
AN INDEX IN HANDOVER.md, because there were three branch handoffs and
nothing pointed at any of them. HANDOVER.md is the file somebody opens
first and it is only updated at merge, so work in flight was reachable
only by knowing it existed.
Corrected two claims while checking them rather than shipping them: the
suite here is 821 tests across 58 files, not the 829/59 measured with
PR #24's own tests included, and measure_pdf.py is in data/prep, not
tools. Every file:line pointer in the document was verified against the
tree.
PR #24 is named as the first thing to do. It is not merged.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Darkest-Teddy added a commit that referenced this pull request Aug 16, 2026
A second session is writing the reading-surface handoff on this same branch, and its
first line is one this document was missing: HANDOVER.md records the submission as due
16 Aug 2026, which is today. A handoff that opens with a forty-minute measurement and
says nothing about the deadline invites someone to start the EMA EPAR corpus work in
section 8 instead, which has no chance of landing. So the deadline is now above section
0, with the note that the ordering survives it either way - after the date, the EPAR
work stops being out of reach and becomes worth doing properly.
Cross-referenced the sibling both directions. It owns the reading surface, the scene and
the preflight; this one owns the numbers. Its first instruction is that PR #24 is open
against this branch and unmerged, which matters to anyone arriving here cold and is not
otherwise discoverable from this file.
Section 13 gains what CI actually enforces, which is more than the three commands this
document was quoting. The one that catches you is the manifest diff: a reported figure
that moves fails the build until the move is committed and explained. Also that this
branch has two sessions on it and the last push was rejected for exactly that - fetch
before pushing.
HANDOVER.md's index row for this file said "three times a metric looked broken". It is
four; the fourth was my own fixture labels being wrong while the model was right, which
is the one of the four most likely to repeat.
Typecheck, lint and 821 tests pass.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…gful
This branch's checks last ran against a base where npm test could not
pass, so its red X was never about the preflight. Taking the base in so
the run says something.
@AndresL230
AndresL230 changed the base branch from feat/product-in-the-atmosphere to mainAugust 17, 2026 04:24
@AndresL230
AndresL230 merged commit 94ed8e4 into mainAug 17, 2026
3 checks passed
AndresL230 added a commit that referenced this pull request Aug 17, 2026
The doc was written an hour before the merge it describes. Also note the
gap it opened: #24 went to main alone, so feat/product-in-the-atmosphere
is one merge behind again.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
AndresL230 added a commit that referenced this pull request Aug 17, 2026
main moved 42 commits under this branch - #33 (Postgres/Supabase), #24, #29,
#32 and the logo - and rewrote the three files this touches most.
THE RECONCILIATION #33 DEFERRED. `ShareStore` was written against the pattern
this branch had: a synchronous `new ShareStore(path)` beside `AuthStore` and
`InviteStore`. That layer is gone. So the store joins the new one the way the
other four did:
- `ShareStoreApi` in postgres-share.ts, where `AuthStoreApi` and
`InviteStoreApi` live, for the reason stated there: the second
implementation is what needs a name for the shape.
- `ShareStore.open(path)`, async, private constructor.
- `PostgresShareStore`, and supabase/migrations/0002_share_links.sql.
- Both branches of `buildStores`, and `Stores.shares`.
- The behaviour is ONE suite over both implementations
(test/share-store-contract.ts), as with auth and invites.
`shareSecret` deliberately stayed OUT of `buildStores`: which backing holds the
links is a storage decision, whether the deployment can publish at all is not.
THE TABLE HOLDS NO TOKEN, and the migration says so at length because that is
the feature's whole security argument - the URL is
HMAC(secret, "caseId:version"), derivable from two columns that are not secret,
so a stolen dump yields nothing. `publish` omits `version` from its upsert's
SET list on purpose: assigning it would reset a revoked case to 1 and re-mint
the token revoke had just killed. A test reads the column list back out of
information_schema, because that property fails silently.
WHAT THE CONFLICTS COST. server.ts kept main's static serving whole and its
`/api/health` route; the branch's "NO STATIC-FILE SERVING HERE" comment was
true when written and is now a lie, so it is replaced by an accurate one:
`/r/:caseId/:token` is still not served in production, a scanned QR 404s on a
deployed host, and the two decisions that has to wait on are written down
beside `staticRoot()`. Adding it here was out of scope and stayed out.
`handleReport` and `handleShare` became async; `handleReport` fetches the people
in one `auth.list()` rather than a lookup per name, because `auth.get` is
asynchronous now and `buildCaseReport` takes a synchronous `person`.
ONE THING THE MERGE HAD TO DECIDE. docs/HANDOFF-open-prs.md predicted that #30
and main each carried a provenance rule and that they would auto-merge without
conflict. They did, and both were live: `view`'s read any unrecognised actor as
`live`, the report's read only "model" as `live`. Two surfaces describing one
signed safety adjudication, disagreeing about whether a model produced it.
Closed with one module-level `sourceOf`, failing toward `stub`; every writer
passes "stub" or "model" so nothing observable changed, and the test pins that
both readers agree on a third actor neither was written for.
The postgres test fixture now applies every migration in filename order. Pinned
to 0001, it built a database that was correct on the day it was written and
silently lacked share_links.
Verified: lint, typecheck, 1267 tests with DATABASE_URL set (1179 without),
both builds, harness + metrics + golden + an unchanged verdict-manifest, e2e.
The public bundle still carries no auth code: only main's own entry chunk
matches AUTO_PASSWORD or /api/auth/login, and public.html references neither.
HANDOFF-pr34.md is deleted - the job it describes is this commit, and what
happened is recorded in docs/HANDOFF-open-prs.md and the spec.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
AndresL230 added a commit that referenced this pull request Aug 17, 2026
…, three fixes
What this session actually did, and how each claim in it was checked.
#25 reviewed from scratch, which nothing had done - its entry was a placeholder that said
so. The ten numbers are sound: every headline re-derived from the raw rows rather than
trusted, Wilson checked against the standard interval, the Ask/retrieval same-fixture
cross-check confirmed real. Three defects in the instrument, all fixed: one headline was
read from a summary field in the file that promises it never does that, one cross-check
could not fire because the results file predates the field it keys off, and a product
change to extraction retrieval rode along unmeasured by any of the ten and untested.
#27 split; the good half is prepared. Also records a third blocker nobody had noted - it
reverts SHAPE_ASK from 64000 to 16000 - and corrects "four eval scripts" to six.
#28 verified empty against current main rather than asserted: five conflicts, all in files
main has superseded. Two corrections to this document's own account of it, both from the
same mistake - reading `git diff main PR` as if it were a merge. It is not: neither merge
base contains `responseSchemaFor`, so main ADDED it and a merge keeps it.
Corrects the no-database baseline, which was wrong by 7. 1055 + 76 = 1131 is the Postgres
total; the recorded 1048 + 76 = 1124 was #33's merge-commit figure carried into a row it
had stopped belonging to. New baselines at 1c25747 measured in both environments.
Corrects the Node-20 note: CI pins node-version 22, and the real item is the action
runtime. Records the dependabot triage, the two #24 risks now fixed, the withTransaction
fix, and the .gitignore hole that let a venv symlink be committed during this session.
Adds the two things this document keeps getting wrong: origin/main moves mid-session, and
the open-PR count must come from `gh pr list` rather than from a sentence - it has now
been miscounted twice in opposite directions, the second time omitting #34.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@Darkest-Teddy@AndresL230
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Make the dev server say "npm install" instead of blaming read.tsx - #24

Merged
AndresL230 merged 2 commits into
mainfrom
fix/dev-dependency-preflight
Aug 17, 2026
Merged

Make the dev server say "npm install" instead of blaming read.tsx#24
AndresL230 merged 2 commits into
mainfrom
fix/dev-dependency-preflight

Conversation

@Darkest-Teddy

Copy link
Copy Markdown
Contributor

The report

Opening a document in Read & mark threw this:

[plugin:vite:import-analysis] Failed to resolve import "pdfjs-dist"
from "src/read.tsx". Does the file exist?

Nothing was wrong with read.tsx. pdfjs-dist is declared by apps/deliberation and recorded in package-lock.json — it was simply never installed, because that checkout's node_modules predated the merge that added it.

The overlay names a correct file, a correct line and a correct import, and asks whether a file the author never wrote exists. Every fact in it points away from the cause, so it sends you reading application source. It cost a round trip.

Why a preflight and not just an install

The trigger isn't this package. It's any npm install older than the last dependency added on any branch — which is every collaborator after every pull, forever. Installing once fixes today; this fixes the class.

tools/check-deps.mjs walks the workspaces the root manifest declares and checks that what they declare is actually on disk, hoisted or nested:

Dependencies on disk do not match the manifests:
- pdfjs-dist (4.10.38) declared by @arbiter/deliberation — not installed
Fix: npm install

Same trade dev-all.mjs already makes with --strictPort: fail loudly at startup rather than proceed into a state whose symptom names the wrong cause.

Exact pins are version-checked, ranges are not. A bare version means somebody needed a specific one — pdfjs-dist is pinned at 4.10.38 because 5.x needs Node ≥ 22.13 and crashes on 20. A stale hoisted 5.x would satisfy a directory check and then fail at runtime talking about something else, which is the exact failure mode this file exists to end. Ranges would need a semver implementation to say anything the range doesn't already say.

Wiring

  • npm run dev — in-process, before a single server is spawned
  • npm run deliberate:dev
  • npm run check:deps — standalone

Tests

A guard's own failure mode is passing while checking nothing, so the suite builds broken fixture trees rather than running against this repo. Gutting checkDeps to return [] fails four of the eight.

Two places this could have gone quietly no-op are closed:

  • the standalone-entry check uses pathToFileURL rather than interpolating argv[1] into a file:// string, which on Windows never matches — the script would have exited 0 having checked nothing
  • an unexpandable workspace pattern throws rather than skipping that workspace and still reporting ok

Verified

  • npm run dev on a tree with the package hidden: exits 1, no server spawned
  • restored: dependencies ok
  • 829 tests / 59 files, typecheck clean, lint clean

Based on feat/product-in-the-atmosphere so it can be merged into the branch being tested locally, without disturbing #22.

🤖 Generated with Claude Code

Opening a document threw:
[plugin:vite:import-analysis] Failed to resolve import "pdfjs-dist"
from "src/read.tsx". Does the file exist?
Nothing was wrong with read.tsx. `pdfjs-dist` is declared by
apps/deliberation and recorded in the lockfile; it was simply not
installed, because that node_modules predated the merge that added it.
The overlay names a correct file, a correct line and a correct import,
and asks whether a file the author never wrote exists - every fact in it
points away from the cause.
The trigger is not this package. It is any install older than the last
dependency added on any branch, which is every collaborator after every
pull, so the fix is not another install: it is a preflight that fails
where the cause is legible.
tools/check-deps.mjs walks the workspaces the root manifest declares and
checks that what they declare is on disk, hoisted or nested. Exact pins
are also version-checked, ranges are not: a bare version means somebody
needed a specific one, and pdfjs-dist is pinned at 4.10.38 because 5.x
needs node >= 22.13 and crashes on 20 - a stale hoisted 5.x would pass a
directory check and then fail at runtime talking about something else.
Ranges would need a semver implementation to say anything ranges do not
already say.
Wired into `npm run dev` in-process before any server is spawned, and
into `deliberate:dev`; also `npm run check:deps` on its own.
A guard that passes while checking nothing is the failure mode here, so
the tests build broken fixture trees rather than running against this
repo - gutting checkDeps to `return []` fails four of the eight. Two
places where this could have gone quietly no-op are handled: the
standalone-entry check uses pathToFileURL rather than interpolating
argv[1], which on Windows never matches, and an unexpandable workspace
pattern throws instead of skipping a workspace and still reporting ok.
Verified: `npm run dev` exits 1 without spawning a server on a tree
missing the package. 829 tests, typecheck and lint clean.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitaiBot commented Aug 16, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 92099a55-0191-40cb-b0de-e3e6b55e3690

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Darkest-Teddy added a commit that referenced this pull request Aug 16, 2026
Written so the next session does not have to reconstruct this from a
terminal. Sibling to HANDOFF-evaluation.md, added to this branch the same
day from another session: that one owns the numbers, this one owns Read &
mark, the environment behind it, and the dev-server preflight.
WHAT IT CARRIES. The three load-bearing decisions in the reading surface
and why each is easy to break: seats are stored rather than derived from
participant order, because that order is a sorted set and adding anybody
silently recoloured every existing highlight below them; the finding join
is sourceDocumentId and not the filename, because real data holds
"FDA NDA 211810" where the file is turalio-211810-multidiscipline.pdf and
a filename join matches nothing while looking like a rendering bug; and
blindness is enforced by the server not returning positions, so a new
endpoint outside the read guard silently ends the blind stage.
THE ONE PIECE OF THE DESIGN THAT IS NOT BUILT is written up as such - the
top-level Read entry in the rail. It is no longer blocked on the scene,
which now exists, and what it actually needs is a launcher route, because
a NAV entry has no caseId to bind to.
The seat palette question is left as a decision for a human rather than
settled quietly in code. Re-fitting the seats to this branch's blue wedge
separates them mostly by lightness, and 3 to 5 are close at badge size
with six people on a case. Three ways out, all design-system calls.
AN INDEX IN HANDOVER.md, because there were three branch handoffs and
nothing pointed at any of them. HANDOVER.md is the file somebody opens
first and it is only updated at merge, so work in flight was reachable
only by knowing it existed.
Corrected two claims while checking them rather than shipping them: the
suite here is 821 tests across 58 files, not the 829/59 measured with
PR #24's own tests included, and measure_pdf.py is in data/prep, not
tools. Every file:line pointer in the document was verified against the
tree.
PR #24 is named as the first thing to do. It is not merged.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Darkest-Teddy added a commit that referenced this pull request Aug 16, 2026
A second session is writing the reading-surface handoff on this same branch, and its
first line is one this document was missing: HANDOVER.md records the submission as due
16 Aug 2026, which is today. A handoff that opens with a forty-minute measurement and
says nothing about the deadline invites someone to start the EMA EPAR corpus work in
section 8 instead, which has no chance of landing. So the deadline is now above section
0, with the note that the ordering survives it either way - after the date, the EPAR
work stops being out of reach and becomes worth doing properly.
Cross-referenced the sibling both directions. It owns the reading surface, the scene and
the preflight; this one owns the numbers. Its first instruction is that PR #24 is open
against this branch and unmerged, which matters to anyone arriving here cold and is not
otherwise discoverable from this file.
Section 13 gains what CI actually enforces, which is more than the three commands this
document was quoting. The one that catches you is the manifest diff: a reported figure
that moves fails the build until the move is committed and explained. Also that this
branch has two sessions on it and the last push was rejected for exactly that - fetch
before pushing.
HANDOVER.md's index row for this file said "three times a metric looked broken". It is
four; the fourth was my own fixture labels being wrong while the model was right, which
is the one of the four most likely to repeat.
Typecheck, lint and 821 tests pass.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…gful
This branch's checks last ran against a base where npm test could not
pass, so its red X was never about the preflight. Taking the base in so
the run says something.
@AndresL230
AndresL230 changed the base branch from feat/product-in-the-atmosphere to mainAugust 17, 2026 04:24
@AndresL230
AndresL230 merged commit 94ed8e4 into mainAug 17, 2026
3 checks passed
AndresL230 added a commit that referenced this pull request Aug 17, 2026
The doc was written an hour before the merge it describes. Also note the
gap it opened: #24 went to main alone, so feat/product-in-the-atmosphere
is one merge behind again.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
AndresL230 added a commit that referenced this pull request Aug 17, 2026
main moved 42 commits under this branch - #33 (Postgres/Supabase), #24, #29,
#32 and the logo - and rewrote the three files this touches most.
THE RECONCILIATION #33 DEFERRED. `ShareStore` was written against the pattern
this branch had: a synchronous `new ShareStore(path)` beside `AuthStore` and
`InviteStore`. That layer is gone. So the store joins the new one the way the
other four did:
- `ShareStoreApi` in postgres-share.ts, where `AuthStoreApi` and
`InviteStoreApi` live, for the reason stated there: the second
implementation is what needs a name for the shape.
- `ShareStore.open(path)`, async, private constructor.
- `PostgresShareStore`, and supabase/migrations/0002_share_links.sql.
- Both branches of `buildStores`, and `Stores.shares`.
- The behaviour is ONE suite over both implementations
(test/share-store-contract.ts), as with auth and invites.
`shareSecret` deliberately stayed OUT of `buildStores`: which backing holds the
links is a storage decision, whether the deployment can publish at all is not.
THE TABLE HOLDS NO TOKEN, and the migration says so at length because that is
the feature's whole security argument - the URL is
HMAC(secret, "caseId:version"), derivable from two columns that are not secret,
so a stolen dump yields nothing. `publish` omits `version` from its upsert's
SET list on purpose: assigning it would reset a revoked case to 1 and re-mint
the token revoke had just killed. A test reads the column list back out of
information_schema, because that property fails silently.
WHAT THE CONFLICTS COST. server.ts kept main's static serving whole and its
`/api/health` route; the branch's "NO STATIC-FILE SERVING HERE" comment was
true when written and is now a lie, so it is replaced by an accurate one:
`/r/:caseId/:token` is still not served in production, a scanned QR 404s on a
deployed host, and the two decisions that has to wait on are written down
beside `staticRoot()`. Adding it here was out of scope and stayed out.
`handleReport` and `handleShare` became async; `handleReport` fetches the people
in one `auth.list()` rather than a lookup per name, because `auth.get` is
asynchronous now and `buildCaseReport` takes a synchronous `person`.
ONE THING THE MERGE HAD TO DECIDE. docs/HANDOFF-open-prs.md predicted that #30
and main each carried a provenance rule and that they would auto-merge without
conflict. They did, and both were live: `view`'s read any unrecognised actor as
`live`, the report's read only "model" as `live`. Two surfaces describing one
signed safety adjudication, disagreeing about whether a model produced it.
Closed with one module-level `sourceOf`, failing toward `stub`; every writer
passes "stub" or "model" so nothing observable changed, and the test pins that
both readers agree on a third actor neither was written for.
The postgres test fixture now applies every migration in filename order. Pinned
to 0001, it built a database that was correct on the day it was written and
silently lacked share_links.
Verified: lint, typecheck, 1267 tests with DATABASE_URL set (1179 without),
both builds, harness + metrics + golden + an unchanged verdict-manifest, e2e.
The public bundle still carries no auth code: only main's own entry chunk
matches AUTO_PASSWORD or /api/auth/login, and public.html references neither.
HANDOFF-pr34.md is deleted - the job it describes is this commit, and what
happened is recorded in docs/HANDOFF-open-prs.md and the spec.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
AndresL230 added a commit that referenced this pull request Aug 17, 2026
…, three fixes
What this session actually did, and how each claim in it was checked.
#25 reviewed from scratch, which nothing had done - its entry was a placeholder that said
so. The ten numbers are sound: every headline re-derived from the raw rows rather than
trusted, Wilson checked against the standard interval, the Ask/retrieval same-fixture
cross-check confirmed real. Three defects in the instrument, all fixed: one headline was
read from a summary field in the file that promises it never does that, one cross-check
could not fire because the results file predates the field it keys off, and a product
change to extraction retrieval rode along unmeasured by any of the ten and untested.
#27 split; the good half is prepared. Also records a third blocker nobody had noted - it
reverts SHAPE_ASK from 64000 to 16000 - and corrects "four eval scripts" to six.
#28 verified empty against current main rather than asserted: five conflicts, all in files
main has superseded. Two corrections to this document's own account of it, both from the
same mistake - reading `git diff main PR` as if it were a merge. It is not: neither merge
base contains `responseSchemaFor`, so main ADDED it and a merge keeps it.
Corrects the no-database baseline, which was wrong by 7. 1055 + 76 = 1131 is the Postgres
total; the recorded 1048 + 76 = 1124 was #33's merge-commit figure carried into a row it
had stopped belonging to. New baselines at 1c25747 measured in both environments.
Corrects the Node-20 note: CI pins node-version 22, and the real item is the action
runtime. Records the dependabot triage, the two #24 risks now fixed, the withTransaction
fix, and the .gitignore hole that let a venv symlink be committed during this session.
Adds the two things this document keeps getting wrong: origin/main moves mid-session, and
the open-PR count must come from `gh pr list` rather than from a sentence - it has now
been miscounted twice in opposite directions, the second time omitting #34.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@Darkest-Teddy@AndresL230
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Make the dev server say "npm install" instead of blaming read.tsx - #24

Merged
AndresL230 merged 2 commits into
mainfrom
fix/dev-dependency-preflight
Aug 17, 2026
Merged

Make the dev server say "npm install" instead of blaming read.tsx#24
AndresL230 merged 2 commits into
mainfrom
fix/dev-dependency-preflight

Conversation

@Darkest-Teddy

Copy link
Copy Markdown
Contributor

The report

Opening a document in Read & mark threw this:

[plugin:vite:import-analysis] Failed to resolve import "pdfjs-dist"
from "src/read.tsx". Does the file exist?

Nothing was wrong with read.tsx. pdfjs-dist is declared by apps/deliberation and recorded in package-lock.json — it was simply never installed, because that checkout's node_modules predated the merge that added it.

The overlay names a correct file, a correct line and a correct import, and asks whether a file the author never wrote exists. Every fact in it points away from the cause, so it sends you reading application source. It cost a round trip.

Why a preflight and not just an install

The trigger isn't this package. It's any npm install older than the last dependency added on any branch — which is every collaborator after every pull, forever. Installing once fixes today; this fixes the class.

tools/check-deps.mjs walks the workspaces the root manifest declares and checks that what they declare is actually on disk, hoisted or nested:

Dependencies on disk do not match the manifests:
- pdfjs-dist (4.10.38) declared by @arbiter/deliberation — not installed
Fix: npm install

Same trade dev-all.mjs already makes with --strictPort: fail loudly at startup rather than proceed into a state whose symptom names the wrong cause.

Exact pins are version-checked, ranges are not. A bare version means somebody needed a specific one — pdfjs-dist is pinned at 4.10.38 because 5.x needs Node ≥ 22.13 and crashes on 20. A stale hoisted 5.x would satisfy a directory check and then fail at runtime talking about something else, which is the exact failure mode this file exists to end. Ranges would need a semver implementation to say anything the range doesn't already say.

Wiring

  • npm run dev — in-process, before a single server is spawned
  • npm run deliberate:dev
  • npm run check:deps — standalone

Tests

A guard's own failure mode is passing while checking nothing, so the suite builds broken fixture trees rather than running against this repo. Gutting checkDeps to return [] fails four of the eight.

Two places this could have gone quietly no-op are closed:

  • the standalone-entry check uses pathToFileURL rather than interpolating argv[1] into a file:// string, which on Windows never matches — the script would have exited 0 having checked nothing
  • an unexpandable workspace pattern throws rather than skipping that workspace and still reporting ok

Verified

  • npm run dev on a tree with the package hidden: exits 1, no server spawned
  • restored: dependencies ok
  • 829 tests / 59 files, typecheck clean, lint clean

Based on feat/product-in-the-atmosphere so it can be merged into the branch being tested locally, without disturbing #22.

🤖 Generated with Claude Code

Opening a document threw:
[plugin:vite:import-analysis] Failed to resolve import "pdfjs-dist"
from "src/read.tsx". Does the file exist?
Nothing was wrong with read.tsx. `pdfjs-dist` is declared by
apps/deliberation and recorded in the lockfile; it was simply not
installed, because that node_modules predated the merge that added it.
The overlay names a correct file, a correct line and a correct import,
and asks whether a file the author never wrote exists - every fact in it
points away from the cause.
The trigger is not this package. It is any install older than the last
dependency added on any branch, which is every collaborator after every
pull, so the fix is not another install: it is a preflight that fails
where the cause is legible.
tools/check-deps.mjs walks the workspaces the root manifest declares and
checks that what they declare is on disk, hoisted or nested. Exact pins
are also version-checked, ranges are not: a bare version means somebody
needed a specific one, and pdfjs-dist is pinned at 4.10.38 because 5.x
needs node >= 22.13 and crashes on 20 - a stale hoisted 5.x would pass a
directory check and then fail at runtime talking about something else.
Ranges would need a semver implementation to say anything ranges do not
already say.
Wired into `npm run dev` in-process before any server is spawned, and
into `deliberate:dev`; also `npm run check:deps` on its own.
A guard that passes while checking nothing is the failure mode here, so
the tests build broken fixture trees rather than running against this
repo - gutting checkDeps to `return []` fails four of the eight. Two
places where this could have gone quietly no-op are handled: the
standalone-entry check uses pathToFileURL rather than interpolating
argv[1], which on Windows never matches, and an unexpandable workspace
pattern throws instead of skipping a workspace and still reporting ok.
Verified: `npm run dev` exits 1 without spawning a server on a tree
missing the package. 829 tests, typecheck and lint clean.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitaiBot commented Aug 16, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 92099a55-0191-40cb-b0de-e3e6b55e3690

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Darkest-Teddy added a commit that referenced this pull request Aug 16, 2026
Written so the next session does not have to reconstruct this from a
terminal. Sibling to HANDOFF-evaluation.md, added to this branch the same
day from another session: that one owns the numbers, this one owns Read &
mark, the environment behind it, and the dev-server preflight.
WHAT IT CARRIES. The three load-bearing decisions in the reading surface
and why each is easy to break: seats are stored rather than derived from
participant order, because that order is a sorted set and adding anybody
silently recoloured every existing highlight below them; the finding join
is sourceDocumentId and not the filename, because real data holds
"FDA NDA 211810" where the file is turalio-211810-multidiscipline.pdf and
a filename join matches nothing while looking like a rendering bug; and
blindness is enforced by the server not returning positions, so a new
endpoint outside the read guard silently ends the blind stage.
THE ONE PIECE OF THE DESIGN THAT IS NOT BUILT is written up as such - the
top-level Read entry in the rail. It is no longer blocked on the scene,
which now exists, and what it actually needs is a launcher route, because
a NAV entry has no caseId to bind to.
The seat palette question is left as a decision for a human rather than
settled quietly in code. Re-fitting the seats to this branch's blue wedge
separates them mostly by lightness, and 3 to 5 are close at badge size
with six people on a case. Three ways out, all design-system calls.
AN INDEX IN HANDOVER.md, because there were three branch handoffs and
nothing pointed at any of them. HANDOVER.md is the file somebody opens
first and it is only updated at merge, so work in flight was reachable
only by knowing it existed.
Corrected two claims while checking them rather than shipping them: the
suite here is 821 tests across 58 files, not the 829/59 measured with
PR #24's own tests included, and measure_pdf.py is in data/prep, not
tools. Every file:line pointer in the document was verified against the
tree.
PR #24 is named as the first thing to do. It is not merged.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Darkest-Teddy added a commit that referenced this pull request Aug 16, 2026
A second session is writing the reading-surface handoff on this same branch, and its
first line is one this document was missing: HANDOVER.md records the submission as due
16 Aug 2026, which is today. A handoff that opens with a forty-minute measurement and
says nothing about the deadline invites someone to start the EMA EPAR corpus work in
section 8 instead, which has no chance of landing. So the deadline is now above section
0, with the note that the ordering survives it either way - after the date, the EPAR
work stops being out of reach and becomes worth doing properly.
Cross-referenced the sibling both directions. It owns the reading surface, the scene and
the preflight; this one owns the numbers. Its first instruction is that PR #24 is open
against this branch and unmerged, which matters to anyone arriving here cold and is not
otherwise discoverable from this file.
Section 13 gains what CI actually enforces, which is more than the three commands this
document was quoting. The one that catches you is the manifest diff: a reported figure
that moves fails the build until the move is committed and explained. Also that this
branch has two sessions on it and the last push was rejected for exactly that - fetch
before pushing.
HANDOVER.md's index row for this file said "three times a metric looked broken". It is
four; the fourth was my own fixture labels being wrong while the model was right, which
is the one of the four most likely to repeat.
Typecheck, lint and 821 tests pass.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…gful
This branch's checks last ran against a base where npm test could not
pass, so its red X was never about the preflight. Taking the base in so
the run says something.
@AndresL230
AndresL230 changed the base branch from feat/product-in-the-atmosphere to mainAugust 17, 2026 04:24
@AndresL230
AndresL230 merged commit 94ed8e4 into mainAug 17, 2026
3 checks passed
AndresL230 added a commit that referenced this pull request Aug 17, 2026
The doc was written an hour before the merge it describes. Also note the
gap it opened: #24 went to main alone, so feat/product-in-the-atmosphere
is one merge behind again.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
AndresL230 added a commit that referenced this pull request Aug 17, 2026
main moved 42 commits under this branch - #33 (Postgres/Supabase), #24, #29,
#32 and the logo - and rewrote the three files this touches most.
THE RECONCILIATION #33 DEFERRED. `ShareStore` was written against the pattern
this branch had: a synchronous `new ShareStore(path)` beside `AuthStore` and
`InviteStore`. That layer is gone. So the store joins the new one the way the
other four did:
- `ShareStoreApi` in postgres-share.ts, where `AuthStoreApi` and
`InviteStoreApi` live, for the reason stated there: the second
implementation is what needs a name for the shape.
- `ShareStore.open(path)`, async, private constructor.
- `PostgresShareStore`, and supabase/migrations/0002_share_links.sql.
- Both branches of `buildStores`, and `Stores.shares`.
- The behaviour is ONE suite over both implementations
(test/share-store-contract.ts), as with auth and invites.
`shareSecret` deliberately stayed OUT of `buildStores`: which backing holds the
links is a storage decision, whether the deployment can publish at all is not.
THE TABLE HOLDS NO TOKEN, and the migration says so at length because that is
the feature's whole security argument - the URL is
HMAC(secret, "caseId:version"), derivable from two columns that are not secret,
so a stolen dump yields nothing. `publish` omits `version` from its upsert's
SET list on purpose: assigning it would reset a revoked case to 1 and re-mint
the token revoke had just killed. A test reads the column list back out of
information_schema, because that property fails silently.
WHAT THE CONFLICTS COST. server.ts kept main's static serving whole and its
`/api/health` route; the branch's "NO STATIC-FILE SERVING HERE" comment was
true when written and is now a lie, so it is replaced by an accurate one:
`/r/:caseId/:token` is still not served in production, a scanned QR 404s on a
deployed host, and the two decisions that has to wait on are written down
beside `staticRoot()`. Adding it here was out of scope and stayed out.
`handleReport` and `handleShare` became async; `handleReport` fetches the people
in one `auth.list()` rather than a lookup per name, because `auth.get` is
asynchronous now and `buildCaseReport` takes a synchronous `person`.
ONE THING THE MERGE HAD TO DECIDE. docs/HANDOFF-open-prs.md predicted that #30
and main each carried a provenance rule and that they would auto-merge without
conflict. They did, and both were live: `view`'s read any unrecognised actor as
`live`, the report's read only "model" as `live`. Two surfaces describing one
signed safety adjudication, disagreeing about whether a model produced it.
Closed with one module-level `sourceOf`, failing toward `stub`; every writer
passes "stub" or "model" so nothing observable changed, and the test pins that
both readers agree on a third actor neither was written for.
The postgres test fixture now applies every migration in filename order. Pinned
to 0001, it built a database that was correct on the day it was written and
silently lacked share_links.
Verified: lint, typecheck, 1267 tests with DATABASE_URL set (1179 without),
both builds, harness + metrics + golden + an unchanged verdict-manifest, e2e.
The public bundle still carries no auth code: only main's own entry chunk
matches AUTO_PASSWORD or /api/auth/login, and public.html references neither.
HANDOFF-pr34.md is deleted - the job it describes is this commit, and what
happened is recorded in docs/HANDOFF-open-prs.md and the spec.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
AndresL230 added a commit that referenced this pull request Aug 17, 2026
…, three fixes
What this session actually did, and how each claim in it was checked.
#25 reviewed from scratch, which nothing had done - its entry was a placeholder that said
so. The ten numbers are sound: every headline re-derived from the raw rows rather than
trusted, Wilson checked against the standard interval, the Ask/retrieval same-fixture
cross-check confirmed real. Three defects in the instrument, all fixed: one headline was
read from a summary field in the file that promises it never does that, one cross-check
could not fire because the results file predates the field it keys off, and a product
change to extraction retrieval rode along unmeasured by any of the ten and untested.
#27 split; the good half is prepared. Also records a third blocker nobody had noted - it
reverts SHAPE_ASK from 64000 to 16000 - and corrects "four eval scripts" to six.
#28 verified empty against current main rather than asserted: five conflicts, all in files
main has superseded. Two corrections to this document's own account of it, both from the
same mistake - reading `git diff main PR` as if it were a merge. It is not: neither merge
base contains `responseSchemaFor`, so main ADDED it and a merge keeps it.
Corrects the no-database baseline, which was wrong by 7. 1055 + 76 = 1131 is the Postgres
total; the recorded 1048 + 76 = 1124 was #33's merge-commit figure carried into a row it
had stopped belonging to. New baselines at 1c25747 measured in both environments.
Corrects the Node-20 note: CI pins node-version 22, and the real item is the action
runtime. Records the dependabot triage, the two #24 risks now fixed, the withTransaction
fix, and the .gitignore hole that let a venv symlink be committed during this session.
Adds the two things this document keeps getting wrong: origin/main moves mid-session, and
the open-PR count must come from `gh pr list` rather than from a sentence - it has now
been miscounted twice in opposite directions, the second time omitting #34.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@Darkest-Teddy@AndresL230
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Make the dev server say "npm install" instead of blaming read.tsx - #24

Merged
AndresL230 merged 2 commits into
mainfrom
fix/dev-dependency-preflight
Aug 17, 2026
Merged

Make the dev server say "npm install" instead of blaming read.tsx#24
AndresL230 merged 2 commits into
mainfrom
fix/dev-dependency-preflight

Conversation

@Darkest-Teddy

Copy link
Copy Markdown
Contributor

The report

Opening a document in Read & mark threw this:

[plugin:vite:import-analysis] Failed to resolve import "pdfjs-dist"
from "src/read.tsx". Does the file exist?

Nothing was wrong with read.tsx. pdfjs-dist is declared by apps/deliberation and recorded in package-lock.json — it was simply never installed, because that checkout's node_modules predated the merge that added it.

The overlay names a correct file, a correct line and a correct import, and asks whether a file the author never wrote exists. Every fact in it points away from the cause, so it sends you reading application source. It cost a round trip.

Why a preflight and not just an install

The trigger isn't this package. It's any npm install older than the last dependency added on any branch — which is every collaborator after every pull, forever. Installing once fixes today; this fixes the class.

tools/check-deps.mjs walks the workspaces the root manifest declares and checks that what they declare is actually on disk, hoisted or nested:

Dependencies on disk do not match the manifests:
- pdfjs-dist (4.10.38) declared by @arbiter/deliberation — not installed
Fix: npm install

Same trade dev-all.mjs already makes with --strictPort: fail loudly at startup rather than proceed into a state whose symptom names the wrong cause.

Exact pins are version-checked, ranges are not. A bare version means somebody needed a specific one — pdfjs-dist is pinned at 4.10.38 because 5.x needs Node ≥ 22.13 and crashes on 20. A stale hoisted 5.x would satisfy a directory check and then fail at runtime talking about something else, which is the exact failure mode this file exists to end. Ranges would need a semver implementation to say anything the range doesn't already say.

Wiring

  • npm run dev — in-process, before a single server is spawned
  • npm run deliberate:dev
  • npm run check:deps — standalone

Tests

A guard's own failure mode is passing while checking nothing, so the suite builds broken fixture trees rather than running against this repo. Gutting checkDeps to return [] fails four of the eight.

Two places this could have gone quietly no-op are closed:

  • the standalone-entry check uses pathToFileURL rather than interpolating argv[1] into a file:// string, which on Windows never matches — the script would have exited 0 having checked nothing
  • an unexpandable workspace pattern throws rather than skipping that workspace and still reporting ok

Verified

  • npm run dev on a tree with the package hidden: exits 1, no server spawned
  • restored: dependencies ok
  • 829 tests / 59 files, typecheck clean, lint clean

Based on feat/product-in-the-atmosphere so it can be merged into the branch being tested locally, without disturbing #22.

🤖 Generated with Claude Code

Opening a document threw:
[plugin:vite:import-analysis] Failed to resolve import "pdfjs-dist"
from "src/read.tsx". Does the file exist?
Nothing was wrong with read.tsx. `pdfjs-dist` is declared by
apps/deliberation and recorded in the lockfile; it was simply not
installed, because that node_modules predated the merge that added it.
The overlay names a correct file, a correct line and a correct import,
and asks whether a file the author never wrote exists - every fact in it
points away from the cause.
The trigger is not this package. It is any install older than the last
dependency added on any branch, which is every collaborator after every
pull, so the fix is not another install: it is a preflight that fails
where the cause is legible.
tools/check-deps.mjs walks the workspaces the root manifest declares and
checks that what they declare is on disk, hoisted or nested. Exact pins
are also version-checked, ranges are not: a bare version means somebody
needed a specific one, and pdfjs-dist is pinned at 4.10.38 because 5.x
needs node >= 22.13 and crashes on 20 - a stale hoisted 5.x would pass a
directory check and then fail at runtime talking about something else.
Ranges would need a semver implementation to say anything ranges do not
already say.
Wired into `npm run dev` in-process before any server is spawned, and
into `deliberate:dev`; also `npm run check:deps` on its own.
A guard that passes while checking nothing is the failure mode here, so
the tests build broken fixture trees rather than running against this
repo - gutting checkDeps to `return []` fails four of the eight. Two
places where this could have gone quietly no-op are handled: the
standalone-entry check uses pathToFileURL rather than interpolating
argv[1], which on Windows never matches, and an unexpandable workspace
pattern throws instead of skipping a workspace and still reporting ok.
Verified: `npm run dev` exits 1 without spawning a server on a tree
missing the package. 829 tests, typecheck and lint clean.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitaiBot commented Aug 16, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 92099a55-0191-40cb-b0de-e3e6b55e3690

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Darkest-Teddy added a commit that referenced this pull request Aug 16, 2026
Written so the next session does not have to reconstruct this from a
terminal. Sibling to HANDOFF-evaluation.md, added to this branch the same
day from another session: that one owns the numbers, this one owns Read &
mark, the environment behind it, and the dev-server preflight.
WHAT IT CARRIES. The three load-bearing decisions in the reading surface
and why each is easy to break: seats are stored rather than derived from
participant order, because that order is a sorted set and adding anybody
silently recoloured every existing highlight below them; the finding join
is sourceDocumentId and not the filename, because real data holds
"FDA NDA 211810" where the file is turalio-211810-multidiscipline.pdf and
a filename join matches nothing while looking like a rendering bug; and
blindness is enforced by the server not returning positions, so a new
endpoint outside the read guard silently ends the blind stage.
THE ONE PIECE OF THE DESIGN THAT IS NOT BUILT is written up as such - the
top-level Read entry in the rail. It is no longer blocked on the scene,
which now exists, and what it actually needs is a launcher route, because
a NAV entry has no caseId to bind to.
The seat palette question is left as a decision for a human rather than
settled quietly in code. Re-fitting the seats to this branch's blue wedge
separates them mostly by lightness, and 3 to 5 are close at badge size
with six people on a case. Three ways out, all design-system calls.
AN INDEX IN HANDOVER.md, because there were three branch handoffs and
nothing pointed at any of them. HANDOVER.md is the file somebody opens
first and it is only updated at merge, so work in flight was reachable
only by knowing it existed.
Corrected two claims while checking them rather than shipping them: the
suite here is 821 tests across 58 files, not the 829/59 measured with
PR #24's own tests included, and measure_pdf.py is in data/prep, not
tools. Every file:line pointer in the document was verified against the
tree.
PR #24 is named as the first thing to do. It is not merged.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Darkest-Teddy added a commit that referenced this pull request Aug 16, 2026
A second session is writing the reading-surface handoff on this same branch, and its
first line is one this document was missing: HANDOVER.md records the submission as due
16 Aug 2026, which is today. A handoff that opens with a forty-minute measurement and
says nothing about the deadline invites someone to start the EMA EPAR corpus work in
section 8 instead, which has no chance of landing. So the deadline is now above section
0, with the note that the ordering survives it either way - after the date, the EPAR
work stops being out of reach and becomes worth doing properly.
Cross-referenced the sibling both directions. It owns the reading surface, the scene and
the preflight; this one owns the numbers. Its first instruction is that PR #24 is open
against this branch and unmerged, which matters to anyone arriving here cold and is not
otherwise discoverable from this file.
Section 13 gains what CI actually enforces, which is more than the three commands this
document was quoting. The one that catches you is the manifest diff: a reported figure
that moves fails the build until the move is committed and explained. Also that this
branch has two sessions on it and the last push was rejected for exactly that - fetch
before pushing.
HANDOVER.md's index row for this file said "three times a metric looked broken". It is
four; the fourth was my own fixture labels being wrong while the model was right, which
is the one of the four most likely to repeat.
Typecheck, lint and 821 tests pass.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…gful
This branch's checks last ran against a base where npm test could not
pass, so its red X was never about the preflight. Taking the base in so
the run says something.
@AndresL230
AndresL230 changed the base branch from feat/product-in-the-atmosphere to mainAugust 17, 2026 04:24
@AndresL230
AndresL230 merged commit 94ed8e4 into mainAug 17, 2026
3 checks passed
AndresL230 added a commit that referenced this pull request Aug 17, 2026
The doc was written an hour before the merge it describes. Also note the
gap it opened: #24 went to main alone, so feat/product-in-the-atmosphere
is one merge behind again.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
AndresL230 added a commit that referenced this pull request Aug 17, 2026
main moved 42 commits under this branch - #33 (Postgres/Supabase), #24, #29,
#32 and the logo - and rewrote the three files this touches most.
THE RECONCILIATION #33 DEFERRED. `ShareStore` was written against the pattern
this branch had: a synchronous `new ShareStore(path)` beside `AuthStore` and
`InviteStore`. That layer is gone. So the store joins the new one the way the
other four did:
- `ShareStoreApi` in postgres-share.ts, where `AuthStoreApi` and
`InviteStoreApi` live, for the reason stated there: the second
implementation is what needs a name for the shape.
- `ShareStore.open(path)`, async, private constructor.
- `PostgresShareStore`, and supabase/migrations/0002_share_links.sql.
- Both branches of `buildStores`, and `Stores.shares`.
- The behaviour is ONE suite over both implementations
(test/share-store-contract.ts), as with auth and invites.
`shareSecret` deliberately stayed OUT of `buildStores`: which backing holds the
links is a storage decision, whether the deployment can publish at all is not.
THE TABLE HOLDS NO TOKEN, and the migration says so at length because that is
the feature's whole security argument - the URL is
HMAC(secret, "caseId:version"), derivable from two columns that are not secret,
so a stolen dump yields nothing. `publish` omits `version` from its upsert's
SET list on purpose: assigning it would reset a revoked case to 1 and re-mint
the token revoke had just killed. A test reads the column list back out of
information_schema, because that property fails silently.
WHAT THE CONFLICTS COST. server.ts kept main's static serving whole and its
`/api/health` route; the branch's "NO STATIC-FILE SERVING HERE" comment was
true when written and is now a lie, so it is replaced by an accurate one:
`/r/:caseId/:token` is still not served in production, a scanned QR 404s on a
deployed host, and the two decisions that has to wait on are written down
beside `staticRoot()`. Adding it here was out of scope and stayed out.
`handleReport` and `handleShare` became async; `handleReport` fetches the people
in one `auth.list()` rather than a lookup per name, because `auth.get` is
asynchronous now and `buildCaseReport` takes a synchronous `person`.
ONE THING THE MERGE HAD TO DECIDE. docs/HANDOFF-open-prs.md predicted that #30
and main each carried a provenance rule and that they would auto-merge without
conflict. They did, and both were live: `view`'s read any unrecognised actor as
`live`, the report's read only "model" as `live`. Two surfaces describing one
signed safety adjudication, disagreeing about whether a model produced it.
Closed with one module-level `sourceOf`, failing toward `stub`; every writer
passes "stub" or "model" so nothing observable changed, and the test pins that
both readers agree on a third actor neither was written for.
The postgres test fixture now applies every migration in filename order. Pinned
to 0001, it built a database that was correct on the day it was written and
silently lacked share_links.
Verified: lint, typecheck, 1267 tests with DATABASE_URL set (1179 without),
both builds, harness + metrics + golden + an unchanged verdict-manifest, e2e.
The public bundle still carries no auth code: only main's own entry chunk
matches AUTO_PASSWORD or /api/auth/login, and public.html references neither.
HANDOFF-pr34.md is deleted - the job it describes is this commit, and what
happened is recorded in docs/HANDOFF-open-prs.md and the spec.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
AndresL230 added a commit that referenced this pull request Aug 17, 2026
…, three fixes
What this session actually did, and how each claim in it was checked.
#25 reviewed from scratch, which nothing had done - its entry was a placeholder that said
so. The ten numbers are sound: every headline re-derived from the raw rows rather than
trusted, Wilson checked against the standard interval, the Ask/retrieval same-fixture
cross-check confirmed real. Three defects in the instrument, all fixed: one headline was
read from a summary field in the file that promises it never does that, one cross-check
could not fire because the results file predates the field it keys off, and a product
change to extraction retrieval rode along unmeasured by any of the ten and untested.
#27 split; the good half is prepared. Also records a third blocker nobody had noted - it
reverts SHAPE_ASK from 64000 to 16000 - and corrects "four eval scripts" to six.
#28 verified empty against current main rather than asserted: five conflicts, all in files
main has superseded. Two corrections to this document's own account of it, both from the
same mistake - reading `git diff main PR` as if it were a merge. It is not: neither merge
base contains `responseSchemaFor`, so main ADDED it and a merge keeps it.
Corrects the no-database baseline, which was wrong by 7. 1055 + 76 = 1131 is the Postgres
total; the recorded 1048 + 76 = 1124 was #33's merge-commit figure carried into a row it
had stopped belonging to. New baselines at 1c25747 measured in both environments.
Corrects the Node-20 note: CI pins node-version 22, and the real item is the action
runtime. Records the dependabot triage, the two #24 risks now fixed, the withTransaction
fix, and the .gitignore hole that let a venv symlink be committed during this session.
Adds the two things this document keeps getting wrong: origin/main moves mid-session, and
the open-PR count must come from `gh pr list` rather than from a sentence - it has now
been miscounted twice in opposite directions, the second time omitting #34.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@Darkest-Teddy@AndresL230
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Make the dev server say "npm install" instead of blaming read.tsx - #24

Merged
AndresL230 merged 2 commits into
mainfrom
fix/dev-dependency-preflight
Aug 17, 2026
Merged

Make the dev server say "npm install" instead of blaming read.tsx#24
AndresL230 merged 2 commits into
mainfrom
fix/dev-dependency-preflight

Conversation

@Darkest-Teddy

Copy link
Copy Markdown
Contributor

The report

Opening a document in Read & mark threw this:

[plugin:vite:import-analysis] Failed to resolve import "pdfjs-dist"
from "src/read.tsx". Does the file exist?

Nothing was wrong with read.tsx. pdfjs-dist is declared by apps/deliberation and recorded in package-lock.json — it was simply never installed, because that checkout's node_modules predated the merge that added it.

The overlay names a correct file, a correct line and a correct import, and asks whether a file the author never wrote exists. Every fact in it points away from the cause, so it sends you reading application source. It cost a round trip.

Why a preflight and not just an install

The trigger isn't this package. It's any npm install older than the last dependency added on any branch — which is every collaborator after every pull, forever. Installing once fixes today; this fixes the class.

tools/check-deps.mjs walks the workspaces the root manifest declares and checks that what they declare is actually on disk, hoisted or nested:

Dependencies on disk do not match the manifests:
- pdfjs-dist (4.10.38) declared by @arbiter/deliberation — not installed
Fix: npm install

Same trade dev-all.mjs already makes with --strictPort: fail loudly at startup rather than proceed into a state whose symptom names the wrong cause.

Exact pins are version-checked, ranges are not. A bare version means somebody needed a specific one — pdfjs-dist is pinned at 4.10.38 because 5.x needs Node ≥ 22.13 and crashes on 20. A stale hoisted 5.x would satisfy a directory check and then fail at runtime talking about something else, which is the exact failure mode this file exists to end. Ranges would need a semver implementation to say anything the range doesn't already say.

Wiring

  • npm run dev — in-process, before a single server is spawned
  • npm run deliberate:dev
  • npm run check:deps — standalone

Tests

A guard's own failure mode is passing while checking nothing, so the suite builds broken fixture trees rather than running against this repo. Gutting checkDeps to return [] fails four of the eight.

Two places this could have gone quietly no-op are closed:

  • the standalone-entry check uses pathToFileURL rather than interpolating argv[1] into a file:// string, which on Windows never matches — the script would have exited 0 having checked nothing
  • an unexpandable workspace pattern throws rather than skipping that workspace and still reporting ok

Verified

  • npm run dev on a tree with the package hidden: exits 1, no server spawned
  • restored: dependencies ok
  • 829 tests / 59 files, typecheck clean, lint clean

Based on feat/product-in-the-atmosphere so it can be merged into the branch being tested locally, without disturbing #22.

🤖 Generated with Claude Code

Opening a document threw:
[plugin:vite:import-analysis] Failed to resolve import "pdfjs-dist"
from "src/read.tsx". Does the file exist?
Nothing was wrong with read.tsx. `pdfjs-dist` is declared by
apps/deliberation and recorded in the lockfile; it was simply not
installed, because that node_modules predated the merge that added it.
The overlay names a correct file, a correct line and a correct import,
and asks whether a file the author never wrote exists - every fact in it
points away from the cause.
The trigger is not this package. It is any install older than the last
dependency added on any branch, which is every collaborator after every
pull, so the fix is not another install: it is a preflight that fails
where the cause is legible.
tools/check-deps.mjs walks the workspaces the root manifest declares and
checks that what they declare is on disk, hoisted or nested. Exact pins
are also version-checked, ranges are not: a bare version means somebody
needed a specific one, and pdfjs-dist is pinned at 4.10.38 because 5.x
needs node >= 22.13 and crashes on 20 - a stale hoisted 5.x would pass a
directory check and then fail at runtime talking about something else.
Ranges would need a semver implementation to say anything ranges do not
already say.
Wired into `npm run dev` in-process before any server is spawned, and
into `deliberate:dev`; also `npm run check:deps` on its own.
A guard that passes while checking nothing is the failure mode here, so
the tests build broken fixture trees rather than running against this
repo - gutting checkDeps to `return []` fails four of the eight. Two
places where this could have gone quietly no-op are handled: the
standalone-entry check uses pathToFileURL rather than interpolating
argv[1], which on Windows never matches, and an unexpandable workspace
pattern throws instead of skipping a workspace and still reporting ok.
Verified: `npm run dev` exits 1 without spawning a server on a tree
missing the package. 829 tests, typecheck and lint clean.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitaiBot commented Aug 16, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 92099a55-0191-40cb-b0de-e3e6b55e3690

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Darkest-Teddy added a commit that referenced this pull request Aug 16, 2026
Written so the next session does not have to reconstruct this from a
terminal. Sibling to HANDOFF-evaluation.md, added to this branch the same
day from another session: that one owns the numbers, this one owns Read &
mark, the environment behind it, and the dev-server preflight.
WHAT IT CARRIES. The three load-bearing decisions in the reading surface
and why each is easy to break: seats are stored rather than derived from
participant order, because that order is a sorted set and adding anybody
silently recoloured every existing highlight below them; the finding join
is sourceDocumentId and not the filename, because real data holds
"FDA NDA 211810" where the file is turalio-211810-multidiscipline.pdf and
a filename join matches nothing while looking like a rendering bug; and
blindness is enforced by the server not returning positions, so a new
endpoint outside the read guard silently ends the blind stage.
THE ONE PIECE OF THE DESIGN THAT IS NOT BUILT is written up as such - the
top-level Read entry in the rail. It is no longer blocked on the scene,
which now exists, and what it actually needs is a launcher route, because
a NAV entry has no caseId to bind to.
The seat palette question is left as a decision for a human rather than
settled quietly in code. Re-fitting the seats to this branch's blue wedge
separates them mostly by lightness, and 3 to 5 are close at badge size
with six people on a case. Three ways out, all design-system calls.
AN INDEX IN HANDOVER.md, because there were three branch handoffs and
nothing pointed at any of them. HANDOVER.md is the file somebody opens
first and it is only updated at merge, so work in flight was reachable
only by knowing it existed.
Corrected two claims while checking them rather than shipping them: the
suite here is 821 tests across 58 files, not the 829/59 measured with
PR #24's own tests included, and measure_pdf.py is in data/prep, not
tools. Every file:line pointer in the document was verified against the
tree.
PR #24 is named as the first thing to do. It is not merged.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Darkest-Teddy added a commit that referenced this pull request Aug 16, 2026
A second session is writing the reading-surface handoff on this same branch, and its
first line is one this document was missing: HANDOVER.md records the submission as due
16 Aug 2026, which is today. A handoff that opens with a forty-minute measurement and
says nothing about the deadline invites someone to start the EMA EPAR corpus work in
section 8 instead, which has no chance of landing. So the deadline is now above section
0, with the note that the ordering survives it either way - after the date, the EPAR
work stops being out of reach and becomes worth doing properly.
Cross-referenced the sibling both directions. It owns the reading surface, the scene and
the preflight; this one owns the numbers. Its first instruction is that PR #24 is open
against this branch and unmerged, which matters to anyone arriving here cold and is not
otherwise discoverable from this file.
Section 13 gains what CI actually enforces, which is more than the three commands this
document was quoting. The one that catches you is the manifest diff: a reported figure
that moves fails the build until the move is committed and explained. Also that this
branch has two sessions on it and the last push was rejected for exactly that - fetch
before pushing.
HANDOVER.md's index row for this file said "three times a metric looked broken". It is
four; the fourth was my own fixture labels being wrong while the model was right, which
is the one of the four most likely to repeat.
Typecheck, lint and 821 tests pass.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…gful
This branch's checks last ran against a base where npm test could not
pass, so its red X was never about the preflight. Taking the base in so
the run says something.
@AndresL230
AndresL230 changed the base branch from feat/product-in-the-atmosphere to mainAugust 17, 2026 04:24
@AndresL230
AndresL230 merged commit 94ed8e4 into mainAug 17, 2026
3 checks passed
AndresL230 added a commit that referenced this pull request Aug 17, 2026
The doc was written an hour before the merge it describes. Also note the
gap it opened: #24 went to main alone, so feat/product-in-the-atmosphere
is one merge behind again.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
AndresL230 added a commit that referenced this pull request Aug 17, 2026
main moved 42 commits under this branch - #33 (Postgres/Supabase), #24, #29,
#32 and the logo - and rewrote the three files this touches most.
THE RECONCILIATION #33 DEFERRED. `ShareStore` was written against the pattern
this branch had: a synchronous `new ShareStore(path)` beside `AuthStore` and
`InviteStore`. That layer is gone. So the store joins the new one the way the
other four did:
- `ShareStoreApi` in postgres-share.ts, where `AuthStoreApi` and
`InviteStoreApi` live, for the reason stated there: the second
implementation is what needs a name for the shape.
- `ShareStore.open(path)`, async, private constructor.
- `PostgresShareStore`, and supabase/migrations/0002_share_links.sql.
- Both branches of `buildStores`, and `Stores.shares`.
- The behaviour is ONE suite over both implementations
(test/share-store-contract.ts), as with auth and invites.
`shareSecret` deliberately stayed OUT of `buildStores`: which backing holds the
links is a storage decision, whether the deployment can publish at all is not.
THE TABLE HOLDS NO TOKEN, and the migration says so at length because that is
the feature's whole security argument - the URL is
HMAC(secret, "caseId:version"), derivable from two columns that are not secret,
so a stolen dump yields nothing. `publish` omits `version` from its upsert's
SET list on purpose: assigning it would reset a revoked case to 1 and re-mint
the token revoke had just killed. A test reads the column list back out of
information_schema, because that property fails silently.
WHAT THE CONFLICTS COST. server.ts kept main's static serving whole and its
`/api/health` route; the branch's "NO STATIC-FILE SERVING HERE" comment was
true when written and is now a lie, so it is replaced by an accurate one:
`/r/:caseId/:token` is still not served in production, a scanned QR 404s on a
deployed host, and the two decisions that has to wait on are written down
beside `staticRoot()`. Adding it here was out of scope and stayed out.
`handleReport` and `handleShare` became async; `handleReport` fetches the people
in one `auth.list()` rather than a lookup per name, because `auth.get` is
asynchronous now and `buildCaseReport` takes a synchronous `person`.
ONE THING THE MERGE HAD TO DECIDE. docs/HANDOFF-open-prs.md predicted that #30
and main each carried a provenance rule and that they would auto-merge without
conflict. They did, and both were live: `view`'s read any unrecognised actor as
`live`, the report's read only "model" as `live`. Two surfaces describing one
signed safety adjudication, disagreeing about whether a model produced it.
Closed with one module-level `sourceOf`, failing toward `stub`; every writer
passes "stub" or "model" so nothing observable changed, and the test pins that
both readers agree on a third actor neither was written for.
The postgres test fixture now applies every migration in filename order. Pinned
to 0001, it built a database that was correct on the day it was written and
silently lacked share_links.
Verified: lint, typecheck, 1267 tests with DATABASE_URL set (1179 without),
both builds, harness + metrics + golden + an unchanged verdict-manifest, e2e.
The public bundle still carries no auth code: only main's own entry chunk
matches AUTO_PASSWORD or /api/auth/login, and public.html references neither.
HANDOFF-pr34.md is deleted - the job it describes is this commit, and what
happened is recorded in docs/HANDOFF-open-prs.md and the spec.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
AndresL230 added a commit that referenced this pull request Aug 17, 2026
…, three fixes
What this session actually did, and how each claim in it was checked.
#25 reviewed from scratch, which nothing had done - its entry was a placeholder that said
so. The ten numbers are sound: every headline re-derived from the raw rows rather than
trusted, Wilson checked against the standard interval, the Ask/retrieval same-fixture
cross-check confirmed real. Three defects in the instrument, all fixed: one headline was
read from a summary field in the file that promises it never does that, one cross-check
could not fire because the results file predates the field it keys off, and a product
change to extraction retrieval rode along unmeasured by any of the ten and untested.
#27 split; the good half is prepared. Also records a third blocker nobody had noted - it
reverts SHAPE_ASK from 64000 to 16000 - and corrects "four eval scripts" to six.
#28 verified empty against current main rather than asserted: five conflicts, all in files
main has superseded. Two corrections to this document's own account of it, both from the
same mistake - reading `git diff main PR` as if it were a merge. It is not: neither merge
base contains `responseSchemaFor`, so main ADDED it and a merge keeps it.
Corrects the no-database baseline, which was wrong by 7. 1055 + 76 = 1131 is the Postgres
total; the recorded 1048 + 76 = 1124 was #33's merge-commit figure carried into a row it
had stopped belonging to. New baselines at 1c25747 measured in both environments.
Corrects the Node-20 note: CI pins node-version 22, and the real item is the action
runtime. Records the dependabot triage, the two #24 risks now fixed, the withTransaction
fix, and the .gitignore hole that let a venv symlink be committed during this session.
Adds the two things this document keeps getting wrong: origin/main moves mid-session, and
the open-PR count must come from `gh pr list` rather than from a sentence - it has now
been miscounted twice in opposite directions, the second time omitting #34.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@Darkest-Teddy@AndresL230