@archmax-ai/harness 1.0.0 → 1.1.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 (48) hide show
  1. package/README.md +11 -6
  2. package/dist/assembly/compose.js +3 -1
  3. package/dist/assembly/compose.js.map +1 -1
  4. package/dist/authoring-skill/archmax-harness/SKILL.md +5 -2
  5. package/dist/authoring-skill/archmax-harness/references/backend-integration.md +25 -13
  6. package/dist/authoring-skill/archmax-harness/references/workflow-schema.md +36 -6
  7. package/dist/authoring-skill/archmax-harness/references/workflow-yaml.md +3 -0
  8. package/dist/core/attachments.d.ts +2 -0
  9. package/dist/core/attachments.js +2 -1
  10. package/dist/core/attachments.js.map +1 -1
  11. package/dist/core/file-operations.d.ts +6 -0
  12. package/dist/core/file-operations.js +29 -0
  13. package/dist/core/file-operations.js.map +1 -1
  14. package/dist/index.d.ts +5 -1
  15. package/dist/index.js +4 -0
  16. package/dist/index.js.map +1 -1
  17. package/dist/machine/signature-pattern.d.ts +24 -0
  18. package/dist/machine/signature-pattern.js +67 -0
  19. package/dist/machine/signature-pattern.js.map +1 -0
  20. package/dist/machine/signature.d.ts +137 -35
  21. package/dist/machine/signature.js +476 -25
  22. package/dist/machine/signature.js.map +1 -1
  23. package/dist/machine/spec-schema.d.ts +202 -1
  24. package/dist/machine/spec-schema.js +143 -4
  25. package/dist/machine/spec-schema.js.map +1 -1
  26. package/dist/public/spec.d.ts +5 -1
  27. package/dist/public/spec.js +4 -0
  28. package/dist/public/spec.js.map +1 -1
  29. package/dist/workflow/control-tools.js +3 -1
  30. package/dist/workflow/control-tools.js.map +1 -1
  31. package/dist/workflow/file-values.d.ts +4 -1
  32. package/dist/workflow/file-values.js +2 -0
  33. package/dist/workflow/file-values.js.map +1 -1
  34. package/dist/workflow/middleware.d.ts +2 -0
  35. package/dist/workflow/middleware.js +1 -0
  36. package/dist/workflow/middleware.js.map +1 -1
  37. package/dist/workflow/render-prompt.js +7 -2
  38. package/dist/workflow/render-prompt.js.map +1 -1
  39. package/dist/workflow/signature-checks.d.ts +8 -3
  40. package/dist/workflow/signature-checks.js +17 -4
  41. package/dist/workflow/signature-checks.js.map +1 -1
  42. package/dist/workflow/sub-workflow.js +4 -1
  43. package/dist/workflow/sub-workflow.js.map +1 -1
  44. package/package.json +3 -2
  45. package/skills/archmax-harness/SKILL.md +5 -2
  46. package/skills/archmax-harness/references/backend-integration.md +25 -13
  47. package/skills/archmax-harness/references/workflow-schema.md +36 -6
  48. package/skills/archmax-harness/references/workflow-yaml.md +3 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signature-pattern.js","sourceRoot":"","sources":["../../src/machine/signature-pattern.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAE9B,sEAAsE;AACtE,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAKvC,0GAA0G;AAC1G,MAAM,KAAK,GAAG,IAAI,GAAG,EAA2B,CAAC;AACjD,MAAM,WAAW,GAAG,IAAI,CAAC;AAEzB;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,OAAe;IAC5C,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAClC,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAC1B,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAClC,IAAI,KAAK,CAAC,IAAI,IAAI,WAAW;QAAE,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,KAAM,CAAC,CAAC;IACxE,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAC7B,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,OAAO,CAAC,OAAe;IAC9B,IAAI,OAAO,CAAC,MAAM,GAAG,kBAAkB,EAAE,CAAC;QACxC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,OAAO,CAAC,MAAM,uCAAuC,kBAAkB,EAAE,EAAE,CAAC;IAClH,CAAC;IACD,IAAI,GAAU,CAAC;IACf,IAAI,CAAC;QACH,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAG,GAAa,CAAC,OAAO,EAAE,CAAC;IACtD,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;AACxD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,sBAAsB,CAAC,OAAe;IACpD,IAAI,CAAC;QACH,IAAI,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QACzB,OAAO,SAAS,CAAC;IACnB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,2CAA4C,GAAa,CAAC,OAAO,EAAE,CAAC;IAC7E,CAAC;AACH,CAAC"}
@@ -1,13 +1,3 @@
1
- /**
2
- * A trigger's signature, typed: what each `requires`/`returns` entry declares,
3
- * the one mapping from a signature to JSON Schema, and the one conformance rule.
4
- *
5
- * Pure and browser-safe — it depends on nothing but the spec's types — so a host
6
- * builds an MCP tool schema, a start form or request validation from exactly the
7
- * mapping and rule the runtime enforces. Every runtime check (the turn boundary,
8
- * `archmax_set_variables`, the completion check, a delegation and its settle)
9
- * decides by {@link signatureValueIssues}; nothing else judges a value's type.
10
- */
11
1
  import type { MachineSpec, SignatureEntryDeclaration } from "./types.js";
12
2
  /**
13
3
  * The types a signature entry may declare: JSON Schema's own type words, plus its
@@ -19,12 +9,61 @@ import type { MachineSpec, SignatureEntryDeclaration } from "./types.js";
19
9
  export declare const SIGNATURE_TYPES: readonly ["string", "integer", "number", "boolean", "date", "date-time", "object", "array", "file"];
20
10
  /** One of {@link SIGNATURE_TYPES}. */
21
11
  export type SignatureType = (typeof SIGNATURE_TYPES)[number];
12
+ /** The formats a `string` entry's `format` rule names. */
13
+ export declare const SIGNATURE_FORMATS: readonly ["email", "url", "phone"];
14
+ /** One of {@link SIGNATURE_FORMATS}. */
15
+ export type SignatureFormat = (typeof SIGNATURE_FORMATS)[number];
16
+ /**
17
+ * The kinds of text a `string` entry's `content` rule declares. A declaration
18
+ * only: carried and mapped, never checked — what a kind permits is a host's call.
19
+ */
20
+ export declare const SIGNATURE_CONTENTS: readonly ["text", "markdown", "html"];
21
+ /** One of {@link SIGNATURE_CONTENTS}. */
22
+ export type SignatureContent = (typeof SIGNATURE_CONTENTS)[number];
23
+ /**
24
+ * The rules an entry declares on its value beyond its type, each spelled as the
25
+ * JSON Schema keyword it maps to where one exists, and each only on the types
26
+ * {@link RULE_TYPES} allows.
27
+ */
28
+ export interface SignatureRules {
29
+ /** `string`: an email address, an http(s) URL, or an E.164 phone number. */
30
+ format?: SignatureFormat;
31
+ /** `string`: a regular expression (RE2 syntax) found anywhere in the value. */
32
+ pattern?: string;
33
+ /** `string`: the fewest code points. */
34
+ minLength?: number;
35
+ /** `string`: the most code points. */
36
+ maxLength?: number;
37
+ /** `string`: the values allowed, compared exactly. */
38
+ enum?: string[];
39
+ /** `string`: what kind of text the value holds. Declared, not checked. */
40
+ content?: SignatureContent;
41
+ /** `integer`/`number`: a number; `date`: `YYYY-MM-DD` or `today`; `date-time`: an RFC 3339 instant or `now`. Inclusive. */
42
+ minimum?: number | string;
43
+ /** As {@link SignatureRules.minimum}, from above. */
44
+ maximum?: number | string;
45
+ /** `array`: the fewest entries. */
46
+ minItems?: number;
47
+ /** `array`: the most entries. */
48
+ maxItems?: number;
49
+ /** `file`: the extensions allowed, each with its leading `.`, compared case-insensitively. */
50
+ accept?: string[];
51
+ /** `file`: the largest file, in bytes. Checked where a `file` value crosses a boundary. */
52
+ maxSize?: number;
53
+ }
54
+ /** Which rule an issue is about. */
55
+ export type SignatureRuleName = keyof SignatureRules;
56
+ /** The types each rule applies to. A rule on any other type, or on an untyped entry, is a load error. */
57
+ export declare const RULE_TYPES: Readonly<Record<SignatureRuleName, readonly SignatureType[]>>;
58
+ /** Every rule name, in the order an entry's rules are read and listed. */
59
+ export declare const SIGNATURE_RULE_NAMES: SignatureRuleName[];
22
60
  /**
23
61
  * One signature entry, normalized: the variable's name, and optionally what kind
24
- * of value it holds and what it is for. An entry without `type` is untyped — any
25
- * value satisfies it, `null` included.
62
+ * of value it holds, the rules that value must meet, and what it is for. An
63
+ * entry without `type` is untyped — any value satisfies it, `null` included —
64
+ * and declares no rules.
26
65
  */
27
- export interface SignatureEntry {
66
+ export interface SignatureEntry extends SignatureRules {
28
67
  name: string;
29
68
  type?: SignatureType;
30
69
  description?: string;
@@ -40,9 +79,10 @@ export interface TriggerSignature {
40
79
  }
41
80
  /**
42
81
  * One reason a value map does not satisfy a signature: a name that is not set,
43
- * or a value that does not conform to its entry's type. `found` is the JSON kind
44
- * of what arrived; `message` is a phrase naming the variable, worded for whoever
45
- * has to correct it, which each site wraps in its own refusal.
82
+ * or a value that does not conform to its entry's type or breaks one of its
83
+ * rules (`rule` names which). `found` is the JSON kind of what arrived;
84
+ * `message` is a phrase naming the variable, worded for whoever has to correct
85
+ * it, which each site wraps in its own refusal.
46
86
  */
47
87
  export type SignatureValueIssue = {
48
88
  kind: "missing";
@@ -53,19 +93,46 @@ export type SignatureValueIssue = {
53
93
  name: string;
54
94
  type: SignatureType;
55
95
  found: SignatureValueKind;
96
+ rule?: SignatureRuleName;
56
97
  message: string;
57
98
  };
99
+ /** How {@link signatureValueIssues} reads its clock. */
100
+ export interface SignatureValueOptions {
101
+ /** The instant `now` is, and whose UTC date `today` is; the current time when omitted. */
102
+ now?: Date;
103
+ }
58
104
  /** The JSON kind of a value, as an issue reports what arrived. */
59
105
  export type SignatureValueKind = "string" | "number" | "boolean" | "null" | "object" | "array";
60
106
  /**
61
- * A `requires`/`returns` list as `{ name, type?, description? }` entries, in
62
- * declaration order: a bare name and `{ name }` are the same untyped entry.
63
- * Total — a list the schema refused (a scalar, an entry naming nothing) yields
64
- * what it can read, so `validate` can read a spec whose shape failed.
107
+ * A `requires`/`returns` list as `{ name, type?, description?, …rules }`
108
+ * entries, in declaration order: a bare name and `{ name }` are the same
109
+ * untyped entry. A rule is carried as written, except `maxSize`, read as bytes;
110
+ * `today` and `now` stay symbolic. Total — a list the schema refused (a scalar,
111
+ * an entry naming nothing, a rule its type does not take) yields what it can
112
+ * read, so `validate` can read a spec whose shape failed.
65
113
  */
66
114
  export declare function normalizeSignature(list: readonly (string | SignatureEntryDeclaration)[] | undefined | null): SignatureEntry[];
67
115
  /** Whether a value is one of {@link SIGNATURE_TYPES}. */
68
116
  export declare function isSignatureType(value: unknown): value is SignatureType;
117
+ /** A length or count: a non-negative integer. */
118
+ export declare function isCount(value: unknown): value is number;
119
+ /**
120
+ * Whether `value` is a well-formed `minimum`/`maximum` for `type`: a finite
121
+ * number for `integer`/`number`, a real `YYYY-MM-DD` or `today` for `date`, an
122
+ * RFC 3339 date-time or `now` for `date-time`.
123
+ */
124
+ export declare function isBound(type: SignatureType, value: unknown): value is number | string;
125
+ /**
126
+ * Whether a `minimum` and a `maximum` for `type` leave room for a value: `true`
127
+ * unless both are literal and the minimum is above the maximum. `today` and
128
+ * `now` move, so a bound naming one is never out of order here.
129
+ */
130
+ export declare function boundsInOrder(type: SignatureType, minimum: unknown, maximum: unknown): boolean;
131
+ /**
132
+ * A `maxSize` in bytes: a non-negative integer as itself, `<n>KB` as n × 1,000,
133
+ * `<n>MB` as n × 1,000,000; `undefined` for anything else.
134
+ */
135
+ export declare function parseSize(value: unknown): number | undefined;
69
136
  /**
70
137
  * A trigger's normalized signature read from a parsed spec, or `undefined` when no
71
138
  * state declares the id. The same reading `WorkflowMachine.signatureForTrigger`
@@ -73,10 +140,22 @@ export declare function isSignatureType(value: unknown): value is SignatureType;
73
140
  * document error; here the later one wins, as in `triggerBindings`.
74
141
  */
75
142
  export declare function signatureForTrigger(spec: MachineSpec, triggerId: string): TriggerSignature | undefined;
76
- /** One property of {@link signatureJsonSchema}'s output. An untyped entry has no `type`. */
143
+ /**
144
+ * One property of {@link signatureJsonSchema}'s output. An untyped entry has no
145
+ * `type`; a rule JSON Schema can express adds its keyword.
146
+ */
77
147
  export interface SignaturePropertySchema {
78
148
  type?: "string" | "integer" | "number" | "boolean" | "object" | "array";
79
- format?: "date" | "date-time" | "file";
149
+ format?: "date" | "date-time" | "file" | "email" | "uri";
150
+ pattern?: string;
151
+ minLength?: number;
152
+ maxLength?: number;
153
+ enum?: string[];
154
+ minimum?: number;
155
+ maximum?: number;
156
+ minItems?: number;
157
+ maxItems?: number;
158
+ contentMediaType?: "text/plain" | "text/markdown" | "text/html";
80
159
  description?: string;
81
160
  }
82
161
  /** What {@link signatureJsonSchema} yields: a JSON Schema object over the signature's names. */
@@ -89,23 +168,46 @@ export interface SignatureJsonSchema {
89
168
  * The one mapping from signature entries to a JSON Schema object: one property
90
169
  * per entry in declaration order, the six JSON Schema type words as themselves,
91
170
  * `date`/`date-time`/`file` as a string with that `format`, an untyped entry as `{}`,
92
- * and every name `required` — each `requires` entry is mandatory, and the
93
- * completion check guarantees each `returns` entry is set. The delegation tool's
94
- * input schema is built by it, so a host building an MCP tool, a form or an API
95
- * body from the same signature describes exactly what the runtime enforces.
171
+ * each rule JSON Schema can express as its keyword, and every name `required` —
172
+ * each `requires` entry is mandatory, and the completion check guarantees each
173
+ * `returns` entry is set. The delegation tool's input schema is built by it, so
174
+ * a host building an MCP tool, a form or an API body from the same signature
175
+ * describes what the runtime enforces. Date bounds, `accept` and `maxSize` have
176
+ * no JSON Schema keyword and are left out; the runtime still enforces them.
96
177
  */
97
178
  export declare function signatureJsonSchema(entries: readonly SignatureEntry[]): SignatureJsonSchema;
98
179
  /**
99
180
  * The one conformance rule: one issue per entry whose name is not set in
100
- * `values`, and one per typed entry whose value does not conform, in declaration
101
- * order; an empty list when the map satisfies the signature. A name is set when
102
- * `values` holds it with any value but `undefined`. An untyped entry takes any
103
- * value, `null` included; a typed one never takes `null`. Nothing is coerced —
104
- * the string `"4"` is not an `integer`. A `file` value is judged by its shape
105
- * alone: whether a file is there, and whether the session may read it, is the
106
- * runtime's check where the value crosses a boundary.
107
- */
108
- export declare function signatureValueIssues(entries: readonly SignatureEntry[], values: Readonly<Record<string, unknown>>): SignatureValueIssue[];
181
+ * `values`, and one per typed entry whose value does not conform to its type
182
+ * or, conforming, breaks one of its rules, in declaration order; an empty list
183
+ * when the map satisfies the signature. A name is set when `values` holds it
184
+ * with any value but `undefined`. An untyped entry takes any value, `null`
185
+ * included; a typed one never takes `null`. Nothing is coerced or trimmed —
186
+ * the string `"4"` is not an `integer`, and `" a@b.co"` is not an email address.
187
+ *
188
+ * Rules are checked only on a value of the right type, and an entry reports
189
+ * only the first rule it breaks, in this order: `format`/`pattern`, `enum`,
190
+ * `minLength`/`maxLength`, `minimum`/`maximum`, `minItems`/`maxItems`,
191
+ * `accept`. `today` and `now` read `options.now`, the current time by default.
192
+ * Every check is synchronous and linear in the value's length; an authored
193
+ * `pattern` runs in RE2, never in `RegExp`. A `file` value is judged by its
194
+ * path alone: whether a file is there, whether the session may read it and
195
+ * how large it is, is the runtime's check where the value crosses a boundary.
196
+ */
197
+ export declare function signatureValueIssues(entries: readonly SignatureEntry[], values: Readonly<Record<string, unknown>>, options?: SignatureValueOptions): SignatureValueIssue[];
198
+ /**
199
+ * The rules an entry declares, as short phrases in declaration-table order
200
+ * (`an email address`, `at most 80 characters`, `not before today`): what the
201
+ * prompt lists beside the entry's type, in the words a refusal of each uses.
202
+ */
203
+ export declare function signatureRulePhrases(entry: SignatureEntry): string[];
204
+ /**
205
+ * A `file` path's last extension, lower-cased with its leading `.`, or `""`
206
+ * when its file name has none (`notes`, `.env`).
207
+ */
208
+ export declare function lastExtension(path: string): string;
209
+ /** A byte count as a refusal states it, 1,000-based: `10 MB`, `512 KB`, `1500 bytes`. */
210
+ export declare function formatSize(bytes: number): string;
109
211
  /**
110
212
  * A workspace path from the root, as a `file` value spells it: at most one
111
213
  * leading `/`, then one or more segments, none empty, `.` or `..`, with no