Skip to content

feat(llm): land the ADR-0031 multimodal seam shape (1.AD)#11

Merged
cemililik merged 10 commits into
mainfrom
development
Jun 10, 2026
Merged

feat(llm): land the ADR-0031 multimodal seam shape (1.AD)#11
cemililik merged 10 commits into
mainfrom
development

Conversation

@cemililik

@cemililik cemililik commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

What

Lands roadmap 1.AD — the ADR-0031 multimodal seam-shape amendment, shape only, before the exhaustive consumers (1.K/1.O) exist: the media ContentPart arm + handle-only durable fork, the media_* StreamChunk triad, the CapabilityFlags.media matrix (vision = derived alias), Usage.mediaUnits, LlmRequest.outputModalities, tool_result.media, and the reserved generateMedia?/pollMediaJob? methods. Ingestion-side ceiling/url-gate/caps enforce now; adapters advertise honest all-false matrices and fail fast on media until 1.AE. The seam doc's ADR-0031 placeholder is replaced with the full amendment section.

Scope

Packages: @relavium/shared, @relavium/llm, docs/. Phase/workstream: Phase 1 · 1.AD (1.m6).

Checklist

  • Conventional Commits, one scope per commit, Refs: ADR-0031
  • standards-check passes (no-any, seam, engine zero-platform-imports)
  • pnpm run ci green (lint/typecheck incl. tsconfig.seam.json, tests, build, format, fence)
  • No vendor SDK type crosses the @relavium/llm seam
  • No secret/media bytes in logs/events/IPC/exported YAML (backstop + ingestion caps tested)
  • Specs cited from docs/reference/ (seam doc is the canonical home; placeholder replaced)
  • Security-sensitive notes for review: url carrier is flag-OFF until the SSRF primitive (1.AE); raw fields carry never-persist notes

Refs: ADR-0031

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Documentation

    • Clarified the multimodal seam, media semantics, durable vs in‑flight media, and recommended provider wiring/order.
  • New Features

    • Added multimodal I/O primitives (text/image/audio/video), output-modality selection, media streaming lifecycle, separate media-generation/job flows, and media usage billing entries.
  • Improvements

    • Enforced fail-fast media gating to reject unsupported media earlier and tightened validation across the seam.
  • Tests

    • Expanded multimodal test coverage and validation suites.

cemililik and others added 3 commits June 10, 2026 09:39
Land the multimodal seam substrate (1.AD, shape only — behavior is
1.AE+): the MIME-discriminated in-flight media ContentPart arm, the
three-carrier MediaSource vs handle-only DurableMediaSource split, the
DurableMediaPart/DurableContentPart fork (Y3 byteLength?/durationMs?;
the reasoning signature structurally dropped on the durable arm), the
INLINE_MEDIA_CEILING tier policy (video/document never inline), the
per-message count/aggregate caps, the url-carrier landing gate (OFF
until the shared SSRF primitive lands at 1.AE), the ingestion and
backstop refines (refineInFlightMediaPart, persistableMediaRefine, the
containsInlineMediaBytes deep scan incl. parameterized data-URIs), the
modality vocabularies, and the reserved MediaStore/DeInlineMedia
contracts. mimeType is bounded to a bare type/subtype so a rejected
part cannot smuggle bytes into interpolated error messages.

Refs: ADR-0031

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Amend the frozen seam before its exhaustive consumers (1.K/1.O) exist:
the media_start/media_delta/media_end StreamChunk triad (handle-only
terminal; partialRef reserved per A3), the CapabilityFlags.media
matrix (per-modality input booleans + outputCombinations) with vision
pinned as its derived alias, Usage.mediaUnits as a disjoint billing
axis, LlmRequest.outputModalities, tool_result.media on the content
part and the stream arm, and the reserved generateMedia?/pollMediaJob?
optional methods (A5) with their MediaGen*/MediaJobStatus shapes.

The seam ingestion boundary (LlmMessageSchema) enforces the ceiling,
the url landing gate, and the per-message caps now, so there is no
cap-less window before 1.AF; LlmResult and the StreamChunk tool_result
arm reject raw media bytes smuggled through result. Every adapter
honestly advertises an all-false media matrix (vision included — it
was advertised-but-unsendable) and fails fast with the typed
UnsupportedCapabilityError on any media part or tool_result media
attachment until 1.AE wires real input. A media-only turn stays
stopReason 'stop'; content inspection is the signal (tested).

Refs: ADR-0031

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Replace the 1.AD placeholder in llm-provider-seam.md with the full
"Seam-shape amendments (ADR-0031)" section (the ADR-0030 mould) and
fold the media shapes into the canonical type blocks. Fix the drift a
field-by-field pass surfaced: signal is AbortSignalLike (not the DOM
type the platform-free fence forbids), supports is readonly, the
streaming-fold table now names the reasoning_* triad (ADR-0030) and
notes that no adapter emits media_* at 1.AD, and the reserved
MediaGenRequest/MediaGenResult/MediaJobStatus shapes are spelled out.
Align architecture/multi-llm-providers.md's escape-hatch section with
the ADR-0030/0031 promotions — reasoning and media are first-class
seam shape now, not providerOptions features.

Refs: ADR-0031

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @cemililik, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds ADR-0031 multimodal I/O: media vocab/constants, in‑flight vs durable media schemas and validators, LLM seam schema updates (request/result/stream/media usage/capabilities), adapter preflight guard rejecting media, expanded exports, tests, and documentation updates.

Changes

Multimodal I/O Provider Seam

Layer / File(s) Summary
Media vocabulary and modality constants
packages/shared/src/constants.ts
Adds canonical media modality and output vocabularies plus billed-modality set (MEDIA_MODALITIES, OUTPUT_MODALITIES, MEDIA_BILLED_MODALITIES).
Shared content model & helpers
packages/shared/src/content.ts
Adds media helpers (MIME→modality, padded-base64 byte accounting, inline-media scanning), in‑flight/durable media unions/schemas, durable refinements, refineInFlightMediaPart, and host boundary interfaces MediaStore/DeInlineMedia.
Shared content tests
packages/shared/src/content.test.ts, packages/shared/src/index.test.ts
Tests for media carriers, durable/backstop rules, helpers, seam ingestion, round-trip parsing, and shared export assertions.
LLM provider seam types & media models
packages/llm/src/types.ts, packages/llm/src/types.test.ts
Extend seam with outputModalities, structural AbortSignalLike, LlmMessageSchema media caps, StreamChunk media_start/delta/end, Usage.mediaUnits, MediaCapabilities/ModalitySet, media-gen/job schemas, and optional LlmProvider.generateMedia/pollMediaJob.
Capability fixtures & docs
packages/llm/src/capabilities.ts, packages/llm/src/capabilities.test.ts
Replace boolean vision fixtures with structured media capability matrix; document capability/media gating behavior and vision→media.input.image alignment.
Adapter preflight enforcement & tests
packages/llm/src/adapters/shared.ts, packages/llm/src/adapters/shared.test.ts, packages/llm/src/adapters/{anthropic,gemini,openai}.ts, packages/llm/src/adapters/{anthropic,gemini,openai}.test.ts
Add exported assertNoMediaRequested(provider, req) guard that throws UnsupportedCapabilityError on media parts or non-text outputModalities; wire it into adapters’ generate and stream paths and update adapters' supports matrices and tests to assert fast-fail behavior.
Public API exports
packages/llm/src/index.ts
Expand named schema/type exports to include media units and media-gen/job schemas/types and broaden re-exports from @relavium/shared with media schemas, constants, and helpers.
Documentation: seam, ADR-0031, roadmap, session contract
docs/reference/shared-core/llm-provider-seam.md, docs/architecture/multi-llm-providers.md, docs/roadmap/phases/phase-1-engine-and-llm.md, docs/reference/contracts/agent-session-spec.md
Seam contract updated to list reasoning+stream triad and media shapes as capability-gated common path; ADR-0031 rewritten for flight vs durable media, media stream triad semantics, capability matrix behavior, adapter-wiring sequencing, and SessionMessage persistence changed to durable content.

🎯 4 (Complex) | ⏱️ ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant Adapter
  participant assertNoMediaRequested
  participant Transport
  Client->>Adapter: generate/stream(req)
  Adapter->>assertNoMediaRequested: validate outputModalities & content parts & tool_result.media
  assertNoMediaRequested-->>Adapter: throws UnsupportedCapabilityError on media
  Adapter->>Transport: send request (only when validation passes)
Loading

Possibly Related PRs

  • HodeTech/Relavium#8: Adds adapter media preflight and related Anthropic adapter adjustments referenced by this PR.
  • HodeTech/Relavium#7: Previous LLMProvider seam freeze that this PR extends with media/outputModality and streaming changes.

"🐰
Through the nested schemas we hop,
From base64 to handle, the bytes won't stop,
Durable and flight, each checked with care,
Caps and guards hum softly in the air,
A ribbon of modalities twinkles there."

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly and specifically describes the main change: landing the ADR-0031 multimodal seam shape for phase 1.AD, which aligns with the extensive multimodal I/O implementation across the changeset.
Docstring Coverage ✅ Passed Docstring coverage is 94.74% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch development

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

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the shape-only types, schemas, and constants for first-class multimodal I/O under ADR-0031, preparing the codebase for future behavior implementation. It updates the Anthropic, Gemini, and OpenAI/DeepSeek adapters to advertise all-false media capabilities and fail fast with an UnsupportedCapabilityError when media parts are encountered. The review feedback highlights a potential crash in the exported mediaModalityOf utility if invoked with non-string arguments, and a critical performance and memory vulnerability in containsInlineMediaBytes where scanning large typed arrays or ArrayBuffer instances could trigger severe degradation or Out Of Memory (OOM) crashes.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +74 to +75
export function mediaModalityOf(mimeType: string): MediaModality | undefined {
const lower = mimeType.toLowerCase();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

If mimeType is not a string (e.g., undefined or null due to validation failures or direct API calls), calling toLowerCase() on it will throw a TypeError and crash the process. We should defensively check the type of mimeType first.

Suggested change
export function mediaModalityOf(mimeType: string): MediaModality | undefined {
const lower = mimeType.toLowerCase();
export function mediaModalityOf(mimeType: string): MediaModality | undefined {
if (typeof mimeType !== 'string') {
return undefined;
}
const lower = mimeType.toLowerCase();

Comment thread packages/shared/src/content.ts Outdated
Comment on lines +146 to +148
if (typeof current !== 'object' || current === null) {
continue;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

If current is a typed array (such as Uint8Array or Buffer) or an ArrayBuffer, typeof current is 'object'. Calling Object.values(current) on a large typed array will create a massive array of numbers, leading to severe performance degradation or Out Of Memory (OOM) crashes. Since binary data cannot contain JSON-like base64 structures or data URIs, these should be skipped defensively.

Suggested change
if (typeof current !== 'object' || current === null) {
continue;
}
if (typeof current !== 'object' || current === null) {
continue;
}
if (ArrayBuffer.isView(current) || current instanceof ArrayBuffer) {
continue;
}

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/shared/src/content.ts`:
- Around line 159-166: The function containsInlineMediaBytes currently uses an
unsafe cast "const record = current as Record<string, unknown>"—remove that cast
and guard property access with a runtime check: in containsInlineMediaBytes,
instead of asserting, first confirm current is a non-null object (e.g., typeof
current === 'object' && current !== null) before accessing properties; then
check record-like properties by reading (current as unknown) via bracket access
only after that guard, verify record['kind'] === 'base64' and typeof
record['data'] === 'string', and when iterating use Object.values(current) only
after the same object guard before pushing nested values onto stack to avoid
unsafe assertions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5776fa6c-816b-4fa5-8bb1-4a51c3d56349

📥 Commits

Reviewing files that changed from the base of the PR and between 4b3b49d and 50814e3.

📒 Files selected for processing (19)
  • docs/architecture/multi-llm-providers.md
  • docs/reference/shared-core/llm-provider-seam.md
  • packages/llm/src/adapters/anthropic.test.ts
  • packages/llm/src/adapters/anthropic.ts
  • packages/llm/src/adapters/gemini.test.ts
  • packages/llm/src/adapters/gemini.ts
  • packages/llm/src/adapters/openai.test.ts
  • packages/llm/src/adapters/openai.ts
  • packages/llm/src/adapters/shared.test.ts
  • packages/llm/src/adapters/shared.ts
  • packages/llm/src/capabilities.test.ts
  • packages/llm/src/capabilities.ts
  • packages/llm/src/index.ts
  • packages/llm/src/types.test.ts
  • packages/llm/src/types.ts
  • packages/shared/src/constants.ts
  • packages/shared/src/content.test.ts
  • packages/shared/src/content.ts
  • packages/shared/src/index.test.ts

Comment thread packages/shared/src/content.ts Outdated
cemililik and others added 7 commits June 10, 2026 11:00
Raw binary containers (typed arrays, DataView, ArrayBuffer — all ES
built-ins, so the check stays platform-free) now fail the
containsInlineMediaBytes scan closed: a Uint8Array in a durable
tool_result.result IS media bytes, and rejecting it before the walk
also removes the Object.values-over-a-multi-MB-buffer OOM hazard.
The record narrowing is now a cast-free isRecord type guard, the scan
is split into intent-named helpers (cognitive-complexity gate), and
the base64 padding ternary is un-nested. The bounded bare-MIME schema
is exported as MediaMimeTypeSchema so every mimeType position — the
llm media_start arm included — shares the one bound. Vendor-native
media shapes (inlineData/b64_json) stay deliberately undetected here:
that is an adapter-normalization obligation, not knowledge the
platform-free package may carry.

Refs: ADR-0031

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…Type (1.AD review)

The shape-only guard becomes assertNoMediaRequested over the whole
request: outputModalities asking for a non-text modality now throws
the same typed UnsupportedCapabilityError instead of being silently
ignored and answered with text — the output-side twin of the
silent-flatten bug class, wired at both generate and stream in all
three adapters. media_start.mimeType drops its unbounded string for
the shared MediaMimeTypeSchema so a data-URI or oversized value cannot
ride the normalized stream through a metadata field. LlmResult.raw and
MediaGenResult.raw now carry the same binding never-log/persist note
as LlmError.cause.

Refs: ADR-0031

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The seam doc's amendment section now names assertNoMediaRequested as
the LIVE media gate at 1.AD (the LlmMessageSchema ceiling/caps bind a
parsed request) covering parts, tool_result attachments, and non-text
outputModalities. The 1.AE workstream gains the matching wiring-order
note: remove the guard per adapter only once that entry validates the
request through LlmMessageSchema or the 1.AF capability gating —
otherwise a cap-less window opens.

Refs: ADR-0031

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Extract the per-object inspection of containsInlineMediaBytes into
objectNodeHasInlineBytes so each function sits well under the
cognitive-complexity gate (the walk loop drops from 22 to ~10).
Behavior is unchanged and pinned by the existing scan tests (binary
buffers, canonical base64 sources, parameterized data-URIs,
cycle safety).

Refs: ADR-0031

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… (final review)

Three empirically reproduced evasions of the fail-closed scan are
closed: a bare SharedArrayBuffer now counts as a binary buffer
(typeof-guarded — hosts may hide the global), Map/Set containers are
walked (keys and values) instead of skipped as empty records, and a
value that booby-traps inspection (throwing getter/proxy) is treated
as containing bytes rather than letting the throw escape every
mounting schema's safeParse. The media arm's text hints are guarded
on both forks: name is bounded to 255 like mimeType, and neither name
nor transcript may itself be a base64 data: URI — a typed media-part
position the opaque-field scan never looks at. Mutation-pinning tests
land for the handle regex anchors and the data-URI /i flag.

Refs: ADR-0031

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…inal review)

The one mimeType position left outside the shared bare-type/subtype
bound — flagged independently by eight review lenses and reproduced
empirically (a 100 KB data-URI parsed) — now uses MediaMimeTypeSchema
like every other position, closing the every-position invariant while
the reserved A5 shape is still consumer-free. Rejection tests pin the
parameterized/data-URI/oversize cases. capabilities.ts comments stop
calling vision/reasoning providerOptions-only (stale since
ADR-0030/0031) and name the live 1.AD media gate.

Refs: ADR-0031

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…al review)

The seam doc now states the binding internal-diagnostics rule it
previously only cited (LlmError.cause + LlmResult/MediaGenResult.raw:
never logged/serialized/checkpointed — sinks strip first), records the
every-position MIME bound and the name/transcript hint guard, and
annotates media_start/MediaGenRequest accordingly.
agent-session-spec.md's persisted SessionMessage now references
DurableContentPart (handle-only media, signature-less reasoning) with
a dated ADR-0031 amendment note binding the 1.X implementation. The
phase-1 overview and 1.D task list stop describing vision/reasoning as
providerOptions-only (stale since ADR-0030/0031).

Refs: ADR-0031

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
docs/reference/contracts/agent-session-spec.md (1)

108-113: 💤 Low value

Consider clarifying the relationship between DurableContentPart and ContentPart.

The phrase "the DurableContentPart/ContentPart unions are the same Relavium types the seam uses" might be misread as suggesting the two types are identical. While the intent—that both are Relavium-owned types rather than vendor SDK types—is clear from context, you could make the distinction more explicit.

✍️ Suggested clarification
 `SessionMessage` is **mapped to the seam's `LlmMessage` at call time, never copied** — when the
 session calls a provider, the `AgentRunner` projects the persisted messages into the `LlmMessage`
 shape owned by [llm-provider-seam.md](../shared-core/llm-provider-seam.md). **No vendor SDK type
 crosses the seam** ([ADR-0011](../../decisions/0011-internal-llm-abstraction.md)); the
-`DurableContentPart`/`ContentPart` unions are the same Relavium types the seam uses — the
-projection resolves durable handles for egress, it never invents a new shape.
+projection maps between the two Relavium content unions (durable handle-only media → in-flight 
+media with resolved bytes), not to vendor shapes — it resolves durable handles for egress but 
+never invents a new type.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/reference/contracts/agent-session-spec.md` around lines 108 - 113, The
sentence risks implying DurableContentPart and ContentPart are identical; update
the text around SessionMessage, DurableContentPart, and ContentPart to
explicitly state they are distinct Relavium-owned types (not vendor SDK types)
and clarify their roles — e.g., that DurableContentPart represents
persisted/egress-capable content with durable handles while ContentPart is the
transient in-session shape — and keep the existing note that AgentRunner
projects SessionMessage into the seam's LlmMessage without crossing vendor SDK
types.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@docs/reference/contracts/agent-session-spec.md`:
- Around line 108-113: The sentence risks implying DurableContentPart and
ContentPart are identical; update the text around SessionMessage,
DurableContentPart, and ContentPart to explicitly state they are distinct
Relavium-owned types (not vendor SDK types) and clarify their roles — e.g., that
DurableContentPart represents persisted/egress-capable content with durable
handles while ContentPart is the transient in-session shape — and keep the
existing note that AgentRunner projects SessionMessage into the seam's
LlmMessage without crossing vendor SDK types.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 04272774-fe01-4bd8-a145-7d4612f626a6

📥 Commits

Reviewing files that changed from the base of the PR and between 5a351f0 and 4bce5e3.

📒 Files selected for processing (8)
  • docs/reference/contracts/agent-session-spec.md
  • docs/reference/shared-core/llm-provider-seam.md
  • docs/roadmap/phases/phase-1-engine-and-llm.md
  • packages/llm/src/capabilities.ts
  • packages/llm/src/types.test.ts
  • packages/llm/src/types.ts
  • packages/shared/src/content.test.ts
  • packages/shared/src/content.ts
✅ Files skipped from review due to trivial changes (2)
  • packages/llm/src/capabilities.ts
  • docs/roadmap/phases/phase-1-engine-and-llm.md
🚧 Files skipped from review as they are similar to previous changes (4)
  • packages/shared/src/content.test.ts
  • packages/llm/src/types.ts
  • packages/llm/src/types.test.ts
  • packages/shared/src/content.ts

@cemililik
cemililik merged commit 32b8cac into main Jun 10, 2026
7 checks passed
cemililik added a commit that referenced this pull request Jun 10, 2026
Per the done-after-merge rule: PR #11 (the ADR-0031 multimodal seam
shape) is merged, so 1.AD flips to Done everywhere it is tracked —
the phase-1 workstream bullet, the 1.m6 milestone row, the dependency
matrix, the Lane-D scheduling note, and the head blockquote; the
deferred-tasks Y3 item is checked off with what actually landed;
current.md records PR #11 and points the seam lane straight at 1.K;
the root README and CLAUDE.md status paragraphs carry the amendment.

Refs: ADR-0031

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
cemililik added a commit that referenced this pull request Jun 11, 2026
The root README / CLAUDE.md / AGENTS.md / roadmap-README status lines still stopped
at M1 (PR #9) and framed the FallbackChain (1.K) as upcoming/active. A doc audit
(verified against the repo) found these were the only stale status surfaces left
after the 1.K done-marking:
- README.md: 1.K dropped from "next on the critical path" (it landed, PR #13); the
  engine (@relavium/core, not yet scaffolded) is now the sole next item.
- CLAUDE.md: the Status headline notes 1.K landed completing 1.m2; the "active work
  continues on" clause points at the engine (1.L next), not 1.K.
- AGENTS.md: the mirror gains the 1.AD (PR #11) + 1.K (PR #13) landings; active work
  redirected to the engine lane.
- roadmap/README.md: the M1 row's "complete just after, at 1.m2" → past tense.

The deferred-tasks audit found nothing closeable by completed work (the pricing
item was already checked off; everything else is correctly future work).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
cemililik added a commit that referenced this pull request Jun 25, 2026
…meticity coverage

Three review findings on dangerous-path / hermeticity test gaps:

- #2 (medium, 2-lens): no real-DB integration test pinned the single highest-stakes invariant —
  a PAUSED run's media must survive (it backs a cross-process human-gate resume). Add a
  sweepHostMediaBestEffort test seeding a human-gate-paused run with a media ref AND a row-less CAS
  orphan, asserting the ref survives, the run is never reclaimed (reclaimedRuns 0), the destructive
  orphan sweep defers (orphanSweepRan false, orphansDeleted 0), and even the orphan blob survives. A
  future TERMINAL_RUN_STATUSES regression that deletes paused-run media now fails CI.
- #11 (nit): the host mediaWrite jail test covered only the `..` form — add the absolute-path
  rejection (distinct cause: "must be relative") and a pre-aborted-signal short-circuit ("was aborted",
  no bytes written).
- #9 (low): run.test.ts / gate.test.ts didn't override HOME/USERPROFILE, so os.homedir() (→ the CAS
  root) resolved to the real developer home; gate.test.ts also used process.cwd() for save_to. Both now
  point HOME+USERPROFILE and cwd at per-test tmpdirs (the generative-e2e hermetic pattern).

Note: the bare `state:'paused'` (no gate) branch of test-support seedRun emits a run:paused that fails
the "≥1 suspension reason" RunEventSchema refinement — a latent test-support gap (no production caller);
the paused-run test uses the realistic human-gate form, which is also the resume scenario under test.

Refs: ADR-0042

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to 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.

1 participant