@tiangong-ai/cli 0.0.35 → 0.0.36

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 (32) hide show
  1. package/AGENTS.md +15 -5
  2. package/README.md +90 -8
  3. package/dist/research/orchestration.js +298 -28
  4. package/dist/research/orchestration.js.map +1 -1
  5. package/dist/research/workspace/audit-bundle.d.ts +44 -0
  6. package/dist/research/workspace/audit-bundle.js +357 -0
  7. package/dist/research/workspace/audit-bundle.js.map +1 -0
  8. package/dist/research/workspace/preflight.d.ts +34 -2
  9. package/dist/research/workspace/preflight.js +145 -1
  10. package/dist/research/workspace/preflight.js.map +1 -1
  11. package/dist/research/workspace/projects.d.ts +28 -4
  12. package/dist/research/workspace/projects.js +249 -12
  13. package/dist/research/workspace/projects.js.map +1 -1
  14. package/dist/research/workspace/publication-workflow.js +2 -0
  15. package/dist/research/workspace/publication-workflow.js.map +1 -1
  16. package/dist/research/workspace/runtime.js +4 -1
  17. package/dist/research/workspace/runtime.js.map +1 -1
  18. package/dist/research/workspace/sanitization.js +9 -3
  19. package/dist/research/workspace/sanitization.js.map +1 -1
  20. package/dist/research/workspace/scientific-design.d.ts +336 -0
  21. package/dist/research/workspace/scientific-design.js +1845 -0
  22. package/dist/research/workspace/scientific-design.js.map +1 -0
  23. package/dist/research/workspace/scientific-review.d.ts +101 -0
  24. package/dist/research/workspace/scientific-review.js +1167 -0
  25. package/dist/research/workspace/scientific-review.js.map +1 -0
  26. package/dist/research/workspace/setup-catalog.js +2 -2
  27. package/dist/research/workspace/setup.js +12 -3
  28. package/dist/research/workspace/setup.js.map +1 -1
  29. package/dist/research/workspace/types.d.ts +27 -0
  30. package/dist/research/workspace/workspace.js +25 -7
  31. package/dist/research/workspace/workspace.js.map +1 -1
  32. 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":"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"}
@@ -1,4 +1,5 @@
1
- import type { AgentPackageStage, AgentRoute, ProjectEvidenceRequirements, VerifiedProjectInputPlan, WorkspaceConfig } from "./types.js";
1
+ import { type VerifiedScientificDesign } from "./scientific-design.js";
2
+ import type { AgentPackageStage, AgentRoute, ProjectEvidenceRequirements, ResearchPolicyBinding, VerifiedProjectInputPlan, WorkspaceConfig } from "./types.js";
2
3
  export declare const RESEARCH_AGENT_PROTOCOL_OVERHEAD_TOKENS: Record<AgentRoute["agent"], number>;
3
4
  export declare const RESEARCH_ESTIMATED_BYTES_PER_TOKEN = 3;
4
5
  export declare const RESEARCH_MAX_REPAIR_SOURCE_BYTES = 32000;
@@ -14,12 +15,20 @@ export interface EvidenceCoverageGap {
14
15
  alternativeCanSatisfyMinimumCoverage: boolean;
15
16
  minimumAction: string;
16
17
  }
17
- export declare function evaluateProjectPreflight(root: string, question: string, requirements: ProjectEvidenceRequirements | null, inputPlan: VerifiedProjectInputPlan | null): Promise<{
18
+ export declare function evaluateProjectPreflight(root: string, question: string, requirements: ProjectEvidenceRequirements | null, inputPlan: VerifiedProjectInputPlan | null, options?: {
19
+ publicationPolicy?: ResearchPolicyBinding | null;
20
+ scientificDesign?: VerifiedScientificDesign | null;
21
+ }): Promise<{
18
22
  preflightSha256: string;
19
23
  schemaVersion: 1;
20
24
  mode: import("./types.js").ResearchMode;
21
25
  questionSha256: string;
22
26
  evidenceRequirements: ProjectEvidenceRequirements | null;
27
+ scientificDesign: {
28
+ sha256: string;
29
+ projectId: string;
30
+ evaluation: import("./scientific-design.js").ScientificDesignEvaluation | null;
31
+ } | null;
23
32
  capabilities: {
24
33
  id: string;
25
34
  allowedHosts: string[];
@@ -122,6 +131,29 @@ export declare function evaluateProjectPreflight(root: string, question: string,
122
131
  review: number;
123
132
  repair: number;
124
133
  };
134
+ lifecycleReservation: {
135
+ enabled: boolean;
136
+ reviewCounts: {
137
+ earlyScientific: number;
138
+ finalPublication: number;
139
+ revisions: number;
140
+ };
141
+ phaseTokens: {
142
+ baseResearch: number;
143
+ earlyScientificReviews: number;
144
+ finalPublicationReviews: number;
145
+ revision: number;
146
+ };
147
+ phaseWallSeconds: {
148
+ baseResearch: number;
149
+ earlyScientificReviews: number;
150
+ finalPublicationReviews: number;
151
+ revision: number;
152
+ };
153
+ totalTokens: number;
154
+ totalWallSeconds: number;
155
+ estimatedMaxCostUsd: number | null;
156
+ };
125
157
  };
126
158
  executionPolicy: {
127
159
  producer: {
@@ -1,6 +1,7 @@
1
1
  import { loadCapabilityDeclarations, verifyCapabilities } from "./capabilities.js";
2
2
  import { hasPublicInternetCapability } from "./external-skills.js";
3
3
  import { deriveDiscoveryPlan } from "./discovery-planning.js";
4
+ import { evaluateScientificDesign, scientificDesignPolicyGaps, } from "./scientific-design.js";
4
5
  import { schemaForStage } from "./schemas.js";
5
6
  import { canonicalJson, sha256Text } from "./storage.js";
6
7
  import { loadWorkspaceConfig, verifyDoctorAttestation } from "./workspace.js";
@@ -16,7 +17,7 @@ export const RESEARCH_CLAUDE_STRUCTURED_OUTPUT_MAX_TURNS = 3;
16
17
  export const RESEARCH_BROKER_MAX_TURNS = 6;
17
18
  export const RESEARCH_REPAIR_MAX_TURNS = 1;
18
19
  const RESEARCH_PREFLIGHT_PROMPT_ALLOWANCE_TOKENS = 3_000;
19
- export async function evaluateProjectPreflight(root, question, requirements, inputPlan) {
20
+ export async function evaluateProjectPreflight(root, question, requirements, inputPlan, options = {}) {
20
21
  const config = await loadWorkspaceConfig(root);
21
22
  const capabilities = await loadCapabilityDeclarations(root);
22
23
  const capabilityVerification = await verifyCapabilities(root);
@@ -47,8 +48,57 @@ export async function evaluateProjectPreflight(root, question, requirements, inp
47
48
  reservedAgentPackageCost(config.producer, packageTokens.synthesize, config) +
48
49
  reservedAgentPackageCost(config.reviewer, packageTokens.review, config))
49
50
  : null;
51
+ const lifecycleEnabled = Boolean(options.publicationPolicy);
52
+ const earlyScientificReviewCount = lifecycleEnabled ? 3 : 0;
53
+ const finalPublicationReviewCount = lifecycleEnabled ? 4 : 0;
54
+ const revisionCount = lifecycleEnabled ? 1 : 0;
55
+ const lifecycleTokenReservation = tokenReservation +
56
+ earlyScientificReviewCount * config.budget.earlyScientificReviewMaxTokens +
57
+ finalPublicationReviewCount * config.budget.finalPublicationReviewMaxTokens +
58
+ revisionCount * config.budget.revisionReserveTokens;
59
+ const lifecycleWallReservation = wallReservation +
60
+ earlyScientificReviewCount * config.budget.earlyScientificReviewMaxWallSeconds +
61
+ finalPublicationReviewCount * config.budget.finalPublicationReviewMaxWallSeconds +
62
+ revisionCount * config.budget.revisionReserveWallSeconds;
63
+ const lifecycleEstimatedMaxCostUsd = !lifecycleEnabled || estimatedMaxCostUsd === null
64
+ ? estimatedMaxCostUsd
65
+ : roundMoney(estimatedMaxCostUsd +
66
+ earlyScientificReviewCount *
67
+ reservedAgentPackageCost(config.reviewer, config.budget.earlyScientificReviewMaxTokens, config) +
68
+ finalPublicationReviewCount *
69
+ reservedAgentPackageCost(config.reviewer, config.budget.finalPublicationReviewMaxTokens, config) +
70
+ revisionCount *
71
+ Math.max(reservedAgentPackageCost(config.producer, config.budget.revisionReserveTokens, config), reservedAgentPackageCost(config.reviewer, config.budget.revisionReserveTokens, config)));
50
72
  const gaps = [];
51
73
  const coverageGaps = [];
74
+ const designEvaluation = options.scientificDesign
75
+ ? evaluateScientificDesign(options.scientificDesign.contract)
76
+ : null;
77
+ if (options.publicationPolicy && !options.scientificDesign) {
78
+ gaps.push("scientific-design-missing");
79
+ }
80
+ if (options.scientificDesign && !options.publicationPolicy) {
81
+ gaps.push("scientific-design-policy-missing");
82
+ }
83
+ if (options.publicationPolicy &&
84
+ options.scientificDesign &&
85
+ options.publicationPolicy.projectId !== options.scientificDesign.contract.projectId) {
86
+ gaps.push("scientific-design-policy-project-mismatch");
87
+ }
88
+ if (options.publicationPolicy?.targetJournal &&
89
+ options.scientificDesign &&
90
+ options.publicationPolicy.targetJournal.trim().toLocaleLowerCase("en-US") !==
91
+ options.scientificDesign.contract.identity.targetJournals.primary
92
+ .trim()
93
+ .toLocaleLowerCase("en-US")) {
94
+ gaps.push("scientific-design-policy-journal-mismatch");
95
+ }
96
+ if (designEvaluation) {
97
+ gaps.push(...designEvaluation.issueCodes.map((code) => `scientific-design:${code}`));
98
+ }
99
+ if (options.publicationPolicy && options.scientificDesign) {
100
+ appendScientificDesignContractGaps(gaps, options.scientificDesign.contract, options.publicationPolicy, requirements);
101
+ }
52
102
  if (config.mode === "production-research" && !requirements) {
53
103
  gaps.push("explicit-evidence-requirements-missing");
54
104
  }
@@ -94,6 +144,17 @@ export async function evaluateProjectPreflight(root, question, requirements, inp
94
144
  if (estimatedMaxCostUsd !== null && estimatedMaxCostUsd > config.budget.maxCostUsd) {
95
145
  gaps.push(`package-cost-reservations-exceed-total:${estimatedMaxCostUsd}/${config.budget.maxCostUsd}`);
96
146
  }
147
+ if (lifecycleEnabled && lifecycleTokenReservation > config.budget.maxTokens) {
148
+ gaps.push(`full-lifecycle-token-reservation-exceeds-total:${lifecycleTokenReservation}/${config.budget.maxTokens}`);
149
+ }
150
+ if (lifecycleEnabled && lifecycleWallReservation > config.budget.maxWallSeconds) {
151
+ gaps.push(`full-lifecycle-wall-reservation-exceeds-total:${lifecycleWallReservation}/${config.budget.maxWallSeconds}`);
152
+ }
153
+ if (lifecycleEnabled &&
154
+ lifecycleEstimatedMaxCostUsd !== null &&
155
+ lifecycleEstimatedMaxCostUsd > config.budget.maxCostUsd) {
156
+ gaps.push(`full-lifecycle-cost-reservation-exceeds-total:${lifecycleEstimatedMaxCostUsd}/${config.budget.maxCostUsd}`);
157
+ }
97
158
  const discoverOutputTokens = discoveryPlan?.recommendedOutputTokens ?? config.budget.maxOutputTokens;
98
159
  const stageOutputReservations = {
99
160
  discover: discoverOutputTokens,
@@ -169,6 +230,13 @@ export async function evaluateProjectPreflight(root, question, requirements, inp
169
230
  mode: config.mode,
170
231
  questionSha256: sha256Text(question),
171
232
  evidenceRequirements: requirements,
233
+ scientificDesign: options.scientificDesign === null || options.scientificDesign === undefined
234
+ ? null
235
+ : {
236
+ sha256: options.scientificDesign.sha256,
237
+ projectId: options.scientificDesign.contract.projectId,
238
+ evaluation: designEvaluation,
239
+ },
172
240
  capabilities: networkCapabilities,
173
241
  inputPlan: inputPlan === null
174
242
  ? null
@@ -228,6 +296,29 @@ export async function evaluateProjectPreflight(root, question, requirements, inp
228
296
  },
229
297
  preCallTokenReservations,
230
298
  maxTurns,
299
+ lifecycleReservation: {
300
+ enabled: lifecycleEnabled,
301
+ reviewCounts: {
302
+ earlyScientific: earlyScientificReviewCount,
303
+ finalPublication: finalPublicationReviewCount,
304
+ revisions: revisionCount,
305
+ },
306
+ phaseTokens: {
307
+ baseResearch: tokenReservation,
308
+ earlyScientificReviews: earlyScientificReviewCount * config.budget.earlyScientificReviewMaxTokens,
309
+ finalPublicationReviews: finalPublicationReviewCount * config.budget.finalPublicationReviewMaxTokens,
310
+ revision: revisionCount * config.budget.revisionReserveTokens,
311
+ },
312
+ phaseWallSeconds: {
313
+ baseResearch: wallReservation,
314
+ earlyScientificReviews: earlyScientificReviewCount * config.budget.earlyScientificReviewMaxWallSeconds,
315
+ finalPublicationReviews: finalPublicationReviewCount * config.budget.finalPublicationReviewMaxWallSeconds,
316
+ revision: revisionCount * config.budget.revisionReserveWallSeconds,
317
+ },
318
+ totalTokens: lifecycleTokenReservation,
319
+ totalWallSeconds: lifecycleWallReservation,
320
+ estimatedMaxCostUsd: lifecycleEstimatedMaxCostUsd,
321
+ },
231
322
  },
232
323
  executionPolicy: {
233
324
  producer: {
@@ -374,6 +465,59 @@ function appendEvidencePlanGaps(gaps, coverageGaps, requirements, inputPlan, net
374
465
  gaps.push(`evidence-plan-dated-sources-insufficient:${plannedDatedCount}/${requirements.minDatedSources}`);
375
466
  }
376
467
  }
468
+ function appendScientificDesignContractGaps(gaps, design, policy, requirements) {
469
+ const prefix = "scientific-design-contract:";
470
+ gaps.push(...scientificDesignPolicyGaps(design, policy).map((gap) => `${prefix}${gap}`));
471
+ if (policy.targetJournal) {
472
+ if (design.identity.targetJournals.approvalStatus !== "policy-approved") {
473
+ gaps.push(`${prefix}policy-journal-unapproved`);
474
+ }
475
+ }
476
+ else if (design.identity.targetJournals.approvalStatus !== "candidate-only") {
477
+ gaps.push(`${prefix}policy-journal-approval-unbound`);
478
+ }
479
+ const requiredRoles = design.evidenceRoles.filter((role) => role.required);
480
+ if (requirements) {
481
+ const mappedDimensions = new Set(requiredRoles.flatMap((role) => role.coverageDimensionIds));
482
+ const mappedSourceTypes = new Set(requiredRoles.flatMap((role) => role.sourceTypeRequirements));
483
+ for (const dimension of requirements.dimensions) {
484
+ if (!mappedDimensions.has(dimension)) {
485
+ gaps.push(`${prefix}evidence-dimension-uncovered:${dimension}`);
486
+ }
487
+ }
488
+ for (const sourceType of requirements.sourceTypes) {
489
+ if (!mappedSourceTypes.has(sourceType)) {
490
+ gaps.push(`${prefix}evidence-source-type-uncovered:${sourceType}`);
491
+ }
492
+ }
493
+ const independentFloor = requiredRoles.reduce((sum, role) => sum + role.minimumIndependentSources, 0);
494
+ const fullTextFloor = requiredRoles.reduce((sum, role) => sum + role.minimumFullText, 0);
495
+ const datedFloor = requiredRoles.reduce((sum, role) => sum + role.minimumDatedSources, 0);
496
+ if (independentFloor < requirements.minSources) {
497
+ gaps.push(`${prefix}evidence-source-floor-insufficient:${independentFloor}/${requirements.minSources}`);
498
+ }
499
+ if (fullTextFloor < requirements.minFullTextSources) {
500
+ gaps.push(`${prefix}evidence-fulltext-floor-insufficient:${fullTextFloor}/${requirements.minFullTextSources}`);
501
+ }
502
+ if (datedFloor < requirements.minDatedSources) {
503
+ gaps.push(`${prefix}evidence-dated-floor-insufficient:${datedFloor}/${requirements.minDatedSources}`);
504
+ }
505
+ }
506
+ if (policy.resolvedRules.includes("independent-validation-required")) {
507
+ const centralClaimIds = new Set(design.claims.filter((claim) => claim.role === "central").map((claim) => claim.id));
508
+ const centralPlans = design.validationPlans.filter((plan) => plan.claimIds.some((claimId) => centralClaimIds.has(claimId)));
509
+ for (const plan of centralPlans) {
510
+ if (!["available", "unavailable-scope-bounded"].includes(plan.independentValidation.status)) {
511
+ gaps.push(`${prefix}independent-validation-undispositioned:${plan.id}`);
512
+ }
513
+ }
514
+ for (const claimId of centralClaimIds) {
515
+ if (!centralPlans.some((plan) => plan.claimIds.includes(claimId))) {
516
+ gaps.push(`${prefix}independent-validation-unplanned:${claimId}`);
517
+ }
518
+ }
519
+ }
520
+ }
377
521
  function capabilityMinimumAction(capabilityId) {
378
522
  if (capabilityId === "database.tiangong.report-search") {
379
523
  return "Rerun the setup Wizard, select tiangong.kb-report-search, review its license and exact endpoint, securely configure tiangong.report.api-key, apply the replacement immutable plan, and pass capability live doctor.";