@alisio/core 0.5.2 → 0.7.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 (204) hide show
  1. package/dist/analysis/janitor.d.ts +48 -0
  2. package/dist/analysis/janitor.js +170 -18
  3. package/dist/analysis/jobs.d.ts +11 -2
  4. package/dist/analysis/jobs.js +13 -0
  5. package/dist/analysis/oci.d.ts +11 -2
  6. package/dist/analysis/oci.js +20 -4
  7. package/dist/analysis/python/sources.js +2 -1
  8. package/dist/analysis/rerun.d.ts +1 -1
  9. package/dist/analysis/status.d.ts +3 -1
  10. package/dist/analysis/status.js +3 -0
  11. package/dist/application.d.ts +28 -2
  12. package/dist/application.js +189 -4
  13. package/dist/changelog/data.js +42 -0
  14. package/dist/config.d.ts +110 -2
  15. package/dist/config.js +188 -6
  16. package/dist/core/call-internals.d.ts +22 -0
  17. package/dist/core/call-internals.js +9 -0
  18. package/dist/core/contracts.d.ts +2 -2
  19. package/dist/core/runner.js +111 -38
  20. package/dist/eval/canonical.d.ts +14 -0
  21. package/dist/eval/canonical.js +40 -0
  22. package/dist/eval/cassette.d.ts +180 -0
  23. package/dist/eval/cassette.js +424 -0
  24. package/dist/eval/compare.d.ts +147 -0
  25. package/dist/eval/compare.js +436 -0
  26. package/dist/eval/engine.d.ts +144 -0
  27. package/dist/eval/engine.js +728 -0
  28. package/dist/eval/export.d.ts +40 -0
  29. package/dist/eval/export.js +90 -0
  30. package/dist/eval/fingerprint.d.ts +88 -0
  31. package/dist/eval/fingerprint.js +186 -0
  32. package/dist/eval/normalize.d.ts +68 -0
  33. package/dist/eval/normalize.js +138 -0
  34. package/dist/eval/paths.d.ts +11 -0
  35. package/dist/eval/paths.js +50 -0
  36. package/dist/eval/plan.d.ts +26 -0
  37. package/dist/eval/plan.js +44 -0
  38. package/dist/eval/report.d.ts +53 -0
  39. package/dist/eval/report.js +258 -0
  40. package/dist/eval/run-suite.d.ts +68 -0
  41. package/dist/eval/run-suite.js +94 -0
  42. package/dist/eval/secrets.d.ts +12 -0
  43. package/dist/eval/secrets.js +45 -0
  44. package/dist/eval/stats.d.ts +17 -0
  45. package/dist/eval/stats.js +50 -0
  46. package/dist/eval/suite.d.ts +20 -0
  47. package/dist/eval/suite.js +165 -0
  48. package/dist/eval/variants.d.ts +35 -0
  49. package/dist/eval/variants.js +137 -0
  50. package/dist/eval/verifiers.d.ts +49 -0
  51. package/dist/eval/verifiers.js +264 -0
  52. package/dist/forge/broker.d.ts +51 -0
  53. package/dist/forge/broker.js +244 -0
  54. package/dist/forge/budget.d.ts +27 -0
  55. package/dist/forge/budget.js +60 -0
  56. package/dist/forge/catalog-view.d.ts +24 -0
  57. package/dist/forge/catalog-view.js +43 -0
  58. package/dist/forge/errors.d.ts +26 -0
  59. package/dist/forge/errors.js +49 -0
  60. package/dist/forge/guides/javascript.d.ts +25 -0
  61. package/dist/forge/guides/javascript.js +90 -0
  62. package/dist/forge/guides/provider.d.ts +42 -0
  63. package/dist/forge/guides/provider.js +96 -0
  64. package/dist/forge/guides/python-environment.d.ts +15 -0
  65. package/dist/forge/guides/python-environment.js +81 -0
  66. package/dist/forge/guides/python.d.ts +38 -0
  67. package/dist/forge/guides/python.js +170 -0
  68. package/dist/forge/javascript/engine.d.ts +44 -0
  69. package/dist/forge/javascript/engine.js +229 -0
  70. package/dist/forge/javascript/hosts/factory.d.ts +25 -0
  71. package/dist/forge/javascript/hosts/factory.js +21 -0
  72. package/dist/forge/javascript/hosts/framing.d.ts +17 -0
  73. package/dist/forge/javascript/hosts/framing.js +49 -0
  74. package/dist/forge/javascript/hosts/isolate-main.d.ts +9 -0
  75. package/dist/forge/javascript/hosts/isolate-main.js +63 -0
  76. package/dist/forge/javascript/hosts/process-entry.d.ts +1 -0
  77. package/dist/forge/javascript/hosts/process-entry.js +3 -0
  78. package/dist/forge/javascript/hosts/process-host.d.ts +33 -0
  79. package/dist/forge/javascript/hosts/process-host.js +160 -0
  80. package/dist/forge/javascript/hosts/worker-entry.d.ts +1 -0
  81. package/dist/forge/javascript/hosts/worker-entry.js +3 -0
  82. package/dist/forge/javascript/hosts/worker-host.d.ts +27 -0
  83. package/dist/forge/javascript/hosts/worker-host.js +116 -0
  84. package/dist/forge/javascript/prelude.d.ts +2 -0
  85. package/dist/forge/javascript/prelude.js +333 -0
  86. package/dist/forge/javascript/probe.d.ts +2 -0
  87. package/dist/forge/javascript/probe.js +53 -0
  88. package/dist/forge/javascript/runtime-manifest.d.ts +14 -0
  89. package/dist/forge/javascript/runtime-manifest.js +14 -0
  90. package/dist/forge/javascript/vm-runner.d.ts +21 -0
  91. package/dist/forge/javascript/vm-runner.js +301 -0
  92. package/dist/forge/javascript/wasm-asset.d.ts +8 -0
  93. package/dist/forge/javascript/wasm-asset.js +8 -0
  94. package/dist/forge/javascript/wasm.d.ts +15 -0
  95. package/dist/forge/javascript/wasm.js +54 -0
  96. package/dist/forge/journal.d.ts +105 -0
  97. package/dist/forge/journal.js +174 -0
  98. package/dist/forge/kernel.d.ts +76 -0
  99. package/dist/forge/kernel.js +339 -0
  100. package/dist/forge/limits.d.ts +38 -0
  101. package/dist/forge/limits.js +73 -0
  102. package/dist/forge/nested.d.ts +96 -0
  103. package/dist/forge/nested.js +214 -0
  104. package/dist/forge/ports.d.ts +120 -0
  105. package/dist/forge/ports.js +1 -0
  106. package/dist/forge/progress.d.ts +24 -0
  107. package/dist/forge/progress.js +76 -0
  108. package/dist/forge/protocol.d.ts +110 -0
  109. package/dist/forge/protocol.js +171 -0
  110. package/dist/forge/python/backend-selector.d.ts +38 -0
  111. package/dist/forge/python/backend-selector.js +111 -0
  112. package/dist/forge/python/backend.d.ts +89 -0
  113. package/dist/forge/python/backend.js +1 -0
  114. package/dist/forge/python/engine.d.ts +84 -0
  115. package/dist/forge/python/engine.js +279 -0
  116. package/dist/forge/python/frame-parser.d.ts +24 -0
  117. package/dist/forge/python/frame-parser.js +107 -0
  118. package/dist/forge/python/frame-transport.d.ts +40 -0
  119. package/dist/forge/python/frame-transport.js +101 -0
  120. package/dist/forge/python/import-scan.d.ts +22 -0
  121. package/dist/forge/python/import-scan.js +133 -0
  122. package/dist/forge/python/managed-backend.d.ts +30 -0
  123. package/dist/forge/python/managed-backend.js +111 -0
  124. package/dist/forge/python/oci-backend.d.ts +27 -0
  125. package/dist/forge/python/oci-backend.js +84 -0
  126. package/dist/forge/python/pyodide-backend.d.ts +40 -0
  127. package/dist/forge/python/pyodide-backend.js +289 -0
  128. package/dist/forge/python/pyodide-install.d.ts +41 -0
  129. package/dist/forge/python/pyodide-install.js +167 -0
  130. package/dist/forge/python/pyodide-manifest.d.ts +42 -0
  131. package/dist/forge/python/pyodide-manifest.js +376 -0
  132. package/dist/forge/python/pyodide-runner-source.d.ts +2 -0
  133. package/dist/forge/python/pyodide-runner-source.js +3 -0
  134. package/dist/forge/python/rss.d.ts +2 -0
  135. package/dist/forge/python/rss.js +33 -0
  136. package/dist/forge/python/scratch-copy.d.ts +6 -0
  137. package/dist/forge/python/scratch-copy.js +61 -0
  138. package/dist/forge/python/settle.d.ts +6 -0
  139. package/dist/forge/python/settle.js +21 -0
  140. package/dist/forge/python/status.d.ts +8 -0
  141. package/dist/forge/python/status.js +15 -0
  142. package/dist/forge/python/wasm-node.d.ts +59 -0
  143. package/dist/forge/python/wasm-node.js +220 -0
  144. package/dist/forge/python/wiring.d.ts +39 -0
  145. package/dist/forge/python/wiring.js +47 -0
  146. package/dist/forge/registry.d.ts +26 -0
  147. package/dist/forge/registry.js +83 -0
  148. package/dist/forge/result.d.ts +58 -0
  149. package/dist/forge/result.js +86 -0
  150. package/dist/forge/routing-rule.d.ts +19 -0
  151. package/dist/forge/routing-rule.js +31 -0
  152. package/dist/forge/runtime.d.ts +64 -0
  153. package/dist/forge/runtime.js +88 -0
  154. package/dist/forge/scratch-files.d.ts +36 -0
  155. package/dist/forge/scratch-files.js +94 -0
  156. package/dist/forge/scratch-provider.d.ts +41 -0
  157. package/dist/forge/scratch-provider.js +79 -0
  158. package/dist/forge/scratch-quota.d.ts +8 -0
  159. package/dist/forge/scratch-quota.js +25 -0
  160. package/dist/forge/selector.d.ts +35 -0
  161. package/dist/forge/selector.js +51 -0
  162. package/dist/forge/session-dir.d.ts +59 -0
  163. package/dist/forge/session-dir.js +239 -0
  164. package/dist/forge/session-path.d.ts +31 -0
  165. package/dist/forge/session-path.js +61 -0
  166. package/dist/forge/slots.d.ts +16 -0
  167. package/dist/forge/slots.js +47 -0
  168. package/dist/forge/state-delta.d.ts +54 -0
  169. package/dist/forge/state-delta.js +99 -0
  170. package/dist/forge/state-machine.d.ts +20 -0
  171. package/dist/forge/state-machine.js +40 -0
  172. package/dist/forge/state-store.d.ts +25 -0
  173. package/dist/forge/state-store.js +50 -0
  174. package/dist/forge/task-log.d.ts +9 -0
  175. package/dist/forge/task-log.js +42 -0
  176. package/dist/forge/verdict.d.ts +20 -0
  177. package/dist/forge/verdict.js +28 -0
  178. package/dist/forge-isolate.d.ts +6 -0
  179. package/dist/forge-isolate.js +6 -0
  180. package/dist/index.d.ts +23 -1
  181. package/dist/index.js +23 -1
  182. package/dist/permissions/decide.d.ts +42 -0
  183. package/dist/permissions/decide.js +24 -0
  184. package/dist/plan/exit-plan.js +2 -1
  185. package/dist/resources/context.d.ts +2 -1
  186. package/dist/resources/context.js +2 -1
  187. package/dist/runtime/access.d.ts +34 -0
  188. package/dist/runtime/access.js +80 -0
  189. package/dist/runtime/ids.d.ts +21 -0
  190. package/dist/runtime/ids.js +41 -1
  191. package/dist/runtime/process.d.ts +2 -1
  192. package/dist/runtime/process.js +5 -5
  193. package/dist/runtime/store.d.ts +11 -0
  194. package/dist/runtime/store.js +106 -2
  195. package/dist/tools/analysis.d.ts +25 -2
  196. package/dist/tools/analysis.js +315 -267
  197. package/dist/tools/execute.js +6 -7
  198. package/dist/tools/forge-guide.d.ts +6 -0
  199. package/dist/tools/forge-guide.js +60 -0
  200. package/dist/tools/js-run.d.ts +19 -0
  201. package/dist/tools/js-run.js +126 -0
  202. package/dist/tools/standard.d.ts +7 -1
  203. package/dist/tools/standard.js +44 -43
  204. package/package.json +7 -2
@@ -129,7 +129,7 @@ export async function runProcess(command, args, options) {
129
129
  written += chunk.byteLength;
130
130
  };
131
131
  };
132
- const consume = (stream, logPath) => new Promise((resolveText, reject) => {
132
+ const consume = (stream, name, logPath) => new Promise((resolveText, reject) => {
133
133
  const decoder = new TextDecoder();
134
134
  const log = logger(logPath);
135
135
  let text = "", done = false;
@@ -155,7 +155,7 @@ export async function runProcess(command, args, options) {
155
155
  if (tailMode) {
156
156
  const live = decoder.decode(value, { stream: true });
157
157
  if (live)
158
- options.onData?.(live);
158
+ options.onData?.(live, name);
159
159
  tail.push(value);
160
160
  tailBytes += value.byteLength;
161
161
  while (tailBytes > max && tail.length) {
@@ -178,7 +178,7 @@ export async function runProcess(command, args, options) {
178
178
  const chunk = decoder.decode(slice, { stream: true });
179
179
  text += chunk;
180
180
  if (chunk)
181
- options.onData?.(chunk);
181
+ options.onData?.(chunk, name);
182
182
  if (value.byteLength > remaining) {
183
183
  truncated = true;
184
184
  kill();
@@ -191,8 +191,8 @@ export async function runProcess(command, args, options) {
191
191
  });
192
192
  try {
193
193
  const [stdout, stderr, exitCode] = await Promise.all([
194
- consume(child.stdout, options.logFiles?.stdout),
195
- consume(child.stderr, options.logFiles?.stderr),
194
+ consume(child.stdout, "stdout", options.logFiles?.stdout),
195
+ consume(child.stderr, "stderr", options.logFiles?.stderr),
196
196
  exited,
197
197
  ]);
198
198
  signal.throwIfAborted();
@@ -46,6 +46,17 @@ export declare class SQLiteStore implements SessionStore {
46
46
  runId?: string;
47
47
  startedAt?: number;
48
48
  }>;
49
+ /**
50
+ * Files the nested `write` calls of Forja executions of a session touched (D-31): one entry per
51
+ * journaled call that did not fail, with the tool call (`js_run`/`python_run`) that ran it so the
52
+ * panel can attach the run. `paths` are the absolute paths the gate resolved. Oldest first.
53
+ */
54
+ forgeWriteCalls(session: string): Array<{
55
+ toolCallId: string;
56
+ paths: string[];
57
+ runId?: string;
58
+ startedAt?: number;
59
+ }>;
49
60
  /** Rich (ui/image) parts persist as part of the serialized result and replay verbatim. */
50
61
  callResult(id: string, callId: string): ToolResult | undefined;
51
62
  reconcile(id: string, acknowledge?: boolean): void;
@@ -1,4 +1,5 @@
1
1
  import { textResult, } from "@alisio/sdk";
2
+ import { newUuid } from "./ids.js";
2
3
  import { isProcessAlive } from "./process.js";
3
4
  import { openDatabase } from "./sqlite.js";
4
5
  const alive = isProcessAlive;
@@ -231,6 +232,86 @@ export class SQLiteStore {
231
232
  add("owner_pid", "INTEGER");
232
233
  this.db.exec("INSERT OR IGNORE INTO schema_migrations VALUES(8)");
233
234
  });
235
+ if (!has(9))
236
+ this.db.transaction(() => {
237
+ // v9 (additive): Forja journal (`forge_executions`, `forge_calls`) and the small JSON state
238
+ // shared across executions (`forge_state`). Only hashes of inputs are stored, never the
239
+ // inputs or results themselves. `owner_pid` lets a restart tell its own dead executions
240
+ // from another live process's.
241
+ this.db.exec(`CREATE TABLE IF NOT EXISTS forge_executions(
242
+ id TEXT PRIMARY KEY,
243
+ root_session_id TEXT NOT NULL,
244
+ session_id TEXT NOT NULL,
245
+ tool_call_id TEXT NOT NULL,
246
+ engine TEXT NOT NULL,
247
+ isolation TEXT NOT NULL,
248
+ selection_reason TEXT NOT NULL,
249
+ status TEXT NOT NULL,
250
+ code_sha256 TEXT NOT NULL,
251
+ started_at INTEGER NOT NULL, ended_at INTEGER,
252
+ metrics_json TEXT,
253
+ error_code TEXT,
254
+ termination_unconfirmed INTEGER NOT NULL DEFAULT 0,
255
+ analysis_execution_id TEXT REFERENCES analysis_executions(id),
256
+ owner_pid INTEGER);
257
+ CREATE INDEX IF NOT EXISTS forge_executions_root
258
+ ON forge_executions(root_session_id, started_at);
259
+ CREATE TABLE IF NOT EXISTS forge_calls(
260
+ execution_id TEXT NOT NULL REFERENCES forge_executions(id),
261
+ call_id TEXT NOT NULL,
262
+ tool_name TEXT NOT NULL,
263
+ effect TEXT NOT NULL,
264
+ status TEXT NOT NULL,
265
+ duration_ms INTEGER,
266
+ input_sha256 TEXT NOT NULL,
267
+ error_code TEXT,
268
+ paths_json TEXT,
269
+ PRIMARY KEY(execution_id, call_id));
270
+ CREATE INDEX IF NOT EXISTS forge_calls_execution
271
+ ON forge_calls(execution_id, call_id);
272
+ CREATE TABLE IF NOT EXISTS forge_state(
273
+ root_session_id TEXT NOT NULL,
274
+ key TEXT NOT NULL,
275
+ value_json TEXT NOT NULL,
276
+ revision INTEGER NOT NULL,
277
+ updated_at INTEGER NOT NULL,
278
+ PRIMARY KEY(root_session_id, key));
279
+ INSERT OR IGNORE INTO schema_migrations VALUES(9);`);
280
+ });
281
+ if (!has(10)) {
282
+ // v10: `analysis_executions.runtime` admits `wasm` (the Pyodide backend). SQLite cannot alter
283
+ // a CHECK, so the table is rebuilt with the official recipe: foreign keys off, copy, drop,
284
+ // rename. Rows, ids and the artifacts that point at them are untouched.
285
+ this.db.exec("PRAGMA foreign_keys=OFF");
286
+ try {
287
+ this.db.transaction(() => {
288
+ this.db.exec(`CREATE TABLE analysis_executions_v10(
289
+ id TEXT PRIMARY KEY,
290
+ session TEXT NOT NULL,
291
+ root_session TEXT NOT NULL,
292
+ workspace TEXT NOT NULL,
293
+ run_id TEXT, call_id TEXT,
294
+ runtime TEXT NOT NULL CHECK(runtime IN ('managed','oci','wasm')),
295
+ status TEXT NOT NULL CHECK(status IN ('running','completed','failed','cancelled','timed_out')),
296
+ script_sha256 TEXT NOT NULL,
297
+ exit_code INTEGER, error TEXT,
298
+ rel_dir TEXT NOT NULL,
299
+ rerun_of TEXT,
300
+ created_at INTEGER NOT NULL, ended_at INTEGER);
301
+ INSERT INTO analysis_executions_v10 SELECT id,session,root_session,workspace,run_id,call_id,
302
+ runtime,status,script_sha256,exit_code,error,rel_dir,rerun_of,created_at,ended_at
303
+ FROM analysis_executions;
304
+ DROP TABLE analysis_executions;
305
+ ALTER TABLE analysis_executions_v10 RENAME TO analysis_executions;
306
+ CREATE INDEX IF NOT EXISTS analysis_executions_session
307
+ ON analysis_executions(root_session, created_at);
308
+ INSERT OR IGNORE INTO schema_migrations VALUES(10);`);
309
+ });
310
+ }
311
+ finally {
312
+ this.db.exec("PRAGMA foreign_keys=ON");
313
+ }
314
+ }
234
315
  }
235
316
  /**
236
317
  * The root of a session (itself for roots), following `parent_id`. Unknown ids are their own
@@ -247,7 +328,7 @@ export class SQLiteStore {
247
328
  return current;
248
329
  }
249
330
  create(workspace, provider, model) {
250
- const id = crypto.randomUUID();
331
+ const id = newUuid();
251
332
  const now = Date.now();
252
333
  this.db
253
334
  .prepare("INSERT INTO sessions(id,workspace,provider,model,created_at,updated_at) VALUES(?,?,?,?,?,?)")
@@ -287,7 +368,7 @@ export class SQLiteStore {
287
368
  .map((r) => this.row(r));
288
369
  }
289
370
  createChild(record) {
290
- const id = record.id ?? crypto.randomUUID();
371
+ const id = record.id ?? newUuid();
291
372
  const now = Date.now();
292
373
  this.db
293
374
  .prepare(`INSERT INTO sessions(id,workspace,provider,model,parent_id,depth,agent,status,title,usage,options,created_at,updated_at)
@@ -433,6 +514,29 @@ export class SQLiteStore {
433
514
  ...(row.started_at != null ? { startedAt: Number(row.started_at) } : {}),
434
515
  }));
435
516
  }
517
+ /**
518
+ * Files the nested `write` calls of Forja executions of a session touched (D-31): one entry per
519
+ * journaled call that did not fail, with the tool call (`js_run`/`python_run`) that ran it so the
520
+ * panel can attach the run. `paths` are the absolute paths the gate resolved. Oldest first.
521
+ */
522
+ forgeWriteCalls(session) {
523
+ const rows = this.db
524
+ .prepare(`SELECT e.tool_call_id AS tool_call_id, c.paths_json AS paths_json,
525
+ t.run_id AS run_id, t.started_at AS started_at
526
+ FROM forge_calls c
527
+ JOIN forge_executions e ON e.id = c.execution_id
528
+ LEFT JOIN tool_calls t ON t.session = e.session_id AND t.call_id = e.tool_call_id
529
+ WHERE e.session_id = ? AND c.effect = 'write' AND c.status != 'failed'
530
+ AND c.paths_json IS NOT NULL
531
+ ORDER BY t.started_at, c.rowid`)
532
+ .all(session);
533
+ return rows.map((row) => ({
534
+ toolCallId: row.tool_call_id,
535
+ paths: JSON.parse(row.paths_json),
536
+ ...(row.run_id ? { runId: row.run_id } : {}),
537
+ ...(row.started_at != null ? { startedAt: Number(row.started_at) } : {}),
538
+ }));
539
+ }
436
540
  /** Rich (ui/image) parts persist as part of the serialized result and replay verbatim. */
437
541
  callResult(id, callId) {
438
542
  const row = this.db
@@ -5,6 +5,10 @@ import type { AnalysisRerun } from "../analysis/rerun.ts";
5
5
  import { type AnalysisRuntimeManager } from "../analysis/runtime-manager.ts";
6
6
  import { type ArtifactStore } from "../artifacts/store.ts";
7
7
  import type { ToolRegistry } from "../core/registry.ts";
8
+ import type { ExecutionKernel } from "../forge/kernel.ts";
9
+ import { type IsolationPolicy, type PythonRuntimeSetting } from "../forge/python/backend-selector.ts";
10
+ import type { PyodideBackendDeps } from "../forge/python/pyodide-backend.ts";
11
+ import type { EngineRegistry } from "../forge/registry.ts";
8
12
  export declare const NOT_SANDBOXED = "Managed Python is not a sandbox: the script runs with your user permissions and can read your files and use the network.";
9
13
  export interface AnalysisLimits {
10
14
  timeoutMs: number;
@@ -17,13 +21,30 @@ export interface AnalysisToolDeps {
17
21
  jobs: AnalysisJobs;
18
22
  /** Discovery (`interpreter`) and, for the optional extras, `hasExtras` / `installExtras`. */
19
23
  runtime: Pick<AnalysisRuntimeManager, "interpreter"> & Partial<Pick<AnalysisRuntimeManager, "hasExtras" | "installExtras">>;
20
- /** Container mode (`analysis.runtime: "oci"`), read when each call starts. */
24
+ /** `analysis.runtime` and the container runtime, read when each call starts. */
21
25
  oci?: {
22
- mode(): "managed" | "oci";
26
+ mode(): PythonRuntimeSetting;
23
27
  runtime(): OciRuntime;
24
28
  };
29
+ /** `analysis.isolation`, read when each call starts (`preferred` when absent). */
30
+ isolation?: () => IsolationPolicy;
31
+ /** The Pyodide backend (`analysis.runtime: "wasm"`, and a candidate of `auto`). */
32
+ wasm?: PyodideBackendDeps;
25
33
  /** Rerun of an earlier execution (`rerunOf`). */
26
34
  rerun?: AnalysisRerun;
35
+ /**
36
+ * The Forja kernel and engine registry shared with `js_run` (one journal, one state store). When
37
+ * absent the tool builds a private kernel over the jobs' database.
38
+ */
39
+ forge?: {
40
+ kernel: ExecutionKernel;
41
+ engines: EngineRegistry;
42
+ };
43
+ /**
44
+ * The verified Forja scratchpad of a session; undefined while there is none (Forja off, or
45
+ * `--read-only`). It enables `codePath` and is exposed to the script read-only.
46
+ */
47
+ scratchpad?: (session: string) => Promise<string | undefined>;
27
48
  /** Datasets of the session: `inputs: [{ datasetId }]` copies the dataset's SQLite file. */
28
49
  datasets?: DatasetService;
29
50
  rootOf: (sessionId: string) => string;
@@ -33,5 +54,7 @@ export interface AnalysisToolDeps {
33
54
  candidates: boolean;
34
55
  extras: string[];
35
56
  };
57
+ /** Whether `forge_guide` exists now; error results then point at `python.environment` (spec §8.4). */
58
+ guideHints?: () => boolean;
36
59
  }
37
60
  export declare function registerAnalysisTools(registry: ToolRegistry, deps: AnalysisToolDeps): void;