Skip to content
Merged
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
176 changes: 175 additions & 1 deletion vendor/intx-inference/PATCHES.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,20 @@ confirm every hunk still maps to an entry here (or, if upstream has since
absorbed the same fix, drop the entry and its markers — verify by reading
the new upstream code, not by assuming).

**Vocabulary:** this ledger's disposition labels map onto the CL-7302
ticket taxonomy as follows — "Promotion candidate" = Upstreamable,
"Long-lived" = Re-carryable, "Kill candidate" = Droppable, and "Companion"
entries are Re-carryable but ride their primary patch's disposition (they
ship out or die with it).

**Re-carry status (CL-5697):** at the sync to upstream HEAD `0205b07b`,
all 17 entries below were re-carried via three-way merge with zero
conflicts. Upstream moved only `reactor.ts` (new doom-loop detection:
`doomLoopThreshold`, `toolBatchSignature`, run-scoped accounting, fatal
break) and `assembly.ts` (passthrough change). Every entry now carries a
re-carry note stating the merge cost and the survivability risk going
into the next sync.

## adapter-ts-stream-terminal-detector

`adapter.ts` — Adds `StreamTerminalDetector`/`ProviderAdapter.isStreamTerminal`.
Expand All @@ -29,6 +43,14 @@ the socket or sending `[DONE]`; without this, a client reading the stream
hangs waiting for a socket close that never comes. Consumed by `harness.ts`'s
SSE loop.

**Disposition:** Promotion candidate. Requires upstream to add a
`StreamTerminalDetector` hook (or equivalent) to `ProviderAdapter`. No kill
date until upstream adopts; downstream users not using OpenAI Responses
protocol can ignore. **Removal path:** Upstream PR to
`@intx/inference` adding `isStreamTerminal` to `ProviderAdapter`.
**Re-carry:** clean three-way at `0205b07b`, zero conflicts. Low risk —
`adapter.ts` is stable upstream and untouched by the doom-loop work.

## assembly-ts-deps-context-transforms

`assembly.ts` — Resolves `contextTransforms` from either the direct assembly
Expand All @@ -38,6 +60,21 @@ forwards `deps` into reactor assembly verbatim and exposes no dedicated field
for transforms; riding `deps` reaches the vendored assembly without requiring
a change to the published package.

**Disposition:** Kill candidate when `@intx/agent` exposes a dedicated
`contextTransforms` field on its assembly config (or when all callers use the
vendored package directly). **Removal path:** Upstream PR to `@intx/agent` to
forward `contextTransforms` explicitly; then delete both this patch and
`harness-ts-context-transforms`.
**Obligation:** both `contextTransforms` patches have live consumers today —
the `contextTransforms` entry in the `deps` argument to
`createAgentWithLiveToolDispatch` in `src/session/assemble-runtime.ts` and in
`src/subagent/run.ts` — so they
must be re-carried on every sync until upstream exposes the field; only then
can they be killed.
**Re-carry:** clean three-way at `0205b07b`, zero conflicts (upstream touched
`assembly.ts` with a passthrough change; the hunk applied cleanly). Low
risk, but the consumer obligation above keeps this on the sync checklist.

## errors-ts-classify-abort-reason

`errors.ts` — `classifyAbortError` takes an optional `reason` argument and
Expand All @@ -47,11 +84,27 @@ carries it as `raw: { origin: reason }` on the returned `InferenceError`.
undifferentiated "inference aborted". Called with `signal?.reason` from all
four abort-check sites in `harness.ts`.

**Disposition:** Promotion candidate. Small, additive change — adding an
optional `reason` param to `classifyAbortError` and enriching `raw`. **Removal
path:** Upstream PR adding the optional `reason` parameter and `ClassifiedAbortRaw`
type. No kill date until upstream ships it.
**Re-carry:** clean three-way at `0205b07b`, zero conflicts. Low risk —
`errors.ts` sees little upstream churn.

## harness-ts-context-transforms

`harness.ts` — `Dependencies.contextTransforms` carries the field
`assembly.ts` reads off `deps` (see assembly-ts-deps-context-transforms).

**Disposition:** Kill candidate — pair with `assembly-ts-deps-context-transforms`.
**Removal path:** Upstream PR to `@intx/agent` exposing `contextTransforms`
explicitly. Ships out together with the assembly patch.
**Obligation:** live consumers at the `contextTransforms` entries in the
`deps` argument to `createAgentWithLiveToolDispatch` in
`src/session/assemble-runtime.ts` and `src/subagent/run.ts` — re-carry until
upstream exposes the field, then kill.
**Re-carry:** clean three-way at `0205b07b`, zero conflicts. Low risk.

## harness-ts-inactivity-on-semantic-progress

`harness.ts` — Inactivity timer armed only on semantic progress. The watchdog
Expand All @@ -60,12 +113,24 @@ forever without a terminal event never tripped it, pinning the caller
indefinitely. Now it re-arms only when `adapter.parseResponse` actually
produces events from a chunk.

**Disposition:** Promotion candidate. Clear upstream bug fix — the inactivity
timer should not re-arm on raw bytes. **Removal path:** Upstream PR to
`@intx/inference` gating re-arm on parsed-event output.
**Re-carry:** clean three-way at `0205b07b`, zero conflicts. Moderate risk —
upstream reworked retry/failover inside `harness.ts`'s `runInference` wrapper;
re-verify the SSE-loop arming site on the next sync.

## harness-ts-is-stream-terminal

`harness.ts` — `isStreamTerminal` consulted in the SSE loop. Stops reading
once `adapter.isStreamTerminal?.(sseData)` returns true, for protocols whose
end-of-turn is a semantic event rather than `[DONE]` or socket close.

**Disposition:** Companion to `adapter-ts-stream-terminal-detector`. Ships
out together when upstream adopts the `isStreamTerminal` hook.
**Re-carry:** clean three-way at `0205b07b`, zero conflicts. Low risk;
same sync-checklist caveat as the inactivity patch above.

## harness-ts-commitment-boundary-streaming

`harness.ts` — `runInference`'s commitment-boundary streaming redesign. The
Expand All @@ -81,12 +146,27 @@ memory. A retryable failure after commitment can no longer discard
already-streamed output, so retry is suppressed there and the error surfaces
on the live stream. See `isCommitting` and the docblock on `runInference`.

**Disposition:** Long-lived. This is a design-level change to `runInference`
that upstream would need to adopt wholesale, not a simple param fix.
**Removal path:** Upstream redesigns `runInference` with commitment-boundary
streaming built in. No kill date — this is the core streaming architecture
for Corbits and likely to remain a fork patch for the foreseeable future.
**Re-carry:** clean three-way at `0205b07b`, zero conflicts. Priority risk —
upstream moved retry emission into `harness.ts`'s `runInference` wrapper,
which is exactly the function this patch redesigns; re-verify the
retry-suppression-after-commitment interaction on every sync.

## harness-ts-is-committing

`harness.ts` — `isCommitting` helper used by the commitment-boundary redesign
above. Classifies which events count as commitment (everything except
pre-commit metadata).

**Disposition:** Companion to `harness-ts-commitment-boundary-streaming`.
Ships out together.
**Re-carry:** clean three-way at `0205b07b`, zero conflicts. Priority risk —
tracks the commitment-boundary patch.

## reactor-ts-ephemeral-turns

`reactor.ts` — `ExtendedInferenceOptions.ephemeralTurns`: turns appended to
Expand All @@ -95,6 +175,16 @@ history, so transient director guidance does not touch the cached transcript
prefix. No native equivalent exists upstream. `index.ts` re-exports the type
(mechanical; no separate marker).

**Disposition:** Long-lived. Upstream carries no transient-turn or
prompt-injection mechanism as of `0205b07b` (verified by reading the
upstream reactor at that SHA); no upstream issue or PR toward one exists in
the clone. **Removal path:** Only if Corbits adopts an alternative mechanism
for transient prompt injection. No kill date.
**Re-carry:** clean three-way at `0205b07b`, zero conflicts. Priority risk —
upstream's new doom-loop detection added run-scoped accounting and a fatal
break path in `reactor.ts`; re-verify that ephemeral turns do not interact
badly with doom-loop signatures or the run accounting on the next sync.

## reactor-ts-correlating-ids-leak

`reactor.ts` — `correlatingIds` leak on every successful correlated resume.
Expand All @@ -104,6 +194,14 @@ but never on the three success dispatch paths (`redispatch` / `error_result` /
of the process. Wrapped the whole critical section in `try/finally` so every
exit clears it.

**Disposition:** Promotion candidate. Clear upstream bug fix. **Removal
path:** Upstream PR wrapping `tryCorrelate` in try/finally to clear
`correlatingIds` on all exit paths.
**Re-carry:** clean three-way at `0205b07b`, zero conflicts. Moderate risk —
`tryCorrelate` sits adjacent to upstream's new signal-driven resume dispatch
in `reactor.ts`; re-verify exit paths after upstream changes to gate
clearing.

## reactor-ts-checkpoint-after-tool-cycle

`reactor.ts` — Checkpoint after a tool cycle that appends to history.
Expand All @@ -112,13 +210,30 @@ interrupt that rebuilds the agent from the store reloads the completed tool
exchange instead of losing an uncommitted tool turn (context previously
committed only at cycle terminals).

**Disposition:** Promotion candidate. Durability correctness fix —
interrupting after a tool cycle must not lose committed tool turns.
**Removal path:** Upstream PR adding `commitCycle()` call in
`executeTools` when `addToHistory` is true.
**Re-carry:** clean three-way at `0205b07b`, zero conflicts. Moderate risk —
upstream's doom-loop fatal break fires from inside the tool cycle; re-verify
that a doom-loop break still commits (or intentionally does not commit) the
in-flight cycle.

## reactor-ts-skip-unchanged-history

`reactor.ts` — Skip re-serializing unchanged history on checkpoint.
`commitCycle` now compares `stateManager.getTurnsRevision()` against the
revision most recently written and skips `contextStore.writeTurns` when
nothing changed, avoiding an O(history) re-serialize (including historical
tool-output blobs) on every checkpoint.
tool-output blobs) on no-op checkpoints.

**Disposition:** Promotion candidate. Performance optimization with no
behavioral change — reduces checkpoint cost from O(history) to O(1) when
no turns were added. **Removal path:** Upstream PR adding revision check
in `commitCycle`.
**Re-carry:** clean three-way at `0205b07b`, zero conflicts. Low risk;
depends on the `turnsRevision` plumbing in `state.ts`, which is itself a
patch (below).

## reactor-ts-after-checkpoint-director-only

Expand All @@ -129,19 +244,36 @@ durability plumbing, not a checkpoint the caller asked for; without gating on
later `decide()` call got `afterCheckpoint` invoked twice for what is, from
its perspective, a single checkpoint.

**Disposition:** Promotion candidate. Event correctness fix — prevents
spurious double `afterCheckpoint` events that confuse directors.
**Removal path:** Upstream PR gating `afterCheckpoint` on
`hasOverride`/`pendingMessage !== null`.
**Re-carry:** clean three-way at `0205b07b`, zero conflicts. Low risk.

## reactor-ts-last-written-turns-revision

`reactor.ts` — `lastWrittenTurnsRevision` state backing the skip-rewrite
optimization (reactor-ts-skip-unchanged-history). Tracks the turns revision
most recently serialized to the context store.

**Disposition:** Companion to `reactor-ts-skip-unchanged-history`. Ships out
together.
**Re-carry:** clean three-way at `0205b07b`, zero conflicts. Low risk;
tracks the skip-unchanged-history patch.

## sse-ts-max-line-length

`sse.ts` — `MAX_LINE_LENGTH` (16 MiB) caps the unterminated SSE line buffer
and throws instead of growing unbounded — an unbounded run of bytes with no
newline is indistinguishable from a stuck or hostile stream and would
otherwise OOM the process.

**Disposition:** Promotion candidate. Security/correctness fix — prevents
OOM from a stuck or malicious stream. **Removal path:** Upstream PR adding
`MAX_LINE_LENGTH` cap to SSE line parsing.
**Re-carry:** clean three-way at `0205b07b`, zero conflicts. Low risk —
`sse.ts` has a single upstream commit and is effectively frozen.

## state-ts-deep-freeze-turns-revision

`state.ts` — `deepFreeze`s appended turns and tracks a `turnsRevision`
Expand All @@ -152,13 +284,55 @@ never inspect `turns`, so the prior eager deep-clone made per-event cost
scale with session length. `getTurnsRevision()` also backs
`reactor.ts`'s checkpoint-skip optimization.

**Disposition:** Promotion candidate. Performance optimization — eliminates
O(n) structuredClone on every event for directors that don't inspect turns.
**Removal path:** Upstream PR lazy-ifying `ReactorState.snapshot().turns`
with revision tracking.
**Re-carry:** clean three-way at `0205b07b`, zero conflicts. Low risk —
`state.ts` sees little upstream churn.

## google-genai-files-ts-body-init-cast

`providers/google-genai-files.ts` — Casts `opts.bytes as unknown as BodyInit`
— DOM lib's `BodyInit` type is narrower than Node's `Uint8Array` typing, but
`fetch` accepts the bytes at runtime. Worth filing upstream as a real typing
gap rather than carrying indefinitely.

**Disposition:** Promotion candidate. Typing gap — should be fixed upstream.
**Removal path:** Upstream PR widening `BodyInit` to accept `Uint8Array` so
the cast can be deleted from the vendored file.
**Re-carry:** clean three-way at `0205b07b`, zero conflicts. Low risk.

---

## Upstream promotion ledger

Every Promotion candidate above, as a tracked dependency row per CL-7302.
These are dependencies on upstream maintainers, not work we schedule; the
tracking reference is this ledger until an upstream issue is filed, and the
revisit point is the next vendored sync (see `docs/VENDORING.md`).

| Patch | Upstream ask | Upstream contact | Tracking | Revisit |
| --- | --- | --- | --- | --- |
| adapter-ts-stream-terminal-detector (+ harness-ts-is-stream-terminal) | Add an `isStreamTerminal`/`StreamTerminalDetector` hook to `ProviderAdapter` for semantic end-of-stream protocols | Alexander Guy <alexander.guy@pm.me> | This ledger (vendor/intx-inference/PATCHES.md#adapter-ts-stream-terminal-detector) | Next vendored sync |
| errors-ts-classify-abort-reason | Add optional `reason` param to `classifyAbortError`, carried as `raw: { origin }` | Alexander Guy <alexander.guy@pm.me> | This ledger (#errors-ts-classify-abort-reason) | Next vendored sync |
| harness-ts-inactivity-on-semantic-progress | Gate the inactivity watchdog's re-arm on parsed events, not raw SSE bytes | Alexander Guy <alexander.guy@pm.me> | This ledger (#harness-ts-inactivity-on-semantic-progress) | Next vendored sync |
| reactor-ts-correlating-ids-leak | Wrap `tryCorrelate` in try/finally so `correlatingIds` clears on success dispatch paths | Alexander Guy <alexander.guy@pm.me> | This ledger (#reactor-ts-correlating-ids-leak) | Next vendored sync |
| reactor-ts-checkpoint-after-tool-cycle | Call `commitCycle()` in `executeTools` when `addToHistory` is true | Alexander Guy <alexander.guy@pm.me> | This ledger (#reactor-ts-checkpoint-after-tool-cycle) | Next vendored sync |
| reactor-ts-skip-unchanged-history (+ reactor-ts-last-written-turns-revision) | Skip `contextStore.writeTurns` when `getTurnsRevision()` is unchanged | Alexander Guy <alexander.guy@pm.me> | This ledger (#reactor-ts-skip-unchanged-history) | Next vendored sync |
| reactor-ts-after-checkpoint-director-only | Gate `afterCheckpoint` on `hasOverride` so auto-commits do not emit it | Alexander Guy <alexander.guy@pm.me> | This ledger (#reactor-ts-after-checkpoint-director-only) | Next vendored sync |
| sse-ts-max-line-length | Cap the unterminated SSE line buffer (`MAX_LINE_LENGTH`, 16 MiB) | Alexander Guy <alexander.guy@pm.me> | This ledger (#sse-ts-max-line-length) | Next vendored sync |
| state-ts-deep-freeze-turns-revision | Make `ReactorState.snapshot().turns` a lazy, revision-tracked getter | Alexander Guy <alexander.guy@pm.me> | This ledger (#state-ts-deep-freeze-turns-revision) | Next vendored sync |
| google-genai-files-ts-body-init-cast | Widen `BodyInit` to accept Node's `Uint8Array` typing so the cast can be removed | Alexander Guy <alexander.guy@pm.me> | This ledger (#google-genai-files-ts-body-init-cast) | Next vendored sync |

Contact basis: identified from the read-only upstream clone
(`faremeter/interchange`); Alexander Guy <alexander.guy@pm.me> is the
overwhelmingly dominant author of every upstream file these patches touch
(`packages/inference/src/{reactor,harness,adapter,errors,sse,state}.ts`,
`providers/google-genai-files.ts`, `packages/inference/src/assembly.ts`),
so he is the named contact for every row. Next action per row: file the
upstream issue and replace the ledger tracking reference.

---

The `void track(p)` → `track(p)` change at three call sites in `reactor.ts`
Expand Down
Loading