@archmax-ai/harness 1.1.0 → 2.0.1

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 (71) hide show
  1. package/README.md +167 -170
  2. package/dist/agent.d.ts +2 -2
  3. package/dist/agent.js +2 -2
  4. package/dist/assembly/compose.js +2 -2
  5. package/dist/assembly/compose.js.map +1 -1
  6. package/dist/authoring-skill/archmax-harness/README.md +13 -15
  7. package/dist/authoring-skill/archmax-harness/SKILL.md +174 -264
  8. package/dist/authoring-skill/archmax-harness/references/backend-integration.md +244 -776
  9. package/dist/authoring-skill/archmax-harness/references/cases.md +178 -53
  10. package/dist/authoring-skill/archmax-harness/references/code-states-and-scripts.md +211 -100
  11. package/dist/authoring-skill/archmax-harness/references/diagnostics.md +57 -78
  12. package/dist/authoring-skill/archmax-harness/references/workflow-schema.md +613 -2006
  13. package/dist/core/deepagents.d.ts +1 -2
  14. package/dist/core/deepagents.js +1 -2
  15. package/dist/core/deepagents.js.map +1 -1
  16. package/dist/kernel/kernel.d.ts +3 -2
  17. package/dist/kernel/kernel.js +8 -4
  18. package/dist/kernel/kernel.js.map +1 -1
  19. package/dist/machine/lint-spec.js +6 -16
  20. package/dist/machine/lint-spec.js.map +1 -1
  21. package/dist/machine/machine.d.ts +8 -10
  22. package/dist/machine/machine.js +19 -13
  23. package/dist/machine/machine.js.map +1 -1
  24. package/dist/machine/spec-schema.d.ts +1 -4
  25. package/dist/machine/spec-schema.js +84 -47
  26. package/dist/machine/spec-schema.js.map +1 -1
  27. package/dist/machine/tool-names.d.ts +24 -34
  28. package/dist/machine/tool-names.js +43 -63
  29. package/dist/machine/tool-names.js.map +1 -1
  30. package/dist/machine/types.d.ts +11 -10
  31. package/dist/machine/types.js.map +1 -1
  32. package/dist/public/spec.d.ts +5 -5
  33. package/dist/public/spec.js +5 -5
  34. package/dist/public/spec.js.map +1 -1
  35. package/dist/validate/validate.js +3 -3
  36. package/dist/validate/validate.js.map +1 -1
  37. package/dist/workflow/automated.js +6 -1
  38. package/dist/workflow/automated.js.map +1 -1
  39. package/dist/workflow/control-tools.js +0 -2
  40. package/dist/workflow/control-tools.js.map +1 -1
  41. package/dist/workflow/grader-state.d.ts +2 -2
  42. package/dist/workflow/grader-state.js +5 -15
  43. package/dist/workflow/grader-state.js.map +1 -1
  44. package/dist/workflow/middleware.js +2 -26
  45. package/dist/workflow/middleware.js.map +1 -1
  46. package/dist/workflow/on-error.js +0 -1
  47. package/dist/workflow/on-error.js.map +1 -1
  48. package/dist/workflow/parks.js +0 -1
  49. package/dist/workflow/parks.js.map +1 -1
  50. package/dist/workflow/render-prompt.d.ts +4 -5
  51. package/dist/workflow/render-prompt.js +24 -27
  52. package/dist/workflow/render-prompt.js.map +1 -1
  53. package/dist/workflow/state.d.ts +0 -9
  54. package/dist/workflow/state.js +0 -3
  55. package/dist/workflow/state.js.map +1 -1
  56. package/dist/workflow/turn-boundary.js +0 -1
  57. package/dist/workflow/turn-boundary.js.map +1 -1
  58. package/package.json +1 -2
  59. package/skills/archmax-harness/README.md +13 -15
  60. package/skills/archmax-harness/SKILL.md +174 -264
  61. package/skills/archmax-harness/references/backend-integration.md +244 -776
  62. package/skills/archmax-harness/references/cases.md +178 -53
  63. package/skills/archmax-harness/references/code-states-and-scripts.md +211 -100
  64. package/skills/archmax-harness/references/diagnostics.md +57 -78
  65. package/skills/archmax-harness/references/workflow-schema.md +613 -2006
  66. package/dist/authoring-skill/archmax-harness/references/code-state-and-test-scripts.md +0 -1424
  67. package/dist/authoring-skill/archmax-harness/references/wiring.md +0 -119
  68. package/dist/authoring-skill/archmax-harness/references/workflow-yaml.md +0 -402
  69. package/skills/archmax-harness/references/code-state-and-test-scripts.md +0 -1424
  70. package/skills/archmax-harness/references/wiring.md +0 -119
  71. package/skills/archmax-harness/references/workflow-yaml.md +0 -402
@@ -6,9 +6,9 @@ description: >-
6
6
  workflow.yaml with states, transitions, grader and code states, tool and skill
7
7
  governance, scripts, cases, or skill bundles), OR wiring the
8
8
  @archmax-ai/harness npm package into a backend service — assembling an agent with
9
- createAgent, running a workflow, resuming human-in-the-loop states, or
9
+ createAgent, sending turns, resuming human-in-the-loop states, or
10
10
  streaming the event stream / session artifacts so a frontend can visualize a
11
- run. Trigger this skill for phrases like "design a workflow", "author a
11
+ session. Trigger this skill for phrases like "design a workflow", "author a
12
12
  workflow.yaml", "add a state/transition/check", "archmax validate fails", "run
13
13
  an agent workflow from my worker", or "integrate @archmax-ai/harness" even when the
14
14
  runtime is not named explicitly.
@@ -16,289 +16,199 @@ description: >-
16
16
 
17
17
  # Building with @archmax-ai/harness
18
18
 
19
- The archmax harness is a thin, governed runtime over
20
- [LangChain Deep Agents](https://docs.langchain.com/oss/javascript/deepagents/overview):
21
- one Deep Agent per workflow, moved by a declarative state machine
22
- (`workflow.yaml`). It holds no use-case logic — a **workspace** supplies it.
23
- Runtime contract: `runtime: { engine: archmax-harness, version: "3" }` in every spec
24
- (omitted resolves to `3`; `1` and `2` are refused).
19
+ The archmax harness is a thin, governed layer over
20
+ [LangChain Deep Agents](https://docs.langchain.com/oss/javascript/deepagents/overview).
21
+ Each workflow runs as one Deep Agent, moved through a state machine you declare in
22
+ `workflow.yaml`. The harness holds no use-case logic: a **workspace** supplies it.
23
+ Every spec targets runtime contract `3` (`runtime: { engine: archmax-harness, version: "3" }`,
24
+ or omit the block).
25
25
 
26
- **Read by task, not by curiosity.** This file holds the procedure, the
27
- workspace layout and the commands. Load exactly the short reference your next
28
- file needs, once, and nothing else:
26
+ ## Load one reference per task
27
+
28
+ This file is the procedure, the workspace layout and the commands. Before you write
29
+ a file, load the one reference it needs:
29
30
 
30
31
  | You are about to… | Load |
31
32
  | --- | --- |
32
- | write or edit `workflow.yaml` | [`references/workflow-yaml.md`](references/workflow-yaml.md) — every key, machine rules, governance |
33
- | write a script — a code state's `workflows/<slug>/scripts/*.js` or a skill's `scripts/*.js` (`archmax_run`) | [`references/code-states-and-scripts.md`](references/code-states-and-scripts.md); sequence the skill case with the *Script playbook* below |
33
+ | write or edit `workflow.yaml` | [`references/workflow-schema.md`](references/workflow-schema.md) |
34
+ | write a code state's script, a grader state, or a skill bundle's `archmax_run` script | [`references/code-states-and-scripts.md`](references/code-states-and-scripts.md) |
34
35
  | write or fix a case (`tests/*.test.yaml`) | [`references/cases.md`](references/cases.md) |
35
- | fix what `archmax validate` / `archmax test` reported | [`references/diagnostics.md`](references/diagnostics.md) |
36
- | embed the package in a service | [`references/wiring.md`](references/wiring.md) |
37
-
38
- The long references — `workflow-schema.md`, `code-state-and-test-scripts.md`,
39
- `backend-integration.md` — are exhaustive; open a **section** of one only when
40
- the short reference says so or a field's exact semantics are in doubt. Do
41
- **not** read the SDK source, do not `ls`/`glob` a workspace to discover its
42
- layout (it is fixed, below), and do not re-read a file already in context.
43
- Naming note: this authoring skill is not a workspace's `skills/<slug>/` bundle;
44
- they share a file format and nothing else.
45
-
46
- ---
47
-
48
- ## Authoring
49
-
50
- ### Procedure
51
-
52
- **Build a workflow.** Design the whole file set first, write each file once,
53
- then verify. Do not write a file, validate, and discover the next file.
54
-
55
- 1. **Sketch the graph**: states (kebab-case slugs), the start state carrying
56
- `triggers: { manual: }` (plus any host trigger ids that enter there),
57
- terminal states (no `transitions`), the edges between them — and for each
58
- edge, the *condition* under which it is taken. That condition is the edge's
59
- `description`, which is what the agent knows about where the edge leads. Leave
60
- an edge undescribed only when the target's `instructions` already say when it
61
- applies: the agent is then shown them instead (never on a human state's
62
- transitions, whose description is the button label, and never on an edge
63
- into a grader, whose instructions are criteria the work is never shown, or
64
- into a code state, which has none; a code state's own edges may go
65
- undescribed, since its script routes). **Checks are states too**: sketch
66
- each deterministic check as a code state and each judgment (tone,
67
- completeness) as a grader state, with its edges — onward, back to the work
68
- it checks, and where it gives up (see *Checks are states* below). If something outside the session calls the workflow (another
69
- workflow, a host's MCP tool or form), give its trigger a
70
- `description` for the caller and a `requires`/`returns` signature, typing an
71
- entry (`{ name, type, description }`; `string` `integer` `number` `boolean`
72
- `date` `date-time` `object` `array` `file`) where the caller must build or read the
73
- value, and adding **rules** where the value has a shape the type does not say
74
- (`format: email`, `pattern`, `maxLength`, `enum`, `minimum`/`maximum`,
75
- `minItems`/`maxItems`, `accept`/`maxSize` on a file). The runtime holds typed
76
- entries and their rules at start, at `archmax_set_variables` and at completion
77
- ([`references/workflow-schema.md`](references/workflow-schema.md)).
78
- Decide how the work can **fail**, too: the agent ends a session it cannot
79
- complete with `archmax_raise({ code, reason })`, always on and only for
80
- failure (a session that never raises is a success). Where a host branches
81
- on why, name the codes in the `instructions` of the states that can hit
82
- them; where a person must always be reached instead, forbid the tool in
83
- that state.
84
- 2. **Decide the file set** from the sketch: `workflow.yaml` always; one
85
- `scripts/<check>.js` per code state (a grader needs no file: its criteria
86
- are its `instructions`); cases — one happy path per branch, one per path a
87
- check declines or sends back, one `decide:` per human state, one `raised:`
88
- per failure a host branches on; a
89
- `skills/<capability>/` bundle only for data, an `archmax_run` script, or
90
- guidance two or more states share identically; `AGENTS.md` only for a
91
- workspace-wide persona.
92
- 3. **Write `workflow.yaml`** from the skeleton in [`references/workflow-yaml.md`](references/workflow-yaml.md),
93
- keeping its `tools.allow_always` list of the twelve default tools: a declared
94
- list replaces them, so drop only a tool this workflow must not have. Each state's behaviour
95
- goes inline in its `instructions`; run-wide rules once in the top-level
96
- `instructions`; nothing about the machine itself (the platform prompt and
97
- the disclosed edges already say it, and prose is billed on every call), and
98
- nothing about the date: every model call opens with the current date and time
99
- in UTC (rounded down to ten minutes, with the host's zone named), so date
100
- arithmetic ("due in 30 days") needs no authored `today`.
101
- Never describe another state in a state's `instructions` or in an edge's
102
- `description`: the agent is shown the active state's edges and nothing else
103
- of the graph, so a routing condition parked in the *target's* `summary` or
104
- `instructions` is invisible to the state that has to route on it. Name
105
- a model (`settings.model`, or `model:` on one state) only where the work
106
- differs in kind — a small model on mechanical states, the default on
107
- drafting, judgement and heavy-routing ones.
108
- 4. **Write code-state scripts, grader criteria, cases** — description first (a
109
- script's JSDoc, a grader's give-up rule, a case's `title` + `description`),
110
- then the body, and never leave the two disagreeing. Before writing a case, settle what to mock ([`references/cases.md`](references/cases.md)).
111
- 5. **Verify**: `archmax validate <slug>` → fix every error (and every warning
112
- you can) → `archmax test <slug>`. Never call a workflow done without a clean
36
+ | fix what `archmax validate` or `archmax test` reported | [`references/diagnostics.md`](references/diagnostics.md) |
37
+ | embed the harness in a service | [`references/backend-integration.md`](references/backend-integration.md) |
38
+
39
+ Read a long reference by section. Do not read the SDK source, do not list a workspace
40
+ to learn its layout (it is fixed, below), and do not reread a file already in context.
41
+
42
+ Two workspaces in the [archmax harness repository](https://github.com/archmax-ai/harness)
43
+ show the result:
44
+
45
+ - [`examples/refund/`](https://github.com/archmax-ai/harness/tree/main/examples/refund) is
46
+ the minimal SDK example: four states (an agent, a code state, a grader, a terminal
47
+ agent), two host tools, and a short program that runs it with `createAgent`.
48
+ - [`examples/customer-support/`](https://github.com/archmax-ai/harness/tree/main/examples/customer-support)
49
+ is the full reference workspace for the CLI: triggers, a human state, a
50
+ sub-workflow, skill bundles and a suite of cases.
51
+
52
+ ## Build a workflow
53
+
54
+ Design the whole file set first, write each file once, then verify.
55
+
56
+ 1. **Sketch the graph.** Name the states (kebab-case slugs). Give the entry state
57
+ `triggers: { manual: }`, plus any host trigger that enters there. A state with
58
+ no transitions is terminal. For every transition, write the condition under which
59
+ it is taken: that is its `description`. It is all the agent learns about the
60
+ transition, so say *when* to take it, never *where* it goes. The one exception: an
61
+ agent state's single edge into another agent state needs none, since the agent
62
+ takes it once the state's instructions are done. Leave it out; never write
63
+ "Proceed".
64
+ 2. **Put each check on the graph.** A deterministic check is a code state; a
65
+ judgment (tone, completeness) is a grader state. Give each one a transition
66
+ onward, one back to the work it checks, and an `on_error`. The patterns are in
67
+ *Checks are states* below.
68
+ 3. **Decide how the work fails.** The agent ends a session it cannot complete with
69
+ `archmax_raise({ code, reason })`. Where a host branches on the reason, name the
70
+ codes in the `instructions` of the states that can hit them. Where a person must
71
+ always be reached instead, forbid the tool in that state.
72
+ 4. **Sign the entry if something calls it.** When another workflow, an MCP tool or a
73
+ form starts the workflow, give its trigger a `description` for the caller and a
74
+ `requires`/`returns` signature. Type an entry where the caller must build or read
75
+ the value, and add rules (`format: email`, `pattern`, `maxLength`, `enum`,
76
+ `minimum`/`maximum`) where the value has a shape its type does not say.
77
+ 5. **Decide the file set.** Always `workflow.yaml`. One `scripts/<check>.js` per code
78
+ state (a grader needs no file: its criteria are its `instructions`). Cases: one
79
+ per branch, one per path a check declines or sends back, one `decide:` per human
80
+ state, one `raised:` per failure a host branches on. A `skills/<slug>/` bundle
81
+ only for data, an `archmax_run` script, or guidance several states share.
82
+ `AGENTS.md` only for a workspace-wide persona.
83
+ 6. **Write `workflow.yaml`** from the skeleton in the schema reference. Keep its
84
+ `tools.allow_always` list of the twelve default tools: a declared list replaces
85
+ them, so drop only what this workflow must not have. Put each state's behaviour
86
+ in its own `instructions`, rules for the whole session in the top-level
87
+ `instructions`, and nothing about the machine itself: the platform prompt and the
88
+ rendered transitions already say it, and every word is billed on every call.
89
+ 7. **Write scripts, grader criteria and cases**, description first: a script's JSDoc
90
+ header, a grader's give-up rule, a case's `title` and `description`. Then the
91
+ body. Keep the two in agreement.
92
+ 8. **Verify.** Run `archmax validate <slug>`, fix every error and every warning you
93
+ can, then `archmax test <slug>`. A workflow is not done without a clean
113
94
  `validate`.
114
95
 
115
- **Fix a workflow.** Diagnose from the tool, not by reading everything.
116
-
117
- 1. Run `archmax validate <slug>` (offline, instant). Every diagnostic names
118
- the file, the field path and the fix; map it with the
119
- [`references/diagnostics.md`](references/diagnostics.md).
120
- 2. Read **only** the files the diagnostics name. Edit once. Re-validate.
121
- 3. When clean, `archmax test <slug> [filter]`. Read the failing case's verdict
122
- line: a **structural** miss (`reachedState`, `parked`, `raised`,
123
- `succeeded`, `trail`) is a routing or governance defect — fix the routing state's
124
- `instructions`, the transition `description`s, or the `tools`/`skills`
125
- grants; a **content** miss (`reply`, `calledTool`, `grade`) is an
126
- `instructions` defect in the state that answered; a decline the reply
127
- quotes, or a send-back the agent keeps failing, is a code or grader state
128
- speaking — fix what it names (or the check, when it is wrong). Change the
129
- case only when it asserts something the spec never promised.
130
- 4. A `grade` miss is the one non-deterministic assertion: re-run that case
131
- once before calling it a regression. Re-run with `--verbose` for raw
132
- events only when the verdict line is not enough.
133
-
134
- Budget: one validate, one edit pass, one validate, one test. If you are on
135
- your fourth read of a file, you are guessing — reread the relevant reference
136
- instead.
137
-
138
- **Shapes come from tools, not from research.** Before naming any field of a
139
- tool's result or a trigger's payload — in `instructions`, a `${{…}}` guard, a
140
- code-state script — ask the host: a platform embedding this runtime typically exposes
141
- describe-style tools (a tool's input and output schema, a trigger's payload
142
- schema and sample) and a way to sample or invoke once with a narrow input. Call
143
- those first; fall back to a recorded session's variables (`archmax sessions <id>`)
144
- only when no such tool exists. Reading more files never reveals what a live
145
- system returns.
146
-
147
- ### Script playbook (a skill's `scripts/<x>.js`)
148
-
149
- Deterministic work the model triggers with `archmax_run`. In order:
150
-
151
- 1. **Shapes first.** Trigger payload and tool I/O from the host's describe/sample
152
- tools; the variables a run actually carries from `archmax sessions <id>`.
153
- Guessing a field name here costs a whole run (above).
154
- 2. **Write it.** `skills/<cap>/scripts/<x>.js`: JSDoc, then the body. Input is the
155
- global `args` — `args.<param>` from the model plus `args.variables`, a read-only
156
- snapshot — and the **last expression** is the result. Contract:
157
- [`references/code-states-and-scripts.md`](references/code-states-and-scripts.md).
158
- 3. **Land the result in a variable.** Return structured data, and name the variable
159
- in the calling state's `requires:`. A script may not call
160
- `archmax_set_variables`, so `requires` is what makes the model record the return;
161
- unrecorded, the result lives in one tool message and is gone.
162
- 4. **Announce it in the skill.** The `SKILL.md` `description` says *when* to run it;
163
- the body says the script's path, its arguments, and the variable its result
164
- lands in. A script nothing points at is never reached.
165
- 5. **Grant it.** The calling state allows `{ tool: archmax_run, paths:
166
- ["skills/<cap>/scripts/**"] }` plus every tool the script itself calls. Then
167
- `archmax validate`.
168
-
169
- ### Reference a variable, never retype it
170
-
171
- `${{name}}` / `${{a.b.-1.c}}` resolves against the run's variables in a
172
- `tools.allow` glob **and inside any text argument the model writes** — mid-string,
173
- repeatable, matched literally. The transcript keeps the reference and only the tool
174
- sees the value, so a stored value costs its tokens once instead of on every later
175
- model call. Step 3 is what puts a value there to reference.
176
-
177
- A state that must emit something already stored is told to interpolate it:
178
-
179
- ```yaml
180
- instructions: >-
181
- Send the reply with gmail__send. Quote the customer's message by writing
182
- ${{inbound.text}} in the body rather than retyping it.
183
- ```
184
-
185
- Exact — a retyped copy truncates and drifts, a reference cannot — and it agrees by
186
- construction with a guard on the same variable. Not available in scripts, which
187
- read `args.variables` (a code state's script: `variables`); a grader's own tool
188
- arguments get it like the agent's. To write the characters literally: `$${{name}}`.
189
-
190
- ### Checks are states (grader and code states)
191
-
192
- A check is a state on the graph, never a slot inside one. A `type: code` state
193
- runs `script: scripts/<x>.js` and a `type: grader` state runs an isolated grader
194
- whose criteria are its `instructions`; both run on entry with **no call of the
195
- agent's model**, are offered only **their own state's** tools (grant there what
196
- the check reads; never `write_todos`, `archmax_eval`, `archmax_run`, `archmax_wait`
197
- or `archmax_reset`, even when `tools.allow_always` lists them), and leave like every state:
198
- `archmax_advance({ to, reason })` — the `reason` is the note the next state
199
- reads — or `archmax_raise({ code, reason })`. Finishing without either fails
200
- closed through `on_error`, so give every automated state an `on_error`. Both
201
- read the **whole session** the same way, with `archmax_get_history` →
202
- `{ messages, trail }` (a script: `JSON.parse(await tools.archmax_get_history())`);
203
- a tool result is inline in its tool message's `text`. Every edge into one needs
204
- a `description`. Put a grader on work the agent hands on (a report, a record),
205
- not on a live answer: everything the agent says in a turn is that turn's reply,
206
- a draft sent back included. Contract:
207
- [`references/code-states-and-scripts.md`](references/code-states-and-scripts.md).
208
-
209
- | Want | Shape |
96
+ Two rules authors get wrong:
97
+
98
+ - **Never describe another state.** The agent sees the active state and its
99
+ transitions, nothing else of the graph. A routing condition written into the
100
+ target's `instructions` or `summary` never reaches the state that routes on it.
101
+ - **Shapes come from tools, not guesses.** Before naming a field of a tool's result
102
+ or a trigger's payload (in `instructions`, a `${{…}}` guard or a script), ask the
103
+ host for it: a platform embedding the harness typically offers describe tools and a
104
+ way to sample a call. Without them, read a recorded session's variables with
105
+ `archmax sessions <id>`.
106
+
107
+ ## Fix a workflow
108
+
109
+ Diagnose from the tools, not by reading everything.
110
+
111
+ 1. Run `archmax validate <slug>`. It runs offline, and every diagnostic names the
112
+ file, the field and the fix; [`references/diagnostics.md`](references/diagnostics.md)
113
+ maps each one.
114
+ 2. Read only the files the diagnostics name. Edit once. Validate again.
115
+ 3. When it is clean, run `archmax test <slug> [filter]` and read the failing case's
116
+ verdict line:
117
+ - A **structural** miss (`reachedState`, `parked`, `raised`, `succeeded`, `trail`)
118
+ is a routing or governance defect: fix the routing state's `instructions`, the
119
+ transition `description`s, or the `tools`/`skills` grants.
120
+ - A **content** miss (`reply`, `calledTool`, `grade`) is an `instructions` defect
121
+ in the state that answered.
122
+ - A decline the reply quotes, or a send-back the agent keeps failing, is a code or
123
+ grader state speaking: fix what it names, or the check when it is wrong.
124
+ - Change the case only when it asserts something the spec never promised.
125
+ 4. `grade` is the one non-deterministic assertion: run a failing case once more
126
+ before you call it a regression. Add `--verbose` for raw events only when the
127
+ verdict line is not enough.
128
+
129
+ Budget one validate, one edit pass, one validate and one test. On your fourth read of
130
+ a file you are guessing: reread the reference instead.
131
+
132
+ ## Checks are states
133
+
134
+ A check is a state on the graph, never a slot inside one. A grader or code state runs
135
+ on entry with no call of the agent's model, reaches only its own state's tools, and
136
+ leaves like every state: with `archmax_advance({ to, reason })`, whose `reason` is the
137
+ note the next state reads, or with `archmax_raise`. Finishing without either fails
138
+ through `on_error`.
139
+
140
+ | You want | Shape |
210
141
  | --- | --- |
211
- | A deterministic check **in front of** a state | The trigger's entry (or the edge's target) is a code state that advances to the work, or to a state that declines it |
212
- | A check **behind** a state | The state's edge points at a code state with an edge onward and one **back**; a send-back's `reason` names the fix |
213
- | **Approve, then end** | Approve into a **terminal code state**: its script records the result and the session completes, no model call; the session's next message opens at its trigger's entry state |
214
- | Judgment with a bounded loop | A grader behind the graded state, edges onward and back; its `instructions` say "raise after N send-backs", counted as trail steps `{ kind: grader, to: <graded state> }` |
142
+ | A deterministic check **in front of** a state | The trigger's entry (or the transition's target) is a code state that advances to the work, or to a state that declines it |
143
+ | A check **behind** a state | The state's transition points at a code state with a transition onward and one **back**; a send-back's `reason` names the fix |
144
+ | **Approve, then end** | Approve into a terminal code state: its script records the result and the session completes with no further model call |
145
+ | Judgment, with a bounded loop | A grader behind the state it grades, with transitions onward and back; its `instructions` say "raise after two send-backs", counted on the trail |
215
146
 
216
- The checked state's `instructions` say that advancing into the check is what
217
- hands the work in, and to fix the work when a note sends it back. There is
218
- no `before:`/`after:`, no `rubric:`, no `max_iterations`: a leftover key fails to
219
- load.
147
+ Grade work the agent hands on (a report, a recorded decision), not a live answer:
148
+ everything the agent says in a turn is that turn's reply, a draft sent back included.
149
+ The graded state's `instructions` say that advancing into the check hands the work in,
150
+ and to fix the work when a note sends it back.
220
151
 
221
- ### Workspace layout (complete — nothing else exists)
152
+ ## Workspace layout
153
+
154
+ This is the whole layout. Nothing else is read.
222
155
 
223
156
  ```
224
- <workspace root>/
225
- AGENTS.md # optional persona; prompt layer 1
226
- workflows/<slug>/ # AUTHORING PLANE — runtime reads it, the agent CANNOT
227
- workflow.yaml # the machine (required, canonical)
228
- WORKFLOW.md # optional plain-markdown addendum, NO frontmatter
229
- scripts/<check>.js # code-state scripts (`type: code`), run by the runtime
230
- tests/<case>.test.yaml # one case per file; fixtures beside them (`from:`)
231
- skills/<capability>/ # AGENT PLANE — mounted read-only, enabled per state by slug
232
- SKILL.md # frontmatter (name = directory slug, description) + body
233
- scripts/<script>.js # archmax_run sources, run by the agent
234
- assets/<file> # read-only inputs
235
- references/<topic>.md # optional deeper material
236
- .env # ARCHMAX_* model config (never mounted)
237
- sessions/<sessionId>/ # the run; the agent's workspace ROOT (never authored)
238
- scratchpad/ # agent-visible `scratchpad/…`: the session's always-writable
239
- # area (a host-wired writable mount is another place to write)
240
- large_tool_results/ conversation_history/ # runtime offload, agent reads only
241
- checkpoints/ artifacts/ # runtime-internal
157
+ <workspace>/
158
+ AGENTS.md # optional persona, the first prompt layer
159
+ workflows/<slug>/ # read by the runtime only; the agent cannot read it
160
+ workflow.yaml # the machine (required)
161
+ WORKFLOW.md # optional Markdown appended to the prompt, no frontmatter
162
+ scripts/<check>.js # code-state scripts
163
+ tests/<case>.test.yaml # one case per file; fixtures beside them
164
+ skills/<slug>/ # a skill bundle, mounted read-only, enabled by slug
165
+ SKILL.md # frontmatter (name = directory slug, description) and body
166
+ scripts/<script>.js # archmax_run scripts, run by the agent
167
+ assets/<file> # read-only data
168
+ .env # ARCHMAX_* model configuration (never mounted)
169
+ sessions/<id>/ # one session; the agent's workspace root (never authored)
170
+ scratchpad/ # the one zone every state may write
242
171
  ```
243
172
 
244
- Rules that follow:
245
-
246
- - **The agent cannot read `workflows/**`** — its spec, code-state scripts,
247
- grader criteria and cases have no route in its workspace. Never point `instructions`,
248
- `evidence` or a case `workspace:` at one (`validate` errors). Text the agent
249
- needs goes in a skill bundle.
250
- - **Placement**: a code-state script is the check, a runtime script is the
251
- tool; they never share a file. Both directories are named `scripts/`, on
252
- different planes.
253
-
254
- | Script | Runs on | Lives at | Wired as |
255
- | --- | --- | --- | --- |
256
- | Code-state script | the runtime, when its `type: code` state is entered; governed by **that state's** grants | `workflows/<slug>/scripts/<x>.js` | `type: code` + `script: scripts/<x>.js` (workflow-relative, confined to `scripts/`) |
257
- | Runtime script | the model's authority, via `archmax_run` | `skills/<cap>/scripts/<x>.js` | enabling the skill; narrow with `{ tool: archmax_run, paths: ["skills/<cap>/scripts/**"] }` |
258
-
259
- `archmax_run` is confined to skill bundles by a non-overridable rule
260
- (`script.skill-only`): a script in `scratchpad/` or `workflows/` is unrunnable.
261
- - **Paths have no leading slash** (`skills/order-data/assets/orders.json`,
262
- `scratchpad/refund.json`); never author a `run/` prefix. `scratchpad/` is
263
- writable in every state that is granted `write_file`, whatever its entry
264
- narrows, so an allow entry inside it narrows nothing (warning); to govern *where* a result lands, name
265
- a non-reserved run path (`reports/*.json`) and allow it.
266
- - **Guidance has three homes, one per rule**: every workflow → `AGENTS.md`;
267
- the whole run → top-level `instructions` (`|-` literal block, since `>-`
268
- folds paragraphs together); one state's turn → that state's `instructions`
269
- (`>-` is fine). Pasting a paragraph into a second state means hoist it.
270
- Never one `skills/<state>/` per state.
271
- - **Every `.js` you author opens with a JSDoc block**: title line, blank
272
- line, then what it reads, the sequence of checks, and where it sends the
273
- session in each case (code state: each `archmax_advance` target and why, each
274
- raise) or what it computes and returns (`archmax_run` script). Admin UIs show this
275
- instead of the code. No `@specification` tag, no sidecar key.
276
-
277
- ### Verify (CLI)
173
+ - **The agent cannot read `workflows/**`.** Its spec, scripts, grader criteria and
174
+ cases are out of reach, so never point `instructions`, `evidence` or a case's
175
+ `workspace:` at them. Text the agent needs goes in a skill bundle.
176
+ - **Two kinds of script, two places.** A code-state script lives in
177
+ `workflows/<slug>/scripts/` and the runtime runs it when its state is entered. An
178
+ `archmax_run` script lives in `skills/<slug>/scripts/` and the agent runs it. They
179
+ never share a file.
180
+ - **Paths have no leading slash**: `skills/order-data/assets/orders.json`,
181
+ `scratchpad/refund.json`. Write session files under `scratchpad/`.
182
+ - **Guidance has three homes.** Every workflow: `AGENTS.md`. The whole session: the
183
+ top-level `instructions`, as a literal block (`|-`). One state: its
184
+ `instructions`. A paragraph pasted into a second state belongs one level up. Never
185
+ write one skill bundle per state.
186
+ - **Every `.js` file opens with a JSDoc block**: a title line, a blank line, then what
187
+ it reads, what it checks or computes, and each outcome (for a code state, every
188
+ `archmax_advance` target and why, and every raise). Admin UIs show this block
189
+ instead of the code.
190
+
191
+ ## Commands
278
192
 
279
193
  ```bash
280
194
  archmax validate [workflow] [--json] # offline; run after every structural edit
281
195
  archmax test [workflow] [filter] [--json] # cases; filter = case-id substring
282
196
  archmax run <workflow> "<prompt>" [--session <id>] [--trigger <id>] [--variables '<json>'] [--file <var>=<path>]...
283
- archmax sessions [session] [--json] # list, or one session's variables (value + locked)
284
- archmax decide <session> --to <state> [--comment "…"] # resume a human state
285
- archmax reply <session> "<message>" # message a parked run; it stays parked
286
- archmax deliver <session> --trigger <id> [--variables '<json>'] # resume an archmax_wait
197
+ archmax sessions [session] [--json] # list sessions, or one session's variables
198
+ archmax decide <session> --to <state> [--comment "…"] # decide a human state
199
+ archmax reply <session> "<message>" # message a parked session; it stays parked
200
+ archmax deliver <session> --trigger <id> [--variables '<json>'] # deliver to an archmax_wait park
287
201
  ```
288
202
 
289
- `<workflow>` may be omitted when the workspace has one. Global `--root <dir>`
290
- (cwd default; `.env` loads from it), `--verbose` for raw events. Results on
291
- stdout, narration on stderr. Exit 0 done/parked, 1 failure (a raise included:
292
- `✖ failed` with the agent's code), 2 usage. Dev from
293
- the SDK checkout: `npm run dev -- <command…>`.
294
-
295
- ---
296
-
297
-
298
- ---
203
+ `<workflow>` may be omitted when the workspace has one. `--root <dir>` sets the
204
+ workspace (default: the current directory; `.env` loads from it), and `--verbose`
205
+ prints raw events. Results go to stdout and narration to stderr. Exit codes: 0 done
206
+ or parked, 1 failure (a raise prints `✖ failed` with its code), 2 usage error. The CLI
207
+ runs workflows that need no host tools; one that needs host tools, like
208
+ `examples/refund/`, runs from code.
299
209
 
300
210
  ## Done when
301
211
 
302
- - Authoring: `archmax validate` clean, `archmax test` passing, every `.js`
303
- opens with its JSDoc, every case has `title` + `description`.
304
- - Wiring: the snippet compiles against the installed package's exports.
212
+ - Authoring: `archmax validate` is clean, `archmax test` passes, every `.js` file opens
213
+ with its JSDoc block, and every case has a `title` and a `description`.
214
+ - Wiring: the program compiles against the installed package's exports.