@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
@@ -1,135 +0,0 @@
1
- /**
2
- * Grading rubrics: the standards a state's exit is measured against, declared
3
- * inline on the hook that applies them and dispatched by the runtime alone.
4
- *
5
- * This module is only the *vocabulary* — the verdict contract, the payload a
6
- * grader receives, the rejection wording, and the projection from a loaded spec
7
- * into a registry. There is deliberately no loader, no file format and no merge
8
- * path: a rubric is spec content, so the spec's own schema is the one thing that
9
- * has to accept it, and nothing outside assembly builds a registry.
10
- *
11
- * A rubric has no author-given name. Its identity is its **position** — the
12
- * state, the phase, and its index in that phase's hook list — which is also how
13
- * its retry budget is keyed, so two graders on one state can never share a
14
- * budget or be confused for one another in an event.
15
- */
16
- import type { BaseChatModel } from "@langchain/core/language_models/chat_models";
17
- import type { CreateDeepAgentParams } from "deepagents";
18
- import type { MachineSpec, RubricDeclaration } from "../machine/types.js";
19
- /** A grader in the Deep Agents shape, registered for the runtime's own `task` dispatch. */
20
- export type LoadedRubric = NonNullable<CreateDeepAgentParams["subagents"]>[number];
21
- /** The verdict vocabulary. `correct` asks for another iteration; `veto` blocks outright. */
22
- export type RubricVerdict = "ok" | "correct" | "veto";
23
- export interface RubricVerdictResult {
24
- verdict: RubricVerdict;
25
- reason: string;
26
- /** The rubric that produced this verdict; absent for a script hook's own verdict. */
27
- rubric?: string;
28
- }
29
- /**
30
- * The structured output a rubric with an iteration budget must return. Applied
31
- * automatically, so a grader's output is a contract rather than a prompt
32
- * convention.
33
- */
34
- export declare const RUBRIC_VERDICT_SCHEMA: {
35
- readonly type: "object";
36
- readonly properties: {
37
- readonly verdict: {
38
- readonly type: "string";
39
- readonly enum: readonly ["ok", "correct", "veto"];
40
- };
41
- readonly reason: {
42
- readonly type: "string";
43
- };
44
- };
45
- readonly required: readonly ["verdict", "reason"];
46
- };
47
- /**
48
- * One registry entry: the declaration plus the positional id the runtime
49
- * dispatches it under. The id is internal — it appears in operator-facing events
50
- * and never in a prompt — so it is built for uniqueness, not for authoring.
51
- */
52
- export interface Rubric extends RubricDeclaration {
53
- id: string;
54
- state: string;
55
- phase: "before" | "after";
56
- index: number;
57
- }
58
- /**
59
- * The id one inline rubric is registered and dispatched under. Positional
60
- * because an inline rubric has no name: reordering a phase's hooks re-keys them,
61
- * which is the same class of change as editing the spec at all (it moves the
62
- * spec hash).
63
- */
64
- export declare function rubricId(state: string, phase: "before" | "after", index: number): string;
65
- /** Whether a value is a usable verdict. Anything else has graded nothing. */
66
- export declare function isRubricVerdict(value: unknown): value is RubricVerdictResult;
67
- /**
68
- * The structured-output schema every dispatch requests: the verdict schema,
69
- * unconditionally.
70
- *
71
- * Not conditional on `max_iterations`, as it was when a grader was a subagent
72
- * that might also be a general-purpose helper. A rubric only ever grades, so a
73
- * grader that needs no retries still has to answer in the verdict vocabulary —
74
- * and without the schema its answer arrives as prose, parses to no verdict, and
75
- * fails closed on a transition the author expected it to wave through.
76
- */
77
- export declare function resolveRubricResponseFormat(_rubric: RubricDeclaration): Record<string, unknown> | undefined;
78
- /** The compact task payload a grader is handed: the request, the transcript, and where it happened. */
79
- export declare function buildRubricTaskDescription(args: Record<string, unknown>): string;
80
- /**
81
- * What an `after`-hook verdict does to an `archmax_advance` attempt.
82
- *
83
- * `reason` is `null` when the transition may proceed. The other two are decided
84
- * here, together, because they are mutually exclusive and were not: a `correct`
85
- * whose budget is already spent is `budgetExhausted` and bills nothing, while
86
- * only a `correct` that actually got its retry is `consumesIteration`. Billing
87
- * an attempt that was never granted costs the state its budget for good on
88
- * re-entry (issue #62).
89
- */
90
- export interface RubricTransitionOutcome {
91
- reason: string | null;
92
- /** A `correct` refused because the hook's `max_iterations` are already spent. */
93
- budgetExhausted: boolean;
94
- /** This block granted a retry, so it spends one of the hook's iterations. */
95
- consumesIteration: boolean;
96
- }
97
- /**
98
- * Map an `after`-hook verdict to an `archmax_advance` rejection outcome. One
99
- * implementation for every hook kind: the retry flow (bounded iterations with
100
- * remaining-attempt guidance) is identical whether the verdict came from a
101
- * rubric or a script — only the label differs (`rubric` vs `hook`).
102
- */
103
- export declare function rubricTransitionOutcome(verdict: RubricVerdictResult, opts: {
104
- maxIterations: number;
105
- iterationsUsed: number;
106
- to?: string;
107
- }): RubricTransitionOutcome;
108
- /**
109
- * The rejection reason alone, for callers that do not decide the retry budget.
110
- */
111
- export declare function rubricTransitionReason(verdict: RubricVerdictResult, opts: {
112
- maxIterations: number;
113
- iterationsUsed: number;
114
- to?: string;
115
- }): string | null;
116
- /**
117
- * The rubric registry for one machine: every inline rubric its states declare,
118
- * keyed by {@link rubricId}. Walks the spec rather than reading a root block,
119
- * because a grader lives on the hook that applies it.
120
- *
121
- * Scoped to this spec, so a delegated child is graded by its own standards; two
122
- * states declaring the same criteria produce two entries, which is the accepted
123
- * cost of a state being legible on its own.
124
- */
125
- export declare function rubricsFromSpec(spec: Pick<MachineSpec, "states">): Map<string, Rubric>;
126
- /**
127
- * Project the registry into the Deep Agents subagent shape so the framework
128
- * registers the `task` tool the runtime dispatches through. These are never
129
- * disclosed to the agent: `task` is withheld in every state and grantable by
130
- * nothing, so registering a grader here gives the graded agent no reach.
131
- *
132
- * `model` resolves the grader's own model when it declared one, else the
133
- * assembly's `rubric`-role model.
134
- */
135
- export declare function rubricsAsSubagents(registry: Map<string, Rubric>, modelFor?: (rubric: Rubric) => BaseChatModel | undefined): LoadedRubric[];
@@ -1,145 +0,0 @@
1
- import { normalizeHooks } from "../lifecycle/hook-shape.js";
2
- import { ADVANCE_TOOL } from "../machine/tool-names.js";
3
- /**
4
- * The structured output a rubric with an iteration budget must return. Applied
5
- * automatically, so a grader's output is a contract rather than a prompt
6
- * convention.
7
- */
8
- export const RUBRIC_VERDICT_SCHEMA = {
9
- type: "object",
10
- properties: {
11
- verdict: { type: "string", enum: ["ok", "correct", "veto"] },
12
- reason: { type: "string" },
13
- },
14
- required: ["verdict", "reason"],
15
- };
16
- /**
17
- * The id one inline rubric is registered and dispatched under. Positional
18
- * because an inline rubric has no name: reordering a phase's hooks re-keys them,
19
- * which is the same class of change as editing the spec at all (it moves the
20
- * spec hash).
21
- */
22
- export function rubricId(state, phase, index) {
23
- return `${state}--${phase}--${index}`;
24
- }
25
- /** Whether a value is a usable verdict. Anything else has graded nothing. */
26
- export function isRubricVerdict(value) {
27
- if (!value || typeof value !== "object")
28
- return false;
29
- const v = value;
30
- return v.verdict === "ok" || v.verdict === "correct" || v.verdict === "veto";
31
- }
32
- /**
33
- * The structured-output schema every dispatch requests: the verdict schema,
34
- * unconditionally.
35
- *
36
- * Not conditional on `max_iterations`, as it was when a grader was a subagent
37
- * that might also be a general-purpose helper. A rubric only ever grades, so a
38
- * grader that needs no retries still has to answer in the verdict vocabulary —
39
- * and without the schema its answer arrives as prose, parses to no verdict, and
40
- * fails closed on a transition the author expected it to wave through.
41
- */
42
- export function resolveRubricResponseFormat(_rubric) {
43
- return RUBRIC_VERDICT_SCHEMA;
44
- }
45
- /** The compact task payload a grader is handed: the request, the transcript, and where it happened. */
46
- export function buildRubricTaskDescription(args) {
47
- return JSON.stringify({
48
- userRequest: args.userRequest ?? null,
49
- history: args.history ?? [],
50
- state: args.state ?? null,
51
- phase: args.phase ?? null,
52
- }, null, 2);
53
- }
54
- /**
55
- * Map an `after`-hook verdict to an `archmax_advance` rejection outcome. One
56
- * implementation for every hook kind: the retry flow (bounded iterations with
57
- * remaining-attempt guidance) is identical whether the verdict came from a
58
- * rubric or a script — only the label differs (`rubric` vs `hook`).
59
- */
60
- export function rubricTransitionOutcome(verdict, opts) {
61
- const label = verdict.rubric ? "rubric" : "hook";
62
- if (verdict.verdict === "ok") {
63
- return { reason: null, budgetExhausted: false, consumesIteration: false };
64
- }
65
- if (verdict.verdict === "veto") {
66
- // A deliberate veto charges nothing: no retry was offered to bill for.
67
- return {
68
- reason: `${label} veto: ${verdict.reason}`,
69
- budgetExhausted: false,
70
- consumesIteration: false,
71
- };
72
- }
73
- const max = Math.max(0, opts.maxIterations);
74
- if (opts.iterationsUsed >= max) {
75
- return {
76
- reason: `${label} veto: reply still incomplete after ${max} attempt(s) — ${verdict.reason}`,
77
- budgetExhausted: true,
78
- consumesIteration: false,
79
- };
80
- }
81
- const remaining = max - opts.iterationsUsed;
82
- const target = opts.to ? `${ADVANCE_TOOL}({ to: "${opts.to}" })` : ADVANCE_TOOL;
83
- return {
84
- reason: `${label}: reply incomplete — ${verdict.reason}. ` +
85
- `Update your answer and call ${target} again. (${remaining} attempt(s) remaining)`,
86
- budgetExhausted: false,
87
- consumesIteration: true,
88
- };
89
- }
90
- /**
91
- * The rejection reason alone, for callers that do not decide the retry budget.
92
- */
93
- export function rubricTransitionReason(verdict, opts) {
94
- return rubricTransitionOutcome(verdict, opts).reason;
95
- }
96
- /**
97
- * The rubric registry for one machine: every inline rubric its states declare,
98
- * keyed by {@link rubricId}. Walks the spec rather than reading a root block,
99
- * because a grader lives on the hook that applies it.
100
- *
101
- * Scoped to this spec, so a delegated child is graded by its own standards; two
102
- * states declaring the same criteria produce two entries, which is the accepted
103
- * cost of a state being legible on its own.
104
- */
105
- export function rubricsFromSpec(spec) {
106
- const registry = new Map();
107
- for (const [state, declared] of Object.entries(spec.states ?? {})) {
108
- for (const phase of ["before", "after"]) {
109
- normalizeHooks(declared?.[phase]).forEach((hook, index) => {
110
- const declaration = hook.rubric;
111
- if (declaration === undefined || typeof declaration !== "object")
112
- return;
113
- const id = rubricId(state, phase, index);
114
- registry.set(id, { ...declaration, id, state, phase, index });
115
- });
116
- }
117
- }
118
- return registry;
119
- }
120
- /**
121
- * Project the registry into the Deep Agents subagent shape so the framework
122
- * registers the `task` tool the runtime dispatches through. These are never
123
- * disclosed to the agent: `task` is withheld in every state and grantable by
124
- * nothing, so registering a grader here gives the graded agent no reach.
125
- *
126
- * `model` resolves the grader's own model when it declared one, else the
127
- * assembly's `rubric`-role model.
128
- */
129
- export function rubricsAsSubagents(registry, modelFor) {
130
- return [...registry.values()].map((rubric) => {
131
- const responseFormat = resolveRubricResponseFormat(rubric);
132
- const model = modelFor?.(rubric);
133
- return {
134
- name: rubric.id,
135
- // A grader is dispatched by the runtime under its positional id, never
136
- // chosen from a menu by the agent, so the description exists only for the
137
- // framework's own tool schema — which no state is ever shown.
138
- description: `Grading rubric on '${rubric.state}' (${rubric.phase}).`,
139
- systemPrompt: rubric.instructions,
140
- ...(responseFormat !== undefined ? { responseFormat } : {}),
141
- ...(model !== undefined ? { model } : {}),
142
- };
143
- });
144
- }
145
- //# sourceMappingURL=rubrics.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"rubrics.js","sourceRoot":"","sources":["../../src/rubrics/rubrics.ts"],"names":[],"mappings":"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"}
@@ -1,22 +0,0 @@
1
- // QuickJS sandbox core: the verdict helpers a lifecycle hook answers with.
2
- //
3
- // return ok(); // proceed
4
- // return correct("why"); // the agent gets another attempt (after hooks)
5
- // return veto("why"); // block, with the reason shown to the agent
6
- //
7
- // Returning nothing is `ok`; throwing is a veto (fail-closed). Nothing else is
8
- // installed here — the hook reads its inputs from the object it is called with.
9
-
10
- globalThis.__verdict = (verdict, reason, fallback) => ({
11
- verdict,
12
- reason: reason == null || String(reason).trim() === "" ? fallback : String(reason),
13
- });
14
-
15
- globalThis.ok = (reason) => globalThis.__verdict("ok", reason, "ok");
16
- globalThis.veto = (reason) => globalThis.__verdict("veto", reason, "vetoed by hook");
17
- globalThis.correct = (reason) => globalThis.__verdict("correct", reason, "correction requested");
18
-
19
- globalThis.__isVerdict = (value) =>
20
- value != null &&
21
- typeof value === "object" &&
22
- (value.verdict === "ok" || value.verdict === "veto" || value.verdict === "correct");
@@ -1,47 +0,0 @@
1
- // Lifecycle-hook context: the contract marker, the `defineHook` authoring
2
- // alias, and the reducer that turns whatever a hook produced into a verdict.
3
- // These globals are absent from the PTC context.
4
-
5
- globalThis.SANDBOX_CONTRACT = { context: "lifecycle-hook", version: globalThis.__SANDBOX_VERSION };
6
-
7
- // `export default defineHook(fn)` and `export default async function hook(...)`
8
- // both register the hook; the executor rewrites `export default` to an
9
- // assignment of `__hookDef`, so `defineHook` is an identity that also registers.
10
- globalThis.defineHook = (fn) => {
11
- globalThis.__hookDef = fn;
12
- return fn;
13
- };
14
-
15
- // How an object that is not a verdict is named back to its author: by its keys,
16
- // never its values, so a diagnostic cannot leak what the hook was inspecting.
17
- globalThis.__hookShape = (value) => {
18
- if (Array.isArray(value)) return "an array";
19
- try {
20
- const keys = Object.keys(value);
21
- if (keys.length === 0) return "an object with no keys";
22
- const shown = keys.slice(0, 6).map((key) => `'${key}'`).join(", ");
23
- return `an object with ${keys.length > 6 ? "keys including " : "keys "}${shown}`;
24
- } catch {
25
- return "an object";
26
- }
27
- };
28
-
29
- // The verdict of a hook run. A verdict object is taken as is, a bare `false`
30
- // vetoes, and returning nothing is `ok`.
31
- //
32
- // Any *other* object fails closed. A hook's return value is its verdict and
33
- // nothing else, so an object that is not one is a verdict its author got wrong
34
- // — a misspelled `verdict`, a retired shape like `{ ok: false, reason }`. Read
35
- // as `ok` it would silently permit precisely what the hook meant to block, and
36
- // the author would have no way to notice: the run just proceeds.
37
- globalThis.__hookVerdict = (value) => {
38
- if (globalThis.__isVerdict(value)) return value;
39
- if (value === false) return globalThis.veto("precondition not met");
40
- if (value !== null && typeof value === "object") {
41
- throw new Error(
42
- `hook returned ${globalThis.__hookShape(value)}, which is not a verdict — ` +
43
- "return ok(), veto(reason), correct(reason), false, or nothing at all",
44
- );
45
- }
46
- return globalThis.ok();
47
- };
@@ -1,16 +0,0 @@
1
- import type { RunnableConfig } from "@langchain/core/runnables";
2
- import type { StructuredTool } from "@langchain/core/tools";
3
- import { type SubagentBridgeOptions } from "@langchain/quickjs";
4
- import type { WorkflowEventEmitter } from "../core/events.js";
5
- /** Recover the textual payload from whatever envelope `task()` returns. */
6
- export declare function unwrapToolEnvelope(value: unknown): unknown;
7
- /**
8
- * Bridge the QuickJS `task()` global to the Deep Agents `task` tool. When
9
- * `telemetry` is supplied, each dispatch is bracketed with
10
- * `rubric-start`/`rubric-result` lifecycle events (this path bypasses the
11
- * outer agent's tool middleware, so it must emit its own bracketing).
12
- */
13
- export declare function createSubagentBridgeDispatch(taskTool: StructuredTool, config: RunnableConfig, telemetry?: {
14
- emit: WorkflowEventEmitter;
15
- state?: string;
16
- }): SubagentBridgeOptions["dispatch"];
@@ -1,95 +0,0 @@
1
- import { BaseMessage } from "@langchain/core/messages";
2
- import { isCommand } from "@langchain/langgraph";
3
- import { SUBAGENT_RESPONSE_FORMAT_CONFIG_KEY } from "deepagents";
4
- import { validateResponseSchema } from "@langchain/quickjs";
5
- /** Recover the textual payload from whatever envelope `task()` returns. */
6
- export function unwrapToolEnvelope(value) {
7
- if (typeof value === "string")
8
- return value;
9
- if (isCommand(value)) {
10
- const messages = value.update?.messages;
11
- if (Array.isArray(messages)) {
12
- for (let i = messages.length - 1; i >= 0; i--) {
13
- const message = messages[i];
14
- if (BaseMessage.isInstance(message) && message.content != null) {
15
- return unwrapToolEnvelope(message.content);
16
- }
17
- }
18
- }
19
- return value;
20
- }
21
- if (BaseMessage.isInstance(value))
22
- return unwrapToolEnvelope(value.content);
23
- if (Array.isArray(value)) {
24
- for (let i = value.length - 1; i >= 0; i--) {
25
- const entry = value[i];
26
- if (BaseMessage.isInstance(entry))
27
- return unwrapToolEnvelope(entry.content);
28
- if (isCommand(entry)) {
29
- const inner = unwrapToolEnvelope(entry);
30
- if (inner !== entry)
31
- return inner;
32
- }
33
- }
34
- }
35
- return value;
36
- }
37
- /** Ids for bridge dispatches, which have no model-assigned tool-call id. */
38
- let bridgeDispatchSeq = 0;
39
- /**
40
- * Bridge the QuickJS `task()` global to the Deep Agents `task` tool. When
41
- * `telemetry` is supplied, each dispatch is bracketed with
42
- * `rubric-start`/`rubric-result` lifecycle events (this path bypasses the
43
- * outer agent's tool middleware, so it must emit its own bracketing).
44
- */
45
- export function createSubagentBridgeDispatch(taskTool, config, telemetry) {
46
- return async (input) => {
47
- const hasSchema = input.responseSchema != null;
48
- if (hasSchema)
49
- validateResponseSchema(input.responseSchema);
50
- const toolConfig = {
51
- ...config,
52
- configurable: {
53
- ...config.configurable,
54
- ...(hasSchema && { [SUBAGENT_RESPONSE_FORMAT_CONFIG_KEY]: input.responseSchema }),
55
- },
56
- };
57
- const dispatchId = `bridge-${++bridgeDispatchSeq}`;
58
- const state = telemetry?.state ?? "";
59
- telemetry?.emit({
60
- type: "rubric-start",
61
- state,
62
- name: input.subagentType,
63
- dispatchId,
64
- });
65
- const startedAt = Date.now();
66
- const settle = (status) => telemetry?.emit({
67
- type: "rubric-result",
68
- state,
69
- name: input.subagentType,
70
- dispatchId,
71
- status,
72
- durationMs: Date.now() - startedAt,
73
- });
74
- let raw;
75
- try {
76
- raw = await taskTool.invoke({ description: input.description, subagent_type: input.subagentType }, toolConfig);
77
- }
78
- catch (err) {
79
- settle("error");
80
- throw err;
81
- }
82
- settle("ok");
83
- const content = unwrapToolEnvelope(raw);
84
- if (hasSchema && typeof content === "string") {
85
- try {
86
- return JSON.parse(content);
87
- }
88
- catch {
89
- return content;
90
- }
91
- }
92
- return content;
93
- };
94
- }
95
- //# sourceMappingURL=bridge.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"bridge.js","sourceRoot":"","sources":["../../src/sandbox/bridge.ts"],"names":[],"mappings":"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"}
@@ -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.