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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 19 additions & 19 deletions VENDORED.md

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions scripts/checks/kill-dates.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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

2 changes: 1 addition & 1 deletion vendor/intx/hub-sessions/VENDORED-FROM
Original file line number Diff line number Diff line change
@@ -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__<n>) 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__<n>) 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).
74 changes: 74 additions & 0 deletions vendor/intx/hub-sessions/src/session-service-pins.test.ts
Original file line number Diff line number Diff line change
@@ -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);
});
});
92 changes: 92 additions & 0 deletions vendor/intx/hub-sessions/src/session-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ import type {
import {
buildInertProjectionStepSources,
deriveRunAddress,
deriveStepAgentId,
resolveStepAddress,
WorkflowDefinitionInvalidError,
type DeployContent as OrchestratorDeployContent,
} from "@intx/workflow-deploy";
Expand Down Expand Up @@ -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. */
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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 `<runId>-<stepId>` 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,
Expand Down
25 changes: 25 additions & 0 deletions vendor/intx/hub-sessions/src/workflow-allocation-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<string, unknown>,
): 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;
Expand Down Expand Up @@ -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,
});
Expand Down
2 changes: 1 addition & 1 deletion vendor/intx/workflow/VENDORED-FROM
Original file line number Diff line number Diff line change
@@ -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).
Loading
Loading