@enderfga/claw-orchestrator 5.0.0 → 6.0.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 (158) hide show
  1. package/README.md +28 -28
  2. package/dist/bin/cli.js +107 -1
  3. package/dist/bin/cli.js.map +1 -1
  4. package/dist/src/acp-server.d.ts +5 -5
  5. package/dist/src/acp-server.js +3 -3
  6. package/dist/src/acp-server.js.map +1 -1
  7. package/dist/src/autoloop/dispatcher.d.ts +22 -0
  8. package/dist/src/autoloop/dispatcher.js +71 -13
  9. package/dist/src/autoloop/dispatcher.js.map +1 -1
  10. package/dist/src/autoloop/messages.d.ts +10 -0
  11. package/dist/src/autoloop/messages.js.map +1 -1
  12. package/dist/src/autoloop/runner.js +6 -0
  13. package/dist/src/autoloop/runner.js.map +1 -1
  14. package/dist/src/constants.d.ts +0 -6
  15. package/dist/src/constants.js +0 -6
  16. package/dist/src/constants.js.map +1 -1
  17. package/dist/src/council.d.ts +15 -0
  18. package/dist/src/council.js +48 -35
  19. package/dist/src/council.js.map +1 -1
  20. package/dist/src/dashboard/index.html +191 -6
  21. package/dist/src/embedded-server.js +132 -9
  22. package/dist/src/embedded-server.js.map +1 -1
  23. package/dist/src/fanout.d.ts +30 -1
  24. package/dist/src/fanout.js +32 -3
  25. package/dist/src/fanout.js.map +1 -1
  26. package/dist/src/index.d.ts +1 -0
  27. package/dist/src/index.js +360 -4
  28. package/dist/src/index.js.map +1 -1
  29. package/dist/src/kernel/agent-step.d.ts +59 -0
  30. package/dist/src/kernel/agent-step.js +100 -0
  31. package/dist/src/kernel/agent-step.js.map +1 -0
  32. package/dist/src/kernel/conditions.d.ts +11 -0
  33. package/dist/src/kernel/conditions.js +24 -0
  34. package/dist/src/kernel/conditions.js.map +1 -0
  35. package/dist/src/kernel/engine.d.ts +319 -0
  36. package/dist/src/kernel/engine.js +1047 -0
  37. package/dist/src/kernel/engine.js.map +1 -0
  38. package/dist/src/kernel/exec.d.ts +43 -0
  39. package/dist/src/kernel/exec.js +112 -0
  40. package/dist/src/kernel/exec.js.map +1 -0
  41. package/dist/src/kernel/file-lock.d.ts +50 -0
  42. package/dist/src/kernel/file-lock.js +135 -0
  43. package/dist/src/kernel/file-lock.js.map +1 -0
  44. package/dist/src/kernel/nodes/agent.d.ts +4 -0
  45. package/dist/src/kernel/nodes/agent.js +35 -0
  46. package/dist/src/kernel/nodes/agent.js.map +1 -0
  47. package/dist/src/kernel/nodes/autoloop.d.ts +78 -0
  48. package/dist/src/kernel/nodes/autoloop.js +75 -0
  49. package/dist/src/kernel/nodes/autoloop.js.map +1 -0
  50. package/dist/src/kernel/nodes/council.d.ts +12 -0
  51. package/dist/src/kernel/nodes/council.js +88 -0
  52. package/dist/src/kernel/nodes/council.js.map +1 -0
  53. package/dist/src/kernel/nodes/fanout.d.ts +11 -0
  54. package/dist/src/kernel/nodes/fanout.js +63 -0
  55. package/dist/src/kernel/nodes/fanout.js.map +1 -0
  56. package/dist/src/kernel/nodes/human-gate.d.ts +4 -0
  57. package/dist/src/kernel/nodes/human-gate.js +7 -0
  58. package/dist/src/kernel/nodes/human-gate.js.map +1 -0
  59. package/dist/src/kernel/nodes/index.d.ts +12 -0
  60. package/dist/src/kernel/nodes/index.js +21 -0
  61. package/dist/src/kernel/nodes/index.js.map +1 -0
  62. package/dist/src/kernel/nodes/router.d.ts +4 -0
  63. package/dist/src/kernel/nodes/router.js +12 -0
  64. package/dist/src/kernel/nodes/router.js.map +1 -0
  65. package/dist/src/kernel/nodes/subflow.d.ts +13 -0
  66. package/dist/src/kernel/nodes/subflow.js +38 -0
  67. package/dist/src/kernel/nodes/subflow.js.map +1 -0
  68. package/dist/src/kernel/nodes/ultraapp.d.ts +60 -0
  69. package/dist/src/kernel/nodes/ultraapp.js +62 -0
  70. package/dist/src/kernel/nodes/ultraapp.js.map +1 -0
  71. package/dist/src/kernel/nodes/verifier.d.ts +14 -0
  72. package/dist/src/kernel/nodes/verifier.js +84 -0
  73. package/dist/src/kernel/nodes/verifier.js.map +1 -0
  74. package/dist/src/kernel/projections.d.ts +42 -0
  75. package/dist/src/kernel/projections.js +133 -0
  76. package/dist/src/kernel/projections.js.map +1 -0
  77. package/dist/src/kernel/repo.d.ts +13 -0
  78. package/dist/src/kernel/repo.js +64 -0
  79. package/dist/src/kernel/repo.js.map +1 -0
  80. package/dist/src/kernel/secrets.d.ts +25 -0
  81. package/dist/src/kernel/secrets.js +48 -0
  82. package/dist/src/kernel/secrets.js.map +1 -0
  83. package/dist/src/kernel/store.d.ts +225 -0
  84. package/dist/src/kernel/store.js +838 -0
  85. package/dist/src/kernel/store.js.map +1 -0
  86. package/dist/src/kernel/templates/index.d.ts +140 -0
  87. package/dist/src/kernel/templates/index.js +266 -0
  88. package/dist/src/kernel/templates/index.js.map +1 -0
  89. package/dist/src/kernel/types.d.ts +326 -0
  90. package/dist/src/kernel/types.js +19 -0
  91. package/dist/src/kernel/types.js.map +1 -0
  92. package/dist/src/models.d.ts +1 -1
  93. package/dist/src/models.js +31 -3
  94. package/dist/src/models.js.map +1 -1
  95. package/dist/src/persistent-cursor-session.js +6 -1
  96. package/dist/src/persistent-cursor-session.js.map +1 -1
  97. package/dist/src/persistent-grok-session.d.ts +40 -0
  98. package/dist/src/persistent-grok-session.js +197 -0
  99. package/dist/src/persistent-grok-session.js.map +1 -0
  100. package/dist/src/run-ledger.d.ts +57 -3
  101. package/dist/src/run-ledger.js +45 -2
  102. package/dist/src/run-ledger.js.map +1 -1
  103. package/dist/src/session-manager.d.ts +176 -129
  104. package/dist/src/session-manager.js +657 -603
  105. package/dist/src/session-manager.js.map +1 -1
  106. package/dist/src/types.d.ts +37 -4
  107. package/dist/src/types.js +15 -1
  108. package/dist/src/types.js.map +1 -1
  109. package/dist/src/ultraapp/build.d.ts +117 -3
  110. package/dist/src/ultraapp/build.js +319 -3
  111. package/dist/src/ultraapp/build.js.map +1 -1
  112. package/dist/src/ultraapp/contract.d.ts +52 -0
  113. package/dist/src/ultraapp/contract.js +83 -0
  114. package/dist/src/ultraapp/contract.js.map +1 -0
  115. package/dist/src/ultraapp/conventions.js +9 -2
  116. package/dist/src/ultraapp/conventions.js.map +1 -1
  117. package/dist/src/ultraapp/fix-on-failure.d.ts +21 -2
  118. package/dist/src/ultraapp/fix-on-failure.js +46 -62
  119. package/dist/src/ultraapp/fix-on-failure.js.map +1 -1
  120. package/dist/src/ultraapp/manager.d.ts +107 -2
  121. package/dist/src/ultraapp/manager.js +305 -86
  122. package/dist/src/ultraapp/manager.js.map +1 -1
  123. package/dist/src/verify/baseline.d.ts +73 -0
  124. package/dist/src/verify/baseline.js +186 -0
  125. package/dist/src/verify/baseline.js.map +1 -0
  126. package/dist/src/verify/contract.d.ts +116 -0
  127. package/dist/src/verify/contract.js +142 -0
  128. package/dist/src/verify/contract.js.map +1 -0
  129. package/dist/src/verify/evidence.d.ts +61 -0
  130. package/dist/src/verify/evidence.js +133 -0
  131. package/dist/src/verify/evidence.js.map +1 -0
  132. package/dist/src/verify/runner.d.ts +63 -0
  133. package/dist/src/verify/runner.js +317 -0
  134. package/dist/src/verify/runner.js.map +1 -0
  135. package/openclaw.plugin.json +8 -0
  136. package/package.json +2 -2
  137. package/skills/SKILL.md +121 -80
  138. package/skills/references/acp.md +18 -18
  139. package/skills/references/autoloop.md +148 -72
  140. package/skills/references/claude-cli-tracking.md +4 -4
  141. package/skills/references/cli.md +103 -60
  142. package/skills/references/council.md +109 -37
  143. package/skills/references/dashboard.md +34 -6
  144. package/skills/references/getting-started.md +14 -14
  145. package/skills/references/inbox.md +4 -4
  146. package/skills/references/mcp.md +39 -34
  147. package/skills/references/multi-engine.md +109 -51
  148. package/skills/references/observability.md +88 -27
  149. package/skills/references/openai-compat.md +40 -40
  150. package/skills/references/sessions.md +44 -26
  151. package/skills/references/tools.md +402 -309
  152. package/skills/references/ultra.md +45 -45
  153. package/skills/references/ultraapp.md +126 -50
  154. package/skills/references/verification.md +187 -0
  155. package/skills/references/workflow.md +362 -0
  156. package/dist/src/ultraapp/fix-on-failure-session.d.ts +0 -23
  157. package/dist/src/ultraapp/fix-on-failure-session.js +0 -51
  158. package/dist/src/ultraapp/fix-on-failure-session.js.map +0 -1
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Baseline capture — the primitive nothing in this repo had.
3
+ *
4
+ * Two existing call sites tried to answer "what did this run change" and both
5
+ * get it wrong in a way that matters:
6
+ *
7
+ * - `council.ts` diffs `HEAD~20..HEAD` (with a `HEAD~10` fallback), a hardcoded
8
+ * magic window that silently returns nothing on shallow history and has no
9
+ * relationship to when the run actually started.
10
+ * - `autoloop/dispatcher.ts` runs a bare `git diff`, which lists tracked
11
+ * modifications only. Files the Coder *created* appear in neither the patch
12
+ * nor the `--name-only` fallback, yet the following `git add -A` commits them.
13
+ * So the Reviewer audits a diff that structurally cannot show new files.
14
+ *
15
+ * Here the base commit is recorded when the run starts, and the change set is
16
+ * tracked-diff ∪ untracked-files. Nothing mutates the caller's index: untracked
17
+ * files are rendered with `git diff --no-index /dev/null <file>`, which emits a
18
+ * proper new-file patch without an `add -N`.
19
+ */
20
+ export type ChangeStatus = 'added' | 'modified' | 'deleted' | 'untracked';
21
+ export interface ChangedFile {
22
+ path: string;
23
+ status: ChangeStatus;
24
+ insertions: number;
25
+ deletions: number;
26
+ }
27
+ /** `git rev-parse HEAD`, or undefined when cwd is not a repo (or has no commits yet). */
28
+ export declare function captureBaseline(cwd: string): Promise<string | undefined>;
29
+ /**
30
+ * Everything the run touched since `baseSha`: tracked changes in the working
31
+ * tree (committed or not) plus every untracked file.
32
+ */
33
+ export declare function changedFilesSince(cwd: string, baseSha: string | undefined): Promise<ChangedFile[]>;
34
+ /**
35
+ * A unified patch covering the same set: `git diff <base>` for tracked changes,
36
+ * then a synthetic new-file patch per untracked file appended after it.
37
+ */
38
+ export declare function capturePatch(cwd: string, baseSha: string | undefined): Promise<string>;
39
+ /**
40
+ * A digest of the working tree's current *content*.
41
+ *
42
+ * Evidence describes the tree as it was when the checks ran. If anything moves
43
+ * afterwards the bundle still exists but no longer describes what is there, and
44
+ * a run that keeps reporting `verified` on the strength of it is claiming
45
+ * something nobody measured. Comparing this before and after is how the kernel
46
+ * notices.
47
+ *
48
+ * The first version of this hashed `git rev-parse HEAD` plus
49
+ * `git status --porcelain`, which does not work: porcelain reports a file's
50
+ * *state*, not its bytes. A file that was already `M` before the verifier and
51
+ * is rewritten afterwards still prints ` M a.txt`, so the digest was unchanged
52
+ * and a stale verdict sailed through. The common case — an agent editing a file
53
+ * it had already edited — was exactly the case it missed.
54
+ *
55
+ * So this hashes content: HEAD, the full `git diff HEAD` patch (which covers
56
+ * staged and unstaged changes to tracked files), and the path plus bytes of
57
+ * every untracked file.
58
+ *
59
+ * Returns undefined outside a repo — a caller that cannot fingerprint must not
60
+ * assume the tree held still.
61
+ */
62
+ export declare function treeFingerprint(cwd: string): Promise<string | undefined>;
63
+ /**
64
+ * True when `file` sits under `prefix`.
65
+ *
66
+ * Segment-aware, so `srcfoo/a.ts` is not under `src`. `.` and `''` both mean the
67
+ * repo root and match everything — without that, a policy of `requirePaths: ['.']`
68
+ * ("the run must change something") reports that nothing changed no matter what
69
+ * the run did.
70
+ */
71
+ export declare function isUnder(file: string, prefix: string): boolean;
72
+ /** Resolve a check-relative path against the run cwd. */
73
+ export declare function resolveIn(cwd: string, p: string): string;
@@ -0,0 +1,186 @@
1
+ /**
2
+ * Baseline capture — the primitive nothing in this repo had.
3
+ *
4
+ * Two existing call sites tried to answer "what did this run change" and both
5
+ * get it wrong in a way that matters:
6
+ *
7
+ * - `council.ts` diffs `HEAD~20..HEAD` (with a `HEAD~10` fallback), a hardcoded
8
+ * magic window that silently returns nothing on shallow history and has no
9
+ * relationship to when the run actually started.
10
+ * - `autoloop/dispatcher.ts` runs a bare `git diff`, which lists tracked
11
+ * modifications only. Files the Coder *created* appear in neither the patch
12
+ * nor the `--name-only` fallback, yet the following `git add -A` commits them.
13
+ * So the Reviewer audits a diff that structurally cannot show new files.
14
+ *
15
+ * Here the base commit is recorded when the run starts, and the change set is
16
+ * tracked-diff ∪ untracked-files. Nothing mutates the caller's index: untracked
17
+ * files are rendered with `git diff --no-index /dev/null <file>`, which emits a
18
+ * proper new-file patch without an `add -N`.
19
+ */
20
+ import crypto from 'node:crypto';
21
+ import fs from 'node:fs';
22
+ import path from 'node:path';
23
+ import { exec } from '../kernel/exec.js';
24
+ const GIT_TIMEOUT_MS = 60_000;
25
+ /** `git rev-parse HEAD`, or undefined when cwd is not a repo (or has no commits yet). */
26
+ export async function captureBaseline(cwd) {
27
+ const r = await exec('git', ['-C', cwd, 'rev-parse', 'HEAD'], { timeoutMs: GIT_TIMEOUT_MS });
28
+ if (r.code !== 0)
29
+ return undefined;
30
+ const sha = r.out.trim();
31
+ return /^[0-9a-f]{7,40}$/i.test(sha) ? sha : undefined;
32
+ }
33
+ async function untrackedFiles(cwd) {
34
+ const r = await exec('git', ['-C', cwd, 'ls-files', '--others', '--exclude-standard'], {
35
+ timeoutMs: GIT_TIMEOUT_MS,
36
+ });
37
+ if (r.code !== 0)
38
+ return [];
39
+ return r.out
40
+ .split('\n')
41
+ .map((l) => l.trim())
42
+ .filter(Boolean);
43
+ }
44
+ async function countLines(cwd, file) {
45
+ const r = await exec('git', ['-C', cwd, 'diff', '--no-index', '--numstat', '/dev/null', file], {
46
+ timeoutMs: GIT_TIMEOUT_MS,
47
+ });
48
+ // `--no-index` exits 1 when there are differences, which is the normal case here.
49
+ const first = r.out.split('\n').find((l) => l.trim() !== '');
50
+ if (!first)
51
+ return 0;
52
+ const n = Number(first.split('\t')[0]);
53
+ return Number.isFinite(n) ? n : 0;
54
+ }
55
+ /**
56
+ * Everything the run touched since `baseSha`: tracked changes in the working
57
+ * tree (committed or not) plus every untracked file.
58
+ */
59
+ export async function changedFilesSince(cwd, baseSha) {
60
+ const files = [];
61
+ if (baseSha) {
62
+ const r = await exec('git', ['-C', cwd, 'diff', '--numstat', '--no-renames', baseSha, '--'], {
63
+ timeoutMs: GIT_TIMEOUT_MS,
64
+ });
65
+ if (r.code === 0) {
66
+ for (const line of r.out.split('\n')) {
67
+ const parts = line.split('\t');
68
+ if (parts.length < 3)
69
+ continue;
70
+ const insertions = Number(parts[0]);
71
+ const deletions = Number(parts[1]);
72
+ const file = parts.slice(2).join('\t').trim();
73
+ if (!file)
74
+ continue;
75
+ // A binary file reports "-\t-"; count it as touched with zero line deltas.
76
+ files.push({
77
+ path: file,
78
+ status: deletions > 0 && insertions === 0 ? 'deleted' : 'modified',
79
+ insertions: Number.isFinite(insertions) ? insertions : 0,
80
+ deletions: Number.isFinite(deletions) ? deletions : 0,
81
+ });
82
+ }
83
+ }
84
+ }
85
+ const seen = new Set(files.map((f) => f.path));
86
+ for (const file of await untrackedFiles(cwd)) {
87
+ if (seen.has(file))
88
+ continue;
89
+ files.push({ path: file, status: 'untracked', insertions: await countLines(cwd, file), deletions: 0 });
90
+ }
91
+ return files.sort((a, b) => a.path.localeCompare(b.path));
92
+ }
93
+ /**
94
+ * A unified patch covering the same set: `git diff <base>` for tracked changes,
95
+ * then a synthetic new-file patch per untracked file appended after it.
96
+ */
97
+ export async function capturePatch(cwd, baseSha) {
98
+ const parts = [];
99
+ if (baseSha) {
100
+ const r = await exec('git', ['-C', cwd, 'diff', '--unified=3', '--no-renames', baseSha, '--'], {
101
+ timeoutMs: GIT_TIMEOUT_MS,
102
+ });
103
+ if (r.code === 0 && r.out.trim())
104
+ parts.push(r.out.replace(/\n*$/, '\n'));
105
+ }
106
+ for (const file of await untrackedFiles(cwd)) {
107
+ const r = await exec('git', ['-C', cwd, 'diff', '--no-index', '--unified=3', '/dev/null', file], {
108
+ cwd,
109
+ timeoutMs: GIT_TIMEOUT_MS,
110
+ });
111
+ // Exit 1 = "differences found", the expected outcome for a new file.
112
+ if ((r.code === 0 || r.code === 1) && r.out.trim())
113
+ parts.push(r.out.replace(/\n*$/, '\n'));
114
+ }
115
+ return parts.join('');
116
+ }
117
+ /**
118
+ * A digest of the working tree's current *content*.
119
+ *
120
+ * Evidence describes the tree as it was when the checks ran. If anything moves
121
+ * afterwards the bundle still exists but no longer describes what is there, and
122
+ * a run that keeps reporting `verified` on the strength of it is claiming
123
+ * something nobody measured. Comparing this before and after is how the kernel
124
+ * notices.
125
+ *
126
+ * The first version of this hashed `git rev-parse HEAD` plus
127
+ * `git status --porcelain`, which does not work: porcelain reports a file's
128
+ * *state*, not its bytes. A file that was already `M` before the verifier and
129
+ * is rewritten afterwards still prints ` M a.txt`, so the digest was unchanged
130
+ * and a stale verdict sailed through. The common case — an agent editing a file
131
+ * it had already edited — was exactly the case it missed.
132
+ *
133
+ * So this hashes content: HEAD, the full `git diff HEAD` patch (which covers
134
+ * staged and unstaged changes to tracked files), and the path plus bytes of
135
+ * every untracked file.
136
+ *
137
+ * Returns undefined outside a repo — a caller that cannot fingerprint must not
138
+ * assume the tree held still.
139
+ */
140
+ export async function treeFingerprint(cwd) {
141
+ const status = await exec('git', ['-C', cwd, 'status', '--porcelain'], { timeoutMs: GIT_TIMEOUT_MS });
142
+ if (status.code !== 0)
143
+ return undefined;
144
+ const head = await exec('git', ['-C', cwd, 'rev-parse', 'HEAD'], { timeoutMs: GIT_TIMEOUT_MS });
145
+ const tracked = await exec('git', ['-C', cwd, 'diff', 'HEAD'], { timeoutMs: GIT_TIMEOUT_MS });
146
+ const hash = crypto.createHash('sha256');
147
+ hash.update(head.code === 0 ? head.out.trim() : 'no-head');
148
+ hash.update('\u0000');
149
+ hash.update(tracked.code === 0 ? tracked.out : status.out);
150
+ // Untracked files are invisible to `git diff`, so hash them by hand — path and
151
+ // bytes both, so a rename and an edit are each detected.
152
+ for (const file of (await untrackedFiles(cwd)).sort()) {
153
+ hash.update('\u0000');
154
+ hash.update(file);
155
+ try {
156
+ hash.update(fs.readFileSync(path.join(cwd, file)));
157
+ }
158
+ catch {
159
+ // Unreadable (a dangling symlink, a race with a delete): record that we
160
+ // could not read it rather than silently treating it as empty.
161
+ hash.update('\u0000unreadable');
162
+ }
163
+ }
164
+ return hash.digest('hex');
165
+ }
166
+ /**
167
+ * True when `file` sits under `prefix`.
168
+ *
169
+ * Segment-aware, so `srcfoo/a.ts` is not under `src`. `.` and `''` both mean the
170
+ * repo root and match everything — without that, a policy of `requirePaths: ['.']`
171
+ * ("the run must change something") reports that nothing changed no matter what
172
+ * the run did.
173
+ */
174
+ export function isUnder(file, prefix) {
175
+ const norm = (p) => p.replace(/\\/g, '/').replace(/^\.\//, '').replace(/\/+$/, '').replace(/^\.$/, '');
176
+ const f = norm(file);
177
+ const p = norm(prefix);
178
+ if (p === '')
179
+ return true;
180
+ return f === p || f.startsWith(p + '/');
181
+ }
182
+ /** Resolve a check-relative path against the run cwd. */
183
+ export function resolveIn(cwd, p) {
184
+ return path.isAbsolute(p) ? p : path.join(cwd, p);
185
+ }
186
+ //# sourceMappingURL=baseline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"baseline.js","sourceRoot":"","sources":["../../../src/verify/baseline.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Acceptance contracts — what the runtime itself checks before calling a run done.
3
+ *
4
+ * Every completion signal that existed before this module was the agent grading
5
+ * its own work: council terminated on a regex over agent prose (`consensus.ts`),
6
+ * autoloop's `eval_output` was whatever the Coder passed to a tool call
7
+ * (`autoloop/agent-tools.ts`), ultraapp's frontend gate was a sentence in a
8
+ * persona string (`ultraapp/council-adapter.ts`). A contract is the opposite:
9
+ * a caller-declared list of checks that *we* execute and whose exit codes we read.
10
+ *
11
+ * Provenance rule, and the reason `normalizeContract` exists: a contract may
12
+ * come from the caller or from a mode default, never from agent output. If an
13
+ * agent could declare its own checks we would be back to self-grading with extra
14
+ * steps. Nothing in the kernel reads a contract out of a node's result.
15
+ */
16
+ /** Argv form only — there is no shell string anywhere, so there is nothing to inject into. */
17
+ export interface CommandCheck {
18
+ type: 'command';
19
+ cmd: string;
20
+ args?: string[];
21
+ /** Relative to the run cwd when not absolute. */
22
+ cwd?: string;
23
+ timeoutMs?: number;
24
+ /** Exit code that counts as pass. Default 0. */
25
+ expectExit?: number;
26
+ }
27
+ export interface HttpCheck {
28
+ type: 'http';
29
+ url: string;
30
+ /** Default 200. */
31
+ expectStatus?: number;
32
+ /** Total time to keep retrying before failing. Default 30s. */
33
+ timeoutMs?: number;
34
+ intervalMs?: number;
35
+ }
36
+ /**
37
+ * Captures and stores a screenshot; it does not judge pixels. The judgement is
38
+ * still a human's or an agent's, but whether the capture actually happened is
39
+ * now decided by the runtime instead of by an agent's self-report. Do not
40
+ * describe this as visual regression — it is evidence collection.
41
+ */
42
+ export interface ScreenshotCheck {
43
+ type: 'screenshot';
44
+ url: string;
45
+ viewports: Array<{
46
+ width: number;
47
+ height: number;
48
+ label?: string;
49
+ }>;
50
+ /** Chrome/Chromium binary; resolved from the usual locations when omitted. */
51
+ browserBin?: string;
52
+ timeoutMs?: number;
53
+ }
54
+ export interface DiffPolicyCheck {
55
+ type: 'diff_policy';
56
+ maxFiles?: number;
57
+ /** Glob-ish prefixes that must not be touched. */
58
+ forbidPaths?: string[];
59
+ /** At least one changed file must sit under one of these. */
60
+ requirePaths?: string[];
61
+ }
62
+ export interface FileCheck {
63
+ type: 'file';
64
+ path: string;
65
+ /** Default true. `false` asserts absence. */
66
+ exists?: boolean;
67
+ /** Applied to file contents when present. */
68
+ matches?: string;
69
+ }
70
+ export type CheckSpec = CommandCheck | HttpCheck | ScreenshotCheck | DiffPolicyCheck | FileCheck;
71
+ export interface ContractCheck {
72
+ /** Stable id used in the evidence bundle. Generated when omitted. */
73
+ id?: string;
74
+ spec: CheckSpec;
75
+ /**
76
+ * A failing non-required check is recorded in the bundle but does not refute
77
+ * the run. The predecessor field (`fix-on-failure.ts` `steps[].required`) was
78
+ * declared but never read; here it is honoured.
79
+ */
80
+ required?: boolean;
81
+ }
82
+ export interface AcceptanceContract {
83
+ id?: string;
84
+ checks: ContractCheck[];
85
+ /**
86
+ * On red, spawn a fixer session and re-run the whole check list, up to N times.
87
+ * Ported from ultraapp's fix-on-failure loop. 0 disables.
88
+ */
89
+ fixOnFailureRounds?: number;
90
+ }
91
+ export interface CheckResult {
92
+ id: string;
93
+ type: CheckSpec['type'];
94
+ required: boolean;
95
+ passed: boolean;
96
+ durationMs: number;
97
+ /** Human-readable one-liner: the command that failed, the status we got, etc. */
98
+ detail: string;
99
+ /** Tail of captured output, byte-capped. */
100
+ tail?: string;
101
+ /** Paths (relative to the evidence dir) of files this check produced. */
102
+ artifacts?: string[];
103
+ /** Set when the check was killed by its own timeout rather than exiting. */
104
+ timedOut?: boolean;
105
+ }
106
+ export declare const DEFAULT_CHECK_TIMEOUT_MS: number;
107
+ export declare const DEFAULT_HTTP_TIMEOUT_MS = 30000;
108
+ export declare const DEFAULT_SCREENSHOT_TIMEOUT_MS = 60000;
109
+ /**
110
+ * Parse an untrusted contract, dropping anything unrecognised. Returns undefined
111
+ * when nothing usable survives, so a malformed contract fails loudly at declare
112
+ * time rather than silently degrading to "no checks" at completion time.
113
+ */
114
+ export declare function normalizeContract(raw: unknown): AcceptanceContract | undefined;
115
+ /** True when every required check passed. Non-required failures are recorded, not fatal. */
116
+ export declare function contractPassed(results: CheckResult[]): boolean;
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Acceptance contracts — what the runtime itself checks before calling a run done.
3
+ *
4
+ * Every completion signal that existed before this module was the agent grading
5
+ * its own work: council terminated on a regex over agent prose (`consensus.ts`),
6
+ * autoloop's `eval_output` was whatever the Coder passed to a tool call
7
+ * (`autoloop/agent-tools.ts`), ultraapp's frontend gate was a sentence in a
8
+ * persona string (`ultraapp/council-adapter.ts`). A contract is the opposite:
9
+ * a caller-declared list of checks that *we* execute and whose exit codes we read.
10
+ *
11
+ * Provenance rule, and the reason `normalizeContract` exists: a contract may
12
+ * come from the caller or from a mode default, never from agent output. If an
13
+ * agent could declare its own checks we would be back to self-grading with extra
14
+ * steps. Nothing in the kernel reads a contract out of a node's result.
15
+ */
16
+ export const DEFAULT_CHECK_TIMEOUT_MS = 10 * 60_000;
17
+ export const DEFAULT_HTTP_TIMEOUT_MS = 30_000;
18
+ export const DEFAULT_SCREENSHOT_TIMEOUT_MS = 60_000;
19
+ // ─── Normalization ──────────────────────────────────────────────────────────
20
+ function str(v) {
21
+ return typeof v === 'string' && v.trim() !== '' ? v : undefined;
22
+ }
23
+ function num(v) {
24
+ return typeof v === 'number' && Number.isFinite(v) ? v : undefined;
25
+ }
26
+ function strArray(v) {
27
+ if (!Array.isArray(v))
28
+ return undefined;
29
+ const out = v.filter((x) => typeof x === 'string');
30
+ return out.length === v.length ? out : undefined;
31
+ }
32
+ function normalizeSpec(raw) {
33
+ if (!raw || typeof raw !== 'object')
34
+ return undefined;
35
+ const r = raw;
36
+ switch (r.type) {
37
+ case 'command': {
38
+ const cmd = str(r.cmd);
39
+ if (!cmd)
40
+ return undefined;
41
+ const args = strArray(r.args) ?? [];
42
+ return {
43
+ type: 'command',
44
+ cmd,
45
+ args,
46
+ cwd: str(r.cwd),
47
+ timeoutMs: num(r.timeoutMs),
48
+ expectExit: num(r.expectExit),
49
+ };
50
+ }
51
+ case 'http': {
52
+ const url = str(r.url);
53
+ if (!url)
54
+ return undefined;
55
+ return {
56
+ type: 'http',
57
+ url,
58
+ expectStatus: num(r.expectStatus),
59
+ timeoutMs: num(r.timeoutMs),
60
+ intervalMs: num(r.intervalMs),
61
+ };
62
+ }
63
+ case 'screenshot': {
64
+ const url = str(r.url);
65
+ if (!url || !Array.isArray(r.viewports) || r.viewports.length === 0)
66
+ return undefined;
67
+ const viewports = [];
68
+ for (const v of r.viewports) {
69
+ if (!v || typeof v !== 'object')
70
+ return undefined;
71
+ const vv = v;
72
+ const width = num(vv.width);
73
+ const height = num(vv.height);
74
+ if (!width || !height)
75
+ return undefined;
76
+ viewports.push({ width, height, label: str(vv.label) });
77
+ }
78
+ return { type: 'screenshot', url, viewports, browserBin: str(r.browserBin), timeoutMs: num(r.timeoutMs) };
79
+ }
80
+ case 'diff_policy':
81
+ return {
82
+ type: 'diff_policy',
83
+ maxFiles: num(r.maxFiles),
84
+ forbidPaths: strArray(r.forbidPaths),
85
+ requirePaths: strArray(r.requirePaths),
86
+ };
87
+ case 'file': {
88
+ const p = str(r.path);
89
+ if (!p)
90
+ return undefined;
91
+ return {
92
+ type: 'file',
93
+ path: p,
94
+ exists: typeof r.exists === 'boolean' ? r.exists : true,
95
+ matches: str(r.matches),
96
+ };
97
+ }
98
+ default:
99
+ return undefined;
100
+ }
101
+ }
102
+ /**
103
+ * Parse an untrusted contract, dropping anything unrecognised. Returns undefined
104
+ * when nothing usable survives, so a malformed contract fails loudly at declare
105
+ * time rather than silently degrading to "no checks" at completion time.
106
+ */
107
+ export function normalizeContract(raw) {
108
+ if (!raw || typeof raw !== 'object')
109
+ return undefined;
110
+ const r = raw;
111
+ const rawChecks = Array.isArray(r.checks) ? r.checks : undefined;
112
+ if (!rawChecks)
113
+ return undefined;
114
+ const checks = [];
115
+ for (let i = 0; i < rawChecks.length; i++) {
116
+ const entry = rawChecks[i];
117
+ if (!entry || typeof entry !== 'object')
118
+ continue;
119
+ // Accept both `{spec: {...}}` and a bare check spec, since hand-written
120
+ // contracts in tool calls tend to omit the wrapper.
121
+ const spec = normalizeSpec('spec' in entry ? entry.spec : entry);
122
+ if (!spec)
123
+ continue;
124
+ checks.push({
125
+ id: str(entry.id) ?? `${spec.type}-${i + 1}`,
126
+ spec,
127
+ required: entry.required === false ? false : true,
128
+ });
129
+ }
130
+ if (checks.length === 0)
131
+ return undefined;
132
+ return {
133
+ id: str(r.id),
134
+ checks,
135
+ fixOnFailureRounds: num(r.fixOnFailureRounds),
136
+ };
137
+ }
138
+ /** True when every required check passed. Non-required failures are recorded, not fatal. */
139
+ export function contractPassed(results) {
140
+ return results.every((r) => r.passed || !r.required);
141
+ }
142
+ //# sourceMappingURL=contract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract.js","sourceRoot":"","sources":["../../../src/verify/contract.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Evidence bundles — the machine-readable record of what was checked.
3
+ *
4
+ * A run's claim to be finished is only as good as what can be re-read after the
5
+ * process that made it is gone. So every verifier attempt writes a directory:
6
+ * the verdict and per-check results as JSON, the failure tails as plain text,
7
+ * whatever files the checks produced (screenshots), and the patch the run
8
+ * actually made, against the base commit recorded when it started.
9
+ */
10
+ import type { Logger } from '../logger.js';
11
+ import { type ChangedFile } from './baseline.js';
12
+ import { type CheckResult } from './contract.js';
13
+ export interface EvidenceBundle {
14
+ evidenceId: string;
15
+ runId: string;
16
+ /** Node that produced it, or `'run'` for a standalone `verify_run`. */
17
+ node: string;
18
+ contractId?: string;
19
+ createdAt: string;
20
+ cwd: string;
21
+ baseSha?: string;
22
+ headSha?: string;
23
+ passed: boolean;
24
+ /** Fix-on-red rounds consumed before this verdict. */
25
+ rounds: number;
26
+ results: CheckResult[];
27
+ changedFiles: ChangedFile[];
28
+ /**
29
+ * Digest of the working tree at the moment the checks finished. The kernel
30
+ * re-computes it when the run ends: if it moved, this bundle describes an
31
+ * earlier tree and the verdict no longer applies to what is on disk.
32
+ * Undefined outside a git repo, where we cannot tell.
33
+ */
34
+ treeFingerprint?: string;
35
+ }
36
+ export declare function evidenceRoot(runDir: string): string;
37
+ export declare function evidenceDir(runDir: string, evidenceId: string): string;
38
+ /** `<node>-<attempt>` — stable, sortable, and readable in a ledger row. */
39
+ export declare function makeEvidenceId(node: string, attempt: number): string;
40
+ export interface WriteEvidenceArgs {
41
+ runDir: string;
42
+ runId: string;
43
+ node: string;
44
+ evidenceId: string;
45
+ cwd: string;
46
+ baseSha?: string;
47
+ contractId?: string;
48
+ results: CheckResult[];
49
+ rounds: number;
50
+ logger?: Logger;
51
+ }
52
+ /**
53
+ * Write the bundle. Best-effort like the run ledger: a bundle that fails to land
54
+ * must not change the verdict it is describing — the verdict is already decided
55
+ * by `results`.
56
+ */
57
+ export declare function writeEvidence(args: WriteEvidenceArgs): Promise<EvidenceBundle>;
58
+ export declare function readEvidence(runDir: string, evidenceId: string): EvidenceBundle | undefined;
59
+ export declare function listEvidence(runDir: string): string[];
60
+ /** Render a bundle for the CLI. Pure — no I/O. */
61
+ export declare function formatEvidence(bundle: EvidenceBundle): string;