V1 Web PWA · Surface walkthrough

Studio Neith · Inverse Modeling

A per-surface walkthrough of the V1 Web PWA studio surface: layout, states, interactions, data, and cross-references.

walked
8sections11 minread

On this page

Context. surface studio · domain neith · route /studio/neith/inverse-modeling · auth signed-in + studio entitlement (fit-quality lane is admin-scoped: admin:* | admin:studio, fail-closed) · source apps/oshun/web/src/app/studio/neith/inverse-modeling/page.tsx

Last walked. 2026-06-25 by Codex (V1 reference-image feature extraction, four-model parameter estimates, confidence scoring, export manifest, domain tests, and E2E), against commit HEAD' '2026-06-25 by Codex (recoverable catalog retry, submit busy state, mobile tap targets, and live-BFF evaluator coverage), against commit HEAD' '2026-06-23 by Codex (direct-route auth readiness + live E2E), against commit HEAD

Purpose#

Studio-only Neith inverse procedural modeling console. The route now has two lanes:

  • Reference Inversion Lane — paste a compact RGBA reference-image payload, extract the V1 feature vector (mean, contrast, edgeEnergy, entropy, warmBias), estimate parameters for all four Neith model families (terrain, vegetation, urban, noise), score confidence, and emit a deterministic export manifest for downstream Studio handoff.
  • Goodness-of-Fit Lane — admin-scoped JSON sample evaluator backed by the real BFF (/v1/admin/studio/fit-quality) that reports per-sample residuals, RMSE, MAE, R², and the worst-fitting sample.

The page mounts ShellLayout (active=studio), the StudioNeithInverseModelingWorkspace body, the canonical route-map, and a quick-action lane to two Isis sibling workspaces.

Entry points#

  • Linked from /studio body — Domain-bridge studios section lists Neith
  • Quick action lanes from siblings: isis/reference-image-processing, isis/live-preview (cross-domain links into Isis)
  • Direct URL / bookmark — yes; metadata sets alternates.canonical to /studio/neith/inverse-modeling

Layout regions#

page.tsx renders inside <ShellLayout active="studio">:

  • Header: shell header (active=studio)
  • Main: <StudioNeithInverseModelingWorkspace /> — client component ('use client') with useAuth() access-token readiness plus state hooks for outcome (catalog load result), fit-quality payloadText, result, evaluateError, reference-image referenceText, inverseReport, and inverseError
    • Eyebrow "Neith Procgen"
    • <h1> "Inverse Modeling Workspace" (via WorkspaceHeading)
    • Summary <p data-neith-inverse-modeling-summary> describing the feature-extraction, four-model estimate, export-manifest, and goodness-of-fit flow
    • Reference Inversion Lane (data-neith-reference-lane) with <h2 data-neith-reference-lane-heading> "Reference Inversion Lane":
      • <form data-neith-reference-form> with <textarea data-neith-reference-payload> (aria-label="Neith reference image json", rows={14}, monospace, seeded with DEFAULT_NEITH_REFERENCE_IMAGE) and <button data-neith-reference-submit> "Run inverse modeling"
      • Error: <div data-neith-reference-error role="alert"> with parser or validation error; prior inverseReport remains rendered
      • Feature grid: <div data-neith-feature-grid> with cells keyed by data-neith-feature="mean|contrast|edgeEnergy|entropy|warmBias"
      • Model grid: four <article data-neith-model-card data-neith-model="terrain|vegetation|urban|noise"> cards with data-neith-model-confidence, parameter rows (data-neith-param-row data-neith-param-name), and rationale copy
      • Export manifest: keyboard-focusable <pre data-neith-export-manifest tabindex="0" aria-label="Neith inverse modeling export manifest">
    • Goodness-of-Fit Lane (WorkspaceSection) with <h2 data-fq-lane-heading> "Goodness-of-Fit Lane". Its body depends on the catalog-load outcome:
      • Loading: <p data-fq-loading> "Loading fit-quality evaluator…"
      • Unauthorized: <div data-fq-unauthorized> "Access restricted." + reason
      • Error: <div data-fq-error> "Could not load the fit-quality evaluator." + reason
      • Ready (catalog present):
        • <p data-fq-enums> " metrics" (from catalog.metrics.length)
        • <form data-fq-form> with a labelled <textarea data-fq-payload> (aria-label="fit quality samples json", rows={16}, monospace, seeded with DEFAULT_PAYLOAD) and a <button data-fq-submit type="submit"> "Evaluate fit quality" / "Evaluating fit quality…"
        • On catalog error: <div data-fq-error role="alert"> with the message and <button data-fq-retry> "Retry evaluator"
        • On evaluate error: <div data-fq-evaluate-error role="alert"> with the message
        • On result: <div data-fq-result role="status"> containing a <div data-fq-headline> ("RMSE … · MAE … · R² … · worst …" with data-fq-rmse / data-fq-mae / data-fq-r2 / data-fq-worst spans) and a <table data-fq-samples> of <tr data-fq-sample-row data-sample-id> rows (sample / data-fq-sample-residual / data-fq-sample-abs)
  • Route Map panel (data-neith-inverse-modeling-route-map): renders 5 entries from STUDIO_NEITH_INVERSE_MODELING_ROUTE_MAP — primary, sessions/[sessionId], presets/[presetId], exports/[exportId], audit/[auditId]
  • Quick-action lane: three Link.quickAction anchors — Isis Reference Image Processing, Isis Live Preview, Back to Studio workspace index

States#

  • Reference ready (default known image)analyzeNeithReferenceImage(DEFAULT_NEITH_REFERENCE_IMAGE) runs at mount. The feature grid shows the known reference vector: mean 0.373, contrast 0.118, edgeEnergy 0.135, entropy 0.583, warmBias 0.004. Domain-covered in neith-inverse-modeling.test.ts and E2E-covered in studio-neith-inverse-modeling.spec.ts.
  • Reference estimate populated — four data-neith-model-card cards render for terrain, vegetation, urban, and noise. The known reference estimates include terrain erosionStrength 0.565, vegetation canopyDensity 0.502, urban blockDensity 0.649, and noiseKind perlin.
  • Reference export manifestdata-neith-export-manifest renders manifestVersion: neith.inverse.v1, modelCount: 4, checksum fnv1a-82598ffa, source dimensions, feature vector, four estimates, and Studio handoff targets. The manifest <pre> is focusable and labelled so its scrollable region has keyboard access.
  • Reference error (malformed/invalid image payload) — invalid JSON or validation failures set <div data-neith-reference-error role="alert">; the prior inverse report stays visible so an operator does not lose the last known-good feature vector.
  • Loading — server component for outer page; workspace mounts with outcome === null and renders <p data-fq-loading> "Loading fit-quality evaluator…" while auth hydrates and then while fetchCatalog() runs (GET /v1/admin/studio/fit-quality). Unit-covered in StudioNeithInverseModelingWorkspace.test.tsx
  • Ready (catalog loaded) — GET returns a Catalog ({ metrics: string[] }); <p data-fq-enums> shows " metrics" and the data-fq-form payload form renders, seeded with DEFAULT_PAYLOAD (4 sample rows)
  • Gated (unauthorized) — GET returns 401/403; <div data-fq-unauthorized> "Access restricted." renders with the server message, or the fallback "Studio admin scope required to evaluate fit quality." The form is NOT rendered (no catalog)
  • Error (recoverable) — GET non-OK (other than 401/403), malformed catalog body, or fetch rejection; <div data-fq-error> "Could not load the fit-quality evaluator." renders with the reason (Fit-quality catalog request failed (<status>)., Fit-quality catalog response was malformed., Could not reach the fit-quality evaluator., or Network unavailable.). The retry button (data-fq-retry) reissues the catalog request and returns to the ready form when the real evaluator catalog responds.
  • Evaluate success — POST /v1/admin/studio/fit-quality/evaluate returns 200 with a valid result; <div data-fq-result> renders the headline metrics and per-sample table
  • Evaluate error (invalid JSON)JSON.parse(payloadText) throws; setEvaluateError('Payload must be valid JSON.'); <div data-fq-evaluate-error> renders; no network call is made
  • Evaluate error (server) — POST is non-200 or the body fails isResult(); error is the server detail string or Evaluation failed (<status>).; on fetch rejection, Could not reach the fit-quality evaluator.; data-fq-result is cleared
  • Network unavailabletypeof fetch === 'undefined': catalog load yields the error state; submit sets evaluateError = 'Network unavailable.'
  • Offline — both catalog GET and evaluate POST require the BFF; offline, they surface as the error states above; PWA cache serves the shell
  • Standalone PWA — workspace section and route-map panels stack; form maxWidth: 900, textarea full-width
  • Empty — N/A; the payload textarea is seeded with DEFAULT_PAYLOAD
  • Populated (long) — N/A; sample-count is driven by the user-supplied JSON, not a paginated list

Interactions#

Reference Inversion Lane — image payload form#

  • Reference image JSON textarea (<textarea data-neith-reference-payload>, aria-label="Neith reference image json")
    • Function: controlled input bound to referenceText; accepts { width, height, sourceArtifactId, label, pixels } where pixels is a row-major RGB/RGBA tuple array.
    • Keyboard: standard multiline editing in tab order inside data-neith-reference-form.
    • Touch target: full-width textarea; measured at 390 px in the E2E path.
    • Validation: payload must parse as JSON, include non-empty sourceArtifactId and label, positive integer width / height, and exactly width * height pixels with channel values in 0..=255.
  • "Run inverse modeling" (<button data-neith-reference-submit>)
    • Function: submits data-neith-reference-form; calls analyzeNeithReferenceImage(), updates the feature vector, all model estimates, confidence values, and export manifest.
    • Failure: parser/validation errors render data-neith-reference-error without clearing the prior report.
    • Keyboard: Enter/Space activates; Enter inside the form submits.
    • Touch target: 44 px minimum height; measured at 390 px.
  • Feature cells (data-neith-feature)
    • Non-interactive; exact keys are mean, contrast, edgeEnergy, entropy, and warmBias.
  • Model estimate cards (data-neith-model-card)
    • Non-interactive; one card each for terrain, vegetation, urban, and noise; each card exposes confidence and parameter rows through data-neith-model-confidence and data-neith-param-row.
  • Export manifest (data-neith-export-manifest)
    • Non-interactive JSON manifest for downstream Studio handoff; focusable with an accessible label because it can scroll.

Goodness-of-Fit Lane — payload form#

  • Samples JSON textarea (<textarea data-fq-payload>, aria-label="fit quality samples json")
    • Function: controlled input bound to payloadText via onChange; seeded with DEFAULT_PAYLOAD (4 { sampleId, observed, predicted } rows); rows={16}, monospace
    • Keyboard: standard multiline text editing; in tab order inside data-fq-form
    • Screen reader: labelled "fit quality samples json" (also a visible <span> label "Samples (JSON: { samples[{ sampleId, observed, predicted }] })")
    • Touch target: full-width textarea with 240 px minimum height; measured at 390 px.
    • Telemetry: not instrumented in current code
  • "Evaluate fit quality" (<button data-fq-submit type="submit">)
    • Function: submits data-fq-form; submitEvaluate() clears prior error + result, JSON.parsees payloadText, then POSTs the parsed object to /v1/admin/studio/fit-quality/evaluate with the hydrated AuthProvider access token (local-dev fallback via buildBffAuthHeaders()) + content-type: application/json, cache: 'no-store'
    • On 200 + valid result: sets result (renders data-fq-result)
    • On invalid JSON: short-circuits to data-fq-evaluate-error "Payload must be valid JSON." before any fetch
    • On non-200 / malformed / rejection: sets evaluateError
    • Keyboard: Enter/Space activates (also Enter within the form submits)
    • Touch target: 44 px minimum height; measured at 390 px.
    • Disabled when: while a POST is pending, native disabled plus aria-disabled="true" / aria-busy="true"; the label reads "Evaluating fit quality…".
    • Telemetry: not instrumented in current code
  • "Retry evaluator" (<button data-fq-retry type="button">)
    • Function: shown only in catalog-load error state; clears the error back to data-fq-loading and reissues GET /v1/admin/studio/fit-quality
    • Touch target: 44 px minimum height; measured in the recoverable-error E2E leg.
  • Result table rows (<tr data-fq-sample-row data-sample-id=<id>>)
    • Non-interactive; one row per result.samples[] entry with sample id, data-fq-sample-residual, and data-fq-sample-abs cells
  • Result headline (<div data-fq-headline>)
    • Non-interactive; shows data-fq-rmse / data-fq-mae / data-fq-r2 / data-fq-worst from the FitResult

Route Map panel#

  • Route entries (5 × <article>)
    • /studio/neith/inverse-modeling — primary inverse-modeling workspace
    • …/sessions/[sessionId] — reference provenance + tuning deltas + snapshots
    • …/presets/[presetId] — reusable parameter packs
    • …/exports/[exportId] — generated manifests + Neith pipeline handoff
    • …/audit/[auditId] — estimator confidence + reproducibility evidence
    • Non-interactive listing

Quick-action lane#

  • "Open Isis Reference Image Processing workspace" (link → /studio/isis/reference-image-processing)
  • "Open Isis Live Preview workspace" (link → /studio/isis/live-preview)
  • "Back to Studio workspace index" (link → /studio)
    • Keyboard: included in tab order after route map; touch ≥ 44×44 px (quickAction class)
    • Mobile: anchors wrap (flexWrap: 'wrap')

Data & contracts#

  • Local reference analysis: apps/oshun/web/src/lib/studio/neith-inverse-modeling.ts exports analyzeNeithReferenceImage(), parseReferenceImage(), extractReferenceFeatures(), estimateModelParameters(), and buildExportManifest().
    • Input: { sourceArtifactId, label, width, height, pixels }; pixels is a row-major RGB/RGBA tuple array with channel values in 0..=255.
    • Feature vector: { mean, contrast, edgeEnergy, entropy, warmBias }.
    • Model estimates: four records keyed by terrain, vegetation, urban, and noise, each with confidence and model-specific parameters.
    • Manifest: manifestVersion: neith.inverse.v1, source metadata, feature vector, modelCount, estimates, handoff targets (/studio/isis/reference-image-processing, /studio/bellona/interchange, /studio/hathor/world-configuration), and deterministic FNV-1a checksum.
  • Reads: GET /v1/admin/studio/fit-quality — returns Catalog ({ metrics: string[] }); sent with the hydrated AuthProvider access token, cache: 'no-store'. 401/403 → unauthorized state; other non-OK / malformed → error state
  • Writes: POST /v1/admin/studio/fit-quality/evaluate — accepts the user-supplied JSON object (default shape { samples: [{ sampleId, observed, predicted }] }); returns { result: FitResult } on 200, else { detail }. FitResult = { samples: { sampleId, residual, absError }[], worstSample, rmse, mae, r2, summary: { sampleCount, rmse, mae, r2 } }
  • Realtime: none
  • Caching: static server render; both calls use cache: 'no-store'; metadata sets canonical URL
  • Auth/role check: /studio/* requires signed-in (middleware); the fit-quality endpoints are admin-scoped (admin:* | admin:studio) and fail-closed — a non-admin sees the data-fq-unauthorized state

Cross-references#

  • Parent: ../../studio-overview.md
  • Shell: ../../../shell/04-auth-session.md
  • Cross-domain partners (per quick-action lane):
    • /studio/isis/reference-image-processing
    • /studio/isis/live-preview
  • Component sources:
    • apps/oshun/web/src/components/studio/StudioNeithInverseModelingWorkspace.tsx (client component: reference inversion lane + auth-ready catalog load + JSON-payload evaluate form wired to /v1/admin/studio/fit-quality)
    • apps/oshun/web/src/lib/studio/neith-inverse-modeling.ts (deterministic reference-image feature extraction, four-model parameter estimates, confidence scoring, export manifest checksum)
    • apps/oshun/web/src/components/studio/StudioNeithInverseModelingRouteMap.ts
  • E2E: apps/oshun/web/e2e/studio-neith-inverse-modeling.spec.ts covers direct admin navigation, reference feature extraction, four model estimates, manifest JSON, live catalog/evaluate success, non-admin fail-closed, recoverable catalog retry, 390 px form/quick-action touch targets, pending submit disabled/busy semantics, invalid reference payload, invalid fit-quality JSON with no POST, BFF invalid-payload detail, route-map, and Isis quick links
  • Domain tests:
    • apps/oshun/web/src/lib/studio/neith-inverse-modeling.test.ts proves the known reference image maps to exact feature values, model estimates, and manifest checksum.
    • pnpm nx run @neith/procgen:test passed for the underlying Neith procgen crate family named by V1 §34.
  • Feature spec: V1/TODOS.md §34 and V1/architecture/cross-domain-support.md define Bellona/Hathor/Neith as Studio-only V1 substrates (confirmed in-v1 2026-05-29); the route matrix marks /studio/neith/inverse-modeling as in-v1.

Open questions / known gaps#

  • The header's stated auth (signed-in + studio entitlement) is broader than the lane's actual requirement (admin:* | admin:studio). Confirm whether the whole route should be admin-gated at middleware, or only the fit-quality lane (current behavior: non-admins reach the page but see data-fq-unauthorized).
  • The route map lists sessions/[sessionId], presets/[presetId], exports/[exportId], and audit/[auditId] sub-routes that are absent from the repo — confirm whether these are V1, V2, or out of scope.
  • No telemetry events fire for catalog load, payload edits, or evaluate submit; instrument when wiring to BFF analytics. The reference inversion lane also has no telemetry on payload edits or manifest generation.
  • Quick-action lane crosses into Isis (/studio/isis/reference-image-processing, /studio/isis/live-preview); verify Isis is the canonical owner of image processing while Neith owns inverse-modeling.