OGUR — MVP Scope Contract¶
Owner: founder. Only the owner amends this. Agents may not.
MVP-1 — RELEASED 2026-08-13 as v1.1.0. · MVP-2 — the Explore backend; scope and date TBD (§1, §10 2026-08-19).
Revised: 2026-08-19
Read this before acting. The active milestone is MVP-2. Until the redefinition
session replaces §3, anything not listed in §3 is OUT of the active milestone by
default — and §3 itself is under redefinition, so treat any new work as
NEEDS-EVIDENCE unless it clearly serves the §1 MVP-2 direction.
The durable path from idea to release—including role gates, artifacts, and the
handoff between milestones—is defined in
product-development-workflow.md.
§1 The gates¶
MVP-1 gate — PASSED. Released 2026-08-13 as v1.1.0¶
Evidence: git tag v1.1.0, CHANGELOG.md §1.1.0,
release-notes-v1.1.0.md, production path verified
with named Genfit/Polygon test identities (commit 67819b76, OGUR-61/OGUR-76).
The gate text below is kept verbatim as the record of what was promised.
Genfit and Polygon employees follow an authenticated link and read an auditable report aligned with what they were presented, except for explicitly documented corrections.
Two words carry the whole gate.
Authenticated — they log in as themselves. We know who read what.
Auditable — every claim on the page traces to a real source, and nothing on the page is fabricated. Not "complete," not "regenerated," not "proven generic." Auditable. A client can check any statement we make.
MVP-1 is the delivery surface. It serves the packs that exist today.
MVP-2 gate — UNDER REDEFINITION (was 2026-08-31)¶
Direction (2026-08-19, founder): MVP-2 is the Explore backend — align the discovery, evaluation and landscape-loop work run so far into one robust backend for discovery and exploration that generates new landscapes. The cleanest existing statement of the gap it closes is
release-notes-v1.1.0.mdknown limitation 1: Explore's open-ended live search is not built; Ogur serves landscapes that were discovered offline and frozen into packs.This is a direction, not a scope. The gate sentence, §3's IN list, the date and the §9 cut ladder are set in a dedicated redefinition session (§10 2026-08-19). Until then the pre-redefinition gate below and §3's content stand as candidate material — much of it (rebuild, gold-deck gates, Gates A/B/C) likely survives inside the Explore-backend milestone.
Pre-redefinition gate (2026-08-06, superseded pending redefinition):
The backend rebuilds those reports itself, and a re-run produces a semantically similar report.
Not byte-identical — upstream sources change and we don't control them. This is where generalisation, the literature layer, the gold-deck gates and the de-jargon track live. See §3.
What moved, and why¶
When the 2026-08-13 date was set, the previous §2 represented roughly 14–16 working days of work. It did not shrink — it split by kind:
| MVP-1 (Aug 13) | MVP-2 (Aug 31) | |
|---|---|---|
| Question answered | Can a client reach it and trust it? | Can we rebuild it and prove it generic? |
| Data | Frozen packs, as they are today | Regenerated from the pipeline |
| Risk | Deployment + provenance | Backend correctness |
Everything requiring a rebuild is MVP-2, because nothing that requires a
rebuild can land in 7 days — GNS561 cannot even be rebuilt on main today (§8).
§2 MVP-1 — what was IN (released 2026-08-13)¶
Five items. Each one was required for a client to reach the report and trust it. All five shipped; the closure record below replaces the pre-release delivery forecast. §2.1–§2.5 are kept as the delivered contract — the record of what "auditable", "feedback" and "presented-version alignment" mean in production.
- Authenticated link for named Genfit / Polygon users
- One deployment, one URL, serving both packs — the real frontend, not a static export (§2.3)
- Auditable report — every client-reachable surface real, gated, or deleted per §5, and the four known-wrong claims handled per §4
- Feedback capture — whole-report granularity is acceptable at this date
- Presented-version alignment — the served Genfit and Polygon reports match what each client was shown, except for corrections whose reason and evidence are recorded (§2.4)
Closure record — released 2026-08-13¶
All six release gates passed. Per-gate evidence is in
CHANGELOG.md §1.1.0 (organized by these gates) and the
Linear project
Road to MVP-1 — Aug 13 authenticated reports.
| Gate | Linear | Closed by |
|---|---|---|
| Named-user authentication and report authorization | OGUR-58 | #241 (auth/session), #247/#255 (spend ceiling), #256 (login page) |
| One same-origin production deployment serving both packs | OGUR-59 | #240 (wheel boot), #245 (container + /data volume), #250 (Fly.io deploy + backup) |
| Every client-reachable surface auditable | OGUR-62 | #253 (VITE_DEMO_SURFACES route gate), #254 (evidence depth, OGUR-78), #257 (Gate C audit) |
| Durable attributable report feedback | OGUR-60 | #242/#249 (storage + API, reseed-stable), #251 (feedback box), #258 (Gate D audit) |
| Served reports aligned with client-presented artifacts | OGUR-63 | Gate E reconciliation (#227/#228 pack digests, #246 swimlane fix) |
| Production security and end-to-end smoke gate | OGUR-61 | OGUR-76 security review (#259 deleted unauthenticated generation routes), production verification 67819b76 |
§2.1 Auditable is a claim we are making to a client¶
Do not ship "auditable" while the page carries statements we know are wrong. Deleting the mock surfaces (§5) removes fabricated provenance. §4 is the other half: four claims that are sourced-looking and false.
Auditability also includes evidence depth. The current literature review is
primarily title + abstract, and several patent paths link or synthesize from
metadata/title/abstract even when the upstream query scans full-text fields. A
client must not infer that Ogur read a paper body, patent description, or claims
when it did not. Each source/claim path exposes one of:
metadata-only · title+abstract · full document · unavailable/unknown.
Delivered — OGUR-78, #254/#262
(builder-computed meta.evidence_depth, banner disclosure).
Handling them does not require a rebuild. See §4.
§2.2 Feedback¶
Client employees must be able to write feedback, not just read. Per-section is better; whole-report was accepted for the 2026-08-13 release and is what shipped (#242/#249 storage + API, #251 feedback box). Per-section granularity is roadmap input, not delivered.
Anchor feedback to
content_hash/ NCT id / PMID / publication number / section slug. Never toSignal.id.
A reseed renumbers autoincrement rows and silently re-points feedback at different claims. MVP-2 mandates rebuilds, so this trap fires the moment MVP-2 lands — after clients have written the feedback, against the only unregenerable data in the system.
Acceptance test: seed → attach feedback → reseed → assert every item still resolves to the same document.
§2.3 It has to feel like the product¶
MVP-1 is a static report in the sense that the data is frozen. It is not a static page. A client following the link should get a sense of what the product is, not a PDF behind a login.
Requirements:
- Ship the real frontend. The same React app, shell, navigation, components,
source chips and confidence badges that run locally. Not an HTML export, not a
rendered snapshot. This is why §8's "mount the built frontend as
StaticFiles(html=True), same origin" is the right deployment shape and not merely the cheap one — it deploys the actual application. - Same data local and deployed. The pack served on the web is byte-identical
to the pack served locally. One source of truth, no divergence between what we
demo and what a client sees. Assert it: compare the served pack's
meta.source_digestsagainst the local pack in a smoke check.
The consequence — reachability is now in scope¶
If a client can navigate, then everything reachable from the report is subject
to §5, not just the report route itself. A Genfit employee poking around the
shell can reach /franchise (hand-written LOE dates, phase mix, patent cliffs)
and the Ask panel (scripted answers with a fake animated reasoning trace).
"It feels like the product" and "there are mock surfaces one click away" are not compatible. Every reachable surface must be either real, or unreachable.
That gave a cheap lever, and it is what shipped. Route-gating a client login to the surfaces that are real was far cheaper than making every surface real, and cheaper than deleting everything §5 lists. The release requirement was reachability, not deletion of every mock in the codebase; the §5 deletions remain the intended end state as post-release debt — now due (see the roadmap-inputs doc).
The per-surface real · gated · deleted decisions are recorded in
mvp1-route-inventory-2026-08-12.md
(#253, VITE_DEMO_SURFACES default-gated). §5 states the rule normatively and is
the single place QA reads it from.
§2.4 Presented-version alignment¶
The report a client opens must not drift silently from the report discussed in the meeting. For each of Genfit and Polygon:
- Preserve the exact artifact that was presented.
- Diff it against the currently served pack.
- Classify every material difference as a manual presentation edit, stale source, matcher defect, unsupported synthesis, provenance defect, deliberate correction, or formatting-only change.
- Make the served report match, or record why the evidence-backed correction is intentionally different.
- Record the final pack digest and approval evidence in OGUR-63.
Done for both clients — pack digests and approval evidence recorded in OGUR-63 (#227/#228); CHANGELOG Gate E carries the summary.
This does not authorize copying manual edits blindly. Each edit is evidence about a pipeline defect. MVP-1 reconciles the frozen client surface; MVP-2 fixes the root cause unless a fix is required to prevent a false claim from being served.
§2.5 Full-text-enriched reports are stretch, not a release gate¶
Generating full-text-enriched Genfit and Polygon variants is valuable, but it was not required for the August 13 release and did not land before it. It is tracked as OGUR-79 and rolls into the MVP-2 redefinition as input — per the last paragraph below, the reproducible capability (not a one-off enriched pack) is the MVP-2-shaped deliverable.
The stretch output must remain a separate variant until human review compares it with the abstract-derived baseline. It must preserve retrieval provenance and evidence depth, cite the supporting passage rather than merely the document, and report what full text was unavailable because of access or licensing.
If it does not land before release, MVP-2 owns the reproducible capability: full-document retrieval → chunking → synthesis → claim-to-passage grounding → semantic/regression gates. A one-off enriched pack is not the MVP-2 deliverable.
§3 MVP-2 — what is IN (UNDER REDEFINITION; was due 2026-08-31)¶
2026-08-19 — this section is being redefined. MVP-2's new direction is the Explore backend (§1). Everything below is the pre-redefinition reproducibility scope, kept as candidate content: the rebuilds, the literature harvest, the recall baselines and Gates A/B/C are the strongest existing material for the redefined milestone and are expected to survive inside it, but nothing here is binding until the redefinition session rewrites this section and logs it in §10. Do not gate or estimate new work against this section until then.
§3.1 Rebuild both client reports, no hand edits¶
Neither can be rebuilt today. GNS561's blockers are in §8.
Reproducibility is not done when the pack matches. It is done when nothing in the codebase still pins a reality the pipeline cannot produce — every fixture, test payload, seed CSV and cached artifact either has a generator command or is deleted. That is Gate C (§3.5), and it gates §3.1.
§3.2 The GNS561 literature harvest¶
The literature layer is not an appendix — the served GNS561 pack carries 1,089 PMID references, Polygon's 1,358. A large share of every sourced claim traces to it.
GNS561 has no lit_harvest.py; its corpus came from a discovery result cache
that expired at 7 days. A rebuild would fail or silently reuse the frozen
artifact — the hand-edit failure mode §1 exists to prevent.
- Port Polygon's
lit_harvest.pyto GNS561 (reverse of the original port direction). 12 fixed MeSH/OpenAlex queries, deterministic, no LLM, no DB, $0. Still open —lit_harvest.pyexists only underscripts/eval/polygon_discovery/ Land the three modules unmerged on— DONE.f5559c00lit_curate.py,lit_synthesize.pyandabstracts.pyare onmainunderscripts/eval/gns561_discovery/as of the 2026-08-10 merge (PR #227)
Hard constraint — no third copy of the citation gate. The citation gate,
grounding score and overreach detector exist twice already, carried over
unchanged and annotated as written in response to a real mis-bind. They enforce
Gate B's "zero new unsourced claims," which §9 names never-cut. A never-cut safety
property must not be guarded by three divergeable copies. One implementation;
placement is a tech-lead call, and §8's wheel blocker bears on it.
By /landscape-loop-promote's five-point test this is PROMOTE: point 2 separates
class-neutral mechanism from vocabulary, and it clears point 1(a) — two
runs, two landscape classes.
§3.3 Reproduce siRNA + obesity at a known recall number¶
The Gate A baseline. See §3.5.
§3.4 Trial entity inspection — approved stretch, not a release gate¶
Amendment ratified 2026-08-06 under §6.1, on external user evidence — a client VP of data. It was ratified against an Aug 31 MVP-1. The date moved; the milestone it attaches to moved with it. The ratification stands, and so does the user evidence.
It is not part of the Aug 31 gate. The MVP-2 gate in §1 is the backend rebuilds those reports itself, and a re-run produces a semantically similar report. A 9.5-half-day inspection pane establishes none of that property, and §9 already pre-designates it as the second MVP-2 cut. A requirement that is both mandatory and pre-cut makes "MVP-2 done" unanswerable for QA.
So: the Aug 31 gate contains rebuild (§3.1), literature harvest (§3.2), recall baseline (§3.3), and the three quality gates (§3.5). This pane is an approved stretch item that starts once those are green, on the same terms as §2.5 — ratified scope, real user evidence, no gate authority. It is not re-litigated to build it; it simply cannot fail the milestone.
Scope: trials only. Click a trial → pane with phase, status, sponsor,
why_stopped. Companies and targets are out: Polygon's scope-fit distribution is
1 core / 274 honorable-mention / 112 off-thesis, so company chips would
mostly open panes on rows we ourselves flagged marginal — a client-facing quality
problem that building the pane does not solve. Neither pack has a
records.targets block.
Estimate: 9.5 half-days. Sequenced after PRs #209, #218, #220, #221.
Founder constraint — Monitor schema compatibility. The trial schema matches
Monitor's, and the entity layer stays compatible with the Monitor workspace so an
exploration can be transferred into monitoring mode. This removes an architectural
problem rather than adding one: serving entities from the pack would otherwise
stand up a second entity spine beside Target / DrugTarget /
CompanyProfile / DrugProfile, and the next entity feature would have to guess
which spine to read. Pack records project into Monitor's schema;
TrialDetail becomes another arm of the existing InspectorObject union.
ADR required before it ships.
The deliverable is the pane, not the chip. 24/24 GNS561 and 26/26 Polygon
table NCTs already render as <SourceChip>; exactly one bare unlinked NCT exists
across both packs. Chipping is finished.
Render in_cache: false distinctly from an empty why_stopped. 15 of 34
GNS561 trials never had a record. "We don't have it" and "the registry gave no
reason" are different claims.
§3.5 The de-jargon track and its two gates¶
Replace hand-written keywords with derived vocabulary:
| Layer | Derive from |
|---|---|
| Targets / genes | Open Targets, UniProt |
| Indications | Mondo or EFO |
| Biological function | Gene Ontology |
No de-jargoning change ships unless it passes BOTH gates.
Gate A — recall against truth (siRNA, obesity). Hand-built gold decks exist.
Run /coverage-eval; recall must not drop. The stronger gate, because it measures
against reality rather than our own prior output. A change that quietly narrows
the search shows up here as lost assets and lost deals.
Gate B — semantic similarity (GNS561, PLG-101). No gold deck, so the §3.1 rebuilt reports are the frozen baseline. Claims preserved, entities preserved, sources preserved, zero new unsourced claims.
Gate C — every deterministic input on the rebuild path is reproducible. Applies to §3.1.
Each fixture, test payload, seed CSV, cached JSON and frozen artifact that the GNS561 or PLG-101 rebuild actually reads either has a generator command that reproduces it, or it is deleted.
Bounded by traversal, not by file type. The gated set is the closed dependency set of the two §3.1 rebuilds: start from the two rebuild entry points, follow every file they read, and stop. A fixture nothing on that path reads is not a Gate C item. Enumerate that closed set explicitly and record the roster in the run manifest — the manifest is what makes the gate checkable and what makes its boundary auditable.
Everything else — fixtures under unrelated suites, demo payloads, workflow debris
— is repository hygiene, and it is scheduled in the post-release harness reset
(product-development-workflow.md, "Release transition and harness reset"), which
is explicitly time-boxed. It is not a §3 release requirement.
Reproducing the MVP-1 packs is not finished when the pipeline emits a matching pack. It is finished when nothing the rebuild reads still pins a reality the pipeline cannot produce.
Why this is a gate and not a chore. A hand-made fixture makes the test suite certify the wrong thing. Tests go green against an artifact no pipeline run can regenerate, so the suite reports "reproducible" while measuring a snapshot that was typed in by hand. That is the same false-positive shape as §1's generic-landscape near-miss — self-consistent, and wrong. The larger the suite, the more convincing the wrong answer looks. Baseline is ~1,932 backend tests.
In scope — only where the §3.1 rebuild path reads them:
- Test fixtures encoding a pack — e.g.
frontend/src/test/fixtures/gns561-report-full.json— regenerated by command, not maintained by hand - Unit-test payloads that hardcode pipeline output for GNS561 or PLG-101
- Seed CSVs and
source_digestsinputs consumed by either rebuild - Cached JSON with no generator on either rebuild path
- Any frozen artifact on that path whose provenance is "someone made this once"
Out of Gate C: fixtures and payloads belonging to suites neither rebuild traverses. They are harness-reset work, not release work.
The check: enumerate the closed dependency set, then for every file in it name the command that produces it. A file whose answer is "we don't know" is deleted, and whatever depended on it is either regenerated or dropped. Record both the roster and the traversal that produced it in the run manifest.
Deleting a fixture is a valid outcome. A test resting on an artifact nobody can regenerate is not coverage — it is a claim about the past, asserted by a file.
Gate A catches narrowing; Gate B catches drift; Gate C catches unreproducible ground under both. A change passing only some is not cleared. A change that improves generality and loses recall is a failed change, not a tradeoff to negotiate.
§4 The four known-wrong claims¶
Documented in docs/development/polygon-genfit-alignment-plan.md. Four different
root causes.
| # | Defect | Root cause |
|---|---|---|
| 1 | SGC001 mis-staged "Phase Ib completed" — actual: Phase II, recruiting | Stale fetch |
| 2 | ~4× phantom inflation in acute-cardiac candidate counts | Matcher bug: substring vs token-prefix — root cause fixed, OGUR-52 |
| 3 | "Genuinely failed clinically" with zero whyStopped records |
Unsourced synthesis |
| 4 | GDELT paragraph citing a source the runner doesn't import | Phantom provenance |
MVP-1 handling (shipped): suppress or annotate, not fix. Four distinct pipeline defects could not be fixed pre-release, and they were not served under an "auditable" banner: the claims were removed or visibly marked. That was not a hand edit in the sense §3.1 forbids — it removed content rather than manufacturing it.
Root-cause fixes are roadmap input (previously "MVP-2 (Aug 31)"). Defects
1, #3 and #4 still hold their suppress-or-annotate handling and each remains a¶
defect report against the pipeline; #2 and #4 fall out of a run manifest for free.
#2's root cause was fixed inside MVP-1 (OGUR-52), ahead of that split. It was
pulled forward because the defect is not confined to the frozen text: the same
matcher runs during report reconciliation and any rebuild, so suppressing the
served number would have left the defect available to regenerate it. Anchors now
match on word boundaries ((?<!\w)…(?!\w), not \b — a form ending in a
non-word char like lp(a) breaks under a literal \b).
Measured on the 783-trial PLG-101 CT.gov corpus by
scripts/eval/polygon_discovery/audit_acute_cardiac.py:
| acute-cardiac candidates | |
|---|---|
| before (substring) | 527 |
| after (word-boundary) | 128 |
| dropped as phantom | 399 (4.12×) |
Two anchors carried effectively all of it: STEMI bound 173 trials by substring
and 16 by word — 157 phantom trials, whose most common host word was
systemic (427 occurrences across the corpus; occurrences, not trials) — and AMI bound
416 by substring and 12 by word (404 phantom, inside cyclophosphamide,
pharmacodynamics, familial). The remaining defects — #1, #3, #4 —
still hold their MVP-1 suppress-or-annotate handling.
§5 Fabricated provenance — gate PASSED at release; deletions now due¶
CLAUDE.md principle 1: every claim carries a source chip. The surfaces below
fabricated it.
How the gate was passed (2026-08-12/13): every surface in the table was
gated, not deleted — the default client build ships with demo surfaces off
(VITE_DEMO_SURFACES, #253, OGUR-70), and the per-surface real/gated/deleted
decisions are recorded in
mvp1-route-inventory-2026-08-12.md.
The deletions below were declared post-release debt at the time; that debt is
now due and goes to the roadmap-inputs doc.
The release rule, stated once. Every surface a logged-in client can reach must be real. A surface that is not real must be gated (unreachable from a client session) or deleted before any client login. Gated and deleted both pass; reachable-and-fabricated does not.
This is the same rule as §2.3's real · gated · deleted, and it is the only rule.
Route-gating is the cheap lever and it passes the Aug 13 gate. Deleting the
surfaces below is permanent debt removal and remains the intended end state, but
it is post-release debt, not an Aug 13 requirement. QA checks reachability, and
records the per-surface choice.
Wiring any of these to a real endpoint is not an option: conversational Ask is OUT per §6, so making the mock real would be building an out-of-scope feature.
| Surface | Where |
|---|---|
MOCK_FALLBACK_ENABLED = true — scripted Ask answers with a fake animated reasoning trace |
frontend/src/mocks/chat-dupilumab.ts:245 → components/ask/AskPanel.tsx:163 |
CompetitiveTimeline always renders DUPIXENT_TIMELINE |
frontend |
drugName !== 'dupilumab' hardcoded |
components/.../LandscapeTab.tsx:141 |
/franchise LOE dates, phase mix, patent cliffs are hand-written constants |
frontend/src/mocks/franchise-portfolio.ts |
Inspector "Summarize with AI" → mockSummarize(), fake 700ms delay |
frontend |
Corrected 2026-08-06. An earlier revision claimed Polygon's pack had no
patents and no papers, withheld after the Lens key expired. Verified false —
the pack digests patents_scan_cd8_depleting_PLG101.csv and
scientific_papers_PLG101.csv and carries 753 PMID / 3,499 patent references,
having been rebuilt at briefing v3_REVIEW. Acting on the stale line would have
put a fabricated absence in front of a client, which fails this gate exactly as
a fabricated presence does.
Still open (no longer gate-blocking — the gate passed; now roadmap input): Lens 401s since 2026-07 — confirm which backend produced the patent scan before a client sees it. Where a source genuinely returned nothing, state the absence in the UI; an empty result reads as "we looked and found nothing," a worse claim than an error.
Deadline pressure is not an argument in this section — the rule survives the release: any future client-reachable surface is real, gated, or deleted.
§6 What MVP-1 did NOT do¶
Historical record of the release exclusions. Note the "Live Explore search" row: its "Post-MVP-2" disposition is superseded by the 2026-08-19 redefinition — the Explore backend now is the MVP-2 direction (§1).
| Not done before Aug 13 | Why | Where it went |
|---|---|---|
| Rebuild either client report | Requires the pipeline to work; GNS561 can't rebuild on main at all |
§3.1 |
| GNS561 literature harvest | Doesn't exist; must be written | §3.2 |
| siRNA / obesity reproduction | Gate A baseline, not a client-facing surface | §3.3 |
| Trial entity inspection | 9.5 half-days, blocked behind 4 PRs | §3.4 |
| De-jargoning | Needs the §3.1 baselines to exist first | §3.5 |
| Live Explore search | No candidate retrieval exists | |
| Conversational Ask | CLAUDE.md principle 4. The mock gets gated or deleted, never wired |
Out |
| Multi-tenant isolation | Two client orgs reading their own report needs auth, not tenancy | Out |
| Postgres / Alembic | No driver, no migrations. Self-inflicted outage | Out |
| Marketing site, perf work, new sources, new skills | None serve §1 | Out |
Permanent exclusions (graph UI, COGS, KOL sentiment) live in
docs/architecture.md §10.
§6.1 How to move something into a milestone¶
All four must hold. Scope is conserved.
- A named external user said something requiring it — quoted verbatim. "Would be cool" is a desirability statement; "I cannot do X without it" is a requirement. The difference decides condition 2.
- Required for that milestone's §1 gate, not merely consistent with it.
- A
tech-leadestimate exists, naming real files, in half-days. - Something is cut to pay for it, logged in §10.
Founder enthusiasm is not evidence. Competitor parity is not evidence. "It's only a few hours with Claude Code" is specifically not evidence.
An amendment that adds without subtracting is a deadline change — a legitimate founder decision, but it must be made explicitly.
§6.2 Verdict vocabulary¶
| Verdict | Meaning | Consequence |
|---|---|---|
IN-MVP-1 |
Serves the Aug 13 gate, listed in §2 | Proceed to /spec |
IN-MVP-2 |
Serves the Aug 31 gate, listed in §3 | Spec after MVP-1 ships |
OUT |
Serves neither | Stop. One paragraph |
NEEDS-EVIDENCE |
Might serve a gate, no user has asked | Blocked. Name the question |
Default is OUT.
§7 Blocking questions¶
Q1 — Which named people at Genfit and Polygon get logins?RESOLVED — provisional named client identities seeded and verified in production (scripts/seed/seed_users.py, OGUR-61 verification67819b76).Q2 — Auth mechanism?RESOLVED — scrypt password + opaque session cookie (OGUR-64, #241, specspecs/ogur-64-minimal-auth-session.md); per-identity daily LLM spend ceiling shipped (OGUR-65, #247/#255,DAILY_LLM_SPEND_CEILING_USD=5.00).Q3 — §4: suppress or annotate?RESOLVED — handled per §4 at release; #2's root cause additionally fixed (OGUR-52).- Q4 — STILL OPEN — What recall number counts as "reproduced" for siRNA and obesity? Last measured: siRNA 16/32 assets · 10/12 deals; obesity 12/14 core · 11/11 companies. State the Gate A floor before de-jargoning starts, or it gets negotiated down the first time a change fails it. Goes to the MVP-2 redefinition session as an input.
§8 Known blockers¶
Every row here is a claim about the repository at a point in time, and the repository moves faster than this file. A resolved row that still reads as open is worse than a missing row:
/nextconsumes this section as live blockers, so a stale entry can make a recommendation prioritise, or propose unblocking work for, something already merged. Verify a row against the current code or PR state before acting on it, and strike it here when it resolves — struck through, with the resolving PR and date, so the dependency stays legible without asserting it is still open.
Every row re-verified against the working tree on 2026-08-19 (post-release
cleanup pass): four resolved rows struck; the standing rows confirmed still true
(GNS561 lit_harvest.py absent from scripts/eval/gns561_discovery/, citation
gate present in both discovery script trees and absent from the engine,
_LANDSCAPE_CONFIG still immunology-001-only, no Polygon seeder under
scripts/seed/).
| Blocker | Where |
|---|---|
spec: specs/ogur-66-packaged-api-wheel-boot.md |
|
ogur/api/report_pack.py now serves a roster, one cache entry per configured pack |
|
ogur/api/app.py |
|
User / Tenant modelogur/models/user.py) |
— |
frontend/src |
— |
GNS561 cannot be rebuilt on main. Still blocking, but narrowed 2026-08-10: the figures-payload modules landed with PR #227, so what remains is no lit_harvest.py for GNS561 (only Polygon has one) and the ~160 MB untracked .eval_cache. Blocks §3.1 |
scripts/eval/gns561_discovery/ — present on main; lit_harvest.py is not |
Citation gate exists twice, in scripts, nowhere in the engine. Engine's only literature touch is sources.py::_live_openalex — 11 lines, discovery not review |
ogur/engine/discovery_modality/sources.py |
_LANDSCAPE_CONFIG hardcoded to immunology-001; all else 404s |
ogur/api/routes/evidence.py:48 |
Polygon has no seeder — its pack yields no Signal rows |
no equivalent to scripts/seed/seed_gns561_autophagy.py |
Patent axis: Lens 401s since 2026-07. Pin to gpatents-db ($0/query) |
— |
ogur.db holds immunology-001 + cardiometabolic-rnai-001 + obesity-rnai-001 (verified 2026-08-19). Still 0 CompanyProfile rows; the pack is the only entity source |
— |
Deployment shape. Content SQLite + packs baked read-only into the image;
persistent volume for feedback; WAL mode. Snapshot the volume daily — client
feedback is the only unregenerable data in the system. Fly.io, EU region,
~$5–10/mo, kept warm. .env gitignored; inject via fly secrets; set WORKDIR
explicitly because SettingsConfigDict(env_file=".env") resolves relative to cwd.
§9 Cut ladder¶
MVP-1 ladder — CLOSED UNUSED. The release shipped without taking either cut (feedback landed at whole-report granularity per §2.2's accepted floor, and both clients shipped). Kept as the record:
- Feedback granularity → single free-text box per report
- Polygon → Genfit only (one client at the gate, not two)
MVP-2 ladder — pending redefinition (§1, §3). The pre-redefinition ladder, kept as candidate content:
- Adjacent-landscape bonus runs
- Obesity reproduction → siRNA alone (one gold deck holding Gate A)
- PLG-101 rebuild → GNS561 only
Trial entity inspection (§3.4) is not on this ladder because it is not on the gate — it is an approved stretch item and drops out without a cut decision.
Never cut, at any date — these are durable invariants of the product, not
release-specific constraints, and they survive the MVP-2 redefinition:
fabricated provenance handled per §5 — real, gated, or deleted, never reachable ·
the four known-wrong claims handled (§4) · feedback anchored to content_hash ·
at least one gold deck holding Gate A · the per-identity spend cap ·
presented-versus-served alignment evidence for every client report (§2.4) ·
truthful evidence-depth disclosure (§2.1).
If a ladder is exhausted and it still will not land, the date moves — explicitly, as a founder decision, not by shipping something that fails §5.
§10 Decision log¶
| Date | Decision |
|---|---|
| 2026-08-04 | Harness established: 4 read-only gate agents, /spec, /triage |
| 2026-08-04 | QM (YC agent harness) rejected; keep its skills-promotion pattern as ADR prior art |
| 2026-08-05 | Codebase survey ratified — 6/6 spot-checks held |
| 2026-08-06 | Exit criterion corrected: named client employees, not network testers |
| 2026-08-06 | MVP-2 gate = semantic similarity on re-run, not byte-identity |
| 2026-08-06 | De-jargon track added; vocabulary derived from Open Targets / UniProt / GO, indications via Mondo / EFO |
| 2026-08-06 | siRNA + obesity promoted to MUST — the only landscapes with a gold deck |
| 2026-08-06 | Quality gate split: Gate A (recall vs truth) + Gate B (similarity vs baseline). Both must pass |
| 2026-08-06 | Feedback confirmed required, not read-only |
| 2026-08-06 | Amendment rule + verdict vocabulary restored as §6.1/§6.2 |
| 2026-08-06 | GNS561 literature harvest ruled in — 1,089 PMID refs, corpus unregenerable |
| 2026-08-06 | No third copy of the citation gate. PROMOTE by /landscape-loop-promote point 2 — mechanism, not vocabulary |
| 2026-08-06 | §5 corrected — it falsely claimed Polygon had no patents or papers |
| 2026-08-06 | Trial entity inspection ratified on external user evidence; Monitor schema compatibility made a constraint; ADR required |
| 2026-08-06 | DATES CHANGED. MVP-1 → 2026-08-13, MVP-2 → 2026-08-31. MVP-1 redefined as the delivery surface: authenticated link + auditable report served from frozen packs. Everything requiring a rebuild moved to MVP-2, because nothing requiring a rebuild fits in 7 days |
| 2026-08-06 | §4 handling split by milestone. MVP-1 suppresses or annotates the four known-wrong claims; MVP-2 fixes the root causes. Suppression is not a hand edit — it removes content rather than manufacturing it |
| 2026-08-06 | §2.3 added — MVP-1 ships the real frontend, not a static export, and the deployed pack is byte-identical to the local one. Frozen data, not a frozen page |
| 2026-08-06 | Reachability pulled into scope. If a client can navigate, every reachable surface is subject to §5 — real, gated, or deleted. Route-gating is the cheap lever; §5's deletions still stand as debt removal |
| 2026-08-07 | Gate C added. Reproducing the MVP-1 packs gates on a fixture/payload/deterministic-input cleanup: each one has a generator command or is deleted. A hand-made fixture makes ~1,932 tests certify a snapshot no pipeline run can regenerate |
| 2026-08-07 | Never push to main without human or agent review. 15 commits had accumulated on local main after a parallel session switched the working directory; moved to chore/mvp-scope-contract, main reset to origin/main |
| 2026-08-08 | Presented-version alignment added to MVP-1 as Gate E. The served Genfit and Polygon reports must match what each client was shown, except for explicitly documented evidence-backed corrections. Linear: OGUR-63. |
| 2026-08-08 | Evidence-depth disclosure is gating; full-text enrichment is stretch. MVP-1 must say whether support is metadata, abstract, or full document (OGUR-78). Full-text report variants (OGUR-79) never block Aug 13 and become a reproducible MVP-2 capability if deferred. |
| 2026-08-10 | One reachability rule, stated in §5. Every client-reachable surface must be real; a non-real surface must be gated or deleted. Route-gating passes Aug 13; §5's deletions are post-release debt. §2.3 and §5 previously implied different release decisions for the same surface |
| 2026-08-10 | Gate C bounded to the §3.1 rebuild path. The gated set is the closed dependency set of the GNS561 and PLG-101 rebuilds, enumerated and recorded in the run manifest. Repository-wide fixture cleanup moves to the time-boxed post-release harness reset |
| 2026-08-10 | Trial entity inspection (§3.4) reclassified as approved stretch. The ratification and its user evidence stand, but it does not establish the MVP-2 rebuild property and was already the second pre-designated cut. Removed from the Aug 31 gate and from the cut ladder |
| 2026-08-10 | Role contracts moved to tracked .agents/roles/; .claude/agents/*.md are thin adapters. Claude Code and Codex now consume one file per role, matching the .agents/skills/ pattern in PR #235 |
| 2026-08-10 | §8 single-pack row struck — resolved by PR #208, merged 2026-08-05. §8 rows are dated claims about the repo and nothing invalidates one when the work merges; /next consumes them as live blockers, so a stale row makes it recommend unblocking work that is already done. §8 now carries a verify-before-acting instruction and /next must check a row against current code or PR state before it changes a ranking. The other ten rows were re-verified and hold |
| 2026-08-10 | §3.2 and §8's GNS561 rows narrowed after merging main. PR #227 landed lit_curate.py, lit_synthesize.py and abstracts.py under scripts/eval/gns561_discovery/, so the "unmerged on f5559c00" bullet is done and the blocker's "modules live on feat/gns561-lit-review" clause is false. What still blocks §3.1: no GNS561 lit_harvest.py, and the untracked .eval_cache. Caught by applying §8's own verify-before-acting rule to the merge that created the staleness |
| 2026-08-10 | The active milestone is the earliest unreleased gate, not the earliest un-passed one. An overdue gate stays active until a founder release, a §9 cut, or a §6.1 amendment. Selecting on date would have let a missed MVP-1 stop being the gate at midnight on Aug 14 and start admitting MVP-2 work — scope expansion by clock rather than by decision |
| 2026-08-11 | Founder override of an OUT /spec verdict. "Landscape at a glance" swimlane figure (SwimlaneFigure.tsx) gained vertical scroll (was horizontal-only) — a readability fix on the served-pack main figure. product-manager returned OUT (§6.1 conditions 1 and 2 unmet: no named-user requirement, not required for the §1 gate). Founder overrode directly rather than amending §2; no §6.1 amendment, no cut logged — a one-line CSS/layout change, not new scope. Logged per §6.1's "override must be a deliberate act" rule |
| 2026-08-12 | §4 defect #2's root cause fixed inside MVP-1, not deferred to MVP-2 (OGUR-52). Anchor matching is word-boundaried; the acute-cardiac candidate count falls 527 → 128 (4.12×) on the 783-trial PLG-101 corpus. Pulled forward because the matcher runs during reconciliation and rebuild, so suppressing the served number would leave the defect able to regenerate it. #1, #3 and #4 keep their suppress-or-annotate handling. The result cache is namespaced v3 → v4: the payload SHAPE did not change, so only the namespace stops cached hits replaying substring linkage |
| 2026-08-12 | Two release-blocking security defects fixed inside MVP-1, not deferred (OGUR-76). Eleven briefing/evidence routes served landscape data with no authentication, and five of them ran the Synthesizer against Anthropic outside OGUR-65's spend ceiling. Both were invisible in production only because the prod content.db has no Briefing rows and ANTHROPIC_API_KEY is unset — states, not controls, and OGUR-77 is the step that sets the key. The five generation POSTs were DELETED rather than gated: on-demand generation is not an MVP-1 surface (§6) and the offline scripts remain. Login rate limiting (unthrottled password guessing) is the one finding consciously accepted rather than fixed — out of §2, and more deadline risk than it removes. Full review: docs/product/security-review-2026-08-12.md |
| 2026-08-13 | MVP-1 RELEASED as v1.1.0. All six release gates passed (OGUR-58/59/60/61/62/63); production path verified with named Genfit and Polygon test identities (67819b76). Evidence: git tag v1.1.0, CHANGELOG §1.1.0, release-notes-v1.1.0.md. Per the 2026-08-10 active-milestone rule, the active milestone advances to MVP-2. (Entry recorded 2026-08-19 — the release-day step-down in deployment.md "After the tag" was skipped at the time.) |
| 2026-08-19 | MVP-2 redefined in direction: the Explore backend. Align the discovery, evaluation and landscape-loop work into one robust backend for discovery/exploration that generates new landscapes. Scope, gate sentence and date are set in a dedicated founder redefinition session; until then §3's pre-redefinition content stands as candidate material and no new work is gated against it. The 2026-08-31 date is dropped from the header |
| 2026-08-19 | Deferred release transition executed by the documentation cleanup pass. Contract updated to released state (§1/§2 closure record, §5 passed-gate record, §7 Q1–Q3 struck, four §8 rows struck after re-verification, §9 MVP-1 ladder closed unused); README / CLAUDE.md / official docs realigned; stale run artifacts archived; roadmap inputs collected in roadmap-inputs-2026-08-19.md |
| 2026-08-19 | Record correction: the 2026-08-11 spec-log.md OUT verdict (swimlane vertical scroll) was founder-overridden the same day and shipped in #246 (already logged 2026-08-11 below); spec-log.md now records the override so the log does not read as a rejection that stood |