@interf/compiler 0.16.0 → 0.21.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 (203) hide show
  1. package/LICENSE.md +1 -0
  2. package/README.md +90 -73
  3. package/TRADEMARKS.md +4 -4
  4. package/dist/cli/commands/mcp.d.ts +0 -34
  5. package/dist/cli/commands/mcp.js +246 -45
  6. package/dist/cli/commands/method.js +261 -15
  7. package/dist/cli/commands/prep.js +116 -15
  8. package/dist/cli/commands/runs.js +103 -9
  9. package/dist/cli/commands/status.js +4 -2
  10. package/dist/cli/commands/test.d.ts +10 -0
  11. package/dist/cli/commands/{verify.js → test.js} +24 -17
  12. package/dist/cli/commands/web.js +82 -8
  13. package/dist/cli/commands/wizard.js +158 -51
  14. package/dist/cli/index.d.ts +2 -2
  15. package/dist/cli/index.js +3 -3
  16. package/dist/compiler-ui/404.html +1 -1
  17. package/dist/compiler-ui/__next.__PAGE__.txt +5 -5
  18. package/dist/compiler-ui/__next._full.txt +13 -12
  19. package/dist/compiler-ui/__next._head.txt +3 -3
  20. package/dist/compiler-ui/__next._index.txt +5 -4
  21. package/dist/compiler-ui/__next._tree.txt +4 -3
  22. package/dist/compiler-ui/_next/static/chunks/01646j7yi.w5a.css +1 -0
  23. package/dist/compiler-ui/_next/static/chunks/{0n51hrfoufc7g.js → 02f_.8.ebn556.js} +1 -1
  24. package/dist/compiler-ui/_next/static/chunks/02r7siaw-_p5w.js +1 -0
  25. package/dist/compiler-ui/_next/static/chunks/{08m7vf5asqlsm.js → 04d0ly-7xb~-j.js} +10 -10
  26. package/dist/compiler-ui/_next/static/chunks/0fhs9psnxqd8s.js +1 -0
  27. package/dist/compiler-ui/_next/static/chunks/0mssmhpbifj15.css +2 -0
  28. package/dist/compiler-ui/_next/static/chunks/0nypu~ddwxari.js +116 -0
  29. package/dist/compiler-ui/_next/static/chunks/0p3s8iyhgcww2.js +31 -0
  30. package/dist/compiler-ui/_next/static/chunks/0tjf-vu_rz8s0.css +1 -0
  31. package/dist/compiler-ui/_next/static/chunks/0u6p3fpbbfgtl.js +1 -0
  32. package/dist/compiler-ui/_next/static/chunks/0wpx5..8dnh0w.js +1 -0
  33. package/dist/compiler-ui/_next/static/chunks/0y0uj160p0ts~.js +1 -0
  34. package/dist/compiler-ui/_next/static/chunks/10t8l~_oenf.c.js +1 -0
  35. package/dist/compiler-ui/_next/static/chunks/13gz9e7z~imx1.js +5 -0
  36. package/dist/compiler-ui/_next/static/chunks/156xed-b6czaw.js +1 -0
  37. package/dist/compiler-ui/_next/static/chunks/{turbopack-0.uq1k8c0j4s..js → turbopack-02-3e_c-yz~5g.js} +1 -1
  38. package/dist/compiler-ui/_next/static/chunks/{turbopack-10e~t1yzi4svj.js → turbopack-0apv8vb-nczuy.js} +1 -1
  39. package/dist/compiler-ui/_not-found/__next._full.txt +10 -9
  40. package/dist/compiler-ui/_not-found/__next._head.txt +3 -3
  41. package/dist/compiler-ui/_not-found/__next._index.txt +5 -4
  42. package/dist/compiler-ui/_not-found/__next._not-found.__PAGE__.txt +2 -2
  43. package/dist/compiler-ui/_not-found/__next._not-found.txt +3 -3
  44. package/dist/compiler-ui/_not-found/__next._tree.txt +3 -2
  45. package/dist/compiler-ui/_not-found.html +1 -1
  46. package/dist/compiler-ui/_not-found.txt +10 -9
  47. package/dist/compiler-ui/index.html +1 -1
  48. package/dist/compiler-ui/index.txt +13 -12
  49. package/dist/packages/contracts/index.d.ts +2 -2
  50. package/dist/packages/contracts/index.js +1 -1
  51. package/dist/packages/contracts/lib/schema.d.ts +275 -72
  52. package/dist/packages/contracts/lib/schema.js +244 -83
  53. package/dist/packages/engine/action-definitions.d.ts +174 -13
  54. package/dist/packages/engine/action-definitions.js +125 -122
  55. package/dist/packages/engine/action-planner.js +4 -11
  56. package/dist/packages/engine/agents/lib/shells.d.ts +15 -5
  57. package/dist/packages/engine/agents/lib/shells.js +134 -123
  58. package/dist/packages/engine/agents/role-executors.js +1 -1
  59. package/dist/packages/engine/cloud-seams.d.ts +115 -0
  60. package/dist/packages/engine/cloud-seams.js +84 -0
  61. package/dist/packages/engine/compile/artifact-counts.d.ts +1 -1
  62. package/dist/packages/engine/compile/artifact-counts.js +3 -3
  63. package/dist/packages/engine/compile/artifact-status.d.ts +41 -0
  64. package/dist/packages/engine/compile/artifact-status.js +166 -0
  65. package/dist/packages/engine/compile/billing-events.d.ts +89 -0
  66. package/dist/packages/engine/compile/billing-events.js +74 -0
  67. package/dist/packages/engine/compile/check-evaluator.d.ts +66 -0
  68. package/dist/packages/engine/compile/check-evaluator.js +298 -0
  69. package/dist/packages/engine/compile/compiled-paths.js +6 -6
  70. package/dist/packages/engine/compile/compiled-schema.d.ts +7 -17
  71. package/dist/packages/engine/compile/compiled-schema.js +55 -70
  72. package/dist/packages/engine/compile/compiled-stage-plan.d.ts +1 -0
  73. package/dist/packages/engine/compile/compiled-stage-plan.js +32 -15
  74. package/dist/packages/engine/compile/compiled-stage-runner.js +1 -1
  75. package/dist/packages/engine/compile/index.d.ts +0 -1
  76. package/dist/packages/engine/compile/index.js +0 -1
  77. package/dist/packages/engine/compile/lib/schema.d.ts +111 -92
  78. package/dist/packages/engine/compile/lib/schema.js +35 -39
  79. package/dist/packages/engine/compile/method-primitives.d.ts +2 -2
  80. package/dist/packages/engine/compile/method-primitives.js +1 -1
  81. package/dist/packages/engine/compile/reset.js +4 -4
  82. package/dist/packages/engine/compile/runtime-contracts.js +2 -1
  83. package/dist/packages/engine/compile/runtime-prompt.js +3 -2
  84. package/dist/packages/engine/compile/runtime-reconcile.js +35 -35
  85. package/dist/packages/engine/compile/runtime-runs.js +0 -1
  86. package/dist/packages/engine/compile/runtime-types.d.ts +7 -8
  87. package/dist/packages/engine/compile/runtime.d.ts +1 -2
  88. package/dist/packages/engine/compile/runtime.js +0 -1
  89. package/dist/packages/engine/compile/state-health.js +6 -6
  90. package/dist/packages/engine/compile/state-view.js +7 -6
  91. package/dist/packages/engine/compile/validate-compiled.js +61 -30
  92. package/dist/packages/engine/compile/validate.js +26 -24
  93. package/dist/packages/engine/connection-config.js +1 -1
  94. package/dist/packages/engine/execution/lib/schema.d.ts +89 -33
  95. package/dist/packages/engine/execution/lib/schema.js +13 -5
  96. package/dist/packages/engine/index.d.ts +2 -2
  97. package/dist/packages/engine/index.js +1 -1
  98. package/dist/packages/engine/instance-paths.d.ts +15 -9
  99. package/dist/packages/engine/instance-paths.js +15 -9
  100. package/dist/packages/engine/lib/schema.d.ts +1316 -351
  101. package/dist/packages/engine/lib/schema.js +99 -36
  102. package/dist/packages/engine/native-run-handlers.js +25 -15
  103. package/dist/packages/engine/preparation-store.d.ts +9 -7
  104. package/dist/packages/engine/preparation-store.js +20 -0
  105. package/dist/packages/engine/requested-artifacts.d.ts +5 -0
  106. package/dist/packages/engine/requested-artifacts.js +36 -0
  107. package/dist/packages/engine/routes.d.ts +7 -1
  108. package/dist/packages/engine/routes.js +7 -1
  109. package/dist/packages/engine/run-observability.js +4 -4
  110. package/dist/packages/engine/runtime-event-applier.js +7 -0
  111. package/dist/packages/engine/runtime-proposal-helpers.d.ts +2 -2
  112. package/dist/packages/engine/runtime-proposal-helpers.js +6 -8
  113. package/dist/packages/engine/runtime-resource-builders.d.ts +11 -6
  114. package/dist/packages/engine/runtime-resource-builders.js +18 -6
  115. package/dist/packages/engine/runtime.d.ts +70 -8
  116. package/dist/packages/engine/runtime.js +304 -49
  117. package/dist/packages/engine/server.d.ts +25 -0
  118. package/dist/packages/engine/server.js +161 -50
  119. package/dist/packages/engine/verify/index.d.ts +10 -10
  120. package/dist/packages/engine/verify/index.js +8 -8
  121. package/dist/packages/engine/verify/readiness-check-run.d.ts +27 -4
  122. package/dist/packages/engine/verify/readiness-check-run.js +92 -24
  123. package/dist/packages/engine/verify/{test-execution.d.ts → verify-execution.d.ts} +2 -2
  124. package/dist/packages/engine/verify/{test-execution.js → verify-execution.js} +3 -3
  125. package/dist/packages/engine/verify/{test-paths.d.ts → verify-paths.d.ts} +1 -1
  126. package/dist/packages/engine/verify/{test-sandbox.d.ts → verify-sandbox.d.ts} +1 -1
  127. package/dist/packages/engine/verify/{test-specs.d.ts → verify-specs.d.ts} +1 -1
  128. package/dist/packages/engine/verify/{test-specs.js → verify-specs.js} +1 -1
  129. package/dist/packages/engine/verify/{test-targets.d.ts → verify-targets.d.ts} +1 -1
  130. package/dist/packages/engine/verify/{test.d.ts → verify.d.ts} +4 -4
  131. package/dist/packages/engine/verify/{test.js → verify.js} +3 -3
  132. package/dist/packages/engine/wire-schemas.d.ts +549 -0
  133. package/dist/packages/engine/wire-schemas.js +59 -0
  134. package/dist/packages/methods/authoring/method-authoring.d.ts +5 -1
  135. package/dist/packages/methods/authoring/method-authoring.js +68 -18
  136. package/dist/packages/methods/authoring/method-edit-session.js +5 -5
  137. package/dist/packages/methods/authoring/method-improvement.js +1 -1
  138. package/dist/packages/methods/package/builtin-compiled-method.d.ts +12 -12
  139. package/dist/packages/methods/package/builtin-compiled-method.js +26 -23
  140. package/dist/packages/methods/package/context-interface.d.ts +39 -26
  141. package/dist/packages/methods/package/context-interface.js +48 -39
  142. package/dist/packages/methods/package/interf-method-package.js +28 -47
  143. package/dist/packages/methods/package/local-methods.d.ts +4 -4
  144. package/dist/packages/methods/package/local-methods.js +53 -66
  145. package/dist/packages/methods/package/method-definitions.d.ts +4 -6
  146. package/dist/packages/methods/package/method-definitions.js +1 -5
  147. package/dist/packages/methods/package/method-helpers.d.ts +0 -2
  148. package/dist/packages/methods/package/method-helpers.js +0 -4
  149. package/dist/packages/project/interf-detect.js +6 -6
  150. package/dist/packages/project/interf-scaffold.js +12 -12
  151. package/dist/packages/project/lib/schema.d.ts +193 -0
  152. package/dist/packages/project/lib/schema.js +46 -1
  153. package/dist/packages/project/source-config.js +6 -1
  154. package/dist/packages/project/source-folders.js +1 -1
  155. package/package.json +12 -23
  156. package/public-repo/CONTRIBUTING.md +47 -0
  157. package/public-repo/LICENSE.md +1 -0
  158. package/public-repo/README.md +325 -0
  159. package/public-repo/SECURITY.md +67 -0
  160. package/public-repo/TRADEMARKS.md +8 -0
  161. package/{builtin-methods → public-repo/methods}/interf-default/README.md +10 -7
  162. package/{builtin-methods → public-repo/methods}/interf-default/compile/stages/shape/SKILL.md +4 -8
  163. package/{builtin-methods → public-repo/methods}/interf-default/method.json +8 -69
  164. package/public-repo/methods/interf-default/method.schema.json +75 -0
  165. package/public-repo/methods/interf-default/use/query/SKILL.md +23 -0
  166. package/public-repo/plugins/README.md +9 -0
  167. package/public-repo/plugins/interf/.claude-plugin/plugin.json +21 -0
  168. package/public-repo/plugins/interf/.mcp.json +12 -0
  169. package/public-repo/plugins/interf/README.md +29 -0
  170. package/public-repo/plugins/interf/skills/interf/SKILL.md +477 -0
  171. package/public-repo/skills/interf/SKILL.md +477 -0
  172. package/agent-skills/interf-actions/SKILL.md +0 -185
  173. package/agent-skills/interf-actions/references/cli.md +0 -243
  174. package/builtin-methods/interf-default/method.schema.json +0 -73
  175. package/builtin-methods/interf-default/use/query/SKILL.md +0 -28
  176. package/dist/cli/commands/verify.d.ts +0 -8
  177. package/dist/compiler-ui/_next/static/chunks/06yhdspx~ca5-.js +0 -5
  178. package/dist/compiler-ui/_next/static/chunks/06z~l3kwb891e.js +0 -1
  179. package/dist/compiler-ui/_next/static/chunks/08g7lvje.te.u.js +0 -1
  180. package/dist/compiler-ui/_next/static/chunks/0_i-3_5l9t2qe.js +0 -1
  181. package/dist/compiler-ui/_next/static/chunks/0b-ywny_j0g~0.js +0 -1
  182. package/dist/compiler-ui/_next/static/chunks/0b52v41o1gixx.js +0 -1
  183. package/dist/compiler-ui/_next/static/chunks/0gpzgsv0w.q~m.js +0 -31
  184. package/dist/compiler-ui/_next/static/chunks/0ilwfezfvu6~-.js +0 -1
  185. package/dist/compiler-ui/_next/static/chunks/0jipmpez3_ehh.js +0 -89
  186. package/dist/compiler-ui/_next/static/chunks/0xxmf45eskdt~.css +0 -1
  187. package/dist/compiler-ui/_next/static/chunks/13awzu4tooflw.css +0 -3
  188. package/dist/compiler-ui/_next/static/chunks/14wtz~vq25~qq.js +0 -1
  189. package/dist/packages/engine/compile/runtime-acceptance.d.ts +0 -9
  190. package/dist/packages/engine/compile/runtime-acceptance.js +0 -265
  191. /package/dist/compiler-ui/_next/static/{a3UiUF0DiMEbfWy_0gihg → tYHMLL9oKds1yDoNYgkPV}/_buildManifest.js +0 -0
  192. /package/dist/compiler-ui/_next/static/{a3UiUF0DiMEbfWy_0gihg → tYHMLL9oKds1yDoNYgkPV}/_clientMiddlewareManifest.js +0 -0
  193. /package/dist/compiler-ui/_next/static/{a3UiUF0DiMEbfWy_0gihg → tYHMLL9oKds1yDoNYgkPV}/_ssgManifest.js +0 -0
  194. /package/dist/packages/engine/verify/{test-paths.js → verify-paths.js} +0 -0
  195. /package/dist/packages/engine/verify/{test-profile-presets.d.ts → verify-profile-presets.d.ts} +0 -0
  196. /package/dist/packages/engine/verify/{test-profile-presets.js → verify-profile-presets.js} +0 -0
  197. /package/dist/packages/engine/verify/{test-sandbox.js → verify-sandbox.js} +0 -0
  198. /package/dist/packages/engine/verify/{test-targets.js → verify-targets.js} +0 -0
  199. /package/dist/packages/engine/verify/{test-types.d.ts → verify-types.d.ts} +0 -0
  200. /package/dist/packages/engine/verify/{test-types.js → verify-types.js} +0 -0
  201. /package/{builtin-methods → public-repo/methods}/interf-default/compile/stages/structure/SKILL.md +0 -0
  202. /package/{builtin-methods → public-repo/methods}/interf-default/compile/stages/summarize/SKILL.md +0 -0
  203. /package/{builtin-methods → public-repo/methods}/interf-default/improve/SKILL.md +0 -0
@@ -2,6 +2,7 @@
2
2
  * `interf method` — manage methods on the connected instance.
3
3
  *
4
4
  * interf method ls # list methods (instance-wide)
5
+ * interf method show <method-id> # show a Build Plan summary
5
6
  * interf method install <path> # install a method package
6
7
  * interf method draft <prep-id> # start a method-authoring run
7
8
  * interf method improve <prep-id> # start a method-improvement run
@@ -9,6 +10,10 @@
9
10
  import chalk from "chalk";
10
11
  import { resolve } from "node:path";
11
12
  import { CONNECT_OR_ERROR_HINT, readActiveConnection } from "../../packages/engine/connection-config.js";
13
+ import { methodResourcePath, preparationResourcePath, preparationSubresourcePath, } from "../../packages/engine/routes.js";
14
+ import { MethodAuthoringArtifactRequirementSchema, } from "../../packages/engine/lib/schema.js";
15
+ import { artifactRequirementsFromRequestedArtifacts, formatRequestedArtifactsForPrompt, } from "../../packages/engine/requested-artifacts.js";
16
+ import { slugify } from "../../packages/contracts/utils/naming.js";
12
17
  function resolveConnection(args) {
13
18
  const conn = readActiveConnection({
14
19
  urlOverride: args.url,
@@ -39,6 +44,220 @@ async function callJson(url, token, init = {}) {
39
44
  }
40
45
  return { status: response.status, body, raw };
41
46
  }
47
+ function asArray(value) {
48
+ return Array.isArray(value) ? value : [];
49
+ }
50
+ const MethodAuthoringArtifactRequirementsCliSchema = MethodAuthoringArtifactRequirementSchema.array();
51
+ function parseJsonOption(label, value, parse) {
52
+ if (!value)
53
+ return undefined;
54
+ let parsed;
55
+ try {
56
+ parsed = JSON.parse(value);
57
+ }
58
+ catch (error) {
59
+ console.error(chalk.red(`Invalid JSON for ${label}.`));
60
+ console.error(chalk.dim(error instanceof Error ? error.message : String(error)));
61
+ process.exit(1);
62
+ }
63
+ try {
64
+ return parse(parsed);
65
+ }
66
+ catch (error) {
67
+ console.error(chalk.red(`Invalid ${label}.`));
68
+ console.error(chalk.dim(error instanceof Error ? error.message : String(error)));
69
+ process.exit(1);
70
+ }
71
+ }
72
+ function buildPreparationReviewUrl(url, prepId) {
73
+ return `${url}/?section=preparations&preparation=${encodeURIComponent(prepId)}&preparationTab=build-plan`;
74
+ }
75
+ function buildRunUrl(url, prepId, runId) {
76
+ if (!runId)
77
+ return null;
78
+ return `${url}/?section=preparations&preparation=${encodeURIComponent(prepId)}&preparationTab=runs&run=${encodeURIComponent(runId)}`;
79
+ }
80
+ function defaultMethodIdForPreparation(prepId) {
81
+ return slugify(`${prepId}-build-plan`) || "build-plan";
82
+ }
83
+ function labelFromMethodId(methodId) {
84
+ const label = methodId
85
+ .split("-")
86
+ .filter(Boolean)
87
+ .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
88
+ .join(" ");
89
+ return label || "Build Plan";
90
+ }
91
+ function renderMethodSummary(method) {
92
+ const id = method.method_id ?? method.id ?? "(?)";
93
+ console.log();
94
+ console.log(` ${chalk.bold(method.label ?? id)}`);
95
+ console.log(chalk.dim(` id: ${id}`));
96
+ if (method.hint)
97
+ console.log(chalk.dim(` hint: ${method.hint}`));
98
+ if (method.purpose?.task_hint)
99
+ console.log(chalk.dim(` purpose: ${method.purpose.task_hint}`));
100
+ if (method.source_kind)
101
+ console.log(chalk.dim(` source: ${method.source_kind}`));
102
+ const artifacts = method.artifacts ?? [];
103
+ if (artifacts.length > 0) {
104
+ console.log();
105
+ console.log(chalk.bold(" Artifacts"));
106
+ for (const artifact of artifacts) {
107
+ const shape = artifact.shape?.path
108
+ ? chalk.dim(` -> ${artifact.shape.path}`)
109
+ : "";
110
+ console.log(` ${chalk.bold(artifact.id)}${shape}`);
111
+ console.log(chalk.dim(` ${artifact.description}`));
112
+ const checks = artifact.checks ?? [];
113
+ for (const check of checks.slice(0, 3)) {
114
+ const required = check.required === false ? "soft" : "required";
115
+ console.log(chalk.dim(` - ${check.description ?? check.kind} (${required})`));
116
+ }
117
+ }
118
+ }
119
+ const stages = method.stages ?? [];
120
+ if (stages.length > 0) {
121
+ console.log();
122
+ console.log(chalk.bold(" Stages"));
123
+ for (const stage of stages) {
124
+ const role = stage.role ? chalk.dim(` [${stage.role}]`) : "";
125
+ console.log(` ${chalk.bold(stage.label)}${role}`);
126
+ if (stage.description)
127
+ console.log(chalk.dim(` ${stage.description}`));
128
+ const reads = stage.reads?.length ? stage.reads.join(", ") : "source";
129
+ const writes = stage.writes?.length ? stage.writes.join(", ") : "(none declared)";
130
+ console.log(chalk.dim(` reads: ${reads}`));
131
+ console.log(chalk.dim(` writes: ${writes}`));
132
+ }
133
+ }
134
+ if (method.active_for_preparations?.length) {
135
+ console.log();
136
+ console.log(chalk.dim(` used by: ${method.active_for_preparations.join(", ")}`));
137
+ }
138
+ console.log();
139
+ console.log(chalk.dim(" Run with --json for the raw Build Plan record."));
140
+ console.log();
141
+ }
142
+ function preparationChecks(preparation) {
143
+ return asArray(preparation.checks).length
144
+ ? asArray(preparation.checks)
145
+ : asArray(preparation.preparation?.checks);
146
+ }
147
+ function preparationRequestedArtifacts(preparation) {
148
+ return preparation.requested_artifacts?.length
149
+ ? preparation.requested_artifacts
150
+ : preparation.preparation?.requested_artifacts ?? [];
151
+ }
152
+ function preparationSourceProfile(preparation) {
153
+ return preparation.source_profile ?? preparation.preparation?.source_profile ?? null;
154
+ }
155
+ function selectedMethodId(preparation) {
156
+ return preparation.method_id ?? preparation.preparation?.method ?? null;
157
+ }
158
+ function sourceFolderPathFromPreparation(preparation, sourceFiles) {
159
+ if (preparation.source?.kind === "local-folder" && preparation.source.locator)
160
+ return preparation.source.locator;
161
+ if (sourceFiles?.source_files?.[0]?.source_folder_path)
162
+ return sourceFiles.source_files[0].source_folder_path;
163
+ return preparation.source_path ?? null;
164
+ }
165
+ function buildTaskPrompt(args, preparation, prepId, mode) {
166
+ const about = (preparation.about ?? preparation.preparation?.about)?.trim();
167
+ const requestedArtifacts = formatRequestedArtifactsForPrompt(preparationRequestedArtifacts(preparation));
168
+ const sections = [
169
+ `${mode === "improve" ? "Improve" : "Draft"} a Build Plan for Preparation "${prepId}".`,
170
+ args.task?.trim() ? `Agent job:\n${args.task.trim()}` : null,
171
+ about ? `Preparation context:\n${about}` : null,
172
+ requestedArtifacts ? `Requested Artifacts saved on the Preparation:\n${requestedArtifacts}` : null,
173
+ args.artifacts?.trim() ? `Additional Artifact notes:\n${args.artifacts.trim()}` : null,
174
+ args.readyWhen?.trim() ? `Ready when:\n${args.readyWhen.trim()}` : null,
175
+ "Return a Method package that declares the verifiable Artifacts, the stages that build them, and the checks that prove the portable context is ready for agent work.",
176
+ ].filter((section) => Boolean(section));
177
+ return sections.join("\n\n");
178
+ }
179
+ async function readPreparationContext(url, token, prepId) {
180
+ const fetched = await callJson(`${url}${preparationResourcePath(prepId)}`, token);
181
+ if (fetched.status !== 200 || !fetched.body) {
182
+ console.error(chalk.red(`Failed to read Preparation ${prepId} (HTTP ${fetched.status}).`));
183
+ if (fetched.raw)
184
+ console.error(fetched.raw);
185
+ process.exit(1);
186
+ }
187
+ let sourceFiles = null;
188
+ const sourcePath = sourceFolderPathFromPreparation(fetched.body, sourceFiles);
189
+ if (!sourcePath) {
190
+ const listed = await callJson(`${url}${preparationSubresourcePath(prepId, "sourceFiles")}`, token);
191
+ if (listed.status === 200)
192
+ sourceFiles = listed.body;
193
+ }
194
+ const sourceFolderPath = sourceFolderPathFromPreparation(fetched.body, sourceFiles);
195
+ if (!sourceFolderPath) {
196
+ console.error(chalk.red(`Preparation ${prepId} has no readable local Source binding.`));
197
+ process.exit(1);
198
+ }
199
+ return {
200
+ preparation: fetched.body,
201
+ sourceFolderPath,
202
+ checks: preparationChecks(fetched.body),
203
+ };
204
+ }
205
+ async function startBuildPlanRun(args, mode) {
206
+ const { url, token } = resolveConnection(args);
207
+ const { preparation, sourceFolderPath, checks } = await readPreparationContext(url, token, args.prepId);
208
+ const existingMethod = selectedMethodId(preparation);
209
+ const methodId = args.method ?? (mode === "improve" ? existingMethod : defaultMethodIdForPreparation(args.prepId));
210
+ const requestedArtifacts = preparationRequestedArtifacts(preparation);
211
+ const explicitArtifactRequirements = parseJsonOption("--artifact-requirements-json", args.artifactRequirementsJson, (input) => MethodAuthoringArtifactRequirementsCliSchema.parse(input));
212
+ const artifactRequirements = explicitArtifactRequirements
213
+ ?? artifactRequirementsFromRequestedArtifacts(requestedArtifacts);
214
+ if (!methodId) {
215
+ console.error(chalk.red(`Preparation ${args.prepId} has no selected Build Plan to improve.`));
216
+ console.error(chalk.dim(`Draft one first: interf method draft ${args.prepId} --task "..."`));
217
+ process.exit(1);
218
+ }
219
+ const body = {
220
+ preparation: args.prepId,
221
+ source_folder_path: sourceFolderPath,
222
+ ...(args.baseMethod ? { base_method_id: args.baseMethod } : {}),
223
+ ...(args.referenceMethod ? { reference_method_id: args.referenceMethod } : {}),
224
+ ...(mode === "improve" && !args.referenceMethod && existingMethod ? { reference_method_id: existingMethod } : {}),
225
+ method_id: methodId,
226
+ label: args.label ?? labelFromMethodId(methodId),
227
+ hint: args.hint ?? `Build Plan for Preparation ${args.prepId}.`,
228
+ task_prompt: buildTaskPrompt(args, preparation, args.prepId, mode),
229
+ checks,
230
+ requested_artifacts: requestedArtifacts,
231
+ source_profile: preparationSourceProfile(preparation),
232
+ artifact_requirements: artifactRequirements,
233
+ };
234
+ const endpoint = mode === "improve" ? "methodImprovementRuns" : "methodAuthoringRuns";
235
+ const { status, body: run, raw } = await callJson(`${url}${preparationSubresourcePath(args.prepId, endpoint)}`, token, { method: "POST", body: JSON.stringify(body) });
236
+ if (status !== 202 && status !== 201 && status !== 200) {
237
+ console.error(chalk.red(`Failed to start Build Plan ${mode} run (HTTP ${status}).`));
238
+ if (raw)
239
+ console.error(raw);
240
+ process.exit(1);
241
+ }
242
+ const runUrl = buildRunUrl(url, args.prepId, run?.run_id);
243
+ const reviewUrl = buildPreparationReviewUrl(url, args.prepId);
244
+ if (args.json) {
245
+ console.log(JSON.stringify({
246
+ run_id: run?.run_id ?? null,
247
+ status: run?.status ?? null,
248
+ preparation: args.prepId,
249
+ method_id: methodId,
250
+ run_url: runUrl,
251
+ review_url: reviewUrl,
252
+ }, null, 2));
253
+ return;
254
+ }
255
+ console.log(chalk.green(`Build Plan ${mode} run ${chalk.bold(run?.run_id ?? "(?)")} started.`));
256
+ console.log(chalk.dim(` Build Plan: ${methodId}`));
257
+ if (runUrl)
258
+ console.log(chalk.dim(` watch: ${runUrl}`));
259
+ console.log(chalk.dim(` review after it finishes: ${reviewUrl}`));
260
+ }
42
261
  export const methodCommand = {
43
262
  command: "method <subcommand>",
44
263
  describe: "Manage methods on the connected instance",
@@ -83,27 +302,54 @@ export const methodCommand = {
83
302
  }
84
303
  console.log(chalk.green(`Installed method from ${absolute}.`));
85
304
  })
86
- .command("draft <prep-id>", "Start a method-authoring run for a preparation", (y) => y.positional("prep-id", { type: "string", demandOption: true, describe: "Preparation id" }), async (args) => {
305
+ .command("show <method-id>", "Show a Build Plan / Method package", (y) => y
306
+ .positional("method-id", { type: "string", demandOption: true, describe: "Build Plan / Method package id" })
307
+ .option("json", {
308
+ type: "boolean",
309
+ default: false,
310
+ describe: "Print the raw JSON record instead of the formatted summary",
311
+ }), async (args) => {
87
312
  const { url, token } = resolveConnection(args);
88
- const { status, body, raw } = await callJson(`${url}/v1/preparations/${encodeURIComponent(args.prepId)}/method-authoring-runs`, token, { method: "POST", body: JSON.stringify({}) });
89
- if (status !== 201 && status !== 200) {
90
- console.error(chalk.red(`Failed to start method-authoring run (HTTP ${status}).`));
313
+ const { status, body, raw } = await callJson(`${url}${methodResourcePath(args.methodId)}`, token);
314
+ if (status !== 200 || !body) {
315
+ console.error(chalk.red(`Failed to read Build Plan ${args.methodId} (HTTP ${status}).`));
91
316
  if (raw)
92
317
  console.error(raw);
93
318
  process.exit(1);
94
319
  }
95
- console.log(chalk.green(`Method-authoring run ${chalk.bold(body?.run_id ?? "(?)")} started.`));
96
- })
97
- .command("improve <prep-id>", "Start a method-improvement run for a preparation", (y) => y.positional("prep-id", { type: "string", demandOption: true, describe: "Preparation id" }), async (args) => {
98
- const { url, token } = resolveConnection(args);
99
- const { status, body, raw } = await callJson(`${url}/v1/preparations/${encodeURIComponent(args.prepId)}/method-improvement-runs`, token, { method: "POST", body: JSON.stringify({}) });
100
- if (status !== 201 && status !== 200) {
101
- console.error(chalk.red(`Failed to start method-improvement run (HTTP ${status}).`));
102
- if (raw)
103
- console.error(raw);
104
- process.exit(1);
320
+ if (args.json) {
321
+ console.log(JSON.stringify(body, null, 2));
322
+ return;
105
323
  }
106
- console.log(chalk.green(`Method-improvement run ${chalk.bold(body?.run_id ?? "(?)")} started.`));
324
+ renderMethodSummary(body);
325
+ })
326
+ .command("draft <prep-id>", "Start a Build Plan draft run for a preparation", (y) => y
327
+ .positional("prep-id", { type: "string", demandOption: true, describe: "Preparation id" })
328
+ .option("task", { type: "string", describe: "Agent job this Build Plan should support" })
329
+ .option("artifacts", { type: "string", describe: "Requested Artifacts and why the agent needs them" })
330
+ .option("artifact-requirements-json", { type: "string", describe: "JSON array of exact Artifact output requirements for the Build Plan" })
331
+ .option("ready-when", { type: "string", describe: "Proof or readiness expectations for the Build Plan" })
332
+ .option("method", { type: "string", describe: "Build Plan / Method id to write" })
333
+ .option("label", { type: "string", describe: "Human-readable Build Plan label" })
334
+ .option("hint", { type: "string", describe: "Short Build Plan hint for reviewers" })
335
+ .option("base-method", { type: "string", describe: "Existing Method id to use as a starting point" })
336
+ .option("reference-method", { type: "string", describe: "Existing Method id to reference while drafting" })
337
+ .option("json", { type: "boolean", default: false, describe: "Print machine-readable run metadata" }), async (args) => {
338
+ await startBuildPlanRun(args, "draft");
339
+ })
340
+ .command("improve <prep-id>", "Start a Build Plan improvement run for a preparation", (y) => y
341
+ .positional("prep-id", { type: "string", demandOption: true, describe: "Preparation id" })
342
+ .option("task", { type: "string", describe: "Change request for the selected Build Plan" })
343
+ .option("artifacts", { type: "string", describe: "Requested Artifact changes and why they matter" })
344
+ .option("artifact-requirements-json", { type: "string", describe: "JSON array of exact Artifact output requirements for the Build Plan" })
345
+ .option("ready-when", { type: "string", describe: "Proof or readiness expectations to add or change" })
346
+ .option("method", { type: "string", describe: "Build Plan / Method id to update" })
347
+ .option("label", { type: "string", describe: "Human-readable Build Plan label" })
348
+ .option("hint", { type: "string", describe: "Short Build Plan hint for reviewers" })
349
+ .option("base-method", { type: "string", describe: "Existing Method id to use as a starting point" })
350
+ .option("reference-method", { type: "string", describe: "Existing Method id to reference while improving" })
351
+ .option("json", { type: "boolean", default: false, describe: "Print machine-readable run metadata" }), async (args) => {
352
+ await startBuildPlanRun(args, "improve");
107
353
  })
108
354
  .demandCommand(1)
109
355
  .strict(),
@@ -2,7 +2,7 @@
2
2
  * `interf prep` — preparation CRUD against a connected instance.
3
3
  *
4
4
  * interf prep ls
5
- * interf prep create <id> --source <path> --method <id> [--about <text>]
5
+ * interf prep create <id> --source <path> [--method <id>] [--about <text>]
6
6
  * interf prep show <id>
7
7
  * interf prep rm <id>
8
8
  *
@@ -14,6 +14,8 @@ import { resolve } from "node:path";
14
14
  import chalk from "chalk";
15
15
  import { CONNECT_OR_ERROR_HINT, readActiveConnection, } from "../../packages/engine/connection-config.js";
16
16
  import { preparationResourcePath } from "../../packages/engine/routes.js";
17
+ import { requestedArtifactCheckLabel } from "../../packages/engine/requested-artifacts.js";
18
+ import { RequestedArtifactSchema, SourceProfileSchema, } from "../../packages/project/lib/schema.js";
17
19
  function requireConnection(args) {
18
20
  const conn = readActiveConnection({
19
21
  urlOverride: args.url,
@@ -45,6 +47,87 @@ async function callJson(url, token, init = {}) {
45
47
  }
46
48
  return { status: response.status, body, raw };
47
49
  }
50
+ const RequestedArtifactsCliSchema = RequestedArtifactSchema.array();
51
+ function parseJsonOption(label, value, parse) {
52
+ if (!value)
53
+ return undefined;
54
+ let parsed;
55
+ try {
56
+ parsed = JSON.parse(value);
57
+ }
58
+ catch (error) {
59
+ console.error(chalk.red(`Invalid JSON for ${label}.`));
60
+ console.error(chalk.dim(error instanceof Error ? error.message : String(error)));
61
+ process.exit(1);
62
+ }
63
+ try {
64
+ return parse(parsed);
65
+ }
66
+ catch (error) {
67
+ console.error(chalk.red(`Invalid ${label}.`));
68
+ console.error(chalk.dim(error instanceof Error ? error.message : String(error)));
69
+ process.exit(1);
70
+ }
71
+ }
72
+ function statusColor(status) {
73
+ if (status === "ready")
74
+ return chalk.green;
75
+ if (status === "failed")
76
+ return chalk.red;
77
+ if (status === "skipped")
78
+ return chalk.dim;
79
+ return chalk.yellow;
80
+ }
81
+ function renderPreparationSummary(prep) {
82
+ console.log();
83
+ console.log(` ${chalk.bold(prep.name)}`);
84
+ console.log(chalk.dim(` Build Plan: ${prep.method_id ?? "(not selected)"}`));
85
+ if (prep.source_path)
86
+ console.log(chalk.dim(` source: ${prep.source_path}`));
87
+ if (prep.portable_context_path) {
88
+ console.log(chalk.dim(` output: ${prep.portable_context_path}`));
89
+ }
90
+ if (prep.readiness?.status) {
91
+ const aggColor = prep.readiness.ready ? chalk.green : chalk.yellow;
92
+ console.log(` readiness: ${aggColor(prep.readiness.status)}${prep.readiness.summary ? chalk.dim(` (${prep.readiness.summary})`) : ""}`);
93
+ }
94
+ if (prep.artifacts && prep.artifacts.length > 0) {
95
+ console.log();
96
+ console.log(chalk.bold(" Artifacts"));
97
+ const idWidth = Math.max(...prep.artifacts.map((entry) => entry.artifact_id.length), 8);
98
+ for (const artifact of prep.artifacts) {
99
+ const colored = statusColor(artifact.status)(artifact.status);
100
+ const stages = artifact.built_by_stages && artifact.built_by_stages.length > 0
101
+ ? chalk.dim(` ← ${artifact.built_by_stages.join(", ")}`)
102
+ : "";
103
+ console.log(` ${artifact.artifact_id.padEnd(idWidth)} ${colored}${stages}`);
104
+ }
105
+ }
106
+ if (prep.requested_artifacts && prep.requested_artifacts.length > 0) {
107
+ console.log();
108
+ console.log(chalk.bold(" Requested Artifacts"));
109
+ for (const artifact of prep.requested_artifacts) {
110
+ console.log(` ${chalk.bold(artifact.title)}`);
111
+ if (artifact.purpose ?? artifact.description) {
112
+ console.log(chalk.dim(` ${artifact.purpose ?? artifact.description}`));
113
+ }
114
+ const checks = artifact.checks ?? [];
115
+ for (const check of checks.slice(0, 4)) {
116
+ console.log(chalk.dim(` - ${requestedArtifactCheckLabel(check)}`));
117
+ }
118
+ }
119
+ }
120
+ if (prep.latest_compile_run_id) {
121
+ console.log();
122
+ console.log(chalk.dim(` latest compile run: ${prep.latest_compile_run_id}`));
123
+ }
124
+ if (prep.latest_test_run_id) {
125
+ console.log(chalk.dim(` latest check run: ${prep.latest_test_run_id}`));
126
+ }
127
+ console.log();
128
+ console.log(chalk.dim(` Run with --json for the raw resource record.`));
129
+ console.log();
130
+ }
48
131
  export const prepCommand = {
49
132
  command: "prep <subcommand>",
50
133
  describe: "Manage preparations on the connected instance",
@@ -62,7 +145,7 @@ export const prepCommand = {
62
145
  }
63
146
  const preparations = body.preparations ?? [];
64
147
  if (preparations.length === 0) {
65
- console.log(chalk.dim(" No preparations yet. Create one with `interf prep create <id> --source <path> --method <method-id>`."));
148
+ console.log(chalk.dim(" No preparations yet. Create one with `interf prep create <id> --source <path>`."));
66
149
  return;
67
150
  }
68
151
  console.log();
@@ -70,26 +153,34 @@ export const prepCommand = {
70
153
  console.log();
71
154
  for (const prep of preparations) {
72
155
  const sourceLabel = prep.source?.locator ?? prep.source_path ?? "(no source)";
73
- const method = prep.method_id ?? "(no method)";
156
+ const method = prep.method_id ?? "(no Build Plan)";
74
157
  const readiness = prep.readiness?.status ?? "—";
158
+ const requested = prep.requested_artifacts?.length ?? 0;
75
159
  console.log(` ${prep.id}`);
76
160
  console.log(chalk.dim(` source: ${sourceLabel}`));
77
- console.log(chalk.dim(` method: ${method}`));
161
+ console.log(chalk.dim(` Build Plan: ${method}`));
162
+ console.log(chalk.dim(` requested Artifacts: ${requested}`));
78
163
  console.log(chalk.dim(` readiness: ${readiness}`));
79
164
  }
80
165
  })
81
- .command("create <prep-id>", "Create a preparation (method binding optional — set later if you don't have one yet)", (y) => y
166
+ .command("create <prep-id>", "Create a Preparation (Build Plan optional — select or draft it later)", (y) => y
82
167
  .positional("prep-id", { type: "string", demandOption: true, describe: "Preparation id (lowercase, dash-separated)" })
83
- .option("source", { type: "string", demandOption: true, describe: "Path to the Source Folder" })
84
- .option("method", { type: "string", describe: "Method id (e.g. interf-default). Optional — bind later via `interf prep set-method`." })
85
- .option("about", { type: "string", describe: "One-line description of the agent work" }), async (args) => {
168
+ .option("source", { type: "string", demandOption: true, describe: "Path to the Source" })
169
+ .option("method", { type: "string", describe: "Build Plan / Method package id. Optional — bind later via `interf prep set-method`." })
170
+ .option("about", { type: "string", describe: "One-line description of the agent work" })
171
+ .option("requested-artifacts-json", { type: "string", describe: "JSON array of requested Artifacts for this Preparation" })
172
+ .option("source-profile-json", { type: "string", describe: "JSON object describing the agent's advisory source profile" }), async (args) => {
86
173
  const { url, token } = requireConnection(args);
87
174
  const sourceAbs = resolve(process.cwd(), args.source);
175
+ const requestedArtifacts = parseJsonOption("--requested-artifacts-json", args.requestedArtifactsJson, (input) => RequestedArtifactsCliSchema.parse(input));
176
+ const sourceProfile = parseJsonOption("--source-profile-json", args.sourceProfileJson, (input) => SourceProfileSchema.parse(input));
88
177
  const requestBody = {
89
178
  id: args.prepId,
90
179
  source: { kind: "local-folder", locator: sourceAbs },
91
180
  ...(args.method ? { method_id: args.method } : {}),
92
181
  about: args.about,
182
+ ...(requestedArtifacts ? { requested_artifacts: requestedArtifacts } : {}),
183
+ ...(sourceProfile ? { source_profile: sourceProfile } : {}),
93
184
  checks: [],
94
185
  };
95
186
  const { status, body, raw } = await callJson(`${url}/v1/preparations`, token, { method: "POST", body: JSON.stringify(requestBody) });
@@ -101,17 +192,17 @@ export const prepCommand = {
101
192
  }
102
193
  console.log(chalk.green(`Created preparation ${chalk.bold(args.prepId)}.`));
103
194
  if (!args.method) {
104
- console.log(chalk.dim(` no method bound yet — pick or draft one before compiling:`));
195
+ console.log(chalk.dim(` no Build Plan selected yet — pick or draft one before compiling:`));
105
196
  console.log(chalk.dim(` interf prep set-method ${args.prepId} <method-id>`));
106
197
  console.log(chalk.dim(` interf method draft ${args.prepId}`));
107
198
  }
108
- if (body?.portable_context?.value) {
199
+ if (body?.method_id && body?.portable_context?.value) {
109
200
  console.log(chalk.dim(` portable context (locator): ${body.portable_context.value}`));
110
201
  }
111
202
  })
112
- .command("set-method <prep-id> <method-id>", "Bind a method to a preparation (or change which method it uses)", (y) => y
203
+ .command("set-method <prep-id> <method-id>", "Select a Build Plan / Method package for a Preparation", (y) => y
113
204
  .positional("prep-id", { type: "string", demandOption: true, describe: "Preparation id" })
114
- .positional("method-id", { type: "string", demandOption: true, describe: "Method id to bind" }), async (args) => {
205
+ .positional("method-id", { type: "string", demandOption: true, describe: "Build Plan / Method package id to select" }), async (args) => {
115
206
  const { url, token } = requireConnection(args);
116
207
  const { status, raw } = await callJson(`${url}${preparationResourcePath(args.prepId)}`, token, { method: "PATCH", body: JSON.stringify({ method_id: args.methodId }) });
117
208
  if (status !== 200) {
@@ -120,9 +211,15 @@ export const prepCommand = {
120
211
  console.error(raw);
121
212
  process.exit(1);
122
213
  }
123
- console.log(chalk.green(`Bound ${chalk.bold(args.methodId)} to ${chalk.bold(args.prepId)}.`));
214
+ console.log(chalk.green(`Selected Build Plan ${chalk.bold(args.methodId)} for ${chalk.bold(args.prepId)}.`));
124
215
  })
125
- .command("show <prep-id>", "Show a preparation's full record", (y) => y.positional("prep-id", { type: "string", demandOption: true, describe: "Preparation id" }), async (args) => {
216
+ .command("show <prep-id>", "Show a preparation's full record", (y) => y
217
+ .positional("prep-id", { type: "string", demandOption: true, describe: "Preparation id" })
218
+ .option("json", {
219
+ type: "boolean",
220
+ default: false,
221
+ describe: "Print the raw JSON record instead of the formatted summary",
222
+ }), async (args) => {
126
223
  const { url, token } = requireConnection(args);
127
224
  const { status, body, raw } = await callJson(`${url}${preparationResourcePath(args.prepId)}`, token);
128
225
  if (status !== 200) {
@@ -131,7 +228,11 @@ export const prepCommand = {
131
228
  console.error(raw);
132
229
  process.exit(1);
133
230
  }
134
- console.log(JSON.stringify(body, null, 2));
231
+ if (args.json || !body) {
232
+ console.log(JSON.stringify(body, null, 2));
233
+ return;
234
+ }
235
+ renderPreparationSummary(body);
135
236
  })
136
237
  .command("rm <prep-id>", "Delete a preparation", (y) => y.positional("prep-id", { type: "string", demandOption: true, describe: "Preparation id" }), async (args) => {
137
238
  const { url, token } = requireConnection(args);
@@ -40,6 +40,90 @@ async function callJson(url, token, init = {}) {
40
40
  }
41
41
  return { status: response.status, body, raw };
42
42
  }
43
+ function runStatusColor(status) {
44
+ if (status === "succeeded" || status === "completed")
45
+ return chalk.green;
46
+ if (status === "failed" || status === "cancelled")
47
+ return chalk.red;
48
+ if (status === "running")
49
+ return chalk.yellow;
50
+ return chalk.dim;
51
+ }
52
+ function renderRunStatus(run) {
53
+ const status = run.status ?? (run.trace?.run?.error ? "failed" : "unknown");
54
+ const color = runStatusColor(status);
55
+ console.log();
56
+ console.log(` ${chalk.bold(run.title ?? run.run_id)} ${color(`(${status})`)}`);
57
+ console.log(chalk.dim(` run: ${run.run_id}`));
58
+ if (run.run_type)
59
+ console.log(chalk.dim(` type: ${run.run_type}`));
60
+ if (run.preparation)
61
+ console.log(chalk.dim(` preparation: ${run.preparation}`));
62
+ if (run.method)
63
+ console.log(chalk.dim(` Build Plan: ${run.method}`));
64
+ if (run.agent_label)
65
+ console.log(chalk.dim(` agent: ${run.agent_label}`));
66
+ if (run.started_at)
67
+ console.log(chalk.dim(` started: ${run.started_at}`));
68
+ if (run.finished_at)
69
+ console.log(chalk.dim(` finished: ${run.finished_at}`));
70
+ if (run.output_path ?? run.portable_context_path) {
71
+ console.log(chalk.dim(` output: ${run.output_path ?? run.portable_context_path}`));
72
+ }
73
+ if (run.trace?.run?.error?.message) {
74
+ console.log();
75
+ console.log(chalk.red(" Error"));
76
+ console.log(chalk.dim(` ${run.trace.run.error.message}`));
77
+ }
78
+ const readiness = run.readiness;
79
+ if (readiness?.status) {
80
+ console.log();
81
+ const readinessColor = readiness.ready ? chalk.green : chalk.yellow;
82
+ console.log(` readiness: ${readinessColor(readiness.status)}${readiness.summary ? chalk.dim(` (${readiness.summary})`) : ""}`);
83
+ }
84
+ const metrics = run.metrics ?? [];
85
+ if (metrics.length > 0) {
86
+ console.log();
87
+ console.log(chalk.bold(" Metrics"));
88
+ for (const metric of metrics.slice(0, 8)) {
89
+ const value = metric.value !== undefined ? `${metric.value}${metric.unit ? ` ${metric.unit}` : ""}` : "";
90
+ console.log(chalk.dim(` ${metric.label ?? "metric"}: ${value}`));
91
+ }
92
+ }
93
+ const artifacts = run.artifacts ?? [];
94
+ if (artifacts.length > 0) {
95
+ console.log();
96
+ console.log(chalk.bold(" Artifacts"));
97
+ for (const artifact of artifacts.slice(0, 12)) {
98
+ const stage = artifact.stage_id ? chalk.dim(` ← ${artifact.stage_id}`) : "";
99
+ console.log(` ${artifact.label ?? artifact.role}: ${chalk.dim(artifact.path)}${stage}`);
100
+ }
101
+ if (artifacts.length > 12)
102
+ console.log(chalk.dim(` ... ${artifacts.length - 12} more`));
103
+ }
104
+ const proof = run.proof ?? [];
105
+ if (proof.length > 0) {
106
+ console.log();
107
+ console.log(chalk.bold(" Proof"));
108
+ for (const check of proof.slice(0, 12)) {
109
+ const marker = check.ok ? chalk.green("pass") : chalk.red("fail");
110
+ console.log(` ${marker} ${check.label}${check.detail ? chalk.dim(` — ${check.detail}`) : ""}`);
111
+ }
112
+ if (proof.length > 12)
113
+ console.log(chalk.dim(` ... ${proof.length - 12} more`));
114
+ }
115
+ const events = run.trace?.events ?? [];
116
+ if (events.length > 0) {
117
+ console.log();
118
+ console.log(chalk.bold(" Recent trace"));
119
+ for (const event of events.slice(-6)) {
120
+ console.log(chalk.dim(` ${event.createdAt ?? ""} ${event.eventType ?? "event"}`.trim()));
121
+ }
122
+ }
123
+ console.log();
124
+ console.log(chalk.dim(" Run with --json for the raw run resource."));
125
+ console.log();
126
+ }
43
127
  export const runsCommand = {
44
128
  command: "runs <subcommand>",
45
129
  describe: "Inspect runs on the connected instance",
@@ -48,10 +132,7 @@ export const runsCommand = {
48
132
  .option("token", { type: "string", describe: "Override the active bearer token" })
49
133
  .command("ls", "List runs (optionally filtered by preparation)", (y) => y.option("prep", { type: "string", describe: "Filter by preparation id" }), async (args) => {
50
134
  const { url, token } = resolveConnection(args);
51
- const path = args.prep
52
- ? `/v1/preparations/${encodeURIComponent(args.prep)}/runs`
53
- : "/v1/runs";
54
- const { status, body, raw } = await callJson(`${url}${path}`, token);
135
+ const { status, body, raw } = await callJson(`${url}/v1/runs`, token);
55
136
  if (status !== 200) {
56
137
  console.error(chalk.red(`Failed to list runs (HTTP ${status}).`));
57
138
  if (raw)
@@ -60,12 +141,15 @@ export const runsCommand = {
60
141
  }
61
142
  const runs = body?.runs
62
143
  ?? (body?.compile_runs ?? []).map((r) => r.run).filter(Boolean);
63
- if (runs.length === 0) {
144
+ const visibleRuns = args.prep
145
+ ? runs.filter((run) => run.preparation === args.prep)
146
+ : runs;
147
+ if (visibleRuns.length === 0) {
64
148
  console.log(chalk.dim(" No runs."));
65
149
  return;
66
150
  }
67
151
  console.log();
68
- for (const run of runs) {
152
+ for (const run of visibleRuns) {
69
153
  console.log(` ${chalk.bold(run.run_id)} ${chalk.dim(`(${run.status ?? "?"})`)}`);
70
154
  if (run.preparation)
71
155
  console.log(chalk.dim(` prep: ${run.preparation}`));
@@ -74,14 +158,24 @@ export const runsCommand = {
74
158
  }
75
159
  console.log();
76
160
  })
77
- .command("status <run-id>", "Show full record for a run", (y) => y.positional("run-id", { type: "string", demandOption: true, describe: "Run id" }), async (args) => {
161
+ .command("status <run-id>", "Show full record for a run", (y) => y
162
+ .positional("run-id", { type: "string", demandOption: true, describe: "Run id" })
163
+ .option("json", {
164
+ type: "boolean",
165
+ default: false,
166
+ describe: "Print the raw JSON record instead of the formatted summary",
167
+ }), async (args) => {
78
168
  const { url, token } = resolveConnection(args);
79
- const { status, raw } = await callJson(`${url}/v1/runs/${encodeURIComponent(args.runId)}`, token);
169
+ const { status, body, raw } = await callJson(`${url}/v1/runs/${encodeURIComponent(args.runId)}`, token);
80
170
  if (status !== 200) {
81
171
  console.error(chalk.red(`Failed to read run ${args.runId} (HTTP ${status}).`));
82
172
  process.exit(1);
83
173
  }
84
- console.log(raw);
174
+ if (args.json || !body) {
175
+ console.log(raw);
176
+ return;
177
+ }
178
+ renderRunStatus(body);
85
179
  })
86
180
  .command("cancel <run-id>", "Cancel a running run", (y) => y.positional("run-id", { type: "string", demandOption: true, describe: "Run id" }), async (args) => {
87
181
  const { url, token } = resolveConnection(args);