@tiangong-ai/cli 0.0.59 → 0.0.61

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 (104) hide show
  1. package/AGENTS.md +2 -2
  2. package/README.md +287 -41
  3. package/dist/research/orchestration.js +209 -62
  4. package/dist/research/orchestration.js.map +1 -1
  5. package/dist/research/workspace/acquisition-forecast.d.ts +3 -0
  6. package/dist/research/workspace/acquisition-forecast.js +28 -3
  7. package/dist/research/workspace/acquisition-forecast.js.map +1 -1
  8. package/dist/research/workspace/acquisition-revision.d.ts +13 -0
  9. package/dist/research/workspace/acquisition-revision.js +142 -0
  10. package/dist/research/workspace/acquisition-revision.js.map +1 -0
  11. package/dist/research/workspace/acquisition-routes.d.ts +1 -1
  12. package/dist/research/workspace/acquisition-routes.js +2 -11
  13. package/dist/research/workspace/acquisition-routes.js.map +1 -1
  14. package/dist/research/workspace/acquisition.d.ts +3 -1
  15. package/dist/research/workspace/acquisition.js +67 -35
  16. package/dist/research/workspace/acquisition.js.map +1 -1
  17. package/dist/research/workspace/analysis-run.d.ts +2 -0
  18. package/dist/research/workspace/analysis-run.js +28 -0
  19. package/dist/research/workspace/analysis-run.js.map +1 -0
  20. package/dist/research/workspace/artifact-read-audit.d.ts +16 -0
  21. package/dist/research/workspace/artifact-read-audit.js +176 -0
  22. package/dist/research/workspace/artifact-read-audit.js.map +1 -0
  23. package/dist/research/workspace/artifact-trace.d.ts +12 -0
  24. package/dist/research/workspace/artifact-trace.js +109 -0
  25. package/dist/research/workspace/artifact-trace.js.map +1 -0
  26. package/dist/research/workspace/artifact-view-mcp.d.ts +75 -0
  27. package/dist/research/workspace/artifact-view-mcp.js +214 -0
  28. package/dist/research/workspace/artifact-view-mcp.js.map +1 -0
  29. package/dist/research/workspace/artifact-views.d.ts +100 -0
  30. package/dist/research/workspace/artifact-views.js +395 -0
  31. package/dist/research/workspace/artifact-views.js.map +1 -0
  32. package/dist/research/workspace/artifacts.d.ts +3 -0
  33. package/dist/research/workspace/artifacts.js +13 -0
  34. package/dist/research/workspace/artifacts.js.map +1 -1
  35. package/dist/research/workspace/audit-bundle.d.ts +9 -0
  36. package/dist/research/workspace/audit-bundle.js +124 -8
  37. package/dist/research/workspace/audit-bundle.js.map +1 -1
  38. package/dist/research/workspace/content-evidence.d.ts +3 -0
  39. package/dist/research/workspace/content-evidence.js +149 -22
  40. package/dist/research/workspace/content-evidence.js.map +1 -1
  41. package/dist/research/workspace/executor.d.ts +5 -1
  42. package/dist/research/workspace/executor.js +106 -22
  43. package/dist/research/workspace/executor.js.map +1 -1
  44. package/dist/research/workspace/native-run.d.ts +77 -0
  45. package/dist/research/workspace/native-run.js +637 -0
  46. package/dist/research/workspace/native-run.js.map +1 -0
  47. package/dist/research/workspace/preflight.d.ts +8 -2
  48. package/dist/research/workspace/preflight.js +17 -14
  49. package/dist/research/workspace/preflight.js.map +1 -1
  50. package/dist/research/workspace/project-authority.d.ts +21 -0
  51. package/dist/research/workspace/project-authority.js +186 -0
  52. package/dist/research/workspace/project-authority.js.map +1 -0
  53. package/dist/research/workspace/project-mutations.d.ts +26 -0
  54. package/dist/research/workspace/project-mutations.js +332 -0
  55. package/dist/research/workspace/project-mutations.js.map +1 -0
  56. package/dist/research/workspace/projects.d.ts +2 -1
  57. package/dist/research/workspace/projects.js +133 -91
  58. package/dist/research/workspace/projects.js.map +1 -1
  59. package/dist/research/workspace/publication-workflow.d.ts +3 -0
  60. package/dist/research/workspace/publication-workflow.js +15 -3
  61. package/dist/research/workspace/publication-workflow.js.map +1 -1
  62. package/dist/research/workspace/request-provenance.d.ts +67 -0
  63. package/dist/research/workspace/request-provenance.js +115 -0
  64. package/dist/research/workspace/request-provenance.js.map +1 -0
  65. package/dist/research/workspace/review-executor.js +22 -11
  66. package/dist/research/workspace/review-executor.js.map +1 -1
  67. package/dist/research/workspace/runtime.d.ts +57 -0
  68. package/dist/research/workspace/runtime.js +292 -140
  69. package/dist/research/workspace/runtime.js.map +1 -1
  70. package/dist/research/workspace/sanitization.js +1 -1
  71. package/dist/research/workspace/sanitization.js.map +1 -1
  72. package/dist/research/workspace/schema-compatibility.d.ts +5 -0
  73. package/dist/research/workspace/schema-compatibility.js +55 -0
  74. package/dist/research/workspace/schema-compatibility.js.map +1 -0
  75. package/dist/research/workspace/schemas.d.ts +6 -0
  76. package/dist/research/workspace/schemas.js +13 -2
  77. package/dist/research/workspace/schemas.js.map +1 -1
  78. package/dist/research/workspace/scientific-design.js +8 -17
  79. package/dist/research/workspace/scientific-design.js.map +1 -1
  80. package/dist/research/workspace/scientific-fulfillment-audit.d.ts +3 -0
  81. package/dist/research/workspace/scientific-fulfillment-audit.js +137 -0
  82. package/dist/research/workspace/scientific-fulfillment-audit.js.map +1 -0
  83. package/dist/research/workspace/scientific-fulfillment.d.ts +121 -0
  84. package/dist/research/workspace/scientific-fulfillment.js +539 -0
  85. package/dist/research/workspace/scientific-fulfillment.js.map +1 -0
  86. package/dist/research/workspace/scientific-review-execution.js +84 -61
  87. package/dist/research/workspace/scientific-review-execution.js.map +1 -1
  88. package/dist/research/workspace/scientific-review.d.ts +8 -2
  89. package/dist/research/workspace/scientific-review.js +205 -53
  90. package/dist/research/workspace/scientific-review.js.map +1 -1
  91. package/dist/research/workspace/setup-catalog.js +2 -2
  92. package/dist/research/workspace/task-acceptance.d.ts +134 -0
  93. package/dist/research/workspace/task-acceptance.js +544 -0
  94. package/dist/research/workspace/task-acceptance.js.map +1 -0
  95. package/dist/research/workspace/task-audit.d.ts +12 -0
  96. package/dist/research/workspace/task-audit.js +231 -0
  97. package/dist/research/workspace/task-audit.js.map +1 -0
  98. package/dist/research/workspace/task-contract.d.ts +142 -0
  99. package/dist/research/workspace/task-contract.js +506 -0
  100. package/dist/research/workspace/task-contract.js.map +1 -0
  101. package/dist/research/workspace/types.d.ts +6 -3
  102. package/dist/research/workspace/workspace.js +11 -8
  103. package/dist/research/workspace/workspace.js.map +1 -1
  104. package/package.json +1 -1
@@ -1,6 +1,7 @@
1
1
  import { lstat, readFile } from "node:fs/promises";
2
2
  import { isAbsolute, join, resolve } from "node:path";
3
3
  import { CliError } from "../errors.js";
4
+ import { projectAuthority, projectWithEffectiveAuthority, readProjectAuthorityIndex, } from "./workspace/project-authority.js";
4
5
  import { stringifyJson, write } from "../io.js";
5
6
  import { parseStrictArgs, strictBoolean, strictString } from "../strict-args.js";
6
7
  import { researchSetupHelp, runResearchSetupCommand } from "./setup-command.js";
@@ -9,13 +10,16 @@ import { inspectResearchContext } from "./workspace/context.js";
9
10
  import { packageVersion } from "./workspace/constants.js";
10
11
  import { researchDataCredentialIds, setCapabilityCredentialValue, } from "./workspace/credentials.js";
11
12
  import { configureExternalSkillProfile, doctorExternalCapabilities, EXTERNAL_SKILL_CONTEXT_PROFILE, EXTERNAL_SKILL_MEDIA_PROFILE, EXTERNAL_SKILL_PROFILE, importExternalCapability, inspectExternalSkillCatalog, } from "./workspace/external-skills.js";
12
- import { appendJournalEvent, readJournal } from "./workspace/journal.js";
13
+ import { appendJournalEvent } from "./workspace/journal.js";
13
14
  import { fetchNativeCandidateSource } from "./workspace/broker.js";
14
15
  import { preflightEvidenceArtifact, registerEvidenceArtifact } from "./workspace/artifacts.js";
15
16
  import { executeResearchDataCapability } from "./workspace/data-evidence-adapter.js";
16
17
  import { exportProjectAuditBundle, verifyProjectAuditBundle } from "./workspace/audit-bundle.js";
17
18
  import { loadCurrentEvidenceSnapshot } from "./workspace/acquisition.js";
18
19
  import { inspectAcquisitionForecast } from "./workspace/acquisition-forecast.js";
20
+ import { reviseProjectAcquisition } from "./workspace/acquisition-revision.js";
21
+ import { approveProjectTaskScope, defineProjectTask, isTaskSchemaName, proposeProjectTaskScope, taskInputSchema, } from "./workspace/task-contract.js";
22
+ import { inspectProjectTask, recordProjectTaskAcceptance, taskAcceptanceInputSchema, } from "./workspace/task-acceptance.js";
19
23
  import { freezeEvidenceContentSnapshot, loadCurrentEvidenceContentSnapshot, recordArtifactDecomposition, registerEvidenceAtom, registerEvidenceContentBatch, } from "./workspace/content-evidence.js";
20
24
  import { inspectDiscoveryProgress } from "./workspace/discovery-status.js";
21
25
  import { EVIDENCE_CONTENT_LIMITS, EVIDENCE_CONTENT_SCHEMA_NAMES, evidenceContentInputSchema, isEvidenceContentSchemaName, } from "./workspace/evidence-content-schema.js";
@@ -27,16 +31,19 @@ import { recordNativeResearchActivity } from "./workspace/native-activity.js";
27
31
  import { inspectReviewerStatus, startReviewerBridgeSidecar } from "./workspace/review-executor.js";
28
32
  import { readAndVerifyProjectInputPlan } from "./workspace/input-plan.js";
29
33
  import { executeScientificReview } from "./workspace/scientific-review-execution.js";
34
+ import { claudeCodeCompatibleSchema } from "./workspace/schema-compatibility.js";
30
35
  import { loadCurrentClaimEvidenceGraph, loadCurrentInferenceSnapshot, } from "./workspace/inference.js";
31
36
  import { addProjectInput, createProjectAddendum, initializeProject, forkProject, listProjects, loadProject, nextReadyPackage, normalizeEvidenceRequirements, refreshProject, retryProjectPackage, setProjectDisposition, scientificGateRecommendedAction, } from "./workspace/projects.js";
32
37
  import { evaluateProjectPreflight } from "./workspace/preflight.js";
33
38
  import { closePublication, freezePublicationManuscript, inspectPublicationStatus, preparePublicationReview, publicationAssessmentSchema, publicationReviewSchema, submitPublicationReview, } from "./workspace/publication-workflow.js";
34
39
  import { approveResearchPolicy, initializeResearchPolicy, inspectResearchPolicyCatalog, inspectResearchPolicyStatus, loadApprovedResearchPolicy, } from "./workspace/research-policy.js";
35
40
  import { resolveInstalledResearchPolicySource, runInteractiveResearchPolicyWizard, } from "./workspace/research-policy-wizard.js";
36
- import { abortNativeResearchStage, inspectNativeResearchStage, prepareNativeResearchStage, requestResearchHandoff, resolveResearchHandoff, runResearchWorkspace, submitNativeResearchStage, } from "./workspace/runtime.js";
41
+ import { abortNativeResearchStage, inspectNativeResearchStage, prepareNativeResearchStage, readNativeStageArtifact, requestResearchHandoff, resolveResearchHandoff, runResearchWorkspace, submitNativeResearchStage, } from "./workspace/runtime.js";
37
42
  import { schemaForStage } from "./workspace/schemas.js";
38
43
  import { readAndVerifyScientificDesign, scientificDesignSchema, } from "./workspace/scientific-design.js";
39
44
  import { inspectScientificObject, parseScientificObjectKind, registerScientificObject, } from "./workspace/scientific-objects.js";
45
+ import { inspectScientificFulfillment, recordScientificFulfillment, scientificFulfillmentSchema, } from "./workspace/scientific-fulfillment.js";
46
+ import { inspectNativeRun, nativeRunInputSchema, observeNativeRun, } from "./workspace/native-run.js";
40
47
  import { inspectScientificReviewStatus, prepareScientificReview, scientificGateAssessmentSchema, scientificReviewSchema, submitScientificReview, } from "./workspace/scientific-review.js";
41
48
  import { isObject, pathExists, sha256Text, workspacePaths } from "./workspace/storage.js";
42
49
  import { doctorResearchWorkspace, initializeResearchWorkspace, loadWorkspaceConfig, requireResearchWorkspace, withWorkspaceLock, } from "./workspace/workspace.js";
@@ -100,10 +107,19 @@ export function researchOrchestrationHelp() {
100
107
  tiangong-ai research publication close <project-id> [--workspace <path>] [--json]
101
108
  tiangong-ai research scientific object register --kind model-implementation|environment-lock --path <absolute-file> [--media-type <type>] [--workspace <path>] [--json]
102
109
  tiangong-ai research scientific object inspect --kind model-implementation|environment-lock --locator <control-relative-locator> [--workspace <path>] [--json]
110
+ tiangong-ai research scientific fulfillment record <project> --input <json-file> [--workspace <path>] [--json]
111
+ tiangong-ai research scientific fulfillment status <project> [--workspace <path>] [--json]
112
+ tiangong-ai research project task run observe <project> --input <json-file> --confirm-execution [--workspace <path>] [--json]
113
+ tiangong-ai research project task run inspect <project> --run <run-id> [--workspace <path>] [--json]
103
114
  tiangong-ai research project init <project-id> --question <question> [--goal evidence-report|top-journal] [--design <absolute-json> --design-producer-agent codex|claude --design-producer-session <opaque-id>] [--requirements <absolute-json>] [--input-plan <absolute-json>] [--confirm-budget] [--workspace <path>] [--json]
104
115
  tiangong-ai research project preflight --question <question> [--goal evidence-report|top-journal] [--policy-project <project-id> --design <absolute-json>] [--requirements <absolute-json>] [--input-plan <absolute-json>] [--workspace <path>] [--json]
105
116
  tiangong-ai research project input add <project-id> --path <absolute-file> [--role primary|reference|replication] [--trust-status verified-owner-input|unverified-owner-input|reference-only|replication-candidate] [--independently-reproduced] [--workspace <path>] [--json]
106
117
  tiangong-ai research project retry <project-id> [--package <package-id>] [--workspace <path>] [--json]
118
+ tiangong-ai research project task define <project-id> --input <absolute-json> [--workspace <path>] [--json]
119
+ tiangong-ai research project task status <project-id> [--workspace <path>] [--json]
120
+ tiangong-ai research project task acceptance record <project-id> --input <absolute-json> [--workspace <path>] [--json]
121
+ tiangong-ai research project task scope propose <project-id> --input <absolute-json> --expected-contract <sha256> [--workspace <path>] [--json]
122
+ tiangong-ai research project task scope approve <project-id> --proposal <sha256> --confirm-change <sha256> [--workspace <path>] [--json]
107
123
  tiangong-ai research project fork <source-project-id> --to <target-project-id> [--resume-through discover|acquire|analyze|synthesize] [--design <absolute-json> --design-producer-agent codex|claude --design-producer-session <opaque-id>] [--workspace <path>] [--json]
108
124
  tiangong-ai research project addendum <closed-project-id> --to <target-project-id> [--design <absolute-json> --design-producer-agent codex|claude --design-producer-session <opaque-id>] [--workspace <path>] [--json]
109
125
  tiangong-ai research project archive <project-id> --reason <text> [--workspace <path>] [--json]
@@ -120,6 +136,8 @@ export function researchOrchestrationHelp() {
120
136
  tiangong-ai research project stage prepare <project-id> --stage discover|acquire|analyze|synthesize --host-agent codex|claude|workbuddy|codebuddy [--workspace <path>] [--json]
121
137
  tiangong-ai research project stage submit <project-id> --session <id> --output <absolute-json> [--confirm-model <id>] [--workspace <path>] [--json]
122
138
  tiangong-ai research project stage abort <project-id> --session <id> [--workspace <path>] [--json]
139
+ tiangong-ai research project stage artifacts <project-id> --session <id> [--offset <n>] [--limit <n>] [--path-prefix <prefix>] [--workspace <path>] [--json]
140
+ tiangong-ai research project stage read <project-id> --session <id> --artifact <object-id> [--offset <bytes>] [--length <bytes|all>] [--encoding utf8|base64] [--workspace <path>] [--json]
123
141
  tiangong-ai research project evidence fetch <project-id> --request <absolute-json> [--workspace <path>] [--json]
124
142
  tiangong-ai research project evidence data run <project-id> --request <absolute-data-run-request.json> [--workspace <path>] [--json]
125
143
  tiangong-ai research project evidence activity record <project-id> --record <absolute-json> [--workspace <path>] [--json]
@@ -134,8 +152,9 @@ export function researchOrchestrationHelp() {
134
152
  tiangong-ai research project evidence atom register <project-id> --record <absolute-json> [--workspace <path>] [--json]
135
153
  tiangong-ai research project evidence content freeze <project-id> [--workspace <path>] [--json]
136
154
  tiangong-ai research project evidence content forecast <project-id> --input <absolute-acquisition-audit.json> [--workspace <path>] [--json]
155
+ tiangong-ai research project evidence acquisition revise <project-id> --expected-snapshot <sha256> --reason <text> [--include-discovery] [--workspace <path>] [--json]
137
156
  tiangong-ai research project evidence content status <project-id> [--workspace <path>] [--json]
138
- tiangong-ai research schema show <discover|acquire|analyze|synthesize|review|doctor|scientific-design|scientific-assessment-research-design|scientific-assessment-evidence-construct|scientific-assessment-pilot-methods|scientific-review-research-design|scientific-review-evidence-construct|scientific-review-pilot-methods|publication-assessment|publication-review-evidence|publication-review-methods-reproducibility|publication-review-domain-novelty|publication-review-journal-editor> [--compatibility claude-code] [--json]
157
+ tiangong-ai research schema show <discover|acquire|analyze|synthesize|review|doctor|task-contract|task-scope-change|task-acceptance|scientific-design|scientific-assessment-research-design|scientific-assessment-evidence-construct|scientific-assessment-pilot-methods|scientific-review-research-design|scientific-review-evidence-construct|scientific-review-pilot-methods|publication-assessment|publication-review-evidence|publication-review-methods-reproducibility|publication-review-domain-novelty|publication-review-journal-editor> [--compatibility claude-code] [--json]
139
158
  tiangong-ai research status [--project <project-id>] [--all] [--workspace <absolute-path>] [--json]
140
159
  tiangong-ai research run [--project <project-id>] [--max-parallel <1-8>] [--max-cycles <1-100>] [--dry-run] [--progress-jsonl] [--workspace <absolute-path>] [--json]
141
160
 
@@ -150,6 +169,28 @@ async function runScientific(argv, io) {
150
169
  const [action, ...rest] = argv;
151
170
  if (!action || action === "--help" || action === "-h")
152
171
  return writeHelp(io);
172
+ if (action === "fulfillment") {
173
+ const [operation, ...arguments_] = rest;
174
+ if (operation !== "record" && operation !== "status")
175
+ throw unknownAction("research scientific fulfillment", operation ?? "");
176
+ const args = parseStrictArgs(arguments_, { ...WORKSPACE_OPTIONS, ...(operation === "record" ? { input: "string" } : {}) }, `research scientific fulfillment ${operation}`);
177
+ if (strictBoolean(args, "help"))
178
+ return writeHelp(io);
179
+ const projectId = onePositional(args.positionals, `research scientific fulfillment ${operation}`);
180
+ const root = await workspaceFromArgs(args);
181
+ if (operation === "status")
182
+ writeJson(io, await inspectScientificFulfillment(root, projectId), args);
183
+ else {
184
+ const path = strictString(args, "input");
185
+ if (!path)
186
+ throw new CliError("Fulfillment record requires --input.", {
187
+ code: "RESEARCH_SCIENTIFIC_FULFILLMENT_INVALID",
188
+ exitCode: 2,
189
+ });
190
+ writeJson(io, await recordScientificFulfillment(root, projectId, await readBoundedJsonRecord(path, "--input", "RESEARCH_SCIENTIFIC_FULFILLMENT_INVALID")), args);
191
+ }
192
+ return 0;
193
+ }
153
194
  if (action !== "object")
154
195
  throw unknownAction("research scientific", action);
155
196
  const [objectAction, ...objectRest] = rest;
@@ -506,12 +547,24 @@ async function runSchema(argv, io) {
506
547
  return writeHelp(io);
507
548
  const stage = onePositional(args.positionals, "research schema show");
508
549
  let schema;
509
- if (isEvidenceContentSchemaName(stage)) {
550
+ if (stage === "task-acceptance") {
551
+ schema = taskAcceptanceInputSchema();
552
+ }
553
+ else if (stage === "task-native-run") {
554
+ schema = nativeRunInputSchema();
555
+ }
556
+ else if (isTaskSchemaName(stage)) {
557
+ schema = taskInputSchema(stage);
558
+ }
559
+ else if (isEvidenceContentSchemaName(stage)) {
510
560
  schema = evidenceContentInputSchema(stage);
511
561
  }
512
562
  else if (stage === "scientific-design") {
513
563
  schema = scientificDesignSchema();
514
564
  }
565
+ else if (stage === "scientific-fulfillment") {
566
+ schema = scientificFulfillmentSchema();
567
+ }
515
568
  else if (stage.startsWith("scientific-assessment-")) {
516
569
  const role = scientificReviewRole(stage.slice("scientific-assessment-".length));
517
570
  schema = scientificGateAssessmentSchema(role);
@@ -554,23 +607,7 @@ function compatibleSchema(schema, compatibility) {
554
607
  details: { supported: ["claude-code"] },
555
608
  });
556
609
  }
557
- const compatible = structuredClone(schema);
558
- const stripMetadata = (value) => {
559
- if (Array.isArray(value)) {
560
- for (const item of value)
561
- stripMetadata(item);
562
- return;
563
- }
564
- if (!value || typeof value !== "object")
565
- return;
566
- const record = value;
567
- delete record.$schema;
568
- delete record.$id;
569
- for (const item of Object.values(record))
570
- stripMetadata(item);
571
- };
572
- stripMetadata(compatible);
573
- return compatible;
610
+ return claudeCodeCompatibleSchema(schema);
574
611
  }
575
612
  async function runContext(argv, io) {
576
613
  const [action, ...rest] = argv;
@@ -965,6 +1002,60 @@ async function runProject(argv, io) {
965
1002
  }
966
1003
  if (action === "stage") {
967
1004
  const [stageAction, ...stageRest] = rest;
1005
+ if (stageAction === "artifacts" || stageAction === "read") {
1006
+ const args = parseStrictArgs(stageRest, {
1007
+ ...WORKSPACE_OPTIONS,
1008
+ session: "string",
1009
+ artifact: "string",
1010
+ offset: "string",
1011
+ limit: "string",
1012
+ length: "string",
1013
+ encoding: "string",
1014
+ "path-prefix": "string",
1015
+ }, `research project stage ${stageAction}`);
1016
+ if (strictBoolean(args, "help"))
1017
+ return writeHelp(io);
1018
+ const sessionId = strictString(args, "session");
1019
+ const objectId = strictString(args, "artifact");
1020
+ if (!sessionId || (stageAction === "read" && !objectId))
1021
+ throw new CliError("Stage artifact reads require --session and an exact --artifact for read.", { code: "RESEARCH_NATIVE_STAGE_SESSION_REQUIRED", exitCode: 3 });
1022
+ const offset = strictString(args, "offset");
1023
+ const limit = strictString(args, "limit");
1024
+ const length = strictString(args, "length");
1025
+ const encoding = strictString(args, "encoding");
1026
+ if (encoding && encoding !== "utf8" && encoding !== "base64")
1027
+ throw new CliError("Artifact encoding must be utf8 or base64.", {
1028
+ code: "RESEARCH_ARTIFACT_VIEW_INVALID",
1029
+ exitCode: 3,
1030
+ });
1031
+ const projectId = onePositional(args.positionals, `research project stage ${stageAction}`);
1032
+ writeJson(io, await readNativeStageArtifact({
1033
+ root: await workspaceFromArgs(args),
1034
+ projectId,
1035
+ sessionId,
1036
+ ...(stageAction === "read"
1037
+ ? {
1038
+ selection: {
1039
+ objectId: objectId,
1040
+ ...(offset === undefined ? {} : { offset: Number(offset) }),
1041
+ ...(length === undefined
1042
+ ? {}
1043
+ : { length: length === "all" ? null : Number(length) }),
1044
+ ...(encoding ? { encoding: encoding } : {}),
1045
+ },
1046
+ }
1047
+ : {
1048
+ listing: {
1049
+ ...(offset === undefined ? {} : { offset: Number(offset) }),
1050
+ ...(limit === undefined ? {} : { limit: Number(limit) }),
1051
+ ...(strictString(args, "path-prefix")
1052
+ ? { pathPrefix: strictString(args, "path-prefix") }
1053
+ : {}),
1054
+ },
1055
+ }),
1056
+ }), args);
1057
+ return 0;
1058
+ }
968
1059
  if (stageAction === "prepare") {
969
1060
  const args = parseStrictArgs(stageRest, { ...WORKSPACE_OPTIONS, stage: "string", "host-agent": "string" }, "research project stage prepare");
970
1061
  if (strictBoolean(args, "help"))
@@ -1025,8 +1116,94 @@ async function runProject(argv, io) {
1025
1116
  }
1026
1117
  throw unknownAction("research project stage", stageAction ?? "");
1027
1118
  }
1119
+ if (action === "task") {
1120
+ const [taskAction, ...taskRest] = rest;
1121
+ if (taskAction === "run") {
1122
+ const [runAction, ...runRest] = taskRest;
1123
+ if (runAction !== "observe" && runAction !== "inspect")
1124
+ throw unknownAction("research project task run", runAction ?? "");
1125
+ const args = parseStrictArgs(runRest, { ...WORKSPACE_OPTIONS, input: "string", run: "string", "confirm-execution": "boolean" }, `research project task run ${runAction}`);
1126
+ if (strictBoolean(args, "help"))
1127
+ return writeHelp(io);
1128
+ const projectId = onePositional(args.positionals, `research project task run ${runAction}`);
1129
+ const root = await workspaceFromArgs(args);
1130
+ const result = runAction === "inspect"
1131
+ ? await inspectNativeRun(root, projectId, strictString(args, "run") ?? "")
1132
+ : await observeNativeRun(root, projectId, await readBoundedJsonRecord(strictString(args, "input") ?? "", "--input", "RESEARCH_NATIVE_RUN_INVALID"), strictBoolean(args, "confirm-execution"));
1133
+ writeJson(io, result, args);
1134
+ return "record" in result && result.record && result.record.status !== "succeeded" ? 3 : 0;
1135
+ }
1136
+ if (taskAction === "acceptance") {
1137
+ const [acceptanceAction, ...acceptanceRest] = taskRest;
1138
+ if (acceptanceAction !== "record")
1139
+ throw unknownAction("research project task acceptance", acceptanceAction ?? "");
1140
+ const args = parseStrictArgs(acceptanceRest, { ...WORKSPACE_OPTIONS, input: "string" }, "research project task acceptance record");
1141
+ if (strictBoolean(args, "help"))
1142
+ return writeHelp(io);
1143
+ const projectId = onePositional(args.positionals, "research project task acceptance record");
1144
+ const result = await recordProjectTaskAcceptance(await workspaceFromArgs(args), projectId, await readBoundedJsonRecord(strictString(args, "input") ?? "", "--input", "RESEARCH_TASK_ACCEPTANCE_INVALID"));
1145
+ writeJson(io, result, args);
1146
+ return 0;
1147
+ }
1148
+ if (taskAction === "scope") {
1149
+ const [scopeAction, ...scopeRest] = taskRest;
1150
+ if (!["propose", "approve"].includes(scopeAction ?? ""))
1151
+ throw unknownAction("research project task scope", scopeAction ?? "");
1152
+ const args = parseStrictArgs(scopeRest, {
1153
+ ...WORKSPACE_OPTIONS,
1154
+ input: "string",
1155
+ "expected-contract": "string",
1156
+ proposal: "string",
1157
+ "confirm-change": "string",
1158
+ }, `research project task scope ${scopeAction}`);
1159
+ if (strictBoolean(args, "help"))
1160
+ return writeHelp(io);
1161
+ const projectId = onePositional(args.positionals, `research project task scope ${scopeAction}`);
1162
+ const root = await workspaceFromArgs(args);
1163
+ const result = scopeAction === "approve"
1164
+ ? await approveProjectTaskScope(root, projectId, strictString(args, "proposal") ?? "", strictString(args, "confirm-change"))
1165
+ : await proposeProjectTaskScope(root, projectId, strictString(args, "expected-contract") ?? "", await readBoundedJsonRecord(strictString(args, "input") ?? "", "--input", "RESEARCH_TASK_INVALID"));
1166
+ writeJson(io, result, args);
1167
+ return 0;
1168
+ }
1169
+ if (taskAction !== "define" && taskAction !== "status")
1170
+ throw unknownAction("research project task", taskAction ?? "");
1171
+ const args = parseStrictArgs(taskRest, { ...WORKSPACE_OPTIONS, input: "string" }, `research project task ${taskAction}`);
1172
+ if (strictBoolean(args, "help"))
1173
+ return writeHelp(io);
1174
+ const projectId = onePositional(args.positionals, `research project task ${taskAction}`);
1175
+ const root = await workspaceFromArgs(args);
1176
+ const result = taskAction === "status"
1177
+ ? await inspectProjectTask(root, projectId)
1178
+ : await defineProjectTask(root, projectId, await readBoundedJsonRecord(strictString(args, "input") ?? "", "--input", "RESEARCH_TASK_INVALID"));
1179
+ writeJson(io, result, args);
1180
+ return 0;
1181
+ }
1028
1182
  if (action === "evidence") {
1029
1183
  const [evidenceAction, ...evidenceRest] = rest;
1184
+ if (evidenceAction === "acquisition") {
1185
+ const [revisionAction, ...revisionRest] = evidenceRest;
1186
+ if (revisionAction !== "revise")
1187
+ throw unknownAction("research project evidence acquisition", revisionAction ?? "");
1188
+ const args = parseStrictArgs(revisionRest, {
1189
+ ...WORKSPACE_OPTIONS,
1190
+ "expected-snapshot": "string",
1191
+ reason: "string",
1192
+ "include-discovery": "boolean",
1193
+ }, "research project evidence acquisition revise");
1194
+ if (strictBoolean(args, "help"))
1195
+ return writeHelp(io);
1196
+ const projectId = onePositional(args.positionals, "research project evidence acquisition revise");
1197
+ const result = await reviseProjectAcquisition({
1198
+ root: await workspaceFromArgs(args),
1199
+ projectId,
1200
+ expectedSnapshotSha256: strictString(args, "expected-snapshot") ?? "",
1201
+ reason: strictString(args, "reason") ?? "",
1202
+ includeDiscovery: strictBoolean(args, "include-discovery"),
1203
+ });
1204
+ writeJson(io, result, args);
1205
+ return 0;
1206
+ }
1030
1207
  if (evidenceAction === "data") {
1031
1208
  const [dataAction, ...dataRest] = evidenceRest;
1032
1209
  if (dataAction !== "run") {
@@ -1287,7 +1464,9 @@ async function runProject(argv, io) {
1287
1464
  const value = await readBoundedJsonRecord(inputPath, "--input", "RESEARCH_ACQUISITION_FORECAST_INVALID");
1288
1465
  const result = await inspectAcquisitionForecast(root, projectId, value);
1289
1466
  writeJson(io, result, args);
1290
- return result.acquisitionGate.decision === "pass" && !result.knownRoleDeficits.length
1467
+ return result.submissionGate.decision !== "stop" &&
1468
+ result.acquisitionGate.decision === "pass" &&
1469
+ !result.knownRoleDeficits.length
1291
1470
  ? 0
1292
1471
  : 3;
1293
1472
  }
@@ -1603,12 +1782,8 @@ async function runStatus(argv, io) {
1603
1782
  const root = await workspaceFromArgs(args);
1604
1783
  const config = await loadWorkspaceConfig(root);
1605
1784
  const selectedProject = strictString(args, "project");
1606
- const workspaceProjects = await listProjects(root);
1607
- const committedForkTargets = new Set((await readJournal(workspacePaths(root).journal))
1608
- .filter((event) => event.type === "project.forked" &&
1609
- isObject(event.payload) &&
1610
- typeof event.payload.targetProjectId === "string")
1611
- .map((event) => String(event.payload.targetProjectId)));
1785
+ const authorityIndex = await readProjectAuthorityIndex(root);
1786
+ const workspaceProjects = await listProjects(root, authorityIndex);
1612
1787
  const allProjects = selectedProject
1613
1788
  ? [
1614
1789
  workspaceProjects.find((project) => project.id === selectedProject) ??
@@ -1617,9 +1792,7 @@ async function runStatus(argv, io) {
1617
1792
  : workspaceProjects;
1618
1793
  const projects = selectedProject || strictBoolean(args, "all")
1619
1794
  ? allProjects
1620
- : allProjects.filter((project) => project.lineage.supersededBy === null &&
1621
- project.status !== "archived" &&
1622
- project.status !== "abandoned");
1795
+ : allProjects.filter((project) => ["authoritative", "invalid"].includes(projectAuthority(project, authorityIndex).state));
1623
1796
  const result = {
1624
1797
  workspace: root,
1625
1798
  execution: {
@@ -1638,7 +1811,7 @@ async function runStatus(argv, io) {
1638
1811
  },
1639
1812
  hiddenSupersededProjects: selectedProject || strictBoolean(args, "all")
1640
1813
  ? 0
1641
- : workspaceProjects.filter((project) => project.lineage.supersededBy !== null).length,
1814
+ : workspaceProjects.filter((project) => authorityIndex.successors.has(project.id)).length,
1642
1815
  hiddenArchivedProjects: selectedProject || strictBoolean(args, "all")
1643
1816
  ? 0
1644
1817
  : workspaceProjects.filter((project) => project.status === "archived").length,
@@ -1646,13 +1819,13 @@ async function runStatus(argv, io) {
1646
1819
  ? 0
1647
1820
  : workspaceProjects.filter((project) => project.status === "abandoned").length,
1648
1821
  projects: await Promise.all(projects.map(async (project) => {
1649
- const current = refreshProject(project);
1650
- const authority = projectAuthority(current, workspaceProjects, committedForkTargets);
1822
+ const current = refreshProject(projectWithEffectiveAuthority(project, authorityIndex));
1823
+ const authority = projectAuthority(current, authorityIndex);
1651
1824
  const nativeStage = await inspectNativeResearchStage(root, current);
1652
1825
  const evidencePipeline = await inspectEvidencePipelineForStatus(root, current);
1653
1826
  const snapshot = evidencePipeline.acquisition;
1654
1827
  const readyPackage = nextReadyPackage(current)?.id ?? null;
1655
- const scientificReview = await inspectScientificReviewStatus(root, current.id);
1828
+ const scientificReview = await inspectScientificReviewStatus(root, current.id, current);
1656
1829
  const evidenceAccess = current.scientificDesign
1657
1830
  ? await inspectEvidenceAccessForStatus(root, current.id)
1658
1831
  : null;
@@ -1671,6 +1844,7 @@ async function runStatus(argv, io) {
1671
1844
  evidencePipeline,
1672
1845
  nativeStage,
1673
1846
  scientificReview,
1847
+ task: await inspectProjectTask(root, current.id, authorityIndex.taskEvents.get(current.id) ?? []),
1674
1848
  evidenceAccess,
1675
1849
  publication,
1676
1850
  readyPackage,
@@ -1786,33 +1960,6 @@ async function inspectEvidenceAccessForStatus(root, projectId) {
1786
1960
  };
1787
1961
  }
1788
1962
  }
1789
- function projectAuthority(project, projects, committedForkTargets) {
1790
- if (project.lineage.kind === "fork" && !committedForkTargets.has(project.id)) {
1791
- return { state: "invalid", projectId: project.id };
1792
- }
1793
- const byId = new Map(projects.map((candidate) => [candidate.id, candidate]));
1794
- const visited = new Set([project.id]);
1795
- let current = project;
1796
- while (current.lineage.supersededBy) {
1797
- if (visited.has(current.lineage.supersededBy))
1798
- break;
1799
- visited.add(current.lineage.supersededBy);
1800
- const next = byId.get(current.lineage.supersededBy);
1801
- if (!next)
1802
- return { state: "superseded", projectId: current.lineage.supersededBy };
1803
- if (next.lineage.kind === "fork" && !committedForkTargets.has(next.id))
1804
- break;
1805
- current = next;
1806
- }
1807
- if (project.status === "archived")
1808
- return { state: "archived", projectId: current.id };
1809
- if (project.status === "abandoned")
1810
- return { state: "abandoned", projectId: current.id };
1811
- return {
1812
- state: project.id === current.id ? "authoritative" : "superseded",
1813
- projectId: current.id,
1814
- };
1815
- }
1816
1963
  async function inspectSnapshotForStatus(root, projectId) {
1817
1964
  const currentPath = join(workspacePaths(root).projects, projectId, "outputs", "evidence-snapshot.json");
1818
1965
  if (!(await pathExists(currentPath)))