@openpond/evals 0.11.20 → 0.12.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 (159) hide show
  1. package/README.md +12 -0
  2. package/dist/connected-evidence/codex-command-observations.js +81 -0
  3. package/dist/connected-evidence/collector-coverage-contracts.js +160 -0
  4. package/dist/connected-evidence/contracts.js +13 -0
  5. package/dist/connected-evidence/git-file-contracts.js +16 -0
  6. package/dist/connected-evidence/git-file-proof.js +86 -0
  7. package/dist/connected-evidence/git-starting-state.js +81 -0
  8. package/dist/connected-evidence/git.js +2 -0
  9. package/dist/connected-evidence/imports.js +2 -1
  10. package/dist/connected-evidence/index.js +2 -0
  11. package/dist/connected-evidence/normalize.js +1 -0
  12. package/dist/connected-evidence/sources/codex-metadata.js +33 -0
  13. package/dist/connected-evidence/sources/codex.js +16 -2
  14. package/dist/execution-contracts.js +1 -1
  15. package/dist/graders.js +10 -4
  16. package/dist/javascript-isolate-node.js +2 -1
  17. package/dist/javascript-isolate-process-source.js +1 -1
  18. package/dist/javascript-isolate-process.js +2 -1
  19. package/dist/javascript-isolate.js +2 -1
  20. package/dist/javascript-verifier-worker-source.js +1 -1
  21. package/dist/javascript-verifier.js +1 -0
  22. package/dist/native-conversations/codex-window-inventory.js +96 -0
  23. package/dist/native-conversations/collector-acquisition.js +149 -0
  24. package/dist/native-conversations/collector-branches.js +1 -0
  25. package/dist/native-conversations/collector-calendar-gate.js +19 -0
  26. package/dist/native-conversations/collector-contracts.js +4 -3
  27. package/dist/native-conversations/collector-coverage.js +100 -0
  28. package/dist/native-conversations/collector-cron.js +43 -0
  29. package/dist/native-conversations/collector-schedule.js +61 -0
  30. package/dist/native-conversations/collector-service-files.js +51 -0
  31. package/dist/native-conversations/collector-snapshots.js +70 -0
  32. package/dist/native-conversations/collector-source-cache.js +41 -0
  33. package/dist/native-conversations/collector-store.js +43 -8
  34. package/dist/native-conversations/collector.js +189 -261
  35. package/dist/native-conversations/git-assets.js +61 -0
  36. package/dist/native-conversations/history.js +9 -0
  37. package/dist/native-conversations/index.js +2 -0
  38. package/dist/native-conversations/location.js +4 -2
  39. package/dist/native-conversations/supervisor.js +131 -81
  40. package/dist/prepared-process-isolation.js +131 -0
  41. package/dist/rewards.js +17 -5
  42. package/dist/sql-execution-node.js +2 -1
  43. package/dist/tasksets.js +7 -1
  44. package/dist/types/builtin-benchmarks/harness-refiner.d.ts +4 -0
  45. package/dist/types/builtin-benchmarks/harness-refiner.d.ts.map +1 -1
  46. package/dist/types/conformance.d.ts +8 -0
  47. package/dist/types/conformance.d.ts.map +1 -1
  48. package/dist/types/connected-evidence/codex-command-observations.d.ts +15 -0
  49. package/dist/types/connected-evidence/codex-command-observations.d.ts.map +1 -0
  50. package/dist/types/connected-evidence/collector-coverage-contracts.d.ts +98 -0
  51. package/dist/types/connected-evidence/collector-coverage-contracts.d.ts.map +1 -0
  52. package/dist/types/connected-evidence/contracts.d.ts +22 -0
  53. package/dist/types/connected-evidence/contracts.d.ts.map +1 -1
  54. package/dist/types/connected-evidence/git-file-contracts.d.ts +18 -0
  55. package/dist/types/connected-evidence/git-file-contracts.d.ts.map +1 -0
  56. package/dist/types/connected-evidence/git-file-proof.d.ts +13 -0
  57. package/dist/types/connected-evidence/git-file-proof.d.ts.map +1 -0
  58. package/dist/types/connected-evidence/git-starting-state.d.ts +28 -0
  59. package/dist/types/connected-evidence/git-starting-state.d.ts.map +1 -0
  60. package/dist/types/connected-evidence/git.d.ts +3 -0
  61. package/dist/types/connected-evidence/git.d.ts.map +1 -0
  62. package/dist/types/connected-evidence/imports.d.ts.map +1 -1
  63. package/dist/types/connected-evidence/index.d.ts +2 -0
  64. package/dist/types/connected-evidence/index.d.ts.map +1 -1
  65. package/dist/types/connected-evidence/normalize.d.ts +1 -0
  66. package/dist/types/connected-evidence/normalize.d.ts.map +1 -1
  67. package/dist/types/connected-evidence/sources/claude-code.d.ts +10 -0
  68. package/dist/types/connected-evidence/sources/claude-code.d.ts.map +1 -1
  69. package/dist/types/connected-evidence/sources/codex-metadata.d.ts +10 -0
  70. package/dist/types/connected-evidence/sources/codex-metadata.d.ts.map +1 -0
  71. package/dist/types/connected-evidence/sources/codex.d.ts +10 -0
  72. package/dist/types/connected-evidence/sources/codex.d.ts.map +1 -1
  73. package/dist/types/connected-evidence/sources/grok-build.d.ts +10 -0
  74. package/dist/types/connected-evidence/sources/grok-build.d.ts.map +1 -1
  75. package/dist/types/connected-evidence/sources/history.d.ts +20 -0
  76. package/dist/types/connected-evidence/sources/history.d.ts.map +1 -1
  77. package/dist/types/connected-evidence/sources/opencode.d.ts +10 -0
  78. package/dist/types/connected-evidence/sources/opencode.d.ts.map +1 -1
  79. package/dist/types/connected-evidence/sources/pi.d.ts +10 -0
  80. package/dist/types/connected-evidence/sources/pi.d.ts.map +1 -1
  81. package/dist/types/execution-contracts.d.ts +8 -0
  82. package/dist/types/execution-contracts.d.ts.map +1 -1
  83. package/dist/types/graders.d.ts +3 -0
  84. package/dist/types/graders.d.ts.map +1 -1
  85. package/dist/types/javascript-isolate-node.d.ts.map +1 -1
  86. package/dist/types/javascript-isolate-process.d.ts.map +1 -1
  87. package/dist/types/javascript-isolate.d.ts.map +1 -1
  88. package/dist/types/javascript-verifier.d.ts +1 -0
  89. package/dist/types/javascript-verifier.d.ts.map +1 -1
  90. package/dist/types/learning/admission.d.ts +1 -0
  91. package/dist/types/learning/admission.d.ts.map +1 -1
  92. package/dist/types/learning/authoring-service.d.ts +2 -0
  93. package/dist/types/learning/authoring-service.d.ts.map +1 -1
  94. package/dist/types/learning/authoring.d.ts +8 -0
  95. package/dist/types/learning/authoring.d.ts.map +1 -1
  96. package/dist/types/learning/batch-service.d.ts +4 -0
  97. package/dist/types/learning/batch-service.d.ts.map +1 -1
  98. package/dist/types/learning/contracts.d.ts +17 -0
  99. package/dist/types/learning/contracts.d.ts.map +1 -1
  100. package/dist/types/learning/operations.d.ts +8 -0
  101. package/dist/types/learning/operations.d.ts.map +1 -1
  102. package/dist/types/learning/repository.d.ts +14 -0
  103. package/dist/types/learning/repository.d.ts.map +1 -1
  104. package/dist/types/learning/reward-calibration-closure.d.ts +9 -1
  105. package/dist/types/learning/reward-calibration-closure.d.ts.map +1 -1
  106. package/dist/types/learning/reward-checks.d.ts +2 -0
  107. package/dist/types/learning/reward-checks.d.ts.map +1 -1
  108. package/dist/types/learning/transport.d.ts +18 -0
  109. package/dist/types/learning/transport.d.ts.map +1 -1
  110. package/dist/types/native-conversations/codex-window-inventory.d.ts +12 -0
  111. package/dist/types/native-conversations/codex-window-inventory.d.ts.map +1 -0
  112. package/dist/types/native-conversations/collector-acquisition.d.ts +17 -0
  113. package/dist/types/native-conversations/collector-acquisition.d.ts.map +1 -0
  114. package/dist/types/native-conversations/collector-branches.d.ts.map +1 -1
  115. package/dist/types/native-conversations/collector-calendar-gate.d.ts +9 -0
  116. package/dist/types/native-conversations/collector-calendar-gate.d.ts.map +1 -0
  117. package/dist/types/native-conversations/collector-contracts.d.ts +41 -5
  118. package/dist/types/native-conversations/collector-contracts.d.ts.map +1 -1
  119. package/dist/types/native-conversations/collector-coverage.d.ts +62 -0
  120. package/dist/types/native-conversations/collector-coverage.d.ts.map +1 -0
  121. package/dist/types/native-conversations/collector-cron.d.ts +20 -0
  122. package/dist/types/native-conversations/collector-cron.d.ts.map +1 -0
  123. package/dist/types/native-conversations/collector-schedule.d.ts +13 -0
  124. package/dist/types/native-conversations/collector-schedule.d.ts.map +1 -0
  125. package/dist/types/native-conversations/collector-service-files.d.ts +20 -0
  126. package/dist/types/native-conversations/collector-service-files.d.ts.map +1 -0
  127. package/dist/types/native-conversations/collector-snapshots.d.ts +25 -0
  128. package/dist/types/native-conversations/collector-snapshots.d.ts.map +1 -0
  129. package/dist/types/native-conversations/collector-source-cache.d.ts +31 -0
  130. package/dist/types/native-conversations/collector-source-cache.d.ts.map +1 -0
  131. package/dist/types/native-conversations/collector-store.d.ts +11 -2
  132. package/dist/types/native-conversations/collector-store.d.ts.map +1 -1
  133. package/dist/types/native-conversations/collector.d.ts +5 -1
  134. package/dist/types/native-conversations/collector.d.ts.map +1 -1
  135. package/dist/types/native-conversations/git-assets.d.ts +32 -0
  136. package/dist/types/native-conversations/git-assets.d.ts.map +1 -0
  137. package/dist/types/native-conversations/history.d.ts +7 -0
  138. package/dist/types/native-conversations/history.d.ts.map +1 -1
  139. package/dist/types/native-conversations/index.d.ts +2 -0
  140. package/dist/types/native-conversations/index.d.ts.map +1 -1
  141. package/dist/types/native-conversations/location.d.ts.map +1 -1
  142. package/dist/types/native-conversations/supervisor.d.ts +4 -3
  143. package/dist/types/native-conversations/supervisor.d.ts.map +1 -1
  144. package/dist/types/prepared-process-isolation.d.ts +5 -0
  145. package/dist/types/prepared-process-isolation.d.ts.map +1 -0
  146. package/dist/types/review-conformance.d.ts +5 -5
  147. package/dist/types/rewards.d.ts +9 -0
  148. package/dist/types/rewards.d.ts.map +1 -1
  149. package/dist/types/sql-execution-node.d.ts.map +1 -1
  150. package/dist/types/tasksets.d.ts +16 -0
  151. package/dist/types/tasksets.d.ts.map +1 -1
  152. package/package.json +8 -2
  153. package/schemas/learning/v1/binding.schema.json +8 -0
  154. package/schemas/learning/v1/command-request.schema.json +8 -0
  155. package/schemas/learning/v1/decision.schema.json +5 -1
  156. package/schemas/learning/v1/draft.schema.json +8 -0
  157. package/schemas/learning/v1/grade.schema.json +5 -1
  158. package/schemas/learning/v1/package.schema.json +113 -94
  159. package/schemas/learning/v1/reward_check.schema.json +2 -1
@@ -7,6 +7,8 @@ import { homedir } from "node:os";
7
7
  import { isAbsolute, join } from "node:path";
8
8
  import { contentHash } from "@openpond/harness";
9
9
  import { CollectorStore } from "./collector-store.js";
10
+ import { validateCollectorSchedule } from "./collector-schedule.js";
11
+ import { collectorServiceFiles } from "./collector-service-files.js";
10
12
  const execute = promisify(execFile);
11
13
  const command = async (file, args) => {
12
14
  await execute(file, args, {
@@ -15,12 +17,6 @@ const command = async (file, args) => {
15
17
  windowsHide: true,
16
18
  });
17
19
  };
18
- const xml = (value) => value
19
- .replace(/&/gu, "&")
20
- .replace(/</gu, "&lt;")
21
- .replace(/>/gu, "&gt;")
22
- .replace(/"/gu, "&quot;");
23
- const systemd = (value) => `"${value.replace(/\\/gu, "\\\\").replace(/"/gu, '\\"').replace(/%/gu, "%%").replace(/\$/gu, "$$")}"`;
24
20
  function identity(directory) {
25
21
  return `openpond-import-${contentHash(directory).slice(0, 16)}`;
26
22
  }
@@ -70,86 +66,154 @@ export async function controlCollector(directory, action, connectionId) {
70
66
  store.close();
71
67
  }
72
68
  }
73
- /** Per-user logon supervision. Installing does not override the retained Stop intent. */
69
+ /** Install calendar triggers only. Registration never launches an import. */
74
70
  export async function installCollectorService(input) {
75
- if (!isAbsolute(input.directory) ||
76
- !isAbsolute(input.executable) ||
77
- [input.directory, input.executable, ...input.args].some((value) => /[\r\n\0]/u.test(value)))
78
- throw new Error("Collector service requires absolute paths and single-line arguments.");
71
+ // Reloading a launchd calendar also terminates its active process. Preserve
72
+ // the current import instead of silently cancelling it during a settings edit.
73
+ if (process.platform === "darwin" && (await collectorStatus(input.directory)).running)
74
+ throw new Error("Wait for the current import to finish, or cancel it, before changing its macOS schedule.");
75
+ if (!isAbsolute(input.directory) || !isAbsolute(input.executable) ||
76
+ [input.directory, input.executable, ...input.args].some(value => /[\r\n\0]/u.test(value)))
77
+ throw new Error("Collector jobs require absolute paths and single-line arguments.");
79
78
  const retainedRuntime = await retainAppImageRuntime(input);
80
79
  if (retainedRuntime)
81
80
  input = { ...input, ...retainedRuntime, environment: { ...input.environment, ELECTRON_RUN_AS_NODE: "1", APPIMAGE_EXTRACT_AND_RUN: "1" } };
82
81
  const environment = Object.entries(input.environment ?? {});
83
- if (environment.some(([key, value]) => !["OPENPOND_HOME", "ELECTRON_RUN_AS_NODE", "APPIMAGE_EXTRACT_AND_RUN"].includes(key) ||
84
- typeof value !== "string" ||
85
- /[\r\n\0]/u.test(value)))
82
+ if (environment.some(([key, value]) => !["OPENPOND_HOME", "ELECTRON_RUN_AS_NODE", "APPIMAGE_EXTRACT_AND_RUN"].includes(key) || typeof value !== "string" || /[\r\n\0]/u.test(value)))
86
83
  throw new Error("Unsupported service environment setting.");
87
84
  const home = input.home ?? homedir(), name = identity(input.directory);
88
- const launch = [
89
- ...input.args,
90
- "import",
91
- "service",
92
- "run",
93
- "--collector-dir",
94
- input.directory,
95
- ];
85
+ const store = await CollectorStore.open(input.directory);
86
+ let schedules;
87
+ try {
88
+ schedules = store.connections().map(connection => store.schedule(connection.id)).filter((schedule) => schedule !== null);
89
+ }
90
+ finally {
91
+ store.close();
92
+ }
93
+ const gatePath = join(input.directory, "calendar-gate.cjs");
94
+ const files = collectorServiceFiles({ name, gatePath, executable: input.executable,
95
+ args: [...input.args, "import", "service", "run", "--scheduled", "--collector-dir", input.directory], environment, schedules });
96
+ await atomicServiceFile(gatePath, files.gate, { mode: 0o600 });
96
97
  if (process.platform === "linux") {
97
98
  const directory = join(home, ".config/systemd/user");
98
99
  await mkdir(directory, { recursive: true, mode: 0o700 });
99
- await atomicServiceFile(join(directory, `${name}.service`), `[Unit]\nDescription=OpenPond conversation importer\nAfter=network-online.target\n[Service]\nType=simple\n${environment.map(([key, value]) => `Environment=${systemd(`${key}=${value}`)}`).join("\n")}\nExecStart=${[input.executable, ...launch].map(systemd).join(" ")}\nRestart=on-failure\nRestartSec=5\nUMask=0077\nNoNewPrivileges=true\n[Install]\nWantedBy=default.target\n`, { mode: 0o600 });
100
- await command("systemctl", ["--user", "daemon-reload"]);
101
- await command("systemctl", ["--user", "enable", `${name}.service`]);
100
+ // Remove the old login enablement without stopping an already owned job.
101
+ await optionalCommand("systemctl", ["--user", "disable", `${name}.service`]);
102
+ await atomicServiceFile(join(directory, `${name}.service`), files.service, { mode: 0o600 });
103
+ if (schedules.length) {
104
+ await atomicServiceFile(join(directory, `${name}.timer`), files.timer, { mode: 0o600 });
105
+ await command("systemctl", ["--user", "daemon-reload"]);
106
+ await command("systemctl", ["--user", "enable", "--now", `${name}.timer`]);
107
+ await command("systemctl", ["--user", "restart", `${name}.timer`]);
108
+ }
109
+ else {
110
+ await optionalCommand("systemctl", ["--user", "disable", "--now", `${name}.timer`]);
111
+ await rm(join(directory, `${name}.timer`), { force: true });
112
+ await command("systemctl", ["--user", "daemon-reload"]);
113
+ }
102
114
  }
103
115
  else if (process.platform === "darwin") {
104
- const directory = join(home, "Library/LaunchAgents");
116
+ const directory = join(home, "Library/LaunchAgents"), file = join(directory, `${name}.plist`);
105
117
  await mkdir(directory, { recursive: true, mode: 0o700 });
106
- const file = join(directory, `${name}.plist`);
107
- let loaded = false;
118
+ await optionalCommand("launchctl", ["bootout", `gui/${process.getuid()}/${name}`]);
119
+ if (schedules.length) {
120
+ await atomicServiceFile(file, files.plist, { mode: 0o600 });
121
+ await command("launchctl", ["bootstrap", `gui/${process.getuid()}`, file]);
122
+ }
123
+ else
124
+ await rm(file, { force: true });
125
+ }
126
+ else if (process.platform === "win32") {
127
+ if (!schedules.length)
128
+ await optionalCommand("schtasks", ["/Delete", "/TN", name, "/F"]);
129
+ else {
130
+ const user = (await execute("whoami", [], { timeout: 5000, maxBuffer: 1024 })).stdout.trim();
131
+ const file = join(input.directory, "scheduled-task.xml"), script = join(input.directory, "start-collector.ps1");
132
+ await mkdir(input.directory, { recursive: true, mode: 0o700 });
133
+ await atomicServiceFile(script, files.powershell, { mode: 0o600 });
134
+ await atomicServiceFile(file, files.windowsTask(user, script), { mode: 0o600 });
135
+ await command("schtasks", ["/Create", "/TN", name, "/XML", file, "/F"]);
136
+ }
137
+ }
138
+ else
139
+ throw new Error("Scheduled imports need a supported OS scheduler. Use import sync manually on this OS.");
140
+ return { name, platform: process.platform, status: await collectorStatus(input.directory) };
141
+ }
142
+ // Absence is allowed only when removing an optional trigger. Installation and
143
+ // activation failures remain errors and never claim that a schedule is enabled.
144
+ async function optionalCommand(file, args) {
145
+ try {
146
+ await command(file, args);
147
+ }
148
+ catch (error) {
149
+ const result = error;
150
+ if (result.code === "ENOENT" || !/not (?:loaded|found|exist)|does not exist|No such|could not be found|cannot find|not been loaded/iu.test(result.stderr ?? result.message))
151
+ throw error;
152
+ }
153
+ }
154
+ /** Serialize OS/config updates; a failed installation restores retained intent. */
155
+ export async function setCollectorSchedule(input, connectionId, schedule) {
156
+ if (schedule !== null)
157
+ schedule = validateCollectorSchedule(schedule);
158
+ if (process.platform === "darwin" && (await collectorStatus(input.directory)).running)
159
+ throw new Error("Wait for the current import to finish, or cancel it, before changing its macOS schedule.");
160
+ const store = await CollectorStore.open(input.directory), token = randomUUID();
161
+ let prior;
162
+ store.database.exec("BEGIN IMMEDIATE");
163
+ try {
164
+ const connection = store.connections().find(item => item.id === connectionId);
165
+ if (!connection || (schedule && connection.state === "disconnected"))
166
+ throw new Error("Select a connected source before scheduling imports.");
167
+ const owner = store.setting("scheduleOwner");
168
+ if (owner) {
169
+ const { pid } = JSON.parse(owner);
170
+ let alive = true;
171
+ try {
172
+ process.kill(pid, 0);
173
+ }
174
+ catch (error) {
175
+ alive = error.code !== "ESRCH";
176
+ }
177
+ if (alive)
178
+ throw new Error("Another schedule update is in progress. Try again shortly.");
179
+ }
180
+ prior = store.setting(`schedule:${connectionId}`);
181
+ store.set("scheduleOwner", JSON.stringify({ pid: process.pid, token }));
182
+ store.set(`schedule:${connectionId}`, schedule ? JSON.stringify(schedule) : "");
183
+ store.database.exec("COMMIT");
184
+ }
185
+ catch (error) {
186
+ store.database.exec("ROLLBACK");
187
+ store.close();
188
+ throw error;
189
+ }
190
+ try {
191
+ await installCollectorService(input);
192
+ return store.status();
193
+ }
194
+ catch (error) {
195
+ store.set(`schedule:${connectionId}`, prior ?? "");
108
196
  try {
109
- await command("launchctl", ["print", `gui/${process.getuid()}/${name}`]);
110
- loaded = true;
197
+ await installCollectorService(input);
111
198
  }
112
199
  catch {
113
- /* A first installation has no loaded job. Bootstrap below reports actual setup errors. */
200
+ throw new Error(`Schedule installation failed and OS rollback could not be verified. Review the OS scheduler. ${error instanceof Error ? error.message : ""}`);
114
201
  }
115
- if (loaded)
116
- await command("launchctl", [
117
- "bootout",
118
- `gui/${process.getuid()}/${name}`,
119
- ]);
120
- await writeFile(file, `<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.0"><dict><key>Label</key><string>${name}</string><key>ProgramArguments</key><array>${[input.executable, ...launch].map((value) => `<string>${xml(value)}</string>`).join("")}</array><key>EnvironmentVariables</key><dict>${environment.map(([key, value]) => `<key>${xml(key)}</key><string>${xml(value)}</string>`).join("")}</dict><key>RunAtLoad</key><true/><key>KeepAlive</key><dict><key>SuccessfulExit</key><false/></dict><key>ThrottleInterval</key><integer>5</integer></dict></plist>`, { mode: 0o600 });
121
- await command("launchctl", ["bootstrap", `gui/${process.getuid()}`, file]);
202
+ throw error;
122
203
  }
123
- else if (process.platform === "win32") {
124
- const user = (await execute("whoami", [], { timeout: 5000, maxBuffer: 1024 })).stdout.trim();
125
- const file = join(input.directory, "scheduled-task.xml");
126
- await mkdir(input.directory, { recursive: true });
127
- const quoted = (value) => `"${value.replace(/(\\*)"/gu, '$1$1\\"').replace(/(\\+)$/u, "$1$1")}"`;
128
- const script = join(input.directory, "start-collector.ps1");
129
- const ps = (value) => `'${value.replace(/'/gu, "''")}'`;
130
- await writeFile(script, `${environment.map(([key, value]) => `$env:${key} = ${ps(value)}`).join("\n")}\n& ${[input.executable, ...launch].map(ps).join(" ")}\nexit $LASTEXITCODE\n`, { mode: 0o600 });
131
- await writeFile(file, `<?xml version="1.0"?><Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task"><Triggers><LogonTrigger><Enabled>true</Enabled><UserId>${xml(user)}</UserId></LogonTrigger></Triggers><Principals><Principal id="Owner"><UserId>${xml(user)}</UserId><LogonType>InteractiveToken</LogonType><RunLevel>LeastPrivilege</RunLevel></Principal></Principals><Settings><MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy><DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries><StopIfGoingOnBatteries>false</StopIfGoingOnBatteries><ExecutionTimeLimit>PT0S</ExecutionTimeLimit><RestartOnFailure><Interval>PT1M</Interval><Count>999</Count></RestartOnFailure></Settings><Actions Context="Owner"><Exec><Command>powershell.exe</Command><Arguments>${xml(["-NoProfile", "-NonInteractive", "-File", script].map(quoted).join(" "))}</Arguments></Exec></Actions></Task>`, { mode: 0o600 });
132
- await command("schtasks", ["/Create", "/TN", name, "/XML", file, "/F"]);
204
+ finally {
205
+ store.set("scheduleOwner", "");
206
+ store.close();
133
207
  }
134
- else
135
- throw new Error("This OS has no qualified per-user supervisor. Run the collector in the foreground.");
136
- return {
137
- name,
138
- platform: process.platform,
139
- status: await collectorStatus(input.directory),
140
- };
141
208
  }
142
209
  /** Removing supervision preserves receipts, pending uploads and retained datasets. */
143
210
  export async function uninstallCollectorService(directory, home = homedir()) {
144
211
  await controlCollector(directory, "stop");
145
212
  const name = identity(directory);
146
213
  if (process.platform === "linux") {
147
- await command("systemctl", [
148
- "--user",
149
- "disable",
150
- "--now",
151
- `${name}.service`,
152
- ]);
214
+ await optionalCommand("systemctl", ["--user", "disable", "--now", `${name}.timer`]);
215
+ await rm(join(home, ".config/systemd/user", `${name}.timer`), { force: true });
216
+ await command("systemctl", ["--user", "disable", "--now", `${name}.service`]);
153
217
  await rm(join(home, ".config/systemd/user", `${name}.service`), {
154
218
  force: true,
155
219
  });
@@ -169,30 +233,16 @@ export async function uninstallCollectorService(directory, home = homedir()) {
169
233
  }
170
234
  else
171
235
  throw new Error("No per-user supervisor is available.");
236
+ await rm(join(directory, "calendar-gate.cjs"), { force: true });
172
237
  if (process.platform === "linux")
173
238
  await removeAppImageRuntimes(directory);
174
- return collectorStatus(directory);
175
- }
176
- export async function startCollectorService(directory) {
177
- await controlCollector(directory, "start");
178
- const name = identity(directory);
239
+ const store = await CollectorStore.open(directory);
179
240
  try {
180
- if (process.platform === "linux")
181
- await command("systemctl", ["--user", "restart", `${name}.service`]);
182
- else if (process.platform === "darwin")
183
- await command("launchctl", [
184
- "kickstart",
185
- "-k",
186
- `gui/${process.getuid()}/${name}`,
187
- ]);
188
- else if (process.platform === "win32")
189
- await command("schtasks", ["/Run", "/TN", name]);
190
- else
191
- throw new Error("No per-user supervisor is available.");
241
+ for (const connection of store.connections())
242
+ store.set(`schedule:${connection.id}`, "");
192
243
  }
193
- catch (error) {
194
- await controlCollector(directory, "stop");
195
- throw error;
244
+ finally {
245
+ store.close();
196
246
  }
197
247
  return collectorStatus(directory);
198
248
  }
@@ -0,0 +1,131 @@
1
+ /** Staged by the private verifier owner. Untrusted policy programs run with no
2
+ * capabilities as a different UID, outside the sealed private verifier tree.
3
+ * The parent must assess returned behavior; an exit code is never correctness. */
4
+ export const PREPARED_PROCESS_ISOLATION_SOURCE = String.raw `
5
+ import fs from "node:fs/promises";
6
+ import os from "node:os";
7
+ import path from "node:path";
8
+ import { fileURLToPath } from "node:url";
9
+ import { randomInt } from "node:crypto";
10
+
11
+ const MAX_BYTES = 15 * 1024 * 1024, MAX_OUTPUT = 1024 * 1024;
12
+ const usedUsers = new Set();
13
+ const safePath = value => typeof value === "string" && value.length > 0 && value.length <= 2000
14
+ && !value.startsWith("/") && !/[\\\x00-\x1f\x7f]/.test(value)
15
+ && value.split("/").every(part => part && part !== "." && part !== ".." && !part.startsWith(".env"));
16
+
17
+ /** files contain only public original/policy bytes and a public invocation
18
+ * adapter. Never stage independent assertions, expected answers or checkers. */
19
+ export async function runPolicyProgram(input) {
20
+ const privateRoot = path.dirname(fileURLToPath(import.meta.url));
21
+ if (process.getuid?.() !== 0 || !path.basename(privateRoot).startsWith(".openpond-reward-verifier-"))
22
+ throw new Error("policy_process_isolation_runtime_unavailable");
23
+ if (!Array.isArray(input.files) || input.files.length < 1 || input.files.length > 100
24
+ || !safePath(input.entrypoint) || !input.files.some(file => file.path === input.entrypoint)
25
+ || !Number.isSafeInteger(input.timeoutMs) || input.timeoutMs < 1 || input.timeoutMs > 60000
26
+ || !Array.isArray(input.args ?? []) || (input.args ?? []).length > 100
27
+ || (input.args ?? []).some(arg => typeof arg !== "string" || arg.length > 2000 || arg.includes("\0")))
28
+ throw new Error("policy_process_isolation_input_invalid");
29
+ let total = 0;
30
+ const paths = new Set();
31
+ const files = input.files.map(file => {
32
+ if (!safePath(file.path) || paths.has(file.path) || typeof file.base64 !== "string")
33
+ throw new Error("policy_process_isolation_file_invalid");
34
+ paths.add(file.path);
35
+ const bytes = Buffer.from(file.base64, "base64");
36
+ if (bytes.toString("base64") !== file.base64) throw new Error("policy_process_isolation_file_invalid");
37
+ total += bytes.length;
38
+ if (total > MAX_BYTES) throw new Error("policy_process_isolation_file_limit");
39
+ return { path: file.path, bytes };
40
+ });
41
+ // Directory access seals request JSON, checker modules, helper source and
42
+ // private artifacts before any untrusted program can be spawned.
43
+ await fs.chmod(privateRoot, 0o700);
44
+ const stat = await fs.stat(privateRoot);
45
+ if (stat.uid !== 0 || (stat.mode & 0o777) !== 0o700) throw new Error("policy_process_private_tree_not_sealed");
46
+ for (const executable of ["/usr/bin/setsid", "/usr/bin/setpriv", "/usr/local/bin/bun"])
47
+ await fs.access(executable, 1);
48
+ const directory = await fs.mkdtemp(path.join(os.tmpdir(), "openpond-policy-"));
49
+ let user;
50
+ do { user = randomInt(1000000, 2000000); } while (usedUsers.has(user));
51
+ usedUsers.add(user);
52
+ let child, timer, timedOut = false;
53
+ const kill = () => {
54
+ if (!child) return;
55
+ try { process.kill(-child.pid, "SIGKILL"); } catch {}
56
+ try { child.kill("SIGKILL"); } catch {}
57
+ };
58
+ try {
59
+ await fs.chmod(directory, 0o700);
60
+ await fs.chown(directory, user, user);
61
+ for (const file of files) {
62
+ const target = path.join(directory, file.path);
63
+ const parent = path.dirname(target);
64
+ await fs.mkdir(parent, { recursive: true, mode: 0o700 });
65
+ let current = parent;
66
+ while (current !== directory) {
67
+ await fs.chmod(current, 0o700); await fs.chown(current, user, user);
68
+ current = path.dirname(current);
69
+ }
70
+ await fs.writeFile(target, file.bytes, { mode: 0o600, flag: "wx" });
71
+ await fs.chown(target, user, user);
72
+ }
73
+ child = Bun.spawn(["/usr/bin/setsid", "/usr/bin/setpriv", "--reuid=" + user, "--regid=" + user, "--clear-groups",
74
+ "--no-new-privs", "--bounding-set=-all", "--inh-caps=-all", "--ambient-caps=-all",
75
+ "/usr/local/bin/bun", path.join(directory, input.entrypoint), ...(input.args ?? [])], {
76
+ cwd: directory, env: { PATH: "/usr/local/bin:/usr/bin:/bin", TMPDIR: directory }, stdout: "pipe", stderr: "pipe", stdin: "ignore",
77
+ });
78
+ timer = setTimeout(() => { timedOut = true; kill(); }, input.timeoutMs);
79
+ const read = async stream => {
80
+ const reader = stream.getReader(), chunks = [];
81
+ let bytes = 0;
82
+ try {
83
+ while (true) {
84
+ const item = await reader.read(); if (item.done) break;
85
+ bytes += item.value.byteLength;
86
+ if (bytes > MAX_OUTPUT) { kill(); throw new Error("policy_process_output_limit"); }
87
+ chunks.push(item.value);
88
+ }
89
+ return new TextDecoder("utf8", { fatal: true }).decode(Buffer.concat(chunks));
90
+ } finally { await reader.cancel(); reader.releaseLock(); }
91
+ };
92
+ const [stdout, stderr, exitCode] = await Promise.all([read(child.stdout), read(child.stderr), child.exited]);
93
+ return { stdout, stderr, exitCode, timedOut, isolation: { uid: user, gid: user, privateTreeSealed: true } };
94
+ } finally {
95
+ if (timer) clearTimeout(timer);
96
+ kill();
97
+ // A policy child can call setsid and escape its initial process group.
98
+ // Drain every process with this invocation's unique real UID before the
99
+ // next call; namespaces cannot grant a different outside UID or privilege.
100
+ try { await drainPolicyProcesses(user); }
101
+ finally { await fs.rm(directory, { recursive: true, force: true }); }
102
+ }
103
+ }
104
+
105
+ async function drainPolicyProcesses(user) {
106
+ const deadline = Date.now() + 2000;
107
+ let empty = 0;
108
+ while (Date.now() < deadline) {
109
+ const entries = (await fs.readdir("/proc")).filter(value => /^\d+$/.test(value));
110
+ if (entries.length > 10000) throw new Error("policy_process_inventory_limit");
111
+ let owned = 0;
112
+ for (const entry of entries) {
113
+ let status;
114
+ try { status = await fs.readFile("/proc/" + entry + "/status", "utf8"); }
115
+ catch (error) { if (["ENOENT", "ESRCH"].includes(error.code)) continue; throw error; }
116
+ const ids = /^Uid:\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/m.exec(status);
117
+ if (ids && ids.slice(1).some(value => Number(value) === user)) {
118
+ // Zombies cannot fork, inspect a subsequent invocation or hold files.
119
+ if (/^State:\s+Z/m.test(status)) continue;
120
+ owned++;
121
+ try { process.kill(Number(entry), "SIGKILL"); }
122
+ catch (error) { if (error.code !== "ESRCH") throw error; }
123
+ }
124
+ }
125
+ empty = owned === 0 ? empty + 1 : 0;
126
+ if (empty >= 2) return;
127
+ await new Promise(resolve => setTimeout(resolve, 20));
128
+ }
129
+ throw new Error("policy_process_cleanup_unconfirmed");
130
+ }
131
+ `;
package/dist/rewards.js CHANGED
@@ -4,7 +4,7 @@ import { ImmutableAssetRefSchema, ImmutableReleaseRefSchema, ReleaseHashSchema,
4
4
  import { gradeEvidence, GraderEvidenceSchema } from "./graders.js";
5
5
  import { CustomVerifierGraderSpecSchema, DeterministicGraderSpecSchema, GraderSpecSchema, HumanGraderSpecSchema, ModelJudgeGraderSpecSchema } from "./tasksets.js";
6
6
  import { assertBoundedTaskJson, validateTaskSchema } from "./task-schema.js";
7
- const bindingFields = { id: true, version: true, weight: true, hardGate: true, rewardEligible: true, privileged: true };
7
+ const bindingFields = { taskIds: true, id: true, version: true, weight: true, hardGate: true, rewardEligible: true, privileged: true };
8
8
  export const FeedbackKeySchema = z.string().regex(/^[a-z][a-z0-9_]{0,79}$/);
9
9
  export function feedbackKeyForReward(reward) {
10
10
  return reward.feedbackKey ?? `reward_${contentHash(reward.id).slice(0, 24)}`;
@@ -49,6 +49,7 @@ export const RewardNormalizationSchema = z.discriminatedUnion("kind", [
49
49
  ]);
50
50
  export const RewardBindingSourceSchema = z.object({
51
51
  graderId: ReleaseIdSchema,
52
+ taskIds: z.array(ReleaseIdSchema).min(1).max(10_000).refine(ids => new Set(ids).size === ids.length, "Task scope must be unique.").optional(),
52
53
  reward: RewardReleaseRefSchema,
53
54
  role: z.enum(["training", "evaluation"]),
54
55
  normalization: RewardNormalizationSchema,
@@ -87,7 +88,7 @@ export const BoundRewardResultSchema = z.object({
87
88
  graderId: ReleaseIdSchema,
88
89
  reward: RewardReleaseRefSchema,
89
90
  role: z.enum(["training", "evaluation"]),
90
- status: z.enum(["scored", "pending", "unavailable", "failed"]),
91
+ status: z.enum(["scored", "pending", "unavailable", "failed", "not_applicable"]),
91
92
  rawScore: z.number().finite().nullable(),
92
93
  normalizedScore: z.number().min(0).max(1).nullable(),
93
94
  passed: z.boolean().nullable(),
@@ -99,6 +100,7 @@ export const RewardCompositionContentSchema = z.object({
99
100
  schemaVersion: z.literal("openpond.rewardComposition.v1"),
100
101
  binding: RewardReleaseRefSchema,
101
102
  taskHash: ReleaseHashSchema,
103
+ taskId: ReleaseIdSchema.optional(),
102
104
  outputHash: ReleaseHashSchema,
103
105
  results: z.array(BoundRewardResultSchema).max(100),
104
106
  training: z.object({ status: z.enum(["scored", "pending", "unscorable", "not_configured"]), score: z.number().min(0).max(1).nullable(), passed: z.boolean().nullable() }).strict(),
@@ -149,6 +151,10 @@ export async function executeRewardBinding(input) {
149
151
  for (const { source, reward } of resolved) {
150
152
  input.signal?.throwIfAborted();
151
153
  const result = { graderId: source.graderId, reward: source.reward, role: source.role, status: "unavailable", rawScore: null, normalizedScore: null, passed: null, evidenceHashes: [], message: null };
154
+ if (source.taskIds && !source.taskIds.includes(input.task.id)) {
155
+ results.push({ ...result, status: "not_applicable" });
156
+ continue;
157
+ }
152
158
  try {
153
159
  if (reward.implementation.kind === "human") {
154
160
  result.status = "pending";
@@ -183,11 +189,13 @@ export async function executeRewardBinding(input) {
183
189
  }
184
190
  results.push(BoundRewardResultSchema.parse(result));
185
191
  }
186
- return composeBoundRewards({ binding: input.binding, taskHash: contentHash(input.task), outputHash: contentHash(input.evidence), results });
192
+ return composeBoundRewards({ binding: input.binding, ...(input.binding.sources.some(source => source.taskIds) ? { taskId: input.task.id } : {}), taskHash: contentHash(input.task), outputHash: contentHash(input.evidence), results });
187
193
  }
188
194
  export function composeBoundRewards(input) {
189
195
  const binding = RewardBindingSchema.parse(input.binding);
190
196
  assertRewardHash(binding);
197
+ if (binding.sources.some(source => source.taskIds) && !input.taskId)
198
+ throw new LearningDomainError("reward_task_scope_missing");
191
199
  const results = input.results.map((result) => BoundRewardResultSchema.parse(result));
192
200
  if (results.length !== binding.sources.length || new Set(results.map((result) => result.graderId)).size !== results.length)
193
201
  throw new LearningDomainError("reward_result_set_incomplete");
@@ -195,6 +203,9 @@ export function composeBoundRewards(input) {
195
203
  const result = results.find((candidate) => candidate.graderId === source.graderId);
196
204
  if (!result || contentHash(result.reward) !== contentHash(source.reward) || result.role !== source.role)
197
205
  throw new LearningDomainError("reward_result_binding_mismatch");
206
+ const applicable = !source.taskIds || source.taskIds.includes(input.taskId);
207
+ if (applicable === (result.status === "not_applicable") || !applicable && (result.graderEvidence || result.evidenceHashes.length || result.message !== null))
208
+ throw new LearningDomainError("reward_result_task_scope_mismatch");
198
209
  if (result.graderEvidence) {
199
210
  const { contentHash: evidenceHash, ...body } = result.graderEvidence;
200
211
  if (contentHash(body) !== evidenceHash || !result.evidenceHashes.includes(evidenceHash)
@@ -219,6 +230,7 @@ export function composeBoundRewards(input) {
219
230
  schemaVersion: "openpond.rewardComposition.v1",
220
231
  binding: { id: binding.id, revision: binding.revision, contentHash: binding.contentHash },
221
232
  taskHash: input.taskHash,
233
+ ...(input.taskId ? { taskId: input.taskId } : {}),
222
234
  outputHash: input.outputHash,
223
235
  results,
224
236
  training: aggregate("training"),
@@ -226,7 +238,7 @@ export function composeBoundRewards(input) {
226
238
  });
227
239
  return RewardCompositionSchema.parse({ ...content, contentHash: contentHash(content) });
228
240
  function aggregate(role) {
229
- const selected = binding.sources.filter((source) => source.role === role).map((source) => ({ source, result: results.find((candidate) => candidate.graderId === source.graderId) }));
241
+ const selected = binding.sources.filter((source) => source.role === role && (!source.taskIds || source.taskIds.includes(input.taskId))).map((source) => ({ source, result: results.find((candidate) => candidate.graderId === source.graderId) }));
230
242
  if (!selected.length)
231
243
  return { status: "not_configured", score: null, passed: null };
232
244
  if (selected.some(({ source, result }) => source.required && result.status !== "scored" && result.status !== "pending"))
@@ -250,5 +262,5 @@ function withoutRewardHash(value) { const { contentHash: _hash, ...content } = v
250
262
  function compileSource(source, reward) {
251
263
  if (reward.implementation.kind === "learned_model")
252
264
  throw new LearningDomainError("learned_reward_requires_model_execution_adapter");
253
- return GraderSpecSchema.parse({ ...reward.implementation, id: source.graderId, version: String(reward.revision), weight: source.weight, hardGate: source.hardGate, rewardEligible: source.role === "training", privileged: source.privileged });
265
+ return GraderSpecSchema.parse({ ...reward.implementation, ...(source.taskIds ? { taskIds: source.taskIds } : {}), id: source.graderId, version: String(reward.revision), weight: source.weight, hardGate: source.hardGate, rewardEligible: source.role === "training", privileged: source.privileged });
254
266
  }
@@ -1,5 +1,4 @@
1
1
  import { spawn } from "node:child_process";
2
- import { sqlExecutionProcessSource } from "./sql-execution-process-source.js";
3
2
  import { assertBoundedTaskJson } from "./task-schema.js";
4
3
  import { assertSqlExecutionRequest, SqlExecutionResultSchema } from "./sql-execution-contract.js";
5
4
  export * from "./sql-execution-contract.js";
@@ -9,6 +8,8 @@ export async function executeSqlInProcess(input) {
9
8
  if (!Number.isSafeInteger(input.timeoutMs) || input.timeoutMs < 1 || input.timeoutMs > 30_000)
10
9
  throw new Error("sql_timeout_invalid");
11
10
  const request = assertSqlExecutionRequest(input.request);
11
+ const { sqlExecutionProcessSource } = await import("./sql-execution-process-source.js");
12
+ input.signal?.throwIfAborted();
12
13
  const { signal } = input;
13
14
  const program = `globalThis.__openpondSqlInput = JSON.parse(${JSON.stringify(JSON.stringify(request))});\n${sqlExecutionProcessSource}`;
14
15
  return new Promise((resolve, reject) => {
package/dist/tasksets.js CHANGED
@@ -28,6 +28,7 @@ export const EnvironmentContractSchema = z.object({
28
28
  }).strict();
29
29
  const GraderBaseSchema = z.object({
30
30
  id: ReleaseIdSchema,
31
+ taskIds: z.array(ReleaseIdSchema).min(1).max(10_000).refine(ids => new Set(ids).size === ids.length, "Grader task IDs must be unique.").optional(),
31
32
  version: z.string().trim().min(1).max(100),
32
33
  weight: z.number().nonnegative().max(1_000).default(1),
33
34
  hardGate: z.boolean().default(false),
@@ -89,7 +90,7 @@ export const TasksetReleaseContentSchema = z.object({
89
90
  tools: z.array(ToolDeclarationSchema).max(200),
90
91
  capabilities: z.array(CapabilityRequirementSchema).max(200),
91
92
  tasks: z.array(TaskRecordSchema).min(1).max(1_000_000),
92
- graders: z.array(GraderSpecSchema).min(1).max(1_000),
93
+ graders: z.array(GraderSpecSchema).max(1_000),
93
94
  verifierSetRelease: z.object({ id: ReleaseIdSchema, contentHash: ReleaseHashSchema }).strict().optional(),
94
95
  metrics: TasksetMetricPolicySchema.optional(),
95
96
  metadata: MetadataSchema,
@@ -120,6 +121,11 @@ export function validateTasksetRelease(input) {
120
121
  path: "environmentRelease",
121
122
  });
122
123
  }
124
+ const taskIds = new Set(taskset.tasks.map(task => task.id));
125
+ for (const grader of taskset.graders)
126
+ if (grader.taskIds?.some(id => !taskIds.has(id))) {
127
+ issues.push({ code: "grader_task_missing", severity: "error", message: `Grader ${grader.id} refers to a task outside this release.`, path: "graders" });
128
+ }
123
129
  const clusterSplits = new Map();
124
130
  for (const task of taskset.tasks) {
125
131
  if (taskset.metrics?.aggregation === "weighted_mean" && !Object.hasOwn(taskset.metrics.taskWeights, task.id)) {
@@ -73,6 +73,7 @@ export declare const harnessRefinerBenchmarkRelease: {
73
73
  privileged: boolean;
74
74
  kind: "content" | "schema" | "artifact" | "runtime_event" | "state";
75
75
  config: Record<string, unknown>;
76
+ taskIds?: string[] | undefined;
76
77
  } | {
77
78
  id: string;
78
79
  version: string;
@@ -90,6 +91,7 @@ export declare const harnessRefinerBenchmarkRelease: {
90
91
  visibility: "policy" | "verifier" | "host_private";
91
92
  };
92
93
  calibrationStatus: "pending" | "passed" | "failed";
94
+ taskIds?: string[] | undefined;
93
95
  model?: {
94
96
  providerId: string;
95
97
  modelId: string;
@@ -114,6 +116,7 @@ export declare const harnessRefinerBenchmarkRelease: {
114
116
  };
115
117
  timeoutMs: number;
116
118
  networkPolicy: "none";
119
+ taskIds?: string[] | undefined;
117
120
  runtime?: "isolated_javascript" | "sandbox_process" | undefined;
118
121
  exportName?: string | undefined;
119
122
  } | {
@@ -133,6 +136,7 @@ export declare const harnessRefinerBenchmarkRelease: {
133
136
  visibility: "policy" | "verifier" | "host_private";
134
137
  };
135
138
  reviewerRole: string;
139
+ taskIds?: string[] | undefined;
136
140
  form?: {
137
141
  schemaVersion: "openpond.humanForm.v1";
138
142
  mode: "individual" | "pairwise";
@@ -1 +1 @@
1
- {"version":3,"file":"harness-refiner.d.ts","sourceRoot":"","sources":["../../../../../src/builtin-benchmarks/harness-refiner.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,8BAA8B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqqD1C,CAAC;AAEF,eAAO,MAAM,6BAA6B,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CASzE,CAAC"}
1
+ {"version":3,"file":"harness-refiner.d.ts","sourceRoot":"","sources":["../../../../../src/builtin-benchmarks/harness-refiner.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,8BAA8B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqqD1C,CAAC;AAEF,eAAO,MAAM,6BAA6B,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CASzE,CAAC"}
@@ -183,6 +183,7 @@ export declare const genericToolConformance: {
183
183
  privileged: boolean;
184
184
  kind: "content" | "schema" | "artifact" | "runtime_event" | "state";
185
185
  config: Record<string, unknown>;
186
+ taskIds?: string[] | undefined;
186
187
  } | {
187
188
  id: string;
188
189
  version: string;
@@ -200,6 +201,7 @@ export declare const genericToolConformance: {
200
201
  visibility: "policy" | "verifier" | "host_private";
201
202
  };
202
203
  calibrationStatus: "pending" | "passed" | "failed";
204
+ taskIds?: string[] | undefined;
203
205
  model?: {
204
206
  providerId: string;
205
207
  modelId: string;
@@ -224,6 +226,7 @@ export declare const genericToolConformance: {
224
226
  };
225
227
  timeoutMs: number;
226
228
  networkPolicy: "none";
229
+ taskIds?: string[] | undefined;
227
230
  runtime?: "isolated_javascript" | "sandbox_process" | undefined;
228
231
  exportName?: string | undefined;
229
232
  } | {
@@ -243,6 +246,7 @@ export declare const genericToolConformance: {
243
246
  visibility: "policy" | "verifier" | "host_private";
244
247
  };
245
248
  reviewerRole: string;
249
+ taskIds?: string[] | undefined;
246
250
  form?: {
247
251
  schemaVersion: "openpond.humanForm.v1";
248
252
  mode: "individual" | "pairwise";
@@ -568,6 +572,7 @@ export declare const marketingPortfolioConformance: {
568
572
  privileged: boolean;
569
573
  kind: "content" | "schema" | "artifact" | "runtime_event" | "state";
570
574
  config: Record<string, unknown>;
575
+ taskIds?: string[] | undefined;
571
576
  } | {
572
577
  id: string;
573
578
  version: string;
@@ -585,6 +590,7 @@ export declare const marketingPortfolioConformance: {
585
590
  visibility: "policy" | "verifier" | "host_private";
586
591
  };
587
592
  calibrationStatus: "pending" | "passed" | "failed";
593
+ taskIds?: string[] | undefined;
588
594
  model?: {
589
595
  providerId: string;
590
596
  modelId: string;
@@ -609,6 +615,7 @@ export declare const marketingPortfolioConformance: {
609
615
  };
610
616
  timeoutMs: number;
611
617
  networkPolicy: "none";
618
+ taskIds?: string[] | undefined;
612
619
  runtime?: "isolated_javascript" | "sandbox_process" | undefined;
613
620
  exportName?: string | undefined;
614
621
  } | {
@@ -628,6 +635,7 @@ export declare const marketingPortfolioConformance: {
628
635
  visibility: "policy" | "verifier" | "host_private";
629
636
  };
630
637
  reviewerRole: string;
638
+ taskIds?: string[] | undefined;
631
639
  form?: {
632
640
  schemaVersion: "openpond.humanForm.v1";
633
641
  mode: "individual" | "pairwise";