@interf/compiler 0.16.0 → 0.18.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 (133) hide show
  1. package/LICENSE.md +1 -0
  2. package/README.md +10 -7
  3. package/TRADEMARKS.md +4 -4
  4. package/builtin-methods/interf-default/README.md +6 -7
  5. package/builtin-methods/interf-default/method.json +7 -68
  6. package/builtin-methods/interf-default/method.schema.json +52 -50
  7. package/dist/cli/commands/prep.js +58 -2
  8. package/dist/cli/commands/verify.d.ts +2 -0
  9. package/dist/cli/commands/verify.js +17 -8
  10. package/dist/cli/commands/wizard.js +122 -14
  11. package/dist/compiler-ui/404.html +1 -1
  12. package/dist/compiler-ui/__next.__PAGE__.txt +2 -2
  13. package/dist/compiler-ui/__next._full.txt +3 -3
  14. package/dist/compiler-ui/__next._head.txt +1 -1
  15. package/dist/compiler-ui/__next._index.txt +2 -2
  16. package/dist/compiler-ui/__next._tree.txt +2 -2
  17. package/dist/compiler-ui/_next/static/chunks/{13awzu4tooflw.css → 0_c_tvh-cukjz.css} +1 -1
  18. package/dist/compiler-ui/_next/static/chunks/{0jipmpez3_ehh.js → 0f_geuwdesg_c.js} +42 -17
  19. package/dist/compiler-ui/_not-found/__next._full.txt +2 -2
  20. package/dist/compiler-ui/_not-found/__next._head.txt +1 -1
  21. package/dist/compiler-ui/_not-found/__next._index.txt +2 -2
  22. package/dist/compiler-ui/_not-found/__next._not-found.__PAGE__.txt +1 -1
  23. package/dist/compiler-ui/_not-found/__next._not-found.txt +1 -1
  24. package/dist/compiler-ui/_not-found/__next._tree.txt +2 -2
  25. package/dist/compiler-ui/_not-found.html +1 -1
  26. package/dist/compiler-ui/_not-found.txt +2 -2
  27. package/dist/compiler-ui/index.html +1 -1
  28. package/dist/compiler-ui/index.txt +3 -3
  29. package/dist/packages/contracts/index.d.ts +2 -2
  30. package/dist/packages/contracts/index.js +1 -1
  31. package/dist/packages/contracts/lib/schema.d.ts +271 -72
  32. package/dist/packages/contracts/lib/schema.js +243 -83
  33. package/dist/packages/engine/action-definitions.js +1 -1
  34. package/dist/packages/engine/agents/lib/shells.d.ts +12 -4
  35. package/dist/packages/engine/agents/lib/shells.js +127 -120
  36. package/dist/packages/engine/cloud-seams.d.ts +115 -0
  37. package/dist/packages/engine/cloud-seams.js +84 -0
  38. package/dist/packages/engine/compile/artifact-counts.d.ts +1 -1
  39. package/dist/packages/engine/compile/artifact-counts.js +3 -3
  40. package/dist/packages/engine/compile/artifact-status.d.ts +41 -0
  41. package/dist/packages/engine/compile/artifact-status.js +166 -0
  42. package/dist/packages/engine/compile/billing-events.d.ts +89 -0
  43. package/dist/packages/engine/compile/billing-events.js +74 -0
  44. package/dist/packages/engine/compile/check-evaluator.d.ts +66 -0
  45. package/dist/packages/engine/compile/check-evaluator.js +298 -0
  46. package/dist/packages/engine/compile/compiled-schema.d.ts +7 -17
  47. package/dist/packages/engine/compile/compiled-schema.js +55 -70
  48. package/dist/packages/engine/compile/compiled-stage-plan.d.ts +1 -0
  49. package/dist/packages/engine/compile/compiled-stage-plan.js +32 -15
  50. package/dist/packages/engine/compile/compiled-stage-runner.js +1 -1
  51. package/dist/packages/engine/compile/index.d.ts +0 -1
  52. package/dist/packages/engine/compile/index.js +0 -1
  53. package/dist/packages/engine/compile/lib/schema.d.ts +111 -92
  54. package/dist/packages/engine/compile/lib/schema.js +35 -39
  55. package/dist/packages/engine/compile/method-primitives.d.ts +2 -2
  56. package/dist/packages/engine/compile/method-primitives.js +1 -1
  57. package/dist/packages/engine/compile/reset.js +4 -4
  58. package/dist/packages/engine/compile/runtime-contracts.js +2 -1
  59. package/dist/packages/engine/compile/runtime-prompt.js +3 -2
  60. package/dist/packages/engine/compile/runtime-reconcile.js +35 -35
  61. package/dist/packages/engine/compile/runtime-runs.js +0 -1
  62. package/dist/packages/engine/compile/runtime-types.d.ts +7 -8
  63. package/dist/packages/engine/compile/runtime.d.ts +1 -2
  64. package/dist/packages/engine/compile/runtime.js +0 -1
  65. package/dist/packages/engine/compile/state-health.js +6 -6
  66. package/dist/packages/engine/compile/state-view.js +7 -6
  67. package/dist/packages/engine/compile/validate-compiled.js +61 -30
  68. package/dist/packages/engine/compile/validate.js +26 -24
  69. package/dist/packages/engine/execution/lib/schema.d.ts +79 -33
  70. package/dist/packages/engine/execution/lib/schema.js +13 -5
  71. package/dist/packages/engine/index.d.ts +2 -2
  72. package/dist/packages/engine/index.js +1 -1
  73. package/dist/packages/engine/lib/schema.d.ts +551 -242
  74. package/dist/packages/engine/lib/schema.js +53 -17
  75. package/dist/packages/engine/native-run-handlers.js +15 -7
  76. package/dist/packages/engine/preparation-store.d.ts +6 -0
  77. package/dist/packages/engine/preparation-store.js +8 -0
  78. package/dist/packages/engine/routes.d.ts +6 -0
  79. package/dist/packages/engine/routes.js +6 -0
  80. package/dist/packages/engine/run-observability.js +1 -2
  81. package/dist/packages/engine/runtime-event-applier.js +7 -0
  82. package/dist/packages/engine/runtime-proposal-helpers.js +1 -1
  83. package/dist/packages/engine/runtime-resource-builders.d.ts +6 -6
  84. package/dist/packages/engine/runtime-resource-builders.js +5 -4
  85. package/dist/packages/engine/runtime.d.ts +67 -7
  86. package/dist/packages/engine/runtime.js +159 -29
  87. package/dist/packages/engine/server.d.ts +25 -0
  88. package/dist/packages/engine/server.js +62 -3
  89. package/dist/packages/engine/verify/index.d.ts +10 -10
  90. package/dist/packages/engine/verify/index.js +8 -8
  91. package/dist/packages/engine/verify/readiness-check-run.d.ts +27 -4
  92. package/dist/packages/engine/verify/readiness-check-run.js +92 -24
  93. package/dist/packages/engine/verify/{test-execution.d.ts → verify-execution.d.ts} +2 -2
  94. package/dist/packages/engine/verify/{test-execution.js → verify-execution.js} +2 -2
  95. package/dist/packages/engine/verify/{test-paths.d.ts → verify-paths.d.ts} +1 -1
  96. package/dist/packages/engine/verify/{test-sandbox.d.ts → verify-sandbox.d.ts} +1 -1
  97. package/dist/packages/engine/verify/{test-specs.d.ts → verify-specs.d.ts} +1 -1
  98. package/dist/packages/engine/verify/{test-specs.js → verify-specs.js} +1 -1
  99. package/dist/packages/engine/verify/{test-targets.d.ts → verify-targets.d.ts} +1 -1
  100. package/dist/packages/engine/verify/{test.d.ts → verify.d.ts} +4 -4
  101. package/dist/packages/engine/verify/{test.js → verify.js} +3 -3
  102. package/dist/packages/engine/wire-schemas.d.ts +545 -0
  103. package/dist/packages/engine/wire-schemas.js +59 -0
  104. package/dist/packages/methods/authoring/method-authoring.d.ts +2 -0
  105. package/dist/packages/methods/authoring/method-authoring.js +99 -18
  106. package/dist/packages/methods/authoring/method-edit-session.js +5 -5
  107. package/dist/packages/methods/authoring/method-improvement.js +1 -1
  108. package/dist/packages/methods/package/builtin-compiled-method.d.ts +12 -12
  109. package/dist/packages/methods/package/builtin-compiled-method.js +25 -22
  110. package/dist/packages/methods/package/context-interface.d.ts +39 -26
  111. package/dist/packages/methods/package/context-interface.js +48 -39
  112. package/dist/packages/methods/package/interf-method-package.js +28 -47
  113. package/dist/packages/methods/package/local-methods.d.ts +3 -4
  114. package/dist/packages/methods/package/local-methods.js +34 -62
  115. package/dist/packages/methods/package/method-definitions.d.ts +4 -6
  116. package/dist/packages/methods/package/method-definitions.js +0 -4
  117. package/dist/packages/methods/package/method-helpers.d.ts +0 -2
  118. package/dist/packages/methods/package/method-helpers.js +0 -4
  119. package/dist/packages/project/interf-scaffold.js +12 -12
  120. package/dist/packages/project/source-config.js +2 -1
  121. package/package.json +6 -16
  122. package/dist/packages/engine/compile/runtime-acceptance.d.ts +0 -9
  123. package/dist/packages/engine/compile/runtime-acceptance.js +0 -265
  124. /package/dist/compiler-ui/_next/static/{a3UiUF0DiMEbfWy_0gihg → 6qyE1u9m_oBUkvAhhoCmO}/_buildManifest.js +0 -0
  125. /package/dist/compiler-ui/_next/static/{a3UiUF0DiMEbfWy_0gihg → 6qyE1u9m_oBUkvAhhoCmO}/_clientMiddlewareManifest.js +0 -0
  126. /package/dist/compiler-ui/_next/static/{a3UiUF0DiMEbfWy_0gihg → 6qyE1u9m_oBUkvAhhoCmO}/_ssgManifest.js +0 -0
  127. /package/dist/packages/engine/verify/{test-paths.js → verify-paths.js} +0 -0
  128. /package/dist/packages/engine/verify/{test-profile-presets.d.ts → verify-profile-presets.d.ts} +0 -0
  129. /package/dist/packages/engine/verify/{test-profile-presets.js → verify-profile-presets.js} +0 -0
  130. /package/dist/packages/engine/verify/{test-sandbox.js → verify-sandbox.js} +0 -0
  131. /package/dist/packages/engine/verify/{test-targets.js → verify-targets.js} +0 -0
  132. /package/dist/packages/engine/verify/{test-types.d.ts → verify-types.d.ts} +0 -0
  133. /package/dist/packages/engine/verify/{test-types.js → verify-types.js} +0 -0
@@ -0,0 +1,84 @@
1
+ /**
2
+ * 0.17 — interface seams for the future cloud variant.
3
+ *
4
+ * These types document the injection points a cloud variant of the
5
+ * engine slots into without forking. The local binary keeps its
6
+ * in-process implementations (private `Map` fields on the runtime,
7
+ * the per-instance bearer-token check in `server.ts`); cloud variants
8
+ * provide their own implementations and pass them through
9
+ * `startLocalService` / `LocalServiceRuntimeOptions`.
10
+ *
11
+ * Each seam below is paired with a `TODO(cloud)` marker at the
12
+ * concrete call site so the cloud variant has a clear "wire this
13
+ * through" landing pad. Local default behavior is unchanged in 0.17.
14
+ */
15
+ // ───────────────────────────────────────────────────────────────────────────
16
+ // Local default implementations
17
+ //
18
+ // These wrap in-process Maps and satisfy the interfaces above so the
19
+ // runtime can inject either a local default (current behavior) or a
20
+ // cloud override (Redis-shaped store, shared lease, etc) without
21
+ // branching on the deployment.
22
+ // ───────────────────────────────────────────────────────────────────────────
23
+ export class InMemoryIdempotencyStore {
24
+ buckets = new Map();
25
+ get(scope, key) {
26
+ return this.buckets.get(scope)?.get(key) ?? null;
27
+ }
28
+ set(scope, key, value) {
29
+ let bucket = this.buckets.get(scope);
30
+ if (!bucket) {
31
+ bucket = new Map();
32
+ this.buckets.set(scope, bucket);
33
+ }
34
+ bucket.set(key, value);
35
+ }
36
+ delete(scope, key) {
37
+ const bucket = this.buckets.get(scope);
38
+ if (!bucket)
39
+ return;
40
+ bucket.delete(key);
41
+ if (bucket.size === 0)
42
+ this.buckets.delete(scope);
43
+ }
44
+ prune(now) {
45
+ for (const [scope, bucket] of this.buckets) {
46
+ for (const [key, value] of bucket) {
47
+ if (value.expiresAt < now)
48
+ bucket.delete(key);
49
+ }
50
+ if (bucket.size === 0)
51
+ this.buckets.delete(scope);
52
+ }
53
+ }
54
+ size() {
55
+ let total = 0;
56
+ for (const bucket of this.buckets.values())
57
+ total += bucket.size;
58
+ return total;
59
+ }
60
+ }
61
+ export class InMemoryRunLeaseStore {
62
+ leases = new Map();
63
+ acquire(runId, lease) {
64
+ this.leases.set(runId, lease);
65
+ }
66
+ release(runId) {
67
+ this.leases.delete(runId);
68
+ }
69
+ get(runId) {
70
+ return this.leases.get(runId) ?? null;
71
+ }
72
+ markCancelled(runId) {
73
+ const lease = this.leases.get(runId);
74
+ if (!lease)
75
+ return;
76
+ lease.cancelled = true;
77
+ lease.cancelledAt = new Date().toISOString();
78
+ }
79
+ *listActive() {
80
+ for (const [runId, lease] of this.leases) {
81
+ yield { runId, lease };
82
+ }
83
+ }
84
+ }
@@ -1 +1 @@
1
- export declare function countCompiledZoneArtifacts(compiledPath: string, zonePath: string, kind: "directory" | "file" | "runtime"): number;
1
+ export declare function countCompiledArtifactsAtPath(compiledPath: string, artifactPath: string, kind: "directory" | "file" | "runtime"): number;
@@ -1,6 +1,6 @@
1
1
  import { existsSync, readFileSync } from "node:fs";
2
2
  import { listFilesRecursive } from "../../contracts/utils/filesystem.js";
3
- import { compiledZoneAbsolutePath } from "./compiled-schema.js";
3
+ import { compiledArtifactAbsolutePath } from "./compiled-schema.js";
4
4
  const SCAFFOLD_PLACEHOLDER_SNIPPETS = [
5
5
  "Not yet compiled. Run `interf compile` to build the portable context.",
6
6
  "Not yet compiled. Run `interf compile` to build this portable context.",
@@ -16,8 +16,8 @@ function isScaffoldPlaceholderFile(filePath) {
16
16
  return false;
17
17
  }
18
18
  }
19
- export function countCompiledZoneArtifacts(compiledPath, zonePath, kind) {
20
- const absolutePath = compiledZoneAbsolutePath(compiledPath, { path: zonePath });
19
+ export function countCompiledArtifactsAtPath(compiledPath, artifactPath, kind) {
20
+ const absolutePath = compiledArtifactAbsolutePath(compiledPath, { path: artifactPath });
21
21
  if (!existsSync(absolutePath))
22
22
  return 0;
23
23
  if (kind === "file")
@@ -0,0 +1,41 @@
1
+ import type { ArtifactStatus } from "../../contracts/lib/schema.js";
2
+ import type { MethodDefinition } from "../../methods/package/method-definitions.js";
3
+ import type { StageRun } from "../execution/lib/schema.js";
4
+ /**
5
+ * 0.17 — compute per-Artifact status for a compile run.
6
+ *
7
+ * Walks the Method's declared `artifacts[]` and decides
8
+ * `ready | not_ready | failed | skipped` for each.
9
+ *
10
+ * Mapping rules:
11
+ * - **shape kind = "path"**: the artifact is `ready` when the declared
12
+ * path exists inside `compiledPath` with the declared artifact kind,
13
+ * `not_ready` otherwise. Future shape kinds (value, remote-handle,
14
+ * confirmation) slot in here.
15
+ * - **`built_by_stages`** is preserved from the Method declaration when
16
+ * present, otherwise inferred from stage `writes` that match the
17
+ * artifact's path.
18
+ * - **proofs** carries structured evidence from the shared check
19
+ * evaluator.
20
+ *
21
+ * Stage-failure short-circuit: if any stage has `status: "failed"`, all
22
+ * non-existent artifacts are marked `failed` instead of `not_ready` so
23
+ * the run record carries the real causal signal.
24
+ */
25
+ export declare function computeArtifactStatuses(options: {
26
+ method: Pick<MethodDefinition<string>, "stages" | "contextInterface" | "schema">;
27
+ compiledPath: string;
28
+ stageRuns: StageRun[];
29
+ /**
30
+ * Optional runtime counts (e.g. `source_total`) passed to checks
31
+ * that compare against source. Threaded through from the compile
32
+ * runtime; absent for ad-hoc evaluations.
33
+ */
34
+ counts?: Record<string, number>;
35
+ }): ArtifactStatus[];
36
+ /**
37
+ * Aggregate verdict: any artifact in `not_ready | failed | skipped`
38
+ * makes the preparation `not_ready`. Used by the readiness state view
39
+ * once Phase D lights up the per-artifact UI.
40
+ */
41
+ export declare function aggregateArtifactVerdict(statuses: readonly ArtifactStatus[]): "ready" | "not_ready";
@@ -0,0 +1,166 @@
1
+ import { existsSync, statSync } from "node:fs";
2
+ import { resolve } from "node:path";
3
+ import { evaluateChecks } from "./check-evaluator.js";
4
+ /**
5
+ * 0.17 — compute per-Artifact status for a compile run.
6
+ *
7
+ * Walks the Method's declared `artifacts[]` and decides
8
+ * `ready | not_ready | failed | skipped` for each.
9
+ *
10
+ * Mapping rules:
11
+ * - **shape kind = "path"**: the artifact is `ready` when the declared
12
+ * path exists inside `compiledPath` with the declared artifact kind,
13
+ * `not_ready` otherwise. Future shape kinds (value, remote-handle,
14
+ * confirmation) slot in here.
15
+ * - **`built_by_stages`** is preserved from the Method declaration when
16
+ * present, otherwise inferred from stage `writes` that match the
17
+ * artifact's path.
18
+ * - **proofs** carries structured evidence from the shared check
19
+ * evaluator.
20
+ *
21
+ * Stage-failure short-circuit: if any stage has `status: "failed"`, all
22
+ * non-existent artifacts are marked `failed` instead of `not_ready` so
23
+ * the run record carries the real causal signal.
24
+ */
25
+ export function computeArtifactStatuses(options) {
26
+ const schema = pickContextInterface(options.method);
27
+ const artifacts = schema?.artifacts ?? [];
28
+ if (artifacts.length === 0)
29
+ return [];
30
+ const stageWriteIndex = buildStageWriteIndex(options.method.stages);
31
+ const anyStageFailed = options.stageRuns.some((stage) => stage.status === "failed");
32
+ return artifacts.map((artifact) => buildArtifactStatus({
33
+ artifact,
34
+ compiledPath: options.compiledPath,
35
+ stageWriteIndex,
36
+ anyStageFailed,
37
+ counts: options.counts,
38
+ }));
39
+ }
40
+ function pickContextInterface(method) {
41
+ return method.contextInterface ?? method.schema;
42
+ }
43
+ function buildStageWriteIndex(stages) {
44
+ const index = new Map();
45
+ for (const stage of stages) {
46
+ for (const write of stage.writes ?? []) {
47
+ const owners = index.get(write) ?? [];
48
+ if (!owners.includes(stage.id))
49
+ owners.push(stage.id);
50
+ index.set(write, owners);
51
+ }
52
+ }
53
+ return index;
54
+ }
55
+ function buildArtifactStatus(options) {
56
+ const { artifact, compiledPath, stageWriteIndex, anyStageFailed, counts } = options;
57
+ const builtBy = artifact.built_by_stages.length > 0
58
+ ? artifact.built_by_stages
59
+ : inferBuiltByStages(artifact, stageWriteIndex);
60
+ const shapeStatus = resolveStatusValue({
61
+ artifact,
62
+ compiledPath,
63
+ anyStageFailed,
64
+ });
65
+ // Run the locked CheckKind evaluator against artifact.checks. Proofs
66
+ // are surfaced for each declared check; if any required check fails,
67
+ // the artifact's status is forced to failed (or not_ready if the
68
+ // shape itself isn't built yet).
69
+ const targetPath = artifact.shape.kind === "path" ? artifact.shape.path : undefined;
70
+ // `artifact.checks` is `default([])` in the schema, but raw objects
71
+ // (test fixtures, hand-edited Methods loaded without parsing) may
72
+ // omit the field entirely.
73
+ const declaredChecks = artifact.checks ?? [];
74
+ const checkResult = declaredChecks.length > 0
75
+ ? evaluateChecks(declaredChecks, {
76
+ rootPath: compiledPath,
77
+ targetPath,
78
+ counts,
79
+ })
80
+ : { proofs: [], ready: true, failures: [] };
81
+ const status = (() => {
82
+ if (shapeStatus !== "ready")
83
+ return shapeStatus;
84
+ if (checkResult.failures.length > 0)
85
+ return "failed";
86
+ return "ready";
87
+ })();
88
+ return {
89
+ artifact_id: artifact.id,
90
+ status,
91
+ built_by_stages: builtBy,
92
+ proofs: checkResult.proofs,
93
+ ...(buildSummary(artifact, status, checkResult.failures.length)),
94
+ };
95
+ }
96
+ function buildSummary(artifact, status, failedRequiredCount) {
97
+ if (status === "ready")
98
+ return { summary: `Artifact ${artifact.id} is ready.` };
99
+ if (status === "failed") {
100
+ if (failedRequiredCount > 0) {
101
+ return { summary: `Artifact ${artifact.id}: ${failedRequiredCount} required check(s) failed.` };
102
+ }
103
+ return { summary: `Artifact ${artifact.id} did not produce ${describeShape(artifact)}.` };
104
+ }
105
+ if (status === "not_ready")
106
+ return { summary: `Artifact ${artifact.id} has not been produced yet.` };
107
+ return { summary: `Artifact ${artifact.id} was skipped.` };
108
+ }
109
+ function inferBuiltByStages(artifact, stageWriteIndex) {
110
+ if (artifact.shape.kind !== "path")
111
+ return [];
112
+ const directOwners = stageWriteIndex.get(artifact.id);
113
+ if (directOwners && directOwners.length > 0)
114
+ return directOwners;
115
+ const pathOwners = stageWriteIndex.get(artifact.shape.path);
116
+ return pathOwners ?? [];
117
+ }
118
+ function resolveStatusValue(options) {
119
+ const { artifact, compiledPath, anyStageFailed } = options;
120
+ if (artifact.shape.kind !== "path")
121
+ return "skipped";
122
+ const compiledRoot = resolve(compiledPath);
123
+ const absolutePath = resolve(compiledRoot, artifact.shape.path);
124
+ // Defense in depth: the schema-level `isInterfRelativePath` refine
125
+ // already rejects `..` and absolute paths in `ArtifactPathShape.path`,
126
+ // but Method packages can land on disk before the schema validates
127
+ // (hand-edited drafts can still bypass normal package validation).
128
+ // Reject any resolved path that escapes the portable-context root.
129
+ if (absolutePath !== compiledRoot && !absolutePath.startsWith(`${compiledRoot}/`)) {
130
+ return "failed";
131
+ }
132
+ if (!existsSync(absolutePath)) {
133
+ return anyStageFailed ? "failed" : "not_ready";
134
+ }
135
+ try {
136
+ const info = statSync(absolutePath);
137
+ // For directory artifacts, ready means the directory exists; the
138
+ // directory may be empty during early stages, but content-shape
139
+ // checks live in artifact `checks[]`, not here. For file artifacts,
140
+ // the file must have non-zero bytes —
141
+ // an empty placeholder is not_ready.
142
+ if (artifact.shape.artifact_kind === "directory" && info.isDirectory())
143
+ return "ready";
144
+ if (artifact.shape.artifact_kind === "file" && info.isFile() && info.size > 0)
145
+ return "ready";
146
+ return anyStageFailed ? "failed" : "not_ready";
147
+ }
148
+ catch {
149
+ return anyStageFailed ? "failed" : "not_ready";
150
+ }
151
+ }
152
+ function describeShape(artifact) {
153
+ if (artifact.shape.kind === "path")
154
+ return `\`${artifact.shape.path}\``;
155
+ return `(${artifact.shape.kind})`;
156
+ }
157
+ /**
158
+ * Aggregate verdict: any artifact in `not_ready | failed | skipped`
159
+ * makes the preparation `not_ready`. Used by the readiness state view
160
+ * once Phase D lights up the per-artifact UI.
161
+ */
162
+ export function aggregateArtifactVerdict(statuses) {
163
+ if (statuses.length === 0)
164
+ return "not_ready";
165
+ return statuses.every((status) => status.status === "ready") ? "ready" : "not_ready";
166
+ }
@@ -0,0 +1,89 @@
1
+ import { z } from "zod";
2
+ import type { ArtifactStatus } from "../../contracts/lib/schema.js";
3
+ /**
4
+ * 0.17 — per-Artifact billing event record.
5
+ *
6
+ * Emitted once per Artifact each time a compile run produces it.
7
+ * `account_id` is `null` for loopback (no auth); the cloud variant
8
+ * fills it from the `tokenValidator` (B4.3) result.
9
+ *
10
+ * `event_kind`:
11
+ * - `fresh` — first-time build of this Artifact in this run
12
+ * - `resync` — incremental rebuild (deferred to 0.18+; not emitted in 0.17)
13
+ */
14
+ export declare const BillingEventKindSchema: z.ZodEnum<{
15
+ fresh: "fresh";
16
+ resync: "resync";
17
+ }>;
18
+ export declare const CompilationEventSchema: z.ZodObject<{
19
+ kind: z.ZodLiteral<"interf-compilation-event">;
20
+ version: z.ZodLiteral<1>;
21
+ timestamp: z.ZodString;
22
+ run_id: z.ZodString;
23
+ preparation: z.ZodString;
24
+ artifact_id: z.ZodString;
25
+ method_id: z.ZodString;
26
+ account_id: z.ZodNullable<z.ZodString>;
27
+ event_kind: z.ZodEnum<{
28
+ fresh: "fresh";
29
+ resync: "resync";
30
+ }>;
31
+ size_class: z.ZodOptional<z.ZodEnum<{
32
+ small: "small";
33
+ medium: "medium";
34
+ large: "large";
35
+ }>>;
36
+ duration_ms: z.ZodOptional<z.ZodNumber>;
37
+ }, z.core.$strict>;
38
+ export type CompilationEvent = z.infer<typeof CompilationEventSchema>;
39
+ export type BillingEventKind = z.infer<typeof BillingEventKindSchema>;
40
+ /**
41
+ * Sink for billing events.
42
+ *
43
+ * **STUB FOR 0.17 — JSONL local default.** Production sink (Metronome
44
+ * HTTP) wires in 0.18+ once the Stripe + Metronome accounts are
45
+ * provisioned. The `<prep>/runs/<run-id>/billing-events.jsonl` file is
46
+ * an **observability / dev fixture, NOT production billing data**.
47
+ * Future readers must not treat it as authoritative — Stripe Billing
48
+ * holds the books once 0.18 ships the HTTP sink.
49
+ *
50
+ * Cloud variants inject a remote sink via `startLocalService` options
51
+ * (paired with the `BillingEventSink` injection point in B4-style
52
+ * dependency injection); the engine treats either implementation
53
+ * identically.
54
+ */
55
+ export interface BillingEventSink {
56
+ emit(event: CompilationEvent): void;
57
+ }
58
+ export declare class JsonlBillingEventSink implements BillingEventSink {
59
+ private readonly logPath;
60
+ constructor(logPath: string);
61
+ emit(event: CompilationEvent): void;
62
+ }
63
+ /**
64
+ * Default sink path for a run. Each compile run gets its own JSONL
65
+ * file alongside its other on-disk artifacts.
66
+ */
67
+ export declare function defaultBillingEventLogPath(options: {
68
+ preparationDataDir: string;
69
+ preparationName: string;
70
+ runId: string;
71
+ }): string;
72
+ /**
73
+ * Convert a list of per-Artifact statuses into compilation events for
74
+ * the run. Only `ready` and `failed` artifacts emit events — `skipped`
75
+ * and `not_ready` represent work that didn't happen and shouldn't bill.
76
+ *
77
+ * 0.17 ships `event_kind: "fresh"` only. The resync optimization that
78
+ * differentiates cached-vs-rebuilt artifacts lands in 0.18+.
79
+ */
80
+ export declare function buildCompilationEventsForRun(options: {
81
+ runId: string;
82
+ preparation: string;
83
+ methodId: string;
84
+ accountId: string | null;
85
+ artifacts: readonly ArtifactStatus[];
86
+ startedAt?: string | null;
87
+ finishedAt?: string | null;
88
+ timestamp?: string;
89
+ }): CompilationEvent[];
@@ -0,0 +1,74 @@
1
+ import { appendFileSync, mkdirSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { z } from "zod";
4
+ /**
5
+ * 0.17 — per-Artifact billing event record.
6
+ *
7
+ * Emitted once per Artifact each time a compile run produces it.
8
+ * `account_id` is `null` for loopback (no auth); the cloud variant
9
+ * fills it from the `tokenValidator` (B4.3) result.
10
+ *
11
+ * `event_kind`:
12
+ * - `fresh` — first-time build of this Artifact in this run
13
+ * - `resync` — incremental rebuild (deferred to 0.18+; not emitted in 0.17)
14
+ */
15
+ export const BillingEventKindSchema = z.enum(["fresh", "resync"]);
16
+ export const CompilationEventSchema = z.object({
17
+ kind: z.literal("interf-compilation-event"),
18
+ version: z.literal(1),
19
+ timestamp: z.string().min(1),
20
+ run_id: z.string().min(1),
21
+ preparation: z.string().min(1),
22
+ artifact_id: z.string().min(1),
23
+ method_id: z.string().min(1),
24
+ account_id: z.string().min(1).nullable(),
25
+ event_kind: BillingEventKindSchema,
26
+ size_class: z.enum(["small", "medium", "large"]).optional(),
27
+ duration_ms: z.number().nonnegative().optional(),
28
+ }).strict();
29
+ export class JsonlBillingEventSink {
30
+ logPath;
31
+ constructor(logPath) {
32
+ this.logPath = logPath;
33
+ }
34
+ emit(event) {
35
+ const validated = CompilationEventSchema.parse(event);
36
+ mkdirSync(dirname(this.logPath), { recursive: true });
37
+ appendFileSync(this.logPath, `${JSON.stringify(validated)}\n`);
38
+ }
39
+ }
40
+ /**
41
+ * Default sink path for a run. Each compile run gets its own JSONL
42
+ * file alongside its other on-disk artifacts.
43
+ */
44
+ export function defaultBillingEventLogPath(options) {
45
+ return join(options.preparationDataDir, options.preparationName, "runs", options.runId, "billing-events.jsonl");
46
+ }
47
+ /**
48
+ * Convert a list of per-Artifact statuses into compilation events for
49
+ * the run. Only `ready` and `failed` artifacts emit events — `skipped`
50
+ * and `not_ready` represent work that didn't happen and shouldn't bill.
51
+ *
52
+ * 0.17 ships `event_kind: "fresh"` only. The resync optimization that
53
+ * differentiates cached-vs-rebuilt artifacts lands in 0.18+.
54
+ */
55
+ export function buildCompilationEventsForRun(options) {
56
+ const timestamp = options.timestamp ?? new Date().toISOString();
57
+ const durationMs = options.startedAt && options.finishedAt
58
+ ? Math.max(0, new Date(options.finishedAt).getTime() - new Date(options.startedAt).getTime())
59
+ : undefined;
60
+ return options.artifacts
61
+ .filter((status) => status.status === "ready" || status.status === "failed")
62
+ .map((status) => ({
63
+ kind: "interf-compilation-event",
64
+ version: 1,
65
+ timestamp,
66
+ run_id: options.runId,
67
+ preparation: options.preparation,
68
+ artifact_id: status.artifact_id,
69
+ method_id: options.methodId,
70
+ account_id: options.accountId,
71
+ event_kind: "fresh",
72
+ ...(durationMs !== undefined ? { duration_ms: durationMs } : {}),
73
+ }));
74
+ }
@@ -0,0 +1,66 @@
1
+ import { type Check, type CheckKind, type Proof } from "../../contracts/lib/schema.js";
2
+ /**
3
+ * 0.17 — Check evaluator for the locked verification vocabulary.
4
+ *
5
+ * One evaluator per `CheckKind` from `CHECK_KINDS`. The evaluator is
6
+ * scope-agnostic: it takes a Check, a target path, and optional
7
+ * runtime context (counts, source-file totals); it returns a Proof.
8
+ *
9
+ * The same evaluator serves stage-level checks, artifact-level checks,
10
+ * and (for `qa_match`) user-level checks. Methods and user-defined
11
+ * verification declare `Check[]`; the runtime invokes this evaluator
12
+ * to produce `Proof[]`.
13
+ *
14
+ * This evaluator is the source of truth for declared verification
15
+ * checks. Legacy stage-acceptance rules were retired after the
16
+ * artifact-first migration.
17
+ */
18
+ export interface CheckEvaluationContext {
19
+ /**
20
+ * Filesystem root the check evaluates against. For artifact checks
21
+ * this is the portable-context root; the artifact's path is
22
+ * resolved relative to it. For stage checks this can be the same
23
+ * root or a stage-output sub-directory.
24
+ */
25
+ rootPath: string;
26
+ /**
27
+ * Optional: the path the check targets. For artifact-scoped checks
28
+ * this is the artifact's `shape.path`; for stage-scoped checks
29
+ * this is the stage's writes path. Some kinds (qa_match) ignore
30
+ * targetPath because they operate on agent answers, not files.
31
+ */
32
+ targetPath?: string;
33
+ /**
34
+ * Optional runtime-derived counts used by `min_file_count_matches_source`
35
+ * and similar rules. `source_total` is the canonical key for "how
36
+ * many source files were processed." Methods reference it in check
37
+ * params via `{ match: "source_total" }`.
38
+ */
39
+ counts?: Record<string, number>;
40
+ /**
41
+ * Optional: the agent's answer for a `qa_match` check. Provided by
42
+ * the verify-run flow, not relevant for compile-time evaluation.
43
+ */
44
+ agentAnswer?: string;
45
+ }
46
+ export type CheckEvaluator = (check: Check, context: CheckEvaluationContext) => Proof;
47
+ /**
48
+ * Evaluate a single Check against a context, returning a Proof.
49
+ */
50
+ export declare function evaluateCheck(check: Check, context: CheckEvaluationContext): Proof;
51
+ /**
52
+ * Evaluate a list of checks. Aggregate ready/not_ready verdict over
53
+ * the proofs: `ready` if every required check passed, otherwise
54
+ * `not_ready`. Soft checks (required: false) that fail produce a
55
+ * proof but don't change the verdict.
56
+ */
57
+ export declare function evaluateChecks(checks: readonly Check[], context: CheckEvaluationContext): {
58
+ proofs: Proof[];
59
+ ready: boolean;
60
+ failures: Proof[];
61
+ };
62
+ /**
63
+ * Type guard for the canonical CheckKinds. Useful at parse boundaries
64
+ * where a string came from on-disk JSON.
65
+ */
66
+ export declare function isCheckKind(value: unknown): value is CheckKind;