@tiangong-ai/cli 0.0.50 → 0.0.55

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 (218) hide show
  1. package/AGENTS.md +22 -2
  2. package/README.md +200 -7
  3. package/dist/cli.js +10 -1
  4. package/dist/cli.js.map +1 -1
  5. package/dist/data/builtins.d.ts +1 -0
  6. package/dist/data/builtins.js +40 -0
  7. package/dist/data/builtins.js.map +1 -0
  8. package/dist/data/catalog.d.ts +25 -0
  9. package/dist/data/catalog.js +305 -0
  10. package/dist/data/catalog.js.map +1 -0
  11. package/dist/data/commands.d.ts +9 -0
  12. package/dist/data/commands.js +307 -0
  13. package/dist/data/commands.js.map +1 -0
  14. package/dist/data/connectors/airnow-hourly-observations.d.ts +2 -0
  15. package/dist/data/connectors/airnow-hourly-observations.js +522 -0
  16. package/dist/data/connectors/airnow-hourly-observations.js.map +1 -0
  17. package/dist/data/connectors/airnow-hourly-observations.schemas.d.ts +299 -0
  18. package/dist/data/connectors/airnow-hourly-observations.schemas.js +188 -0
  19. package/dist/data/connectors/airnow-hourly-observations.schemas.js.map +1 -0
  20. package/dist/data/connectors/bluesky-public-posts.d.ts +2 -0
  21. package/dist/data/connectors/bluesky-public-posts.js +705 -0
  22. package/dist/data/connectors/bluesky-public-posts.js.map +1 -0
  23. package/dist/data/connectors/bluesky-public-posts.schemas.d.ts +733 -0
  24. package/dist/data/connectors/bluesky-public-posts.schemas.js +422 -0
  25. package/dist/data/connectors/bluesky-public-posts.schemas.js.map +1 -0
  26. package/dist/data/connectors/epa-eis-records.d.ts +2 -0
  27. package/dist/data/connectors/epa-eis-records.js +566 -0
  28. package/dist/data/connectors/epa-eis-records.js.map +1 -0
  29. package/dist/data/connectors/epa-eis-records.schemas.d.ts +199 -0
  30. package/dist/data/connectors/epa-eis-records.schemas.js +146 -0
  31. package/dist/data/connectors/epa-eis-records.schemas.js.map +1 -0
  32. package/dist/data/connectors/federal-register-documents.d.ts +2 -0
  33. package/dist/data/connectors/federal-register-documents.js +517 -0
  34. package/dist/data/connectors/federal-register-documents.js.map +1 -0
  35. package/dist/data/connectors/federal-register-documents.schemas.d.ts +357 -0
  36. package/dist/data/connectors/federal-register-documents.schemas.js +243 -0
  37. package/dist/data/connectors/federal-register-documents.schemas.js.map +1 -0
  38. package/dist/data/connectors/gdelt-doc-search.d.ts +2 -0
  39. package/dist/data/connectors/gdelt-doc-search.js +658 -0
  40. package/dist/data/connectors/gdelt-doc-search.js.map +1 -0
  41. package/dist/data/connectors/gdelt-doc-search.schemas.d.ts +446 -0
  42. package/dist/data/connectors/gdelt-doc-search.schemas.js +330 -0
  43. package/dist/data/connectors/gdelt-doc-search.schemas.js.map +1 -0
  44. package/dist/data/connectors/gdelt-file-feeds.d.ts +4 -0
  45. package/dist/data/connectors/gdelt-file-feeds.js +591 -0
  46. package/dist/data/connectors/gdelt-file-feeds.js.map +1 -0
  47. package/dist/data/connectors/gdelt-file-feeds.schemas.d.ts +40 -0
  48. package/dist/data/connectors/gdelt-file-feeds.schemas.js +256 -0
  49. package/dist/data/connectors/gdelt-file-feeds.schemas.js.map +1 -0
  50. package/dist/data/connectors/nasa-firms-fire.d.ts +2 -0
  51. package/dist/data/connectors/nasa-firms-fire.js +578 -0
  52. package/dist/data/connectors/nasa-firms-fire.js.map +1 -0
  53. package/dist/data/connectors/nasa-firms-fire.schemas.d.ts +369 -0
  54. package/dist/data/connectors/nasa-firms-fire.schemas.js +238 -0
  55. package/dist/data/connectors/nasa-firms-fire.schemas.js.map +1 -0
  56. package/dist/data/connectors/open-meteo-air-quality.d.ts +2 -0
  57. package/dist/data/connectors/open-meteo-air-quality.js +401 -0
  58. package/dist/data/connectors/open-meteo-air-quality.js.map +1 -0
  59. package/dist/data/connectors/open-meteo-air-quality.schemas.d.ts +335 -0
  60. package/dist/data/connectors/open-meteo-air-quality.schemas.js +225 -0
  61. package/dist/data/connectors/open-meteo-air-quality.schemas.js.map +1 -0
  62. package/dist/data/connectors/open-meteo-flood.d.ts +2 -0
  63. package/dist/data/connectors/open-meteo-flood.js +446 -0
  64. package/dist/data/connectors/open-meteo-flood.js.map +1 -0
  65. package/dist/data/connectors/open-meteo-flood.schemas.d.ts +388 -0
  66. package/dist/data/connectors/open-meteo-flood.schemas.js +227 -0
  67. package/dist/data/connectors/open-meteo-flood.schemas.js.map +1 -0
  68. package/dist/data/connectors/open-meteo-historical-weather.d.ts +2 -0
  69. package/dist/data/connectors/open-meteo-historical-weather.js +468 -0
  70. package/dist/data/connectors/open-meteo-historical-weather.js.map +1 -0
  71. package/dist/data/connectors/open-meteo-historical-weather.schemas.d.ts +420 -0
  72. package/dist/data/connectors/open-meteo-historical-weather.schemas.js +282 -0
  73. package/dist/data/connectors/open-meteo-historical-weather.schemas.js.map +1 -0
  74. package/dist/data/connectors/openaq-air-quality.d.ts +2 -0
  75. package/dist/data/connectors/openaq-air-quality.js +734 -0
  76. package/dist/data/connectors/openaq-air-quality.js.map +1 -0
  77. package/dist/data/connectors/openaq-air-quality.schemas.d.ts +1067 -0
  78. package/dist/data/connectors/openaq-air-quality.schemas.js +512 -0
  79. package/dist/data/connectors/openaq-air-quality.schemas.js.map +1 -0
  80. package/dist/data/connectors/regulations-gov-attachments.d.ts +2 -0
  81. package/dist/data/connectors/regulations-gov-attachments.js +486 -0
  82. package/dist/data/connectors/regulations-gov-attachments.js.map +1 -0
  83. package/dist/data/connectors/regulations-gov-attachments.schemas.d.ts +270 -0
  84. package/dist/data/connectors/regulations-gov-attachments.schemas.js +181 -0
  85. package/dist/data/connectors/regulations-gov-attachments.schemas.js.map +1 -0
  86. package/dist/data/connectors/regulations-gov-comments.d.ts +2 -0
  87. package/dist/data/connectors/regulations-gov-comments.js +718 -0
  88. package/dist/data/connectors/regulations-gov-comments.js.map +1 -0
  89. package/dist/data/connectors/regulations-gov-comments.schemas.d.ts +717 -0
  90. package/dist/data/connectors/regulations-gov-comments.schemas.js +389 -0
  91. package/dist/data/connectors/regulations-gov-comments.schemas.js.map +1 -0
  92. package/dist/data/connectors/usbr-project-records.d.ts +2 -0
  93. package/dist/data/connectors/usbr-project-records.js +467 -0
  94. package/dist/data/connectors/usbr-project-records.js.map +1 -0
  95. package/dist/data/connectors/usbr-project-records.schemas.d.ts +194 -0
  96. package/dist/data/connectors/usbr-project-records.schemas.js +137 -0
  97. package/dist/data/connectors/usbr-project-records.schemas.js.map +1 -0
  98. package/dist/data/connectors/usbr-rise.d.ts +2 -0
  99. package/dist/data/connectors/usbr-rise.js +625 -0
  100. package/dist/data/connectors/usbr-rise.js.map +1 -0
  101. package/dist/data/connectors/usbr-rise.schemas.d.ts +623 -0
  102. package/dist/data/connectors/usbr-rise.schemas.js +407 -0
  103. package/dist/data/connectors/usbr-rise.schemas.js.map +1 -0
  104. package/dist/data/connectors/usgs-water-instantaneous-values.d.ts +2 -0
  105. package/dist/data/connectors/usgs-water-instantaneous-values.js +521 -0
  106. package/dist/data/connectors/usgs-water-instantaneous-values.js.map +1 -0
  107. package/dist/data/connectors/usgs-water-instantaneous-values.schemas.d.ts +496 -0
  108. package/dist/data/connectors/usgs-water-instantaneous-values.schemas.js +309 -0
  109. package/dist/data/connectors/usgs-water-instantaneous-values.schemas.js.map +1 -0
  110. package/dist/data/connectors/youtube-public-content.d.ts +2 -0
  111. package/dist/data/connectors/youtube-public-content.js +974 -0
  112. package/dist/data/connectors/youtube-public-content.js.map +1 -0
  113. package/dist/data/connectors/youtube-public-content.schemas.d.ts +773 -0
  114. package/dist/data/connectors/youtube-public-content.schemas.js +567 -0
  115. package/dist/data/connectors/youtube-public-content.schemas.js.map +1 -0
  116. package/dist/data/contracts.d.ts +374 -0
  117. package/dist/data/contracts.js +10 -0
  118. package/dist/data/contracts.js.map +1 -0
  119. package/dist/data/runtime/artifacts.d.ts +6 -0
  120. package/dist/data/runtime/artifacts.js +103 -0
  121. package/dist/data/runtime/artifacts.js.map +1 -0
  122. package/dist/data/runtime/bounded-http.d.ts +10 -0
  123. package/dist/data/runtime/bounded-http.js +403 -0
  124. package/dist/data/runtime/bounded-http.js.map +1 -0
  125. package/dist/data/runtime/canonical-json.d.ts +3 -0
  126. package/dist/data/runtime/canonical-json.js +59 -0
  127. package/dist/data/runtime/canonical-json.js.map +1 -0
  128. package/dist/data/runtime/credentials.d.ts +14 -0
  129. package/dist/data/runtime/credentials.js +67 -0
  130. package/dist/data/runtime/credentials.js.map +1 -0
  131. package/dist/data/runtime/csv.d.ts +4 -0
  132. package/dist/data/runtime/csv.js +51 -0
  133. package/dist/data/runtime/csv.js.map +1 -0
  134. package/dist/data/runtime/errors.d.ts +22 -0
  135. package/dist/data/runtime/errors.js +101 -0
  136. package/dist/data/runtime/errors.js.map +1 -0
  137. package/dist/data/runtime/execute.d.ts +11 -0
  138. package/dist/data/runtime/execute.js +358 -0
  139. package/dist/data/runtime/execute.js.map +1 -0
  140. package/dist/data/runtime/receipts.d.ts +13 -0
  141. package/dist/data/runtime/receipts.js +38 -0
  142. package/dist/data/runtime/receipts.js.map +1 -0
  143. package/dist/data/schemas/catalog.v1.json +73 -0
  144. package/dist/data/schemas/core-receipt.v1.json +117 -0
  145. package/dist/data/schemas/describe.v1.json +24 -0
  146. package/dist/data/schemas/discovery.v1.json +130 -0
  147. package/dist/data/schemas/doctor.v1.json +40 -0
  148. package/dist/data/schemas/error.v1.json +48 -0
  149. package/dist/data/schemas/manifest.v1.json +174 -0
  150. package/dist/data/schemas/run-request.v1.json +37 -0
  151. package/dist/data/schemas/run-result.v1.json +77 -0
  152. package/dist/data/schemas.d.ts +27 -0
  153. package/dist/data/schemas.js +69 -0
  154. package/dist/data/schemas.js.map +1 -0
  155. package/dist/env.js.map +1 -1
  156. package/dist/errors.js.map +1 -1
  157. package/dist/http.js.map +1 -1
  158. package/dist/kb/config.js.map +1 -1
  159. package/dist/kb/pipeline-health.js.map +1 -1
  160. package/dist/research/orchestration.js +71 -11
  161. package/dist/research/orchestration.js.map +1 -1
  162. package/dist/research/workspace/acquisition.js +70 -5
  163. package/dist/research/workspace/acquisition.js.map +1 -1
  164. package/dist/research/workspace/audit-bundle.js +7 -2
  165. package/dist/research/workspace/audit-bundle.js.map +1 -1
  166. package/dist/research/workspace/broker.js.map +1 -1
  167. package/dist/research/workspace/constants.js.map +1 -1
  168. package/dist/research/workspace/credentials.d.ts +3 -0
  169. package/dist/research/workspace/credentials.js +20 -3
  170. package/dist/research/workspace/credentials.js.map +1 -1
  171. package/dist/research/workspace/data-evidence-adapter.d.ts +60 -0
  172. package/dist/research/workspace/data-evidence-adapter.js +314 -0
  173. package/dist/research/workspace/data-evidence-adapter.js.map +1 -0
  174. package/dist/research/workspace/discovery-status.js +10 -7
  175. package/dist/research/workspace/discovery-status.js.map +1 -1
  176. package/dist/research/workspace/discovery.js +12 -11
  177. package/dist/research/workspace/discovery.js.map +1 -1
  178. package/dist/research/workspace/evidence-ledger.d.ts +8 -1
  179. package/dist/research/workspace/evidence-ledger.js +46 -4
  180. package/dist/research/workspace/evidence-ledger.js.map +1 -1
  181. package/dist/research/workspace/evidence.d.ts +31 -0
  182. package/dist/research/workspace/evidence.js +77 -0
  183. package/dist/research/workspace/evidence.js.map +1 -1
  184. package/dist/research/workspace/executor.js.map +1 -1
  185. package/dist/research/workspace/external-skills.d.ts +49 -49
  186. package/dist/research/workspace/external-skills.js.map +1 -1
  187. package/dist/research/workspace/platform-capabilities.js.map +1 -1
  188. package/dist/research/workspace/preflight.d.ts +4 -4
  189. package/dist/research/workspace/preflight.js +33 -8
  190. package/dist/research/workspace/preflight.js.map +1 -1
  191. package/dist/research/workspace/projects.js +203 -76
  192. package/dist/research/workspace/projects.js.map +1 -1
  193. package/dist/research/workspace/publication.js.map +1 -1
  194. package/dist/research/workspace/research-policy-wizard.js.map +1 -1
  195. package/dist/research/workspace/research-policy.js.map +1 -1
  196. package/dist/research/workspace/runtime.d.ts +7 -0
  197. package/dist/research/workspace/runtime.js +82 -23
  198. package/dist/research/workspace/runtime.js.map +1 -1
  199. package/dist/research/workspace/sanitization.js.map +1 -1
  200. package/dist/research/workspace/schemas.js +1 -1
  201. package/dist/research/workspace/schemas.js.map +1 -1
  202. package/dist/research/workspace/scientific-design.js.map +1 -1
  203. package/dist/research/workspace/scientific-review.js.map +1 -1
  204. package/dist/research/workspace/setup-catalog.d.ts +9 -9
  205. package/dist/research/workspace/setup-catalog.js +2 -2
  206. package/dist/research/workspace/setup-catalog.js.map +1 -1
  207. package/dist/research/workspace/setup-declarative.js.map +1 -1
  208. package/dist/research/workspace/setup-instructions.d.ts +42 -0
  209. package/dist/research/workspace/setup-instructions.js +413 -0
  210. package/dist/research/workspace/setup-instructions.js.map +1 -0
  211. package/dist/research/workspace/setup-invocation.js.map +1 -1
  212. package/dist/research/workspace/setup-wizard.js +7 -0
  213. package/dist/research/workspace/setup-wizard.js.map +1 -1
  214. package/dist/research/workspace/setup.d.ts +18 -15
  215. package/dist/research/workspace/setup.js +68 -3
  216. package/dist/research/workspace/setup.js.map +1 -1
  217. package/dist/research/workspace/workspace.js.map +1 -1
  218. package/package.json +3 -3
@@ -2,10 +2,12 @@ import { randomUUID } from "node:crypto";
2
2
  import { cp, lstat, readFile, rm } from "node:fs/promises";
3
3
  import { basename, dirname, isAbsolute, join, relative, resolve } from "node:path";
4
4
  import { CliError } from "../../errors.js";
5
+ import { dataPublicSchemas } from "../../data/schemas.js";
5
6
  import { loadCapabilityDeclarations, stageLockedCapabilities, verifyCapabilities, } from "./capabilities.js";
6
7
  import { startCapabilityBroker } from "./broker.js";
7
8
  import { commitAcquisitionAssessments, freezeEvidenceSnapshot, loadCurrentEvidenceSnapshot, loadInferenceReadyEvidenceSnapshot, loadImmutableEvidenceSnapshotChain, materializeAcquisitionAudit, parseMaterializedAcquisitionAudit, } from "./acquisition.js";
8
9
  import { stageEvidenceArtifacts } from "./artifacts.js";
10
+ import { projectResearchDataCapabilities, } from "./data-evidence-adapter.js";
9
11
  import { commitDiscoveryDecisions, materializeDiscoveryEvidence } from "./discovery.js";
10
12
  import { inspectDiscoveryProgress } from "./discovery-status.js";
11
13
  import { downloadBindingRecordSchema } from "./downloads.js";
@@ -392,12 +394,24 @@ export async function prepareNativeResearchStage(input) {
392
394
  const stageContextContent = await stageContextForPackage(capsule.projectRoot, project, workPackage, config);
393
395
  const declarations = await loadCapabilityDeclarations(input.root);
394
396
  const hasBrokeredEvidence = declarations.capabilities.some((capability) => capability.permissions.includes("brokered-network"));
397
+ const dataCapabilities = projectResearchDataCapabilities();
398
+ const hasDataEvidence = dataCapabilities.capabilities.length > 0;
395
399
  const basePrompt = packagePrompt(project, workPackage, capsule.inputManifest, capsule.stagedSkills, capsule.capabilityDocumentation, null, capsule.contextBundle, capsule.contextBundleContent, stageContextContent, discovery, await listEvidenceCandidates(input.root, project.id));
396
400
  const prompt = [
397
401
  "Perform this producer stage in the current interactive host session. Do not launch codex exec, claude -p, or any other nested reasoning agent.",
398
402
  capsule.publicationPolicyDocumentation,
399
- input.stage === "discover" && hasBrokeredEvidence
400
- ? "Use native Web/Browser broadly for discovery when useful, but record every native search/navigation with recordActivity and register its candidates. Before admitting any native lead, formalize the same URL or DOI through fetchEvidence so it receives an immutable broker receipt. Assess candidates in bounded batches with recordAssessment as they arrive; the final output is only a small coverage closeout. Native results without broker/input provenance are discovery leads, never evidence."
403
+ input.stage === "discover" && (hasBrokeredEvidence || hasDataEvidence)
404
+ ? [
405
+ hasBrokeredEvidence
406
+ ? "Use native Web/Browser broadly for discovery when useful, but record every native search/navigation with recordActivity and register its candidates. Before admitting any native lead, formalize the same URL or DOI through fetchEvidence so it receives an immutable broker receipt."
407
+ : null,
408
+ hasDataEvidence
409
+ ? "Use the dynamically projected structured data capabilities when their source coverage and operation semantics fit the question. Inspect a selected capability with the supplied describe command, then call runDataCapability with the exact published DataRunRequest. The Research adapter invokes the same TypeScript runtime in-process and returns an immutable data receipt plus candidate ID; do not invoke standalone data run for project evidence."
410
+ : null,
411
+ "Assess candidates in bounded batches with recordAssessment as they arrive; the final output is only a small coverage closeout. Native results without broker/data/input provenance are discovery leads, never evidence.",
412
+ ]
413
+ .filter((value) => value !== null)
414
+ .join(" ")
401
415
  : input.stage === "acquire"
402
416
  ? "Acquire the provisionally admitted sources with the installed external acquisition/document Skills or an explicitly selected user-authorized browser. Capture the exact browser/adapter Download object, save it to the planned unique staging path, and call bindDownload before registerArtifact. Record browser/download/file-inspection activity with recordActivity. Failed or cancelled downloads cannot create bindings or artifacts. Never scan a download directory or infer success from file existence."
403
417
  : "Do not acquire additional evidence in this stage.",
@@ -418,7 +432,7 @@ export async function prepareNativeResearchStage(input) {
418
432
  preparedAt,
419
433
  bindingSha256,
420
434
  prompt,
421
- outputSchema: schemaForStage(input.stage, null, input.stage === "discover" && !hasBrokeredEvidence
435
+ outputSchema: schemaForStage(input.stage, null, input.stage === "discover" && !hasBrokeredEvidence && !hasDataEvidence
422
436
  ? { inputOnlyProvenanceIds: capsule.inputManifest.map((record) => record.id) }
423
437
  : {}),
424
438
  publicationPolicy: capsule.publicationPolicy,
@@ -499,6 +513,27 @@ export async function prepareNativeResearchStage(input) {
499
513
  requestSchema: nativeEvidenceRequestSchema(Boolean(project.scientificDesign)),
500
514
  }
501
515
  : null,
516
+ runDataCapability: input.stage === "discover" && hasDataEvidence
517
+ ? {
518
+ argv: [
519
+ "tiangong-ai",
520
+ "research",
521
+ "project",
522
+ "evidence",
523
+ "data",
524
+ "run",
525
+ project.id,
526
+ "--request",
527
+ "<absolute-data-run-request.json>",
528
+ "--workspace",
529
+ input.root,
530
+ "--json",
531
+ ],
532
+ describeArgv: ["tiangong-ai", "data", "describe", "<capability-id>", "--json"],
533
+ requestSchema: structuredClone(dataPublicSchemas.runRequest),
534
+ catalog: dataCapabilities,
535
+ }
536
+ : null,
502
537
  registerArtifact: input.stage === "acquire"
503
538
  ? {
504
539
  argv: [
@@ -651,10 +686,10 @@ export async function prepareNativeResearchStage(input) {
651
686
  },
652
687
  rules: [
653
688
  "Current native host performs producer reasoning; the CLI does not spawn a producer.",
654
- "Native Web/Browser activity is visible in the evidence ledger but becomes admissible only after broker/input formalization and strict assessment.",
689
+ "Native Web/Browser activity is visible in the evidence ledger but becomes admissible only after broker/data/input formalization and strict assessment.",
655
690
  "An interactive challenge pauses immediately. A material evidence-exhausted handoff is valid only after inspectAccess proves every required plan-bound agent route with exact terminal event hashes.",
656
691
  "When the next material step requires user authorization or an external response, request a durable handoff and stop; do not keep searching low-yield substitutes.",
657
- "Only broker receipts or registered immutable inputs may support discover output.",
692
+ "Only broker receipts, data-runtime receipts, or registered immutable inputs may support discover output.",
658
693
  "Only exact, structurally validated, content-addressed artifacts may support full-text acquisition claims.",
659
694
  "Do not place credentials, cookies, authorization data, or sensitive URL parameters in request/output files.",
660
695
  "A file's existence is not success; submit performs schema, provenance, budget, hash, and atomic-commit checks.",
@@ -1588,9 +1623,11 @@ async function createCapsule(root, project, workPackage, runId, config) {
1588
1623
  const evidenceArtifacts = frozenSnapshot
1589
1624
  ? await stageEvidenceArtifacts(root, project.id, capsuleProject, new Set(frozenSnapshot.artifacts.map((artifact) => artifact.artifactId)))
1590
1625
  : [];
1626
+ const inputSha256s = new Set(project.inputs.map((input) => input.sha256));
1627
+ const contextualEvidenceArtifacts = evidenceArtifacts.filter((artifact) => !inputSha256s.has(artifact.sha256));
1591
1628
  if ((workPackage.stage === "analyze" || workPackage.stage === "synthesize") &&
1592
- evidenceArtifacts.length) {
1593
- await writeProducerArtifactContext(capsuleProject, evidenceArtifacts, Math.floor((config.budget.maxInputContextTokens * RESEARCH_ESTIMATED_BYTES_PER_TOKEN) / 2));
1629
+ contextualEvidenceArtifacts.length) {
1630
+ await writeProducerArtifactContext(capsuleProject, contextualEvidenceArtifacts, Math.floor((config.budget.maxInputContextTokens * RESEARCH_ESTIMATED_BYTES_PER_TOKEN) / 2));
1594
1631
  }
1595
1632
  await writeJsonAtomic(join(capsuleProject, "inputs", "evidence-receipts.json"), evidenceReceipts.map(reviewSafeReceipt));
1596
1633
  await writeJsonAtomic(join(capsuleProject, "project.json"), {
@@ -1614,7 +1651,7 @@ async function createCapsule(root, project, workPackage, runId, config) {
1614
1651
  const stagedSkills = await stageLockedCapabilities(root, join(capsuleProject, "skills"));
1615
1652
  const capabilityDocumentation = await buildCapabilityDocumentation(capsuleProject, stagedSkills, config.budget.maxInputContextTokens * RESEARCH_ESTIMATED_BYTES_PER_TOKEN);
1616
1653
  const reviewEvidenceContext = workPackage.stage === "review"
1617
- ? await writeReviewEvidenceContext(root, project.id, capsuleProject, contextBundleContent, evidenceReceipts, evidenceArtifacts, config.budget.maxInputContextTokens * RESEARCH_ESTIMATED_BYTES_PER_TOKEN)
1654
+ ? await writeReviewEvidenceContext(root, project.id, capsuleProject, contextBundleContent, evidenceReceipts, contextualEvidenceArtifacts, config.budget.maxInputContextTokens * RESEARCH_ESTIMATED_BYTES_PER_TOKEN)
1618
1655
  : null;
1619
1656
  const reviewPacket = reviewEvidenceContext
1620
1657
  ? await writeReviewPacket(root, capsuleProject, project, inputManifest, evidenceReceipts, evidenceArtifacts, reviewEvidenceContext.persistent)
@@ -1697,7 +1734,11 @@ async function writeReviewPacket(root, capsuleProject, project, inputManifest, e
1697
1734
  ];
1698
1735
  const evidenceFiles = new Map();
1699
1736
  for (const receipt of evidenceReceipts) {
1700
- for (const locator of [receipt.locator, receipt.contextLocator]) {
1737
+ for (const locator of [
1738
+ receipt.locator,
1739
+ receipt.contextLocator,
1740
+ ...(receipt.data?.artifacts.map((artifact) => artifact.locator) ?? []),
1741
+ ]) {
1701
1742
  if (!evidenceFiles.has(locator)) {
1702
1743
  evidenceFiles.set(locator, await fileRecord(resolveContained(capsuleProject, locator), locator));
1703
1744
  }
@@ -1789,7 +1830,7 @@ async function writeReviewEvidenceContext(root, projectId, capsuleProject, input
1789
1830
  : "[No admitted evidence source cites this receipt; its raw object and bounded context remain hash-bound in the review packet.]";
1790
1831
  views.push({
1791
1832
  prefix: [
1792
- `--- BROKER RECEIPT ${receipt.attemptId} ---`,
1833
+ `--- ${receipt.evidenceKind === "data" ? "DATA" : "BROKER"} RECEIPT ${receipt.attemptId} ---`,
1793
1834
  `metadata: ${JSON.stringify(metadata)}`,
1794
1835
  "--- BEGIN BOUNDED REVIEW EXCERPT ---",
1795
1836
  "",
@@ -1934,7 +1975,8 @@ async function loadBrokerReviewReferences(capsuleProject) {
1934
1975
  for (const source of evidence.sources) {
1935
1976
  if (!isObject(source) || !isObject(source.provenance))
1936
1977
  continue;
1937
- if (source.provenance.kind !== "broker" || typeof source.provenance.id !== "string")
1978
+ if (!["broker", "data"].includes(String(source.provenance.kind)) ||
1979
+ typeof source.provenance.id !== "string")
1938
1980
  continue;
1939
1981
  if (typeof source.id !== "string" || typeof source.title !== "string")
1940
1982
  continue;
@@ -2200,6 +2242,7 @@ async function reviewEnvironmentPacket(root, projectId) {
2200
2242
  function reviewSafeReceipt(receipt) {
2201
2243
  return {
2202
2244
  schemaVersion: receipt.schemaVersion,
2245
+ evidenceKind: receipt.evidenceKind ?? "broker",
2203
2246
  attemptId: receipt.attemptId,
2204
2247
  capabilityId: receipt.capabilityId,
2205
2248
  status: receipt.status,
@@ -2220,6 +2263,7 @@ function reviewSafeReceipt(receipt) {
2220
2263
  retrievedAt: receipt.retrievedAt,
2221
2264
  servedAt: receipt.servedAt,
2222
2265
  cacheHit: receipt.cacheHit,
2266
+ data: receipt.data ?? null,
2223
2267
  };
2224
2268
  }
2225
2269
  function agentRequest(input) {
@@ -2352,7 +2396,13 @@ async function validateEvidenceSources(root, project, sources) {
2352
2396
  join("inputs", input.id, basename(input.path)).replaceAll("\\", "/"),
2353
2397
  ]));
2354
2398
  const receipts = await loadProjectEvidenceReceipts(root, project.id);
2355
- const brokerLocators = new Map(receipts.map((receipt) => [receipt.attemptId, receipt.locator]));
2399
+ const receiptLocators = new Map(receipts.map((receipt) => [
2400
+ receipt.attemptId,
2401
+ {
2402
+ kind: receipt.evidenceKind === "data" ? "data" : "broker",
2403
+ locator: receipt.locator,
2404
+ },
2405
+ ]));
2356
2406
  const sourceIds = new Set();
2357
2407
  for (const source of sources) {
2358
2408
  if (!isObject(source) || !isObject(source.provenance)) {
@@ -2366,13 +2416,15 @@ async function validateEvidenceSources(root, project, sources) {
2366
2416
  }
2367
2417
  const expectedLocator = source.provenance.kind === "input"
2368
2418
  ? inputLocators.get(String(source.provenance.id))
2369
- : source.provenance.kind === "broker"
2370
- ? brokerLocators.get(String(source.provenance.id))
2419
+ : source.provenance.kind === "broker" || source.provenance.kind === "data"
2420
+ ? receiptLocators.get(String(source.provenance.id))?.kind === source.provenance.kind
2421
+ ? receiptLocators.get(String(source.provenance.id))?.locator
2422
+ : undefined
2371
2423
  : undefined;
2372
2424
  if (!expectedLocator || expectedLocator !== source.locator) {
2373
2425
  throw new StructuredOutputError(`discover output contains invalid provenance for evidence source ${String(id)}.`, {
2374
2426
  validation: [
2375
- "provenance.id must be an exact immutable input ID or broker receipt attemptId",
2427
+ "provenance.id must be an exact immutable input ID or evidence receipt attemptId",
2376
2428
  "locator must exactly match the locator bound to that provenance record",
2377
2429
  ],
2378
2430
  actual: {
@@ -2385,10 +2437,10 @@ async function validateEvidenceSources(root, project, sources) {
2385
2437
  id: inputId,
2386
2438
  locator,
2387
2439
  })),
2388
- allowedBrokerReceipts: [...brokerLocators].map(([attemptId, locator]) => ({
2389
- kind: "broker",
2440
+ allowedEvidenceReceipts: [...receiptLocators].map(([attemptId, receipt]) => ({
2441
+ kind: receipt.kind,
2390
2442
  id: attemptId,
2391
- locator,
2443
+ locator: receipt.locator,
2392
2444
  })),
2393
2445
  });
2394
2446
  }
@@ -2691,12 +2743,18 @@ async function assertDiscoveryCoverage(root, project, evidencePath) {
2691
2743
  // establish breadth, dates, source types and dimensions, but cannot claim
2692
2744
  // that a search-result receipt is already acquired full text.
2693
2745
  const gaps = computed.mechanicalGaps.filter((gap) => !/full-text source\(s\)/.test(gap));
2694
- const requiredCapabilities = requiredDiscoveryCapabilityIds(await loadCapabilityDeclarations(root));
2746
+ const requiredCapabilities = [
2747
+ ...new Set([
2748
+ ...requiredDiscoveryCapabilityIds(await loadCapabilityDeclarations(root)),
2749
+ ...(project.evidenceRequirements.requiredCapabilityIds ?? []),
2750
+ ]),
2751
+ ];
2695
2752
  const exercisedCapabilities = new Set((await loadProjectEvidenceReceipts(root, project.id)).map((receipt) => receipt.capabilityId));
2696
2753
  const journalEvents = await readJournal(workspacePaths(root).journal);
2697
2754
  const attemptedCapabilities = new Map();
2698
2755
  for (const event of journalEvents) {
2699
- if (event.scope !== project.id || event.type !== "capability.fetch.attempted")
2756
+ if (event.scope !== project.id ||
2757
+ (event.type !== "capability.fetch.attempted" && event.type !== "data.capability.requested"))
2700
2758
  continue;
2701
2759
  const capabilityId = event.payload.capabilityId;
2702
2760
  if (typeof capabilityId !== "string")
@@ -2709,7 +2767,8 @@ async function assertDiscoveryCoverage(root, project, evidencePath) {
2709
2767
  attemptedCapabilities.set(capabilityId, current);
2710
2768
  }
2711
2769
  for (const event of journalEvents) {
2712
- if (event.scope !== project.id || event.type !== "capability.fetch.failed")
2770
+ if (event.scope !== project.id ||
2771
+ (event.type !== "capability.fetch.failed" && event.type !== "data.capability.failed"))
2713
2772
  continue;
2714
2773
  const capabilityId = event.payload.capabilityId;
2715
2774
  const failureKind = event.payload.failureKind;
@@ -3028,7 +3087,7 @@ async function stageContextForPackage(capsuleProject, project, workPackage, conf
3028
3087
  }
3029
3088
  function packagePrompt(project, workPackage, inputs, stagedSkills, capabilityDocumentation, reviewPacketSha256, contextBundle, contextBundleContent, stageContextContent, discovery, evidenceCandidates) {
3030
3089
  const stageInstructions = {
3031
- discover: "Assess candidates incrementally through the packet's recordAssessment command; do not accumulate a source-sized final response. The control plane has already assigned every immutable input and broker result a candidateId and retains its title, URL, DOI, dates, receipt, locator, JSON Pointer, hashes, and retrieval metadata. Reference candidateId; never repeat or invent those deterministic fields. Give each admitted candidate a concise sourceId plus source type, relevance, quality, applicability, coverage dimensions, and limitations. Record meaningful explicit rejections; omitted candidates remain unassessed for later gap filling. Native Web or Browser discoveries are supplemental candidates only and cannot be admitted until an immutable broker receipt is attached to the same canonical URL or DOI. After broad search, strict assessment, and focused gap filling, return only the small closeout object with one judgment for every reviewed dimension plus limitations and remaining gaps. The CLI mechanically joins the latest recorded assessments to provenance, derives counts/date range/coverage, and rejects unknown or unformalized candidates.",
3090
+ discover: "Assess candidates incrementally through the packet's recordAssessment command; do not accumulate a source-sized final response. The control plane has already assigned every immutable input, broker result, and structured data result a candidateId and retains its title, URL, DOI, dates, receipt, locator, JSON Pointer, hashes, and retrieval metadata. Reference candidateId; never repeat or invent those deterministic fields. Give each admitted candidate a concise sourceId plus source type, relevance, quality, applicability, coverage dimensions, and limitations. Record meaningful explicit rejections; omitted candidates remain unassessed for later gap filling. Native Web or Browser discoveries are supplemental candidates only and cannot be admitted until an immutable broker receipt is attached to the same canonical URL or DOI. After broad search, strict assessment, and focused gap filling, return only the small closeout object with one judgment for every reviewed dimension plus limitations and remaining gaps. The CLI mechanically joins the latest recorded assessments to provenance, derives counts/date range/coverage, and rejects unknown or unformalized candidates.",
3032
3091
  acquire: "Audit every provisionally admitted source exactly once. For each source, bind its ledger candidateId, list only artifactIds returned by the exact artifact registration command, and choose accepted, limited, or rejected with a concise rationale and explicit limitations. A broker receipt is an immutable discovery record but is not full text. Use an empty artifactIds array only when intentionally retaining a source as metadata/abstract evidence or when the source is an already registered local input. Put unresolved blocking acquisition or coverage deficiencies in gaps; put honest non-blocking scope constraints in limitations. Do not invent file paths, hashes, URLs, artifact IDs, or successful downloads.",
3033
3092
  analyze: "Use only the complete embedded inference snapshot below and return analysis schema v2. Bind the exact inference snapshot hash and one reproducible analysisRun. Every finding must cite admitted source IDs and exact evidenceAtomIds; a top-journal finding must also bind design claimIds. State uncertainty and applicability. Never promote a source-level citation when no exact atom supports the statement.",
3034
3093
  synthesize: "Use only the complete embedded inference snapshot, analysis, and Claim–Evidence Graph below. Return the schema-defined object whose reportMarkdown separates supported conclusions, uncertainty, limitations, and next actions. Every material statement must remain within a graph-bound finding. Use real Markdown line breaks encoded exactly once for JSON; never place literal /n or double-escaped \\n markers in reportMarkdown.",
@@ -3050,7 +3109,7 @@ function packagePrompt(project, workPackage, inputs, stagedSkills, capabilityDoc
3050
3109
  ? "Use the installed external acquisition/document Skills in the current native host, but treat the CLI artifact registry and acquisition schema as the only authority for durable evidence."
3051
3110
  : "Capability files are provenance-bound but are not available as execution tools in this stage.",
3052
3111
  workPackage.stage === "discover"
3053
- ? `Follow the reviewed discovery plan: ${JSON.stringify(discovery)}. The plan's max broker-view count is a hard working ceiling, not a target to exhaust. Execute required first-pass channels before supplemental channels, prefer broad high-yield queries, assess registered candidates between batches, and use the next gap-fill batch only for explicit uncovered dimensions, source types, date ranges, full text, limitations, or counterevidence. Stop fetching as soon as the declared coverage minimums are supportable. Native Web/Browser may broaden lead discovery, but every such action must be recorded through recordActivity, every useful result must be registered as a candidate, and the same URL/DOI must then be formalized through the broker before admission. The broker or an immutable registered input is the sole admissible evidence path. Do not execute a staged Skill's curl/CLI examples or read provider environment variables. Invoke fetch_candidate_source with the manifest capability ID and obey its exact declared HTTP method. GET capabilities use only declared query parameters; POST capabilities require request_body containing only the documented non-secret request JSON. Never place API keys, tokens, authorization data, cookies, or other credential-like fields in request_body. The broker injects the sole declared logical credential, disables caching for credentialed requests, and never persists the POST body (only its hash). The tool result includes exact bounded context, registered candidate IDs, its receipt, whether a network call was avoided, and remaining view budget. Exercise every manifest capability with requiredForDiscovery=true, or the mechanical coverage gate will stop downstream work.`
3112
+ ? `Follow the reviewed discovery plan: ${JSON.stringify(discovery)}. The plan's max evidence-call count is a hard working ceiling, not a target to exhaust. Execute required first-pass channels before supplemental channels, prefer broad high-yield queries, assess registered candidates between batches, and use the next gap-fill batch only for explicit uncovered dimensions, source types, date ranges, full text, limitations, or counterevidence. Stop fetching as soon as the declared coverage minimums are supportable. Native Web/Browser may broaden lead discovery, but every such action must be recorded through recordActivity, every useful result must be registered as a candidate, and the same URL/DOI must then be formalized through the broker before admission. A broker receipt, structured data-runtime receipt, or immutable registered input is an admissible evidence path. Do not execute a staged Skill's curl/CLI examples or read provider environment variables. For generic broker capabilities, invoke fetch_candidate_source with the manifest capability ID and obey its exact declared HTTP method. For structured data capabilities, use the packet's dynamic catalog and describe command, then invoke runDataCapability; never call standalone data run for project evidence. Never place API keys, tokens, authorization data, cookies, or other credential-like fields in request files. The Research control plane injects declared logical credentials and persists only safe hash-bound results. Exercise every manifest capability with requiredForDiscovery=true and every project-required data capability ID, or the mechanical coverage gate will stop downstream work.`
3054
3113
  : "Use only the complete embedded stage context; no tools or additional source reads are allowed.",
3055
3114
  stageInstructions[workPackage.stage],
3056
3115
  "Do not write stage output files directly. Your final response must be only the JSON object required by the supplied output schema; the CLI will validate and atomically materialize it.",