@loomwork/compiler 0.0.0-stage → 0.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 (59) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +8 -0
  3. package/README.md +62 -2
  4. package/dist/cli.d.ts +3 -0
  5. package/dist/cli.d.ts.map +1 -0
  6. package/dist/cli.js +81 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/hash.d.ts +3 -0
  9. package/dist/hash.d.ts.map +1 -0
  10. package/dist/hash.js +16 -0
  11. package/dist/hash.js.map +1 -0
  12. package/dist/importResolve.d.ts +5 -0
  13. package/dist/importResolve.d.ts.map +1 -0
  14. package/dist/importResolve.js +130 -0
  15. package/dist/importResolve.js.map +1 -0
  16. package/dist/index.d.ts +14 -0
  17. package/dist/index.d.ts.map +1 -0
  18. package/dist/index.js +26 -0
  19. package/dist/index.js.map +1 -0
  20. package/dist/loopIdentity.d.ts +18 -0
  21. package/dist/loopIdentity.d.ts.map +1 -0
  22. package/dist/loopIdentity.js +179 -0
  23. package/dist/loopIdentity.js.map +1 -0
  24. package/dist/manifest.d.ts +98 -0
  25. package/dist/manifest.d.ts.map +1 -0
  26. package/dist/manifest.js +123 -0
  27. package/dist/manifest.js.map +1 -0
  28. package/dist/nondeterminism.d.ts +25 -0
  29. package/dist/nondeterminism.d.ts.map +1 -0
  30. package/dist/nondeterminism.js +88 -0
  31. package/dist/nondeterminism.js.map +1 -0
  32. package/dist/plugin.d.ts +3 -0
  33. package/dist/plugin.d.ts.map +1 -0
  34. package/dist/plugin.js +71 -0
  35. package/dist/plugin.js.map +1 -0
  36. package/dist/runnerReach.d.ts +136 -0
  37. package/dist/runnerReach.d.ts.map +1 -0
  38. package/dist/runnerReach.js +1809 -0
  39. package/dist/runnerReach.js.map +1 -0
  40. package/dist/transform.d.ts +6 -0
  41. package/dist/transform.d.ts.map +1 -0
  42. package/dist/transform.js +416 -0
  43. package/dist/transform.js.map +1 -0
  44. package/dist/types.d.ts +73 -0
  45. package/dist/types.d.ts.map +1 -0
  46. package/dist/types.js +3 -0
  47. package/dist/types.js.map +1 -0
  48. package/package.json +64 -3
  49. package/src/cli.ts +90 -0
  50. package/src/hash.ts +12 -0
  51. package/src/importResolve.ts +133 -0
  52. package/src/index.ts +23 -0
  53. package/src/loopIdentity.ts +210 -0
  54. package/src/manifest.ts +185 -0
  55. package/src/nondeterminism.ts +133 -0
  56. package/src/plugin.ts +74 -0
  57. package/src/runnerReach.ts +1964 -0
  58. package/src/transform.ts +523 -0
  59. package/src/types.ts +79 -0
@@ -0,0 +1,136 @@
1
+ import ts from "typescript";
2
+ /** A `ctx.run` target resolved to a concrete tool. */
3
+ export interface RunnerStepRef {
4
+ /** The step's declared id, when the binding carried one. */
5
+ stepId?: string;
6
+ toolId: string;
7
+ /**
8
+ * The target was reached through `scope.invokeTransient(…)` inside a `ctx.decide`
9
+ * decider (L31), not through `ctx.run`. Such a call is transient: it is refused at
10
+ * runtime for a `journaled` effect, which the verifier can only check if it knows
11
+ * the call came from a scope.
12
+ */
13
+ viaDecider?: true;
14
+ }
15
+ /** A `ctx.run`/`ctx.suspend` whose target could not be resolved statically. */
16
+ export interface UnresolvedReach {
17
+ /** Source text of the unresolved expression, e.g. `mcpInvoke$(…)` or `steps[i]`. */
18
+ expr: string;
19
+ /** What was being resolved — a step target or a suspend condition. */
20
+ kind: "step" | "suspend";
21
+ location?: string;
22
+ }
23
+ /** A suspend point read from a `ctx.suspend({ … })` object literal. */
24
+ export interface RunnerSuspend {
25
+ /** The `on` event type, used to name the finding. */
26
+ id?: string;
27
+ correlationKey?: string;
28
+ /** A `timeout` was declared — the wake depends on a timer. */
29
+ timed?: boolean;
30
+ /** A `wakeAt` was declared explicitly in the condition. */
31
+ wakeAt?: boolean;
32
+ }
33
+ /**
34
+ * L32 — the flow's `ctx` (or its `ctx.decide`) is handed to code outside this region. The
35
+ * compiler cannot see that code, so it records WHERE it went; `@loomwork/verify`'s adapter
36
+ * resolves `callee`/`root` against the app's declared reach (`verify.reach`) and either
37
+ * counts the declared tools or reports the escape unresolved.
38
+ */
39
+ export interface ReachEscape {
40
+ /** Source text of the callee the value was handed to, e.g. `planner.compose`. */
41
+ callee: string;
42
+ /** The leftmost identifier of `callee` (`planner`), absent for `this.x` / call results. */
43
+ root?: string;
44
+ /** What was handed over: the whole `ctx`, or just `ctx.decide`. */
45
+ via: "ctx" | "decide";
46
+ /** When `via` is "ctx": the ctx METHOD handed over (`run` for `lib(ctx.run)`), absent for the whole ctx. */
47
+ member?: string;
48
+ /**
49
+ * L34 - the arguments of the hand-off that RESOLVE to a step, by position, for a callee whose
50
+ * declaration says it runs a step it is handed (`fanout$(ctx, step, items)`: argument 1). A
51
+ * position absent here did not resolve; the verifier reports that only if the declaration names
52
+ * the position. Absent for `via: "decide"`, a ctx method, and a pass-through
53
+ * (`setTimeout(lib, …)`), whose arguments are not the callee's.
54
+ */
55
+ args?: ReachEscapeArg[];
56
+ location?: string;
57
+ }
58
+ /** One argument of a ctx hand-off, see {@link ReachEscape.args}. */
59
+ export interface ReachEscapeArg {
60
+ index: number;
61
+ step: RunnerStepRef;
62
+ }
63
+ /**
64
+ * Resolution services the analysis cannot do on a single parsed module. Optional: without it
65
+ * the analysis is same-module only.
66
+ */
67
+ export interface AnalyzeReachOptions {
68
+ /**
69
+ * L37 - resolve a name this module IMPORTS to what its declaration shows: a string constant
70
+ * (`export const LLM_X = "llm.x"`) or a step-factory shape (`export function llmStep$(id, toolId)`).
71
+ */
72
+ importResolver?: (localName: string) => ImportedBinding | undefined;
73
+ }
74
+ /** What an imported name resolves to. */
75
+ export interface ImportedBinding {
76
+ value?: string;
77
+ factory?: StepFactoryShape;
78
+ }
79
+ /**
80
+ * L37 - how a step factory yields its effect id: a fixed one (`mcpInvoke$` always dispatches
81
+ * `mcp.invoke`; the step ID is minted but the EFFECT is what verify checks) or the value of one of
82
+ * its parameters (`llmStep$(id, toolId)`).
83
+ */
84
+ export type StepFactoryShape = {
85
+ fixed: string;
86
+ }
87
+ /** The effect id is argument `argIndex`; when that argument is absent, `default` (a parameter default). */
88
+ | {
89
+ argIndex: number;
90
+ default?: string;
91
+ };
92
+ /**
93
+ * First-party factories whose effect id is fixed and whose source is in a package (never followed
94
+ * through an import). `mcp.invoke` is `MCP_INVOKE_TOOL_ID` in `@loomwork/plugin-mcp` and `sandbox.eval` is
95
+ * `SANDBOX_TOOL_ID` in `@loomwork/sandbox` (re-exported by `@loomwork/plugin-sandbox`, ADR 0144); a test pins each to its package.
96
+ */
97
+ export declare const KNOWN_STEP_FACTORIES: Readonly<Record<string, StepFactoryShape>>;
98
+ export interface RunnerReach {
99
+ steps: RunnerStepRef[];
100
+ unresolved: UnresolvedReach[];
101
+ suspends: RunnerSuspend[];
102
+ /** L32 — `ctx` handed to out-of-region callees. Absent when there are none. */
103
+ escapes?: ReachEscape[];
104
+ }
105
+ /** The string a literal-ish expression denotes (`"x"`, an expression-free template, `"x" as const`). */
106
+ export declare function stringLiteralValue(e: ts.Expression): string | undefined;
107
+ /**
108
+ * L37 - infer how a function yields a step's effect id, by SHAPE (like {@link collectBindings}):
109
+ * its single returned expression is a call whose first argument is an object literal with a
110
+ * `toolId` that is a constant (per `str`) or one of the function's plain parameters. Anything else
111
+ * (several returns, a spread, a computed toolId) is `undefined`, never a guess.
112
+ */
113
+ export declare function inferStepFactory(fn: ts.Node, rawStr: (e: ts.Expression) => string | undefined): StepFactoryShape | undefined;
114
+ /** Analyze a parsed node (a flow runner body) for reachable steps and suspend points. */
115
+ export declare function analyzeReachNode(root: ts.Node, location?: string, options?: AnalyzeReachOptions): RunnerReach;
116
+ /**
117
+ * {@link analyzeReachNode} plus how many runner functions the region declares and the analysis
118
+ * followed, and how many of them are BOUND to a `flow$` definition: declared in the same object
119
+ * literal / class as a `flow$(...)` (or a const holding one), or passed to `registerFlow(def, …)`
120
+ * whose `def` is a `flow$` call or names one. An EMPTY reach is ambiguous on its own: "the runner
121
+ * reaches nothing" and "no runner of THIS flow is here" (an unrelated runner elsewhere in the
122
+ * module, or one registered from another module) look the same. A runner that is NOT followable is
123
+ * never silent (`unresolved`), so an empty reach with `boundRunners > 0` means the flow's own
124
+ * runner was read and reaches no step, suspend or ctx hand-off: a pure runner, analysed.
125
+ */
126
+ export declare function analyzeReachRegion(root: ts.Node, location?: string, options?: AnalyzeReachOptions): {
127
+ reach: RunnerReach;
128
+ runners: number;
129
+ boundRunners: number;
130
+ };
131
+ /**
132
+ * Analyze a source string (a flow runner / orchestration body). Feed the result
133
+ * to `@loomwork/verify` via `resolveVerifyInput({ runnerReachByFlow })`.
134
+ */
135
+ export declare function analyzeRunnerReach(source: string, location?: string): RunnerReach;
136
+ //# sourceMappingURL=runnerReach.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runnerReach.d.ts","sourceRoot":"","sources":["../src/runnerReach.ts"],"names":[],"mappings":"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"}