Skip to content

feat(workflow-mount): run-scoped routes and agent tools accept metadata - #19

Merged
TheGreatAxios merged 1 commit into
mainfrom
cl-8722-run-scoped-routes-and-agent-tools-accept-metadata
Sep 20, 2026
Merged

TheGreatAxios merged 1 commit into
mainfrom
cl-8722-run-scoped-routes-and-agent-tools-accept-metadata

Conversation

@TheGreatAxios

Copy link
Copy Markdown
Contributor

Motivation

CL-8722. mount.ts (the browser-facing mount) already accepts optional metadata on POST /artifacts and POST /artifacts/:id/versions, but the run-scoped mount (workflow-mount.ts) and the agent tool definitions in tools.ts had no metadata surface at all — a workflow run had no way to attach application metadata (e.g. which project/stage an artifact belongs to) the way a human caller already can.

Change

  • workflow-mount.ts: CreateWorkflowArtifactBody, CreateWorkflowBinaryArtifactBody, and ReviseWorkflowArtifactBody all gain an optional metadata field, reusing the exact MetadataShape.or("null") shape mount.ts validates with. ReviseWorkflowArtifactBody also gains a .narrow requiring at least one of title/content/metadata, matching ReviseArtifactRequest.
  • uploads.ts: createFileArtifact gains an optional metadata pass-through to createArtifact, so POST /artifacts/binary can stamp metadata on version 1 in the same transaction, rather than bypassing the single MIME/content-store choke point the module's doc comment calls out as the "ONE way a file becomes an artifact."
  • tools.ts: artifact_create and artifact_write in ARTIFACT_TOOL_DEFINITIONS gain an optional metadata object parameter with a one-line description.
  • sidecar-bundle.ts: requestFor forwards metadata to the artifact_create/artifact_write requests unchanged when present, omitted otherwise.

Semantics (unchanged from mount.ts)

  • Create: metadata omitted or explicit null both store null; an object is stored as-is.
  • Revise: omitted carries the prior version's metadata forward; explicit null clears it; an object replaces it.
  • Anything else (string, array, number) is 400.
  • source ({ origin: "workflow", runId }) and generatedBy are always built from the resolved run scope in the handler, never read off the request body — a body field named source, runId, or generatedBy has no effect, same as before this change.

Verification

Ran locally (no local Postgres, per repo policy):

  • bun run typecheck — clean
  • bun run build — clean
  • bun run scripts/check-deps.ts — clean
  • bun test src/sidecar-bundle.test.ts src/destructive-tests-gate.test.ts — 30 pass (the only Postgres-free suites touched)

Postgres-backed suites (workflow-mount.test.ts, uploads.test.ts, tools.test.ts, mount.test.ts unchanged) fail closed locally by design (ALLOW_DESTRUCTIVE_ARTIFACT_TESTS unset) and run only in CI: new tests cover metadata persisting on version 1 (text + binary create), revise carry-forward/clear/reject, the tool-definition schema, sidecar pass-through, and a body that tries to smuggle source/runId/generatedBy on create (asserts the stored source stays server-stamped).

Reference CL-8722.

…tools

Run-scoped create/binary/revise and the artifact_create/artifact_write
tool definitions carried no metadata field, forcing a workflow run to
lose whatever project/stage context the browser mount already lets a
human attach. Reuse mount.ts's exact metadata shape and semantics:
omitted carries the prior version forward on revise, explicit null
clears it, anything else must be a JSON object. source and generatedBy
stay server-stamped from the resolved run scope regardless of what a
body sends.

createFileArtifact (uploads.ts) gained an optional metadata pass-through
so the binary create route can stamp it on version 1 without a second
write or duplicating the single MIME/content-store choke point it
already guards.
@TheGreatAxios
TheGreatAxios merged commit 031fc9e into main Sep 20, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant