Skip to content

Current state & blockers

The question this answers: what is decided, what is built, and what is waiting on a person?

This page states facts about the repository rather than rulings, and each one below was checked by reading or running what is named beside it. The rulings are in docs/adr/ and are indexed in Decisions. The state-of-now written by the last session is session-handoff.md, and it is authoritative for the blocker list at the bottom of this page.

Observed 2026-09-20. Every number here was re-derived on that date by running the command beside it. The version of this page that preceded it claimed 47 ADRs and 104 decisions against a real 56 and D-127, nine days after both had moved — which is why each row names a command rather than a source.

What exists

ArtifactStateChecked by
ADRs75 ADRs, 6 of them superseded, every supersession recorded on both sides./init.sh (ADRSTATUS, IDSTATUS)
Decision indexGenerated from docs/adr/; 75 ADRs, 148 numbered decisions, 6 supersededbun scripts/gen-decision-index.mjs
GlossaryWritten, and the vocabulary the ADRs and the spec both useCONTEXT.md
SpecificationStage 2 written and revised, 72 US- idsgrep -ohE '^- \*\*US-[0-9]+\*\*' spec/PRD.md | sort -u | wc -l
Build tickets12 stage-3 application tickets, 13–24; every one resolved except ticket 19.scratch/chemical-safety-assistant/issues/
Curation tickets19 curator-side tickets, 25–43; 25–38 and 41–42 resolved, 39 and 40 in progress, 43 open.scratch/chemical-safety-assistant/issues/
The applicationBuilt — see the section below./init.sh in each app repository
Research notes112 R- findings declared across five notes in docs/knowledge/research/grep -rhoE '^### R-[0-9]+' docs/knowledge/research/ | sort -u | wc -l
This documentation siteVitePress over the repository root, ignoreDeadLinks: false.vitepress/config.mts

What is built

The application exists. The two entries under app/ are gitlinks — commit pointers to independent repositories, with no .gitmodules here. That layout is itself a ruling, ADR-0063, and the paths every checkout resolves against are fixed by it:

$ git ls-files -s app/
160000 acb425bc941762e3c5f2401591f80dc38d02841a 0  app/chemical-safety-assistant-api
160000 e9c9f9c4140cac9a1eba3f0e827ab741f324b6f7 0  app/chemical-safety-assistant-frontend
SurfaceState
Home, manual search, QR IdentificationBuilt
Chemical Record, with the chooser and the four no-answer statesBuilt
First Aid, Spill Response, EscalationBuilt
Conversational surface, on the Routing FloorBuilt, with the Escalation Trigger and Curated Explanation lookup
History and SettingsBuilt
Boot Splash and the First Run Notice, in front of the routerBuilt
The curator's surfaces — admission, verification, span selection, reconciliation, translation, explanation authoring, QR labels, publishBuilt, in the curation build only
PPE as a surface of its ownA placeholder route
Camera text recognitionNo route — blocked, see below
Query Intent tierClient half built; the endpoint is deferred by ruling, see below

Verification, run in each application repository:

RepositoryGatesObserved 2026-09-20
FrontendLINT, TYPECHECK, TEST, SEAM4RESULT: PASS — 802 unit tests across 65 files, 26 Playwright cases in the Seam 4 harness
ApiLINT, TYPECHECK, TESTRESULT: PASS — 777 tests across 23 files

Both application gates were red from 2026-09-13 until 2026-09-20, in both repositories, from a single cause. Two commits written that day assumed a workspace where the two application repositories are siblings of scripts/ rather than gitlinks under app/: the api resolved corpus_check.py one directory up instead of two, and the frontend imported the snapshot golden fixture from a chem-assistant-api/ directory that has never existed on disk. Neither failure was encoded by a test, so restoring the real layout turned every one of them green. The layout is now a ruling rather than an assumption — ADR-0063.

Seams 1, 3, 4 and 5 are executable. Seam 1 is a parent-repository gate (scripts/corpus-check.sh, which runs scripts/corpus_check.py) and reports that there is no Corpus snapshot on disk to check, which is a blocker rather than a pass. Seam 2 is asserted by the frontend's surface specs. What each seam is for is in Specification, Testing Decisions.

Four golden fixtures now gate a payload shape across the two repositories rather than inside one — the Corpus snapshot, the curation refusal codes, the sixteen GHS Section headings, and the Reconciliation gaps read. Which of those shapes is a contract and which is an implementation detail is settled in ADR-0060, ADR-0062, ADR-0071 and ADR-0072.

Two capabilities the design depends on were recorded in Specification §1 as absent from the stack and therefore new work. One landed: the service worker and precached shell. The other did not: text recognition for Identification, which is blocked on a spike.

Where the work stopped

Stage 3 produced 12 application build tickets (13–24) and 19 curation tickets (25–43). What each ticket delivered is in its own file under .scratch/chemical-safety-assistant/issues/, and each carries an ## Answer naming the commit and the gate result. Four are not resolved:

TicketStatus on diskWhy
19 — the Query Intent tieropenIts client half is in the Routing Floor and asserted by Seam 5. The server endpoint is deferred by ruling until the Study Area's Corpus exists — ADR-0055 (D-126)
39 — the selection workbenchin progress — reviewed 2026-09-20Built and reviewed on 2026-09-20. The review's own findings are what remain; two of them were ruled on the same day, in ADR-0062 and ADR-0060
40 — the reconciliation pagein progress — reviewed 2026-09-20As above. The review is what produced ADR-0067 and ADR-0068
43 — the unreadable answer in five more resourcesopenNew on 2026-09-20. Five curation resources still report an unparseable success body as "the service may not be running"; closing it needs Thai copy a person has reviewed

The gate is green

./init.sh in this repository runs six checks. Its summary, observed on 2026-09-20:

COVERAGE: PASS
FIXTURE: PASS
ADRSTATUS: PASS
IDSTATUS: PASS
STACKCLAIMS: PASS
CORPUS: PASS
RESULT: PASS

COVERAGE reports 332 declared ids, all mapped downstream, with US as the frontier stage. It was red for nine days on R-46..R-112, the ids declared by the two stack-conventions research notes, which predicted that red in their own preambles; that closed on 2026-09-11. It went red again for part of 2026-09-20 while two sessions wrote in this repository at once, and closed again when the second session's own Coverage rows landed. Any COVERAGE problem now is new. Read the count from ./init.sh, not from this page.

FIXTURE PASS means scripts/test_pipeline_fixture.sh still detects a deliberately broken Coverage table, so the checker itself is working and its green is not a checker bug. ADRSTATUS and IDSTATUS PASS mean every supersession is recorded on both the superseded and the superseding document, and that no Coverage row cites a superseded finding without naming its replacement. STACKCLAIMS PASS means every package the spec claims is installed is installed — twelve of them, since the spec's claims were themselves corrected. CORPUS PASS means the gate found no snapshot on disk and so had nothing to check. It says nothing about whether anything has been curated, and until 2026-09-20 its wording did — "nothing curated yet, the Study Area is unchosen" — which was read as a statement about the project while the database held five curated documents. The Corpus lives in Postgres; a snapshot reaches that path only when one is exported to it.

Correcting a curated selection, and what the database actually holds

Two things landed late on 2026-09-20 and both change what this page could previously say.

A curated selection can now be corrected. The Corpus was append-only with no way back, and ADR-0073 had recorded that hole in its own text. Five rulings close it for selections '—ADR-0084 through ADR-0088, D-169 to D-185 '—and both halves are built: the API carries supersession, retraction, a branch act of its own and the record read that makes any of them reachable by a person, and the curator's surfaces carry all four. See Curation.

There is a reachable database, and there has been for some time. The API's own agent instructions said "None has been applied, and none has been seen by a live database" and "DATABASE_URL is empty"; both were false, and an agent repeated them twice in one session before running prisma migrate status. What is there: all eleven migrations applied, five curated documents (Acetone, Sulphuric Acid, Toluene, IPA, MEK), five Chemical Records, 79 Source Spans, six Restrictions, 83 selections and four snapshots of which one is published.

That matters for how the tests are read. They remain storeless '—every P2002 the curation write path relies on is asserted through an injected store, so the suite needs no database and runs in pre-commit '—but that is now a property of the tests rather than of the checkout. The correction path's constraints were exercised against real Postgres on the day they were written.

What the 2026-09-20 review round changed

A cross-model grill ran on ADR-0057..0063, 0067, 0068 and 0069 — two Grillers, each cold and neither a fork of the session that wrote them. Its findings are recorded in .scratch/chemical-safety-assistant/grill-findings-2026-09-20.md, and the repairs it forced are rulings rather than edits, because an Accepted ADR is never edited:

ResultWhere
Two supersessionsADR-0073 supersedes ADR-0061; ADR-0074 supersedes ADR-0059
One amending ADRADR-0075 amends ADR-0057, ADR-0060, ADR-0062, ADR-0068 and ADR-0069, all of which stand

What the prototype test of 2026-09-20 changed

A Handler and a Curator used the built application and the curator's workbench, and their report was grilled against the rulings before anything was written. Eight ADRs came out of it, D-154..D-168, and three of them had to be shaped around rulings the feedback collided with:

ResultWhere
Home is six cards; an unbuilt route is absent, not disabledADR-0076 amends ADR-0030, which stands — D-62's peer rule binds routes that exist, and camera text returns as a card when its surface does
Chrome is three parts, and the alarm colour stays spent on EscalationADR-0077
Typography and motion join the list the design extract bindsADR-0078 amends ADR-0066, which stands
One control vocabulary on both buildsADR-0079
The Curator's surfaces state what the server statesADR-0080 — the 409 that told a Curator a verified page was unverified
The original document is a network improvement, never a gateADR-0081
A published version is inspectable from its own payloadADR-0082
The record tabs reference fields; emergency content stays flatADR-0083ADR-0008's rejected option is untouched

None of it is built. These are rulings; the implementation is the next session's work.

Blockers

Taken from session-handoff.md, which is the live list. The middle column says what document governs the question; the right column says who answers it.

#BlockerGoverned byAnswered by
1The Plant's SDS binder is not secured. Nothing can be curated without it, and with no Corpus there is nothing for the built application to show.ADR-0011, and the abuse warning in ADR-0016the human
2The Study Area is not chosen and The Plant has not supplied its chemical list (D-79, D-80). Asked 2026-09-20; the reply answered from the project poster, which names no production area, so the questions have not yet reached anyone who has been on the site.ADR-0034, ADR-0054the human
3The spend cap number is not set (D-77), and neither is the per-address bucket size, which D-103 requires to be sized for The Plant's shared egress.ADR-0033, ADR-0043the human
4Two Curation artifacts need a site authority rather than a curator — the Curated Escalation (D-95) and the Escalation Trigger phrase list (D-70). Until signed, the app ships the hotline alone.ADR-0049the human
5Camera text recognition has no route, and the spike it needs requires photographs of real drum labels.Specification, Risks, ADR-0030the human
6Corpus size is the schedule (D-58, D-59). The handoff names no answerer here; it records that if the Study Area turns out to be large, the lever is still the owner's.ADR-0028, ADR-0034
7Nothing can correct a wrong Curated Explanation, and a soft delete locks its term out permanently.ADR-0073a ruling
8All sixteen Thai Section Headings are unsourced. GHS Annex 4 fixes the English; the Thai comes from a ministerial notification no artifact in this repository names.ADR-0060/research
9Ten Prisma migrations exist and none has ever been applied to a live Postgres.ADR-0020the next session that stands one up

Blockers 1, 2 and 6 are all the same dependency seen from three angles, and Curation is where the cost of it is worked through. Blocker 3 concerns the one networked path, drawn in System architecture. Blockers 7 and 8 are holes the 2026-09-20 rulings opened or exposed and left open on purpose; each one says in its ADR what deciding it would take.

What a reader should do next

  • Reviewing the design — start at The content split, which is the decision the other ADRs bend around.
  • Reviewing what was builtSystem architecture for the topology and the installed stack, Sources & data for what the application is fed, Cost for what it costs to run and to curate.
  • Picking up the work — tickets 39, 40 and 43 are the only unfinished engineering; everything else remaining is an owner decision. Run ./init.sh here and in both application repositories first.
  • Looking for a specific rulingDecisions lists all 75 with status, superseded ones included.