@citeark/agent 0.3.20

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 (347) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +128 -0
  3. package/data/dataset-source-registry.v1.json +300 -0
  4. package/dist/arkgraph/boot.js +6 -0
  5. package/dist/arkgraph/index.html +1 -0
  6. package/dist/arkgraph/viewer.css +1 -0
  7. package/dist/arkgraph/viewer.en.css +1 -0
  8. package/dist/arkgraph/viewer.en.js +49 -0
  9. package/dist/arkgraph/viewer.en.js.LEGAL.txt +56 -0
  10. package/dist/arkgraph/viewer.js +49 -0
  11. package/dist/arkgraph/viewer.js.LEGAL.txt +56 -0
  12. package/docker/claude-code/Dockerfile +97 -0
  13. package/docker/claude-code/codex-pro-relay.mjs +466 -0
  14. package/docker/claude-code/runtime-contract-check.mjs +79 -0
  15. package/docs/arkgraph-reading.md +79 -0
  16. package/docs/configuration.md +100 -0
  17. package/docs/integration.md +92 -0
  18. package/docs/maturity-plan.md +27 -0
  19. package/docs/npm-release.md +44 -0
  20. package/docs/paper-reading.md +40 -0
  21. package/docs/research-plan-granularity.md +27 -0
  22. package/docs/terminal.md +49 -0
  23. package/examples/toy-evaluation/compile-task.json +27 -0
  24. package/examples/toy-evaluation/paper.md +5 -0
  25. package/examples/toy-evaluation/repository/README.md +9 -0
  26. package/examples/toy-evaluation/repository/checkpoint.json +4 -0
  27. package/examples/toy-evaluation/repository/evaluate.py +17 -0
  28. package/examples/toy-evaluation/task.json +81 -0
  29. package/package.json +59 -0
  30. package/prompts/compile-research.md +58 -0
  31. package/prompts/execute-contract.md +72 -0
  32. package/prompts/execute-workspace-simple.md +51 -0
  33. package/prompts/execute-workspace.md +34 -0
  34. package/prompts/prepare-reproduction.md +82 -0
  35. package/prompts/repair-research.md +45 -0
  36. package/protocol/CAP.md +129 -0
  37. package/protocol/LICENSE +12 -0
  38. package/protocol/MAPPINGS.md +72 -0
  39. package/protocol/README.md +38 -0
  40. package/protocol/conformance-v2.0-alpha.1.json +36 -0
  41. package/protocol/examples/arkgraph/checkpoint-evaluation.json +309 -0
  42. package/protocol/examples/arkgraph/fixtures.mjs +49 -0
  43. package/protocol/examples/arkgraph/paper-free.json +291 -0
  44. package/protocol/examples/arkgraph/partial-failure.json +344 -0
  45. package/protocol/examples/arkgraph/training-evaluation.json +443 -0
  46. package/protocol/profiles/agent-trace.md +16 -0
  47. package/protocol/profiles/computational-run.md +16 -0
  48. package/protocol/profiles/core.md +15 -0
  49. package/protocol/profiles/public-bundle.md +18 -0
  50. package/protocol/profiles/reproduction.md +29 -0
  51. package/protocol/profiles/research-compilation.md +44 -0
  52. package/protocol/profiles/research-plan.md +39 -0
  53. package/protocol/profiles/restricted-evidence.md +15 -0
  54. package/runtime/bootstrap-autodl-runtime.sh +314 -0
  55. package/runtime/create-runtime-venv.sh +41 -0
  56. package/runtime/install-local-cpu-runtime.sh +23 -0
  57. package/runtime/install-scientific-runtime.sh +153 -0
  58. package/runtime/mineru/parse.py +62 -0
  59. package/runtime/mineru/requirements.txt +4 -0
  60. package/runtime/requirements-baseline.txt +38 -0
  61. package/schemas/cap/v2/activity.schema.json +47 -0
  62. package/schemas/cap/v2/agent.schema.json +32 -0
  63. package/schemas/cap/v2/assertion.schema.json +110 -0
  64. package/schemas/cap/v2/descriptor.schema.json +243 -0
  65. package/schemas/cap/v2/entity.schema.json +64 -0
  66. package/schemas/cap/v2/manifest.schema.json +67 -0
  67. package/schemas/cap/v2/relation.schema.json +82 -0
  68. package/schemas/compute-catalog.schema.json +63 -0
  69. package/schemas/compute-decision.schema.json +27 -0
  70. package/schemas/execution-contract.schema.json +1024 -0
  71. package/schemas/research-card.schema.json +30 -0
  72. package/schemas/research-inventory-draft.schema.json +366 -0
  73. package/schemas/research.schema.json +1044 -0
  74. package/schemas/result.schema.json +173 -0
  75. package/schemas/verification-policy.schema.json +47 -0
  76. package/schemas/verified-conclusion.schema.json +58 -0
  77. package/schemas/workspace-summary.schema.json +24 -0
  78. package/scripts/build-arkgraph-view.mjs +12 -0
  79. package/scripts/check-execution-feasibility.mjs +24 -0
  80. package/scripts/check-syntax.mjs +15 -0
  81. package/scripts/deterministic-asset-preparation.py +438 -0
  82. package/scripts/package-cap.mjs +23 -0
  83. package/scripts/package-local-agent.mjs +23 -0
  84. package/scripts/preview-arkgraph.mjs +25 -0
  85. package/scripts/replay-research-compiler-candidate.mjs +134 -0
  86. package/scripts/review-compiler-sources.mjs +44 -0
  87. package/scripts/run-asset-preparation.sh +17 -0
  88. package/scripts/run-research-plan.mjs +98 -0
  89. package/scripts/validate-asset-preparation.py +290 -0
  90. package/scripts/verify-local-runtime.mjs +57 -0
  91. package/scripts/verify-npm-package.mjs +57 -0
  92. package/src/adapters/paper2agent.mjs +107 -0
  93. package/src/assets/cache.mjs +159 -0
  94. package/src/assets/compute.mjs +98 -0
  95. package/src/assets/executor.mjs +145 -0
  96. package/src/assets/lifecycle.mjs +213 -0
  97. package/src/assets/manifest.mjs +242 -0
  98. package/src/assets/opportunistic-preparation.mjs +81 -0
  99. package/src/assets/plan.mjs +411 -0
  100. package/src/assets/prompts.mjs +29 -0
  101. package/src/assets/public-asset-probe.mjs +525 -0
  102. package/src/assets/qualification.mjs +119 -0
  103. package/src/assets/readiness.mjs +130 -0
  104. package/src/assets/reproduction-admission.mjs +355 -0
  105. package/src/assets/requirements.mjs +152 -0
  106. package/src/assets/source-grounding.mjs +341 -0
  107. package/src/assets/source-policy.mjs +118 -0
  108. package/src/autodl/client.mjs +260 -0
  109. package/src/autodl/ssh.mjs +380 -0
  110. package/src/autodl/tools.mjs +129 -0
  111. package/src/cap/redaction.mjs +38 -0
  112. package/src/cap/v2/archive.mjs +152 -0
  113. package/src/cap/v2/attestation.mjs +204 -0
  114. package/src/cap/v2/canonical-json.mjs +114 -0
  115. package/src/cap/v2/compilation-artifact.mjs +240 -0
  116. package/src/cap/v2/core.mjs +282 -0
  117. package/src/cap/v2/measurement-assessment-records.mjs +23 -0
  118. package/src/cap/v2/pipeline-artifact.mjs +922 -0
  119. package/src/cap/v2/read.mjs +41 -0
  120. package/src/cap/v2/reassessment-artifact.mjs +383 -0
  121. package/src/cap/v2/research-artifact.mjs +231 -0
  122. package/src/cap/v2/research-map-records.mjs +46 -0
  123. package/src/cap/v2/research-object-records.mjs +163 -0
  124. package/src/cap/v2/research-records.mjs +187 -0
  125. package/src/cap/v2/verify.mjs +642 -0
  126. package/src/cli.mjs +1146 -0
  127. package/src/compute/autodl-pro-compiler.mjs +347 -0
  128. package/src/compute/autodl-pro-executor.mjs +459 -0
  129. package/src/compute/autodl-pro-job.mjs +843 -0
  130. package/src/compute/autodl-pro-network.mjs +295 -0
  131. package/src/compute/autodl-pro-remote.mjs +810 -0
  132. package/src/compute/autodl-pro-staging.mjs +117 -0
  133. package/src/compute/campaign.mjs +110 -0
  134. package/src/compute/catalog.mjs +123 -0
  135. package/src/compute/checkpoint-protocol.mjs +154 -0
  136. package/src/compute/codex-account-lock.mjs +111 -0
  137. package/src/compute/codex-account-session.mjs +107 -0
  138. package/src/compute/compiler-profile.mjs +38 -0
  139. package/src/compute/compiler-router.mjs +23 -0
  140. package/src/compute/coordinator-recovery.mjs +210 -0
  141. package/src/compute/executor-router.mjs +29 -0
  142. package/src/compute/gcp-batch-compiler.mjs +685 -0
  143. package/src/compute/gcp-batch-executor.mjs +1215 -0
  144. package/src/compute/gcp-batch-failure.mjs +92 -0
  145. package/src/compute/gcp-batch-job.mjs +527 -0
  146. package/src/compute/gcp-batch-lifecycle.mjs +81 -0
  147. package/src/compute/gcp-checkpoint-worker.mjs +1633 -0
  148. package/src/compute/local-codex-compiler.mjs +52 -0
  149. package/src/compute/measurement-hardware.mjs +128 -0
  150. package/src/compute/remote-attempt.mjs +226 -0
  151. package/src/compute/requirements.mjs +124 -0
  152. package/src/compute/research-phases.mjs +48 -0
  153. package/src/compute/scheduler.mjs +452 -0
  154. package/src/compute/shared-workloads.mjs +26 -0
  155. package/src/compute/stage-archive.mjs +79 -0
  156. package/src/contracts/campaign-contract.mjs +52 -0
  157. package/src/contracts/execution-contract.mjs +819 -0
  158. package/src/contracts/execution-mode.mjs +19 -0
  159. package/src/contracts/execution-timeouts.mjs +45 -0
  160. package/src/contracts/execution-workload.mjs +68 -0
  161. package/src/contracts/preflight-schema.mjs +25 -0
  162. package/src/contracts/public-contract.mjs +63 -0
  163. package/src/contracts/subject-tags.mjs +31 -0
  164. package/src/dashboard/data.mjs +898 -0
  165. package/src/dashboard/server.mjs +79 -0
  166. package/src/dashboard/static/dashboard.css +366 -0
  167. package/src/dashboard/static/dashboard.js +560 -0
  168. package/src/dashboard/static/index.html +85 -0
  169. package/src/deployment/community-policy.mjs +9 -0
  170. package/src/deployment/environment.mjs +112 -0
  171. package/src/deployment/guided.mjs +98 -0
  172. package/src/deployment/handoff.mjs +102 -0
  173. package/src/deployment/local-contract.mjs +31 -0
  174. package/src/deployment/local.mjs +100 -0
  175. package/src/deployment/prepare.mjs +46 -0
  176. package/src/deployment/recipe.mjs +108 -0
  177. package/src/deployment/supplement.mjs +51 -0
  178. package/src/deployment/terminal.mjs +43 -0
  179. package/src/diagnosis/renderer.mjs +75 -0
  180. package/src/diagnosis/target-failure.mjs +46 -0
  181. package/src/evidence/parser-registry.mjs +54 -0
  182. package/src/evidence/parsers/fasttext-classification.mjs +82 -0
  183. package/src/evidence/parsers/json-scalar.mjs +96 -0
  184. package/src/evidence/parsers/simcse-senteval.mjs +104 -0
  185. package/src/evidence/parsers/starspace-classification.mjs +78 -0
  186. package/src/evidence/registry.mjs +147 -0
  187. package/src/execution/runner-audit.mjs +473 -0
  188. package/src/gcp/auth.mjs +106 -0
  189. package/src/gcp/batch-client.mjs +120 -0
  190. package/src/gcp/resource-discovery.mjs +177 -0
  191. package/src/gcp/rest.mjs +82 -0
  192. package/src/gcp/secret-manager.mjs +34 -0
  193. package/src/gcp/signed-url.mjs +133 -0
  194. package/src/gcp/storage.mjs +220 -0
  195. package/src/graph/command.mjs +41 -0
  196. package/src/graph/execution.mjs +97 -0
  197. package/src/graph/model.mjs +37 -0
  198. package/src/graph/presentation.mjs +110 -0
  199. package/src/graph/query.mjs +159 -0
  200. package/src/graph/research-relations.mjs +69 -0
  201. package/src/graph/source-page.mjs +12 -0
  202. package/src/graph/source-preview.mjs +34 -0
  203. package/src/graph/validate.mjs +76 -0
  204. package/src/job.mjs +496 -0
  205. package/src/network/autodl-routing-proxy.mjs +462 -0
  206. package/src/network/egress-proxy.mjs +158 -0
  207. package/src/observability/event-contract.mjs +230 -0
  208. package/src/observability/pipeline-monitor.mjs +166 -0
  209. package/src/pipeline/orchestrator.mjs +1281 -0
  210. package/src/pipeline/recovery-error.mjs +11 -0
  211. package/src/pipeline/replay.mjs +304 -0
  212. package/src/pipeline/shared-execution.mjs +115 -0
  213. package/src/pipeline/stage-checkpoint.mjs +86 -0
  214. package/src/pipeline/stage-recovery.mjs +101 -0
  215. package/src/pipeline/targets.mjs +110 -0
  216. package/src/process.mjs +143 -0
  217. package/src/protocol.mjs +312 -0
  218. package/src/provider/codex-account.mjs +44 -0
  219. package/src/provider/codex-completion.mjs +49 -0
  220. package/src/provider/completion.mjs +292 -0
  221. package/src/provider/model-client.mjs +44 -0
  222. package/src/provider/model-route.mjs +29 -0
  223. package/src/provider/openrouter-readiness.mjs +189 -0
  224. package/src/provider/reader-bridge.mjs +35 -0
  225. package/src/provider/relay.mjs +263 -0
  226. package/src/provider/runtime-auth.mjs +40 -0
  227. package/src/public/cap.d.mts +90 -0
  228. package/src/public/cap.mjs +12 -0
  229. package/src/public/contracts.d.mts +2 -0
  230. package/src/public/host.mjs +171 -0
  231. package/src/public/operations.d.mts +11 -0
  232. package/src/public/presentation.d.mts +4 -0
  233. package/src/records/views.mjs +26 -0
  234. package/src/remote/command.mjs +178 -0
  235. package/src/remote/ssh.mjs +59 -0
  236. package/src/repository-origin.mjs +81 -0
  237. package/src/reproduction/evidence-feedback.mjs +96 -0
  238. package/src/reproduction/incomplete-initialization.mjs +25 -0
  239. package/src/reproduction/lifecycle.mjs +253 -0
  240. package/src/reproduction/plan.mjs +132 -0
  241. package/src/reproduction/prompts.mjs +70 -0
  242. package/src/reproduction/runner.mjs +188 -0
  243. package/src/reproduction/summary.mjs +130 -0
  244. package/src/reproduction/workspace-mode.mjs +7 -0
  245. package/src/research/automatic-admission.mjs +156 -0
  246. package/src/research/compiler-coverage.mjs +85 -0
  247. package/src/research/compiler-failure.mjs +24 -0
  248. package/src/research/compiler-normalization-guards.mjs +112 -0
  249. package/src/research/compiler-repair.mjs +3 -0
  250. package/src/research/compiler.mjs +853 -0
  251. package/src/research/continuation-selection.mjs +26 -0
  252. package/src/research/execution-graph-context.mjs +43 -0
  253. package/src/research/experiment-importance.mjs +15 -0
  254. package/src/research/inventory-handoff.mjs +104 -0
  255. package/src/research/inventory-revisions.mjs +32 -0
  256. package/src/research/mineru-local.mjs +73 -0
  257. package/src/research/paper-command.mjs +19 -0
  258. package/src/research/paper-markdown.mjs +180 -0
  259. package/src/research/paper-source-map.mjs +69 -0
  260. package/src/research/planning-policy.mjs +88 -0
  261. package/src/research/reference-materials.mjs +11 -0
  262. package/src/research/reproduction-scope.mjs +30 -0
  263. package/src/research/research-map.mjs +94 -0
  264. package/src/research/research-objects.mjs +88 -0
  265. package/src/research/source-discovery.mjs +646 -0
  266. package/src/research/source-observations.mjs +75 -0
  267. package/src/research/source-review-cli-mcp.mjs +26 -0
  268. package/src/research/source-review-input.mjs +209 -0
  269. package/src/research/source-review-local-codex.mjs +36 -0
  270. package/src/research/source-review-model.mjs +70 -0
  271. package/src/research/source-review.mjs +173 -0
  272. package/src/research/structure.mjs +3163 -0
  273. package/src/research-card/renderer.mjs +277 -0
  274. package/src/research-card/verified-conclusion.mjs +143 -0
  275. package/src/results/output-registry.mjs +183 -0
  276. package/src/runtime/claude-code.mjs +52 -0
  277. package/src/runtime/codex-capacity-retry.mjs +87 -0
  278. package/src/runtime/codex.mjs +64 -0
  279. package/src/runtime/config.mjs +157 -0
  280. package/src/runtime/final-output.mjs +40 -0
  281. package/src/runtime/index.mjs +21 -0
  282. package/src/runtime/local-codex.mjs +74 -0
  283. package/src/runtime/opencode.mjs +95 -0
  284. package/src/runtime/prompt.mjs +13 -0
  285. package/src/sandbox/docker.mjs +363 -0
  286. package/src/settings/command.mjs +297 -0
  287. package/src/settings/store.mjs +119 -0
  288. package/src/telemetry/pricing.mjs +68 -0
  289. package/src/telemetry/usage.mjs +265 -0
  290. package/src/terminal/events.mjs +97 -0
  291. package/src/terminal/input.mjs +40 -0
  292. package/src/terminal/plain.mjs +40 -0
  293. package/src/terminal/remote-stream.mjs +22 -0
  294. package/src/terminal/screen.mjs +214 -0
  295. package/src/terminal/transcript.mjs +69 -0
  296. package/src/util.mjs +107 -0
  297. package/src/verification/ai-assessor.mjs +534 -0
  298. package/src/verification/claim-evaluator.mjs +242 -0
  299. package/src/verification/evidence-context.mjs +165 -0
  300. package/src/verification/evidence-reader.mjs +95 -0
  301. package/src/verification/integrity.mjs +570 -0
  302. package/src/verification/tolerance.mjs +32 -0
  303. package/src/workloads/cpu-research-preparation.mjs +56 -0
  304. package/src/workloads/definition.mjs +74 -0
  305. package/src/workloads/phase-aware-reproduction.mjs +46 -0
  306. package/src/workloads/reproduction.mjs +85 -0
  307. package/src/workspace/command.mjs +242 -0
  308. package/src/workspace/control.mjs +49 -0
  309. package/src/workspace/entry.mjs +28 -0
  310. package/src/workspace/input.mjs +93 -0
  311. package/src/workspace/interactive.mjs +94 -0
  312. package/src/workspace/jobs.mjs +418 -0
  313. package/src/workspace/session.mjs +97 -0
  314. package/src/workspace/worker.mjs +137 -0
  315. package/ui/arkgraph/ambient-motion.mjs +10 -0
  316. package/ui/arkgraph/app.jsx +153 -0
  317. package/ui/arkgraph/boot.js +6 -0
  318. package/ui/arkgraph/camera-motion.mjs +20 -0
  319. package/ui/arkgraph/context-reveal.mjs +39 -0
  320. package/ui/arkgraph/details.css +3 -0
  321. package/ui/arkgraph/entry.jsx +28 -0
  322. package/ui/arkgraph/experiment-curves.mjs +17 -0
  323. package/ui/arkgraph/experiment-selection.mjs +15 -0
  324. package/ui/arkgraph/experiment-style.css +26 -0
  325. package/ui/arkgraph/experiment-ui.jsx +32 -0
  326. package/ui/arkgraph/frame.html +1 -0
  327. package/ui/arkgraph/graph-gestures.mjs +62 -0
  328. package/ui/arkgraph/label-layout.mjs +57 -0
  329. package/ui/arkgraph/locales/en.json +229 -0
  330. package/ui/arkgraph/locales/source-types.json +15 -0
  331. package/ui/arkgraph/localization-build.mjs +27 -0
  332. package/ui/arkgraph/material-build.mjs +23 -0
  333. package/ui/arkgraph/material-colors.mjs +39 -0
  334. package/ui/arkgraph/material-style.css +15 -0
  335. package/ui/arkgraph/open-graph.jsx +326 -0
  336. package/ui/arkgraph/outline.jsx +49 -0
  337. package/ui/arkgraph/package-lock.json +888 -0
  338. package/ui/arkgraph/package.json +17 -0
  339. package/ui/arkgraph/reading-layout.mjs +130 -0
  340. package/ui/arkgraph/reading-presentation.mjs +73 -0
  341. package/ui/arkgraph/record-detail.css +51 -0
  342. package/ui/arkgraph/record-details.jsx +29 -0
  343. package/ui/arkgraph/research-types.mjs +31 -0
  344. package/ui/arkgraph/selection-mark.jsx +6 -0
  345. package/ui/arkgraph/soft-spine.mjs +26 -0
  346. package/ui/arkgraph/steering-style.css +187 -0
  347. package/ui/arkgraph/style.css +272 -0
package/src/cli.mjs ADDED
@@ -0,0 +1,1146 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { deployLocally, publishLocalCap } from "./deployment/local.mjs";
4
+ import { setupLocalRuntime } from "./deployment/environment.mjs";
5
+ import { existsSync, readFileSync, realpathSync } from "node:fs";
6
+ import { cp, mkdtemp, mkdir, rm } from "node:fs/promises";
7
+ import os from "node:os";
8
+ import path from "node:path";
9
+ import { fileURLToPath } from "node:url";
10
+
11
+ import { assemblePaper2AgentCompilationCap } from "./adapters/paper2agent.mjs";
12
+ import {
13
+ packCap,
14
+ verifyCapArchive,
15
+ } from "./cap/v2/archive.mjs";
16
+ import { assembleResearchCompilationCap } from "./cap/v2/compilation-artifact.mjs";
17
+ import { verifyCapDirectory } from "./cap/v2/verify.mjs";
18
+ import { AutoDlProClient } from "./autodl/client.mjs";
19
+ import { AutoDlSshClient, parseAutoDlSshConnection } from "./autodl/ssh.mjs";
20
+ import {
21
+ ASSET_QUALIFICATION_BOUNDARY,
22
+ loadAssetQualificationContext,
23
+ planAssetQualification,
24
+ probeAssetQualification,
25
+ verifyAssetQualification,
26
+ } from "./assets/qualification.mjs";
27
+ import { loadComputeCatalog, loadComputePolicy } from "./compute/catalog.mjs";
28
+ import { loadComputeDecision, scheduleCompute } from "./compute/scheduler.mjs";
29
+ import { executeScheduledReproduction } from "./compute/executor-router.mjs";
30
+ import { createExecutionContract, loadExecutionContract } from "./contracts/execution-contract.mjs";
31
+ import { startDashboardServer } from "./dashboard/server.mjs";
32
+ import { listEvidenceParsers, parseContractEvidence } from "./evidence/registry.mjs";
33
+ import {
34
+ loadAndNormalizeTask,
35
+ validateResultFile,
36
+ } from "./protocol.mjs";
37
+ import { executeFullPipeline } from "./pipeline/orchestrator.mjs";
38
+ import { runResearchCompiler } from "./research/compiler.mjs";
39
+ import { loadResearchStructure, normalizeResearchFile } from "./research/structure.mjs";
40
+ import { primaryMetric } from "./records/views.mjs";
41
+ import { dockerDoctor } from "./sandbox/docker.mjs";
42
+ import { CiteArkError, createRunId, shellQuote, writeJson } from "./util.mjs";
43
+
44
+ const PACKAGE_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
45
+ const VERSION = JSON.parse(readFileSync(path.join(PACKAGE_ROOT, "package.json"), "utf8")).version;
46
+
47
+ if (process.argv[1] && realpathSync(process.argv[1]) === fileURLToPath(import.meta.url)) await bootstrap().catch((error) => {
48
+ const message = error instanceof Error ? error.message : String(error);
49
+ console.error(`\nCiteArk Agent: ${message}`);
50
+ process.exitCode = error?.exitCode ?? 1;
51
+ });
52
+
53
+ async function bootstrap() {
54
+ loadLocalEnvironment();
55
+ await main();
56
+ }
57
+
58
+ function loadLocalEnvironment() {
59
+ if (typeof process.loadEnvFile !== "function") return;
60
+ const candidates = [
61
+ path.resolve(".env.local"),
62
+ path.join(PACKAGE_ROOT, ".env.local"),
63
+ ];
64
+ for (const candidate of new Set(candidates)) {
65
+ if (!existsSync(candidate)) continue;
66
+ process.loadEnvFile(candidate);
67
+ return;
68
+ }
69
+ }
70
+
71
+ export async function main(argv = process.argv.slice(2)) {
72
+ const [command = process.stdin.isTTY && process.stdout.isTTY ? "start" : "help", ...rest] = argv;
73
+ if (command === "--help" || command === "-h" || command === "help") {
74
+ printHelp();
75
+ return;
76
+ }
77
+ if (command === "--version" || command === "-v" || command === "version") {
78
+ console.log(VERSION);
79
+ return;
80
+ }
81
+ if (command === 'view') {
82
+ if (!rest[0]) throw Error('Usage: citeark view <workspace-directory>');
83
+ const filename = path.join(path.resolve(rest[0]), 'session.events.jsonl');
84
+ if (!process.stdin.isTTY || !process.stdout.isTTY || process.env.TERM === 'dumb') {
85
+ const { Transcript } = await import('./terminal/transcript.mjs');
86
+ const transcript = new Transcript();
87
+ for (const line of readFileSync(filename, 'utf8').split('\n').filter(Boolean)) transcript.add(JSON.parse(line));
88
+ console.log(transcript.lines(100, true).join('\n'));
89
+ return;
90
+ }
91
+ const { TerminalScreen } = await import('./terminal/screen.mjs');
92
+ const screen = new TerminalScreen({ version: VERSION }); screen.start();
93
+ try { await screen.view(filename); } finally { await screen.close(); }
94
+ return;
95
+ }
96
+ if (command === 'paper') return (await import('./research/paper-command.mjs')).paperCommand(rest, parseOptions);
97
+ if (command === 'session') return (await import('./workspace/jobs.mjs')).sessionCommand(rest, parseOptions);
98
+ if (command === 'graph') return (await import('./graph/command.mjs')).graphCommand(rest, parseOptions);
99
+ if (command === 'start' || (command === 'deploy' && !rest.includes('--replay'))) {
100
+ const { startResearch } = await import('./workspace/command.mjs');
101
+ return startResearch(rest, { parseOptions, agentEntryOptions, gcpEntryOptions, autoDlEntryOptions, agentRuntimeOptions, executorOptions });
102
+ }
103
+ if (command === 'deploy') return deployCommand(rest.filter(value => value !== '--replay'));
104
+ if (command === "handoff") {
105
+ const options = parseOptions(rest, { "--cap": { type: "string", required: true },
106
+ "--research-cap": { type: "string" }, "--output": { type: "string", required: true },
107
+ "--model": { type: "string", required: true }, "--effort": { type: "string", default: "high" },
108
+ "--signing-key": { type: "string" } });
109
+ const { prepareHistoricalHandoff } = await import('./deployment/prepare.mjs');
110
+ console.log(JSON.stringify(await prepareHistoricalHandoff({ capPath: options['--cap'], researchCapPath: options['--research-cap'],
111
+ directory: path.resolve(options['--output']), model: options['--model'], effort: options['--effort'], signingKeyPath: options['--signing-key'] }), null, 2));
112
+ return;
113
+ }
114
+ if (command === "setup") {
115
+ const options = parseOptions(rest, { "--gpu": { type: "boolean", default: false } });
116
+ console.log(JSON.stringify(await setupLocalRuntime({ gpu: options["--gpu"] }), null, 2));
117
+ return;
118
+ }
119
+ if (command === "publish") return await publishCommand(rest);
120
+ if (command === "run") return await runCommand(rest);
121
+ if (command === "compile") return await compileCommand(rest);
122
+ if (command === "validate") return await validateCommand(rest);
123
+ if (command === "research") return await researchCommand(rest);
124
+ if (command === "contract") return await contractCommand(rest);
125
+ if (command === 'model' || command === 'compute' && rest[0] !== 'plan') {
126
+ return (await import('./settings/command.mjs')).settingsCommand(command, rest, parseOptions);
127
+ }
128
+ if (command === "compute") return await computeCommand(rest);
129
+ if (command === "assets") return await assetsCommand(rest);
130
+ if (command === "evidence") return await evidenceCommand(rest);
131
+ if (command === "pipeline") return await pipelineCommand(rest);
132
+ if (command === "cap") return await capCommand(rest);
133
+ if (command === "parsers") return parsersCommand();
134
+ if (command === "doctor") return await doctorCommand(rest);
135
+ if (command === "dashboard") return await dashboardCommand(rest);
136
+ if (command === "autodl") return await autoDlCommand(rest);
137
+ if (command === "init") return await initCommand(rest);
138
+ throw new CiteArkError(`Unknown command: ${command}\nRun citeark --help for usage.`);
139
+ }
140
+
141
+ async function deployCommand(argv) {
142
+ const reference = argv[0] && !argv[0].startsWith('-') ? argv.shift() : null;
143
+ const optionalAgent = Object.fromEntries(Object.entries(agentEntryOptions()).map(([key, value]) => [key, { ...value, required: false }]));
144
+ const options = parseOptions(argv, { ...optionalAgent,
145
+ "--repository-id": { type: "string" }, "--run": { type: "string" }, "--cap": { type: "string" },
146
+ "--platform": { type: "string", default: "https://citeark.co" },
147
+ "--work-dir": { type: "string" }, "--image": { type: "string" },
148
+ "--device": { type: "string", default: "auto" }, "--non-interactive": { type: "boolean", default: false },
149
+ "--signing-key": { type: "string" }, "--dry-run": { type: "boolean", default: false },
150
+ });
151
+ if ([reference, options['--repository-id'], options['--cap']].filter(Boolean).length !== 1) {
152
+ throw Error('Provide exactly one paper ID, --repository-id, or --cap.');
153
+ }
154
+ if (Number(process.versions.node.split('.')[0]) < 22) throw Error('Install Node.js 22 or later: https://nodejs.org/');
155
+ const dryRun = options['--dry-run'];
156
+ const interactive = !dryRun && !options['--non-interactive'] && Boolean(process.stdin.isTTY && process.stdout.isTTY);
157
+ const { createTerminalPrompter, cancelled } = await import('./deployment/terminal.mjs');
158
+ const { fetchDeployment, chooseDeployment, readLocalPreferences, writeLocalPreferences,
159
+ configureLocalModel, ensureGuidedEnvironment, describeDeployment } = await import('./deployment/guided.mjs');
160
+ const prompt = interactive ? createTerminalPrompter() : null;
161
+ let repositoryId = options['--repository-id'] ?? reference;
162
+ let route;
163
+ if (repositoryId) {
164
+ const data = await fetchDeployment(repositoryId, { baseUrl: options['--platform'] });
165
+ repositoryId = data.repositoryId ?? repositoryId;
166
+ console.log(`\nCiteArk · ${data.title ?? repositoryId}`);
167
+ route = await chooseDeployment(data, { runId: options['--run'], prompt });
168
+ }
169
+ if (options['--api-key'] && options['--api-key-env']) throw Error('Provide either --api-key or --api-key-env.');
170
+ if (options['--api-key-env'] && !process.env[options['--api-key-env']] && !dryRun) throw Error(`Environment variable ${options['--api-key-env']} is not set`);
171
+ const explicitRuntime = {
172
+ runtime: options['--agent'], apiBaseUrl: options['--api-base-url'], model: options['--model'],
173
+ apiKey: options['--api-key'] ?? process.env[options['--api-key-env']],
174
+ apiKeySource: options['--api-key-env'] ? `env:${options['--api-key-env']}` : undefined,
175
+ subagentModel: options['--subagent-model'],
176
+ };
177
+ let agentRuntime;
178
+ if (!interactive) {
179
+ if (!dryRun && (!explicitRuntime.apiBaseUrl || !explicitRuntime.model)) {
180
+ throw Error('Use an interactive terminal to configure the model, or pass --api-base-url, --model, and --api-key-env. Use --dry-run to inspect inputs.');
181
+ }
182
+ agentRuntime = agentRuntimeOptions({ ...options, '--agent': options['--agent'] ?? 'opencode',
183
+ '--api-base-url': options['--api-base-url'] ?? 'https://api.invalid', '--model': options['--model'] ?? 'dry-run' }, dryRun);
184
+ }
185
+ const workDirectory = options['--work-dir'] ?? path.join(process.cwd(), `citeark-${(reference ?? 'run').replace(/[^a-zA-Z0-9-]/g, '').slice(0, 40)}-${Date.now()}`);
186
+ const result = await deployLocally({ repositoryId, runId: route?.runId ?? options['--run'], capPath: options['--cap'],
187
+ baseUrl: options['--platform'], workDirectory, image: options['--image'], device: options['--device'],
188
+ signingKeyPath: options['--signing-key'], dryRun, agentRuntime,
189
+ prepareExecution: prompt ? async context => {
190
+ describeDeployment({ ...context, route });
191
+ const localPreflight = await ensureGuidedEnvironment({ ...context, prompt });
192
+ const configured = await configureLocalModel({ options: explicitRuntime, saved: await readLocalPreferences(), prompt });
193
+ console.log(`\nModel: ${configured.model}\nDirectory: ${context.directory}`);
194
+ console.log('This will download research materials and run experiments using your model provider.');
195
+ if (!await prompt.confirm('Start local reproduction?')) throw cancelled();
196
+ await writeLocalPreferences(configured);
197
+ return { agentRuntime: configured, localPreflight };
198
+ } : undefined,
199
+ });
200
+ console.log(result.dryRun ? `Prepared (dry run): ${result.runDirectory}` : `Signed local run: ${result.archive}\nAssessment: ${result.conclusion}`);
201
+ if (prompt && repositoryId && await prompt.confirm('Upload this result to CiteArk?')) {
202
+ const token = process.env.CITEARK_API_KEY ?? await prompt.ask('CiteArk API key (write access required; hidden)', { secret: true });
203
+ console.log(JSON.stringify(await publishLocalCap({ capPath: result.archive, repositoryId, baseUrl: options['--platform'], token }), null, 2));
204
+ }
205
+ }
206
+
207
+ async function publishCommand(argv) {
208
+ const options = parseOptions(argv, { "--cap": { type: "string", required: true },
209
+ "--repository-id": { type: "string" },
210
+ "--plan": { type: "string" }, "--visibility": { type: "string" },
211
+ "--platform": { type: "string", default: "https://citeark.co" },
212
+ "--token-env": { type: "string", default: "CITEARK_API_KEY" }, });
213
+ if (options['--plan']) await publishLocalCap({ capPath: options['--plan'], repositoryId: options['--repository-id'],
214
+ baseUrl: options['--platform'], token: process.env[options['--token-env']], visibility: options['--visibility'] });
215
+ console.log(JSON.stringify(await publishLocalCap({ capPath: options["--cap"], repositoryId: options["--repository-id"],
216
+ baseUrl: options["--platform"], token: process.env[options["--token-env"]], visibility: options["--visibility"] }), null, 2));
217
+ }
218
+
219
+ async function compileCommand(argv) {
220
+ const options = parseOptions(argv, {
221
+ ...agentEntryOptions(),
222
+ "--task": { type: "string", required: true },
223
+ "--runs-dir": { type: "string", default: ".citeark/compilations" },
224
+ "--run-id": { type: "string" },
225
+ "--image": { type: "string" },
226
+ "--cap-output": { type: "string" },
227
+ "--signing-key": { type: "string" },
228
+ "--dry-run": { type: "boolean", default: false },
229
+ });
230
+ const compilation = await runResearchCompiler({
231
+ taskPath: options["--task"],
232
+ runsDirectory: options["--runs-dir"],
233
+ runId: options["--run-id"],
234
+ imageOverride: options["--image"],
235
+ agentRuntime: agentRuntimeOptions(options, options["--dry-run"]),
236
+ dryRun: options["--dry-run"],
237
+ });
238
+ if (compilation.dryRun) {
239
+ console.log("CiteArk Research Compiler Run bundle prepared (dry run):");
240
+ console.log(`Run directory: ${compilation.bundle.directories.run}`);
241
+ console.log(`Command: ${compilation.invocation.printable}`);
242
+ return;
243
+ }
244
+ console.log("Research compilation: completed");
245
+ console.log(`Research: ${path.join(compilation.bundle.directories.output, "research.normalized.json")}`);
246
+ if (compilation.research.compilationStage === "inventory") {
247
+ const capDirectory = path.join(compilation.bundle.directories.run, "research-compilation-cap");
248
+ const built = await assembleResearchCompilationCap({
249
+ directory: capDirectory,
250
+ inventory: compilation.research,
251
+ compiler: {
252
+ id: "citeark/compiler",
253
+ name: "CiteArk Research Compiler",
254
+ version: compilation.research.provenance?.compiler,
255
+ },
256
+ runId: compilation.bundle.runId,
257
+ createdAt: compilation.bundle.state.finishedAt,
258
+ signingKeyPath: options["--signing-key"],
259
+ });
260
+ const outputPath = path.resolve(
261
+ options["--cap-output"]
262
+ ?? path.join(compilation.bundle.directories.run, "research-compilation.cap"),
263
+ );
264
+ await mkdir(path.dirname(outputPath), { recursive: true });
265
+ const archive = await packCap({ directory: capDirectory, outputPath });
266
+ console.log(`Compilation CAP: ${archive.path}`);
267
+ console.log(`Compilation Artifact Digest: ${built.artifactDigest}`);
268
+ }
269
+ }
270
+
271
+ async function runCommand(argv) {
272
+ const options = parseOptions(argv, {
273
+ ...agentEntryOptions(),
274
+ ...gcpEntryOptions(),
275
+ ...autoDlEntryOptions(),
276
+ "--task": { type: "string", required: true },
277
+ "--runs-dir": { type: "string", default: ".citeark/runs" },
278
+ "--image": { type: "string" },
279
+ "--run-id": { type: "string" },
280
+ "--compute-decision": { type: "string" },
281
+ "--dry-run": { type: "boolean", default: false },
282
+ });
283
+
284
+ const computeDecision = options["--compute-decision"] ? await loadComputeDecision(options["--compute-decision"]) : null;
285
+ const usesRemoteSecret = new Set(["gcp-batch", "autodl-pro"])
286
+ .has(computeDecision?.selectedProfile?.executor);
287
+ const execution = await executeScheduledReproduction({
288
+ taskPath: options["--task"],
289
+ runsDirectory: options["--runs-dir"],
290
+ runId: options["--run-id"],
291
+ imageOverride: options["--image"],
292
+ computeDecision,
293
+ agentRuntime: agentRuntimeOptions(options, options["--dry-run"], { allowGcpSecret: usesRemoteSecret }),
294
+ executorOptions: executorOptions(options),
295
+ dryRun: options["--dry-run"],
296
+ progress: (message) => console.log(`\n${message}`),
297
+ });
298
+ if (execution.dryRun) {
299
+ console.log("\nCiteArk Agent Run bundle prepared (dry run):");
300
+ console.log(`Run ID: ${execution.bundle.runId}`);
301
+ console.log(`Run directory: ${execution.bundle.directories.run}`);
302
+ console.log(`Command: ${execution.invocation.printable}`);
303
+ return;
304
+ }
305
+ console.log("\nCiteArk Agent Run finished:");
306
+ console.log(`Status: ${execution.runStatus}`);
307
+ console.log("Research artifacts are generated by the full pipeline under the Research Plan CAP.");
308
+ }
309
+
310
+ async function validateCommand(argv) {
311
+ const options = parseOptions(argv, {
312
+ "--task": { type: "string", required: true },
313
+ "--result": { type: "string", required: true },
314
+ "--output-dir": { type: "string" },
315
+ });
316
+ const { task } = await loadAndNormalizeTask(options["--task"]);
317
+ const resultPath = path.resolve(options["--result"]);
318
+ const outputDirectory = path.resolve(
319
+ options["--output-dir"] ?? path.dirname(resultPath),
320
+ );
321
+ const validation = await validateResultFile(resultPath, task, outputDirectory);
322
+ if (validation.issues.length > 0) {
323
+ throw new CiteArkError(
324
+ `Result validation failed: \n- ${validation.issues.join("\n- ")}`,
325
+ { exitCode: 2 },
326
+ );
327
+ }
328
+ console.log("Result protocol: valid");
329
+ if (validation.protocolVerification) {
330
+ console.log(`Verification: ${validation.protocolVerification.status}`);
331
+ console.log(`Absolute difference: ${validation.protocolVerification.absoluteDifference}`);
332
+ } else {
333
+ console.log("Verification: deferred to the independent verification engine");
334
+ }
335
+ }
336
+
337
+ async function researchCommand(argv) {
338
+ const [subcommand, ...rest] = argv;
339
+ if (subcommand !== "validate") throw new CiteArkError("Usage: citeark research validate --input <research.json> [--output <normalized.json>]");
340
+ const options = parseOptions(rest, {
341
+ "--input": { type: "string", required: true },
342
+ "--output": { type: "string" },
343
+ });
344
+ const output = options["--output"] ?? options["--input"];
345
+ const research = await normalizeResearchFile(options["--input"], output);
346
+ console.log(`Research structure: valid (${research.claims.length} claims, ${research.experiments.length} experiments)`);
347
+ console.log(`Normalized: ${path.resolve(output)}`);
348
+ }
349
+
350
+ async function contractCommand(argv) {
351
+ const [subcommand, ...rest] = argv;
352
+ if (subcommand !== "create") throw new CiteArkError("Usage: citeark contract create --research <research.json> --claim <id> --output <contract.json> --policy <private.json> --tolerance <number>");
353
+ const options = parseOptions(rest, {
354
+ "--research": { type: "string", required: true },
355
+ "--claim": { type: "string", required: true },
356
+ "--experiment": { type: "string" },
357
+ "--output": { type: "string", required: true },
358
+ "--policy": { type: "string", required: true },
359
+ "--tolerance": { type: "string", required: true },
360
+ });
361
+ const { contract, policy } = await createExecutionContract({
362
+ researchPath: options["--research"],
363
+ claimId: options["--claim"],
364
+ experimentId: options["--experiment"],
365
+ outputPath: options["--output"],
366
+ policyPath: options["--policy"],
367
+ tolerance: options["--tolerance"],
368
+ });
369
+ console.log(`Execution contract: ${path.resolve(options["--output"])}`);
370
+ console.log(`Private policy: ${path.resolve(options["--policy"])}`);
371
+ console.log(`Contract digest: ${contract.contractDigest}`);
372
+ console.log(`Policy digest: ${policy.policyDigest}`);
373
+ }
374
+
375
+ async function computeCommand(argv) {
376
+ const [subcommand, ...rest] = argv;
377
+ if (subcommand !== "plan") throw new CiteArkError("Usage: citeark compute plan --research <research.json> --experiment <id> [--contract <contract.json>] [--catalog <catalog.json>] [--policy <policy.json>] [--profile <id>] [--output <decision.json>]");
378
+ const options = parseOptions(rest, {
379
+ "--research": { type: "string", required: true },
380
+ "--experiment": { type: "string", required: true },
381
+ "--contract": { type: "string" },
382
+ "--catalog": { type: "string" },
383
+ "--policy": { type: "string" },
384
+ "--profile": { type: "string" },
385
+ "--output": { type: "string" },
386
+ });
387
+ const [research, catalog, policy, contract] = await Promise.all([
388
+ loadResearchStructure(options["--research"]),
389
+ loadComputeCatalog(options["--catalog"]),
390
+ loadComputePolicy(options["--policy"]),
391
+ options["--contract"] ? loadExecutionContract(options["--contract"]) : null,
392
+ ]);
393
+ const experiment = research.experiments.find((item) => item.id === options["--experiment"]);
394
+ if (!experiment) throw new CiteArkError(`Experiment not found: ${options["--experiment"]}`);
395
+ const decision = await scheduleCompute({
396
+ experiment,
397
+ contract,
398
+ catalog,
399
+ policy,
400
+ profileOverride: options["--profile"],
401
+ outputPath: options["--output"],
402
+ });
403
+ console.log(`Compute class: ${decision.requirement.classification}`);
404
+ console.log(`Selected profile: ${decision.selectedProfile.id}`);
405
+ console.log(`Executor: ${decision.selectedProfile.executor}`);
406
+ console.log(`Estimated cost: ${decision.estimate.costUsd ?? "unknown"} USD`);
407
+ if (options["--output"]) console.log(`Decision: ${path.resolve(options["--output"])}`);
408
+ }
409
+
410
+ async function evidenceCommand(argv) {
411
+ const [subcommand, ...rest] = argv;
412
+ if (subcommand !== "parse") throw new CiteArkError("Usage: citeark evidence parse --contract <contract.json> --output-dir <run/output> --metrics <metrics.json>");
413
+ const options = parseOptions(rest, {
414
+ "--contract": { type: "string", required: true },
415
+ "--output-dir": { type: "string", required: true },
416
+ "--metrics": { type: "string", required: true },
417
+ });
418
+ const contract = await loadExecutionContract(options["--contract"]);
419
+ const { resolveResearchPlan } = await import("./reproduction/plan.mjs");
420
+ const effectiveContract = await resolveResearchPlan(contract, options["--output-dir"]);
421
+ const metrics = await parseContractEvidence({ contract: effectiveContract, outputDirectory: options["--output-dir"], metricsPath: options["--metrics"] });
422
+ const measurement = metrics.measurements?.[0] ?? metrics;
423
+ const primary = primaryMetric(metrics);
424
+ console.log(`Evidence parser: ${measurement.parser.id}@${measurement.parser.version}`);
425
+ console.log(`Primary metric: ${primary.metric}=${primary.value} ${primary.unit}`);
426
+ }
427
+
428
+ async function pipelineCommand(argv) {
429
+ const [subcommand, ...rest] = argv;
430
+ if (subcommand !== "execute") throw new CiteArkError("Usage: citeark pipeline execute ...");
431
+ return await pipelineExecuteCommand(rest);
432
+ }
433
+
434
+ async function pipelineExecuteCommand(argv, { forcedStopAfter } = {}) {
435
+ const options = parseOptions(argv, {
436
+ ...agentEntryOptions(),
437
+ ...gcpEntryOptions(),
438
+ ...autoDlEntryOptions(),
439
+ "--compile-task": { type: "string" },
440
+ "--research": { type: "string" },
441
+ "--compilation": { type: "string" },
442
+ "--paper": { type: "string" },
443
+ "--claim": { type: "string" },
444
+ "--experiment": { type: "string" },
445
+ "--tolerance": { type: "string", required: true },
446
+ "--work-dir": { type: "string", required: true },
447
+ "--resume": { type: "boolean", default: false },
448
+ "--signing-key": { type: "string" },
449
+ "--compute-catalog": { type: "string" },
450
+ "--compute-policy": { type: "string" },
451
+ "--compute-profile": { type: "string" },
452
+ "--dataset-registry": { type: "string" },
453
+ "--repository": { type: "string" },
454
+ "--stop-after": { type: "string" },
455
+ "--dry-run": { type: "boolean", default: false },
456
+ });
457
+ if (forcedStopAfter && options["--stop-after"] && options["--stop-after"] !== forcedStopAfter) {
458
+ throw new CiteArkError(`assets prepare stops at ${forcedStopAfter}`);
459
+ }
460
+ const stopAfter = forcedStopAfter ?? options["--stop-after"];
461
+ const pipeline = await executeFullPipeline({
462
+ compileTaskPath: options["--compile-task"],
463
+ researchPath: options["--research"],
464
+ compilationArtifactPath: options["--compilation"],
465
+ paperPath: options["--paper"],
466
+ claimId: options["--claim"],
467
+ experimentId: options["--experiment"],
468
+ tolerance: options["--tolerance"],
469
+ workDirectory: options["--work-dir"],
470
+ resume: options["--resume"],
471
+ signingKeyPath: options["--signing-key"],
472
+ computeCatalogPath: options["--compute-catalog"],
473
+ computePolicyPath: options["--compute-policy"],
474
+ computeProfile: options["--compute-profile"],
475
+ datasetRegistryPath: options["--dataset-registry"],
476
+ repositoryPath: options["--repository"],
477
+ stopAfter,
478
+ agentRuntime: agentRuntimeOptions(options, options["--dry-run"], { allowGcpSecret: true }),
479
+ executorOptions: executorOptions(options),
480
+ dryRun: options["--dry-run"],
481
+ progress: (message) => console.log(message),
482
+ });
483
+ if (pipeline.dryRun) {
484
+ console.log(stopAfter === ASSET_QUALIFICATION_BOUNDARY
485
+ ? `Asset preparation bundle ready (dry run): ${pipeline.directories.root}`
486
+ : `Pipeline prepared: ${pipeline.directories.root}`);
487
+ if (pipeline.compilationArtifact) {
488
+ console.log(`Input Compilation Artifact: ${pipeline.compilationArtifact.artifactDigest}`);
489
+ }
490
+ return;
491
+ }
492
+ if (stopAfter === ASSET_QUALIFICATION_BOUNDARY) {
493
+ console.log("Asset checks passed");
494
+ console.log("Research execution not started");
495
+ console.log(`Plan digest: ${pipeline.qualification.planDigest}`);
496
+ console.log(`Manifest digest: ${pipeline.qualification.manifestDigest}`);
497
+ console.log(`Cache hit: ${pipeline.qualification.cacheHit}`);
498
+ console.log(`Checkpoint: ${pipeline.qualification.checkpointPrefix}`);
499
+ console.log(`Evidence: ${path.join(pipeline.directories.protocol, "asset-qualification.json")}`);
500
+ return;
501
+ }
502
+ console.log(`Pipeline: ${pipeline.state.status}`);
503
+ console.log(`Verification: ${pipeline.replay.assessment.verificationStatus}`);
504
+ console.log(`CAP: ${pipeline.directories.cap}`);
505
+ console.log(`CAP file: ${pipeline.archive.path}`);
506
+ console.log(`Archive SHA-256: ${pipeline.archive.sha256}`);
507
+ }
508
+
509
+ async function assetsCommand(argv) {
510
+ const [subcommand, ...rest] = argv;
511
+ if (subcommand === "prepare") {
512
+ return await pipelineExecuteCommand(rest, {
513
+ forcedStopAfter: ASSET_QUALIFICATION_BOUNDARY,
514
+ });
515
+ }
516
+ if (subcommand === "verify") {
517
+ const options = parseOptions(rest, {
518
+ "--plan": { type: "string", required: true },
519
+ "--manifest": { type: "string", required: true },
520
+ });
521
+ const verification = await verifyAssetQualification({
522
+ planPath: options["--plan"],
523
+ manifestPath: options["--manifest"],
524
+ });
525
+ if (!verification.valid) {
526
+ throw new CiteArkError(`Invalid asset manifest: \n- ${verification.issues.join("\n- ")}`, {
527
+ exitCode: 2,
528
+ });
529
+ }
530
+ console.log("Asset manifest valid");
531
+ console.log(`Plan digest: ${verification.plan.planDigest}`);
532
+ console.log(`Manifest digest: ${verification.manifest.manifestDigest}`);
533
+ return;
534
+ }
535
+ if (!new Set(["plan", "probe"]).has(subcommand)) {
536
+ throw new CiteArkError("Usage: citeark assets plan|probe|prepare|verify ...");
537
+ }
538
+ const options = parseOptions(rest, {
539
+ "--research": { type: "string", required: true },
540
+ "--claim": { type: "string" },
541
+ "--experiment": { type: "string" },
542
+ "--dataset-registry": { type: "string" },
543
+ "--output": { type: "string" },
544
+ });
545
+ const context = await loadAssetQualificationContext({
546
+ researchPath: options["--research"],
547
+ claimId: options["--claim"],
548
+ experimentId: options["--experiment"],
549
+ datasetRegistryPath: options["--dataset-registry"],
550
+ });
551
+ if (subcommand === "plan") {
552
+ const { plan, failures } = planAssetQualification(context);
553
+ if (options["--output"]) await writeJson(options["--output"], plan);
554
+ console.log(`Assets: ${plan.summary.assetCount}`);
555
+ console.log(`Prepared assets: ${plan.summary.prepareCount}`);
556
+ console.log(`Streamed assets: ${plan.summary.streamCount}`);
557
+ console.log(`Metadata only: ${plan.summary.metadataOnlyCount}`);
558
+ console.log(`Over budget: ${plan.summary.blockedCount}`);
559
+ console.log(`Estimated download: ${plan.summary.expectedDownloadBytes} bytes`);
560
+ if (options["--output"]) console.log(`Plan: ${path.resolve(options["--output"])}`);
561
+ for (const failure of failures) console.log(`Blocked: ${failure.reasonCode} ${failure.message}`);
562
+ return;
563
+ }
564
+ const admission = await probeAssetQualification({
565
+ ...context,
566
+ outputPath: options["--output"],
567
+ });
568
+ console.log(`Ready targets: ${admission.summary.admittedTargetCount}/${admission.summary.targetCount}`);
569
+ console.log(`Blocked targets: ${admission.summary.blockedTargetCount}`);
570
+ console.log(`Retryable targets: ${admission.summary.retryableTargetCount}`);
571
+ console.log(`URL request attempts: ${admission.summary.requestAttemptCount}`);
572
+ if (options["--output"]) console.log(`Probe: ${path.resolve(options["--output"])}`);
573
+ if (admission.summary.admittedTargetCount !== admission.summary.targetCount) process.exitCode = 2;
574
+ }
575
+
576
+ async function capCommand(argv) {
577
+ const [subcommand, ...rest] = argv;
578
+ if (subcommand === "import-paper2agent") {
579
+ const options = parseOptions(rest, {
580
+ "--delivery": { type: "string", required: true },
581
+ "--inventory": { type: "string", required: true },
582
+ "--paper2agent-version": { type: "string" },
583
+ "--run-id": { type: "string" },
584
+ "--signing-key": { type: "string" },
585
+ "--output": { type: "string", required: true },
586
+ });
587
+ const inventory = await loadResearchStructure(options["--inventory"]);
588
+ const temporary = await mkdtemp(path.join(os.tmpdir(), "citeark-import-paper2agent-"));
589
+ try {
590
+ const artifactDirectory = path.join(temporary, "artifact");
591
+ const built = await assemblePaper2AgentCompilationCap({
592
+ directory: artifactDirectory,
593
+ inventory,
594
+ deliveryPath: options["--delivery"],
595
+ paper2AgentVersion: options["--paper2agent-version"],
596
+ runId: options["--run-id"] ?? createRunId(),
597
+ signingKeyPath: options["--signing-key"],
598
+ });
599
+ const outputPath = path.resolve(options["--output"]);
600
+ await mkdir(path.dirname(outputPath), { recursive: true });
601
+ const archive = await packCap({ directory: artifactDirectory, outputPath });
602
+ console.log(`Paper2Agent delivery: ${built.delivery.kind}`);
603
+ console.log(`Compilation CAP: ${archive.path}`);
604
+ console.log(`Artifact Digest: ${built.artifactDigest}`);
605
+ return;
606
+ } finally {
607
+ await rm(temporary, { recursive: true, force: true });
608
+ }
609
+ }
610
+ if (subcommand === "create-compilation") {
611
+ const options = parseOptions(rest, {
612
+ "--inventory": { type: "string", required: true },
613
+ "--compiler-id": { type: "string", required: true },
614
+ "--compiler-name": { type: "string", required: true },
615
+ "--compiler-version": { type: "string" },
616
+ "--run-id": { type: "string" },
617
+ "--signing-key": { type: "string" },
618
+ "--output": { type: "string", required: true },
619
+ });
620
+ const inventory = await loadResearchStructure(options["--inventory"]);
621
+ const temporary = await mkdtemp(path.join(os.tmpdir(), "citeark-create-compilation-"));
622
+ try {
623
+ const built = await assembleResearchCompilationCap({
624
+ directory: path.join(temporary, "artifact"),
625
+ inventory,
626
+ compiler: {
627
+ id: options["--compiler-id"],
628
+ name: options["--compiler-name"],
629
+ version: options["--compiler-version"],
630
+ },
631
+ runId: options["--run-id"] ?? createRunId(),
632
+ signingKeyPath: options["--signing-key"],
633
+ });
634
+ const outputPath = path.resolve(options["--output"]);
635
+ await mkdir(path.dirname(outputPath), { recursive: true });
636
+ const archive = await packCap({
637
+ directory: path.join(temporary, "artifact"),
638
+ outputPath,
639
+ });
640
+ console.log(`Compilation CAP: ${archive.path}`);
641
+ console.log(`Artifact Digest: ${built.artifactDigest}`);
642
+ return;
643
+ } finally {
644
+ await rm(temporary, { recursive: true, force: true });
645
+ }
646
+ }
647
+ if (subcommand === "pack") {
648
+ const options = parseOptions(rest, {
649
+ "--dir": { type: "string", required: true },
650
+ "--output": { type: "string", required: true },
651
+ });
652
+ const source = path.resolve(options["--dir"]);
653
+ const destination = path.resolve(options["--output"]);
654
+ const archive = await packCap({ directory: source, outputPath: destination });
655
+ console.log(`CAP file: ${archive.path}`);
656
+ console.log(`Archive SHA-256: ${archive.sha256}`);
657
+ console.log(`Artifact Digest: ${archive.artifactDigest}`);
658
+ return;
659
+ }
660
+ if (subcommand !== "verify") {
661
+ throw new CiteArkError("Usage: citeark cap import-paper2agent|create-compilation|pack|verify ...");
662
+ }
663
+ const options = parseOptions(rest, {
664
+ "--dir": { type: "string" },
665
+ "--file": { type: "string" },
666
+ });
667
+ if (Boolean(options["--dir"]) === Boolean(options["--file"])) {
668
+ throw new CiteArkError("cap verify requires exactly one of --dir or --file");
669
+ }
670
+ const report = options["--file"]
671
+ ? await verifyCapArchive(path.resolve(options["--file"]))
672
+ : await verifyCapDirectory(path.resolve(options["--dir"]));
673
+ if (!report.valid) throw new CiteArkError(`CAP validation failed: \n- ${report.issues.join("\n- ")}`, { exitCode: 2 });
674
+ console.log("CAP: valid");
675
+ console.log(`Protocol: ${report.protocolVersion}`);
676
+ console.log(`Artifact Digest: ${report.artifactDigest}`);
677
+ console.log(`Profiles: ${report.manifest.profiles.join(", ")}`);
678
+ console.log(`Valid signatures: ${report.attestations.filter((item) => item.signatureValid && item.subjectValid).length}`);
679
+ if (report.archive) console.log(`Archive SHA-256: ${report.archive.sha256}`);
680
+ }
681
+
682
+ function parsersCommand() {
683
+ for (const parser of listEvidenceParsers()) console.log(`${parser.id}@${parser.version}`);
684
+ }
685
+
686
+ async function autoDlCommand(argv) {
687
+ const [subcommand, ...rest] = argv;
688
+ if (!new Set([
689
+ "list",
690
+ "images",
691
+ "status",
692
+ "start",
693
+ "stop",
694
+ "release",
695
+ "bootstrap",
696
+ "save-image",
697
+ ]).has(subcommand)) {
698
+ throw new CiteArkError(
699
+ "Usage: citeark autodl list|images|status|start|stop|release|bootstrap|save-image [--instance <uuid>] [--token-env AUTODL_API_TOKEN]",
700
+ );
701
+ }
702
+ const needsInstance = !new Set(["list", "images"]).has(subcommand);
703
+ const options = parseOptions(rest, {
704
+ "--instance": { type: "string", required: needsInstance },
705
+ "--token-env": { type: "string", default: "AUTODL_API_TOKEN" },
706
+ "--token-stdin": { type: "boolean", default: false },
707
+ "--confirm": { type: "string" },
708
+ "--image-name": { type: "string" },
709
+ "--save-as": { type: "string" },
710
+ });
711
+ const token = options["--token-stdin"]
712
+ ? await readSecretFromStdin()
713
+ : process.env[options["--token-env"]];
714
+ if (!token) {
715
+ throw new CiteArkError(
716
+ options["--token-stdin"]
717
+ ? "No AutoDL token received on stdin"
718
+ : `Environment variable ${options["--token-env"]} is not set`,
719
+ );
720
+ }
721
+ const client = new AutoDlProClient({ token });
722
+ const instanceUuid = options["--instance"];
723
+ if (subcommand === "list") {
724
+ const result = await client.listInstances();
725
+ const instances = Array.isArray(result?.list) ? result.list : [];
726
+ console.log(JSON.stringify(instances.map((instance) => ({
727
+ uuid: instance.uuid,
728
+ name: instance.name,
729
+ status: instance.status,
730
+ region: instance.region_name ?? instance.region_sign,
731
+ gpuSpecUuid: instance.gpu_spec_uuid,
732
+ gpuCount: instance.req_gpu_amount,
733
+ })), null, 2));
734
+ return;
735
+ }
736
+ if (subcommand === "images") {
737
+ const result = await client.listPrivateImages();
738
+ const images = Array.isArray(result?.list) ? result.list : [];
739
+ console.log(JSON.stringify(images.map((image) => ({
740
+ imageUuid: image.image_uuid,
741
+ name: image.name,
742
+ status: image.status,
743
+ imageSize: image.image_size,
744
+ createdAt: image.create_at,
745
+ })), null, 2));
746
+ return;
747
+ }
748
+ if (subcommand === "status") {
749
+ console.log(await client.getStatus(instanceUuid));
750
+ return;
751
+ }
752
+ if (subcommand === "start") {
753
+ await client.powerOn(instanceUuid, { startCommand: "sleep infinity" });
754
+ console.log(`AutoDL instance start requested: ${instanceUuid}`);
755
+ return;
756
+ }
757
+ if (subcommand === "stop") {
758
+ await client.powerOff(instanceUuid);
759
+ console.log(`AutoDL instance stop requested: ${instanceUuid}`);
760
+ return;
761
+ }
762
+ if (subcommand === "bootstrap") {
763
+ const connection = parseAutoDlSshConnection(
764
+ await client.getInstance(instanceUuid),
765
+ );
766
+ const ssh = new AutoDlSshClient(connection);
767
+ try {
768
+ await ssh.connect();
769
+ await Promise.all([
770
+ ssh.putFile(
771
+ path.join(PACKAGE_ROOT, "runtime", "bootstrap-autodl-runtime.sh"),
772
+ "/root/citeark-bootstrap-runtime.sh",
773
+ ),
774
+ ssh.putFile(
775
+ path.join(PACKAGE_ROOT, "docker", "claude-code", "codex-pro-relay.mjs"),
776
+ "/root/codex-pro-relay.mjs",
777
+ ),
778
+ ssh.putFile(
779
+ path.join(PACKAGE_ROOT, "runtime", "requirements-baseline.txt"),
780
+ "/root/citeark-requirements-baseline.txt",
781
+ ),
782
+ ssh.putFile(
783
+ path.join(PACKAGE_ROOT, "runtime", "create-runtime-venv.sh"),
784
+ "/root/citeark-create-runtime-venv.sh",
785
+ ),
786
+ ]);
787
+ const result = await ssh.exec(
788
+ "chmod 0700 /root/citeark-bootstrap-runtime.sh && /root/citeark-bootstrap-runtime.sh",
789
+ {
790
+ onStdout: (text) => process.stdout.write(text),
791
+ onStderr: (text) => process.stderr.write(text),
792
+ },
793
+ );
794
+ if (result.code !== 0) {
795
+ throw new CiteArkError(`AutoDL runtime initialization failed (exit code ${result.code})`);
796
+ }
797
+ } finally {
798
+ ssh.close();
799
+ }
800
+ if (options["--save-as"]) {
801
+ await ensureAutoDlInstanceStopped(client, instanceUuid);
802
+ const saved = await client.saveInstanceImage(instanceUuid, options["--save-as"]);
803
+ console.log(`AutoDL private image save submitted: ${saved?.image_uuid ?? "waiting for AutoDL image ID"}`);
804
+ } else {
805
+ console.log("AutoDL runtime ready. Save a private image or run again with --save-as.");
806
+ }
807
+ return;
808
+ }
809
+ if (subcommand === "save-image") {
810
+ if (!options["--image-name"]) {
811
+ throw new CiteArkError("save-image requires --image-name");
812
+ }
813
+ await ensureAutoDlInstanceStopped(client, instanceUuid);
814
+ const saved = await client.saveInstanceImage(instanceUuid, options["--image-name"]);
815
+ console.log(`AutoDL private image save submitted: ${saved?.image_uuid ?? "waiting for AutoDL image ID"}`);
816
+ return;
817
+ }
818
+ if (options["--confirm"] !== instanceUuid) {
819
+ throw new CiteArkError("Releasing an instance deletes its system disk. Pass the full instance UUID with --confirm.");
820
+ }
821
+ const status = String(await client.getStatus(instanceUuid)).toLowerCase();
822
+ if (!new Set(["stopped", "shutdown", "shutoff"]).has(status)) {
823
+ await client.powerOff(instanceUuid);
824
+ await client.waitForStatus(instanceUuid, ["stopped", "shutdown", "shutoff"]);
825
+ }
826
+ await client.release(instanceUuid);
827
+ console.log(`AutoDL instance released: ${instanceUuid}`);
828
+ }
829
+
830
+ async function ensureAutoDlInstanceStopped(client, instanceUuid) {
831
+ const status = String(await client.getStatus(instanceUuid)).trim().toLowerCase();
832
+ if (new Set(["stopped", "shutdown", "shutoff"]).has(status)) return;
833
+ await client.powerOff(instanceUuid);
834
+ await client.waitForStatus(instanceUuid, ["stopped", "shutdown", "shutoff"]);
835
+ }
836
+
837
+ async function readSecretFromStdin() {
838
+ const chunks = [];
839
+ let bytes = 0;
840
+ for await (const chunk of process.stdin) {
841
+ bytes += chunk.length;
842
+ if (bytes > 16 * 1024) throw new CiteArkError("The credential on stdin exceeds the size limit");
843
+ chunks.push(chunk);
844
+ }
845
+ return Buffer.concat(chunks).toString("utf8").trim();
846
+ }
847
+
848
+ async function doctorCommand(argv) {
849
+ const options = parseOptions(argv, {
850
+ "--image": {
851
+ type: "string",
852
+ default: "citeark-agent/runtime:cpu",
853
+ },
854
+ "--agent": { type: "string", default: "opencode" },
855
+ });
856
+ if (!new Set(["claude-code", "codex", "opencode"]).has(options["--agent"])) {
857
+ throw new CiteArkError("--agent must be claude-code, codex, or opencode");
858
+ }
859
+ const report = await dockerDoctor(options["--image"], options["--agent"]);
860
+ console.log(`Docker client: ${report.client ?? "unavailable"}`);
861
+ console.log(`Docker server: ${report.server ?? "unavailable"}`);
862
+ console.log(`Runtime image: ${report.image ?? "unavailable"}`);
863
+ console.log(`Agent runtime: ${options["--agent"]}`);
864
+ console.log(`Agent CLI: ${report.runtime ?? "unavailable"}`);
865
+ if (report.issues.length > 0) {
866
+ throw new CiteArkError(`Runtime not ready: \n- ${report.issues.join("\n- ")}`);
867
+ }
868
+ console.log("CiteArk Agent runtime: ready");
869
+ }
870
+
871
+ async function dashboardCommand(argv) {
872
+ const options = parseOptions(argv, {
873
+ "--pipelines-dir": { type: "string", default: ".citeark/pipelines" },
874
+ "--host": { type: "string", default: "127.0.0.1" },
875
+ "--port": { type: "string", default: "4310" },
876
+ });
877
+ const port = Number(options["--port"]);
878
+ if (!Number.isInteger(port) || port < 0 || port > 65535) {
879
+ throw new CiteArkError("--port must be an integer from 0 to 65535");
880
+ }
881
+ const dashboard = await startDashboardServer({
882
+ pipelinesDirectory: options["--pipelines-dir"],
883
+ host: options["--host"],
884
+ port,
885
+ });
886
+ console.log("CiteArk Agent dashboard started");
887
+ console.log(`URL: ${dashboard.url}`);
888
+ console.log(`Pipeline directory: ${dashboard.pipelinesDirectory}`);
889
+ console.log("Press Ctrl+C to stop");
890
+ }
891
+
892
+ async function initCommand(argv) {
893
+ const options = parseOptions(argv, {
894
+ "--dir": { type: "string", default: "citeark-agent-task" },
895
+ });
896
+ const destination = path.resolve(options["--dir"]);
897
+ await mkdir(destination, { recursive: true });
898
+ await cp(
899
+ path.join(PACKAGE_ROOT, "examples", "toy-evaluation", "task.json"),
900
+ path.join(destination, "task.json"),
901
+ );
902
+ await cp(
903
+ path.join(PACKAGE_ROOT, "examples", "toy-evaluation", "paper.md"),
904
+ path.join(destination, "paper.md"),
905
+ );
906
+ await cp(
907
+ path.join(PACKAGE_ROOT, "examples", "toy-evaluation", "repository"),
908
+ path.join(destination, "repository"),
909
+ { recursive: true },
910
+ );
911
+ console.log(`Example task created: ${destination}`);
912
+ console.log(
913
+ `Next: citeark run --task ${shellQuote(path.join(destination, "task.json"))} --agent opencode --api-base-url https://api.deepseek.com --model '<model-id>' --dry-run`,
914
+ );
915
+ }
916
+
917
+ function parseOptions(argv, definitions) {
918
+ const output = {};
919
+ for (const [name, definition] of Object.entries(definitions)) {
920
+ if (definition.default !== undefined) output[name] = definition.default;
921
+ }
922
+ for (let index = 0; index < argv.length; index += 1) {
923
+ const name = argv[index];
924
+ const definition = definitions[name];
925
+ if (!definition) throw new CiteArkError(`Unknown option: ${name}`);
926
+ if (definition.type === "boolean") {
927
+ output[name] = true;
928
+ continue;
929
+ }
930
+ const value = argv[index + 1];
931
+ if (value === undefined || value.startsWith("--")) {
932
+ throw new CiteArkError(`Missing value for ${name}`);
933
+ }
934
+ output[name] = value;
935
+ index += 1;
936
+ }
937
+ for (const [name, definition] of Object.entries(definitions)) {
938
+ if (definition.required && output[name] === undefined) {
939
+ throw new CiteArkError(`Missing required option: ${name}`);
940
+ }
941
+ }
942
+ return output;
943
+ }
944
+
945
+ function agentEntryOptions() {
946
+ return {
947
+ "--agent": { type: "string", required: true },
948
+ "--api-base-url": { type: "string", required: true },
949
+ "--api-key": { type: "string" },
950
+ "--api-key-env": { type: "string" },
951
+ "--model": { type: "string", required: true },
952
+ "--subagent-model": { type: "string" },
953
+ "--effort": { type: "string" }, "--model-budget": { type: "string" },
954
+ };
955
+ }
956
+
957
+ function agentRuntimeOptions(options, dryRun, { allowGcpSecret = false } = {}) {
958
+ const runtime = options["--agent"];
959
+ if (!new Set(["claude-code", "codex", "opencode"]).has(runtime)) {
960
+ throw new CiteArkError("--agent must be claude-code, codex, or opencode");
961
+ }
962
+ if (options["--api-key"] && options["--api-key-env"]) {
963
+ throw new CiteArkError("Provide either --api-key or --api-key-env");
964
+ }
965
+ const environmentName = options["--api-key-env"];
966
+ const apiKey = options["--api-key"] ?? (environmentName ? process.env[environmentName] : null);
967
+ const hasGcpSecret = Boolean(options["--gcp-provider-secret"] ?? process.env.CITEARK_GCP_PROVIDER_SECRET);
968
+ if (!dryRun && !apiKey && !(allowGcpSecret && hasGcpSecret)) {
969
+ throw new CiteArkError(
970
+ environmentName
971
+ ? `Environment variable ${environmentName} is not set`
972
+ : "Provide --api-key, --api-key-env, or --gcp-provider-secret for GCP Batch.",
973
+ );
974
+ }
975
+ return {
976
+ runtime,
977
+ apiBaseUrl: options["--api-base-url"],
978
+ apiKey,
979
+ apiKeySource: apiKey
980
+ ? (environmentName ? `env:${environmentName}` : "parameter")
981
+ : "gcp-secret-manager",
982
+ model: options["--model"],
983
+ subagentModel: options["--subagent-model"],
984
+ effort: options["--effort"], maxBudgetUsd: options["--model-budget"] ? Number(options["--model-budget"]) : undefined,
985
+ };
986
+ }
987
+
988
+ function gcpEntryOptions() {
989
+ return {
990
+ "--gcp-project": { type: "string" },
991
+ "--gcp-region": { type: "string" },
992
+ "--gcp-staging-bucket": { type: "string" },
993
+ "--gcp-asset-cache-bucket": { type: "string" },
994
+ "--gcp-asset-restore-checkpoint-prefix": { type: "string" },
995
+ "--gcp-asset-restore-checkpoint-bucket": { type: "string" },
996
+ "--gcp-service-account": { type: "string" },
997
+ "--gcp-provider-secret": { type: "string" },
998
+ "--gcp-machine-type": { type: "string" },
999
+ "--gcp-provisioning-model": { type: "string" },
1000
+ "--gcp-boot-disk-gb": { type: "string" },
1001
+ "--gcp-wait-timeout-minutes": { type: "string" },
1002
+ "--gcp-critical-checkpoint-seconds": { type: "string" },
1003
+ "--gcp-full-checkpoint-seconds": { type: "string" },
1004
+ "--gcp-checkpoint-retention": { type: "string" },
1005
+ "--gcp-result-stability-seconds": { type: "string" },
1006
+ "--gcp-disable-checkpoints": { type: "boolean", default: false },
1007
+ "--gcp-keep-job": { type: "boolean", default: false },
1008
+ "--gcp-keep-staging": { type: "boolean", default: false },
1009
+ };
1010
+ }
1011
+
1012
+ function autoDlEntryOptions() {
1013
+ return {
1014
+ "--autodl-token-env": { type: "string", default: "AUTODL_API_TOKEN" },
1015
+ "--allow-remote-model-key": { type: "boolean", default: false },
1016
+ "--autodl-image-uuid": { type: "string" },
1017
+ "--autodl-gpu-spec-uuid": { type: "string" },
1018
+ "--autodl-data-centers": { type: "string" },
1019
+ "--autodl-max-hourly-cny": { type: "string" },
1020
+ "--autodl-expand-system-disk-gb": { type: "string" },
1021
+ "--autodl-keep-instance": { type: "boolean", default: false },
1022
+ "--autodl-keep-failed-instance": { type: "boolean", default: false },
1023
+ "--autodl-release-on-failure": { type: "boolean", default: false },
1024
+ };
1025
+ }
1026
+
1027
+ function executorOptions(options) {
1028
+ const autoDlTokenEnvironment = options["--autodl-token-env"];
1029
+ return {
1030
+ gcpBatch: {
1031
+ projectId: options["--gcp-project"],
1032
+ region: options["--gcp-region"],
1033
+ stagingBucket: options["--gcp-staging-bucket"],
1034
+ assetCacheBucket: options["--gcp-asset-cache-bucket"],
1035
+ assetPreparationRestoreCheckpointPrefix:
1036
+ options["--gcp-asset-restore-checkpoint-prefix"],
1037
+ assetPreparationRestoreCheckpointBucket:
1038
+ options["--gcp-asset-restore-checkpoint-bucket"],
1039
+ serviceAccount: options["--gcp-service-account"],
1040
+ providerSecret: options["--gcp-provider-secret"],
1041
+ machineType: options["--gcp-machine-type"],
1042
+ provisioningModel: options["--gcp-provisioning-model"],
1043
+ bootDiskGb: options["--gcp-boot-disk-gb"],
1044
+ waitTimeoutMinutes: options["--gcp-wait-timeout-minutes"],
1045
+ checkpointEnabled: options["--gcp-disable-checkpoints"] ? false : undefined,
1046
+ criticalCheckpointIntervalSeconds: options["--gcp-critical-checkpoint-seconds"],
1047
+ fullCheckpointIntervalSeconds: options["--gcp-full-checkpoint-seconds"],
1048
+ checkpointRetention: options["--gcp-checkpoint-retention"],
1049
+ keepJob: options["--gcp-keep-job"],
1050
+ keepStaging: options["--gcp-keep-staging"],
1051
+ },
1052
+ autoDl: {
1053
+ allowRemoteModelKey: options["--allow-remote-model-key"],
1054
+ apiToken: autoDlTokenEnvironment
1055
+ ? process.env[autoDlTokenEnvironment]
1056
+ : undefined,
1057
+ imageUuid: options["--autodl-image-uuid"],
1058
+ gpuSpecUuid: options["--autodl-gpu-spec-uuid"],
1059
+ dataCenterList: options["--autodl-data-centers"]
1060
+ ?.split(",")
1061
+ .map((item) => item.trim())
1062
+ .filter(Boolean),
1063
+ maxHourlyCny: options["--autodl-max-hourly-cny"],
1064
+ expandSystemDiskGb: options["--autodl-expand-system-disk-gb"],
1065
+ providerSecret: options["--gcp-provider-secret"],
1066
+ keepInstance: options["--autodl-keep-instance"],
1067
+ keepFailedInstance: options["--autodl-keep-failed-instance"]
1068
+ ? true
1069
+ : options["--autodl-release-on-failure"]
1070
+ ? false
1071
+ : undefined,
1072
+ },
1073
+ };
1074
+ }
1075
+
1076
+ function printHelp() {
1077
+ console.log(`CiteArk Agent ${VERSION}
1078
+
1079
+ Independent research, experiment execution, and signed evidence.
1080
+
1081
+ Start and continue
1082
+ citeark Open the interactive research workspace
1083
+ citeark start <paper-id> Start from a CiteArk paper
1084
+ citeark start --paper <path> Start from a paper file or URL
1085
+ citeark start --cap <file> Use a CAP artifact as research input
1086
+ citeark start --resume --work-dir <directory>
1087
+ citeark view <directory> Browse a saved conversation without running it
1088
+
1089
+ Profiles and sessions
1090
+ citeark model add|list|use|remove|check <name>
1091
+ citeark compute add|list|use|remove|check <name>
1092
+ citeark session list
1093
+ citeark session attach|status|pause|resume|cancel <directory>
1094
+ citeark session note <directory> --message <text>
1095
+ citeark session fetch <remote-directory> --compute <name> --output <path>
1096
+
1097
+ Research options
1098
+ --goal <text> Set your research question
1099
+ --repository <path-or-url> Include source code
1100
+ --guide <file> Include research instructions
1101
+ --compute <name> Select a saved local, SSH or catalog profile
1102
+ --background Start a detached research worker
1103
+ --compute-catalog <file> Use your local or remote compute configuration
1104
+ --plan-only Save a plan without running experiments
1105
+ --experiments <id,id> Select experiments
1106
+ --plain Use line-oriented terminal output
1107
+ --non-interactive Run with explicit options, without prompts
1108
+ --dry-run Prepare inputs without models or compute
1109
+
1110
+ Model options
1111
+ --model-profile <name> Select a saved model configuration
1112
+ --assessment-profile <name> Use a separate model for scientific assessment
1113
+ --change-model Record an explicit model change on resume
1114
+ --effort <level> low, medium, high, xhigh or max
1115
+ --model-budget <usd> Runtime model budget (not a total cost cap)
1116
+ --agent <runtime> opencode, codex, or claude-code
1117
+ --api-base-url <url> Model endpoint
1118
+ --model <name> Model name
1119
+ --api-key-env <name> Environment variable containing the API key
1120
+
1121
+ Artifacts and tools
1122
+ citeark publish --cap <file> [--plan <file>]
1123
+ citeark cap verify --file <file>
1124
+ citeark graph --cap <file> --operation subgraph
1125
+ citeark paper setup --python python3.12
1126
+ citeark paper parse --input paper.pdf --output ./paper-reading
1127
+ citeark setup [--gpu]
1128
+ citeark doctor
1129
+ citeark deploy --replay <paper-id>
1130
+
1131
+ Advanced commands
1132
+ compile · run · pipeline · research · contract · compute · assets
1133
+ evidence · handoff · parsers · dashboard · autodl · init
1134
+
1135
+ Terminal controls
1136
+ PgUp/PgDn or mouse wheel Browse the full conversation
1137
+ End Follow new output
1138
+ Ctrl+O Expand or collapse long tool output
1139
+ /pause /resume /cancel Control the attached research worker
1140
+ Enter Queue an instruction for the next invocation
1141
+ Ctrl+C Detach from the research worker
1142
+
1143
+ Documentation: https://citeark.co/docs/local-reproduction`);
1144
+ }
1145
+
1146
+ export { parseOptions, agentEntryOptions, gcpEntryOptions, autoDlEntryOptions, agentRuntimeOptions, executorOptions };