@archmax-ai/harness 0.4.2 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. package/README.md +13 -1
  2. package/dist/agent.d.ts +14 -0
  3. package/dist/agent.js.map +1 -1
  4. package/dist/assembly/compose.js +54 -28
  5. package/dist/assembly/compose.js.map +1 -1
  6. package/dist/assembly/index.js +51 -11
  7. package/dist/assembly/index.js.map +1 -1
  8. package/dist/authoring-skill/archmax-harness/SKILL.md +2 -2
  9. package/dist/authoring-skill/archmax-harness/references/backend-integration.md +52 -14
  10. package/dist/authoring-skill/archmax-harness/references/hook-and-test-scripts.md +5 -2
  11. package/dist/authoring-skill/archmax-harness/references/workflow-schema.md +95 -18
  12. package/dist/authoring-skill/archmax-harness/references/workflow-yaml.md +1 -1
  13. package/dist/cli/bootstrap.d.ts +8 -1
  14. package/dist/cli/bootstrap.js +43 -3
  15. package/dist/cli/bootstrap.js.map +1 -1
  16. package/dist/cli/command.d.ts +3 -1
  17. package/dist/cli/command.js +1 -1
  18. package/dist/cli/command.js.map +1 -1
  19. package/dist/cli/turn.d.ts +3 -1
  20. package/dist/cli/turn.js +1 -0
  21. package/dist/cli/turn.js.map +1 -1
  22. package/dist/cli.js +9 -1
  23. package/dist/cli.js.map +1 -1
  24. package/dist/core/attachments.d.ts +64 -0
  25. package/dist/core/attachments.js +87 -0
  26. package/dist/core/attachments.js.map +1 -0
  27. package/dist/core/binary-read.d.ts +20 -4
  28. package/dist/core/binary-read.js +36 -5
  29. package/dist/core/binary-read.js.map +1 -1
  30. package/dist/core/events.d.ts +6 -0
  31. package/dist/core/events.js.map +1 -1
  32. package/dist/core/file-operations.d.ts +22 -0
  33. package/dist/core/file-operations.js +54 -0
  34. package/dist/core/file-operations.js.map +1 -1
  35. package/dist/core/mount-prompt.d.ts +2 -1
  36. package/dist/core/mount-prompt.js +4 -2
  37. package/dist/core/mount-prompt.js.map +1 -1
  38. package/dist/core/platform-prompt.generated.js +1 -1
  39. package/dist/core/platform-prompt.generated.js.map +1 -1
  40. package/dist/core/session-id.d.ts +12 -2
  41. package/dist/core/session-id.js +30 -2
  42. package/dist/core/session-id.js.map +1 -1
  43. package/dist/core/tool-context.d.ts +13 -2
  44. package/dist/core/tool-context.js +2 -1
  45. package/dist/core/tool-context.js.map +1 -1
  46. package/dist/core/workspace-router.js +5 -3
  47. package/dist/core/workspace-router.js.map +1 -1
  48. package/dist/index.d.ts +5 -1
  49. package/dist/index.js +3 -1
  50. package/dist/index.js.map +1 -1
  51. package/dist/kernel/kernel.d.ts +9 -0
  52. package/dist/kernel/kernel.js +23 -4
  53. package/dist/kernel/kernel.js.map +1 -1
  54. package/dist/machine/lint-spec.js +8 -4
  55. package/dist/machine/lint-spec.js.map +1 -1
  56. package/dist/machine/machine.d.ts +33 -7
  57. package/dist/machine/machine.js +55 -10
  58. package/dist/machine/machine.js.map +1 -1
  59. package/dist/machine/mount-grants.d.ts +3 -2
  60. package/dist/machine/mount-grants.js.map +1 -1
  61. package/dist/machine/signature.d.ts +16 -5
  62. package/dist/machine/signature.js +25 -4
  63. package/dist/machine/signature.js.map +1 -1
  64. package/dist/machine/spec-schema.d.ts +10 -0
  65. package/dist/public/spec.d.ts +5 -3
  66. package/dist/public/spec.js +5 -3
  67. package/dist/public/spec.js.map +1 -1
  68. package/dist/sessions/resume.d.ts +14 -1
  69. package/dist/sessions/resume.js +13 -0
  70. package/dist/sessions/resume.js.map +1 -1
  71. package/dist/sessions/scope.d.ts +18 -11
  72. package/dist/sessions/scope.js +21 -23
  73. package/dist/sessions/scope.js.map +1 -1
  74. package/dist/workflow/agent-tools.d.ts +2 -1
  75. package/dist/workflow/agent-tools.js +8 -7
  76. package/dist/workflow/agent-tools.js.map +1 -1
  77. package/dist/workflow/control-tools.d.ts +12 -1
  78. package/dist/workflow/control-tools.js +33 -4
  79. package/dist/workflow/control-tools.js.map +1 -1
  80. package/dist/workflow/file-values.d.ts +44 -0
  81. package/dist/workflow/file-values.js +29 -0
  82. package/dist/workflow/file-values.js.map +1 -0
  83. package/dist/workflow/governance.d.ts +10 -0
  84. package/dist/workflow/governance.js +70 -1
  85. package/dist/workflow/governance.js.map +1 -1
  86. package/dist/workflow/middleware.d.ts +6 -0
  87. package/dist/workflow/middleware.js +34 -1
  88. package/dist/workflow/middleware.js.map +1 -1
  89. package/dist/workflow/parks.js +5 -1
  90. package/dist/workflow/parks.js.map +1 -1
  91. package/dist/workflow/returns-check.d.ts +3 -0
  92. package/dist/workflow/returns-check.js +1 -1
  93. package/dist/workflow/returns-check.js.map +1 -1
  94. package/dist/workflow/signature-checks.d.ts +47 -5
  95. package/dist/workflow/signature-checks.js +73 -9
  96. package/dist/workflow/signature-checks.js.map +1 -1
  97. package/dist/workflow/state.d.ts +7 -0
  98. package/dist/workflow/state.js +14 -1
  99. package/dist/workflow/state.js.map +1 -1
  100. package/dist/workflow/sub-workflow.d.ts +31 -2
  101. package/dist/workflow/sub-workflow.js +148 -30
  102. package/dist/workflow/sub-workflow.js.map +1 -1
  103. package/dist/workflow/tool-service.d.ts +5 -1
  104. package/dist/workflow/tool-service.js +9 -3
  105. package/dist/workflow/tool-service.js.map +1 -1
  106. package/dist/workflow/turn-boundary.d.ts +3 -0
  107. package/dist/workflow/turn-boundary.js +5 -2
  108. package/dist/workflow/turn-boundary.js.map +1 -1
  109. package/dist/workflow/workflow-tools.js +11 -0
  110. package/dist/workflow/workflow-tools.js.map +1 -1
  111. package/package.json +1 -1
  112. package/skills/archmax-harness/SKILL.md +2 -2
  113. package/skills/archmax-harness/references/backend-integration.md +52 -14
  114. package/skills/archmax-harness/references/hook-and-test-scripts.md +5 -2
  115. package/skills/archmax-harness/references/workflow-schema.md +95 -18
  116. package/skills/archmax-harness/references/workflow-yaml.md +1 -1
@@ -96,7 +96,7 @@ All optional (`CreateAgentParams`, `src/assembly/index.ts`):
96
96
  | `model` | `BaseChatModel` | Defaults to the env-configured OpenAI-compatible model. Inject your own to bypass env. |
97
97
  | `backend` | `BackendProtocolV2` | Serves the authored workspace. Defaults to a `FilesystemBackend` over `rootDir`. |
98
98
  | `authoring` | `BackendProtocolV2` | Serves the **authoring plane** — `workflows/**` (machine specs including the rubrics their states declare, `WORKFLOW.md`, `hooks/`, `tests/`) — to the runtime only. Never a route in the agent's workspace, so no tool call or PTC call can reach it. Defaults to `backend` when you supply one, else a `FilesystemBackend` over the resolved root. Handing it to a **writable** mount throws `AuthoringBackendExposedError`; a read-only mount may share it. |
99
- | `mounts` | `Record<string, MountSpec>` | Authored mounts as a `CompositeBackend` route table: key → backend, or `{ backend, readOnly, governed, searchable }`. Trailing slash = directory mount; no slash = exact-path file mount (`"/AGENTS.md"`). Read-only unless declared otherwise. `governed: true` hands the spec's `mounts` block the decision of **which states** may reach it (closed by default, like a skill bundle) and whether each may write there; a mount not so declared is visible in every state exactly as today, so a table that marks nothing behaves unchanged. `readOnly` is a **ceiling** the spec cannot lift: a grant may narrow a writable mount to reads in a state, never open a read-only one. A key may be several segments deep (`"/catalogs/eu/"`); its **first** segment is what is reserved, so `/workflows/x/` fails as `/workflows/` does. Omitted on the default backend: `defaultMounts(rootDir)` (the conventional table — `/skills/`, `/.platform/`, `/AGENTS.md`, none governed — extend with `{ ...defaultMounts(root), "/templates/": … }`). Omitted with a custom `backend`: nothing authored is served; expose subtrees with `mountSubtree(backend, "skills")`. A key colliding with a run area — or naming the authoring-plane prefix (`/workflows/`) — throws `MountCollisionError`. `searchable: false` declares a mount the runtime never searches on its own initiative: a root-wide `grep`/`glob` fans out over the other mounts only, while a search the agent addresses at the mount (or a path inside it) still reaches its backend and returns the backend's own answer — matches or `{ error }` — verbatim. Use it for a backend that must refuse searches (a remote folder served live). Listing and reading are unchanged, the prompt marks it "browse only", names arrive as `MountPrefixes.unsearchable`, and it is ignored on a file mount. |
99
+ | `mounts` | `Record<string, MountSpec>` | Authored mounts as a `CompositeBackend` route table: key → backend, or `{ backend, readOnly, governed, searchable }`. Trailing slash = directory mount; no slash = exact-path file mount (`"/AGENTS.md"`). Read-only unless declared otherwise. `governed: true` hands the spec's `mounts` block the decision of **which states** may reach it (closed by default, like a skill bundle) and whether each may write there; a mount not so declared is visible in every state exactly as today, so a table that marks nothing behaves unchanged. `readOnly` is a **ceiling** the spec cannot lift: a governed writable mount is written only by a workflow whose own grants ask `access: read_write` (a bare grant reads it, so serving one route writable for one workflow in a delegation tree opens it to no other), and a grant may narrow a writable mount to reads in a state, never open a read-only one. A key may be several segments deep (`"/catalogs/eu/"`); its **first** segment is what is reserved, so `/workflows/x/` fails as `/workflows/` does. Omitted on the default backend: `defaultMounts(rootDir)` (the conventional table — `/skills/`, `/.platform/`, `/AGENTS.md`, none governed — extend with `{ ...defaultMounts(root), "/templates/": … }`). Omitted with a custom `backend`: nothing authored is served; expose subtrees with `mountSubtree(backend, "skills")`. A key colliding with a run area — or naming the authoring-plane prefix (`/workflows/`) — throws `MountCollisionError`. `searchable: false` declares a mount the runtime never searches on its own initiative: a root-wide `grep`/`glob` fans out over the other mounts only, while a search the agent addresses at the mount (or a path inside it) still reaches its backend and returns the backend's own answer — matches or `{ error }` — verbatim. Use it for a backend that must refuse searches (a remote folder served live). Listing and reading are unchanged, the prompt marks it "browse only", names arrive as `MountPrefixes.unsearchable`, and it is ignored on a file mount. |
100
100
  | `sessionStore` | `SessionStore` | Physical storage for run state (checkpoints, artifacts, the per-session `scratchpad/`). Zero-config default: `createFilesystemSessionStore({ dir: "<rootDir>/sessions" })`. Required with a custom `backend` (else `SessionStoreRequiredError`). Build with `createBackendSessionStore({ backend, prefix? })` for S3-style storage or `createMemorySessionStore()` for ephemeral runs. |
101
101
  | `systemPrompt` | `string` | Appended after workspace `AGENTS.md`. |
102
102
  | `tools` | `StructuredTool[]` | Host tools, granted per state by `tools.allow`. Build them with `toolsFromMap` — see [host tools](#host-tools). A name starting `archmax_`, or naming a runtime file operation (`copy_file`, `move_file`, `remove_file`), throws `ReservedToolNameError`. |
@@ -333,9 +333,11 @@ turn ended in — the position, variables, transcript and files are already ther
333
333
  message.
334
334
 
335
335
  The runtime does not reposition a later turn, so nothing is injected into the
336
- transcript to explain a jump. When a turn needs a path the current state cannot
337
- reach, the agent calls `archmax_reset` to return to the state the conversation began
338
- in (available in every state). To continue *mid-state* instead — inside the state
336
+ transcript to explain a jump. When the current state can serve the new message, the
337
+ agent answers there without a reset. That includes a terminal state that is also the
338
+ state the conversation began in, such as a one-state chat workflow. When a turn needs
339
+ a path the current state cannot reach, the agent calls `archmax_reset` to return to
340
+ the state the conversation began in (available in every state). To continue *mid-state* instead — inside the state
339
341
  that stopped, with the arrival in its transcript — the turn must park rather than
340
342
  finish.
341
343
 
@@ -378,7 +380,7 @@ const outcome = await agent.workflow!.send(sessionId, { message: "Refund the ord
378
380
 
379
381
  - `signatureJsonSchema(entries)` → `{ type: "object", properties, required }`:
380
382
  one property per entry in declaration order, every name required,
381
- `date`/`date-time` as `{ type: "string", format }`, an untyped entry as `{}`,
383
+ `date`/`date-time`/`file` as `{ type: "string", format }`, an untyped entry as `{}`,
382
384
  an entry's `description` carried over. It adds no `additionalProperties`; set
383
385
  it for your own ingress.
384
386
  - `signatureValueIssues(entries, values)` → one issue per missing name and per
@@ -387,6 +389,19 @@ const outcome = await agent.workflow!.send(sessionId, { message: "Refund the ord
387
389
  `"4"` to `4` before it validates or seeds.
388
390
  - A trigger's `description` is written for the caller. Use it as the MCP tool
389
391
  or operation description. The session's own model never sees it.
392
+ - **A `file` entry** (`format: "file"` in the schema) takes a workspace path. To
393
+ hand a session an uploaded file, pass it on the turn rather than writing into
394
+ the store yourself:
395
+ `send(sessionId, { message, files: { invoice: { name: "invoice.pdf", content: bytes } } })`.
396
+ The runtime places the bytes in the session's `scratchpad/attachments/` (a taken
397
+ name gets `-1`, `-2`, …), seeds `invoice`, locked, with the placed path, and the
398
+ turn boundary then checks that the file is there and readable. `send` throws
399
+ `InvalidTurnFileError`, before anything is written, for a bad variable or file
400
+ name, a variable also given in `variables`, a session parked at a human state, or
401
+ bytes the store cannot hold exactly (a non-text file needs a store with
402
+ `uploadFiles`). `signatureValueIssues` checks only a `file` value's shape, so a
403
+ start form validates the path the upload will produce, or skips the entry and
404
+ lets `files` supply it.
390
405
  - A host that reads specs itself must read `requires`/`returns` through
391
406
  `normalizeSignature` (both spellings → `{ name, type?, description? }[]`),
392
407
  never as `string[]`: an entry may be an object. Hosts must be on the release
@@ -601,6 +616,15 @@ A custom `backend` **requires** an explicit `sessionStore` — assembly throws
601
616
  Persisting the session zone off-box (an S3-backed session store) is how you share run
602
617
  state across a worker fleet and an API.
603
618
 
619
+ A session's files are stored under `<sessionId>/` in the store (beneath its
620
+ `prefix`): the agent's `scratchpad/x.txt` in session `s1` is `s1/scratchpad/x.txt`.
621
+ That address is a contract, so a host may read or write a session's files through
622
+ its own handle on the store (ranged reads, recursive listings, presigned URLs). A
623
+ host tool keys them by `ToolContext.sessionId`, which inside a sub-workflow is the
624
+ child's id, never the session the turn was sent to. `sessionIdRejection` refuses an
625
+ id holding `~` in any shape but a child's (`<parent>~<n>`): mint top-level ids
626
+ without it.
627
+
604
628
  `downloadFiles`, `uploadFiles` and `delete` are optional in the protocol and stay
605
629
  optional in the workspace: a store with only the required methods serves skills,
606
630
  reads and text copies. `downloadFiles` is always present and reads a store without
@@ -645,7 +669,8 @@ const agent = await createAgent({ tools, essentialTools: ["get_markdown"] });
645
669
  - `paths` declares the arguments that name workspace paths and how the call
646
670
  uses each. Every path rule binds them: the read-only zone, the runtime's own
647
671
  areas, the skills and mounts the state was given (`mount.not-allowed`,
648
- `skill.not-allowed`), a mount's `access: read` (`mount.read-only` for a
672
+ `skill.not-allowed`), a mount's `access: read` or a governed mount no grant
673
+ of the workflow asks `read_write` for (`mount.read-only` for a
649
674
  `write` or `remove`), inherited denials and `paths:` guards. A refused call
650
675
  never runs the handler. No declaration, no path rules. An argument may hold a
651
676
  list of paths (`files: string[]`), each governed; any other shape is refused.
@@ -654,8 +679,13 @@ const agent = await createAgent({ tools, essentialTools: ["get_markdown"] });
654
679
  - `context.workspace` is the turn's workspace, bound to the session — the
655
680
  instance `read_file` uses — with `downloadFiles`, `uploadFiles` (when the
656
681
  session store has it) and `delete` besides the text methods. The plain agent
657
- hands the same context. Outside a turn, reading it throws; the property is
658
- non-enumerable there, so comparing or logging the context does not.
682
+ hands the same context.
683
+ - `context.sessionId` is the session the call is made in: inside a sub-workflow,
684
+ the child's own id (`<parent>~<n>`), for the model's call and a script's alike.
685
+ Key any session file your host stores itself by it (`<sessionId>/<path>` in the
686
+ session store), never by the session you sent the turn to.
687
+ - Outside a turn, reading either throws; both are non-enumerable there, so
688
+ comparing or logging the context does not.
659
689
 
660
690
  ## Cases against your agent
661
691
 
@@ -708,7 +738,7 @@ real). A bespoke target that intercepts by other means sets
708
738
  `capabilities.toolMocks` itself. Mockless cases run against any
709
739
  workflow-governed target.
710
740
 
711
- **Sub-workflows inherit the assembly.** When a workflow delegates (by advancing
741
+ **Sub-workflows inherit the assembly.** When a workflow delegates (by calling
712
742
  an `archmax_workflow_<slug>` tool), the child runtime is
713
743
  composed from the *same* resolved inputs as the parent — model and
714
744
  `modelFactory`, `backend` and `mounts`, `sessionStore` and `checkpointer`, host
@@ -721,11 +751,19 @@ never delegated to is never loaded, and one delegated from many places is
721
751
  composed once. A child whose spec is broken surfaces as a *dispatch* failure, not
722
752
  an assembly failure — a parent still assembles.
723
753
 
724
- The child runs on the parent's **session id** (which is what gives it the same
725
- run zone) under a nested checkpoint namespace, so `sessions.list()` reports one
726
- session and the parent session's metrics include the child's tokens.
727
- `capabilities.subWorkflows` is stamped `true` for a governed assembly and `false`
728
- for the plain one.
754
+ The child runs as a **separate session**, `<parent>~<n>`, in the same session
755
+ store, with its own checkpoints, its own token accounting and its own file space:
756
+ its `scratchpad/` is not its caller's, so it can neither read nor overwrite a file
757
+ of its caller's. `n` is the dispatch's number in the calling session, counted from 1
758
+ across all its turns in its checkpointed state, so an agent built per turn never
759
+ reuses one; a grandchild is `<parent>~<n>~<m>`. The `sub-workflow-*` events and a
760
+ pending delegation name it by its `dispatchId`, the id below the root session (`1`,
761
+ `1~1`). A host tool called in the child gets the child's id as
762
+ `ToolContext.sessionId`, and its file work belongs to the child. `sessions.list()` reports it beside its caller
763
+ with `parentSessionId` naming the caller, and `sessions.delete` removes it by its
764
+ own id. The only files that cross are the runtime's copies of declared `file` arguments and
765
+ `file` returns. `capabilities.subWorkflows` is stamped `true` for a governed
766
+ assembly and `false` for the plain one.
729
767
 
730
768
  Omit both options and behavior is identical to `archmax test`. Cases run
731
769
  sequentially (`tests.maxConcurrency` above 1 is rejected, not silently
@@ -236,7 +236,9 @@ A **binary file** is not a refusal and does not throw: reads are text only, so
236
236
  file whose content holds a NUL byte (an archive, an Office document), resolves to
237
237
  the notice `Error: '<path>' is a binary file (<type>, <size>) and was not read;
238
238
  read_file returns text files only.` instead of content — an image too, even when
239
- the host turned on `images`, which shows images to the model only. A missing file reads as
239
+ the host turned on `images`, which shows images to the model only. XML and JSON
240
+ are text even when the store labels them `application/xml` or a `+xml`/`+json`
241
+ type, so an Office document's unpacked `word/document.xml` reads as text. A missing file reads as
240
242
  an `Error: …` string the same way. A script that parses what it read checks
241
243
  first:
242
244
 
@@ -322,7 +324,8 @@ state fails that call closed with `parked`.
322
324
  Scripts still may not call `archmax_advance` (moving the state machine is the model's governed
323
325
  decision) or `archmax_set_variables`. Concurrent calls succeed or fail **independently**, so a script
324
326
  can act on what worked — `Promise.allSettled` is the honest shape when partial success is
325
- meaningful. Give each sub-run its own output path: they share one run zone.
327
+ meaningful. Each sub-run is its own session with its own `scratchpad/`, so concurrent sub-runs
328
+ never collide on a path; a `file` return comes back as a copy under a name no other file holds.
326
329
 
327
330
  ### Worked example: a `before` gate
328
331
 
@@ -196,7 +196,10 @@ mounts?:
196
196
  # workflow reaches no governed mount; validate says so
197
197
  # ONCE, naming them — write `allow_always: []` to mean it.
198
198
  # An entry is a NAME, or `{ mount: <name>, access: read |
199
- # read_write }` to say what this level gives. The host's
199
+ # read_write }` to say what this level gives. A bare NAME
200
+ # asks for NO write: a governed mount is written only
201
+ # where some grant of THIS workflow says `read_write`
202
+ # (a child's or caller's grant never counts). The host's
200
203
  # readOnly is a CEILING: `read_write` on a read-only mount
201
204
  # opens nothing (validate warns); `read` NARROWS a
202
205
  # writable one, and no narrower level widens it back.
@@ -368,7 +371,9 @@ states:
368
371
  # warns about one that reads like it) — `forbid` is.
369
372
  # An entry may name its access:
370
373
  # allow: [{ mount: shared, access: read }]
371
- # reads a writable mount without writing it here. The
374
+ # reads a writable mount without writing it here, and
375
+ # allow: [{ mount: shared, access: read_write }]
376
+ # asks to write it — which a bare name never does. The
372
377
  # host's posture is the ceiling — `read_write` cannot
373
378
  # open a read-only mount — and a `read` at either level
374
379
  # holds, so a state never widens what the workflow
@@ -557,7 +562,9 @@ states:
557
562
  - **`type`** is one of `string`, `integer` (no fractional part), `number`
558
563
  (finite), `boolean`, `date` (RFC 3339 `YYYY-MM-DD`, a real calendar day),
559
564
  `date-time` (RFC 3339 with a mandatory `Z`/`±hh:mm` offset), `object` (not an
560
- array) or `array`. Nothing is coerced (`"4"` is not an `integer`) and a typed
565
+ array), `array` or `file` (a path from the workspace root, such as
566
+ `scratchpad/attachments/invoice.pdf` or `skills/billing/assets/template.pdf`; see
567
+ [Passing files](#passing-files)). Nothing is coerced (`"4"` is not an `integer`) and a typed
561
568
  entry never takes `null`. It is held **at the start** (a mistyped seed is
562
569
  refused before any model call), **at the write** (`archmax_set_variables` of a
563
570
  mistyped typed return of the current trigger is a correctable refusal,
@@ -565,6 +572,17 @@ states:
565
572
  run — in practice a script or hook write). There are no enums, item or
566
573
  property schemas, ranges or optional inputs. An unknown `type`, an unknown
567
574
  entry key (`default:`) or an empty `description` fails load.
575
+ - **A `file` value must name a readable file.** The pure rule checks only the
576
+ path's shape (a host runs it in a browser). At the start, at the write, at
577
+ completion and at a delegation call the runtime also requires a **file** (not a
578
+ folder) at the path that the session may read **on runtime authority** — the
579
+ rules a hook is bound by: zone rules (`checkpoints/`, `artifacts/`, `_specs/`
580
+ never) and every workflow-wide `forbid_always`, inherited ones included; the
581
+ state's allow list and mount/skill grants do not narrow it. So tell the agent to
582
+ write the file *before* it sets a `file` return: `archmax_set_variables` refuses
583
+ a path with nothing there. A host hands a file in with `TurnInput.files` (CLI:
584
+ `archmax run … --file invoice=./invoice.pdf`), which places it under
585
+ `scratchpad/attachments/` and seeds the path.
568
586
  - **When to type.** Type an entry when something outside the session reads the
569
587
  contract: a delegating model that must build the argument, a host publishing an
570
588
  MCP tool or a start form. Leave it bare when any value will do. Typing a
@@ -908,13 +926,13 @@ error.
908
926
 
909
927
  ### Read or read/write
910
928
 
911
- A grant entry is either a bare mount name — taking the posture the host wired — or
912
- a mapping naming the access this level gives:
929
+ A grant entry is either a bare mount name, which asks for no write, or a mapping
930
+ naming the access this level gives:
913
931
 
914
932
  ```yaml
915
933
  mounts:
916
934
  allow_always:
917
- - reference # the host's posture
935
+ - reference # read; written only if a grant below asks
918
936
  - { mount: shared, access: read_write } # writable where the host allows it
919
937
 
920
938
  states:
@@ -923,6 +941,17 @@ states:
923
941
  allow: [{ mount: shared, access: read }] # reads it, cannot write it here
924
942
  ```
925
943
 
944
+ **A workflow writes a governed mount only where its own grants ask to.** It is
945
+ writable in a state when the host serves it writable, some grant of *this*
946
+ workflow says `access: read_write` (in `allow_always` or any state's `allow`), and
947
+ no grant applicable in the state says `access: read`. So a bare grant in one state
948
+ and a `read_write` grant in another both write. One mount table serves a session
949
+ and every child it dispatches, and the host serves a route writable when any
950
+ workflow in that tree asks; a mount still belongs to the workflow that grants it,
951
+ so a caller's `read_write` never lets its child write through a bare grant, nor the
952
+ other way round. An ungoverned mount takes the host's posture: it has no grant to
953
+ ask with.
954
+
926
955
  The host's `readOnly` is a **ceiling**, not a default to argue with:
927
956
 
928
957
  - `access: read_write` on a mount the workspace serves read-only opens nothing,
@@ -936,7 +965,8 @@ The host's `readOnly` is a **ceiling**, not a default to argue with:
936
965
 
937
966
  Two refusals, because they are two different edits: a write into a mount the
938
967
  **host** serves read-only is `zone.read-only` (fix the wiring), and a write into
939
- one a **grant** narrowed is `mount.read-only` (fix the spec).
968
+ one a **grant** narrowed, or one no grant of the workflow asks to write, is
969
+ `mount.read-only` (fix the spec; the refusal says which).
940
970
 
941
971
  ### What the agent sees
942
972
 
@@ -972,7 +1002,8 @@ so `AGENTS.md.bak` is not captured.
972
1002
  everywhere already — use `forbid` to take one away);
973
1003
  - an `access: read_write` on a mount the host serves **read-only**;
974
1004
  - a name in both `allow_always` and a state's `allow` (unless the state entry
975
- narrows the access, which does real work);
1005
+ narrows the access to `read`, or asks `read_write` of a mount the root grants
1006
+ bare: both do real work);
976
1007
  - a state's `allow: []` beside a non-empty `allow_always`;
977
1008
  - a `forbid` naming a governed mount nothing would have enabled there;
978
1009
  - a `forbid_always` name some `allow` list also grants;
@@ -1015,7 +1046,8 @@ the host at assembly (`variables`, every seed locked), the agent mid-run
1015
1046
 
1016
1047
  `trigger` holds the current turn's trigger id. `title` holds a short one-line label
1017
1048
  naming the task the run is doing; the platform system prompt asks the agent to set
1018
- one as its first activity and update it when the task changes significantly, so a
1049
+ one as its first activity, and to rename it only when the whole conversation has
1050
+ moved to a different subject (a follow-up on the same subject keeps it), so a
1019
1051
  host can name a run instead of showing a session id. A sub-workflow's child is not
1020
1052
  asked — its title names a session nothing lists and is never returned — so its
1021
1053
  prompt leaves the step out; do not write "set the title" into a child's state
@@ -1340,7 +1372,7 @@ enrich:
1340
1372
  delegation may happen is decided by the caller's `tools.allow` entry. A target
1341
1373
  with no `manual` entry has no state to start in and fails closed. `session:` and
1342
1374
  `message:` on that trigger are host-facing keys a delegation ignores: a sub-run
1343
- shares its parent's session, and carries no message. `sub-workflow` is no longer
1375
+ is its own session, derived from its caller's, and carries no message. `sub-workflow` is no longer
1344
1376
  a trigger id — load and `validate` report it with the rename.
1345
1377
  - **Declare the child's signature** on that trigger — the contract, enforced both
1346
1378
  ways and at both ingresses:
@@ -1400,14 +1432,17 @@ enrich:
1400
1432
  state's work. A workspace overriding the platform prompt
1401
1433
  (`.platform/system/GRAPH_STATE.md`) keeps that by wrapping what children skip
1402
1434
  in `<!-- top-level-only -->` … `<!-- /top-level-only -->` lines.
1403
- - **Same agent, isolated context, shared session.** Same model, backend, host
1435
+ - **Same agent, isolated context, own session.** Same model, backend, host
1404
1436
  tools; its **own** grading rubrics, from its own spec; a fresh transcript; the child's *own* per-state
1405
- `tools.allow`. It shares the run's session, so it writes `scratchpad/…` and
1406
- `scratchpad/…` exactly as the parent does and the parent reads them afterwards.
1437
+ `tools.allow`. It is a separate session (`<parent>~<n>`, `n` the dispatch's
1438
+ number in the caller, counted across its turns) with its own checkpoints and its own `scratchpad/`: a path it reads or writes
1439
+ resolves inside its own session, so it can neither see nor overwrite a file of
1440
+ its caller's, and concurrent sub-runs cannot collide on a path.
1407
1441
  - **Nothing crosses implicitly.** Down: only the arguments the call passed —
1408
1442
  the calling run's own variables are not copied. Up: only the result message
1409
- and the files. Everything the child sets is discarded when it finishes.
1410
- - **Give each concurrent sub-run its own output path** — they share one run zone.
1443
+ and the declared returns. Everything else the child sets or writes stays in its
1444
+ session. The only files that cross are runtime-made copies of `file` arguments
1445
+ and `file` returns (see "Passing files" below).
1411
1446
  - **Bounds** — the dispatcher's `bounds: { maxDepth: 3, maxConcurrent: 4 }`. No longer a spec key: the strict schema rejects `settings.sub_workflows` by name.
1412
1447
  Excess concurrency queues; depth and cycles are refused.
1413
1448
  - **Params are the sub-run's initial variables** — same construction, same name
@@ -1435,6 +1470,46 @@ parent reading a field the child does not return is an **error**; a state whose
1435
1470
  still carry it), and a fan-out is exempt from that warning because its
1436
1471
  entries' keys are not knowable statically.
1437
1472
 
1473
+ ### Passing files
1474
+
1475
+ A sub-run's `scratchpad/` is not its caller's, so a bare path string returned by a
1476
+ child (`returns: [result_file]`, untyped) names a file the caller **cannot
1477
+ read**. Type the entry `file` instead, and the runtime copies the file across:
1478
+
1479
+ ```yaml
1480
+ # the child
1481
+ triggers:
1482
+ manual:
1483
+ requires: [{ name: invoice, type: file }]
1484
+ returns: [{ name: report, type: file }]
1485
+ ```
1486
+
1487
+ - **Down.** The caller passes any path in its workspace (`scratchpad/inbox/a.pdf`,
1488
+ `skills/billing/assets/template.pdf`). Before the child starts, the runtime
1489
+ copies the exact bytes into the **child's** `scratchpad/attachments/` (same name;
1490
+ two arguments with one name take `-1`, `-2`) and seeds the child with that path,
1491
+ so its opening message shows it. The child edits its own copy and never the
1492
+ caller's file. The argument is a `read` path argument of the delegation tool, so
1493
+ a `paths:` guard on the allow entry and the zone and mount rules bind it. An
1494
+ argument naming nothing is refused `invalid-param` before the child runs. A
1495
+ failed call's record names the caller's path.
1496
+ - **Up.** On completion, each `file` return the child set is copied into the
1497
+ **caller's** `scratchpad/attachments/` and the result names that path. A taken
1498
+ name gets the lowest free `-1`, `-2`, … before the extension (`report-1.pdf`), so
1499
+ repeated or parallel calls never overwrite each other or the caller's files. A
1500
+ return whose file is gone at completion fails the call `invalid-return`.
1501
+ - **No laundering.** A `file` value must name a file the session may read on
1502
+ runtime authority, and a child inherits every ancestor's `forbid_always`. So a
1503
+ child cannot hand back a file its caller's workflow denies: its agent's write
1504
+ is refused, and a script's write is rejected at completion.
1505
+ - **Instructions to write.** Tell the child to write the file *first* and then set
1506
+ the return to its path. Tell the caller the returned path is under
1507
+ `scratchpad/attachments/`. Name files for what they hold (`<order_id>.json`):
1508
+ the name survives the copy.
1509
+ - **Mocks and cases.** A mocked `file` return names a file in the case's own
1510
+ session (seed it with `workspace:`), and it arrives copied into
1511
+ `scratchpad/attachments/` like a real one. Assert the copy's path.
1512
+
1438
1513
  ### A parked run may speak, never act
1439
1514
 
1440
1515
  A park does not end the conversation. Two moments get a **reply-only turn** — one
@@ -1696,9 +1771,11 @@ single-segment one is, and a sibling under the same first segment (`catalogs/uk`
1696
1771
  is not.
1697
1772
 
1698
1773
  A mount the host mounted **writable** is not a read-only zone — its paths are
1699
- governed like ordinary run paths — but a state may still be given it read-only,
1700
- with `mounts: { allow: [{ mount: <name>, access: read }] }`. A write refused by
1701
- that grant is `mount.read-only`; one refused by the wiring is `zone.read-only`.
1774
+ governed like ordinary run paths — but a governed one is written only where a grant
1775
+ of the workflow says `access: read_write`, and a state may still be given it
1776
+ read-only, with `mounts: { allow: [{ mount: <name>, access: read }] }`. A write
1777
+ refused by a grant is `mount.read-only`; one refused by the wiring is
1778
+ `zone.read-only`.
1702
1779
  See [Mount governance](#mount-governance).
1703
1780
 
1704
1781
  The run root is writable, and it has exactly one named working area:
@@ -50,7 +50,7 @@ states:
50
50
  - { name: due, type: date, description: The day it is due. } # typed: held at the boundary
51
51
  returns: [result_file] # variables the run guarantees on completion (a caller's result);
52
52
  # short of them: a child returns what it set + a `note`; a top-level run is rejected
53
- # entry types: string integer number boolean date date-time object array
53
+ # entry types: string integer number boolean date date-time object array file
54
54
  instructions: >-
55
55
  Record the decision in scratchpad/refund.json, then archmax_advance to
56
56
  review; never close the case yourself.
@@ -1,4 +1,4 @@
1
- import type { Agent, WorkflowSurface } from "../agent.js";
1
+ import type { Agent, TurnFile, WorkflowSurface } from "../agent.js";
2
2
  import { type TriggerInput } from "../machine/triggers.js";
3
3
  import { type UsageTracker } from "../core/usage.js";
4
4
  import { type Style } from "./style.js";
@@ -10,6 +10,13 @@ import { type Invocation } from "./command.js";
10
10
  export declare function resolveWorkflow(given: string | undefined, rootDir: string | undefined): string;
11
11
  /** `--variables` must be a JSON object; anything else is an argument error before any assembly. */
12
12
  export declare function parseVariablesJson(raw: string | undefined): Record<string, unknown> | undefined;
13
+ /**
14
+ * `--file <variable>=<path>` occurrences as a turn's files: each local file read
15
+ * (relative to the working directory) under its base name. The CLI is a host, so
16
+ * it reads the local filesystem; the runtime places the bytes in the session.
17
+ * Every problem is a usage error, found before anything is assembled.
18
+ */
19
+ export declare function parseFileFlags(raw: string[] | undefined, variables: Record<string, unknown> | undefined): Record<string, TurnFile> | undefined;
13
20
  /** The one session header every command prints to stderr. Loads `.env` first so the model line is the effective one. */
14
21
  export declare function printSessionHeader(style: Style, workflow: string, rootDir: string | undefined, showModel?: boolean): void;
15
22
  /** Wire the state flow (and `--verbose` raw lines) behind a usage tracker whose handler the agent receives. */
@@ -4,12 +4,13 @@
4
4
  * event sink behind the state flow and the usage tracker, and the one
5
5
  * `withSession` wrapper every session command runs its body inside.
6
6
  */
7
- import { existsSync, readdirSync } from "node:fs";
8
- import { resolve } from "node:path";
7
+ import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
8
+ import { basename, resolve } from "node:path";
9
9
  import { createAgent } from "../assembly/index.js";
10
+ import { VARIABLE_NAME_PATTERN } from "../machine/variables.js";
10
11
  import { UnknownTriggerError } from "../machine/triggers.js";
11
12
  import { WorkflowDisabledError, WorkflowLoadError } from "../machine/load-spec.js";
12
- import { EmptyMessageError, InvalidDecisionTargetError, MissingDeliveryTriggerError, SessionNotAwaitingInputError, SessionNotParkedError, } from "../sessions/resume.js";
13
+ import { EmptyMessageError, InvalidTurnFileError, InvalidDecisionTargetError, MissingDeliveryTriggerError, SessionNotAwaitingInputError, SessionNotParkedError, } from "../sessions/resume.js";
13
14
  import { SessionNotResumableError, UnknownSessionTriggerError } from "../sessions/resolve.js";
14
15
  import { sessionIdRejection } from "../core/session-store.js";
15
16
  import { UnsupportedRuntimeContractError } from "../runtime/contract.js";
@@ -54,6 +55,44 @@ export function parseVariablesJson(raw) {
54
55
  }
55
56
  return value;
56
57
  }
58
+ /**
59
+ * `--file <variable>=<path>` occurrences as a turn's files: each local file read
60
+ * (relative to the working directory) under its base name. The CLI is a host, so
61
+ * it reads the local filesystem; the runtime places the bytes in the session.
62
+ * Every problem is a usage error, found before anything is assembled.
63
+ */
64
+ export function parseFileFlags(raw, variables) {
65
+ if (!raw || raw.length === 0)
66
+ return undefined;
67
+ const files = {};
68
+ for (const flag of raw) {
69
+ const at = flag.indexOf("=");
70
+ if (at <= 0 || at === flag.length - 1) {
71
+ throw new UsageError(`--file '${flag}' must be <variable>=<path> (e.g. --file invoice=./invoice.pdf)`);
72
+ }
73
+ const variable = flag.slice(0, at);
74
+ const path = flag.slice(at + 1);
75
+ if (!VARIABLE_NAME_PATTERN.test(variable)) {
76
+ throw new UsageError(`--file '${flag}': '${variable}' is not a valid variable name (lowercase letters, digits and underscores, starting with a letter)`);
77
+ }
78
+ if (Object.hasOwn(files, variable))
79
+ throw new UsageError(`--file names '${variable}' more than once`);
80
+ if (variables && Object.hasOwn(variables, variable)) {
81
+ throw new UsageError(`--file '${flag}': '${variable}' is also given in --variables; give it once`);
82
+ }
83
+ let content;
84
+ try {
85
+ if (!statSync(path).isFile())
86
+ throw new Error("not a file");
87
+ content = new Uint8Array(readFileSync(path));
88
+ }
89
+ catch {
90
+ throw new UsageError(`--file '${flag}': cannot read the file '${path}'`);
91
+ }
92
+ files[variable] = { name: basename(path), content };
93
+ }
94
+ return files;
95
+ }
57
96
  /** The raw event line for `--verbose`, including the two events the default console output skips. */
58
97
  function rawEventLine(event) {
59
98
  switch (event.type) {
@@ -96,6 +135,7 @@ const KNOWN_ERRORS = [
96
135
  SessionNotParkedError,
97
136
  InvalidDecisionTargetError,
98
137
  EmptyMessageError,
138
+ InvalidTurnFileError,
99
139
  SessionNotAwaitingInputError,
100
140
  MissingDeliveryTriggerError,
101
141
  SessionNotResumableError,
@@ -1 +1 @@
1
- {"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../../src/cli/bootstrap.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../../src/cli/bootstrap.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC1E,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEnD,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,mBAAmB,EAAqB,MAAM,wBAAwB,CAAC;AAChF,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACnF,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,0BAA0B,EAC1B,2BAA2B,EAC3B,4BAA4B,EAC5B,qBAAqB,GACtB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,wBAAwB,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AAC9F,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,+BAA+B,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAqB,MAAM,kBAAkB,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,eAAe,EAA+B,MAAM,mBAAmB,CAAC;AAC9F,OAAO,EAAE,WAAW,EAAE,KAAK,EAAc,MAAM,YAAY,CAAC;AAC5D,OAAO,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,EAAmB,MAAM,cAAc,CAAC;AAE1E;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,KAAyB,EAAE,OAA2B;IACpF,IAAI,KAAK;QAAE,OAAO,KAAK,CAAC;IACxB,MAAM,GAAG,GAAG,OAAO,CAAC,oBAAoB,CAAC,OAAO,CAAC,EAAE,WAAW,CAAC,CAAC;IAChE,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC;QAC3B,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;aACtC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,IAAI,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC,CAAC;aACnF,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QACvB,CAAC,CAAC,EAAE,CAAC;IACP,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,CAAC,CAAW,CAAC;IAClD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QACpB,MAAM,IAAI,UAAU,CAAC,mDAAmD,GAAG,EAAE,CAAC,CAAC;IACjF,MAAM,IAAI,UAAU,CAClB,uDAAuD,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACjF,CAAC;AACJ,CAAC;AAED,mGAAmG;AACnG,MAAM,UAAU,kBAAkB,CAAC,GAAuB;IACxD,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IACxC,IAAI,KAAc,CAAC;IACnB,IAAI,CAAC;QACH,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC1B,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,UAAU,CAAC,+BAA+B,CAAC,CAAC;IACxD,CAAC;IACD,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAChE,MAAM,IAAI,UAAU,CAClB,2EAA2E,CAC5E,CAAC;IACJ,CAAC;IACD,OAAO,KAAgC,CAAC;AAC1C,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAC5B,GAAyB,EACzB,SAA8C;IAE9C,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAC/C,MAAM,KAAK,GAA6B,EAAE,CAAC;IAC3C,KAAK,MAAM,IAAI,IAAI,GAAG,EAAE,CAAC;QACvB,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC7B,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACtC,MAAM,IAAI,UAAU,CAAC,WAAW,IAAI,iEAAiE,CAAC,CAAC;QACzG,CAAC;QACD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACnC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;QAChC,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC1C,MAAM,IAAI,UAAU,CAClB,WAAW,IAAI,OAAO,QAAQ,oGAAoG,CACnI,CAAC;QACJ,CAAC;QACD,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC;YAAE,MAAM,IAAI,UAAU,CAAC,iBAAiB,QAAQ,kBAAkB,CAAC,CAAC;QACtG,IAAI,SAAS,IAAI,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC,EAAE,CAAC;YACpD,MAAM,IAAI,UAAU,CAAC,WAAW,IAAI,OAAO,QAAQ,8CAA8C,CAAC,CAAC;QACrG,CAAC;QACD,IAAI,OAAmB,CAAC;QACxB,IAAI,CAAC;YACH,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE;gBAAE,MAAM,IAAI,KAAK,CAAC,YAAY,CAAC,CAAC;YAC5D,OAAO,GAAG,IAAI,UAAU,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC;QAC/C,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,UAAU,CAAC,WAAW,IAAI,4BAA4B,IAAI,GAAG,CAAC,CAAC;QAC3E,CAAC;QACD,KAAK,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC;IACtD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,qGAAqG;AACrG,SAAS,YAAY,CAAC,KAA6B;IACjD,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;QACnB,KAAK,YAAY;YACf,OAAO,UAAU,KAAK,CAAC,KAAK,KAAK,KAAK,CAAC,IAAI,EAAE,CAAC;QAChD,KAAK,aAAa;YAChB,OAAO,CACL,aAAa,KAAK,CAAC,KAAK,UAAU,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE;gBACvF,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAClE,CAAC;QACJ;YACE,OAAO,eAAe,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;IACxC,CAAC;AACH,CAAC;AAED,wHAAwH;AACxH,MAAM,UAAU,kBAAkB,CAChC,KAAY,EACZ,QAAgB,EAChB,OAA2B,EAC3B,SAAS,GAAG,KAAK;IAEjB,UAAU,CAAC,OAAO,CAAC,CAAC;IACpB,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,OAAO,IAAI,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC;IAC5D,GAAG,CAAC,KAAK,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,KAAK,oBAAoB,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACrE,IAAI,SAAS;QACX,GAAG,CAAC,KAAK,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,oBAAoB,EAAE,CAAC,CAAC;IAC3F,GAAG,CAAC,EAAE,CAAC,CAAC;AACV,CAAC;AAED,+GAA+G;AAC/G,MAAM,UAAU,eAAe,CAC7B,KAAY,EACZ,OAAgB,EAChB,IAAI,GAAG,uBAAuB,CAAC,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC;IAErD,OAAO,kBAAkB,CAAC;QACxB,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YACjB,IAAI,OAAO,EAAE,CAAC;gBACZ,MAAM,IAAI,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;gBACjC,IAAI,IAAI;oBAAE,GAAG,CAAC,IAAI,CAAC,CAAC;YACtB,CAAC;YACD,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAED,MAAM,YAAY,GAAG;IACnB,+BAA+B;IAC/B,iBAAiB;IACjB,mBAAmB;IACnB,qBAAqB;IACrB,qBAAqB;IACrB,0BAA0B;IAC1B,iBAAiB;IACjB,oBAAoB;IACpB,4BAA4B;IAC5B,2BAA2B;IAC3B,wBAAwB;IACxB,0BAA0B;CAC3B,CAAC;AACF,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,CAAU,EAAc,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,YAAY,GAAG,CAAC,CAAC;AAEhG,yGAAyG;AACzG,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,QAAgB,EAChB,OAA2B,EAC3B,KAAmB,EACnB,QAAyE,EAAE;IAE3E,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC;YAC9B,QAAQ;YACR,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5D,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACpD,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC3D,CAAC,CAAC;QACH,IAAI,CAAC,KAAK,CAAC,QAAQ;YAAE,MAAM,IAAI,QAAQ,CAAC,aAAa,QAAQ,gCAAgC,CAAC,CAAC;QAC/F,OAAO,KAA8C,CAAC;IACxD,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAI,OAAO,CAAC,CAAC,CAAC;YAAE,MAAM,IAAI,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;QAC9C,MAAM,CAAC,CAAC;IACV,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,GAAe,EACf,SAA6B,EAC7B,IAAmH;IAEnH,MAAM,SAAS,GAAG,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC;IACjF,IAAI,SAAS;QACX,MAAM,IAAI,UAAU,CAClB,uBAAuB,SAAS,OAAO,SAAS,oCAAoC,CACrF,CAAC;IACJ,MAAM,QAAQ,GAAG,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,QAA8B,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;IACtF,MAAM,KAAK,GAAG,WAAW,EAAE,CAAC;IAC5B,kBAAkB,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;IAC9C,MAAM,KAAK,GAAG,eAAe,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC;IAClE,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,QAAQ,EAAE,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACzD,IAAI,CAAC;QACH,OAAO,MAAM,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IAC7C,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAI,OAAO,CAAC,CAAC,CAAC;YAAE,MAAM,IAAI,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;QAC9C,MAAM,CAAC,CAAC;IACV,CAAC;YAAS,CAAC;QACT,IAAI,SAAS,KAAK,SAAS;YAAE,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACxD,CAAC;AACH,CAAC"}
@@ -10,8 +10,10 @@ export interface OptionSpec {
10
10
  description: string;
11
11
  placeholder?: string;
12
12
  short?: string;
13
+ /** The flag may be given more than once; its value is then the list of every occurrence. */
14
+ multiple?: boolean;
13
15
  }
14
- export type Values = Record<string, string | boolean | undefined>;
16
+ export type Values = Record<string, string | boolean | string[] | undefined>;
15
17
  export interface Invocation {
16
18
  positionals: string[];
17
19
  values: Values;
@@ -25,7 +25,7 @@ export const err = (line) => console.error(line);
25
25
  export function parseInvocation(cmd, args) {
26
26
  const options = Object.fromEntries(Object.entries({ ...GLOBAL_OPTIONS, ...cmd.options }).map(([name, spec]) => [
27
27
  name,
28
- { type: spec.type, ...(spec.short ? { short: spec.short } : {}) },
28
+ { type: spec.type, ...(spec.short ? { short: spec.short } : {}), ...(spec.multiple ? { multiple: true } : {}) },
29
29
  ]));
30
30
  let parsed;
31
31
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"command.js","sourceRoot":"","sources":["../../src/cli/command.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"command.js","sourceRoot":"","sources":["../../src/cli/command.ts"],"names":[],"mappings":"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"}
@@ -4,7 +4,7 @@
4
4
  * turn through `agent.workflow.send`; `decide` / `reply` / `deliver` each
5
5
  * resume one, and every outcome is described the same way.
6
6
  */
7
- import type { Agent } from "../agent.js";
7
+ import type { Agent, TurnFile } from "../agent.js";
8
8
  import type { TriggerInput } from "../machine/triggers.js";
9
9
  import type { DecideOutcome, Outcome, ReplyOutcome } from "../sessions/resume.js";
10
10
  import type { WorkflowMachine } from "../machine/machine.js";
@@ -27,6 +27,8 @@ export interface RunTurnInput {
27
27
  prompt: string;
28
28
  trigger?: TriggerInput;
29
29
  variables?: Record<string, unknown>;
30
+ /** Local files handed to the turn (`--file`), each seeding its variable with the placed path. */
31
+ files?: Record<string, TurnFile>;
30
32
  sessionId?: string;
31
33
  sessionPath?: string;
32
34
  }
package/dist/cli/turn.js CHANGED
@@ -192,6 +192,7 @@ export async function driveTurn(agent, style, usage, input) {
192
192
  message: input.prompt,
193
193
  trigger,
194
194
  ...(input.variables ? { variables: input.variables } : {}),
195
+ ...(input.files ? { files: input.files } : {}),
195
196
  ...(input.sessionPath ? { sessionPath: input.sessionPath } : {}),
196
197
  });
197
198
  const code = printOutcome(style, workflow.machine, sessionId, outcome);