@arnilo/prism-coding-agent 0.0.96 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/CHANGELOG.md +139 -3
  2. package/README.md +48 -19
  3. package/dist/ask-user-decision.d.ts +160 -0
  4. package/dist/ask-user-decision.js +495 -0
  5. package/dist/atomic-write.d.ts +3 -0
  6. package/dist/atomic-write.js +24 -0
  7. package/dist/checks.js +5 -0
  8. package/dist/coding-checkpoint.js +6 -15
  9. package/dist/delete.d.ts +29 -0
  10. package/dist/delete.js +119 -0
  11. package/dist/edit-diff.js +1 -4
  12. package/dist/edit.d.ts +5 -1
  13. package/dist/edit.js +20 -9
  14. package/dist/effects.d.ts +33 -0
  15. package/dist/effects.js +89 -0
  16. package/dist/execution-policy.d.ts +8 -3
  17. package/dist/execution-policy.js +5 -2
  18. package/dist/file-mutation-queue.js +1 -2
  19. package/dist/forge/github.d.ts +2 -0
  20. package/dist/forge/github.js +554 -0
  21. package/dist/forge/index.d.ts +3 -0
  22. package/dist/forge/index.js +3 -0
  23. package/dist/forge/types.d.ts +150 -0
  24. package/dist/forge/types.js +19 -0
  25. package/dist/git-aware-repository.d.ts +25 -0
  26. package/dist/git-aware-repository.js +268 -0
  27. package/dist/git-exec.js +1 -1
  28. package/dist/git-tools.d.ts +4 -1
  29. package/dist/git-tools.js +15 -7
  30. package/dist/git.d.ts +3 -3
  31. package/dist/git.js +14 -14
  32. package/dist/glob-match.d.ts +6 -0
  33. package/dist/glob-match.js +81 -0
  34. package/dist/glob.d.ts +14 -0
  35. package/dist/glob.js +147 -0
  36. package/dist/goal-verify.d.ts +66 -0
  37. package/dist/goal-verify.js +280 -0
  38. package/dist/index.d.ts +63 -30
  39. package/dist/index.js +40 -16
  40. package/dist/language/client.d.ts +44 -0
  41. package/dist/language/client.js +290 -0
  42. package/dist/language/framing.d.ts +23 -0
  43. package/dist/language/framing.js +112 -0
  44. package/dist/language/index.d.ts +4 -0
  45. package/dist/language/index.js +4 -0
  46. package/dist/language/intelligence.d.ts +10 -0
  47. package/dist/language/intelligence.js +526 -0
  48. package/dist/language/types.d.ts +106 -0
  49. package/dist/language/types.js +21 -0
  50. package/dist/lifecycle.d.ts +75 -0
  51. package/dist/lifecycle.js +102 -0
  52. package/dist/limits.d.ts +41 -0
  53. package/dist/limits.js +41 -0
  54. package/dist/list.js +6 -10
  55. package/dist/move.d.ts +24 -0
  56. package/dist/move.js +150 -0
  57. package/dist/mutation-path.d.ts +7 -0
  58. package/dist/mutation-path.js +51 -0
  59. package/dist/output-accumulator.d.ts +8 -0
  60. package/dist/output-accumulator.js +45 -1
  61. package/dist/path-utils.js +1 -1
  62. package/dist/process/index.d.ts +3 -0
  63. package/dist/process/index.js +3 -0
  64. package/dist/process/sessions.d.ts +2 -0
  65. package/dist/process/sessions.js +592 -0
  66. package/dist/process/types.d.ts +146 -0
  67. package/dist/process/types.js +19 -0
  68. package/dist/read-path-set.d.ts +14 -0
  69. package/dist/read-path-set.js +26 -0
  70. package/dist/read.d.ts +3 -0
  71. package/dist/read.js +11 -17
  72. package/dist/repository.d.ts +54 -3
  73. package/dist/repository.js +144 -38
  74. package/dist/search.d.ts +1 -1
  75. package/dist/search.js +91 -27
  76. package/dist/shell.d.ts +3 -0
  77. package/dist/shell.js +23 -8
  78. package/dist/truncate.js +1 -1
  79. package/dist/write.d.ts +5 -1
  80. package/dist/write.js +19 -6
  81. package/package.json +6 -4
package/dist/git.js CHANGED
@@ -5,12 +5,12 @@
5
5
  * `git check-ref-format` for refs, and safe config that disables hooks,
6
6
  * external diff/textconv, pagers, and credential prompts by default.
7
7
  */
8
- import { mkdtemp, writeFile, rm } from "node:fs/promises";
8
+ import { mkdtemp, rm, writeFile } from "node:fs/promises";
9
9
  import { tmpdir } from "node:os";
10
10
  import { join } from "node:path";
11
- import { DEFAULT_MAX_GIT_CHANGED_FILES, DEFAULT_MAX_GIT_DIFF_LINES, DEFAULT_MAX_GIT_MESSAGE_BYTES, DEFAULT_MAX_GIT_OUTPUT_BYTES, DEFAULT_MAX_GIT_PATCH_BYTES, DEFAULT_MAX_GIT_PATHS, DEFAULT_MAX_GIT_REF_BYTES, DEFAULT_MAX_GIT_WORKTREES, DEFAULT_MAX_PR_COMMITS, DEFAULT_MAX_PR_HANDOFF_BYTES, HARD_MAX_GIT_CHANGED_FILES, HARD_MAX_GIT_DIFF_LINES, HARD_MAX_GIT_MESSAGE_BYTES, HARD_MAX_GIT_OUTPUT_BYTES, HARD_MAX_GIT_PATCH_BYTES, HARD_MAX_GIT_PATHS, HARD_MAX_GIT_REF_BYTES, HARD_MAX_GIT_WORKTREES, HARD_MAX_PR_COMMITS, HARD_MAX_PR_HANDOFF_BYTES, validateCodingLimit, } from "./limits.js";
12
11
  import { createBoundGitRunner, GitError, gitRequireOk, gitText, } from "./git-exec.js";
13
12
  import { parsePorcelainV2 } from "./git-status.js";
13
+ import { DEFAULT_MAX_GIT_CHANGED_FILES, DEFAULT_MAX_GIT_DIFF_LINES, DEFAULT_MAX_GIT_MESSAGE_BYTES, DEFAULT_MAX_GIT_OUTPUT_BYTES, DEFAULT_MAX_GIT_PATCH_BYTES, DEFAULT_MAX_GIT_PATHS, DEFAULT_MAX_GIT_REF_BYTES, DEFAULT_MAX_GIT_WORKTREES, DEFAULT_MAX_PR_COMMITS, DEFAULT_MAX_PR_HANDOFF_BYTES, HARD_MAX_GIT_CHANGED_FILES, HARD_MAX_GIT_DIFF_LINES, HARD_MAX_GIT_MESSAGE_BYTES, HARD_MAX_GIT_OUTPUT_BYTES, HARD_MAX_GIT_PATCH_BYTES, HARD_MAX_GIT_PATHS, HARD_MAX_GIT_REF_BYTES, HARD_MAX_GIT_WORKTREES, HARD_MAX_PR_COMMITS, HARD_MAX_PR_HANDOFF_BYTES, validateCodingLimit, } from "./limits.js";
14
14
  import { resolveToCwd } from "./path-utils.js";
15
15
  export function resolveGitLimits(options) {
16
16
  return {
@@ -77,7 +77,7 @@ function truncateLines(text, maxLines) {
77
77
  const lineCount = lines.length;
78
78
  if (lineCount <= maxLines)
79
79
  return { text, truncated: false, lineCount };
80
- const kept = lines.slice(0, maxLines).join("\n") + "\n";
80
+ const kept = `${lines.slice(0, maxLines).join("\n")}\n`;
81
81
  return { text: kept, truncated: true, lineCount };
82
82
  }
83
83
  async function withTempFile(prefix, contents, fn) {
@@ -292,9 +292,7 @@ export async function createGitOperations(options) {
292
292
  ? await ensureCleanOrCheckpoint(request.createCheckpoint, request.signal, `git apply ${request.action}`)
293
293
  : undefined;
294
294
  // Always check first for apply/reverse.
295
- const checkArgs = request.action === "reverse"
296
- ? ["apply", "--reverse", "--check"]
297
- : ["apply", "--check"];
295
+ const checkArgs = request.action === "reverse" ? ["apply", "--reverse", "--check"] : ["apply", "--check"];
298
296
  const check = await runApply(checkArgs, filePath);
299
297
  if (check.exitCode !== 0) {
300
298
  const output = (gitText(check, "stderr") || gitText(check)).trim();
@@ -302,9 +300,7 @@ export async function createGitOperations(options) {
302
300
  await restoreCheckpoint(checkpoint, request.signal).catch(() => undefined);
303
301
  return { ok: false, checkpoint, restored: Boolean(checkpoint), output: output || "patch check failed" };
304
302
  }
305
- const applyArgs = request.action === "reverse"
306
- ? ["apply", "--reverse"]
307
- : ["apply"];
303
+ const applyArgs = request.action === "reverse" ? ["apply", "--reverse"] : ["apply"];
308
304
  const result = await runApply(applyArgs, filePath);
309
305
  if (result.exitCode !== 0) {
310
306
  const output = (gitText(result, "stderr") || gitText(result)).trim();
@@ -314,12 +310,14 @@ export async function createGitOperations(options) {
314
310
  }
315
311
  else {
316
312
  // Best-effort restore of tracked files when no checkpoint was taken (clean tree).
317
- await runner.exec({
313
+ await runner
314
+ .exec({
318
315
  args: ["checkout", "--", "."],
319
316
  cwd,
320
317
  signal: request.signal,
321
318
  maxOutputBytes: limits.maxOutputBytes,
322
- }).catch(() => undefined);
319
+ })
320
+ .catch(() => undefined);
323
321
  restored = true;
324
322
  }
325
323
  return { ok: false, checkpoint, restored, output: output || `apply failed with exit ${result.exitCode}` };
@@ -378,12 +376,14 @@ export async function createGitOperations(options) {
378
376
  }
379
377
  catch (error) {
380
378
  // Reset index for the attempted paths; never drop pre-existing dirty work unless checkpointed.
381
- await runner.exec({
379
+ await runner
380
+ .exec({
382
381
  args: ["reset", "-q", "HEAD", "--", ...paths],
383
382
  cwd,
384
383
  signal: request.signal,
385
384
  maxOutputBytes: limits.maxOutputBytes,
386
- }).catch(() => undefined);
385
+ })
386
+ .catch(() => undefined);
387
387
  if (checkpoint)
388
388
  await restoreCheckpoint(checkpoint, request.signal).catch(() => undefined);
389
389
  throw error;
@@ -490,6 +490,6 @@ export async function createGitOperations(options) {
490
490
  }
491
491
  return { status, diff, branch, worktree, apply, commit, prHandoff };
492
492
  }
493
+ export { createBoundGitRunner, GitError, runGitCli, SAFE_GIT_CONFIG_ARGS, SAFE_GIT_ENV, } from "./git-exec.js";
493
494
  export { parsePorcelainV2 } from "./git-status.js";
494
- export { GitError, SAFE_GIT_ENV, SAFE_GIT_CONFIG_ARGS, createBoundGitRunner, runGitCli, } from "./git-exec.js";
495
495
  //# sourceMappingURL=git.js.map
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Minimal glob matcher: `*`, `?`, and `**` only. No brace expansion, no regex.
3
+ */
4
+ export declare function validateGlobPattern(pattern: string, maxPatternBytes: number): void;
5
+ /** Match a workspace-relative path against a glob pattern using `/` separators. */
6
+ export declare function matchGlobPattern(pattern: string, path: string): boolean;
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Minimal glob matcher: `*`, `?`, and `**` only. No brace expansion, no regex.
3
+ */
4
+ export function validateGlobPattern(pattern, maxPatternBytes) {
5
+ const patternBytes = Buffer.byteLength(pattern, "utf8");
6
+ if (patternBytes < 1)
7
+ throw new Error("pattern must be non-empty");
8
+ if (patternBytes > maxPatternBytes) {
9
+ throw new Error(`pattern exceeds ${maxPatternBytes} byte pattern limit`);
10
+ }
11
+ if (pattern.includes("{") || pattern.includes("}")) {
12
+ throw new Error("brace expansion is not supported in glob patterns");
13
+ }
14
+ }
15
+ function matchSegment(pattern, segment) {
16
+ function go(pi, si) {
17
+ if (pi === pattern.length)
18
+ return si === segment.length;
19
+ const pc = pattern[pi];
20
+ if (pc === "*") {
21
+ if (pi === pattern.length - 1)
22
+ return true;
23
+ for (let k = si; k <= segment.length; k++) {
24
+ if (go(pi + 1, k))
25
+ return true;
26
+ }
27
+ return false;
28
+ }
29
+ if (pc === "?") {
30
+ if (si >= segment.length)
31
+ return false;
32
+ return go(pi + 1, si + 1);
33
+ }
34
+ if (si >= segment.length || pc !== segment[si])
35
+ return false;
36
+ return go(pi + 1, si + 1);
37
+ }
38
+ return go(0, 0);
39
+ }
40
+ function splitPattern(pattern) {
41
+ const normalized = pattern.replace(/\\/g, "/");
42
+ if (normalized === "")
43
+ return [];
44
+ const parts = normalized.split("/");
45
+ if (parts.length > 0 && parts[0] === "")
46
+ parts.shift();
47
+ if (parts.length > 0 && parts[parts.length - 1] === "")
48
+ parts.pop();
49
+ return parts;
50
+ }
51
+ function matchSegments(patternParts, pathParts, pi, pj) {
52
+ while (pi < patternParts.length) {
53
+ const part = patternParts[pi];
54
+ if (part === "**") {
55
+ pi++;
56
+ if (pi === patternParts.length)
57
+ return true;
58
+ for (let k = pj; k <= pathParts.length; k++) {
59
+ if (matchSegments(patternParts, pathParts, pi, k))
60
+ return true;
61
+ }
62
+ return false;
63
+ }
64
+ if (pj >= pathParts.length)
65
+ return false;
66
+ if (!matchSegment(part, pathParts[pj]))
67
+ return false;
68
+ pi++;
69
+ pj++;
70
+ }
71
+ return pj === pathParts.length;
72
+ }
73
+ /** Match a workspace-relative path against a glob pattern using `/` separators. */
74
+ export function matchGlobPattern(pattern, path) {
75
+ const patternParts = splitPattern(pattern);
76
+ const pathParts = splitPattern(path);
77
+ if (patternParts.length === 0)
78
+ return pathParts.length === 0;
79
+ return matchSegments(patternParts, pathParts, 0, 0);
80
+ }
81
+ //# sourceMappingURL=glob-match.js.map
package/dist/glob.d.ts ADDED
@@ -0,0 +1,14 @@
1
+ /**
2
+ * `glob` tool: bounded native pattern file finder.
3
+ */
4
+ import type { ExecutionPolicy, ToolDefinition } from "@arnilo/prism";
5
+ import { type RepositoryLimitOptions, type RepositoryOperations } from "./repository.js";
6
+ export interface GlobToolOptions {
7
+ executionPolicy?: ExecutionPolicy;
8
+ operations?: RepositoryOperations;
9
+ repository?: RepositoryLimitOptions;
10
+ maxDepth?: number;
11
+ maxResults?: number;
12
+ exclude?: readonly string[];
13
+ }
14
+ export declare function createGlobTool(cwd: string, options?: GlobToolOptions): ToolDefinition;
package/dist/glob.js ADDED
@@ -0,0 +1,147 @@
1
+ import { CODING_OBSERVATION_EFFECT } from "./effects.js";
2
+ import { enforceExecutionPolicy } from "./execution-policy.js";
3
+ import { HARD_MAX_REPO_DEPTH, HARD_MAX_REPO_RESULTS, validateCodingLimit, validateCodingLimitAllowZero } from "./limits.js";
4
+ import { createLocalRepositoryOperations, RepositoryError, resolveRepositoryLimits, } from "./repository.js";
5
+ function errorResult(toolCallId, message) {
6
+ return {
7
+ toolCallId,
8
+ name: "glob",
9
+ content: [{ type: "text", text: message }],
10
+ error: { message },
11
+ };
12
+ }
13
+ function formatGlobText(result) {
14
+ if (result.paths.length === 0) {
15
+ return result.truncated ? `[truncated by ${result.truncatedBy ?? "limit"} before any matches]` : "(no matches)";
16
+ }
17
+ const lines = [...result.paths];
18
+ if (result.truncated) {
19
+ const next = result.nextOffset !== undefined ? ` Use offset=${result.nextOffset} to continue.` : "";
20
+ lines.push(`[truncated by ${result.truncatedBy ?? "limit"}.${next}]`);
21
+ }
22
+ return lines.join("\n");
23
+ }
24
+ export function createGlobTool(cwd, options) {
25
+ const limits = resolveRepositoryLimits({
26
+ ...options?.repository,
27
+ maxDepth: options?.maxDepth ?? options?.repository?.maxDepth,
28
+ maxResults: options?.maxResults ?? options?.repository?.maxResults,
29
+ exclude: options?.exclude ?? options?.repository?.exclude,
30
+ });
31
+ const ops = options?.operations ?? createLocalRepositoryOperations(limits);
32
+ return {
33
+ name: "glob",
34
+ effect: CODING_OBSERVATION_EFFECT,
35
+ description: `Find workspace files by glob pattern without shell find. Supports * (segment), ? (one char), and ** (directories). Brace expansion is rejected. Skips hidden names and excluded basenames (default: ${limits.exclude.join(", ")}) unless overridden. Does not follow symlinks. Results paginate with offset/maxResults (default ${limits.maxResults}). Depth default ${limits.maxDepth}. Prefer repo_list to enumerate directories and repo_search to find text inside files.`,
36
+ parameters: {
37
+ type: "object",
38
+ properties: {
39
+ pattern: {
40
+ type: "string",
41
+ description: "Glob pattern matched against workspace-relative file paths (required)",
42
+ },
43
+ path: {
44
+ type: "string",
45
+ description: "Workspace-relative directory or file to search under (default: workspace root)",
46
+ },
47
+ includeHidden: {
48
+ type: "boolean",
49
+ description: "Include dotfile/dotdir names (default false). Excluded basenames still apply.",
50
+ },
51
+ maxDepth: {
52
+ type: "number",
53
+ description: `Maximum directory depth to descend (default ${limits.maxDepth}, hard ${HARD_MAX_REPO_DEPTH})`,
54
+ },
55
+ maxResults: {
56
+ type: "number",
57
+ description: `Maximum paths returned in this page (default ${limits.maxResults}, hard ${HARD_MAX_REPO_RESULTS})`,
58
+ },
59
+ offset: {
60
+ type: "number",
61
+ description: "Number of matching paths to skip before retaining results (default 0)",
62
+ },
63
+ },
64
+ required: ["pattern"],
65
+ additionalProperties: false,
66
+ },
67
+ async execute(args, context) {
68
+ const toolCallId = context.toolCallId;
69
+ if (context.signal?.aborted)
70
+ return errorResult(toolCallId, "Operation aborted");
71
+ const pattern = typeof args.pattern === "string" ? args.pattern : "";
72
+ if (!pattern)
73
+ return errorResult(toolCallId, "pattern must be a non-empty string");
74
+ const path = typeof args.path === "string" ? args.path : undefined;
75
+ const includeHidden = args.includeHidden === true;
76
+ let maxDepth;
77
+ let maxResults;
78
+ let offset = 0;
79
+ try {
80
+ if (args.maxDepth !== undefined) {
81
+ maxDepth = validateCodingLimit("maxDepth", args.maxDepth, HARD_MAX_REPO_DEPTH);
82
+ }
83
+ if (args.maxResults !== undefined) {
84
+ maxResults = validateCodingLimit("maxResults", args.maxResults, HARD_MAX_REPO_RESULTS);
85
+ }
86
+ if (args.offset !== undefined) {
87
+ offset = validateCodingLimitAllowZero("offset", args.offset, limits.maxEntries);
88
+ }
89
+ }
90
+ catch (error) {
91
+ return errorResult(toolCallId, error instanceof Error ? error.message : String(error));
92
+ }
93
+ const policyCheck = await enforceExecutionPolicy(options?.executionPolicy, {
94
+ kind: "glob",
95
+ operation: "glob",
96
+ paths: [path ? path : cwd],
97
+ risk: "low",
98
+ metadata: {
99
+ pattern,
100
+ includeHidden,
101
+ maxDepth,
102
+ maxResults,
103
+ offset,
104
+ sessionId: context.sessionId,
105
+ runId: context.runId,
106
+ signal: context.signal,
107
+ },
108
+ }, toolCallId, "glob");
109
+ if (!policyCheck.allowed)
110
+ return policyCheck.result;
111
+ try {
112
+ const result = await ops.glob({
113
+ root: cwd,
114
+ pattern,
115
+ path,
116
+ includeHidden,
117
+ exclude: limits.exclude,
118
+ maxDepth: maxDepth ?? limits.maxDepth,
119
+ maxResults: maxResults ?? limits.maxResults,
120
+ offset,
121
+ signal: context.signal,
122
+ deadlineMs: limits.maxTimeMs,
123
+ });
124
+ return {
125
+ toolCallId,
126
+ name: "glob",
127
+ content: [{ type: "text", text: formatGlobText(result) }],
128
+ metadata: {
129
+ truncated: result.truncated,
130
+ truncatedBy: result.truncatedBy,
131
+ offset: result.offset,
132
+ nextOffset: result.nextOffset,
133
+ returned: result.paths.length,
134
+ scannedEntries: result.scannedEntries,
135
+ scannedFiles: result.scannedFiles,
136
+ paths: result.paths,
137
+ },
138
+ };
139
+ }
140
+ catch (error) {
141
+ const message = error instanceof RepositoryError ? error.message : error instanceof Error ? error.message : String(error);
142
+ return errorResult(toolCallId, message);
143
+ }
144
+ },
145
+ };
146
+ }
147
+ //# sourceMappingURL=glob.js.map
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Thin goal→verify composition: plan Markdown + named checks + workflow
3
+ * suspend/approve + bounded handoff. Not a second agent/workflow engine.
4
+ */
5
+ import type { OwnershipScope, SecretRedactor } from "@arnilo/prism";
6
+ import { type WorkflowCheckpointAdapter, type WorkflowEvent, type WorkflowResumeValidator, type WorkflowRunResult } from "@arnilo/prism-workflows";
7
+ import { type CodingCheckpointMetadata, type CodingCheckSummary, type CodingHandoffSummary } from "./coding-checkpoint.js";
8
+ export declare const CODING_GOAL_VERIFY_WORKFLOW_ID: "coding-goal-verify";
9
+ export declare const CODING_GOAL_VERIFY_REVISION: "1";
10
+ export declare const CODING_GOAL_VERIFY_SUSPEND_REASON: "approve-coding-goal-verify";
11
+ export declare class CodingGoalVerifyError extends Error {
12
+ readonly code = "ERR_PRISM_CODING_GOAL_VERIFY";
13
+ constructor(message: string);
14
+ }
15
+ export interface CodingGoalVerifyApproval {
16
+ /** Host validator; required — helper fails closed without it. */
17
+ readonly validateResume: WorkflowResumeValidator;
18
+ readonly reason?: string;
19
+ }
20
+ export interface RunCodingGoalVerifyOptions {
21
+ readonly goal: string;
22
+ readonly cwd: string;
23
+ readonly taskId?: string;
24
+ readonly title?: string;
25
+ readonly baseBranch?: string;
26
+ readonly branch?: string;
27
+ /** Named checks to execute via `runCheck` (host-declared; no free-form shell). */
28
+ readonly checks: readonly string[];
29
+ readonly runCheck: (name: string) => Promise<CodingCheckSummary>;
30
+ /** Host-owned bounded handoff; required before completion. */
31
+ readonly buildHandoff: (input: {
32
+ readonly coding: CodingCheckpointMetadata;
33
+ readonly checks: readonly CodingCheckSummary[];
34
+ }) => Promise<CodingHandoffSummary>;
35
+ readonly approval: CodingGoalVerifyApproval;
36
+ readonly checkpoints: WorkflowCheckpointAdapter;
37
+ readonly ownership?: OwnershipScope;
38
+ readonly redactor?: SecretRedactor;
39
+ readonly signal?: AbortSignal;
40
+ readonly onEvent?: (event: WorkflowEvent) => void;
41
+ /** Second call after suspension — mirrors workflow resume. */
42
+ readonly resume?: {
43
+ readonly runId: string;
44
+ readonly decision: "approve" | "deny";
45
+ readonly expectedVersion: number;
46
+ readonly input?: unknown;
47
+ };
48
+ }
49
+ /** Build the durable DAG used by `runCodingGoalVerify` (exported for hosts that want the definition alone). */
50
+ export declare function createCodingGoalVerifyWorkflow(options: {
51
+ readonly goal: string;
52
+ readonly cwd: string;
53
+ readonly taskId: string;
54
+ readonly title: string;
55
+ readonly baseBranch: string;
56
+ readonly branch: string;
57
+ readonly checks: readonly string[];
58
+ readonly runCheck: (name: string) => Promise<CodingCheckSummary>;
59
+ readonly buildHandoff: RunCodingGoalVerifyOptions["buildHandoff"];
60
+ readonly suspendReason: string;
61
+ }): import("@arnilo/prism-workflows").WorkflowDefinition;
62
+ /**
63
+ * Run (or resume) a thin goal→verify coding composition.
64
+ * Fails closed when `approval` / `approval.validateResume` is missing.
65
+ */
66
+ export declare function runCodingGoalVerify(options: RunCodingGoalVerifyOptions): Promise<WorkflowRunResult>;