@archmax-ai/harness 0.8.0 → 1.0.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 (219) hide show
  1. package/README.md +58 -14
  2. package/dist/agent.d.ts +4 -4
  3. package/dist/agent.js +4 -4
  4. package/dist/assembly/compose.d.ts +5 -24
  5. package/dist/assembly/compose.js +40 -41
  6. package/dist/assembly/compose.js.map +1 -1
  7. package/dist/assembly/delegation-registry.js +3 -14
  8. package/dist/assembly/delegation-registry.js.map +1 -1
  9. package/dist/assembly/index.d.ts +18 -15
  10. package/dist/assembly/index.js +50 -32
  11. package/dist/assembly/index.js.map +1 -1
  12. package/dist/assembly/plain.js +1 -2
  13. package/dist/assembly/plain.js.map +1 -1
  14. package/dist/authoring-skill/archmax-harness/README.md +5 -5
  15. package/dist/authoring-skill/archmax-harness/SKILL.md +72 -30
  16. package/dist/authoring-skill/archmax-harness/references/backend-integration.md +35 -23
  17. package/dist/authoring-skill/archmax-harness/references/cases.md +44 -10
  18. package/dist/authoring-skill/archmax-harness/references/{hook-and-test-scripts.md → code-state-and-test-scripts.md} +617 -313
  19. package/dist/authoring-skill/archmax-harness/references/code-states-and-scripts.md +115 -0
  20. package/dist/authoring-skill/archmax-harness/references/diagnostics.md +40 -7
  21. package/dist/authoring-skill/archmax-harness/references/wiring.md +19 -10
  22. package/dist/authoring-skill/archmax-harness/references/workflow-schema.md +416 -276
  23. package/dist/authoring-skill/archmax-harness/references/workflow-yaml.md +161 -62
  24. package/dist/cli/state-flow.d.ts +1 -1
  25. package/dist/cli/state-flow.js +18 -28
  26. package/dist/cli/state-flow.js.map +1 -1
  27. package/dist/cli/turn.d.ts +1 -1
  28. package/dist/cli/turn.js +2 -3
  29. package/dist/cli/turn.js.map +1 -1
  30. package/dist/core/clock.d.ts +26 -0
  31. package/dist/core/clock.js +64 -0
  32. package/dist/core/clock.js.map +1 -0
  33. package/dist/core/code-description.d.ts +3 -3
  34. package/dist/core/code-description.js +3 -3
  35. package/dist/core/deepagents.d.ts +5 -5
  36. package/dist/core/deepagents.js +4 -4
  37. package/dist/core/events.d.ts +23 -42
  38. package/dist/core/events.js +21 -24
  39. package/dist/core/events.js.map +1 -1
  40. package/dist/core/message-readers.d.ts +22 -2
  41. package/dist/core/message-readers.js +31 -0
  42. package/dist/core/message-readers.js.map +1 -1
  43. package/dist/core/messages.d.ts +1 -23
  44. package/dist/core/messages.js +2 -35
  45. package/dist/core/messages.js.map +1 -1
  46. package/dist/core/mounts.js +3 -3
  47. package/dist/core/platform-prompt.generated.js +1 -1
  48. package/dist/core/platform-prompt.generated.js.map +1 -1
  49. package/dist/core/session-zone.d.ts +1 -1
  50. package/dist/core/session-zone.js +1 -1
  51. package/dist/core/workspace-context.d.ts +1 -1
  52. package/dist/core/workspace.d.ts +1 -1
  53. package/dist/core/workspace.js +1 -1
  54. package/dist/core/zones.d.ts +4 -4
  55. package/dist/core/zones.js +5 -5
  56. package/dist/core/zones.js.map +1 -1
  57. package/dist/env.d.ts +9 -9
  58. package/dist/index.d.ts +3 -7
  59. package/dist/index.js +2 -4
  60. package/dist/index.js.map +1 -1
  61. package/dist/kernel/kernel.d.ts +31 -61
  62. package/dist/kernel/kernel.js +57 -114
  63. package/dist/kernel/kernel.js.map +1 -1
  64. package/dist/machine/allow.d.ts +17 -2
  65. package/dist/machine/allow.js +16 -6
  66. package/dist/machine/allow.js.map +1 -1
  67. package/dist/machine/lint-spec.js +68 -12
  68. package/dist/machine/lint-spec.js.map +1 -1
  69. package/dist/machine/machine.d.ts +39 -16
  70. package/dist/machine/machine.js +72 -49
  71. package/dist/machine/machine.js.map +1 -1
  72. package/dist/machine/spec-schema.d.ts +34 -179
  73. package/dist/machine/spec-schema.js +93 -106
  74. package/dist/machine/spec-schema.js.map +1 -1
  75. package/dist/machine/tool-names.d.ts +34 -10
  76. package/dist/machine/tool-names.js +41 -10
  77. package/dist/machine/tool-names.js.map +1 -1
  78. package/dist/machine/tool-paths.d.ts +6 -0
  79. package/dist/machine/tool-paths.js +10 -0
  80. package/dist/machine/tool-paths.js.map +1 -1
  81. package/dist/machine/types.d.ts +14 -38
  82. package/dist/machine/types.js.map +1 -1
  83. package/dist/machine/validate-spec.d.ts +1 -1
  84. package/dist/machine/variables.d.ts +2 -0
  85. package/dist/machine/variables.js.map +1 -1
  86. package/dist/public/sandbox.d.ts +62 -66
  87. package/dist/public/sandbox.js +22 -23
  88. package/dist/public/sandbox.js.map +1 -1
  89. package/dist/public/spec.d.ts +12 -19
  90. package/dist/public/spec.js +11 -19
  91. package/dist/public/spec.js.map +1 -1
  92. package/dist/runtime/contract.d.ts +11 -12
  93. package/dist/runtime/contract.js +16 -16
  94. package/dist/runtime/contract.js.map +1 -1
  95. package/dist/sandbox/assets/parts/code-state.js +17 -0
  96. package/dist/sandbox/executor.d.ts +25 -7
  97. package/dist/sandbox/executor.js +56 -47
  98. package/dist/sandbox/executor.js.map +1 -1
  99. package/dist/sandbox/imports.d.ts +10 -10
  100. package/dist/sandbox/imports.js +11 -11
  101. package/dist/sandbox/imports.js.map +1 -1
  102. package/dist/sandbox/prelude.d.ts +5 -6
  103. package/dist/sandbox/prelude.js +38 -35
  104. package/dist/sandbox/prelude.js.map +1 -1
  105. package/dist/sandbox/ptc-gateway.d.ts +19 -18
  106. package/dist/sandbox/ptc-gateway.js +26 -22
  107. package/dist/sandbox/ptc-gateway.js.map +1 -1
  108. package/dist/sessions/operations.js +4 -5
  109. package/dist/sessions/operations.js.map +1 -1
  110. package/dist/sessions/resume.d.ts +12 -7
  111. package/dist/sessions/resume.js +12 -9
  112. package/dist/sessions/resume.js.map +1 -1
  113. package/dist/sessions/summary.d.ts +1 -1
  114. package/dist/testing/assertions.js +9 -4
  115. package/dist/testing/assertions.js.map +1 -1
  116. package/dist/testing/case-document.d.ts +2 -0
  117. package/dist/testing/case-document.js.map +1 -1
  118. package/dist/testing/case-schema.d.ts +1 -1
  119. package/dist/testing/case-schema.js +17 -1
  120. package/dist/testing/case-schema.js.map +1 -1
  121. package/dist/testing/driver.d.ts +4 -0
  122. package/dist/testing/driver.js +22 -3
  123. package/dist/testing/driver.js.map +1 -1
  124. package/dist/testing/grade.js +3 -3
  125. package/dist/testing/grade.js.map +1 -1
  126. package/dist/testing/interpreter.d.ts +2 -2
  127. package/dist/testing/interpreter.js +1 -0
  128. package/dist/testing/interpreter.js.map +1 -1
  129. package/dist/testing/runner.d.ts +2 -2
  130. package/dist/validate/validate.d.ts +1 -1
  131. package/dist/validate/validate.js +39 -70
  132. package/dist/validate/validate.js.map +1 -1
  133. package/dist/workflow/automated-controls.d.ts +63 -0
  134. package/dist/workflow/automated-controls.js +158 -0
  135. package/dist/workflow/automated-controls.js.map +1 -0
  136. package/dist/workflow/automated.d.ts +112 -0
  137. package/dist/workflow/automated.js +163 -0
  138. package/dist/workflow/automated.js.map +1 -0
  139. package/dist/workflow/checkpointer.d.ts +7 -0
  140. package/dist/workflow/checkpointer.js +28 -0
  141. package/dist/workflow/checkpointer.js.map +1 -1
  142. package/dist/workflow/code-state.d.ts +46 -0
  143. package/dist/workflow/code-state.js +26 -0
  144. package/dist/workflow/code-state.js.map +1 -0
  145. package/dist/workflow/control-tools.d.ts +54 -23
  146. package/dist/workflow/control-tools.js +121 -77
  147. package/dist/workflow/control-tools.js.map +1 -1
  148. package/dist/workflow/file-values.d.ts +4 -4
  149. package/dist/workflow/file-values.js +1 -1
  150. package/dist/workflow/file-values.js.map +1 -1
  151. package/dist/workflow/governance.d.ts +13 -22
  152. package/dist/workflow/governance.js +51 -87
  153. package/dist/workflow/governance.js.map +1 -1
  154. package/dist/workflow/grader-state.d.ts +55 -0
  155. package/dist/workflow/grader-state.js +182 -0
  156. package/dist/workflow/grader-state.js.map +1 -0
  157. package/dist/workflow/history.d.ts +11 -0
  158. package/dist/workflow/history.js +64 -0
  159. package/dist/workflow/history.js.map +1 -0
  160. package/dist/workflow/middleware.d.ts +14 -17
  161. package/dist/workflow/middleware.js +106 -74
  162. package/dist/workflow/middleware.js.map +1 -1
  163. package/dist/workflow/move-events.d.ts +21 -0
  164. package/dist/workflow/move-events.js +20 -0
  165. package/dist/workflow/move-events.js.map +1 -0
  166. package/dist/workflow/parks.d.ts +9 -2
  167. package/dist/workflow/parks.js +16 -8
  168. package/dist/workflow/parks.js.map +1 -1
  169. package/dist/workflow/paths.d.ts +9 -9
  170. package/dist/workflow/paths.js +19 -19
  171. package/dist/workflow/paths.js.map +1 -1
  172. package/dist/workflow/render-prompt.d.ts +7 -5
  173. package/dist/workflow/render-prompt.js +22 -37
  174. package/dist/workflow/render-prompt.js.map +1 -1
  175. package/dist/workflow/signature-checks.d.ts +2 -2
  176. package/dist/workflow/snapshot.js +5 -29
  177. package/dist/workflow/snapshot.js.map +1 -1
  178. package/dist/workflow/state.d.ts +19 -6
  179. package/dist/workflow/state.js +24 -8
  180. package/dist/workflow/state.js.map +1 -1
  181. package/dist/workflow/sub-workflow.d.ts +3 -3
  182. package/dist/workflow/tool-service.d.ts +1 -9
  183. package/dist/workflow/tool-service.js +21 -24
  184. package/dist/workflow/tool-service.js.map +1 -1
  185. package/dist/workflow/turn-boundary.d.ts +2 -2
  186. package/dist/workflow/turn-boundary.js +10 -7
  187. package/dist/workflow/turn-boundary.js.map +1 -1
  188. package/dist/workflow/turn-runner.js +30 -2
  189. package/dist/workflow/turn-runner.js.map +1 -1
  190. package/package.json +1 -1
  191. package/skills/archmax-harness/README.md +5 -5
  192. package/skills/archmax-harness/SKILL.md +72 -30
  193. package/skills/archmax-harness/references/backend-integration.md +35 -23
  194. package/skills/archmax-harness/references/cases.md +44 -10
  195. package/skills/archmax-harness/references/{hook-and-test-scripts.md → code-state-and-test-scripts.md} +617 -313
  196. package/skills/archmax-harness/references/code-states-and-scripts.md +115 -0
  197. package/skills/archmax-harness/references/diagnostics.md +40 -7
  198. package/skills/archmax-harness/references/wiring.md +19 -10
  199. package/skills/archmax-harness/references/workflow-schema.md +416 -276
  200. package/skills/archmax-harness/references/workflow-yaml.md +161 -62
  201. package/dist/authoring-skill/archmax-harness/references/hooks-and-scripts.md +0 -88
  202. package/dist/lifecycle/hook-shape.d.ts +0 -44
  203. package/dist/lifecycle/hook-shape.js +0 -66
  204. package/dist/lifecycle/hook-shape.js.map +0 -1
  205. package/dist/lifecycle/runner.d.ts +0 -183
  206. package/dist/lifecycle/runner.js +0 -373
  207. package/dist/lifecycle/runner.js.map +0 -1
  208. package/dist/lifecycle/transcript.d.ts +0 -27
  209. package/dist/lifecycle/transcript.js +0 -43
  210. package/dist/lifecycle/transcript.js.map +0 -1
  211. package/dist/rubrics/rubrics.d.ts +0 -135
  212. package/dist/rubrics/rubrics.js +0 -145
  213. package/dist/rubrics/rubrics.js.map +0 -1
  214. package/dist/sandbox/assets/parts/core.js +0 -22
  215. package/dist/sandbox/assets/parts/lifecycle-hook.js +0 -47
  216. package/dist/sandbox/bridge.d.ts +0 -16
  217. package/dist/sandbox/bridge.js +0 -95
  218. package/dist/sandbox/bridge.js.map +0 -1
  219. package/skills/archmax-harness/references/hooks-and-scripts.md +0 -88
@@ -14,7 +14,7 @@ instructions: |- # standing direction for the whole run (warning
14
14
  Records live in skills/order-data/assets/orders.json; write artifacts under scratchpad/.
15
15
 
16
16
  Answer only from records you have read; never fabricate.
17
- runtime: { engine: archmax-harness, version: "2" }
17
+ runtime: { engine: archmax-harness, version: "3" } # 3 is the only contract; omitted = 3
18
18
  disabled: false # true = out of service: no new turns; parked runs still drain
19
19
  settings: # sandbox limits: timeoutMs, memoryLimitBytes, maxPtcCalls,
20
20
  timeoutMs: 15000 # maxResultChars, prompt_cache: { enabled, ttl }
@@ -23,8 +23,7 @@ tests: # case suite config (no tests.config.js exists)
23
23
  maxConcurrency: 1 # only 1 accepted
24
24
  caseTimeoutMs: 120000 # per-case wall clock, distinct from settings.timeoutMs
25
25
  judge: {} # required for grade:; {} = env default model, or { model, modelOptions }
26
- metadata: { canvas: {} } # host data, never read; accepted at root, state, rubric — leave as found
27
- extensions: { hooks: [] } # host-registered hook kinds; rarely authored
26
+ metadata: { canvas: {} } # host data, never read; accepted at root and on a state — leave as found
28
27
 
29
28
  tools: # tool governance, workflow level
30
29
  allow_always: # granted in EVERY state; a state's allow adds to or narrows it.
@@ -47,7 +46,7 @@ skills: # skill governance, workflow level — SLUGS, n
47
46
 
48
47
  states:
49
48
  triage: # key = slug = identity (^[a-z0-9]+(-[a-z0-9]+)*$)
50
- type: agent # agent (default) | human
49
+ type: agent # agent (default) | human | grader | code (grader/code = automated)
51
50
  title: Triage request # label for people/hosts; reaches no model call
52
51
  summary: Record the refund decision for review. # ditto: an authoring/host label, NOT in the prompt
53
52
  triggers: # a trigger is declared on the state it ENTERS; key = id
@@ -65,17 +64,8 @@ states:
65
64
  # entry types: string integer number boolean date date-time object array file
66
65
  instructions: >-
67
66
  Record the decision in scratchpad/refund.json, then archmax_advance to
68
- review; never close the case yourself.
69
- before: # gates entry: ok/veto only; a veto here rejects the run
70
- - script: hooks/check-requester.js
71
- after: # gates the archmax_advance out (or completion, when terminal)
72
- - script: hooks/check-policy.js
73
- max_iterations: 2 # how many `correct`s before a hard veto (per hook; default 0)
74
- - rubric: # LLM grader, inline; the agent never sees it
75
- instructions: |- # the only required key: criteria + verdict (ok/correct/veto + reason)
76
- Judge the tone of the last assistant message …
77
- max_iterations: 1
78
- model: gpt-4.1-mini # optional override
67
+ check-policy; never close the case yourself. If a note sends the case
68
+ back, fix what it names and advance again.
79
69
  tools:
80
70
  allow: # adds to allow_always; entry = name | { tool, args: {<arg>: [globs]} } | { tool, paths }
81
71
  - lookup_customer
@@ -87,18 +77,33 @@ states:
87
77
  allow: [refund-policy] # adds to allow_always (bundle readable + scripts runnable, no path entries)
88
78
  forbid: [order-data] # subtracts, even from allow_always ([] never denies)
89
79
  requires: [case_id] # variables that must be set before this state may be left
80
+ locks: [case_id] # variables only this state may write (change = come back here)
90
81
  model: claude-opus-5 # MODEL ID ONLY — this state's turns; beats settings.model
91
82
  budget: { maxTurns: 12, timeoutMs: 60000, maxParks: 5 } # bounds the state's segment
92
83
  on_error: closed # where a terminal failure of this segment routes
93
84
  metadata: { x: 40, y: 180 }
94
85
  transitions: # none => terminal state
95
- - to: review # slug; must exist
96
- description: The decision is recorded and needs a person's approval. # what the agent routes
86
+ - to: check-policy # slug; must exist
87
+ description: The decision is recorded in scratchpad/refund.json. # what the agent routes
97
88
  # on. Say WHEN, never where. Omit it to route on the target's
98
89
  # instructions instead (target must have some); REQUIRED on a
99
- # human state's transitions, where it is the button label.
90
+ # human state's transitions (the button label) and on every edge
91
+ # INTO a grader or code state, like this one.
100
92
  type: none # approve | reject | refine | none — semantic on human states
101
93
 
94
+ check-policy: # CODE state: the runtime runs its script on entry, NO model call
95
+ type: code
96
+ script: scripts/check-policy.js # REQUIRED on a code state, refused on any other type; resolves
97
+ # to workflows/<slug>/scripts/check-policy.js (.js|.mjs, no `..`)
98
+ summary: Re-derive the decision from the refund policy. # instructions/model/budget/evidence/
99
+ # approvers here are validate ERRORS: nothing reads them
100
+ skills: { allow: [order-data] } # the script's tools are THIS state's surface: grant here
101
+ # what it reads or calls (another state's grant never reaches it)
102
+ on_error: closed # a throw, a timeout, or finishing undecided routes here
103
+ transitions: # the script takes one: tools.archmax_advance({ to, reason })
104
+ - { to: review, description: The recorded decision matches the policy. }
105
+ - { to: triage, description: The decision contradicts the policy; send it back with the fix. }
106
+
102
107
  review: # human state: parks with a decision record; a PERSON picks the edge
103
108
  type: human
104
109
  title: Review refund
@@ -108,31 +113,64 @@ states:
108
113
  approvers: [finance@acme.com]
109
114
  evidence: [scratchpad/refund.json] # plus whatever archmax_advance attached via `evidence:`
110
115
  transitions: # required; no self-edge; one target per labeled type
111
- - { to: closed, type: approve, description: Approve and close. }
116
+ - { to: reply, type: approve, description: Approve; tell the customer. }
112
117
  - { to: triage, type: refine, description: Send back with a comment. }
113
118
 
114
- closed: # bare key = terminal state with no declarations
119
+ reply: # agent state (type omitted)
120
+ instructions: >-
121
+ Draft the customer's email in scratchpad/reply.md, then archmax_advance to
122
+ grade-reply; if a note sends it back, revise the draft as it says.
123
+ transitions:
124
+ - { to: grade-reply, description: The email is drafted in scratchpad/reply.md. }
125
+
126
+ grade-reply: # GRADER state: an isolated grader judges WORK HANDED ON (a draft,
127
+ type: grader # a report), never a live answer: a turn's reply is every text
128
+ # the agent said, a draft sent back included
129
+ instructions: |- # REQUIRED: its criteria, appended to a compiled-in grader preamble
130
+ Judge only the tone of scratchpad/reply.md.
131
+ - Friendly and professional: advance to `send-reply`.
132
+ - Curt or cold: advance back to `reply`, saying exactly what to change.
133
+ - If archmax_get_history's trail already holds two steps with kind
134
+ "grader" and to "reply", raise `reply-tone` instead of sending it back.
135
+ model: gpt-4.1-mini # optional; resolved under the `grader` model role
136
+ budget: { maxTurns: 4, timeoutMs: 60000 } # ITS OWN model calls / run time; no maxParks
137
+ on_error: closed # fails closed: an undecided grader routes here
138
+ transitions: # REQUIRED, at least one; no evidence/approvers on a grader
139
+ - { to: send-reply, description: The draft is friendly and professional. }
140
+ - { to: reply, description: The tone is off; send it back naming what to change. }
141
+
142
+ send-reply: # TERMINAL code state: the session completes when the script
143
+ type: code # returns — "approve, then end" with no further model call
144
+ script: scripts/send-reply.js
145
+ tools: { allow: [send_email] } # the host tool its script calls, granted HERE
146
+
147
+ closed: # bare key = terminal (agent) state with no declarations
115
148
  ```
116
149
 
117
150
  ## Machine rules
118
151
 
119
152
  - **Movement.** The agent moves only by `archmax_advance({ to, reason, evidence? })`
120
- — one per message, edge validated, then the leaving state's `after` hooks,
121
- the target's `before` hooks, then the target's tools unlock. A state with no
122
- transitions is terminal; the run ends when the agent finishes there. Human
123
- decisions and `on_error` are the other two movers. `archmax_reset({ reason })`
153
+ — one per message, edge and `requires` validated, then the target's tools
154
+ unlock (or, for a grader or code target, the target runs at once). A state
155
+ with no transitions is terminal; the run ends when the agent finishes there.
156
+ Human decisions, `on_error`, and grader and code states' own `archmax_advance`
157
+ are the other movers. `archmax_reset({ reason })`
124
158
  returns to the entry state (forbid it via `forbid_always` when a run must
125
159
  never restart). No fan-out: sequence states; concurrency lives in
126
160
  sub-workflow calls.
127
161
  - **Entry.** At least one state declares `triggers`; one state per trigger id;
128
162
  `manual` is the entry the CLI, a host firing and a caller all use. A
129
163
  re-invoked finished session is a **new turn in the state it ended in**, not
130
- at the entry — give a state re-entry transitions if a conversation must move
131
- on, or park instead of finishing.
164
+ at the entry (one that completed in a terminal code state opens at its
165
+ trigger's entry) — give a state re-entry transitions if a conversation must
166
+ move on, or park instead of finishing.
132
167
  - **Variables.** One flat checkpointed `name → value` store, never declared.
133
168
  Host seeds (`--variables`, `createAgent({ variables })`, a delivery) are
134
169
  **locked**; the agent uses `archmax_get_variables`/`archmax_set_variables`
135
- (`lock: true` to freeze). Reserved: `trigger` (current trigger id, always
170
+ (`lock: true` to freeze, until `archmax_reset` releases the agent's locks).
171
+ A value that must be decided in one place yet stay correctable belongs to a
172
+ state: `locks: [order_id]` lets only that state write it, so a change routes
173
+ back there. Reserved: `trigger` (current trigger id, always
136
174
  locked) and `title` (the run's one-line task label, agent-owned; a
137
175
  sub-workflow child is not asked for one). A
138
176
  `${{name}}` / `${{a.b.-1.c}}` reference works in `tools.allow` globs
@@ -151,7 +189,8 @@ states:
151
189
  judgement and any state with a big tool surface or several transitions on
152
190
  the default, since a small model that routes badly costs more in retries
153
191
  than it saves. Repeating the workflow's id on a state is a validate warning.
154
- A rubric keeps its own `model`, a sub-workflow uses its own spec's, and a
192
+ A grader state's `model` is resolved under the `grader` model role
193
+ (`modelFactory("grader", env, id)`), a sub-workflow uses its own spec's, and a
155
194
  host that passes an explicit `model` instance to `createAgent` outranks
156
195
  every declared id (it must pass `modelFactory` to honour them).
157
196
  - **Parking.** A state that needs an event or a time calls
@@ -165,9 +204,9 @@ states:
165
204
  - **Failing.** When the work cannot be completed, the agent calls
166
205
  `archmax_raise({ code, reason })` (alone in its message; any state): the
167
206
  session ends at once `failed`, with the agent's free-form `code` and
168
- `reason` as the outcome's `exit` — no `on_error` route, no hook, no
169
- `returns` check. A session that never raises is a success, so it is for
170
- failure only. Forbid it (`forbid_always`, or a state's `forbid`) where the
207
+ `reason` as the outcome's `exit` — no `on_error` route, no `returns`
208
+ check. A session that never raises is a success, so it is for failure
209
+ only. Forbid it (`forbid_always`, or a state's `forbid`) where the
171
210
  agent must not end the run itself; a child that raises fails its caller's
172
211
  call with kind `raised`.
173
212
  - **Human states** park with a record built from `instructions`, `evidence`
@@ -177,22 +216,54 @@ states:
177
216
  reply-only turn (every tool call refused) and re-parks unchanged; only
178
217
  `decide` moves the run. A
179
218
  `refine` edge delivers the reviewer's comment as correction.
180
- - **Hooks.** `before`: ok/veto (veto rejects entry; on a start state, the
181
- run; routed through `on_error` if declared). `after`: ok/correct/veto on
182
- the outgoing advance or on completion of a terminal state; `correct` sends
183
- the agent back with the reason, bounded per hook by `max_iterations`
184
- (default 0 → a correct is a hard veto). A list runs in order and stops at
185
- the first non-ok. Errors and missing files veto (fail-closed). Hooks run
186
- on runtime authority: the state's `allow`/`forbid`/`skills`/`mounts` do not
187
- bind them; `forbid_always`, safety rules and the workflow's mount grants
188
- (any state's) do. Human states may not declare hooks.
219
+ - **Grader and code states** (automated states). A **code** state runs
220
+ `script: scripts/<x>.js` in the sandbox; a **grader** state runs an isolated
221
+ grader whose criteria are the state's `instructions`. Both read the session
222
+ with `archmax_get_history` (`{ messages, trail }`: the whole transcript, a
223
+ tool result inline in its tool message's `text`, and the trail; a script
224
+ calls `JSON.parse(await tools.archmax_get_history())`). Both run on
225
+ entry — however the session got there — with **no call of the agent's model**
226
+ (a chain of code states makes none at all), and leave like every state:
227
+ `archmax_advance` along one of their transitions, whose `reason` reaches the
228
+ next state as a `[code]`/`[grader]` runtime note and a `kind: code|grader`
229
+ trail step, or `archmax_raise`. A **terminal** code state completes the
230
+ session when its script returns. Throwing, timing out, a spent grader budget,
231
+ or a non-terminal state that finishes without either call **fails closed** →
232
+ `on_error`. Each is offered exactly its own state's surface (its grants and
233
+ one control set for both types: `archmax_advance`, `archmax_raise`, the
234
+ variable tools, `archmax_get_history`), governed like the agent's calls — never
235
+ `write_todos`, `archmax_eval`, `archmax_run`, `archmax_wait`,
236
+ `archmax_reset`, even when `allow_always` lists one (a state's own
237
+ `tools.allow` naming one is an error): an automated state cannot park.
238
+ There is no iteration budget: a state that gives up after N rounds counts
239
+ them in the trail. Per type, `validate` errors on: a code state's
240
+ `instructions`/`model`/`budget`/`evidence`/`approvers`; a grader without
241
+ `instructions` or without a transition, or with `evidence`/`approvers`/
242
+ `budget.maxParks`. There are **no `before:`/`after:` hooks and no root
243
+ `extensions:`** — a leftover key is a load error naming it. Script contract:
244
+ [`code-states-and-scripts.md`](code-states-and-scripts.md).
245
+ - **Automated-state patterns.** A deterministic check **in front of** a state:
246
+ make the trigger's entry (or the edge's target) a code state that advances
247
+ to the work or to a state that declines it. A check **behind** a state: point
248
+ the state's transition at a code state that advances onward, or back with
249
+ the fix as its `reason` — the agent reads it and advances again. **Approve,
250
+ then end**: approve into a terminal code state, which costs no model call.
251
+ Judgment (tone, completeness): a grader behind the graded state with an edge
252
+ back; its `instructions` say when to raise ("after two send-backs" = two
253
+ trail steps `{ kind: grader, to: <graded state> }`). Grade work the agent
254
+ hands on (a report, a draft), not a live answer: a turn's `reply` is every
255
+ text the agent said in it, so a draft sent back has reached the person.
189
256
  - **Budgets and `on_error`.** `budget.maxTurns`/`timeoutMs`/`maxParks` bound
190
- a state's segment. A terminal failure (hook execution error, exhausted
191
- corrections, exhausted budget, exhausted parks) routes to `on_error`
192
- instead of failing the run; recoverable rejections (invalid edge, veto,
193
- in-budget correct) keep the agent in place. Declare `on_error` on states
194
- with strict `after` hooks or bounded loops. A **tool that throws** is
195
- neither: the call is answered with an error-status tool message carrying
257
+ a state's segment (on a grader: its own model calls and run time; a code
258
+ state takes no `budget`, `settings.timeoutMs` bounds its script). There is
259
+ no root `budget` (declaring one is a load error): a whole turn is bounded by
260
+ LangGraph's `recursionLimit` (400 unless the host's invoke config sets one),
261
+ and a turn that hits it — a cycle between states, say — ends the session
262
+ `failed` (`recursion-limit`). A terminal failure (exhausted budget, exhausted parks, a
263
+ grader or code state that fails) routes to `on_error` instead of failing the
264
+ run; recoverable rejections (invalid edge, unmet `requires`) keep the agent
265
+ in place. Declare `on_error` on every automated state and on bounded loops.
266
+ A **tool that throws** is neither: the call is answered with an error-status tool message carrying
196
267
  the error, the agent stays in the state and can retry or switch tools, and
197
268
  `on_error` never sees it (a park or a cancelled run still propagates).
198
269
  - **Sub-workflows are tools.** Allow `archmax_workflow_<slug>` (slug verbatim)
@@ -220,10 +291,12 @@ states:
220
291
  sub-run; fan out with parallel tool calls or `Promise.all` in a script
221
292
  (bounds: depth 3, 4 concurrent). A child's human state parks the child;
222
293
  a script's delegation cannot park and fails closed.
223
- - **Choosing a mechanism.** Deterministic work with no model → an `archmax_run`
224
- script. Delegated work that is itself a process or reused across workflows
225
- → a sub-workflow. Judging work already done → a rubric hook (never
226
- callable by the agent; `task` is disclosed nowhere and not grantable).
294
+ - **Choosing a mechanism.** Deterministic work the agent triggers → an
295
+ `archmax_run` script. Deterministic work the graph runs at a fixed point (a
296
+ screen, a policy check, a record) → a code state. Delegated work that is itself
297
+ a process or reused across workflows → a sub-workflow. Judging work already
298
+ done → a grader state. Neither automated kind is callable by the agent (`task`
299
+ is disclosed nowhere and not grantable).
227
300
  - **Prompt economy.** The static prompt + tool schemas are re-sent every
228
301
  model call. The static part carries the workflow's `title` + `instructions`
229
302
  and **no state of the graph**; a state's `instructions` and its **own**
@@ -239,14 +312,19 @@ states:
239
312
 
240
313
  Only the state it is in. Every model call is handed that state's outgoing edges
241
314
  and nothing else of the machine — no other state's slug, `title`, `summary`,
242
- hooks or transitions, and no count of the states:
315
+ script, criteria or transitions, and no count of the states:
243
316
 
244
317
  ```
245
318
  Transitions — choose one with `archmax_advance` when this state's work is done:
319
+ - to `check-policy` (code) — The decision is recorded in scratchpad/refund.json.
246
320
  - to `review` (human decision node) — The decision is recorded and needs a person's approval.
321
+ - to `grade-reply` (grader) — The email is drafted in scratchpad/reply.md.
247
322
  - to `closed` (terminal) — Nothing to refund; the case is answered.
248
323
  ```
249
324
 
325
+ A `(grader)` or `(code)` target runs on its own and may send the run straight
326
+ back with a note saying what to change.
327
+
250
328
  Two rules follow, and they are the ones authors get wrong:
251
329
 
252
330
  1. **Write the `description` for the source state, not the target.** The agent
@@ -254,12 +332,19 @@ Two rules follow, and they are the ones authors get wrong:
254
332
  `The refund is over $50, or the customer has asked twice.` Not `Go to
255
333
  refund-review.` — that tells a reader who already knows the graph something
256
334
  they cannot use, and tells this reader nothing.
257
- 2. **Routing conditions cannot live downstream.** A target's `summary` or
258
- `instructions` is never disclosed to the state routing into it. If the
259
- condition is "when the order is over 30 days old", it belongs on the edge.
335
+ 2. **Routing conditions cannot live downstream.** A target's `summary` is never
336
+ disclosed to the state routing into it, nor its `instructions` across a
337
+ described edge. If the condition is "when the order is over 30 days old", it
338
+ belongs on the edge.
260
339
 
261
- A missing or blank `description` is a **load error**. There is no fallback, and
262
- no way to see more of the graph.
340
+ An **undescribed** edge (no `description`, or a blank one) routes on its target's
341
+ `instructions` instead, quoted under the edge's line as what the agent will do
342
+ once there: leave one undescribed only when those instructions already say when
343
+ it applies. It is a **load error** where the target has no instructions, on a
344
+ human state's transitions (the description is the button label), and into a
345
+ grader or code state (a grader's instructions are criteria the work is never
346
+ shown; a code state has none). A code state's own edges may go undescribed: its
347
+ script routes. There is no other way to see more of the graph.
263
348
 
264
349
  ## Governance
265
350
 
@@ -276,8 +361,20 @@ Closed by default; **deny beats allow, and no narrower level widens a denial.**
276
361
  `essentialTools`. Any other tool needs an `allow`/`allow_always` entry. A
277
362
  state entry naming a granted tool **narrows** it there, and one naming a
278
363
  default tool the list omits grants it there. `task` is ungrantable (error).
364
+ - **In a grader or code state** the surface is what the state is granted (the
365
+ workflow-wide grant included), minus `write_todos`, `archmax_eval`,
366
+ `archmax_run`, `archmax_wait` and `archmax_reset` even when `allow_always` lists
367
+ them (naming one in the state's
368
+ own `tools.allow` is an error), plus one control set for both types:
369
+ `archmax_advance`, `archmax_raise`, `archmax_get_variables`,
370
+ `archmax_set_variables` and `archmax_get_history` — never `archmax_wait` or
371
+ `archmax_reset`.
279
372
  - **Entries**: bare name; `{ tool, args: { <arg>: ["glob", …] } }` (matches
280
- if any glob matches; `${{var}}` allowed); `{ tool, paths: [...] }`
373
+ if any glob matches; `${{var}}` allowed). An argument the tool declares as a
374
+ path (else `file_path`) is canonicalized first; any other argument (a URL, an
375
+ address, an email) is matched **as written**, and a denial also catches its
376
+ path form. `""` matches only an empty value. `*` never crosses `/` (`**` does).
377
+ `{ tool, paths: [...] }`
281
378
  (guards every path argument the tool declares — all must match to grant,
282
379
  any matching denies). `"*"` as the tool is legal only in a
283
380
  forbid list. Globs match dot-segments (`secrets/**` covers `secrets/.env`).
@@ -293,8 +390,10 @@ Closed by default; **deny beats allow, and no narrower level widens a denial.**
293
390
  in the prompt). `allow` adds, `forbid` subtracts, `allow: []` denies
294
391
  nothing. A `tools.allow` entry may still narrow *within* an enabled bundle.
295
392
  A state enabling no skill can run no script at all.
296
- - **Scripts' `tools.*` calls** are governed per call: an `archmax_run` script
297
- is bound like the model (grant every tool it calls); a hook is exempt from
298
- the state's lists but held to its workflow's mount grants. Neither may read
299
- `workflows/**` or write a read-only mount. A refused call throws inside the
300
- script.
393
+ - **Scripts' `tools.*` calls** are governed per call against the state they
394
+ run in: an `archmax_run` script is bound like the model (grant every tool it
395
+ calls in the agent's state); a code state's script is bound by **its own**
396
+ state's grants (`tools`, `skills`, `mounts`) — there is no runtime authority.
397
+ `tools` holds exactly that state's surface: anything else is `undefined`.
398
+ Neither may read `workflows/**` or write a read-only mount. A refused call
399
+ rejects inside the script.
@@ -1,88 +0,0 @@
1
- # Hook scripts and `archmax_run` scripts — contracts
2
-
3
- Load this when writing a `workflows/<slug>/hooks/*.js` gate or a
4
- `skills/<cap>/scripts/*.js` source. Worked examples and the sandbox details:
5
- [`hook-and-test-scripts.md`](hook-and-test-scripts.md) Part 1.
6
-
7
- ## Hook script contract
8
-
9
- Default-export function; its return value is the verdict. Verdict helpers are
10
- globals (typed import optional: `import { ok, veto, correct } from "@archmax-ai/harness/sandbox";`,
11
- placed below the JSDoc; no other import is allowed).
12
-
13
- ```js
14
- /**
15
- * Requester gate — the request must name a requester the order records know.
16
- *
17
- * Reads the first user message, extracts the first email address, loads
18
- * skills/order-data/assets/orders.json through the bridge and matches the
19
- * address against every record's `email`, case-insensitively.
20
- *
21
- * Vetoes when the file cannot be parsed, no address is present, or none
22
- * matches — each with the reason. Otherwise ok.
23
- */
24
- export default async function hook({ state, phase, trigger, variables, messages, tools, from, to, reason }) {
25
- let orders;
26
- try { orders = JSON.parse(await tools.readFile({ file_path: "skills/order-data/assets/orders.json" })); }
27
- catch { return veto("Could not load skills/order-data/assets/orders.json."); }
28
- const text = messages.find((m) => m.role === "user")?.text ?? "";
29
- const email = text.match(/[\w.+-]+@[\w.-]+\.\w{2,}/)?.[0];
30
- if (!email) return veto("Include your email address so we can look up your account.");
31
- if (!orders.some((o) => o.email?.toLowerCase() === email.toLowerCase())) return veto(`"${email}" is not in the order database.`);
32
- return ok();
33
- }
34
- ```
35
-
36
- | Input | Meaning |
37
- | --- | --- |
38
- | `state`, `phase` | state slug; `"before"` or `"after"` |
39
- | `trigger` | trigger id string (payload is in `variables`) |
40
- | `variables` | read-only `name → value` map incl. `trigger`; structured values whole |
41
- | `messages` | last 24 messages, newest last, `{ role, text, toolCalls? }`; roles `user`/`assistant`/`tool`/`system`/`runtime` (a runtime note; match `role === "runtime"`, never a `[bracket]`) |
42
- | `from`, `to`, `reason` | `after` only: the attempted transition and the agent's reason |
43
- | `tools` | async camelCased bridge: `tools.readFile`, `tools.writeFile`, `tools.archmaxWorkflowEnrichOrder(...)`; no control tools; a hook's lists every tool on the bridge, not only the state's |
44
-
45
- | Return | Effect |
46
- | --- | --- |
47
- | `ok()`, nothing, `true`/number/string | proceed |
48
- | `veto(reason)` | block; the reason is shown to the agent — make it actionable |
49
- | `correct(reason)` | `after` only: retry with the reason, within `max_iterations` |
50
- | `false` | veto ("precondition not met") |
51
- | any other object, a throw | veto with keys/error named — never silently ok |
52
-
53
- `console.log` goes to the trail. A file with no default export uses its
54
- completion value as the verdict. Parse inputs defensively; turn a failure that
55
- should not block into an explicit `ok()`.
56
-
57
- ## `archmax_run` script contract
58
-
59
- `skills/<cap>/scripts/<x>.js`: plain script, top-level `await`, `tools.*`,
60
- `console.log`; the **last expression** is the tool result. Input is the global
61
- `args`: the arguments the model passed plus `args.variables` (read-only snapshot).
62
- No `archmax_advance`, `archmax_set_variables` or `task`. Fan-out shape:
63
-
64
- ```js
65
- /** One sub-run per requested order, all in flight at once; returns [{ order_id, ...returns }]. */
66
- const orders = args.variables?.orders_to_enrich ?? [];
67
- await Promise.all(orders.map(async (o) => {
68
- const answer = await tools.archmaxWorkflowEnrichOrder({ order_id: o.order_id });
69
- return { order_id: o.order_id, ...JSON.parse(answer).returns };
70
- }));
71
- ```
72
-
73
- The calling state must allow every tool the script calls (here
74
- `archmax_workflow_enrich-order`). A script's `tools` lists exactly the calling
75
- state's tools, re-scoped at every evaluation (so after an advance the same REPL
76
- lists the next state's); a tool the state does not offer is unlisted, and
77
- calling it by name is refused with governance's reason. The listing is
78
- camelCased, but a tool's own name reaches the same function
79
- (`tools["archmax_workflow_enrich-order"]`, `tools.read_file`); a hook's `tools`
80
- takes the camelCased names alone.
81
-
82
- **Return into a variable.** A script's result reaches the model as one tool
83
- message and no further — it is not written to the variable store, and a script
84
- cannot write there itself. Return structured data and name the variable in the
85
- calling state's `requires:`; the model then records it with
86
- `archmax_set_variables`, which is what makes it survive the state, guard a
87
- `tools.allow` glob, and be quotable downstream as `${{name}}` instead of retyped.
88
- A result worth computing is worth naming.
@@ -1,44 +0,0 @@
1
- /**
2
- * Readers for the shape of one authored hook: a tagged object whose single key
3
- * names its kind (`script`, `rubric`, or a custom kind an executor is
4
- * registered for), optionally beside the reserved `max_iterations` sidecar.
5
- */
6
- import type { Hook, HookSpec } from "../machine/types.js";
7
- /** Reserved sidecar keys ignored by hook kind detection. */
8
- export declare const HOOK_SIDECAR_KEYS: ReadonlySet<string>;
9
- /** Normalize a `before`/`after` field into an ordered list of tagged hooks. */
10
- export declare function normalizeHooks(spec: HookSpec | undefined): Hook[];
11
- /**
12
- * The kind of a tagged hook — its single key other than the sidecars — or
13
- * `undefined` for a malformed hook, which callers treat as an error
14
- * (fail-closed veto / validation error).
15
- */
16
- export declare function hookKind(hook: Hook): string | undefined;
17
- /** The target value of a tagged hook (the script path, rubric name, …). */
18
- export declare function hookValue(hook: Hook): string | undefined;
19
- /**
20
- * The hook-level `max_iterations` sidecar — the bounded grade-and-retry budget
21
- * for an `after` hook of any kind — or `undefined` when absent or not a
22
- * non-negative number. It wins over the named rubric's own `max_iterations`,
23
- * because the sidecar describes *this* state's retry loop.
24
- */
25
- export declare function hookMaxIterations(hook: Hook): number | undefined;
26
- /**
27
- * Short, human-readable label for a hook, for operator surfaces (events, the CLI
28
- * state flow). `{ script }` renders as the bare path; a `{ rubric }` renders as
29
- * `rubric#<index>`, because an inline grader has no name and its position is
30
- * what distinguishes it from the next one in the same phase; every other kind
31
- * renders as `<kind>:<value>`.
32
- */
33
- export declare function afterHookLabel(hook: Hook, index?: number): string;
34
- /**
35
- * The key one hook's grade-and-retry budget is counted under. Per hook, not per
36
- * state: `max_iterations` is declared on a hook, so two `after` hooks on one
37
- * state have independent budgets and neither can reset the other's count.
38
- *
39
- * Keyed by **position** rather than by label, so the identity does not move when
40
- * a script is renamed, and so two inline rubrics — which have no names at all —
41
- * are always distinguishable. Reordering a phase's hooks re-keys them, which is
42
- * the same class of edit as any other spec change (it moves the spec hash).
43
- */
44
- export declare function iterationKey(state: string, phase: "before" | "after", index: number): string;
@@ -1,66 +0,0 @@
1
- /** Reserved sidecar keys ignored by hook kind detection. */
2
- export const HOOK_SIDECAR_KEYS = new Set(["max_iterations"]);
3
- /** Normalize a `before`/`after` field into an ordered list of tagged hooks. */
4
- export function normalizeHooks(spec) {
5
- if (spec == null)
6
- return [];
7
- return Array.isArray(spec) ? spec : [spec];
8
- }
9
- /**
10
- * The kind of a tagged hook — its single key other than the sidecars — or
11
- * `undefined` for a malformed hook, which callers treat as an error
12
- * (fail-closed veto / validation error).
13
- */
14
- export function hookKind(hook) {
15
- if (!hook || typeof hook !== "object" || Array.isArray(hook))
16
- return undefined;
17
- const keys = Object.keys(hook).filter((key) => !HOOK_SIDECAR_KEYS.has(key));
18
- return keys.length === 1 ? keys[0] : undefined;
19
- }
20
- /** The target value of a tagged hook (the script path, rubric name, …). */
21
- export function hookValue(hook) {
22
- const kind = hookKind(hook);
23
- return kind ? hook[kind] : undefined;
24
- }
25
- /**
26
- * The hook-level `max_iterations` sidecar — the bounded grade-and-retry budget
27
- * for an `after` hook of any kind — or `undefined` when absent or not a
28
- * non-negative number. It wins over the named rubric's own `max_iterations`,
29
- * because the sidecar describes *this* state's retry loop.
30
- */
31
- export function hookMaxIterations(hook) {
32
- if (!hook || typeof hook !== "object" || Array.isArray(hook))
33
- return undefined;
34
- const value = hook.max_iterations;
35
- return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : undefined;
36
- }
37
- /**
38
- * Short, human-readable label for a hook, for operator surfaces (events, the CLI
39
- * state flow). `{ script }` renders as the bare path; a `{ rubric }` renders as
40
- * `rubric#<index>`, because an inline grader has no name and its position is
41
- * what distinguishes it from the next one in the same phase; every other kind
42
- * renders as `<kind>:<value>`.
43
- */
44
- export function afterHookLabel(hook, index = 0) {
45
- const kind = hookKind(hook);
46
- if (kind === undefined)
47
- return "hook";
48
- if (kind === "rubric")
49
- return `rubric#${index}`;
50
- const value = hook[kind];
51
- return kind === "script" ? value : `${kind}:${value}`;
52
- }
53
- /**
54
- * The key one hook's grade-and-retry budget is counted under. Per hook, not per
55
- * state: `max_iterations` is declared on a hook, so two `after` hooks on one
56
- * state have independent budgets and neither can reset the other's count.
57
- *
58
- * Keyed by **position** rather than by label, so the identity does not move when
59
- * a script is renamed, and so two inline rubrics — which have no names at all —
60
- * are always distinguishable. Reordering a phase's hooks re-keys them, which is
61
- * the same class of edit as any other spec change (it moves the spec hash).
62
- */
63
- export function iterationKey(state, phase, index) {
64
- return `${state}::${phase}::${index}`;
65
- }
66
- //# sourceMappingURL=hook-shape.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"hook-shape.js","sourceRoot":"","sources":["../../src/lifecycle/hook-shape.ts"],"names":[],"mappings":"AAOA,4DAA4D;AAC5D,MAAM,CAAC,MAAM,iBAAiB,GAAwB,IAAI,GAAG,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC;AAElF,+EAA+E;AAC/E,MAAM,UAAU,cAAc,CAAC,IAA0B;IACvD,IAAI,IAAI,IAAI,IAAI;QAAE,OAAO,EAAE,CAAC;IAC5B,OAAO,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AAC7C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CAAC,IAAU;IACjC,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;QAAE,OAAO,SAAS,CAAC;IAC/E,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,iBAAiB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5E,OAAO,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AACjD,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,SAAS,CAAC,IAAU;IAClC,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC5B,OAAO,IAAI,CAAC,CAAC,CAAE,IAA+B,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AACnE,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAU;IAC1C,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;QAAE,OAAO,SAAS,CAAC;IAC/E,MAAM,KAAK,GAAI,IAAgC,CAAC,cAAc,CAAC;IAC/D,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AAC/F,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,IAAU,EAAE,KAAK,GAAG,CAAC;IAClD,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC5B,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC;IACtC,IAAI,IAAI,KAAK,QAAQ;QAAE,OAAO,UAAU,KAAK,EAAE,CAAC;IAChD,MAAM,KAAK,GAAI,IAA+B,CAAC,IAAI,CAAC,CAAC;IACrD,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,KAAK,EAAE,CAAC;AACxD,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,YAAY,CAAC,KAAa,EAAE,KAAyB,EAAE,KAAa;IAClF,OAAO,GAAG,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE,CAAC;AACxC,CAAC"}