@cotal-ai/lang 0.0.0 → 0.15.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 (51) hide show
  1. package/LICENSE +202 -0
  2. package/dist/dryrun.d.ts +106 -0
  3. package/dist/dryrun.d.ts.map +1 -0
  4. package/dist/dryrun.js +172 -0
  5. package/dist/dryrun.js.map +1 -0
  6. package/dist/duration.d.ts +12 -0
  7. package/dist/duration.d.ts.map +1 -0
  8. package/dist/duration.js +34 -0
  9. package/dist/duration.js.map +1 -0
  10. package/dist/effects.d.ts +231 -0
  11. package/dist/effects.d.ts.map +1 -0
  12. package/dist/effects.js +64 -0
  13. package/dist/effects.js.map +1 -0
  14. package/dist/errors.d.ts +141 -0
  15. package/dist/errors.d.ts.map +1 -0
  16. package/dist/errors.js +163 -0
  17. package/dist/errors.js.map +1 -0
  18. package/dist/grammar.d.ts +28 -0
  19. package/dist/grammar.d.ts.map +1 -0
  20. package/dist/grammar.js +793 -0
  21. package/dist/grammar.js.map +1 -0
  22. package/dist/index.d.ts +23 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +23 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/interpret.d.ts +89 -0
  27. package/dist/interpret.d.ts.map +1 -0
  28. package/dist/interpret.js +1117 -0
  29. package/dist/interpret.js.map +1 -0
  30. package/dist/journal.d.ts +177 -0
  31. package/dist/journal.d.ts.map +1 -0
  32. package/dist/journal.js +198 -0
  33. package/dist/journal.js.map +1 -0
  34. package/dist/keys.d.ts +87 -0
  35. package/dist/keys.d.ts.map +1 -0
  36. package/dist/keys.js +105 -0
  37. package/dist/keys.js.map +1 -0
  38. package/dist/primitives.d.ts +84 -0
  39. package/dist/primitives.d.ts.map +1 -0
  40. package/dist/primitives.js +265 -0
  41. package/dist/primitives.js.map +1 -0
  42. package/dist/sim.d.ts +101 -0
  43. package/dist/sim.d.ts.map +1 -0
  44. package/dist/sim.js +192 -0
  45. package/dist/sim.js.map +1 -0
  46. package/dist/values.d.ts +35 -0
  47. package/dist/values.d.ts.map +1 -0
  48. package/dist/values.js +0 -0
  49. package/dist/values.js.map +1 -0
  50. package/package.json +27 -7
  51. package/README.md +0 -10
package/dist/keys.js ADDED
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Step keys: `(scope path, effect kind, step name, occurrence)`, with the input hash compared
3
+ * after lookup rather than folded into the key.
4
+ *
5
+ * Never execution position. Positional keying is the durable-execution field's documented worst
6
+ * production pain, and an LLM author restructures control flow freely, so positions are the one
7
+ * thing that will not survive an edit.
8
+ *
9
+ * The scope path exists for one reason: inside a concurrency combinator, branches interleave, so
10
+ * a per-run occurrence counter would race. Two branches both calling `turn(x, { name: "review" })`
11
+ * would fight over occurrence 0 and the winner would depend on wall-clock timing, which is
12
+ * exactly the nondeterminism replay cannot tolerate. Each branch therefore gets its own counter
13
+ * namespace, and a combinator's own occurrence is allocated synchronously at the call, which sits
14
+ * in already-deterministic code.
15
+ */
16
+ import { createHash } from "node:crypto";
17
+ import { canonicalize } from "json-canonicalize";
18
+ /** `sha256:<hex>` over the RFC 8785 canonical form, matching the digest discipline used for
19
+ * contract artifacts elsewhere in the repo. */
20
+ export const DIGEST_PREFIX = "sha256:";
21
+ /**
22
+ * The identity a handler submits under, written on the pending entry BEFORE the handler runs.
23
+ *
24
+ * Four components, each load-bearing rather than defensive. `runId`, because two runs reaching the
25
+ * same step with the same inputs would otherwise derive the same id and collide at a caller-scoped
26
+ * idempotency boundary. `attempt`, because escalation mints twice under one entry, so the second
27
+ * mint needs a second identity that is still derivable before it happens. The step key and input
28
+ * hash are what make it the identity of THIS step's THIS call.
29
+ *
30
+ * base64url, not the `sha256:<hex>` form this carried first: an endpoint id token is
31
+ * `[A-Za-z0-9_-]{1,64}`, and that form is 71 characters with a colon in it, so it was never a
32
+ * legal id. This is 43 characters in exactly that alphabet, with no `.` to confuse the
33
+ * dot-separated subject a goal id rides.
34
+ */
35
+ export function requestId(runId, key, inputHash, attempt = 0) {
36
+ return createHash("sha256")
37
+ .update(canonicalize([runId, stepKeyString(key), inputHash, attempt]), "utf8")
38
+ .digest("base64url");
39
+ }
40
+ export function digest(value) {
41
+ return DIGEST_PREFIX + createHash("sha256").update(canonicalize(value), "utf8").digest("hex");
42
+ }
43
+ function frameString(f) {
44
+ const named = f.name === null ? f.kind : `${f.kind}:${f.name}`;
45
+ return `/${named}#${f.occurrence}/b:${f.branch}`;
46
+ }
47
+ /** The canonical string form, used in the journal, the trace, and error messages. */
48
+ export function scopePathString(scope) {
49
+ return scope.map(frameString).join("");
50
+ }
51
+ export function stepKeyString(key) {
52
+ const named = key.name === "" ? key.kind : `${key.kind}:${key.name}`;
53
+ return `${scopePathString(key.scope)}/${named}#${key.occurrence}`;
54
+ }
55
+ export function stepKeyEquals(a, b) {
56
+ return stepKeyString(a) === stepKeyString(b);
57
+ }
58
+ /**
59
+ * One counter namespace. A run has one at the root, and every branch of every concurrency scope
60
+ * gets its own child.
61
+ *
62
+ * Both counters are allocated synchronously at the call site, before the first await. That is the
63
+ * whole determinism argument: the allocating code is either sequential or is itself inside an
64
+ * already-deterministic namespace, so no two allocations can race.
65
+ */
66
+ export class KeyScope {
67
+ path;
68
+ effectCounts = new Map();
69
+ scopeCounts = new Map();
70
+ constructor(path = []) {
71
+ this.path = path;
72
+ }
73
+ /** Allocate the next occurrence for an effect in this namespace, and build its key. */
74
+ nextEffect(kind, name = "") {
75
+ const tag = `${kind}:${name}`;
76
+ const occurrence = this.effectCounts.get(tag) ?? 0;
77
+ this.effectCounts.set(tag, occurrence + 1);
78
+ return { scope: this.path, kind, name, occurrence };
79
+ }
80
+ /**
81
+ * Allocate the next occurrence for a concurrency scope entered from this namespace. Call once
82
+ * per combinator call, then {@link branch} once per branch.
83
+ */
84
+ nextScope(kind, name = null) {
85
+ const tag = `${kind}:${name ?? ""}`;
86
+ const occurrence = this.scopeCounts.get(tag) ?? 0;
87
+ this.scopeCounts.set(tag, occurrence + 1);
88
+ return occurrence;
89
+ }
90
+ /** The child namespace for one branch of a scope opened from here. */
91
+ branch(kind, name, occurrence, branchKey) {
92
+ return new KeyScope([...this.path, { kind, name, occurrence, branch: branchKey }]);
93
+ }
94
+ }
95
+ /**
96
+ * The branch keys for a combinator's argument. The record form is the default because its keys
97
+ * survive both reordering and insertion; the array form is keyed by index, which shifts when a
98
+ * branch is inserted, and the validator lints it.
99
+ */
100
+ export function branchKeys(branches) {
101
+ return Array.isArray(branches)
102
+ ? branches.map((_, i) => String(i))
103
+ : Object.keys(branches);
104
+ }
105
+ //# sourceMappingURL=keys.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keys.js","sourceRoot":"","sources":["../src/keys.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * The effect primitives and the builtins, as data.
3
+ *
4
+ * One table drives four things that must never disagree: the validator's call-shape checks, the
5
+ * error catalog's callee documentation, the interpreter's dispatch, and the derived flowchart's
6
+ * node kinds. Keeping them in one place is why an unknown option key can answer with a full
7
+ * signature instead of a shrug.
8
+ */
9
+ import type { CalleeDoc } from "./errors.js";
10
+ /** The journalled effect kinds. `channel` is pure and deliberately absent. */
11
+ export declare const EFFECT_KINDS: readonly ["spawn", "turn", "ask", "checkpoint", "sleep", "wait", "notify", "monitor", "conclave"];
12
+ export type EffectKind = (typeof EFFECT_KINDS)[number];
13
+ /** Which of a call's inputs decide whether a recorded result is still valid (design doc 5.12). */
14
+ export interface PrimitiveSpec extends CalleeDoc {
15
+ /** The effect kind journalled, or null for a pure primitive that writes no entry. */
16
+ readonly kind: EffectKind | null;
17
+ /** A step name is required, not merely allowed. */
18
+ readonly nameRequired: boolean;
19
+ /** Every accepted option key. Bags are closed: anything else is L3011. */
20
+ readonly options: readonly string[];
21
+ /** The argument index the option bag occupies. Fixed per primitive, never "the last record":
22
+ * `notify(agents, fact, opts)` and `checkpoint(name, prompt, opts)` both take a record in an
23
+ * earlier position, and treating that as options would reject perfectly good data. */
24
+ readonly optionsAt: number;
25
+ /**
26
+ * Option keys folded into the input hash. Everything else only steered live execution.
27
+ *
28
+ * NORMATIVE AND EXECUTED. This was documentation for a while, and drifted: the interpreter grew
29
+ * a projection per primitive and this table stayed at whatever it said on the day it was written,
30
+ * so "align interpret to the table" was a change that would have reintroduced the very holes the
31
+ * projections closed. `options.smoke` now edits each key on a resumed run and requires exactly
32
+ * the keys listed here to raise L5001, which is what makes the table a claim rather than a note.
33
+ */
34
+ readonly hashedOptions: readonly string[];
35
+ /**
36
+ * Keys whose VALUE decides whether they are hashed: listed here with the values that put them
37
+ * into the projection, absent from `hashedOptions` because they are not always in it.
38
+ *
39
+ * There is exactly one of these and it is the subtlest rule in the table. `onExpiry` chooses how
40
+ * to READ a recorded expiry at `fail` and `proceed`, which is a reapply and must replay clean;
41
+ * at `escalate` it MINTS A SECOND EFFECT, which is a different question being asked and must
42
+ * diverge. Flattening that either way breaks something real: hash it always and editing `fail`
43
+ * to `proceed` stops working, hash it never and switching an answered checkpoint to `escalate`
44
+ * silently keeps the old answer.
45
+ */
46
+ readonly hashedValues?: Readonly<Record<string, readonly unknown[]>>;
47
+ /** True when the positional subject is part of the input hash. */
48
+ readonly hashesSubject: boolean;
49
+ /** This primitive opens a concurrency scope, so it pushes a scope frame. */
50
+ readonly opensScope: boolean;
51
+ }
52
+ export declare const PRIMITIVES: Readonly<Record<string, PrimitiveSpec>>;
53
+ /** Event constructors. Pure: they build a descriptor and perform no effect. */
54
+ export declare const EVENT_CONSTRUCTORS: Readonly<Record<string, CalleeDoc>>;
55
+ /** Pure primitives that write no journal entry. */
56
+ export declare const PURE_PRIMITIVES: Readonly<Record<string, CalleeDoc>>;
57
+ /** The builtin library. Small on purpose (design doc 4). */
58
+ export declare const BUILTINS: readonly string[];
59
+ /** Every name the program may reference without defining it, and may never shadow. */
60
+ export declare const RESERVED_NAMES: ReadonlySet<string>;
61
+ /** Host globals a program might reach for out of habit, each rejected by name (L2012). */
62
+ export declare const FORBIDDEN_GLOBALS: ReadonlySet<string>;
63
+ /** The Promise API, rejected separately so its error can point at the right replacement (L2011). */
64
+ export declare const PROMISE_NAMES: ReadonlySet<string>;
65
+ /** Step names: kebab-case, 1 to 64 characters. */
66
+ export declare const STEP_NAME_RE: RegExp;
67
+ /**
68
+ * The bound on a `notify` fact.
69
+ *
70
+ * `notify` is the only primitive that moves program-authored bytes toward an agent's context, so
71
+ * an unconstrained field here would be scripted payloads through the side door and the first
72
+ * non-negotiable would hold everywhere except the one place it is easiest to break. Eight short
73
+ * scalars rendered as a labelled table is not enough room to write an instruction, which is the
74
+ * property we want.
75
+ */
76
+ export declare const NOTIFY_BOUND: Readonly<{
77
+ /** `decision` and `outcome` are tokens, not prose. */
78
+ tokenRe: RegExp;
79
+ detailKeyRe: RegExp;
80
+ maxDetailKeys: 8;
81
+ maxDetailStringLength: 128;
82
+ }>;
83
+ export declare function primitiveDoc(name: string): CalleeDoc | undefined;
84
+ //# sourceMappingURL=primitives.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"primitives.d.ts","sourceRoot":"","sources":["../src/primitives.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,8EAA8E;AAC9E,eAAO,MAAM,YAAY,mGAUf,CAAC;AACX,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAEvD,kGAAkG;AAClG,MAAM,WAAW,aAAc,SAAQ,SAAS;IAC9C,qFAAqF;IACrF,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAAC;IACjC,mDAAmD;IACnD,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,0EAA0E;IAC1E,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC;;2FAEuF;IACvF,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;;;;;;;OAQG;IACH,QAAQ,CAAC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,OAAO,EAAE,CAAC,CAAC,CAAC;IACrE,kEAAkE;IAClE,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC,4EAA4E;IAC5E,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;CAC9B;AAED,eAAO,MAAM,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAmK7D,CAAC;AAEH,+EAA+E;AAC/E,eAAO,MAAM,kBAAkB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAqBjE,CAAC;AAEH,mDAAmD;AACnD,eAAO,MAAM,eAAe,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAW9D,CAAC;AAEH,4DAA4D;AAC5D,eAAO,MAAM,QAAQ,EAAE,SAAS,MAAM,EAcpC,CAAC;AAEH,sFAAsF;AACtF,eAAO,MAAM,cAAc,EAAE,WAAW,CAAC,MAAM,CAO7C,CAAC;AAEH,0FAA0F;AAC1F,eAAO,MAAM,iBAAiB,EAAE,WAAW,CAAC,MAAM,CAKhD,CAAC;AAEH,oGAAoG;AACpG,eAAO,MAAM,aAAa,EAAE,WAAW,CAAC,MAAM,CAAwB,CAAC;AAEvE,kDAAkD;AAClD,eAAO,MAAM,YAAY,QAAyC,CAAC;AAEnE;;;;;;;;GAQG;AACH,eAAO,MAAM,YAAY;IACvB,sDAAsD;;;;;EAKtD,CAAC;AAEH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAEhE"}
@@ -0,0 +1,265 @@
1
+ /**
2
+ * The effect primitives and the builtins, as data.
3
+ *
4
+ * One table drives four things that must never disagree: the validator's call-shape checks, the
5
+ * error catalog's callee documentation, the interpreter's dispatch, and the derived flowchart's
6
+ * node kinds. Keeping them in one place is why an unknown option key can answer with a full
7
+ * signature instead of a shrug.
8
+ */
9
+ /** The journalled effect kinds. `channel` is pure and deliberately absent. */
10
+ export const EFFECT_KINDS = [
11
+ "spawn",
12
+ "turn",
13
+ "ask",
14
+ "checkpoint",
15
+ "sleep",
16
+ "wait",
17
+ "notify",
18
+ "monitor",
19
+ "conclave",
20
+ ];
21
+ export const PRIMITIVES = Object.freeze({
22
+ spawn: {
23
+ kind: "spawn",
24
+ nameRequired: false,
25
+ options: ["name", "worktree", "join", "role", "permits", "supervise", "onFork"],
26
+ optionsAt: 1,
27
+ hashedOptions: ["worktree", "join", "role"],
28
+ hashesSubject: true,
29
+ opensScope: false,
30
+ signature: "spawn(persona, { name?, worktree?, join?, role?, permits?, supervise?, onFork? }) -> AgentHandle",
31
+ doc: "Bring an agent into the run. Permits are budgets whose violation is catchable; supervise is a declarative restart policy.",
32
+ example: 'const builder = await spawn("builder", { worktree: "wt-1", join: [team] })',
33
+ },
34
+ turn: {
35
+ kind: "turn",
36
+ nameRequired: true,
37
+ options: ["name", "deadline"],
38
+ optionsAt: 1,
39
+ hashedOptions: ["deadline"],
40
+ hashesSubject: true,
41
+ opensScope: false,
42
+ signature: "turn(agent, { name, deadline? }) -> { status, to?, note?, at }",
43
+ doc: "Wake an agent for one turn. It reads its own channels and speaks for itself; the result is its yield status, one of done, blocked, or handoff.",
44
+ example: 'const r = await turn(builder, { name: "build" })\nif (r.status === "blocked") { await turn(planner, { name: "unblock" }) }',
45
+ },
46
+ ask: {
47
+ kind: "ask",
48
+ nameRequired: true,
49
+ options: ["name", "schema", "deadline", "attempts"],
50
+ optionsAt: 1,
51
+ hashedOptions: ["schema", "deadline", "attempts"],
52
+ hashesSubject: true,
53
+ opensScope: false,
54
+ signature: "ask(agent, { name, schema, deadline?, attempts? }) -> record",
55
+ doc: "The narrow case where the program itself needs a value. The agent publishes a record, the program awaits it, and the record is schema-checked.",
56
+ example: 'const est = await ask(planner, { name: "estimate", schema: { days: "number" } })',
57
+ },
58
+ checkpoint: {
59
+ kind: "checkpoint",
60
+ nameRequired: true,
61
+ options: ["schema", "timeout", "onExpiry", "to"],
62
+ optionsAt: 2,
63
+ // `to` is unconditionally hashed because it cannot legally appear without `escalate` (L3044),
64
+ // so wherever it exists it is addressing a mint. `onExpiry` is the conditional one.
65
+ hashedOptions: ["schema", "timeout", "to"],
66
+ hashedValues: { onExpiry: ["escalate"] },
67
+ hashesSubject: true,
68
+ opensScope: false,
69
+ signature: 'checkpoint(name, prompt, { schema?, timeout?, onExpiry?, to? }) -> { status, value?, by?, at, artifact? }',
70
+ doc: "A durable pause a human or another agent resolves from anywhere, raced against a durable timer. onExpiry is fail, proceed, or escalate.",
71
+ example: 'const ok = await checkpoint("approve-plan", "Approve the plan?", { timeout: "10m", onExpiry: "proceed" })',
72
+ },
73
+ sleep: {
74
+ kind: "sleep",
75
+ nameRequired: false,
76
+ options: ["name"],
77
+ optionsAt: 1,
78
+ hashedOptions: [],
79
+ // The duration is the subject and it IS hashed: a resumed run reads elapsed time back through
80
+ // the run clock, so editing 1h to 1m must diverge rather than silently keep the path the old
81
+ // duration chose. This said `false` while the interpreter hashed it.
82
+ hashesSubject: true,
83
+ opensScope: false,
84
+ signature: "sleep(duration, { name? }) -> null",
85
+ doc: "A durable timer. A resumed run does not re-sleep an elapsed sleep; use fork to re-run from this step.",
86
+ example: 'await sleep("30m")',
87
+ },
88
+ wait: {
89
+ kind: "wait",
90
+ nameRequired: false,
91
+ options: ["name", "timeout"],
92
+ optionsAt: 1,
93
+ // A recorded null means "not within THIS timeout", never "never".
94
+ hashedOptions: ["timeout"],
95
+ hashesSubject: true,
96
+ opensScope: false,
97
+ signature: "wait(event, { name?, timeout? }) -> value | null",
98
+ doc: "Await one event. Resolves null on timeout rather than throwing, which is what makes ?? the recovery operator.",
99
+ example: 'const m = await wait(message(team, { from: builder }), { name: "await-build", timeout: "20m" })\n ?? await turn(planner, { name: "chase" })',
100
+ },
101
+ notify: {
102
+ kind: "notify",
103
+ nameRequired: false,
104
+ options: ["name"],
105
+ optionsAt: 2,
106
+ hashedOptions: [],
107
+ hashesSubject: true,
108
+ opensScope: false,
109
+ signature: "notify(agents, fact, { name? }) -> null",
110
+ doc: "Tell agents about a branch decision. It writes a notice onto the run, rendered ahead of each agent's next turn; it is never a channel message.",
111
+ example: 'await notify([planner], { decision: "build", outcome: "blocked" })',
112
+ },
113
+ monitor: {
114
+ kind: "monitor",
115
+ nameRequired: false,
116
+ options: ["name"],
117
+ optionsAt: 1,
118
+ hashedOptions: [],
119
+ hashesSubject: true,
120
+ opensScope: false,
121
+ signature: "monitor(agent, { name? }) -> null",
122
+ doc: "Register interest in an agent's health, after which down(agent) is an ordinary awaitable event a concurrent branch can watch.",
123
+ example: 'await monitor(builder)\nconst d = await wait(down(builder), { name: "gone", timeout: "1h" })',
124
+ },
125
+ parallel: {
126
+ kind: null,
127
+ nameRequired: false,
128
+ options: ["name"],
129
+ optionsAt: 1,
130
+ hashedOptions: [],
131
+ hashesSubject: false,
132
+ opensScope: true,
133
+ signature: "parallel(branches, { name? }) -> results",
134
+ doc: "Run branches concurrently and settle all of them. The record form is the default; array branches are keyed by index and are linted. The first rejection cancels the rest.",
135
+ example: 'await parallel({ lint: () => turn(linter, { name: "lint" }),\n tests: () => turn(tester, { name: "tests" }) }, { name: "checks" })',
136
+ },
137
+ race: {
138
+ kind: null,
139
+ nameRequired: false,
140
+ options: ["name"],
141
+ optionsAt: 1,
142
+ hashedOptions: [],
143
+ hashesSubject: false,
144
+ opensScope: true,
145
+ signature: "race(branches, { name? }) -> { index, value }",
146
+ doc: "Run branches concurrently and take the first to settle. Losers are cancelled by semantics: they perform no new effects, and an in-flight agent reply completes and is ignored.",
147
+ example: 'await race({ reply: () => wait(replied(builder), { timeout: "20m" }),\n giveUp: () => sleep("1h") }, { name: "await-or-move-on" })',
148
+ },
149
+ fanOut: {
150
+ kind: null,
151
+ nameRequired: true,
152
+ options: ["name", "key"],
153
+ optionsAt: 2,
154
+ hashedOptions: [],
155
+ hashesSubject: false,
156
+ opensScope: true,
157
+ signature: "fanOut(items, fn, { name, key? }) -> results",
158
+ doc: "Run fn(item, index) per item concurrently. key maps an item to the stable string that names its journal namespace, and defaults to a record item's string id.",
159
+ example: 'await fanOut(["security", "perf"], (lens) => turn(reviewers[lens], { name: "review" }),\n { name: "reviews", key: (lens) => lens })',
160
+ },
161
+ conclave: {
162
+ kind: "conclave",
163
+ nameRequired: true,
164
+ options: ["name", "channel"],
165
+ optionsAt: 2,
166
+ hashedOptions: [],
167
+ hashesSubject: true,
168
+ opensScope: true,
169
+ signature: "conclave(members, fn, { name, channel? }) -> result",
170
+ doc: "Open a scoped sub-team: create a conclave channel, join the members, run fn with that channel, then have them leave. It scopes the derived flowchart the same way it scopes the journal.",
171
+ example: 'await conclave([a, b], (ch) => turn(a, { name: "huddle" }), { name: "triage" })',
172
+ },
173
+ });
174
+ /** Event constructors. Pure: they build a descriptor and perform no effect. */
175
+ export const EVENT_CONSTRUCTORS = Object.freeze({
176
+ replied: {
177
+ signature: "replied(agent) -> Event",
178
+ doc: "The agent finished a reply.",
179
+ example: 'await wait(replied(builder), { timeout: "20m" })',
180
+ },
181
+ message: {
182
+ signature: "message(channel, { from?, matches? }) -> Event",
183
+ doc: "A message landed on the channel, optionally filtered by sender or content match.",
184
+ example: 'await wait(message(team, { from: builder }), { timeout: "20m" })',
185
+ },
186
+ idle: {
187
+ signature: "idle(channel, duration) -> Event",
188
+ doc: "The channel went quiet for the duration.",
189
+ example: 'await wait(idle(team, "10m"), { timeout: "1h" })',
190
+ },
191
+ down: {
192
+ signature: "down(agent) -> Event",
193
+ doc: "A monitored agent died. Carries the reason.",
194
+ example: 'const d = await wait(down(builder), { timeout: "1h" })',
195
+ },
196
+ });
197
+ /** Pure primitives that write no journal entry. */
198
+ export const PURE_PRIMITIVES = Object.freeze({
199
+ channel: {
200
+ signature: "channel(name) -> ChannelHandle",
201
+ doc: "Name a channel. Pure: a name is a name, and membership is what costs something.",
202
+ example: 'const team = channel("feat-auth")',
203
+ },
204
+ run: {
205
+ signature: "run() -> { id, programHash, startedAt }",
206
+ doc: "This run's own metadata.",
207
+ example: "const id = run().id",
208
+ },
209
+ });
210
+ /** The builtin library. Small on purpose (design doc 4). */
211
+ export const BUILTINS = Object.freeze([
212
+ // records
213
+ "keys", "values", "entries", "has", "merge",
214
+ // arrays
215
+ "len", "map", "filter", "find", "some", "every", "sort", "slice", "concat", "join",
216
+ "reverse", "unique", "range", "sum",
217
+ // strings
218
+ "split", "trim", "lower", "upper", "startsWith", "endsWith", "contains", "replace",
219
+ // numbers
220
+ "min", "max", "abs", "floor", "ceil", "round", "parseNumber",
221
+ // data and control
222
+ "json", "assert", "log",
223
+ // tamed nondeterminism
224
+ "random", "randomInt", "pick", "now", "duration",
225
+ ]);
226
+ /** Every name the program may reference without defining it, and may never shadow. */
227
+ export const RESERVED_NAMES = new Set([
228
+ ...Object.keys(PRIMITIVES),
229
+ ...Object.keys(EVENT_CONSTRUCTORS),
230
+ ...Object.keys(PURE_PRIMITIVES),
231
+ ...BUILTINS,
232
+ "any",
233
+ "all",
234
+ ]);
235
+ /** Host globals a program might reach for out of habit, each rejected by name (L2012). */
236
+ export const FORBIDDEN_GLOBALS = new Set([
237
+ "globalThis", "global", "window", "self", "process", "console", "fetch", "Date", "Math",
238
+ "RegExp", "Object", "Reflect", "Proxy", "Symbol", "WeakMap", "WeakSet", "Function",
239
+ "setTimeout", "setInterval", "setImmediate", "queueMicrotask", "require", "module",
240
+ "exports", "__dirname", "__filename", "Buffer", "crypto", "performance", "structuredClone",
241
+ ]);
242
+ /** The Promise API, rejected separately so its error can point at the right replacement (L2011). */
243
+ export const PROMISE_NAMES = new Set(["Promise"]);
244
+ /** Step names: kebab-case, 1 to 64 characters. */
245
+ export const STEP_NAME_RE = /^[a-z0-9]([a-z0-9-]{0,62}[a-z0-9])?$/;
246
+ /**
247
+ * The bound on a `notify` fact.
248
+ *
249
+ * `notify` is the only primitive that moves program-authored bytes toward an agent's context, so
250
+ * an unconstrained field here would be scripted payloads through the side door and the first
251
+ * non-negotiable would hold everywhere except the one place it is easiest to break. Eight short
252
+ * scalars rendered as a labelled table is not enough room to write an instruction, which is the
253
+ * property we want.
254
+ */
255
+ export const NOTIFY_BOUND = Object.freeze({
256
+ /** `decision` and `outcome` are tokens, not prose. */
257
+ tokenRe: STEP_NAME_RE,
258
+ detailKeyRe: /^[a-z0-9]([a-z0-9-]{0,30}[a-z0-9])?$/,
259
+ maxDetailKeys: 8,
260
+ maxDetailStringLength: 128,
261
+ });
262
+ export function primitiveDoc(name) {
263
+ return PRIMITIVES[name] ?? EVENT_CONSTRUCTORS[name] ?? PURE_PRIMITIVES[name];
264
+ }
265
+ //# sourceMappingURL=primitives.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"primitives.js","sourceRoot":"","sources":["../src/primitives.ts"],"names":[],"mappings":"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"}
package/dist/sim.d.ts ADDED
@@ -0,0 +1,101 @@
1
+ /**
2
+ * The simulation handler: the same interpreter, a different handler.
3
+ *
4
+ * That is the whole design, and it is why simulation is v1 scope rather than a later nicety. It
5
+ * costs one implementation of an interface the runtime needed anyway, and it is the test harness
6
+ * for everything else: scripted turns, instant sleeps, injected checkpoint answers, and injected
7
+ * faults, with no broker, no agents, and no wall-clock waiting.
8
+ *
9
+ * The rule that makes it worth trusting: **an unscripted effect is an error, never a default**. A
10
+ * simulator that invents a plausible turn result is a simulator that green-lights broken programs,
11
+ * which is worse than having no simulator at all.
12
+ */
13
+ import type { AgentHandleValue, AskRequest, ChannelHandleValue, CheckpointRequest, CheckpointRaw, CheckpointResultValue, ConclaveRequest, EffectContext, EffectHandler, MonitorRequest, NotifyRequest, SleepRequest, SpawnRequest, TurnRequest, TurnResultValue, WaitRequest } from "./effects.js";
14
+ /** A scripted outcome: one value used for every occurrence, or one per occurrence in order. */
15
+ export type Scripted<T> = T | readonly T[];
16
+ export interface SimFault {
17
+ /** The step key, either in full (`/parallel:x#0/b:a/turn:build#1`) or short (`turn:build#1`). */
18
+ readonly at: string;
19
+ readonly kind: string;
20
+ readonly code?: string;
21
+ readonly message?: string;
22
+ }
23
+ export interface SimScript {
24
+ readonly turns?: Readonly<Record<string, Scripted<TurnResultValue>>>;
25
+ readonly asks?: Readonly<Record<string, Scripted<unknown>>>;
26
+ readonly checkpoints?: Readonly<Record<string, Scripted<CheckpointResultValue>>>;
27
+ /** Keyed by the `wait` step's name. A scripted `null` is a timeout, which is a choice. */
28
+ readonly events?: Readonly<Record<string, Scripted<unknown>>>;
29
+ readonly clock?: {
30
+ readonly start?: number;
31
+ /** Virtual time each turn consumes. Default "5m". */
32
+ readonly turn?: string;
33
+ readonly ask?: string;
34
+ readonly checkpoint?: string;
35
+ readonly wait?: string;
36
+ };
37
+ readonly faults?: readonly SimFault[];
38
+ }
39
+ export declare class SimUnscriptedError extends Error {
40
+ readonly code: string;
41
+ readonly stepKey: string;
42
+ constructor(code: string, stepKey: string, message: string);
43
+ }
44
+ interface Consumption {
45
+ readonly table: string;
46
+ readonly name: string;
47
+ readonly occurrence: number;
48
+ }
49
+ /**
50
+ * The simulation handler.
51
+ *
52
+ * Every effect resolves from the script or fails loudly. Sleeps are instant and advance the
53
+ * virtual clock by the duration the program asked for, so a program that waits four hours is
54
+ * tested in microseconds without pretending the wait did not happen.
55
+ */
56
+ export declare class SimHandler implements EffectHandler {
57
+ readonly script: SimScript;
58
+ private virtualNow;
59
+ private readonly occurrences;
60
+ private readonly consumed;
61
+ private readonly agents;
62
+ constructor(script?: SimScript);
63
+ now(): number;
64
+ /** Advance virtual time. Sleeps do this by their full duration; turns by a scripted default. */
65
+ advance(ms: number): void;
66
+ private advanceBy;
67
+ /** Which occurrence of this (table, name) we are on, counted per simulated run. */
68
+ private nextOccurrence;
69
+ private checkFault;
70
+ /**
71
+ * Resolve one scripted outcome, or fail. `name` falls back to the effect kind for unnamed
72
+ * steps, which is the same fallback the journal key uses, so a script and a real trace read
73
+ * against each other without translation.
74
+ */
75
+ private resolve;
76
+ spawn(req: SpawnRequest, ctx: EffectContext): Promise<AgentHandleValue>;
77
+ turn(_req: TurnRequest, ctx: EffectContext): Promise<TurnResultValue>;
78
+ ask(_req: AskRequest, ctx: EffectContext): Promise<unknown>;
79
+ /**
80
+ * Reports WHAT HAPPENED and never whether it throws. A script says `resolved` or `expired`; the
81
+ * interpreter journals that and applies today's `onExpiry` afterwards. A simulator that decided
82
+ * the disposition would bake it into the record exactly as a production handler would.
83
+ */
84
+ checkpoint(_req: CheckpointRequest, ctx: EffectContext): Promise<CheckpointRaw>;
85
+ /** Instant, and honest: the clock moves by exactly what the program asked to wait. */
86
+ sleep(req: SleepRequest, ctx: EffectContext): Promise<null>;
87
+ wait(req: WaitRequest, ctx: EffectContext): Promise<unknown | null>;
88
+ notify(_req: NotifyRequest, ctx: EffectContext): Promise<null>;
89
+ monitor(_req: MonitorRequest, ctx: EffectContext): Promise<null>;
90
+ openConclave(req: ConclaveRequest, ctx: EffectContext): Promise<ChannelHandleValue>;
91
+ closeConclave(_req: ConclaveRequest, ctx: EffectContext): Promise<null>;
92
+ /**
93
+ * Script entries the run never reached. Usually a renamed step, which is worth saying out loud:
94
+ * a script that silently stops matching is a test that silently stops testing.
95
+ */
96
+ unusedScript(): readonly string[];
97
+ /** Every effect the run performed, in order, for the dry-run report. */
98
+ performed(): readonly Consumption[];
99
+ }
100
+ export {};
101
+ //# sourceMappingURL=sim.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sim.d.ts","sourceRoot":"","sources":["../src/sim.ts"],"names":[],"mappings":"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"}