@tiangong-ai/cli 0.0.35 → 0.0.37

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 (47) hide show
  1. package/AGENTS.md +16 -6
  2. package/README.md +128 -10
  3. package/dist/research/orchestration.js +334 -29
  4. package/dist/research/orchestration.js.map +1 -1
  5. package/dist/research/workspace/acquisition-routes.d.ts +14 -0
  6. package/dist/research/workspace/acquisition-routes.js +45 -0
  7. package/dist/research/workspace/acquisition-routes.js.map +1 -0
  8. package/dist/research/workspace/audit-bundle.d.ts +44 -0
  9. package/dist/research/workspace/audit-bundle.js +357 -0
  10. package/dist/research/workspace/audit-bundle.js.map +1 -0
  11. package/dist/research/workspace/broker.js +54 -10
  12. package/dist/research/workspace/broker.js.map +1 -1
  13. package/dist/research/workspace/downloads.d.ts +6 -0
  14. package/dist/research/workspace/downloads.js +32 -8
  15. package/dist/research/workspace/downloads.js.map +1 -1
  16. package/dist/research/workspace/evidence-exhaustion.d.ts +45 -0
  17. package/dist/research/workspace/evidence-exhaustion.js +365 -0
  18. package/dist/research/workspace/evidence-exhaustion.js.map +1 -0
  19. package/dist/research/workspace/native-activity.d.ts +6 -0
  20. package/dist/research/workspace/native-activity.js +24 -7
  21. package/dist/research/workspace/native-activity.js.map +1 -1
  22. package/dist/research/workspace/preflight.d.ts +34 -2
  23. package/dist/research/workspace/preflight.js +161 -1
  24. package/dist/research/workspace/preflight.js.map +1 -1
  25. package/dist/research/workspace/projects.d.ts +28 -4
  26. package/dist/research/workspace/projects.js +301 -12
  27. package/dist/research/workspace/projects.js.map +1 -1
  28. package/dist/research/workspace/publication-workflow.js +2 -0
  29. package/dist/research/workspace/publication-workflow.js.map +1 -1
  30. package/dist/research/workspace/runtime.d.ts +151 -3
  31. package/dist/research/workspace/runtime.js +180 -6
  32. package/dist/research/workspace/runtime.js.map +1 -1
  33. package/dist/research/workspace/sanitization.js +9 -3
  34. package/dist/research/workspace/sanitization.js.map +1 -1
  35. package/dist/research/workspace/scientific-design.d.ts +359 -0
  36. package/dist/research/workspace/scientific-design.js +2021 -0
  37. package/dist/research/workspace/scientific-design.js.map +1 -0
  38. package/dist/research/workspace/scientific-review.d.ts +101 -0
  39. package/dist/research/workspace/scientific-review.js +1167 -0
  40. package/dist/research/workspace/scientific-review.js.map +1 -0
  41. package/dist/research/workspace/setup-catalog.js +2 -2
  42. package/dist/research/workspace/setup.js +12 -3
  43. package/dist/research/workspace/setup.js.map +1 -1
  44. package/dist/research/workspace/types.d.ts +54 -0
  45. package/dist/research/workspace/workspace.js +25 -7
  46. package/dist/research/workspace/workspace.js.map +1 -1
  47. package/package.json +2 -1
@@ -0,0 +1,357 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { constants as fsConstants } from "node:fs";
3
+ import { chmod, copyFile, lstat, mkdir, readFile, rename, rm } from "node:fs/promises";
4
+ import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
5
+ import { CliError } from "../../errors.js";
6
+ import { loadEvidenceArtifactRecords } from "./artifacts.js";
7
+ import { verifyCapabilities } from "./capabilities.js";
8
+ import { loadProjectEvidenceReceipts } from "./evidence.js";
9
+ import { readJournal, verifyJournal } from "./journal.js";
10
+ import { loadProject } from "./projects.js";
11
+ import { sanitizeResearchText } from "./sanitization.js";
12
+ import { canonicalJson, ensureDirectory, isObject, pathExists, readJsonFile, regularTreeFiles, resolveContained, safeRelativePath, sha256File, sha256Text, workspacePaths, writeJsonAtomic, } from "./storage.js";
13
+ import { loadWorkspaceConfig, withWorkspaceLock } from "./workspace.js";
14
+ const SHA256 = /^[a-f0-9]{64}$/;
15
+ const MAX_TEXT_SCAN_BYTES = 16 * 1024 * 1024;
16
+ export async function exportProjectAuditBundle(input) {
17
+ return withWorkspaceLock(input.root, "research.audit.export", async () => {
18
+ const destination = await validateNewDestination(input.destination);
19
+ const paths = workspacePaths(input.root);
20
+ const project = await loadProject(input.root, input.projectId);
21
+ const journal = await verifyJournal(paths.journal);
22
+ const temporary = join(dirname(destination), `.${basename(destination)}.${process.pid}.${randomUUID()}.tmp`);
23
+ await mkdir(temporary, { mode: 0o700 });
24
+ try {
25
+ const staged = new Set();
26
+ const stageFile = async (source, logicalPath) => {
27
+ const logical = safeRelativePath(logicalPath, "Audit bundle file");
28
+ if (staged.has(logical))
29
+ return;
30
+ const info = await lstat(source).catch(() => undefined);
31
+ if (!info?.isFile() || info.isSymbolicLink()) {
32
+ throw auditError(`Audit source is not an exact regular file: ${logical}`);
33
+ }
34
+ const target = resolveContained(temporary, logical);
35
+ await ensureDirectory(dirname(target));
36
+ await copyFile(source, target, fsConstants.COPYFILE_EXCL);
37
+ await chmod(target, 0o444).catch(() => undefined);
38
+ staged.add(logical);
39
+ };
40
+ const projectRoot = join(paths.projects, project.id);
41
+ const projectFiles = await regularTreeFiles(projectRoot).catch((error) => {
42
+ throw auditError("Project tree contains a non-portable entry.", error);
43
+ });
44
+ for (const source of projectFiles) {
45
+ const logical = relative(projectRoot, source).split(sep).join("/");
46
+ if (logical === "project.json" ||
47
+ logical.startsWith("runs/") ||
48
+ logical.startsWith("native/")) {
49
+ continue;
50
+ }
51
+ await stageFile(source, `project/${logical}`);
52
+ }
53
+ const portableProject = portableProjectState(project);
54
+ await writeJsonAtomic(join(temporary, "state", "project.json"), portableProject, 0o444);
55
+ staged.add("state/project.json");
56
+ for (const inputRecord of project.inputs) {
57
+ await assertSourceBinding(inputRecord.path, inputRecord.sha256, inputRecord.bytes);
58
+ await stageFile(inputRecord.path, `inputs/${inputRecord.sha256}`);
59
+ if (inputRecord.contextPath && inputRecord.contextSha256 && inputRecord.contextBytes) {
60
+ await assertSourceBinding(inputRecord.contextPath, inputRecord.contextSha256, inputRecord.contextBytes);
61
+ await stageFile(inputRecord.contextPath, `inputs/${inputRecord.contextSha256}`);
62
+ }
63
+ }
64
+ for (const document of project.publicationPolicy?.documents ?? []) {
65
+ const source = resolveContained(paths.control, document.objectLocator);
66
+ await assertSourceBinding(source, document.sha256);
67
+ await stageFile(source, `workspace-objects/${document.objectLocator}`);
68
+ }
69
+ const receipts = await loadProjectEvidenceReceipts(input.root, project.id);
70
+ for (const receipt of receipts) {
71
+ await stageFile(resolveContained(paths.control, receipt.locator), `workspace-objects/${receipt.locator}`);
72
+ await stageFile(resolveContained(paths.control, receipt.contextLocator), `workspace-objects/${receipt.contextLocator}`);
73
+ }
74
+ const artifacts = await loadEvidenceArtifactRecords(input.root, project.id);
75
+ for (const artifact of artifacts) {
76
+ await assertSourceBinding(resolveContained(paths.control, artifact.locator), artifact.sha256, artifact.bytes);
77
+ await stageFile(resolveContained(paths.control, artifact.locator), `workspace-objects/${artifact.locator}`);
78
+ }
79
+ const [config, runtimeLock, capabilityVerification, journalEvents] = await Promise.all([
80
+ loadWorkspaceConfig(input.root),
81
+ readJsonFile(paths.runtimeLock, "Research runtime lock"),
82
+ verifyCapabilities(input.root),
83
+ readJournal(paths.journal),
84
+ ]);
85
+ await writeJsonAtomic(join(temporary, "state", "environment.json"), {
86
+ schemaVersion: 1,
87
+ mode: config.mode,
88
+ producer: portableAgentRoute(config.producer),
89
+ reviewer: portableAgentRoute(config.reviewer),
90
+ budget: config.budget,
91
+ runtimeLock,
92
+ capabilityVerification,
93
+ }, 0o444);
94
+ staged.add("state/environment.json");
95
+ await writeJsonAtomic(join(temporary, "state", "journal-event-proofs.json"), {
96
+ schemaVersion: 1,
97
+ workspaceJournalHead: journal.head,
98
+ events: journalEvents.filter((event) => event.scope === project.id || containsExactString(event.payload, project.id)),
99
+ }, 0o444);
100
+ staged.add("state/journal-event-proofs.json");
101
+ await assertPortableTextFiles(temporary, resolve(input.root));
102
+ const files = await bundleFileRecords(temporary);
103
+ const projectStatePath = join(projectRoot, "project.json");
104
+ const capabilityLockSha256 = (await pathExists(paths.capabilityLock))
105
+ ? await sha256File(paths.capabilityLock)
106
+ : null;
107
+ const manifestCore = {
108
+ schemaVersion: 1,
109
+ kind: "tiangong-project-audit-bundle",
110
+ projectId: project.id,
111
+ createdAt: new Date().toISOString(),
112
+ authority: {
113
+ status: project.status,
114
+ lineageKind: project.lineage.kind,
115
+ derivedFrom: project.lineage.derivedFrom,
116
+ supersedes: project.lineage.supersedes,
117
+ supersededBy: project.lineage.supersededBy,
118
+ },
119
+ sourceBindings: {
120
+ projectStateSha256: await sha256File(projectStatePath),
121
+ workspaceJournalHead: journal.head,
122
+ workspaceRuntimeLockSha256: await sha256File(paths.runtimeLock),
123
+ capabilityLockSha256,
124
+ sourceWorkspacePathSha256: sha256Text(resolve(input.root)),
125
+ },
126
+ locatorRoots: {
127
+ project: "project",
128
+ workspaceObjects: "workspace-objects",
129
+ inputs: "inputs",
130
+ },
131
+ exclusions: [
132
+ "credentials and environment secrets",
133
+ "setup sources and browser profiles",
134
+ "active native-stage state",
135
+ "ephemeral run capsules and raw agent authentication",
136
+ "unrelated workspace projects and files",
137
+ ],
138
+ files,
139
+ };
140
+ const manifest = {
141
+ ...manifestCore,
142
+ manifestSha256: sha256Text(canonicalJson(manifestCore)),
143
+ };
144
+ await writeJsonAtomic(join(temporary, "manifest.json"), manifest, 0o444);
145
+ await verifyProjectAuditBundle(temporary);
146
+ await rename(temporary, destination);
147
+ return manifest;
148
+ }
149
+ catch (error) {
150
+ await rm(temporary, { recursive: true, force: true }).catch(() => undefined);
151
+ throw error;
152
+ }
153
+ });
154
+ }
155
+ export async function verifyProjectAuditBundle(bundlePath) {
156
+ if (!isAbsolute(bundlePath) || resolve(bundlePath) !== bundlePath) {
157
+ throw auditPathError("Audit bundle path must be absolute and normalized.");
158
+ }
159
+ const info = await lstat(bundlePath).catch(() => undefined);
160
+ if (!info?.isDirectory() || info.isSymbolicLink()) {
161
+ throw auditPathError("Audit bundle must be a regular directory and not a symbolic link.");
162
+ }
163
+ const manifestPath = join(bundlePath, "manifest.json");
164
+ const manifestInfo = await lstat(manifestPath).catch(() => undefined);
165
+ if (!manifestInfo?.isFile() || manifestInfo.isSymbolicLink()) {
166
+ throw auditError("Audit manifest is missing or is not a regular file.");
167
+ }
168
+ let value;
169
+ try {
170
+ value = JSON.parse(await readFile(manifestPath, "utf8"));
171
+ }
172
+ catch {
173
+ throw auditError("Audit manifest is not valid JSON.");
174
+ }
175
+ const manifest = parseManifest(value);
176
+ const { manifestSha256, ...core } = manifest;
177
+ if (sha256Text(canonicalJson(core)) !== manifestSha256) {
178
+ throw auditError("Audit manifest failed its hash binding.");
179
+ }
180
+ const actualFiles = (await regularTreeFiles(bundlePath))
181
+ .map((path) => relative(bundlePath, path).split(sep).join("/"))
182
+ .filter((path) => path !== "manifest.json");
183
+ const expectedPaths = manifest.files.map((file) => file.path);
184
+ if (actualFiles.length !== expectedPaths.length ||
185
+ actualFiles.some((path, index) => path !== expectedPaths[index])) {
186
+ throw auditError("Audit bundle contains missing, extra, or unordered files.");
187
+ }
188
+ for (const record of manifest.files) {
189
+ const path = resolveContained(bundlePath, record.path);
190
+ const fileInfo = await lstat(path).catch(() => undefined);
191
+ if (!fileInfo?.isFile() ||
192
+ fileInfo.isSymbolicLink() ||
193
+ fileInfo.size !== record.bytes ||
194
+ (await sha256File(path)) !== record.sha256) {
195
+ throw auditError(`Audit file failed its exact binding: ${record.path}`);
196
+ }
197
+ }
198
+ await assertPortableTextFiles(bundlePath);
199
+ return {
200
+ status: "verified",
201
+ projectId: manifest.projectId,
202
+ manifestSha256,
203
+ files: manifest.files.length,
204
+ };
205
+ }
206
+ function portableProjectState(project) {
207
+ const portable = structuredClone(project);
208
+ portable.inputs = portable.inputs.map((input) => ({
209
+ ...input,
210
+ path: `inputs/${input.sha256}`,
211
+ ...(input.contextPath && input.contextSha256
212
+ ? { contextPath: `inputs/${input.contextSha256}` }
213
+ : {}),
214
+ }));
215
+ return portable;
216
+ }
217
+ function portableAgentRoute(route) {
218
+ return {
219
+ agent: route.agent,
220
+ executionMode: route.executionMode,
221
+ binaryName: basename(route.binary),
222
+ model: route.model,
223
+ effort: route.effort ?? null,
224
+ verbosity: route.verbosity ?? null,
225
+ };
226
+ }
227
+ async function bundleFileRecords(root) {
228
+ const files = await regularTreeFiles(root);
229
+ return Promise.all(files
230
+ .map((path) => ({ path, logical: relative(root, path).split(sep).join("/") }))
231
+ .filter((item) => item.logical !== "manifest.json")
232
+ .map(async ({ path, logical }) => {
233
+ const info = await lstat(path);
234
+ return { path: logical, sha256: await sha256File(path), bytes: info.size };
235
+ }));
236
+ }
237
+ async function assertSourceBinding(path, expectedSha256, expectedBytes) {
238
+ const info = await lstat(path).catch(() => undefined);
239
+ if (!info?.isFile() ||
240
+ info.isSymbolicLink() ||
241
+ (expectedBytes !== undefined && info.size !== expectedBytes) ||
242
+ (await sha256File(path)) !== expectedSha256) {
243
+ throw auditError("An audit source no longer matches its recorded hash and size.");
244
+ }
245
+ }
246
+ async function assertPortableTextFiles(root, forbiddenRoot) {
247
+ for (const path of await regularTreeFiles(root)) {
248
+ const info = await lstat(path);
249
+ if (info.size > MAX_TEXT_SCAN_BYTES)
250
+ continue;
251
+ const bytes = await readFile(path);
252
+ if (!looksTextual(path, bytes))
253
+ continue;
254
+ const text = bytes.toString("utf8");
255
+ if (forbiddenRoot && text.includes(forbiddenRoot)) {
256
+ throw new CliError("Audit bundle contains a host-specific workspace path.", {
257
+ code: "RESEARCH_AUDIT_BUNDLE_NONPORTABLE",
258
+ exitCode: 3,
259
+ });
260
+ }
261
+ if (sanitizeResearchText(text) !== text) {
262
+ throw new CliError("Audit bundle contains credential-like or sensitive text.", {
263
+ code: "RESEARCH_AUDIT_BUNDLE_SENSITIVE",
264
+ exitCode: 3,
265
+ });
266
+ }
267
+ }
268
+ }
269
+ function looksTextual(path, bytes) {
270
+ if (bytes.includes(0))
271
+ return false;
272
+ if (/\.(?:csv|json|jsonl|md|txt|tsv|ya?ml)$/iu.test(path))
273
+ return true;
274
+ const start = bytes.subarray(0, 64).toString("utf8").trimStart();
275
+ return start.startsWith("{") || start.startsWith("[");
276
+ }
277
+ async function validateNewDestination(value) {
278
+ if (!isAbsolute(value) || resolve(value) !== value) {
279
+ throw auditPathError("Audit export destination must be absolute and normalized.");
280
+ }
281
+ if (await pathExists(value)) {
282
+ throw auditPathError("Audit export destination must not already exist.");
283
+ }
284
+ const parent = dirname(value);
285
+ const parentInfo = await lstat(parent).catch(() => undefined);
286
+ if (!parentInfo?.isDirectory() || parentInfo.isSymbolicLink()) {
287
+ throw auditPathError("Audit export parent must be an existing regular directory.");
288
+ }
289
+ return value;
290
+ }
291
+ function parseManifest(value) {
292
+ if (!isObject(value) ||
293
+ value.schemaVersion !== 1 ||
294
+ value.kind !== "tiangong-project-audit-bundle" ||
295
+ typeof value.projectId !== "string" ||
296
+ typeof value.createdAt !== "string" ||
297
+ !isObject(value.authority) ||
298
+ !isObject(value.sourceBindings) ||
299
+ !isObject(value.locatorRoots) ||
300
+ value.locatorRoots.project !== "project" ||
301
+ value.locatorRoots.workspaceObjects !== "workspace-objects" ||
302
+ value.locatorRoots.inputs !== "inputs" ||
303
+ !Array.isArray(value.exclusions) ||
304
+ value.exclusions.some((item) => typeof item !== "string") ||
305
+ !Array.isArray(value.files) ||
306
+ typeof value.manifestSha256 !== "string" ||
307
+ !SHA256.test(value.manifestSha256)) {
308
+ throw auditError("Audit manifest shape is invalid.");
309
+ }
310
+ const files = value.files;
311
+ if (files.some((file) => !isObject(file) ||
312
+ typeof file.path !== "string" ||
313
+ safePathOrNull(file.path) === null ||
314
+ typeof file.sha256 !== "string" ||
315
+ !SHA256.test(file.sha256) ||
316
+ !Number.isSafeInteger(file.bytes) ||
317
+ Number(file.bytes) < 0)) {
318
+ throw auditError("Audit manifest file records are invalid.");
319
+ }
320
+ const paths = files.map((file) => String(file.path));
321
+ if (new Set(paths).size !== paths.length ||
322
+ paths.some((path, index) => index > 0 && paths[index - 1] >= path)) {
323
+ throw auditError("Audit manifest file paths must be unique and byte-order sorted.");
324
+ }
325
+ return value;
326
+ }
327
+ function safePathOrNull(value) {
328
+ try {
329
+ return safeRelativePath(value, "Audit manifest path");
330
+ }
331
+ catch {
332
+ return null;
333
+ }
334
+ }
335
+ function containsExactString(value, target) {
336
+ if (value === target)
337
+ return true;
338
+ if (Array.isArray(value))
339
+ return value.some((item) => containsExactString(item, target));
340
+ if (!isObject(value))
341
+ return false;
342
+ return Object.values(value).some((item) => containsExactString(item, target));
343
+ }
344
+ function auditError(message, cause) {
345
+ return new CliError(message, {
346
+ code: "RESEARCH_AUDIT_BUNDLE_INVALID",
347
+ exitCode: 3,
348
+ details: cause ? { cause: cause instanceof Error ? cause.message : String(cause) } : undefined,
349
+ });
350
+ }
351
+ function auditPathError(message) {
352
+ return new CliError(message, {
353
+ code: "RESEARCH_AUDIT_BUNDLE_PATH_INVALID",
354
+ exitCode: 2,
355
+ });
356
+ }
357
+ //# sourceMappingURL=audit-bundle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-bundle.js","sourceRoot":"","sources":["../../../src/research/workspace/audit-bundle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,SAAS,IAAI,WAAW,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AACvF,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAExF,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,2BAA2B,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,2BAA2B,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EACL,aAAa,EACb,eAAe,EACf,QAAQ,EACR,UAAU,EACV,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,UAAU,EACV,UAAU,EACV,cAAc,EACd,eAAe,GAChB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAExE,MAAM,MAAM,GAAG,gBAAgB,CAAC;AAChC,MAAM,mBAAmB,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;AA+B7C,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAAC,KAI9C;IACC,OAAO,iBAAiB,CAAC,KAAK,CAAC,IAAI,EAAE,uBAAuB,EAAE,KAAK,IAAI,EAAE;QACvE,MAAM,WAAW,GAAG,MAAM,sBAAsB,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QACpE,MAAM,KAAK,GAAG,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACzC,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;QAC/D,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACnD,MAAM,SAAS,GAAG,IAAI,CACpB,OAAO,CAAC,WAAW,CAAC,EACpB,IAAI,QAAQ,CAAC,WAAW,CAAC,IAAI,OAAO,CAAC,GAAG,IAAI,UAAU,EAAE,MAAM,CAC/D,CAAC;QACF,MAAM,KAAK,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QACxC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,GAAG,EAAU,CAAC;YACjC,MAAM,SAAS,GAAG,KAAK,EAAE,MAAc,EAAE,WAAmB,EAAiB,EAAE;gBAC7E,MAAM,OAAO,GAAG,gBAAgB,CAAC,WAAW,EAAE,mBAAmB,CAAC,CAAC;gBACnE,IAAI,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC;oBAAE,OAAO;gBAChC,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;gBACxD,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC;oBAC7C,MAAM,UAAU,CAAC,8CAA8C,OAAO,EAAE,CAAC,CAAC;gBAC5E,CAAC;gBACD,MAAM,MAAM,GAAG,gBAAgB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;gBACpD,MAAM,eAAe,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;gBACvC,MAAM,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,aAAa,CAAC,CAAC;gBAC1D,MAAM,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;gBAClD,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACtB,CAAC,CAAC;YAEF,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;YACrD,MAAM,YAAY,GAAG,MAAM,gBAAgB,CAAC,WAAW,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;gBACvE,MAAM,UAAU,CAAC,6CAA6C,EAAE,KAAK,CAAC,CAAC;YACzE,CAAC,CAAC,CAAC;YACH,KAAK,MAAM,MAAM,IAAI,YAAY,EAAE,CAAC;gBAClC,MAAM,OAAO,GAAG,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACnE,IACE,OAAO,KAAK,cAAc;oBAC1B,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC;oBAC3B,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,EAC7B,CAAC;oBACD,SAAS;gBACX,CAAC;gBACD,MAAM,SAAS,CAAC,MAAM,EAAE,WAAW,OAAO,EAAE,CAAC,CAAC;YAChD,CAAC;YAED,MAAM,eAAe,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAC;YACtD,MAAM,eAAe,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,cAAc,CAAC,EAAE,eAAe,EAAE,KAAK,CAAC,CAAC;YACxF,MAAM,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;YAEjC,KAAK,MAAM,WAAW,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;gBACzC,MAAM,mBAAmB,CAAC,WAAW,CAAC,IAAI,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC;gBACnF,MAAM,SAAS,CAAC,WAAW,CAAC,IAAI,EAAE,UAAU,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC;gBAClE,IAAI,WAAW,CAAC,WAAW,IAAI,WAAW,CAAC,aAAa,IAAI,WAAW,CAAC,YAAY,EAAE,CAAC;oBACrF,MAAM,mBAAmB,CACvB,WAAW,CAAC,WAAW,EACvB,WAAW,CAAC,aAAa,EACzB,WAAW,CAAC,YAAY,CACzB,CAAC;oBACF,MAAM,SAAS,CAAC,WAAW,CAAC,WAAW,EAAE,UAAU,WAAW,CAAC,aAAa,EAAE,CAAC,CAAC;gBAClF,CAAC;YACH,CAAC;YAED,KAAK,MAAM,QAAQ,IAAI,OAAO,CAAC,iBAAiB,EAAE,SAAS,IAAI,EAAE,EAAE,CAAC;gBAClE,MAAM,MAAM,GAAG,gBAAgB,CAAC,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,aAAa,CAAC,CAAC;gBACvE,MAAM,mBAAmB,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;gBACnD,MAAM,SAAS,CAAC,MAAM,EAAE,qBAAqB,QAAQ,CAAC,aAAa,EAAE,CAAC,CAAC;YACzE,CAAC;YAED,MAAM,QAAQ,GAAG,MAAM,2BAA2B,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;YAC3E,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;gBAC/B,MAAM,SAAS,CACb,gBAAgB,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,EAChD,qBAAqB,OAAO,CAAC,OAAO,EAAE,CACvC,CAAC;gBACF,MAAM,SAAS,CACb,gBAAgB,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,cAAc,CAAC,EACvD,qBAAqB,OAAO,CAAC,cAAc,EAAE,CAC9C,CAAC;YACJ,CAAC;YACD,MAAM,SAAS,GAAG,MAAM,2BAA2B,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;YAC5E,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;gBACjC,MAAM,mBAAmB,CACvB,gBAAgB,CAAC,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,EACjD,QAAQ,CAAC,MAAM,EACf,QAAQ,CAAC,KAAK,CACf,CAAC;gBACF,MAAM,SAAS,CACb,gBAAgB,CAAC,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,EACjD,qBAAqB,QAAQ,CAAC,OAAO,EAAE,CACxC,CAAC;YACJ,CAAC;YAED,MAAM,CAAC,MAAM,EAAE,WAAW,EAAE,sBAAsB,EAAE,aAAa,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;gBACrF,mBAAmB,CAAC,KAAK,CAAC,IAAI,CAAC;gBAC/B,YAAY,CAAc,KAAK,CAAC,WAAW,EAAE,uBAAuB,CAAC;gBACrE,kBAAkB,CAAC,KAAK,CAAC,IAAI,CAAC;gBAC9B,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC;aAC3B,CAAC,CAAC;YACH,MAAM,eAAe,CACnB,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,kBAAkB,CAAC,EAC5C;gBACE,aAAa,EAAE,CAAC;gBAChB,IAAI,EAAE,MAAM,CAAC,IAAI;gBACjB,QAAQ,EAAE,kBAAkB,CAAC,MAAM,CAAC,QAAQ,CAAC;gBAC7C,QAAQ,EAAE,kBAAkB,CAAC,MAAM,CAAC,QAAQ,CAAC;gBAC7C,MAAM,EAAE,MAAM,CAAC,MAAM;gBACrB,WAAW;gBACX,sBAAsB;aACvB,EACD,KAAK,CACN,CAAC;YACF,MAAM,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;YACrC,MAAM,eAAe,CACnB,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,2BAA2B,CAAC,EACrD;gBACE,aAAa,EAAE,CAAC;gBAChB,oBAAoB,EAAE,OAAO,CAAC,IAAI;gBAClC,MAAM,EAAE,aAAa,CAAC,MAAM,CAC1B,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,KAAK,OAAO,CAAC,EAAE,IAAI,mBAAmB,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,CACxF;aACF,EACD,KAAK,CACN,CAAC;YACF,MAAM,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC;YAE9C,MAAM,uBAAuB,CAAC,SAAS,EAAE,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;YAC9D,MAAM,KAAK,GAAG,MAAM,iBAAiB,CAAC,SAAS,CAAC,CAAC;YACjD,MAAM,gBAAgB,GAAG,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;YAC3D,MAAM,oBAAoB,GAAG,CAAC,MAAM,UAAU,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;gBACnE,CAAC,CAAC,MAAM,UAAU,CAAC,KAAK,CAAC,cAAc,CAAC;gBACxC,CAAC,CAAC,IAAI,CAAC;YACT,MAAM,YAAY,GAAG;gBACnB,aAAa,EAAE,CAAU;gBACzB,IAAI,EAAE,+BAAwC;gBAC9C,SAAS,EAAE,OAAO,CAAC,EAAE;gBACrB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBACnC,SAAS,EAAE;oBACT,MAAM,EAAE,OAAO,CAAC,MAAM;oBACtB,WAAW,EAAE,OAAO,CAAC,OAAO,CAAC,IAAI;oBACjC,WAAW,EAAE,OAAO,CAAC,OAAO,CAAC,WAAW;oBACxC,UAAU,EAAE,OAAO,CAAC,OAAO,CAAC,UAAU;oBACtC,YAAY,EAAE,OAAO,CAAC,OAAO,CAAC,YAAY;iBAC3C;gBACD,cAAc,EAAE;oBACd,kBAAkB,EAAE,MAAM,UAAU,CAAC,gBAAgB,CAAC;oBACtD,oBAAoB,EAAE,OAAO,CAAC,IAAI;oBAClC,0BAA0B,EAAE,MAAM,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC;oBAC/D,oBAAoB;oBACpB,yBAAyB,EAAE,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;iBAC3D;gBACD,YAAY,EAAE;oBACZ,OAAO,EAAE,SAAkB;oBAC3B,gBAAgB,EAAE,mBAA4B;oBAC9C,MAAM,EAAE,QAAiB;iBAC1B;gBACD,UAAU,EAAE;oBACV,qCAAqC;oBACrC,oCAAoC;oBACpC,2BAA2B;oBAC3B,qDAAqD;oBACrD,wCAAwC;iBACzC;gBACD,KAAK;aACN,CAAC;YACF,MAAM,QAAQ,GAAyB;gBACrC,GAAG,YAAY;gBACf,cAAc,EAAE,UAAU,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;aACxD,CAAC;YACF,MAAM,eAAe,CAAC,IAAI,CAAC,SAAS,EAAE,eAAe,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;YACzE,MAAM,wBAAwB,CAAC,SAAS,CAAC,CAAC;YAC1C,MAAM,MAAM,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;YACrC,OAAO,QAAQ,CAAC;QAClB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,EAAE,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;YAC7E,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,UAAkB;IAElB,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,KAAK,UAAU,EAAE,CAAC;QAClE,MAAM,cAAc,CAAC,oDAAoD,CAAC,CAAC;IAC7E,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IAC5D,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC;QAClD,MAAM,cAAc,CAAC,mEAAmE,CAAC,CAAC;IAC5F,CAAC;IACD,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC;IACvD,MAAM,YAAY,GAAG,MAAM,KAAK,CAAC,YAAY,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IACtE,IAAI,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,YAAY,CAAC,cAAc,EAAE,EAAE,CAAC;QAC7D,MAAM,UAAU,CAAC,qDAAqD,CAAC,CAAC;IAC1E,CAAC;IACD,IAAI,KAAc,CAAC;IACnB,IAAI,CAAC;QACH,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,CAAY,CAAC;IACtE,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,UAAU,CAAC,mCAAmC,CAAC,CAAC;IACxD,CAAC;IACD,MAAM,QAAQ,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IACtC,MAAM,EAAE,cAAc,EAAE,GAAG,IAAI,EAAE,GAAG,QAAQ,CAAC;IAC7C,IAAI,UAAU,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,KAAK,cAAc,EAAE,CAAC;QACvD,MAAM,UAAU,CAAC,yCAAyC,CAAC,CAAC;IAC9D,CAAC;IACD,MAAM,WAAW,GAAG,CAAC,MAAM,gBAAgB,CAAC,UAAU,CAAC,CAAC;SACrD,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;SAC9D,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,eAAe,CAAC,CAAC;IAC9C,MAAM,aAAa,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9D,IACE,WAAW,CAAC,MAAM,KAAK,aAAa,CAAC,MAAM;QAC3C,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,KAAK,aAAa,CAAC,KAAK,CAAC,CAAC,EAChE,CAAC;QACD,MAAM,UAAU,CAAC,2DAA2D,CAAC,CAAC;IAChF,CAAC;IACD,KAAK,MAAM,MAAM,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;QACpC,MAAM,IAAI,GAAG,gBAAgB,CAAC,UAAU,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;QACvD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC1D,IACE,CAAC,QAAQ,EAAE,MAAM,EAAE;YACnB,QAAQ,CAAC,cAAc,EAAE;YACzB,QAAQ,CAAC,IAAI,KAAK,MAAM,CAAC,KAAK;YAC9B,CAAC,MAAM,UAAU,CAAC,IAAI,CAAC,CAAC,KAAK,MAAM,CAAC,MAAM,EAC1C,CAAC;YACD,MAAM,UAAU,CAAC,wCAAwC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QAC1E,CAAC;IACH,CAAC;IACD,MAAM,uBAAuB,CAAC,UAAU,CAAC,CAAC;IAC1C,OAAO;QACL,MAAM,EAAE,UAAU;QAClB,SAAS,EAAE,QAAQ,CAAC,SAAS;QAC7B,cAAc;QACd,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,MAAM;KAC7B,CAAC;AACJ,CAAC;AAED,SAAS,oBAAoB,CAAC,OAAqB;IACjD,MAAM,QAAQ,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;IAC1C,QAAQ,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAChD,GAAG,KAAK;QACR,IAAI,EAAE,UAAU,KAAK,CAAC,MAAM,EAAE;QAC9B,GAAG,CAAC,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,aAAa;YAC1C,CAAC,CAAC,EAAE,WAAW,EAAE,UAAU,KAAK,CAAC,aAAa,EAAE,EAAE;YAClD,CAAC,CAAC,EAAE,CAAC;KACR,CAAC,CAAC,CAAC;IACJ,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAiB;IAC3C,OAAO;QACL,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,UAAU,EAAE,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC;QAClC,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,IAAI;QAC5B,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,IAAI;KACnC,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,iBAAiB,CAC9B,IAAY;IAEZ,MAAM,KAAK,GAAG,MAAM,gBAAgB,CAAC,IAAI,CAAC,CAAC;IAC3C,OAAO,OAAO,CAAC,GAAG,CAChB,KAAK;SACF,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;SAC7E,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,KAAK,eAAe,CAAC;SAClD,GAAG,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE;QAC/B,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC;QAC/B,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC;IAC7E,CAAC,CAAC,CACL,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,mBAAmB,CAChC,IAAY,EACZ,cAAsB,EACtB,aAAsB;IAEtB,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IACtD,IACE,CAAC,IAAI,EAAE,MAAM,EAAE;QACf,IAAI,CAAC,cAAc,EAAE;QACrB,CAAC,aAAa,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,KAAK,aAAa,CAAC;QAC5D,CAAC,MAAM,UAAU,CAAC,IAAI,CAAC,CAAC,KAAK,cAAc,EAC3C,CAAC;QACD,MAAM,UAAU,CAAC,+DAA+D,CAAC,CAAC;IACpF,CAAC;AACH,CAAC;AAED,KAAK,UAAU,uBAAuB,CAAC,IAAY,EAAE,aAAsB;IACzE,KAAK,MAAM,IAAI,IAAI,MAAM,gBAAgB,CAAC,IAAI,CAAC,EAAE,CAAC;QAChD,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,IAAI,CAAC,IAAI,GAAG,mBAAmB;YAAE,SAAS;QAC9C,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC;QACnC,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC;YAAE,SAAS;QACzC,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACpC,IAAI,aAAa,IAAI,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;YAClD,MAAM,IAAI,QAAQ,CAAC,uDAAuD,EAAE;gBAC1E,IAAI,EAAE,mCAAmC;gBACzC,QAAQ,EAAE,CAAC;aACZ,CAAC,CAAC;QACL,CAAC;QACD,IAAI,oBAAoB,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;YACxC,MAAM,IAAI,QAAQ,CAAC,0DAA0D,EAAE;gBAC7E,IAAI,EAAE,iCAAiC;gBACvC,QAAQ,EAAE,CAAC;aACZ,CAAC,CAAC;QACL,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,IAAY,EAAE,KAAa;IAC/C,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACpC,IAAI,0CAA0C,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACvE,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,CAAC;IACjE,OAAO,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;AACxD,CAAC;AAED,KAAK,UAAU,sBAAsB,CAAC,KAAa;IACjD,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,KAAK,EAAE,CAAC;QACnD,MAAM,cAAc,CAAC,2DAA2D,CAAC,CAAC;IACpF,CAAC;IACD,IAAI,MAAM,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5B,MAAM,cAAc,CAAC,kDAAkD,CAAC,CAAC;IAC3E,CAAC;IACD,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IAC9B,MAAM,UAAU,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IAC9D,IAAI,CAAC,UAAU,EAAE,WAAW,EAAE,IAAI,UAAU,CAAC,cAAc,EAAE,EAAE,CAAC;QAC9D,MAAM,cAAc,CAAC,4DAA4D,CAAC,CAAC;IACrF,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACnC,IACE,CAAC,QAAQ,CAAC,KAAK,CAAC;QAChB,KAAK,CAAC,aAAa,KAAK,CAAC;QACzB,KAAK,CAAC,IAAI,KAAK,+BAA+B;QAC9C,OAAO,KAAK,CAAC,SAAS,KAAK,QAAQ;QACnC,OAAO,KAAK,CAAC,SAAS,KAAK,QAAQ;QACnC,CAAC,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC;QAC1B,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC;QAC/B,CAAC,QAAQ,CAAC,KAAK,CAAC,YAAY,CAAC;QAC7B,KAAK,CAAC,YAAY,CAAC,OAAO,KAAK,SAAS;QACxC,KAAK,CAAC,YAAY,CAAC,gBAAgB,KAAK,mBAAmB;QAC3D,KAAK,CAAC,YAAY,CAAC,MAAM,KAAK,QAAQ;QACtC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC;QAChC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,IAAI,KAAK,QAAQ,CAAC;QACzD,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC;QAC3B,OAAO,KAAK,CAAC,cAAc,KAAK,QAAQ;QACxC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,EAClC,CAAC;QACD,MAAM,UAAU,CAAC,kCAAkC,CAAC,CAAC;IACvD,CAAC;IACD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAkB,CAAC;IACvC,IACE,KAAK,CAAC,IAAI,CACR,CAAC,IAAI,EAAE,EAAE,CACP,CAAC,QAAQ,CAAC,IAAI,CAAC;QACf,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ;QAC7B,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI;QAClC,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ;QAC/B,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;QACzB,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC;QACjC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CACzB,EACD,CAAC;QACD,MAAM,UAAU,CAAC,0CAA0C,CAAC,CAAC;IAC/D,CAAC;IACD,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAE,IAAgC,CAAC,IAAI,CAAC,CAAC,CAAC;IAClF,IACE,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,MAAM;QACpC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,GAAG,CAAC,IAAI,KAAK,CAAC,KAAK,GAAG,CAAC,CAAE,IAAI,IAAI,CAAC,EACnE,CAAC;QACD,MAAM,UAAU,CAAC,iEAAiE,CAAC,CAAC;IACtF,CAAC;IACD,OAAO,KAAwC,CAAC;AAClD,CAAC;AAED,SAAS,cAAc,CAAC,KAAa;IACnC,IAAI,CAAC;QACH,OAAO,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,CAAC,CAAC;IACxD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAc,EAAE,MAAc;IACzD,IAAI,KAAK,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC;IAClC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,mBAAmB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;IACzF,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACnC,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,mBAAmB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;AAChF,CAAC;AAED,SAAS,UAAU,CAAC,OAAe,EAAE,KAAe;IAClD,OAAO,IAAI,QAAQ,CAAC,OAAO,EAAE;QAC3B,IAAI,EAAE,+BAA+B;QACrC,QAAQ,EAAE,CAAC;QACX,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS;KAC/F,CAAC,CAAC;AACL,CAAC;AAED,SAAS,cAAc,CAAC,OAAe;IACrC,OAAO,IAAI,QAAQ,CAAC,OAAO,EAAE;QAC3B,IAAI,EAAE,oCAAoC;QAC1C,QAAQ,EAAE,CAAC;KACZ,CAAC,CAAC;AACL,CAAC"}
@@ -3,6 +3,7 @@ import { createServer } from "node:http";
3
3
  import { readFile, writeFile } from "node:fs/promises";
4
4
  import { dirname, join } from "node:path";
5
5
  import { CliError } from "../../errors.js";
6
+ import { resolveAgentAcquisitionRoute } from "./acquisition-routes.js";
6
7
  import { loadCapabilityDeclarations, verifyCapabilities } from "./capabilities.js";
7
8
  import { loadCapabilityCredentialMap } from "./credentials.js";
8
9
  import { loadBrokerEvidenceCache, loadProjectEvidenceReceipts, persistBrokerEvidence, storeBrokerEvidenceCache, } from "./evidence.js";
@@ -109,6 +110,7 @@ export async function startCapabilityBroker(root, projectId, capsuleProject) {
109
110
  workspaceContextTokens: config.budget.maxBrokerContextTokens,
110
111
  workspaceMaxItems: config.budget.maxBrokerItems,
111
112
  callBudget,
113
+ requireAcquisitionRoute: Boolean(project?.scientificDesign),
112
114
  });
113
115
  });
114
116
  await new Promise((resolvePromise, reject) => {
@@ -164,8 +166,16 @@ async function handleMcpRequest(input) {
164
166
  inputSchema: {
165
167
  type: "object",
166
168
  additionalProperties: false,
167
- required: ["capability_id", "url"],
169
+ required: [
170
+ ...(input.requireAcquisitionRoute ? ["acquisition_route_id"] : []),
171
+ "capability_id",
172
+ "url",
173
+ ],
168
174
  properties: {
175
+ acquisition_route_id: {
176
+ type: "string",
177
+ description: "Exact broker-capability route ID from the frozen scientific design. Required for scientific projects.",
178
+ },
169
179
  capability_id: { type: "string" },
170
180
  credential_id: {
171
181
  type: "string",
@@ -262,6 +272,7 @@ async function handleMcpRequest(input) {
262
272
  }
263
273
  async function fetchCandidateSource(input) {
264
274
  const capabilityId = input.arguments.capability_id;
275
+ const requestedAcquisitionRouteId = input.arguments.acquisition_route_id;
265
276
  const credentialId = input.arguments.credential_id;
266
277
  const rawUrl = input.arguments.url;
267
278
  const requestBody = input.arguments.request_body;
@@ -275,6 +286,10 @@ async function fetchCandidateSource(input) {
275
286
  if (credentialId !== undefined && typeof credentialId !== "string") {
276
287
  throw new Error("credential_id must be a string when provided");
277
288
  }
289
+ if (requestedAcquisitionRouteId !== undefined &&
290
+ typeof requestedAcquisitionRouteId !== "string") {
291
+ throw new Error("acquisition_route_id must be a string when provided");
292
+ }
278
293
  if (jsonPointer !== undefined &&
279
294
  (typeof jsonPointer !== "string" || !validJsonPointer(jsonPointer))) {
280
295
  throw new Error("json_pointer must be an RFC 6901 JSON Pointer when provided");
@@ -302,6 +317,26 @@ async function fetchCandidateSource(input) {
302
317
  if (!capability.http) {
303
318
  throw brokerDiagnosticError("CAPABILITY_NOT_DECLARED", "The requested capability has no locked broker HTTP policy.", false, "Replace the capability declaration with a reviewed brokered-network capability and rebuild the lock.", { capabilityId });
304
319
  }
320
+ const projectPath = join(workspacePaths(input.root).projects, input.projectId, "project.json");
321
+ const project = (await pathExists(projectPath))
322
+ ? await loadProject(input.root, input.projectId)
323
+ : null;
324
+ if (!project && requestedAcquisitionRouteId !== undefined) {
325
+ throw new CliError("A broker acquisition route requires an initialized research project.", {
326
+ code: "RESEARCH_EVIDENCE_ACQUISITION_ROUTE_INVALID",
327
+ exitCode: 3,
328
+ });
329
+ }
330
+ const acquisitionRoute = project
331
+ ? await resolveAgentAcquisitionRoute({
332
+ root: input.root,
333
+ project,
334
+ routeId: requestedAcquisitionRouteId,
335
+ routeClasses: ["broker-capability"],
336
+ capabilityId,
337
+ })
338
+ : null;
339
+ const acquisitionRouteId = acquisitionRoute?.id ?? null;
305
340
  let target;
306
341
  let encodedRequestBody;
307
342
  try {
@@ -349,6 +384,7 @@ async function fetchCandidateSource(input) {
349
384
  await appendJournalEvent(workspacePaths(input.root).journal, "capability.fetch.requested", input.projectId, {
350
385
  attemptId,
351
386
  projectId: input.projectId,
387
+ acquisitionRouteId,
352
388
  capabilityId,
353
389
  credentialId: effectiveCredentialId,
354
390
  targetSha256: sha256Text(target.toString()),
@@ -393,6 +429,7 @@ async function fetchCandidateSource(input) {
393
429
  attemptId,
394
430
  reusedAttemptId: projectReuse.attemptId,
395
431
  projectId: input.projectId,
432
+ acquisitionRouteId,
396
433
  capabilityId,
397
434
  credentialId: effectiveCredentialId,
398
435
  cacheKeySha256,
@@ -400,12 +437,13 @@ async function fetchCandidateSource(input) {
400
437
  contextItems: context.items,
401
438
  candidateCount: candidates.length,
402
439
  });
403
- await appendCompletedReceipt(input.root, input.projectId, receipt, cacheKeySha256, candidates.length, false, "project");
404
- return brokerToolResult(receipt, context.bytes, projectReuse.contentType, candidates, "project");
440
+ await appendCompletedReceipt(input.root, input.projectId, receipt, cacheKeySha256, candidates.length, false, "project", acquisitionRouteId);
441
+ return brokerToolResult(receipt, context.bytes, projectReuse.contentType, candidates, "project", acquisitionRouteId);
405
442
  }
406
443
  await appendJournalEvent(workspacePaths(input.root).journal, "capability.fetch.attempted", input.projectId, {
407
444
  attemptId,
408
445
  projectId: input.projectId,
446
+ acquisitionRouteId,
409
447
  capabilityId,
410
448
  credentialId: effectiveCredentialId,
411
449
  targetSha256: sha256Text(target.toString()),
@@ -448,8 +486,8 @@ async function fetchCandidateSource(input) {
448
486
  selectedJsonPointer: context.selectedJsonPointer,
449
487
  itemOffset: context.offset,
450
488
  });
451
- await appendCompletedReceipt(input.root, input.projectId, receipt, cacheKeySha256, candidates.length, false, "workspace");
452
- return brokerToolResult(receipt, context.bytes, cached.contentType, candidates, "workspace");
489
+ await appendCompletedReceipt(input.root, input.projectId, receipt, cacheKeySha256, candidates.length, false, "workspace", acquisitionRouteId);
490
+ return brokerToolResult(receipt, context.bytes, cached.contentType, candidates, "workspace", acquisitionRouteId);
453
491
  }
454
492
  }
455
493
  const headers = new Headers(capability.http.staticHeaders);
@@ -482,6 +520,8 @@ async function fetchCandidateSource(input) {
482
520
  rateLimitRetries += 1;
483
521
  await appendJournalEvent(workspacePaths(input.root).journal, "capability.fetch.retry.scheduled", input.projectId, {
484
522
  attemptId,
523
+ projectId: input.projectId,
524
+ acquisitionRouteId,
485
525
  capabilityId,
486
526
  credentialId: effectiveCredentialId,
487
527
  status: response.status,
@@ -571,8 +611,8 @@ async function fetchCandidateSource(input) {
571
611
  selectedJsonPointer: context.selectedJsonPointer,
572
612
  itemOffset: context.offset,
573
613
  });
574
- await appendCompletedReceipt(input.root, input.projectId, receipt, cacheKeySha256, candidates.length, true, null);
575
- return brokerToolResult(receipt, context.bytes, contentType, candidates, null);
614
+ await appendCompletedReceipt(input.root, input.projectId, receipt, cacheKeySha256, candidates.length, true, null, acquisitionRouteId);
615
+ return brokerToolResult(receipt, context.bytes, contentType, candidates, null, acquisitionRouteId);
576
616
  }
577
617
  catch (error) {
578
618
  const reportedError = structuredBrokerFailure(error, capabilityId, effectiveCredentialId);
@@ -581,6 +621,8 @@ async function fetchCandidateSource(input) {
581
621
  : {};
582
622
  await appendJournalEvent(workspacePaths(input.root).journal, "capability.fetch.failed", input.projectId, {
583
623
  attemptId,
624
+ projectId: input.projectId,
625
+ acquisitionRouteId,
584
626
  capabilityId,
585
627
  credentialId: effectiveCredentialId,
586
628
  error: bounded(sanitizeResearchText(reportedError.message, [...input.credentialMap.values()]), 500),
@@ -614,7 +656,7 @@ function structuredBrokerFailure(error, capabilityId, credentialId) {
614
656
  },
615
657
  });
616
658
  }
617
- function brokerToolResult(receipt, context, contentType, candidates, reuseScope) {
659
+ function brokerToolResult(receipt, context, contentType, candidates, reuseScope, acquisitionRouteId) {
618
660
  const inline = contentType.includes("json") || contentType.startsWith("text/");
619
661
  return {
620
662
  ...Object.fromEntries(Object.entries(receipt)),
@@ -623,6 +665,7 @@ function brokerToolResult(receipt, context, contentType, candidates, reuseScope)
623
665
  text: inline ? context.toString("utf8") : null,
624
666
  },
625
667
  candidates,
668
+ acquisitionRouteId,
626
669
  networkAttempted: reuseScope === null,
627
670
  reuseScope,
628
671
  };
@@ -731,10 +774,11 @@ async function stageContextObject(capsuleProject, locator, bytes) {
731
774
  }
732
775
  }
733
776
  }
734
- async function appendCompletedReceipt(root, projectId, receipt, cacheKeySha256, candidateCount, networkAttempted, reuseScope) {
777
+ async function appendCompletedReceipt(root, projectId, receipt, cacheKeySha256, candidateCount, networkAttempted, reuseScope, acquisitionRouteId) {
735
778
  await appendJournalEvent(workspacePaths(root).journal, "capability.fetch.completed", projectId, {
736
779
  attemptId: receipt.attemptId,
737
780
  projectId: receipt.projectId,
781
+ acquisitionRouteId,
738
782
  capabilityId: receipt.capabilityId,
739
783
  credentialId: receipt.credentialId,
740
784
  status: receipt.status,
@@ -1099,7 +1143,7 @@ function brokerDiagnosticError(code, message, networkAttempted, minimumAction, e
1099
1143
  }
1100
1144
  function brokerFailureKind(error) {
1101
1145
  if (error instanceof CliError && error.code === "PROVIDER_AUTHENTICATION_FAILED") {
1102
- return "deterministic";
1146
+ return "authentication";
1103
1147
  }
1104
1148
  if (error instanceof CliError && error.code === "RESEARCH_BROKER_HTTP_ERROR") {
1105
1149
  const status = isObject(error.details) ? error.details.status : undefined;