@tiangong-ai/cli 0.0.58 → 0.0.60

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 (64) hide show
  1. package/AGENTS.md +8 -2
  2. package/CONTRIBUTING.md +79 -0
  3. package/README.md +136 -21
  4. package/dist/cli.js +5 -0
  5. package/dist/cli.js.map +1 -1
  6. package/dist/research/orchestration.js +101 -44
  7. package/dist/research/orchestration.js.map +1 -1
  8. package/dist/research/workspace/acquisition-forecast.d.ts +3 -0
  9. package/dist/research/workspace/acquisition-forecast.js +28 -3
  10. package/dist/research/workspace/acquisition-forecast.js.map +1 -1
  11. package/dist/research/workspace/acquisition-revision.d.ts +13 -0
  12. package/dist/research/workspace/acquisition-revision.js +142 -0
  13. package/dist/research/workspace/acquisition-revision.js.map +1 -0
  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/artifacts.d.ts +3 -0
  21. package/dist/research/workspace/artifacts.js +13 -0
  22. package/dist/research/workspace/artifacts.js.map +1 -1
  23. package/dist/research/workspace/audit-bundle.d.ts +5 -0
  24. package/dist/research/workspace/audit-bundle.js +17 -0
  25. package/dist/research/workspace/audit-bundle.js.map +1 -1
  26. package/dist/research/workspace/content-evidence.d.ts +3 -0
  27. package/dist/research/workspace/content-evidence.js +149 -22
  28. package/dist/research/workspace/content-evidence.js.map +1 -1
  29. package/dist/research/workspace/project-authority.d.ts +21 -0
  30. package/dist/research/workspace/project-authority.js +186 -0
  31. package/dist/research/workspace/project-authority.js.map +1 -0
  32. package/dist/research/workspace/project-mutations.d.ts +26 -0
  33. package/dist/research/workspace/project-mutations.js +330 -0
  34. package/dist/research/workspace/project-mutations.js.map +1 -0
  35. package/dist/research/workspace/projects.d.ts +2 -1
  36. package/dist/research/workspace/projects.js +132 -91
  37. package/dist/research/workspace/projects.js.map +1 -1
  38. package/dist/research/workspace/publication-workflow.d.ts +3 -0
  39. package/dist/research/workspace/publication-workflow.js +15 -3
  40. package/dist/research/workspace/publication-workflow.js.map +1 -1
  41. package/dist/research/workspace/runtime.d.ts +5 -0
  42. package/dist/research/workspace/runtime.js +83 -54
  43. package/dist/research/workspace/runtime.js.map +1 -1
  44. package/dist/research/workspace/schemas.d.ts +6 -0
  45. package/dist/research/workspace/schemas.js +13 -2
  46. package/dist/research/workspace/schemas.js.map +1 -1
  47. package/dist/research/workspace/scientific-review-execution.js +2 -0
  48. package/dist/research/workspace/scientific-review-execution.js.map +1 -1
  49. package/dist/research/workspace/scientific-review.d.ts +3 -1
  50. package/dist/research/workspace/scientific-review.js +9 -2
  51. package/dist/research/workspace/scientific-review.js.map +1 -1
  52. package/dist/research/workspace/setup-catalog.js +3 -3
  53. package/dist/research/workspace/task-acceptance.d.ts +126 -0
  54. package/dist/research/workspace/task-acceptance.js +480 -0
  55. package/dist/research/workspace/task-acceptance.js.map +1 -0
  56. package/dist/research/workspace/task-audit.d.ts +12 -0
  57. package/dist/research/workspace/task-audit.js +181 -0
  58. package/dist/research/workspace/task-audit.js.map +1 -0
  59. package/dist/research/workspace/task-contract.d.ts +139 -0
  60. package/dist/research/workspace/task-contract.js +485 -0
  61. package/dist/research/workspace/task-contract.js.map +1 -0
  62. package/dist/research/workspace/workspace.js +11 -8
  63. package/dist/research/workspace/workspace.js.map +1 -1
  64. package/package.json +2 -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";
@@ -104,6 +108,11 @@ export function researchOrchestrationHelp() {
104
108
  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
109
  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
110
  tiangong-ai research project retry <project-id> [--package <package-id>] [--workspace <path>] [--json]
111
+ tiangong-ai research project task define <project-id> --input <absolute-json> [--workspace <path>] [--json]
112
+ tiangong-ai research project task status <project-id> [--workspace <path>] [--json]
113
+ tiangong-ai research project task acceptance record <project-id> --input <absolute-json> [--workspace <path>] [--json]
114
+ tiangong-ai research project task scope propose <project-id> --input <absolute-json> --expected-contract <sha256> [--workspace <path>] [--json]
115
+ tiangong-ai research project task scope approve <project-id> --proposal <sha256> --confirm-change <sha256> [--workspace <path>] [--json]
107
116
  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
117
  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
118
  tiangong-ai research project archive <project-id> --reason <text> [--workspace <path>] [--json]
@@ -134,8 +143,9 @@ export function researchOrchestrationHelp() {
134
143
  tiangong-ai research project evidence atom register <project-id> --record <absolute-json> [--workspace <path>] [--json]
135
144
  tiangong-ai research project evidence content freeze <project-id> [--workspace <path>] [--json]
136
145
  tiangong-ai research project evidence content forecast <project-id> --input <absolute-acquisition-audit.json> [--workspace <path>] [--json]
146
+ tiangong-ai research project evidence acquisition revise <project-id> --expected-snapshot <sha256> --reason <text> [--include-discovery] [--workspace <path>] [--json]
137
147
  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]
148
+ 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
149
  tiangong-ai research status [--project <project-id>] [--all] [--workspace <absolute-path>] [--json]
140
150
  tiangong-ai research run [--project <project-id>] [--max-parallel <1-8>] [--max-cycles <1-100>] [--dry-run] [--progress-jsonl] [--workspace <absolute-path>] [--json]
141
151
 
@@ -506,7 +516,13 @@ async function runSchema(argv, io) {
506
516
  return writeHelp(io);
507
517
  const stage = onePositional(args.positionals, "research schema show");
508
518
  let schema;
509
- if (isEvidenceContentSchemaName(stage)) {
519
+ if (stage === "task-acceptance") {
520
+ schema = taskAcceptanceInputSchema();
521
+ }
522
+ else if (isTaskSchemaName(stage)) {
523
+ schema = taskInputSchema(stage);
524
+ }
525
+ else if (isEvidenceContentSchemaName(stage)) {
510
526
  schema = evidenceContentInputSchema(stage);
511
527
  }
512
528
  else if (stage === "scientific-design") {
@@ -1025,8 +1041,79 @@ async function runProject(argv, io) {
1025
1041
  }
1026
1042
  throw unknownAction("research project stage", stageAction ?? "");
1027
1043
  }
1044
+ if (action === "task") {
1045
+ const [taskAction, ...taskRest] = rest;
1046
+ if (taskAction === "acceptance") {
1047
+ const [acceptanceAction, ...acceptanceRest] = taskRest;
1048
+ if (acceptanceAction !== "record")
1049
+ throw unknownAction("research project task acceptance", acceptanceAction ?? "");
1050
+ const args = parseStrictArgs(acceptanceRest, { ...WORKSPACE_OPTIONS, input: "string" }, "research project task acceptance record");
1051
+ if (strictBoolean(args, "help"))
1052
+ return writeHelp(io);
1053
+ const projectId = onePositional(args.positionals, "research project task acceptance record");
1054
+ const result = await recordProjectTaskAcceptance(await workspaceFromArgs(args), projectId, await readBoundedJsonRecord(strictString(args, "input") ?? "", "--input", "RESEARCH_TASK_ACCEPTANCE_INVALID"));
1055
+ writeJson(io, result, args);
1056
+ return 0;
1057
+ }
1058
+ if (taskAction === "scope") {
1059
+ const [scopeAction, ...scopeRest] = taskRest;
1060
+ if (!["propose", "approve"].includes(scopeAction ?? ""))
1061
+ throw unknownAction("research project task scope", scopeAction ?? "");
1062
+ const args = parseStrictArgs(scopeRest, {
1063
+ ...WORKSPACE_OPTIONS,
1064
+ input: "string",
1065
+ "expected-contract": "string",
1066
+ proposal: "string",
1067
+ "confirm-change": "string",
1068
+ }, `research project task scope ${scopeAction}`);
1069
+ if (strictBoolean(args, "help"))
1070
+ return writeHelp(io);
1071
+ const projectId = onePositional(args.positionals, `research project task scope ${scopeAction}`);
1072
+ const root = await workspaceFromArgs(args);
1073
+ const result = scopeAction === "approve"
1074
+ ? await approveProjectTaskScope(root, projectId, strictString(args, "proposal") ?? "", strictString(args, "confirm-change"))
1075
+ : await proposeProjectTaskScope(root, projectId, strictString(args, "expected-contract") ?? "", await readBoundedJsonRecord(strictString(args, "input") ?? "", "--input", "RESEARCH_TASK_INVALID"));
1076
+ writeJson(io, result, args);
1077
+ return 0;
1078
+ }
1079
+ if (taskAction !== "define" && taskAction !== "status")
1080
+ throw unknownAction("research project task", taskAction ?? "");
1081
+ const args = parseStrictArgs(taskRest, { ...WORKSPACE_OPTIONS, input: "string" }, `research project task ${taskAction}`);
1082
+ if (strictBoolean(args, "help"))
1083
+ return writeHelp(io);
1084
+ const projectId = onePositional(args.positionals, `research project task ${taskAction}`);
1085
+ const root = await workspaceFromArgs(args);
1086
+ const result = taskAction === "status"
1087
+ ? await inspectProjectTask(root, projectId)
1088
+ : await defineProjectTask(root, projectId, await readBoundedJsonRecord(strictString(args, "input") ?? "", "--input", "RESEARCH_TASK_INVALID"));
1089
+ writeJson(io, result, args);
1090
+ return 0;
1091
+ }
1028
1092
  if (action === "evidence") {
1029
1093
  const [evidenceAction, ...evidenceRest] = rest;
1094
+ if (evidenceAction === "acquisition") {
1095
+ const [revisionAction, ...revisionRest] = evidenceRest;
1096
+ if (revisionAction !== "revise")
1097
+ throw unknownAction("research project evidence acquisition", revisionAction ?? "");
1098
+ const args = parseStrictArgs(revisionRest, {
1099
+ ...WORKSPACE_OPTIONS,
1100
+ "expected-snapshot": "string",
1101
+ reason: "string",
1102
+ "include-discovery": "boolean",
1103
+ }, "research project evidence acquisition revise");
1104
+ if (strictBoolean(args, "help"))
1105
+ return writeHelp(io);
1106
+ const projectId = onePositional(args.positionals, "research project evidence acquisition revise");
1107
+ const result = await reviseProjectAcquisition({
1108
+ root: await workspaceFromArgs(args),
1109
+ projectId,
1110
+ expectedSnapshotSha256: strictString(args, "expected-snapshot") ?? "",
1111
+ reason: strictString(args, "reason") ?? "",
1112
+ includeDiscovery: strictBoolean(args, "include-discovery"),
1113
+ });
1114
+ writeJson(io, result, args);
1115
+ return 0;
1116
+ }
1030
1117
  if (evidenceAction === "data") {
1031
1118
  const [dataAction, ...dataRest] = evidenceRest;
1032
1119
  if (dataAction !== "run") {
@@ -1287,7 +1374,9 @@ async function runProject(argv, io) {
1287
1374
  const value = await readBoundedJsonRecord(inputPath, "--input", "RESEARCH_ACQUISITION_FORECAST_INVALID");
1288
1375
  const result = await inspectAcquisitionForecast(root, projectId, value);
1289
1376
  writeJson(io, result, args);
1290
- return result.acquisitionGate.decision === "pass" && !result.knownRoleDeficits.length
1377
+ return result.submissionGate.decision !== "stop" &&
1378
+ result.acquisitionGate.decision === "pass" &&
1379
+ !result.knownRoleDeficits.length
1291
1380
  ? 0
1292
1381
  : 3;
1293
1382
  }
@@ -1603,12 +1692,8 @@ async function runStatus(argv, io) {
1603
1692
  const root = await workspaceFromArgs(args);
1604
1693
  const config = await loadWorkspaceConfig(root);
1605
1694
  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)));
1695
+ const authorityIndex = await readProjectAuthorityIndex(root);
1696
+ const workspaceProjects = await listProjects(root, authorityIndex);
1612
1697
  const allProjects = selectedProject
1613
1698
  ? [
1614
1699
  workspaceProjects.find((project) => project.id === selectedProject) ??
@@ -1617,9 +1702,7 @@ async function runStatus(argv, io) {
1617
1702
  : workspaceProjects;
1618
1703
  const projects = selectedProject || strictBoolean(args, "all")
1619
1704
  ? allProjects
1620
- : allProjects.filter((project) => project.lineage.supersededBy === null &&
1621
- project.status !== "archived" &&
1622
- project.status !== "abandoned");
1705
+ : allProjects.filter((project) => ["authoritative", "invalid"].includes(projectAuthority(project, authorityIndex).state));
1623
1706
  const result = {
1624
1707
  workspace: root,
1625
1708
  execution: {
@@ -1638,7 +1721,7 @@ async function runStatus(argv, io) {
1638
1721
  },
1639
1722
  hiddenSupersededProjects: selectedProject || strictBoolean(args, "all")
1640
1723
  ? 0
1641
- : workspaceProjects.filter((project) => project.lineage.supersededBy !== null).length,
1724
+ : workspaceProjects.filter((project) => authorityIndex.successors.has(project.id)).length,
1642
1725
  hiddenArchivedProjects: selectedProject || strictBoolean(args, "all")
1643
1726
  ? 0
1644
1727
  : workspaceProjects.filter((project) => project.status === "archived").length,
@@ -1646,13 +1729,13 @@ async function runStatus(argv, io) {
1646
1729
  ? 0
1647
1730
  : workspaceProjects.filter((project) => project.status === "abandoned").length,
1648
1731
  projects: await Promise.all(projects.map(async (project) => {
1649
- const current = refreshProject(project);
1650
- const authority = projectAuthority(current, workspaceProjects, committedForkTargets);
1732
+ const current = refreshProject(projectWithEffectiveAuthority(project, authorityIndex));
1733
+ const authority = projectAuthority(current, authorityIndex);
1651
1734
  const nativeStage = await inspectNativeResearchStage(root, current);
1652
1735
  const evidencePipeline = await inspectEvidencePipelineForStatus(root, current);
1653
1736
  const snapshot = evidencePipeline.acquisition;
1654
1737
  const readyPackage = nextReadyPackage(current)?.id ?? null;
1655
- const scientificReview = await inspectScientificReviewStatus(root, current.id);
1738
+ const scientificReview = await inspectScientificReviewStatus(root, current.id, current);
1656
1739
  const evidenceAccess = current.scientificDesign
1657
1740
  ? await inspectEvidenceAccessForStatus(root, current.id)
1658
1741
  : null;
@@ -1671,6 +1754,7 @@ async function runStatus(argv, io) {
1671
1754
  evidencePipeline,
1672
1755
  nativeStage,
1673
1756
  scientificReview,
1757
+ task: await inspectProjectTask(root, current.id, authorityIndex.taskEvents.get(current.id) ?? []),
1674
1758
  evidenceAccess,
1675
1759
  publication,
1676
1760
  readyPackage,
@@ -1786,33 +1870,6 @@ async function inspectEvidenceAccessForStatus(root, projectId) {
1786
1870
  };
1787
1871
  }
1788
1872
  }
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
1873
  async function inspectSnapshotForStatus(root, projectId) {
1817
1874
  const currentPath = join(workspacePaths(root).projects, projectId, "outputs", "evidence-snapshot.json");
1818
1875
  if (!(await pathExists(currentPath)))