Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ labels (REPRESENTATIVE / MODELED / NOT decision-grade) impossible to miss.
# Integrated judging path (run from labrador-demo-orchestrator after bootstrap)
uv run python app.py serve # UI + API on one process, port 8787
open http://127.0.0.1:8787/
open "http://127.0.0.1:8787/?mode=scientific" # explicit v3 IRAK4 replay
open "http://127.0.0.1:8787/?run=LR-..." # attach to an existing run

# Split-process frontend development
bun serve.ts 4173 # serve app/ (loopback, port 4173)
Expand Down Expand Up @@ -57,6 +59,13 @@ The app in `app/` runs against one of two data sources:
Any backend that implements `POST /api/runs` and `GET /api/runs/:id/snapshot`
gets the full three-screen UI for free.

The default URL retains the v0 demo-compatible setup. `?mode=scientific` is an
explicit opt-in that posts the checked-in IRAK4/RA `labrador.run-setup.v3`
replay frame with `presentationMode: SCIENTIFIC`, one HypGen run per selected
focus, and no representative overlay. `?run=<LR-id>` creates nothing; it
attaches read-only to that run and renders whichever snapshot contract the
server returns.

## Honesty rules the UI enforces

- **Ceilings, not quotas.** Setup numbers are caps. Stages report `requested`
Expand All @@ -73,6 +82,18 @@ gets the full three-screen UI for free.
`display_metric_basis=REPRESENTATIVE_DEMO_SCENARIO_V1`. Those values drive
graph placement and the client-side Pareto view while native metrics and
station artifacts remain unchanged and inspectable through run artifacts.
- **Scientific packets stay scientific.** A
`labrador.scientific-snapshot.v1` never uses browser or representative values
to determine comparison membership. The UI posts the terminal packets to
server Highlander, then renders its frontier, incomparable records, exact
hashes, and producer-grounded next evidence action. It does not substitute a
client frontier if that server result is absent.
- **Native branch artifacts remain native.** Scientific inspectors show exact
input/output refs and hashes, producer identity, origin, terminal reason and
message, and the unchanged payload—including clinical `simulated_*` names.
- **Representative watermark is opt-in.** It appears only when the scientific
snapshot explicitly reports both `presentation_mode: REPRESENTATIVE_DEMO`
and `representative_demo: true`.
- **Three-axis plan map.** Highlander maps every returned plan as a numbered,
selectable point using exactly P50 rNPV (ROI), recruitability, and simulation
/ tractability. Plausibility remains visible comparison context but does not
Expand Down
46 changes: 43 additions & 3 deletions app/API-CONTRACT.md
Original file line number Diff line number Diff line change
Expand Up @@ -265,9 +265,49 @@ Abstain (`abstention: true` + reason in `answer`) when the run can't support an
answer. If the endpoint is missing, the client abstains on the backend's behalf
— it never invents an answer.

## Scientific branch snapshot v1

The explicit `/?mode=scientific` path posts `labrador.run-setup.v3` and consumes
`labrador.scientific-snapshot.v1`. The default v0 path above remains supported.
The scientific response contains top-level `branches`; each branch has a real
`focus` and `nodes` keyed by `hypothesis_generator`, `clinical_simulation`,
`simulation`, and `roi_calculator`. Every public node exposes its terminal
`status`, exact `reason_code` and `message`, `output_origin`, input/output refs
and hashes, `producer`, and unchanged `artifact`.

Scientific mode has three additional invariants:

- `scientific_packet_excludes_representative_values` is `true`; presentation
values never determine hashes or comparison membership.
- A watermark is rendered only when both `presentation_mode` is
`REPRESENTATIVE_DEMO` and `representative_demo` is `true`.
- The browser displays `highlander.result` as returned by the server, including
`frontier`, `dominated`, `incomparable`, candidate objective observations,
and `nextEvidenceAction`. Until that result exists, the UI says it is waiting
and computes no substitute frontier.

### `POST /api/runs/:id/highlander`

Request:

```json
{ "acknowledgeGaps": true }
```

The response may be the scientific snapshot directly or the orchestrator UI
state containing it at `scientific`. The frontend requires the refreshed
`labrador.scientific-snapshot.v1` and will not silently fall back to its legacy
client comparator.

### Attach mode

`/?run=<LR-id>` performs no create call. It attaches read-only to the supplied
run and begins polling `GET /api/runs/:id/snapshot`. It can be combined with
`mode=scientific` to label the intent before the first snapshot arrives.

## Not in v0 (documented gaps)

- **Highlander runs client-side** off the snapshot's programs (same Pareto
- **Legacy v0 Highlander runs client-side** off the snapshot's programs (same Pareto
logic in mock and http modes). Its baseline vector is exactly
`metrics.rnpv` (ROI), `metrics.recruit` (recruitability), and the simulation
/ tractability value (`metrics.tractability_fit`, or native `metrics.support`
Expand All @@ -278,8 +318,8 @@ answer. If the endpoint is missing, the client abstains on the backend's behalf
remaining comparison-panel height beneath the objective table. The RA demo's
Z value is explicitly labeled representative branch-context fit; the shared
native cached dossier remains attached and is not presented as a
candidate-specific simulation result. A server-side Highlander job endpoint
is a future addition.
candidate-specific simulation result. Scientific v1 uses the server endpoint
documented above instead.
- **Review actions** (shortlist/constraint/exclude) are recorded in a
client-side audit log only; `POST /api/runs/:id/actions` is future work.
- **No auth/identity.** Do not present actor fields as verified.
Expand Down
5 changes: 4 additions & 1 deletion app/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<link rel="stylesheet" href="./styles.css">
</head>
<body>
<div id="representative-watermark" class="representative-watermark" role="status" hidden></div>
<main>
<section id="screen-setup" class="screen setup-screen active" data-screen="setup" aria-labelledby="setup-title">
<div class="setup-layout">
Expand Down Expand Up @@ -274,11 +275,13 @@ <h1 id="highlander-title">Tradeoffs remain visible.</h1>
</div>

<div class="region-stack middle-stack">
<section id="server-highlander-result" class="card server-highlander-result" data-region="server-highlander-result" hidden></section>

<section class="card" data-region="program-comparison" data-highlander-section="comparison" aria-labelledby="comparison-title">
<div class="card-head"><div><h2 id="comparison-title">Raw objective comparison</h2><p>Original units, uncertainty, qualifiers, and three-axis frontier membership. No global winner.</p></div><span id="comparison-mode-badge" class="badge proxy">illustrative</span></div>
<div class="comparison-wrap"><table class="comparison-table"><thead><tr><th>Program</th><th>P50 rNPV</th><th>Positive rNPV</th><th>Recruitability</th><th>Enroll</th><th>Plausibility</th><th>Simulation / tractability</th><th>Baseline status</th></tr></thead><tbody id="comparison-body"></tbody></table></div>
<figure class="pareto-figure">
<figcaption><strong>Three-dimensional Pareto view:</strong> P50 rNPV × recruitability × simulation / tractability. Each numbered point is one plan. Plans with identical vectors fan slightly around their shared coordinate. <span class="pareto-frontier-key">Nominal frontier projection</span> The line is a projected guide through complete non-dominated records, not a frontier surface or decision threshold. Missing values remain on a separate shelf. The current RA demo uses a labeled representative tractability fit on the Z axis; its native cached dossier remains shared across plans.</figcaption>
<figcaption id="pareto-caption"><strong>Three-dimensional Pareto view:</strong> P50 rNPV × recruitability × simulation / tractability. Each numbered point is one plan. Plans with identical vectors fan slightly around their shared coordinate. <span class="pareto-frontier-key">Nominal frontier projection</span> The line is a projected guide through complete non-dominated records, not a frontier surface or decision threshold. Missing values remain on a separate shelf. The current RA demo uses a labeled representative tractability fit on the Z axis; its native cached dossier remains shared across plans.</figcaption>
<svg id="pareto-plot" class="pareto-plot" data-pareto-frontier="nominal-projection" data-pareto-dimensions="roi,recruitability,simulation" viewBox="0 0 700 250" role="img" aria-label="Three-dimensional plan map for ROI, recruitability, and simulation or tractability with a nominal Pareto frontier projection"><polyline id="nominal-pareto-frontier" class="pareto-frontier-line" data-pareto-frontier-line="nominal-projection" points="" role="img" aria-label="Nominal Pareto frontier projection"></polyline></svg>
</figure>
</section>
Expand Down
Loading