@archmax-ai/harness 0.6.1 → 0.7.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.
- package/README.md +2 -2
- package/dist/assembly/compose.js +0 -1
- package/dist/assembly/compose.js.map +1 -1
- package/dist/authoring-skill/archmax-harness/references/backend-integration.md +6 -0
- package/dist/authoring-skill/archmax-harness/references/hook-and-test-scripts.md +23 -4
- package/dist/authoring-skill/archmax-harness/references/hooks-and-scripts.md +4 -1
- package/dist/authoring-skill/archmax-harness/references/workflow-schema.md +51 -21
- package/dist/authoring-skill/archmax-harness/references/workflow-yaml.md +11 -7
- package/dist/kernel/kernel.d.ts +9 -6
- package/dist/kernel/kernel.js +80 -14
- package/dist/kernel/kernel.js.map +1 -1
- package/dist/lifecycle/runner.d.ts +6 -0
- package/dist/lifecycle/runner.js +1 -0
- package/dist/lifecycle/runner.js.map +1 -1
- package/dist/machine/machine.d.ts +22 -0
- package/dist/machine/machine.js +42 -5
- package/dist/machine/machine.js.map +1 -1
- package/dist/sandbox/executor.d.ts +5 -0
- package/dist/sandbox/executor.js +17 -5
- package/dist/sandbox/executor.js.map +1 -1
- package/dist/sandbox/prelude.js +20 -7
- package/dist/sandbox/prelude.js.map +1 -1
- package/dist/sandbox/runtime.d.ts +15 -2
- package/dist/sandbox/runtime.js +180 -23
- package/dist/sandbox/runtime.js.map +1 -1
- package/dist/sandbox/tools.js +3 -0
- package/dist/sandbox/tools.js.map +1 -1
- package/dist/workflow/file-values.d.ts +8 -10
- package/dist/workflow/file-values.js +4 -5
- package/dist/workflow/file-values.js.map +1 -1
- package/dist/workflow/governance.d.ts +1 -1
- package/dist/workflow/governance.js +3 -2
- package/dist/workflow/governance.js.map +1 -1
- package/dist/workflow/middleware.js +1 -2
- package/dist/workflow/middleware.js.map +1 -1
- package/dist/workflow/parks.js +6 -2
- package/dist/workflow/parks.js.map +1 -1
- package/dist/workflow/render-prompt.js +12 -4
- package/dist/workflow/render-prompt.js.map +1 -1
- package/dist/workflow/sub-workflow.js +8 -7
- package/dist/workflow/sub-workflow.js.map +1 -1
- package/dist/workflow/tool-service.d.ts +1 -1
- package/dist/workflow/tool-service.js +7 -1
- package/dist/workflow/tool-service.js.map +1 -1
- package/dist/workflow/turn-boundary.js +22 -6
- package/dist/workflow/turn-boundary.js.map +1 -1
- package/dist/workflow/workflow-tools.js +1 -1
- package/dist/workflow/workflow-tools.js.map +1 -1
- package/package.json +1 -1
- package/skills/archmax-harness/references/backend-integration.md +6 -0
- package/skills/archmax-harness/references/hook-and-test-scripts.md +23 -4
- package/skills/archmax-harness/references/hooks-and-scripts.md +4 -1
- package/skills/archmax-harness/references/workflow-schema.md +51 -21
- package/skills/archmax-harness/references/workflow-yaml.md +11 -7
|
@@ -206,7 +206,8 @@ mounts?:
|
|
|
206
206
|
# validate ERRORS on a name the table does not mount.
|
|
207
207
|
forbid_always?: string[] # MOUNT NAMES out of reach of EVERY state, governed or
|
|
208
208
|
# not, whatever any list grants. Deny beats allow.
|
|
209
|
-
#
|
|
209
|
+
# Binds this workflow's own HOOKS too, and is
|
|
210
|
+
# inherited by every sub-workflow, naming the workflow
|
|
210
211
|
# that declared it. A NAME only — a denial is total, so
|
|
211
212
|
# there is no `access` to qualify. (A root `mounts.allow`
|
|
212
213
|
# is a load error: one mounts model.)
|
|
@@ -391,7 +392,11 @@ states:
|
|
|
391
392
|
# volatile prompt block, and filtered out of every
|
|
392
393
|
# ls/glob/grep result, the WORKSPACE ROOT LISTING
|
|
393
394
|
# included. Lifecycle HOOKS are exempt from this key
|
|
394
|
-
# (runtime authority), but not from `forbid_always
|
|
395
|
+
# (runtime authority), but not from `forbid_always`
|
|
396
|
+
# nor from the WORKFLOW's grants: a hook reaches a
|
|
397
|
+
# governed mount only if allow_always or SOME state's
|
|
398
|
+
# allow names it, in any state, and writes it only
|
|
399
|
+
# where a grant of the workflow asks `read_write`.
|
|
395
400
|
|
|
396
401
|
model?: string # MODEL ID ONLY — this state's turns run on it (and the
|
|
397
402
|
# handoff message of a park it holds). Most specific of
|
|
@@ -542,12 +547,18 @@ states:
|
|
|
542
547
|
- `requires:` / `returns:` are the run's **signature**, and both are enforced. A
|
|
543
548
|
firing that does not supply every `requires` name does not start. `returns`
|
|
544
549
|
is checked once as the run finishes, and **nothing is handed back**: a
|
|
545
|
-
sub-workflow child with a name unset **completes**, and its caller gets
|
|
546
|
-
|
|
547
|
-
sub-workflow: '<name>' was not set."`; a top-level
|
|
548
|
-
**rejected**; a typed one mistyped rejects either
|
|
549
|
-
not checked — it has not finished.
|
|
550
|
-
|
|
550
|
+
sub-workflow child with a name unset **completes**, and its caller gets
|
|
551
|
+
every declared return, the unset ones `null`, plus `note: "Not all return
|
|
552
|
+
variables were set by the sub-workflow: '<name>' was not set."`; a top-level
|
|
553
|
+
run with a name unset is **rejected**; a typed one mistyped rejects either
|
|
554
|
+
way. A run that *parks* is not checked — it has not finished. A return is
|
|
555
|
+
owed **only at the finish**: `archmax_advance` checks a state's own
|
|
556
|
+
`requires:`, never the returns, a later write replaces an unlocked earlier
|
|
557
|
+
one, and a seed of one (a name in both lists) lands **unlocked** and does not
|
|
558
|
+
overwrite a value the session already holds. So do not list a return in a
|
|
559
|
+
state's `requires:` unless that state must settle it, and do not tell the
|
|
560
|
+
agent to lock one before its value is final. `note` is reserved: a `returns`
|
|
561
|
+
list may not declare it. Want the model to try again? Check the returns in a terminal
|
|
551
562
|
`after` hook, which can `correct`. Each entry is a bare
|
|
552
563
|
run-variable name (**untyped**: any value, `null` included) or a strict object
|
|
553
564
|
`{ name, type?, description? }` naming one; the spellings mix in one list and
|
|
@@ -577,8 +588,10 @@ states:
|
|
|
577
588
|
completion and at a delegation call the runtime also requires a **file** (not a
|
|
578
589
|
folder) at the path that the session may read **on runtime authority** — the
|
|
579
590
|
rules a hook is bound by: zone rules (`checkpoints/`, `artifacts/`, `_specs/`
|
|
580
|
-
never)
|
|
581
|
-
|
|
591
|
+
never), the workflow's mount grants taken across all its states (a governed
|
|
592
|
+
mount no state is granted is out of reach), and every workflow-wide
|
|
593
|
+
`forbid_always`, inherited ones included; the state's allow list and its own
|
|
594
|
+
mount/skill grants do not narrow it. So tell the agent to
|
|
582
595
|
write the file *before* it sets a `file` return: `archmax_set_variables` refuses
|
|
583
596
|
a path with nothing there. A host hands a file in with `TurnInput.files` (CLI:
|
|
584
597
|
`archmax run … --file invoice=./invoice.pdf`), which places it under
|
|
@@ -774,7 +787,8 @@ workflow's grant, the state's own `allow` and the always-on surface alike.
|
|
|
774
787
|
**Deny beats allow, and no narrower level widens a denial.** A forbid entry may
|
|
775
788
|
name the tool `*` (every tool); `*` in an allow list is a load error. A lifecycle
|
|
776
789
|
hook is exempt from the state's `allow` **and** its `forbid` — runtime authority,
|
|
777
|
-
outside that surface both ways — but never from `forbid_always
|
|
790
|
+
outside that surface both ways — but never from `forbid_always` (the workflow's
|
|
791
|
+
own `tools.`, `skills.` and `mounts.forbid_always`, and every ancestor's).
|
|
778
792
|
|
|
779
793
|
Precedence (highest first):
|
|
780
794
|
|
|
@@ -873,7 +887,8 @@ capability workflow-wide.
|
|
|
873
887
|
Hooks are **exempt**: a `before`/`after` script reads authored data on runtime
|
|
874
888
|
authority, so a state may enable nothing and still be gated by a hook that reads
|
|
875
889
|
the very bundle the model cannot. That is the shape to reach for when a capability
|
|
876
|
-
should *enforce* something without being *usable*.
|
|
890
|
+
should *enforce* something without being *usable*. A bundle the workflow's
|
|
891
|
+
`skills.forbid_always` denies is refused to its hooks too.
|
|
877
892
|
|
|
878
893
|
**`tools.forbid` on a state denies there**, and `tools.forbid_always` at the
|
|
879
894
|
root denies everywhere. Both beat every grant. Migrating a workflow off the
|
|
@@ -1015,7 +1030,18 @@ so `AGENTS.md.bak` is not captured.
|
|
|
1015
1030
|
|
|
1016
1031
|
Hooks and rubric graders are bound by `mounts.forbid_always` and **not** by a
|
|
1017
1032
|
state's `forbid` or its enabled set: they run on runtime authority, exactly as for
|
|
1018
|
-
tools, so a `before` hook can read a mount the model in that state cannot.
|
|
1033
|
+
tools, so a `before` hook can read a mount the model in that state cannot. A hook
|
|
1034
|
+
is still held to its **workflow's** grants, taken across every state:
|
|
1035
|
+
|
|
1036
|
+
- it reads a governed mount only if `allow_always` or some state's `allow` names
|
|
1037
|
+
it, else `mount.not-allowed`. The table serves every child too, so it can hold a
|
|
1038
|
+
mount only a child grants, and the caller's hooks cannot reach that;
|
|
1039
|
+
- it writes one only where a grant of the workflow asks `access: read_write`, and an
|
|
1040
|
+
`access: read` in `allow_always` narrows any mount for it (`mount.read-only`).
|
|
1041
|
+
|
|
1042
|
+
So when a hook needs a mount no state's model should see, grant it in a state the
|
|
1043
|
+
hook's workflow has anyway, or in `allow_always` with the model's states
|
|
1044
|
+
forbidding it.
|
|
1019
1045
|
|
|
1020
1046
|
## Session variables in guards
|
|
1021
1047
|
|
|
@@ -1083,7 +1109,8 @@ scalar.
|
|
|
1083
1109
|
**Authoring rules that matter:**
|
|
1084
1110
|
|
|
1085
1111
|
- **Lock anything a guard reads.** Host seeds are locked automatically (`title`
|
|
1086
|
-
|
|
1112
|
+
and a seed of a trigger's `returns` excepted, which land unlocked); for an
|
|
1113
|
+
agent-established fact pass `lock: true` — on a return, only once it is final. An unlocked variable can be
|
|
1087
1114
|
overwritten by any later state — that rewrite is permitted, being one writer
|
|
1088
1115
|
twice, and the later value simply wins — so a guard bound to an unlocked name is
|
|
1089
1116
|
a weak guard. A lock is the only thing that makes a fact settled.
|
|
@@ -1358,7 +1385,7 @@ enrich:
|
|
|
1358
1385
|
(`unresolved-param`) and **disabled-target** refusals are blocked calls —
|
|
1359
1386
|
nothing ran, so correct the call and retry. A child whose returns are
|
|
1360
1387
|
mistyped (`invalid-return`) is a failure: it ran. One that left returns unset
|
|
1361
|
-
is not: the call answers with
|
|
1388
|
+
is not: the call answers with them `null` and a `note`.
|
|
1362
1389
|
- **A whole-argument reference keeps its type.** `{ quantity: "${{count}}" }`
|
|
1363
1390
|
seeds the child with the number `count` holds, so it satisfies an `integer`
|
|
1364
1391
|
parameter; `{ note: "order ${{order_id}}" }` is substituted as text.
|
|
@@ -1396,16 +1423,18 @@ enrich:
|
|
|
1396
1423
|
|
|
1397
1424
|
A dispatch missing a `requires` name is **refused before the child is
|
|
1398
1425
|
composed**; a child that completes without every `returns` name set
|
|
1399
|
-
**completes anyway**, and the call answers with
|
|
1400
|
-
`note` naming
|
|
1426
|
+
**completes anyway**, and the call answers with every declared return, the
|
|
1427
|
+
unset ones `null`, plus a `note` naming them — no second attempt is spent, and
|
|
1428
|
+
the caller decides
|
|
1401
1429
|
(a child that *parks* is not checked — it has not finished; a child that
|
|
1402
1430
|
raises fails the call `raised`). A typed entry is held to its type at both
|
|
1403
1431
|
ends: a mistyped argument is refused `invalid-param` before the child runs, and
|
|
1404
1432
|
a mistyped return fails the call `invalid-return`. What the child must *do* to
|
|
1405
1433
|
produce a variable belongs in the state `instructions` that set it. The names,
|
|
1406
1434
|
with type and description where declared, are rendered into the child's prompt
|
|
1407
|
-
|
|
1408
|
-
|
|
1435
|
+
in every state, so it is told what to produce before it can be failed for
|
|
1436
|
+
omitting it — and to set each once its final value is known, locking one only
|
|
1437
|
+
when it is final.
|
|
1409
1438
|
- **The call answers with the returns, by name.** A signed target answers
|
|
1410
1439
|
`{ message, returns: { enrichment_file, delayed } }`; one declaring no
|
|
1411
1440
|
`returns:` answers with the closing message alone. The message keeps its own
|
|
@@ -1416,7 +1445,7 @@ enrich:
|
|
|
1416
1445
|
- **Mocks are held to the same contract.** An `archmax_workflow_<slug>` mock for a
|
|
1417
1446
|
signed target supplies `returns:`. One that supplies a mistyped typed one
|
|
1418
1447
|
(`invalid-return`) fails the mocked dispatch, and one that omits a declared
|
|
1419
|
-
name answers like a real child that left it unset:
|
|
1448
|
+
name answers like a real child that left it unset: that name `null`, plus a
|
|
1420
1449
|
`note` — a mock stands in for the sub-run, never for its agreement.
|
|
1421
1450
|
- **No prose crosses the boundary.** A sub-run gets no instruction from its
|
|
1422
1451
|
caller — it works from its own state `instructions` (system prompt) plus the
|
|
@@ -1499,7 +1528,8 @@ triggers:
|
|
|
1499
1528
|
repeated or parallel calls never overwrite each other or the caller's files. A
|
|
1500
1529
|
return whose file is gone at completion fails the call `invalid-return`.
|
|
1501
1530
|
- **No laundering.** A `file` value must name a file the session may read on
|
|
1502
|
-
runtime authority
|
|
1531
|
+
runtime authority (its own workflow's mount grants and `forbid_always`), and a
|
|
1532
|
+
child inherits every ancestor's `forbid_always`. So a
|
|
1503
1533
|
child cannot hand back a file its caller's workflow denies: its agent's write
|
|
1504
1534
|
is refused, and a script's write is rejected at completion.
|
|
1505
1535
|
- **Instructions to write.** Tell the child to write the file *first* and then set
|
|
@@ -170,9 +170,9 @@ states:
|
|
|
170
170
|
the agent back with the reason, bounded per hook by `max_iterations`
|
|
171
171
|
(default 0 → a correct is a hard veto). A list runs in order and stops at
|
|
172
172
|
the first non-ok. Errors and missing files veto (fail-closed). Hooks run
|
|
173
|
-
on runtime authority: the state's `allow`/`forbid`/`skills` do not
|
|
174
|
-
them; `forbid_always
|
|
175
|
-
hooks.
|
|
173
|
+
on runtime authority: the state's `allow`/`forbid`/`skills`/`mounts` do not
|
|
174
|
+
bind them; `forbid_always`, safety rules and the workflow's mount grants
|
|
175
|
+
(any state's) do. Human states may not declare hooks.
|
|
176
176
|
- **Budgets and `on_error`.** `budget.maxTurns`/`timeoutMs`/`maxParks` bound
|
|
177
177
|
a state's segment. A terminal failure (hook execution error, exhausted
|
|
178
178
|
corrections, exhausted budget, exhausted parks) routes to `on_error`
|
|
@@ -188,8 +188,11 @@ states:
|
|
|
188
188
|
mistyped argument is refused `invalid-param`, and `"${{count}}"` alone
|
|
189
189
|
passes the value with its own type), its `returns` the result
|
|
190
190
|
(`{ message, returns }`; a child finishing with some unset completes, and
|
|
191
|
-
`returns` holds
|
|
192
|
-
return fails `invalid-return`).
|
|
191
|
+
`returns` holds every declared one, the unset ones `null`, plus a `note`
|
|
192
|
+
naming them; a mistyped typed return fails `invalid-return`). Returns are
|
|
193
|
+
owed only at the finish: no state needs them to be left, a later write
|
|
194
|
+
replaces an unlocked earlier one, and a seed of one lands unlocked; lock one
|
|
195
|
+
only once it is final. Each failed call is the
|
|
193
196
|
calling state's failure, recorded with its arguments and routed through
|
|
194
197
|
`on_error` when the agent finishes unless a later successful call of the
|
|
195
198
|
same workflow from the same state recovers it first. One success recovers
|
|
@@ -276,5 +279,6 @@ Closed by default; **deny beats allow, and no narrower level widens a denial.**
|
|
|
276
279
|
A state enabling no skill can run no script at all.
|
|
277
280
|
- **Scripts' `tools.*` calls** are governed per call: an `archmax_run` script
|
|
278
281
|
is bound like the model (grant every tool it calls); a hook is exempt from
|
|
279
|
-
the state's lists
|
|
280
|
-
refused call throws inside the
|
|
282
|
+
the state's lists but held to its workflow's mount grants. Neither may read
|
|
283
|
+
`workflows/**` or write a read-only mount. A refused call throws inside the
|
|
284
|
+
script.
|