diff --git a/VENDORED.md b/VENDORED.md index df80da24fb..1a20711224 100644 --- a/VENDORED.md +++ b/VENDORED.md @@ -22,24 +22,24 @@ never a convenience. ## Ledger -| Vendored path | What was copied | Upstream repo @ commit | Why not a published package | Owner | Kill date | Kill-date test | -| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | ---------- | ----------------- | -| `apps/sidecar` | Derived from upstream's own `apps/sidecar`: six modules byte-identical (`default-harness.ts`, `signing-keypair.ts`, `source-asset-delivery.ts`, `workflow-closure-apply.ts`, `workflow-probe-handler.ts`, `workflow-run-pack-restore.ts`), three near-verbatim (`atomic-write.ts` differs only by the repo-wide logger namespace), the rest (`index.ts`, `config.ts`, `tool-materialization.ts`, `step-agent-tools.ts`, `workflow-host-wiring/`, `workflow-substrate-factory/`, …) substantially rewritten, plus workbench-only modules. A living fork, not a frozen copy, so this row carries no tree hash. | [faremeter/interchange](https://github.com/faremeter/interchange) @ `692c3106` (origin/main, 2026-09-03) | An app is never npm-published, so no publish can cover the execution host; retired by consuming an upstream-published host, or by renewing this row deliberately | sawyer | 2026-11-03 | `check:killdates` | -| `vendor/intx/agent` | `@intx/agent` source (`src/`, manifest, tsconfig) | [faremeter/interchange](https://github.com/faremeter/interchange) @ `692c3106` (origin/main, 2026-09-03) | npm 0.3.0 predates the operator-configurable doom-loop threshold (`afd0c82b`, `c421c092`) the re-vendored `workflow-host` configures; one local delta (CL-7190): `ToolBundle.beforeToolExtension` (`tool.ts`) and its composition into `ResolvedTools.beforeToolExtensions` (`agent.ts`), so a tool package can contribute its own suspend-capable extension without the reactor or director special-casing it by name; retired by the next `@intx/agent` publish | sawyer | 2026-11-03 | `check:killdates` | -| `vendor/intx/db` | `@intx/db` source (`src/`, `migrations/`, drizzle config, manifest, tsconfigs) | [faremeter/interchange](https://github.com/faremeter/interchange) @ `c1b5bb73` (origin/main, 2026-09-06) | npm 0.3.0 covers the base package but not the `wire_projection` column/loader delta (CL-6324) or the `workflow_definition.origin` column separating a definition from the per-run record of one folded run's deploy (CL-6452), shipped as migrations `0089`/`0090` behind upstream's `0088`, plus `0091` rewriting the retired `onBodyFailure: "continue"` literal to upstream's `"tolerate"` in stored wire projections, plus `0092` adding `workflow_definition.schedule_claimed_minute` for the hub's native ScheduleTrigger poller (CL-4455); the pin also carries upstream's unpublished per-principal signing-key series (`principal_key` migration renumbered to `0093`, the principal/principal-key stores, and the backfill), which npm 0.3.0 lacks; and a CL-7505 serving-time refresh delta (`model-source-resolution.ts`: `buildSource`/`resolveModelSources`/`resolveInstanceModelSources` accept an optional `servingRefresh` hook, exposing `buildSource`, with a new `credential_needs_reauth` skip so an unrefreshable `oauth_token` credential is never served); one more local delta (CL-7510): `"openai-responses"` added to `schema/catalog.ts`'s `modelProvider.plugin` enum, in lockstep with the `@intx/types` delta, and an adapter registry-key dispatch delta in `model-source-resolution.ts` (`buildSource` rewrites both the launched `InferenceSource.provider` and the served credential material's `providerKey` to the provider's own registry key — `ollama`, `codex`, `xai-oauth` — while the catalog `plugin` column keeps the wire-format id, so the sidecar manifest's custom factories actually resolve); retired when upstream absorbs the deltas or publishes the signing-key series | sawyer | 2026-11-03 | `check:killdates` | -| `vendor/intx/harness` | `@intx/harness` source (`src/`, manifest, tsconfig) | [faremeter/interchange](https://github.com/faremeter/interchange) @ `692c3106` (origin/main, 2026-09-03) | npm 0.3.0 predates the connector reply drain (`driveConnectorReplies`, `ConnectorReplyDrain`, `AgentEventStream`; `11590e66`) the sidecar's warm mail loop drives; no local delta; retired by the next `@intx/harness` publish | sawyer | 2026-11-03 | `check:killdates` | -| `vendor/intx/hub-agent` | `@intx/hub-agent` source (`src/`, manifest, tsconfig) | [faremeter/interchange](https://github.com/faremeter/interchange) @ `692c3106` (origin/main, 2026-09-03) | npm 0.3.0 predates the `agentDir` path export (`927556de`) the sidecar's deploy-tree lookup uses, and its own `@intx/mail-memory`/`@intx/harness` pins must resolve the vendored copies; one local delta (CL-6396): `SessionEventSink` / `publishWorkflowInferenceEvent` stamp optional `childRunId` on `agent.event`; another (CL-7508): the `OAuthLoginExecutor` link option (`ws/hub-link.ts`) routing inbound `oauth.login.start` frames to the sidecar host's loopback login executor and answering every path with `oauth.login.result` frames (`started`, then one terminal arm), with a fail-closed placeholder executor so an unwired host still errors instead of hanging the hub, threaded through `sidecar-orchestrator.ts`'s config, plus cancellation: `oauth.login.cancel` frames and link disconnects close the staged login's pinned-port listener via the executor's `cancel` handle; the pin also carries the package's first colocated test (`ws/hub-link-oauth-login.test.ts` with a `bun test` script) pinning the cancel dispatch against a local ws server; retired by the next publish | sawyer | 2026-11-03 | `check:killdates` | -| `vendor/intx/hub-api` | `@intx/hub-api` source (`src/`, manifest, tsconfig) | [faremeter/interchange](https://github.com/faremeter/interchange) @ `c1b5bb73` (origin/main, 2026-09-06) | npm 0.3.0 covers the base package but not the null-principal `resolveApproval` for policy-resolved decisions (CL-6345), the bearer-authenticated workflow-deploy mirror (`middleware/workflow-run-deploy-auth.ts`, CL-workflow-deploy-bearer), or the upstream per-principal signing-key seam this pin re-vendors (`principalKeyStore` threaded through the tenant/invite/run/workflow routes, the grant materializer, and `createApp`); and a CL-7505 serving-time refresh delta (`run-source-resolution.ts`: `resolveDefinitionSources` accepts and threads an optional `servingRefresh` hook); retired when upstream absorbs the deltas or publishes the signing-key series | sawyer | 2026-11-03 | `check:killdates` | -| `vendor/intx/hub-sessions` | `@intx/hub-sessions` source (`src/`, manifest, tsconfig) | [faremeter/interchange](https://github.com/faremeter/interchange) @ `692c3106` (origin/main, 2026-09-03) | npm 0.3.0 covers the base package but not the pack-acceptance fixes (`ownsWorkflowRunRepo`, `anchorAddressForPackSource`, `decideTerminalRunFlip`), the wire-projection writer (CL-6324), malformed tool-call-name sanitization (CL-6478), the sealed-run terminal-status backfill (CL-6595), the CL-7190 `registerSignalCorrelation` approval-only guard (fails loud on a future `SignalKind` this RPC has no persistence for, rather than silently mis-persisting one), or the CL-6396 `childRunId` forward on `agent.event`; and a CL-7505 serving-time refresh delta (`credential-push.ts`: `pushInstanceSourceUpdate`/`pushSourceUpdates`/`pushSourceUpdatesSubtree` accept and thread an optional `servingRefresh` hook); and a CL-7508 loopback-login delta (`ws/sidecar-handler.ts`: the `oauth.login.result` frame classified as a bypass/terminal correlated response, the `pendingOAuthLogins` request map with a whole-login timeout that also sends `oauth.login.cancel` so the sidecar tears its pinned-port listener down, plus a disconnect sweep, the `requestOAuthLogin` router method gated behind a new `oauthLogin.isLocalSidecar` locality policy, and the typed gate outcome when no connected sidecar is local; review fix: the terminal `completed` arm resolves the pending login with its tokens instead of falling into the error arm); retired when upstream absorbs the deltas | sawyer | 2026-11-03 | `check:killdates` | -| `vendor/intx/inference` | `@intx/inference` source (`src/`, manifest, tsconfig) | [faremeter/interchange](https://github.com/faremeter/interchange) @ `692c3106` (origin/main, 2026-09-03) | npm 0.3.0 predates doom-loop detection (`8da4c827`, `afd0c82b`, `c421c092`); local deltas: `providers/google-genai-files.ts` builds its upload body as `new Uint8Array(bytes)` because TS 6's lib.dom `BodyInit` rejects `Uint8Array` (upstream compiles ESNext-only under TS 5.9); and CL-7190's `message_response` resume branch in `reactor.ts`'s `resumePendingOperation`/`timeoutMessageFor`, plus its `reactor.test.ts`/`testing/fakes.ts` regression harness (this package previously had zero tests); retired by the next publish | sawyer | 2026-11-03 | `check:killdates` | -| `vendor/intx/mail-memory` | `@intx/mail-memory` source (`src/`, manifest, tsconfig) | [faremeter/interchange](https://github.com/faremeter/interchange) @ `692c3106` (origin/main, 2026-09-03) | npm 0.3.0 predates the `@intx/mailbox` extraction (`af03bb90`), on-demand body reads (`54f7c239`) and `expunge` returning the swept uids (`bcabb1f8`) that the re-vendored `workflow-host` binds against; no local delta; retired by the next publish | sawyer | 2026-11-03 | `check:killdates` | -| `vendor/intx/mailbox` | `@intx/mailbox` source (`src/`, manifest, tsconfig) | [faremeter/interchange](https://github.com/faremeter/interchange) @ `692c3106` (origin/main, 2026-09-03) | Never published: a new package at the target pin (`af03bb90`) that `workflow-host`'s substrate mailbox store and supervisor-backed transport import; no local delta; retired by its first publish | sawyer | 2026-11-03 | `check:killdates` | -| `vendor/intx/mime` | `@intx/mime` source (`src/`, manifest, tsconfig) | [faremeter/interchange](https://github.com/faremeter/interchange) @ `692c3106` (origin/main, 2026-09-03) | npm 0.3.0 predates the non-RFC message-id guard `isMessageId` (`d97e1832`), the full `References` chain (`65c6fe70`) and the lossless `decodeMail` decoder (`3b6d06b2`) that `mailbox`/`mail-memory` at the same pin import; no local delta; retired by the next publish | sawyer | 2026-11-03 | `check:killdates` | -| `vendor/intx/types` | `@intx/types` source (`src/`, manifest, tsconfig) | [faremeter/interchange](https://github.com/faremeter/interchange) @ `c1b5bb73` (origin/main, 2026-09-06) | npm 0.3.0 predates the type surface the re-vendored trees compile against: `expunge` returning `expungedUids` (`bcabb1f8`), plain-string `PackRejectReason` (`7b42f405`), the run authorization/approvals REST types (`71ad6c08`), the decoded-mail `Mail`/`MailPartReader` model (`3b6d06b2`) and the `interchange.actions`/`loops` package-json refs (`3bd5b837`, `1ea2f39b`); one local delta (CL-7190): `"message_response"` added to `signals.ts`'s `signalKinds`, alongside `signalKindToGateType`; another (CL-6396): optional `childRunId` on `AgentEventFrame`; the pin also carries the unpublished `signer-identity` contract and `principalKeyAad` domain separator from the signing-key series; one more local delta (CL-7510): `"openai-responses"` added to `catalog.ts`'s `modelProviderPlugins` so the workbench's loopback-OAuth providers (Codex, xai-oauth) can create model-provider rows; another (CL-7508): the `oauth.login.start` / `oauth.login.result` / `oauth.login.cancel` frame family (`OAuthLoginStartFrame`/`OAuthLoginResultFrame`/`OAuthLoginCancelFrame` plus the `OAuthLoginOutcome`/`OAuthLoginTokens` arms, in `sidecar.ts`) threaded through the sidecar ws channel for sidecar-hosted loopback logins, with a parse/reject test (`sidecar-oauth-login.test.ts`); retired by the next publish | sawyer | 2026-11-03 | `check:killdates` | -| `vendor/intx/hub-common` | `@intx/hub-common` source (`src/`, manifest, tsconfig) | [faremeter/interchange](https://github.com/faremeter/interchange) @ `c1b5bb73` (origin/main, 2026-09-06) | npm 0.3.0 predates `generateId`'s `pky_` principal-key prefix from the signing-key series, which the re-vendored `db`/`hub-api` import; no local delta; retired by the next `@intx/hub-common` publish | sawyer | 2026-11-03 | `check:killdates` | -| `vendor/intx/workflow` | `@intx/workflow` source (`src/`, manifest, tsconfig) | [faremeter/interchange](https://github.com/faremeter/interchange) @ `692c3106` (origin/main, 2026-09-03) | No local delta: npm 0.3.0 predates the `onBodyFailure: "tolerate"` section policy (`b977ade6`) that `@corbits/agent-runtime` authors and the action/loop primitives (`3bd5b837`, `1ea2f39b`) the re-vendored `workflow-host` runs; retired by the next `@intx/workflow` publish | sawyer | 2026-11-03 | `check:killdates` | -| `vendor/intx/workflow-deploy` | `@intx/workflow-deploy` source (`src/`, manifest, tsconfig) | [faremeter/interchange](https://github.com/faremeter/interchange) @ `692c3106` (origin/main, 2026-09-03) | No local delta: npm 0.3.0 predates `inertLoopBody` and the loop-body source pin (`1ea2f39b`) that the re-vendored `hub-sessions` imports; retired by the next `@intx/workflow-deploy` publish | sawyer | 2026-11-03 | `check:killdates` | -| `vendor/intx/workflow-host` | `@intx/workflow-host` source (`src/`, manifest, tsconfig) | [faremeter/interchange](https://github.com/faremeter/interchange) @ `692c3106` (origin/main, 2026-09-03) | npm 0.3.0 covers the base package but not the body-spawn authorize/mail-part-reader threading and grants head-collapse (CL-6448) -- the credential thread is retired at this pin, upstream now passing the run's live credential-material cell into every body spawn natively -- that let the fork run tool-bearing onTrigger bodies, or the CL-6396 event-channel `childRunId` stamp so overlapping turns HMAC-bind the occurrence they belong to; retired when upstream absorbs the deltas | sawyer | 2026-11-03 | `check:killdates` | +| Vendored path | What was copied | Upstream repo @ commit | Why not a published package | Owner | Kill date | Kill-date test | +| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | ---------- | ----------------- | +| `apps/sidecar` | Derived from upstream's own `apps/sidecar`: six modules byte-identical (`default-harness.ts`, `signing-keypair.ts`, `source-asset-delivery.ts`, `workflow-closure-apply.ts`, `workflow-probe-handler.ts`, `workflow-run-pack-restore.ts`), three near-verbatim (`atomic-write.ts` differs only by the repo-wide logger namespace), the rest (`index.ts`, `config.ts`, `tool-materialization.ts`, `step-agent-tools.ts`, `workflow-host-wiring/`, `workflow-substrate-factory/`, …) substantially rewritten, plus workbench-only modules. A living fork, not a frozen copy, so this row carries no tree hash. | [faremeter/interchange](https://github.com/faremeter/interchange) @ `692c3106` (origin/main, 2026-09-03) | An app is never npm-published, so no publish can cover the execution host; retired by consuming an upstream-published host, or by renewing this row deliberately | sawyer | 2026-11-03 | `check:killdates` | +| `vendor/intx/agent` | `@intx/agent` source (`src/`, manifest, tsconfig) | [faremeter/interchange](https://github.com/faremeter/interchange) @ `692c3106` (origin/main, 2026-09-03) | npm 0.3.0 predates the operator-configurable doom-loop threshold (`afd0c82b`, `c421c092`) the re-vendored `workflow-host` configures; one local delta (CL-7190): `ToolBundle.beforeToolExtension` (`tool.ts`) and its composition into `ResolvedTools.beforeToolExtensions` (`agent.ts`), so a tool package can contribute its own suspend-capable extension without the reactor or director special-casing it by name; retired by the next `@intx/agent` publish | sawyer | 2026-11-03 | `check:killdates` | +| `vendor/intx/db` | `@intx/db` source (`src/`, `migrations/`, drizzle config, manifest, tsconfigs) | [faremeter/interchange](https://github.com/faremeter/interchange) @ `c1b5bb73` (origin/main, 2026-09-06) | npm 0.3.0 covers the base package but not the `wire_projection` column/loader delta (CL-6324) or the `workflow_definition.origin` column separating a definition from the per-run record of one folded run's deploy (CL-6452), shipped as migrations `0089`/`0090` behind upstream's `0088`, plus `0091` rewriting the retired `onBodyFailure: "continue"` literal to upstream's `"tolerate"` in stored wire projections, plus `0092` adding `workflow_definition.schedule_claimed_minute` for the hub's native ScheduleTrigger poller (CL-4455); the pin also carries upstream's unpublished per-principal signing-key series (`principal_key` migration renumbered to `0093`, the principal/principal-key stores, and the backfill), which npm 0.3.0 lacks; and a CL-7505 serving-time refresh delta (`model-source-resolution.ts`: `buildSource`/`resolveModelSources`/`resolveInstanceModelSources` accept an optional `servingRefresh` hook, exposing `buildSource`, with a new `credential_needs_reauth` skip so an unrefreshable `oauth_token` credential is never served); one more local delta (CL-7510): `"openai-responses"` added to `schema/catalog.ts`'s `modelProvider.plugin` enum, in lockstep with the `@intx/types` delta, and an adapter registry-key dispatch delta in `model-source-resolution.ts` (`buildSource` rewrites both the launched `InferenceSource.provider` and the served credential material's `providerKey` to the provider's own registry key — `ollama`, `codex`, `xai-oauth` — while the catalog `plugin` column keeps the wire-format id, so the sidecar manifest's custom factories actually resolve); retired when upstream absorbs the deltas or publishes the signing-key series | sawyer | 2026-11-03 | `check:killdates` | +| `vendor/intx/harness` | `@intx/harness` source (`src/`, manifest, tsconfig) | [faremeter/interchange](https://github.com/faremeter/interchange) @ `692c3106` (origin/main, 2026-09-03) | npm 0.3.0 predates the connector reply drain (`driveConnectorReplies`, `ConnectorReplyDrain`, `AgentEventStream`; `11590e66`) the sidecar's warm mail loop drives; no local delta; retired by the next `@intx/harness` publish | sawyer | 2026-11-03 | `check:killdates` | +| `vendor/intx/hub-agent` | `@intx/hub-agent` source (`src/`, manifest, tsconfig) | [faremeter/interchange](https://github.com/faremeter/interchange) @ `692c3106` (origin/main, 2026-09-03) | npm 0.3.0 predates the `agentDir` path export (`927556de`) the sidecar's deploy-tree lookup uses, and its own `@intx/mail-memory`/`@intx/harness` pins must resolve the vendored copies; one local delta (CL-6396): `SessionEventSink` / `publishWorkflowInferenceEvent` stamp optional `childRunId` on `agent.event`; another (CL-7508): the `OAuthLoginExecutor` link option (`ws/hub-link.ts`) routing inbound `oauth.login.start` frames to the sidecar host's loopback login executor and answering every path with `oauth.login.result` frames (`started`, then one terminal arm), with a fail-closed placeholder executor so an unwired host still errors instead of hanging the hub, threaded through `sidecar-orchestrator.ts`'s config, plus cancellation: `oauth.login.cancel` frames and link disconnects close the staged login's pinned-port listener via the executor's `cancel` handle; the pin also carries the package's first colocated test (`ws/hub-link-oauth-login.test.ts` with a `bun test` script) pinning the cancel dispatch against a local ws server; retired by the next publish | sawyer | 2026-11-03 | `check:killdates` | +| `vendor/intx/hub-api` | `@intx/hub-api` source (`src/`, manifest, tsconfig) | [faremeter/interchange](https://github.com/faremeter/interchange) @ `c1b5bb73` (origin/main, 2026-09-06) | npm 0.3.0 covers the base package but not the null-principal `resolveApproval` for policy-resolved decisions (CL-6345), the bearer-authenticated workflow-deploy mirror (`middleware/workflow-run-deploy-auth.ts`, CL-workflow-deploy-bearer), or the upstream per-principal signing-key seam this pin re-vendors (`principalKeyStore` threaded through the tenant/invite/run/workflow routes, the grant materializer, and `createApp`); and a CL-7505 serving-time refresh delta (`run-source-resolution.ts`: `resolveDefinitionSources` accepts and threads an optional `servingRefresh` hook); retired when upstream absorbs the deltas or publishes the signing-key series | sawyer | 2026-11-03 | `check:killdates` | +| `vendor/intx/hub-sessions` | `@intx/hub-sessions` source (`src/`, manifest, tsconfig) | [faremeter/interchange](https://github.com/faremeter/interchange) @ `692c3106` (origin/main, 2026-09-03) | npm 0.3.0 covers the base package but not the pack-acceptance fixes (`ownsWorkflowRunRepo`, `anchorAddressForPackSource`, `decideTerminalRunFlip`), the wire-projection writer (CL-6324), malformed tool-call-name sanitization (CL-6478), the sealed-run terminal-status backfill (CL-6595), the CL-7190 `registerSignalCorrelation` approval-only guard (fails loud on a future `SignalKind` this RPC has no persistence for, rather than silently mis-persisting one), or the CL-6396 `childRunId` forward on `agent.event`; and a CL-7505 serving-time refresh delta (`credential-push.ts`: `pushInstanceSourceUpdate`/`pushSourceUpdates`/`pushSourceUpdatesSubtree` accept and thread an optional `servingRefresh` hook); and a CL-7508 loopback-login delta (`ws/sidecar-handler.ts`: the `oauth.login.result` frame classified as a bypass/terminal correlated response, the `pendingOAuthLogins` request map with a whole-login timeout that also sends `oauth.login.cancel` so the sidecar tears its pinned-port listener down, plus a disconnect sweep, the `requestOAuthLogin` router method gated behind a new `oauthLogin.isLocalSidecar` locality policy, and the typed gate outcome when no connected sidecar is local; review fix: the terminal `completed` arm resolves the pending login with its tokens instead of falling into the error arm); and a corbitsdev/workbench#709 prepared-deploy delta (`session-service.ts` threads `deployContent` + `toolPackagePins` through the prepared-deploy params and fans every top-level step out to `stageWorkflowStep` before the deployment frame, `workflow-allocation-service.ts` rehydrating both from the frozen launch spec with a fail-closed prompt check); retired when upstream absorbs the deltas | sawyer | 2026-11-03 | `check:killdates` | +| `vendor/intx/inference` | `@intx/inference` source (`src/`, manifest, tsconfig) | [faremeter/interchange](https://github.com/faremeter/interchange) @ `692c3106` (origin/main, 2026-09-03) | npm 0.3.0 predates doom-loop detection (`8da4c827`, `afd0c82b`, `c421c092`); local deltas: `providers/google-genai-files.ts` builds its upload body as `new Uint8Array(bytes)` because TS 6's lib.dom `BodyInit` rejects `Uint8Array` (upstream compiles ESNext-only under TS 5.9); and CL-7190's `message_response` resume branch in `reactor.ts`'s `resumePendingOperation`/`timeoutMessageFor`, plus its `reactor.test.ts`/`testing/fakes.ts` regression harness (this package previously had zero tests); retired by the next publish | sawyer | 2026-11-03 | `check:killdates` | +| `vendor/intx/mail-memory` | `@intx/mail-memory` source (`src/`, manifest, tsconfig) | [faremeter/interchange](https://github.com/faremeter/interchange) @ `692c3106` (origin/main, 2026-09-03) | npm 0.3.0 predates the `@intx/mailbox` extraction (`af03bb90`), on-demand body reads (`54f7c239`) and `expunge` returning the swept uids (`bcabb1f8`) that the re-vendored `workflow-host` binds against; no local delta; retired by the next publish | sawyer | 2026-11-03 | `check:killdates` | +| `vendor/intx/mailbox` | `@intx/mailbox` source (`src/`, manifest, tsconfig) | [faremeter/interchange](https://github.com/faremeter/interchange) @ `692c3106` (origin/main, 2026-09-03) | Never published: a new package at the target pin (`af03bb90`) that `workflow-host`'s substrate mailbox store and supervisor-backed transport import; no local delta; retired by its first publish | sawyer | 2026-11-03 | `check:killdates` | +| `vendor/intx/mime` | `@intx/mime` source (`src/`, manifest, tsconfig) | [faremeter/interchange](https://github.com/faremeter/interchange) @ `692c3106` (origin/main, 2026-09-03) | npm 0.3.0 predates the non-RFC message-id guard `isMessageId` (`d97e1832`), the full `References` chain (`65c6fe70`) and the lossless `decodeMail` decoder (`3b6d06b2`) that `mailbox`/`mail-memory` at the same pin import; no local delta; retired by the next publish | sawyer | 2026-11-03 | `check:killdates` | +| `vendor/intx/types` | `@intx/types` source (`src/`, manifest, tsconfig) | [faremeter/interchange](https://github.com/faremeter/interchange) @ `c1b5bb73` (origin/main, 2026-09-06) | npm 0.3.0 predates the type surface the re-vendored trees compile against: `expunge` returning `expungedUids` (`bcabb1f8`), plain-string `PackRejectReason` (`7b42f405`), the run authorization/approvals REST types (`71ad6c08`), the decoded-mail `Mail`/`MailPartReader` model (`3b6d06b2`) and the `interchange.actions`/`loops` package-json refs (`3bd5b837`, `1ea2f39b`); one local delta (CL-7190): `"message_response"` added to `signals.ts`'s `signalKinds`, alongside `signalKindToGateType`; another (CL-6396): optional `childRunId` on `AgentEventFrame`; the pin also carries the unpublished `signer-identity` contract and `principalKeyAad` domain separator from the signing-key series; one more local delta (CL-7510): `"openai-responses"` added to `catalog.ts`'s `modelProviderPlugins` so the workbench's loopback-OAuth providers (Codex, xai-oauth) can create model-provider rows; another (CL-7508): the `oauth.login.start` / `oauth.login.result` / `oauth.login.cancel` frame family (`OAuthLoginStartFrame`/`OAuthLoginResultFrame`/`OAuthLoginCancelFrame` plus the `OAuthLoginOutcome`/`OAuthLoginTokens` arms, in `sidecar.ts`) threaded through the sidecar ws channel for sidecar-hosted loopback logins, with a parse/reject test (`sidecar-oauth-login.test.ts`); retired by the next publish | sawyer | 2026-11-03 | `check:killdates` | +| `vendor/intx/hub-common` | `@intx/hub-common` source (`src/`, manifest, tsconfig) | [faremeter/interchange](https://github.com/faremeter/interchange) @ `c1b5bb73` (origin/main, 2026-09-06) | npm 0.3.0 predates `generateId`'s `pky_` principal-key prefix from the signing-key series, which the re-vendored `db`/`hub-api` import; no local delta; retired by the next `@intx/hub-common` publish | sawyer | 2026-11-03 | `check:killdates` | +| `vendor/intx/workflow` | `@intx/workflow` source (`src/`, manifest, tsconfig) | [faremeter/interchange](https://github.com/faremeter/interchange) @ `692c3106` (origin/main, 2026-09-03) | One local delta (corbitsdev/workbench#709): `run.ts` treats the per-step timeout as an execution budget — trigger-idle input parks disarm the step timer across the wait and re-arm a fresh budget on resume, while the approval park stays armed; npm 0.3.0 predates the `onBodyFailure: "tolerate"` section policy (`b977ade6`) that `@corbits/agent-runtime` authors and the action/loop primitives (`3bd5b837`, `1ea2f39b`) the re-vendored `workflow-host` runs; retired by the next `@intx/workflow` publish | sawyer | 2026-11-03 | `check:killdates` | +| `vendor/intx/workflow-deploy` | `@intx/workflow-deploy` source (`src/`, manifest, tsconfig) | [faremeter/interchange](https://github.com/faremeter/interchange) @ `692c3106` (origin/main, 2026-09-03) | No local delta: npm 0.3.0 predates `inertLoopBody` and the loop-body source pin (`1ea2f39b`) that the re-vendored `hub-sessions` imports; retired by the next `@intx/workflow-deploy` publish | sawyer | 2026-11-03 | `check:killdates` | +| `vendor/intx/workflow-host` | `@intx/workflow-host` source (`src/`, manifest, tsconfig) | [faremeter/interchange](https://github.com/faremeter/interchange) @ `692c3106` (origin/main, 2026-09-03) | npm 0.3.0 covers the base package but not the body-spawn authorize/mail-part-reader threading and grants head-collapse (CL-6448) -- the credential thread is retired at this pin, upstream now passing the run's live credential-material cell into every body spawn natively -- that let the fork run tool-bearing onTrigger bodies, or the CL-6396 event-channel `childRunId` stamp so overlapping turns HMAC-bind the occurrence they belong to; retired when upstream absorbs the deltas | sawyer | 2026-11-03 | `check:killdates` | The pin is `692c3106` (upstream `origin/main`, 2026-09-03), 90 commits past the `v0.3.0` release tag `b5580a02`. npm is still `0.3.0`, so every tree a @@ -122,7 +122,7 @@ credentials, and an attachments-only inbound mail resolves its parts instead of throwing. `findStepGrantsEntry` collapses a single-step deployment's sole grants entry onto a body step whose own id the parent snapshot never lists. Upstream never runs tool-bearing body agents, so the seam has no upstream -analog. `vendor/intx/workflow` carries no local delta: upstream `b977ade6` ships the +analog. `vendor/intx/workflow` carries one local delta (corbitsdev/workbench#709 step-timer budget — see its ledger row): upstream `b977ade6` ships the `onTrigger` body-failure policy workbench had vendored as `onBodyFailure: "continue"` (CL-6326, CL-6324) under the literal `"tolerate"`, so the authoring site (`@corbits/agent-runtime`) says `"tolerate"` and `@intx/db` diff --git a/scripts/checks/kill-dates.txt b/scripts/checks/kill-dates.txt index 558537e3e0..a9b975ebda 100644 --- a/scripts/checks/kill-dates.txt +++ b/scripts/checks/kill-dates.txt @@ -20,13 +20,13 @@ vendor/intx/harness | sawyer | 2026-11-03 | 399b4e8b3b18e8969e815427625e1bfc6746 vendor/intx/hub-agent | sawyer | 2026-11-03 | b0f3b0bd760b1a397e00ff47cce5b9701273bdb04e294748afe650c4d142aa5a vendor/intx/hub-api | sawyer | 2026-11-03 | 90aa5cddef828d77b62adb63186dcf82b5465926cafea1ab6b64bca263031b57 vendor/intx/hub-common | sawyer | 2026-11-03 | 2fe74684593083f422023b2d6b337e414b5b319c6bfe02c7fa157130d7162e41 -vendor/intx/hub-sessions | sawyer | 2026-11-03 | 80b0d49a6bce40cc22941e5f79b6e7d50308418661ea17a6e88e22244bdabf8f +vendor/intx/hub-sessions | sawyer | 2026-11-03 | 69eb524e236b5c26d543551bd64cb8b3f8c50bc09c7e91b5ef6c41b9280b54e1 vendor/intx/inference | sawyer | 2026-11-03 | 81e1b31947cd8e6cac4e336d21d8a87ba063b638e0ac4ada1b0f375ec6861bf5 vendor/intx/mail-memory | sawyer | 2026-11-03 | e281498352adbc2face631744ce9a02cb838c60a6c318961022904f0fd05d192 vendor/intx/mailbox | sawyer | 2026-11-03 | 926bfef1b60a4ba7e600252e9ad6e37c17d387a200f79c2cbc0b3ceb612000ea vendor/intx/mime | sawyer | 2026-11-03 | ddf7e626172350c6a447890affc6c746b7938e04ee53af8f1d9c8cffd97d1954 vendor/intx/types | sawyer | 2026-11-03 | f1c246c159318778082bb50de90477c46f54a38eef1f6d584ce9f16cd510c9da -vendor/intx/workflow | sawyer | 2026-11-03 | c8f3a7a40d4ef429b58ba913c2faa27a5e7e98baf433dc57f864e12c907eb47a +vendor/intx/workflow | sawyer | 2026-11-03 | 8b5cb3f4085c2e400a0eeafe69caa695769a613a699a25f88f0c2886aa98a00b vendor/intx/workflow-deploy | sawyer | 2026-11-03 | 72a4f931ba5c404a091dc46a7ed60f5b0530a63535f7cacacfe31f95c397e473 vendor/intx/workflow-host | sawyer | 2026-11-03 | b9964010920cef377ba4be777c179d414c430c1709e665bbf8c5e4a413e249e9 diff --git a/vendor/intx/hub-sessions/VENDORED-FROM b/vendor/intx/hub-sessions/VENDORED-FROM index 57917ba1c1..8b6012f84c 100644 --- a/vendor/intx/hub-sessions/VENDORED-FROM +++ b/vendor/intx/hub-sessions/VENDORED-FROM @@ -1,4 +1,4 @@ Source: https://github.com/faremeter/interchange (packages/hub-sessions) Commit: 692c31068cbb636ebb19c6d179ec6fe126a2d4e6 (origin/main, 2026-09-03) License: LGPL-2.1-only (see vendor/intx/LICENSE) -Local modifications: exports map repointed from the upstream intx-src condition to direct TypeScript source resolution (types/default -> ./src/...); dist references removed. Upstream test files are not vendored (they import the unvendored @intx/inference-testing and @intx/test-harness test packages); only the tests covering a workbench delta are kept. Terminal-anchor pack acceptance: hub-session-lookups.ts's receiveWorkflowRunPack gates the anchor lookup on the exported pure helper ownsWorkflowRunRepo (self-anchored row with a routable address, no liveness requirement) instead of upstream's live-status filter, so a terminal run can still land the inbox-enqueue and markConsumed-rejection packs that retire mail arriving in its teardown window; upstream's isNotNull(definitionId) tightening is kept. CL-6361 widens the same lookup to peel a per-step pack source address back to its base run's anchor via anchorAddressForPackSource; CL-6379 classifies an accepted pack's newly-terminal runs through decideTerminalRunFlip so a section occurrence's repo-local child run (turn__) is skipped quietly. CL-6324: workflow-probe-gate.ts's PersistFrozenApprovalFn carries the inert projection and createDbFrozenApprovalWriter stamps workflow_definition_version.wire_projection in the same transaction as approved_wire_hash. CL-6478: sanitize-tool-name.ts + event-collector.ts's tool_call case persist only a tool-call name encodeToolName can re-invert (anything else collapses to MALFORMED_TOOL_NAME), so one bad name fails its turn instead of wedging the room; @intx/inference is a dependency for this. CL-6595: workflow-run-kind.ts's validatePush also reports a run sealed from birth (combined events.jsonl with no per-event blobs) as newly terminal, and the new readCommittedWorkflowRunTerminalStatus export backs a same-push markTerminal backfill in hub-session-lookups.ts; both classify through upstream's classifyTerminalEvent. CL-7190: registerSignalCorrelation (hub-session-lookups.ts) now throws for any signal kind other than "approval", failing loud instead of silently mis-persisting a future SignalKind it has no co-write for. CL-6396: sidecar-events.ts's agent.event map and sidecar-handler.ts's agent.event dispatch forward an optional childRunId from the sidecar frame so the hub can close the matching occurrence row. CL-7508: sidecar-handler.ts's oauth.login result handling settles the caller's request promise as an error when a terminal outcome arrives before the started acknowledgement — previously a completed-before-started frame left the HTTP caller hanging until the whole-login timeout; the no-hang pin lives in sidecar-handler-oauth-login.test.ts (only tests covering a workbench delta are vendored). RETIRED AT THIS PIN: the CL-6324 session-service.ts deltas (deployAdoptedCodeSourcedWorkflow / deployAdoptedWorkflowFromSource / AdoptingWorkflowDeployer, the sourceRef threading, and CL-7191's UserMessageParams.correlationId) hung off upstream's deployWorkflowFromSource front, which this pin deletes in favour of the catalog-offering + provisioner-selection deploy path. session-service.ts is vendored pristine and carries no co-located test. +Local modifications: exports map repointed from the upstream intx-src condition to direct TypeScript source resolution (types/default -> ./src/...); dist references removed. Upstream test files are not vendored (they import the unvendored @intx/inference-testing and @intx/test-harness test packages); only the tests covering a workbench delta are kept. Terminal-anchor pack acceptance: hub-session-lookups.ts's receiveWorkflowRunPack gates the anchor lookup on the exported pure helper ownsWorkflowRunRepo (self-anchored row with a routable address, no liveness requirement) instead of upstream's live-status filter, so a terminal run can still land the inbox-enqueue and markConsumed-rejection packs that retire mail arriving in its teardown window; upstream's isNotNull(definitionId) tightening is kept. CL-6361 widens the same lookup to peel a per-step pack source address back to its base run's anchor via anchorAddressForPackSource; CL-6379 classifies an accepted pack's newly-terminal runs through decideTerminalRunFlip so a section occurrence's repo-local child run (turn__) is skipped quietly. CL-6324: workflow-probe-gate.ts's PersistFrozenApprovalFn carries the inert projection and createDbFrozenApprovalWriter stamps workflow_definition_version.wire_projection in the same transaction as approved_wire_hash. CL-6478: sanitize-tool-name.ts + event-collector.ts's tool_call case persist only a tool-call name encodeToolName can re-invert (anything else collapses to MALFORMED_TOOL_NAME), so one bad name fails its turn instead of wedging the room; @intx/inference is a dependency for this. CL-6595: workflow-run-kind.ts's validatePush also reports a run sealed from birth (combined events.jsonl with no per-event blobs) as newly terminal, and the new readCommittedWorkflowRunTerminalStatus export backs a same-push markTerminal backfill in hub-session-lookups.ts; both classify through upstream's classifyTerminalEvent. CL-7190: registerSignalCorrelation (hub-session-lookups.ts) now throws for any signal kind other than "approval", failing loud instead of silently mis-persisting a future SignalKind it has no co-write for. CL-6396: sidecar-events.ts's agent.event map and sidecar-handler.ts's agent.event dispatch forward an optional childRunId from the sidecar frame so the hub can close the matching occurrence row. CL-7508: sidecar-handler.ts's oauth.login result handling settles the caller's request promise as an error when a terminal outcome arrives before the started acknowledgement — previously a completed-before-started frame left the HTTP caller hanging until the whole-login timeout; the no-hang pin lives in sidecar-handler-oauth-login.test.ts (only tests covering a workbench delta are vendored). RETIRED AT THIS PIN: the CL-6324 session-service.ts deltas (deployAdoptedCodeSourcedWorkflow / deployAdoptedWorkflowFromSource / AdoptingWorkflowDeployer, the sourceRef threading, and CL-7191's UserMessageParams.correlationId) hung off upstream's deployWorkflowFromSource front, which this pin deletes in favour of the catalog-offering + provisioner-selection deploy path. corbitsdev/workbench#709: session-service.ts's prepared-deploy path threads `deployContent` + `toolPackagePins` through `DeployPreparedCodeSourcedWorkflowParams` and fans every top-level step out to `stageWorkflowStep` before the deployment frame (pure `preparedStepStageArgs` maps one step's address via `resolveStepAddress`, agent id via `deriveStepAgentId`, pins verbatim-or-absent); workflow-allocation-service.ts rehydrates both from the frozen launch spec (`preparedDeployContent` fails closed without a string prompt). The pins threading is pinned in session-service-pins.test.ts (only tests covering a workbench delta are vendored). diff --git a/vendor/intx/hub-sessions/src/session-service-pins.test.ts b/vendor/intx/hub-sessions/src/session-service-pins.test.ts new file mode 100644 index 0000000000..ac2c0a9f37 --- /dev/null +++ b/vendor/intx/hub-sessions/src/session-service-pins.test.ts @@ -0,0 +1,74 @@ +import { describe, expect, test } from "bun:test"; + +import type { HarnessConfig } from "@intx/types/runtime"; +import type { ToolPackagePin } from "@intx/types/tool-packages"; +import { + deriveStepAgentId, + resolveStepAddress, +} from "@intx/workflow-deploy"; + +import type { DeployContent } from "./agent-repo"; +import { preparedStepStageArgs } from "./session-service"; +import type { AllocatedSidecarTarget } from "./ws/sidecar-handler"; + +const pins: readonly ToolPackagePin[] = [ + { name: "acme-tool", version: "^1.2.3" }, +]; + +function baseArgs() { + return { + anchorRunId: "run_1", + deploymentDomain: "example.test", + stepId: "step-a", + stepCount: 2, + config: { marker: "config" } as unknown as HarnessConfig, + deployContent: { systemPrompt: "prompt" } satisfies DeployContent, + allocationTarget: { marker: "target" } as unknown as AllocatedSidecarTarget, + }; +} + +describe("preparedStepStageArgs — corbitsdev/workbench#709 prepared-path pins", () => { + test("forwards toolPackagePins verbatim when present", () => { + const base = baseArgs(); + const args = preparedStepStageArgs({ ...base, toolPackagePins: pins }); + + expect(args.toolPackagePins).toBe(pins); + }); + + test("leaves address, agent id, and passthrough fields untouched", () => { + const base = baseArgs(); + const args = preparedStepStageArgs({ ...base, toolPackagePins: pins }); + + expect(args.agentAddress).toBe( + resolveStepAddress({ + runId: base.anchorRunId, + stepId: base.stepId, + domain: base.deploymentDomain, + stepCount: base.stepCount, + }), + ); + expect(args.agentId).toBe( + deriveStepAgentId({ runId: base.anchorRunId, stepId: base.stepId }), + ); + expect(args.runId).toBe(base.anchorRunId); + expect(args.config).toBe(base.config); + expect(args.deployContent).toBe(base.deployContent); + expect(args.allocationTarget).toBe(base.allocationTarget); + }); + + test("omits the key when pins are undefined so the empty/undefined skip holds", () => { + const args = preparedStepStageArgs(baseArgs()); + + expect("toolPackagePins" in args).toBe(false); + }); + + test("forwards an empty array as-is (stageWorkflowStep treats empty as skip)", () => { + const empty: readonly ToolPackagePin[] = []; + const args = preparedStepStageArgs({ + ...baseArgs(), + toolPackagePins: empty, + }); + + expect(args.toolPackagePins).toBe(empty); + }); +}); diff --git a/vendor/intx/hub-sessions/src/session-service.ts b/vendor/intx/hub-sessions/src/session-service.ts index 27dcfe4656..139e6ef7d8 100644 --- a/vendor/intx/hub-sessions/src/session-service.ts +++ b/vendor/intx/hub-sessions/src/session-service.ts @@ -59,6 +59,8 @@ import type { import { buildInertProjectionStepSources, deriveRunAddress, + deriveStepAgentId, + resolveStepAddress, WorkflowDefinitionInvalidError, type DeployContent as OrchestratorDeployContent, } from "@intx/workflow-deploy"; @@ -197,6 +199,21 @@ export type DeployPreparedCodeSourcedWorkflowParams = { approved: InstallAndApproveResult; /** Harness config carrying the re-resolved per-step inference chain. */ config: HarnessConfig; + /** + * Deploy content staged into every step's tree. The prompt rides each + * step's tree verbatim; the step-tools path never reads it (the step + * prompt comes from the closure-evaluated definition), so one shared + * content is staged per step and the per-step manifests resolve fresh + * from `toolPackagePins` inside `stageWorkflowStep`. + */ + deployContent: DeployContent; + /** + * Pinned tool packages, rehydrated from the launch spec. Resolved per + * step into a full closure manifest staged where `materializeStepTools` + * reads it. Empty or undefined skips the resolver entirely: the step + * trees stage with no manifest and the child materializes empty tools. + */ + toolPackagePins?: readonly ToolPackagePin[]; /** The exact allocation generation to deploy onto. */ allocationTarget: AllocatedSidecarTarget; /** Cipher for the definition's tenant-owned credential bindings, if any. */ @@ -964,6 +981,51 @@ export async function deployCodeSourcedWorkflow( return { publicKey }; } +/** + * Map one top-level prepared-deploy step onto `stageWorkflowStep` args. + * Split out (pure) so the pins threading has a direct unit test: pins ride + * verbatim when present; when absent the key stays absent so the + * empty/undefined skip inside `stageWorkflowStep` is preserved bit-for-bit. + */ +export function preparedStepStageArgs(params: { + anchorRunId: string; + deploymentDomain: string; + stepId: string; + stepCount: number; + config: HarnessConfig; + deployContent: DeployContent; + toolPackagePins?: readonly ToolPackagePin[]; + allocationTarget: AllocatedSidecarTarget; +}): { + agentAddress: string; + agentId: string; + runId: string; + config: HarnessConfig; + deployContent: DeployContent; + toolPackagePins?: readonly ToolPackagePin[]; + allocationTarget: AllocatedSidecarTarget; +} { + return { + agentAddress: resolveStepAddress({ + runId: params.anchorRunId, + stepId: params.stepId, + domain: params.deploymentDomain, + stepCount: params.stepCount, + }), + agentId: deriveStepAgentId({ + runId: params.anchorRunId, + stepId: params.stepId, + }), + runId: params.anchorRunId, + config: params.config, + deployContent: params.deployContent, + ...(params.toolPackagePins !== undefined + ? { toolPackagePins: params.toolPackagePins } + : {}), + allocationTarget: params.allocationTarget, + }; +} + export function createSessionService( deps: SessionServiceDeps, ): SessionService & PreparedWorkflowDeployer { @@ -1588,6 +1650,36 @@ export function createSessionService( agentAddress: params.agentAddress, }); + // Stage every top-level step's deploy tree BEFORE the deployment frame: + // the frame spawns the child, whose step tools read each step's staged + // manifest (`deploy/tool-packages-manifest.json` + asset packs) from + // disk. The address goes through `resolveStepAddress` -- the single + // owner of the head/step collapse -- so this producer and the sidecar + // consumer (`stepDeployTreeDir`, keyed off the host-sourced stepCount) + // never derive divergent addresses: a one-step workflow stages at the + // head, a multi-step one at each `-` address. The step + // agent id is hub-local (the `agent-state` repo the pack is built + // from); the pack itself routes by step address. Asset-pack fan-out + // inside `stageWorkflowStep` records its `session_asset` rows against + // the anchor run, the deployment's durable identity. + const stepOrder = params.approved.projection.stepOrder; + for (const stepId of stepOrder) { + await stageWorkflowStep( + preparedStepStageArgs({ + anchorRunId: params.anchorRunId, + deploymentDomain: params.deploymentDomain, + stepId, + stepCount: stepOrder.length, + config: params.config, + deployContent: params.deployContent, + ...(params.toolPackagePins !== undefined + ? { toolPackagePins: params.toolPackagePins } + : {}), + allocationTarget: params.allocationTarget, + }), + ); + } + const commonEmit = { approved: params.approved, sidecarAllocationRouter: allocationRouter, diff --git a/vendor/intx/hub-sessions/src/workflow-allocation-service.ts b/vendor/intx/hub-sessions/src/workflow-allocation-service.ts index 161213af58..9141937e23 100644 --- a/vendor/intx/hub-sessions/src/workflow-allocation-service.ts +++ b/vendor/intx/hub-sessions/src/workflow-allocation-service.ts @@ -170,6 +170,24 @@ function parseDestroyResult(value: unknown): DestroySidecarResult { return result; } +/** + * Narrow the launch spec's persisted deploy content back to the deploy shape. + * The prepare path persisted a `DeployContent`; only the prompt rides forward + * (per-step manifests resolve fresh from pins at deploy time), so anything + * without a string prompt fails closed rather than staging a prompt-less tree. + */ +function preparedDeployContent( + value: Record, +): DeployContent { + const systemPrompt = value["systemPrompt"]; + if (typeof systemPrompt !== "string") { + throw new Error( + "prepared deploy: launch spec deployContent has no string systemPrompt; refusing to stage step trees without a prompt", + ); + } + return { systemPrompt }; +} + function createProvisionedHarnessConfig(args: { readonly tenantId: string; readonly anchorRunId: string; @@ -748,6 +766,13 @@ export function createWorkflowAllocationService({ source: bundle.source, approved, config, + deployContent: preparedDeployContent(spec.deployContent), + // Pins rehydrated from the frozen launch spec. Undefined (or empty) + // skips the tool-package resolver: no manifest is staged and the + // child materializes empty step tools rather than the pinned closure. + ...(spec.toolPackagePins !== null + ? { toolPackagePins: spec.toolPackagePins } + : {}), allocationTarget, credentialCipher, }); diff --git a/vendor/intx/workflow/VENDORED-FROM b/vendor/intx/workflow/VENDORED-FROM index 08ba51f60a..52b447dce0 100644 --- a/vendor/intx/workflow/VENDORED-FROM +++ b/vendor/intx/workflow/VENDORED-FROM @@ -1,4 +1,4 @@ Source: https://github.com/faremeter/interchange (packages/workflow) Commit: 692c31068cbb636ebb19c6d179ec6fe126a2d4e6 (origin/main, 2026-09-03) License: LGPL-2.1-only (see vendor/intx/LICENSE) -Local modifications: exports map repointed from the upstream intx-src condition to direct TypeScript source resolution (types/default -> ./src/...); dist references removed. Upstream test files are not vendored (they import the unvendored @intx/inference-testing and @intx/test-harness test packages); only the tests covering a workbench delta are kept. No source delta. +Local modifications: exports map repointed from the upstream intx-src condition to direct TypeScript source resolution (types/default -> ./src/...); dist references removed. Upstream test files are not vendored (they import the unvendored @intx/inference-testing and @intx/test-harness test packages); only the tests covering a workbench delta are kept. One source delta (corbitsdev/workbench#709): run.ts's per-step timeout is an execution budget — trigger-idle input parks disarm the step timer across the wait and re-arm a fresh budget on resume, while the approval park stays armed (snapshot-bound, still bounded by `step.timeout`); pinned in runtime/run.test.ts (only tests covering a workbench delta are vendored). diff --git a/vendor/intx/workflow/src/runtime/run.test.ts b/vendor/intx/workflow/src/runtime/run.test.ts new file mode 100644 index 0000000000..c30293a7ba --- /dev/null +++ b/vendor/intx/workflow/src/runtime/run.test.ts @@ -0,0 +1,116 @@ +// Step-timeout budget semantics (corbitsdev/workbench#709): `step.timeout` +// bounds active agent execution, not trigger-idle input parks. An input +// park disarms the execution timer across the wait and re-arms a fresh +// budget on resume; an overrunning active invocation still aborts. + +import { describe, expect, test } from "bun:test"; + +import type { AgentDefinition, BaseEnv } from "@intx/agent"; +import { signalName } from "@intx/types"; + +import { defineWorkflow, runLocal, step } from "../index"; +import type { StepInvoker } from "../index"; + +const TIMEOUT_MS = 100; +const IDLE_PARK_MS = TIMEOUT_MS * 4; + +const agent: AgentDefinition = { + id: "timeout-probe", + systemPrompt: "probe", + toolFactories: [], + capabilities: [], + inference: { sources: [] }, +}; + +function sleep(ms: number): Promise { + return new Promise((resolve) => setTimeout(resolve, ms)); +} + +async function waitFor( + condition: () => boolean, + timeoutMs: number, +): Promise { + const started = Date.now(); + while (!condition()) { + if (Date.now() - started > timeoutMs) { + throw new Error("timed out waiting for test condition"); + } + await sleep(10); + } +} + +/** Deterministic `newId` that records every `corr` (input-park) id minted. */ +function corrRecordingNewId(recorded: string[]): (prefix: string) => string { + let n = 0; + return (prefix: string) => { + n += 1; + const id = `${prefix}-test-${String(n)}`; + if (prefix === "corr") recorded.push(id); + return id; + }; +} + +describe("step timeout — input-park vs active execution", () => { + test("an idle input park past the step timeout resumes and completes", async () => { + const turns: unknown[] = []; + const invokeStep: StepInvoker = async ({ resume }) => { + turns.push(resume?.decision ?? null); + return { output: `turn-${String(turns.length)}` }; + }; + const corrIds: string[] = []; + const run = runLocal( + defineWorkflow({ + id: "timeout-idle-park", + trigger: { type: "manual" }, + steps: { + main: step({ agent, timeout: TIMEOUT_MS, triggers: 2 }), + }, + }), + { invokeStep, newId: corrRecordingNewId(corrIds), runId: "run-idle" }, + ); + + // Turn 1 completes fast; the step re-arms onto an input park. Sit idle + // well past the step timeout, then deliver the second trigger. + await waitFor(() => corrIds.length > 0, 5000); + await sleep(IDLE_PARK_MS); + const corr = corrIds[0]; + if (corr === undefined) throw new Error("no input-park correlation minted"); + await run.signal(signalName(corr), { text: "second trigger" }); + + const result = await run.complete; + expect(result.terminalStatus).toBe("completed"); + expect(result.outputs["main"]).toBe("turn-2"); + expect(turns.length).toBe(2); + }); + + test("an active invocation past the step timeout still aborts", async () => { + let sawAbort = false; + const invokeStep: StepInvoker = async ({ signal }) => { + await new Promise((_, reject) => { + signal.addEventListener("abort", () => { + sawAbort = true; + reject(new Error("step aborted")); + }); + if (signal.aborted) { + sawAbort = true; + reject(new Error("step aborted")); + } + }); + throw new Error("unreachable"); + }; + const run = runLocal( + defineWorkflow({ + id: "timeout-active-overrun", + trigger: { type: "manual" }, + steps: { + main: step({ agent, timeout: TIMEOUT_MS }), + }, + }), + { invokeStep, runId: "run-overrun" }, + ); + + const result = await run.complete; + expect(result.terminalStatus).toBe("failed"); + expect(sawAbort).toBe(true); + }); +}); diff --git a/vendor/intx/workflow/src/runtime/run.ts b/vendor/intx/workflow/src/runtime/run.ts index b53fc4a94c..31b8c62752 100644 --- a/vendor/intx/workflow/src/runtime/run.ts +++ b/vendor/intx/workflow/src/runtime/run.ts @@ -1489,17 +1489,34 @@ async function runStep( } // Build per-step abort: timeout AND outer cancellation both abort. + // `step.timeout` is an execution budget: it bounds active agent + // invocations, not parked-idle waits. Each input park below disarms + // it before waiting and re-arms a fresh budget on resume; the + // approval park stays armed (an approval wait holds a mandatory + // snapshot and stays bounded by the execution timer, unlike + // trigger-idle input). Disarming never affects cancellation: the + // outer-abort listener aborts `stepAbort` independently of the timer. const stepAbort = new AbortController(); const onOuter = () => { stepAbort.abort(); }; abort.addEventListener("abort", onOuter, { once: true }); let timer: ReturnType | undefined; - if (step.timeout !== undefined) { - timer = setTimeout(() => { - stepAbort.abort(); - }, step.timeout); - } + const armStepTimer = (): void => { + if (timer !== undefined) clearTimeout(timer); + if (step.timeout !== undefined) { + timer = setTimeout(() => { + stepAbort.abort(); + }, step.timeout); + } + }; + const disarmStepTimer = (): void => { + if (timer !== undefined) { + clearTimeout(timer); + timer = undefined; + } + }; + armStepTimer(); try { // Suspend/resume bridge. The first invocation drives a plain agent @@ -1526,6 +1543,12 @@ async function runStep( // `{ suspend }` arm below. if (resumeFromPark !== undefined) { const parkState = await reloadState(env, runId); + // An input re-park is trigger-idle, not execution: disarm the + // execution timer across the wait and re-arm a fresh budget on + // resume. An approval re-park keeps the timer armed (see the + // approval-park note below). + const resumeIsInput = resumeFromPark.parkKind === "input"; + if (resumeIsInput) disarmStepTimer(); const decision = await parkOnSignal( env, runId, @@ -1536,6 +1559,7 @@ async function runStep( parkState, stepAbort.signal, ); + if (resumeIsInput) armStepTimer(); resume = { correlationId: resumeFromPark.correlationId, decision, @@ -1594,6 +1618,10 @@ async function runStep( if (!hasMoreTriggers) break; const inputCorrelationId = env.newId("corr"); const rearmState = await reloadState(env, runId); + // The step is trigger-idle until its next trigger arrives: disarm + // the execution timer across the park and re-arm a fresh budget + // for the next turn on resume. + disarmStepTimer(); const decision = await parkOnSignal( env, runId, @@ -1605,6 +1633,7 @@ async function runStep( rearmState, stepAbort.signal, ); + armStepTimer(); resume = { correlationId: inputCorrelationId, decision, @@ -1618,7 +1647,9 @@ async function runStep( // reduced state passed to `parkOnSignal` reads the step as // `in-flight`, and its re-park guard emits a fresh `SignalAwaited` // rather than treating this as a re-park of an already-awaiting - // gate. + // gate. The execution timer stays armed across this approval park: + // an approval wait holds a mandatory snapshot and stays bounded by + // `step.timeout`; only trigger-idle input parks disarm (above). const parkState = await reloadState(env, runId); const decision = await parkOnSignal( env,