@tiangong-ai/cli 0.0.42 → 0.0.43
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.
- package/AGENTS.md +2 -2
- package/README.md +45 -18
- package/dist/research/orchestration.js +198 -7
- package/dist/research/orchestration.js.map +1 -1
- package/dist/research/workspace/acquisition.d.ts +7 -0
- package/dist/research/workspace/acquisition.js +37 -10
- package/dist/research/workspace/acquisition.js.map +1 -1
- package/dist/research/workspace/audit-bundle.d.ts +18 -0
- package/dist/research/workspace/audit-bundle.js +99 -3
- package/dist/research/workspace/audit-bundle.js.map +1 -1
- package/dist/research/workspace/content-evidence.d.ts +98 -0
- package/dist/research/workspace/content-evidence.js +715 -0
- package/dist/research/workspace/content-evidence.js.map +1 -0
- package/dist/research/workspace/evidence-ledger.d.ts +1 -1
- package/dist/research/workspace/evidence-ledger.js +2 -0
- package/dist/research/workspace/evidence-ledger.js.map +1 -1
- package/dist/research/workspace/inference.d.ts +69 -0
- package/dist/research/workspace/inference.js +360 -0
- package/dist/research/workspace/inference.js.map +1 -0
- package/dist/research/workspace/native-activity.js +14 -5
- package/dist/research/workspace/native-activity.js.map +1 -1
- package/dist/research/workspace/projects.js +16 -0
- package/dist/research/workspace/projects.js.map +1 -1
- package/dist/research/workspace/publication-workflow.d.ts +26 -0
- package/dist/research/workspace/publication-workflow.js +313 -2
- package/dist/research/workspace/publication-workflow.js.map +1 -1
- package/dist/research/workspace/runtime.js +131 -30
- package/dist/research/workspace/runtime.js.map +1 -1
- package/dist/research/workspace/schemas.js +83 -4
- package/dist/research/workspace/schemas.js.map +1 -1
- package/dist/research/workspace/scientific-review.js +57 -0
- package/dist/research/workspace/scientific-review.js.map +1 -1
- package/dist/research/workspace/setup-catalog.js +2 -2
- package/dist/research/workspace/setup.js +1 -1
- package/dist/research/workspace/setup.js.map +1 -1
- package/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -17,8 +17,8 @@ checkPaths:
|
|
|
17
17
|
- .docpact/config.yaml
|
|
18
18
|
- docs/agents/**
|
|
19
19
|
- src/**
|
|
20
|
-
lastReviewedAt: 2026-08-
|
|
21
|
-
lastReviewedCommit:
|
|
20
|
+
lastReviewedAt: 2026-08-19
|
|
21
|
+
lastReviewedCommit: cd92a737acbdfd05a36c0d0d5b14c7e531ae6ee7
|
|
22
22
|
---
|
|
23
23
|
|
|
24
24
|
# Tiangong AI CLI Contract
|
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@ checkPaths:
|
|
|
13
13
|
- bin/**
|
|
14
14
|
- src/**
|
|
15
15
|
lastReviewedAt: 2026-08-18
|
|
16
|
-
lastReviewedCommit:
|
|
16
|
+
lastReviewedCommit: 34a5c2a3af26fc56e9c9dc94fcbdabd91a6dd1d8
|
|
17
17
|
---
|
|
18
18
|
|
|
19
19
|
# Tiangong AI CLI
|
|
@@ -417,14 +417,17 @@ tiangong-ai research project init top-journal-paper \
|
|
|
417
417
|
--workspace /absolute/path/to/workspace --json
|
|
418
418
|
```
|
|
419
419
|
|
|
420
|
-
The base evidence lifecycle remains
|
|
421
|
-
|
|
422
|
-
|
|
420
|
+
The base evidence lifecycle remains producer-authored in the current interactive
|
|
421
|
+
Codex or Claude Code host, but its frozen control sequence is now
|
|
422
|
+
`discover -> acquire -> typed decomposition/atoms -> content freeze -> inference freeze -> analyze -> Claim-Evidence Graph -> synthesize -> review -> close`.
|
|
423
|
+
A fresh independent reviewer
|
|
423
424
|
must first pass three hash-bound scientific gates: `research-design` before
|
|
424
425
|
discovery, a real-record and outcome-blind `evidence-construct` canary after
|
|
425
|
-
acquisition
|
|
426
|
-
|
|
427
|
-
|
|
426
|
+
acquisition and typed-content freeze, and `pilot-methods` after that canary and
|
|
427
|
+
before analysis. Acquisition always freezes its exact result, including honest
|
|
428
|
+
gaps; a stopped acquisition/content gate prevents inference without discarding
|
|
429
|
+
the acquired evidence. Evidence-construct coverage may cite only frozen
|
|
430
|
+
snapshot source IDs and exact content atoms. Its JSON canary artifacts are promoted and
|
|
428
431
|
content-addressed through `--canary-artifacts`; reviewer prose cannot override
|
|
429
432
|
an invented ID, unbound digest, or other mechanical failure.
|
|
430
433
|
|
|
@@ -457,14 +460,23 @@ audit manifest separately records the raw stored packet-file digest. This keeps
|
|
|
457
460
|
packet identity and byte-level transfer verification explicit rather than
|
|
458
461
|
overloading one hash with both meanings.
|
|
459
462
|
|
|
460
|
-
After base closure, the current native host writes a final
|
|
461
|
-
schema-valid publication assessment
|
|
462
|
-
|
|
463
|
-
|
|
463
|
+
After base closure, the current native host writes a final Markdown/plain-text
|
|
464
|
+
manuscript, schema-valid publication assessment, and an explicit submission
|
|
465
|
+
manifest. The manuscript must contain Abstract, Introduction, Methods, Results,
|
|
466
|
+
Discussion, Data availability, Code availability, and References. The
|
|
467
|
+
submission manifest must bind distinct absolute files for cover letter, title
|
|
468
|
+
page, reporting checklist, data availability, code availability, and source
|
|
469
|
+
data; figure/table index, extended data, and supplementary methods are optional.
|
|
470
|
+
`research publication freeze` then content-addresses the Policy, scientific
|
|
471
|
+
design and early reviews, acquisition/content/inference snapshots, reproduced
|
|
472
|
+
analysis, Claim-Evidence Graph, base outputs, manuscript, assessment,
|
|
473
|
+
supplements, role-complete submission files, and reproducibility manifest.
|
|
464
474
|
Exactly four fresh independent sessions review that frozen generation:
|
|
465
475
|
evidence, methods/reproducibility, domain/novelty, and journal-editor. A revised
|
|
466
|
-
manuscript invalidates prior reviews
|
|
467
|
-
|
|
476
|
+
manuscript invalidates prior reviews. Every reviewer must use the configured
|
|
477
|
+
agent family that differs from the native producer; changing only the session
|
|
478
|
+
ID is not independent. Reviewer-session reuse is rejected from the append-only
|
|
479
|
+
journal even if mutable cache state is removed. The raw opaque
|
|
468
480
|
producer/reviewer session identifiers are accepted only at the command boundary;
|
|
469
481
|
generation, packet, review, journal, and closure objects persist only their
|
|
470
482
|
SHA-256 bindings.
|
|
@@ -474,6 +486,7 @@ tiangong-ai research schema show publication-assessment --json
|
|
|
474
486
|
tiangong-ai research publication freeze top-journal-paper \
|
|
475
487
|
--manuscript /absolute/path/to/final-manuscript.md \
|
|
476
488
|
--assessment /absolute/path/to/publication-assessment.json \
|
|
489
|
+
--submission /absolute/path/to/submission-package.json \
|
|
477
490
|
--producer-agent codex --producer-session OPAQUE_NATIVE_SESSION \
|
|
478
491
|
--workspace /absolute/path/to/workspace --json
|
|
479
492
|
tiangong-ai research publication status top-journal-paper \
|
|
@@ -486,9 +499,13 @@ The CLI returns a mechanically bounded ceiling:
|
|
|
486
499
|
it. None of these states predicts or guarantees editorial acceptance.
|
|
487
500
|
|
|
488
501
|
Before external handoff or archival, export and independently verify a portable
|
|
489
|
-
audit directory.
|
|
502
|
+
audit directory. Export first revalidates the semantic acquisition, content,
|
|
503
|
+
inference, graph, and publication objects; a copied but stale/tampered chain is
|
|
504
|
+
rejected. Its manifest exposes their intrinsic IDs and hashes under
|
|
505
|
+
`researchChain`. It contains the selected project, portable copies of admitted
|
|
490
506
|
inputs, formal evidence and artifact bytes, Policy/design/review objects,
|
|
491
|
-
outputs, environment fingerprints, and
|
|
507
|
+
outputs, environment fingerprints, and safe hash-preserving journal proof
|
|
508
|
+
derivatives. Credentials, setup
|
|
492
509
|
sources, browser profiles, native active state, capsules, unrelated projects,
|
|
493
510
|
and host-specific absolute paths are excluded.
|
|
494
511
|
|
|
@@ -673,9 +690,19 @@ resume criteria. Research then stops; it does not spend more budget on
|
|
|
673
690
|
low-yield substitutes. If no lawful remaining route exists, the user must narrow
|
|
674
691
|
or abandon the unsupported scope before a new reviewed generation can resume.
|
|
675
692
|
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
693
|
+
Acquisition freezes an immutable evidence snapshot even when lawful retrieval
|
|
694
|
+
ends with explicit gaps. Before inference, decompose every acquired PDF,
|
|
695
|
+
spreadsheet, archive, or structured file into exact lineage-bound producer-
|
|
696
|
+
readable artifacts; register line-range or JSON-Pointer evidence atoms; then
|
|
697
|
+
freeze `content-snapshot.json`. `research status --json` exposes acquisition,
|
|
698
|
+
content, inference, and graph state under `evidencePipeline` and does not direct
|
|
699
|
+
the operator to analysis while content preparation is missing or stopped.
|
|
700
|
+
Only passing acquisition/content gates and required scientific reviews can
|
|
701
|
+
freeze `inference-snapshot.json`. Analyze schema v2 binds that exact snapshot,
|
|
702
|
+
a reproduced analysis run, source IDs, atom IDs, and design claim IDs; the CLI
|
|
703
|
+
then creates `claim-evidence-graph.json` mechanically. The reviewer and
|
|
704
|
+
mechanical closure bind and recheck the full chain, ledger, receipts, selected
|
|
705
|
+
artifacts, excerpts, analysis, graph, and report. Refresh a
|
|
679
706
|
closed result with `research project addendum SOURCE --to TARGET`; the original
|
|
680
707
|
closure remains unchanged, the child snapshot records a mechanical delta, and
|
|
681
708
|
default status hides the superseded project (`research status --all` shows full
|
|
@@ -13,6 +13,7 @@ import { fetchNativeCandidateSource } from "./workspace/broker.js";
|
|
|
13
13
|
import { registerEvidenceArtifact } from "./workspace/artifacts.js";
|
|
14
14
|
import { exportProjectAuditBundle, verifyProjectAuditBundle } from "./workspace/audit-bundle.js";
|
|
15
15
|
import { loadCurrentEvidenceSnapshot } from "./workspace/acquisition.js";
|
|
16
|
+
import { freezeEvidenceContentSnapshot, loadCurrentEvidenceContentSnapshot, recordArtifactDecomposition, registerEvidenceAtom, } from "./workspace/content-evidence.js";
|
|
16
17
|
import { inspectDiscoveryProgress } from "./workspace/discovery-status.js";
|
|
17
18
|
import { inspectEvidenceAccessStatus } from "./workspace/evidence-exhaustion.js";
|
|
18
19
|
import { recordDiscoveryAssessmentBatch } from "./workspace/discovery.js";
|
|
@@ -20,6 +21,7 @@ import { bindEvidenceDownload } from "./workspace/downloads.js";
|
|
|
20
21
|
import { registerNativeDiscoveryCandidate } from "./workspace/evidence-ledger.js";
|
|
21
22
|
import { recordNativeResearchActivity } from "./workspace/native-activity.js";
|
|
22
23
|
import { readAndVerifyProjectInputPlan } from "./workspace/input-plan.js";
|
|
24
|
+
import { loadCurrentClaimEvidenceGraph, loadCurrentInferenceSnapshot, } from "./workspace/inference.js";
|
|
23
25
|
import { addProjectInput, createProjectAddendum, initializeProject, forkProject, listProjects, loadProject, nextReadyPackage, normalizeEvidenceRequirements, refreshProject, retryProjectPackage, setProjectDisposition, } from "./workspace/projects.js";
|
|
24
26
|
import { evaluateProjectPreflight } from "./workspace/preflight.js";
|
|
25
27
|
import { closePublication, freezePublicationManuscript, inspectPublicationStatus, preparePublicationReview, publicationAssessmentSchema, publicationReviewSchema, submitPublicationReview, } from "./workspace/publication-workflow.js";
|
|
@@ -29,7 +31,7 @@ import { abortNativeResearchStage, inspectNativeResearchStage, prepareNativeRese
|
|
|
29
31
|
import { schemaForStage } from "./workspace/schemas.js";
|
|
30
32
|
import { readAndVerifyScientificDesign, scientificDesignSchema, } from "./workspace/scientific-design.js";
|
|
31
33
|
import { inspectScientificReviewStatus, prepareScientificReview, scientificGateAssessmentSchema, scientificReviewSchema, submitScientificReview, } from "./workspace/scientific-review.js";
|
|
32
|
-
import { pathExists, sha256Text, workspacePaths } from "./workspace/storage.js";
|
|
34
|
+
import { isObject, pathExists, sha256Text, workspacePaths } from "./workspace/storage.js";
|
|
33
35
|
import { doctorResearchWorkspace, initializeResearchWorkspace, requireResearchWorkspace, withWorkspaceLock, } from "./workspace/workspace.js";
|
|
34
36
|
const COMMON_OPTIONS = { help: "boolean", json: "boolean" };
|
|
35
37
|
const WORKSPACE_OPTIONS = { ...COMMON_OPTIONS, workspace: "string" };
|
|
@@ -77,7 +79,7 @@ export function researchOrchestrationHelp() {
|
|
|
77
79
|
tiangong-ai research policy validate <project-id> [--workspace <path>] [--json]
|
|
78
80
|
tiangong-ai research policy approve <project-id> --confirm [--acknowledge-defaults] [--workspace <path>] [--json]
|
|
79
81
|
tiangong-ai research policy resolve <project-id> [--workspace <path>] [--json]
|
|
80
|
-
tiangong-ai research publication freeze <project-id> --manuscript <absolute-file> --assessment <absolute-json> --producer-agent codex|claude --producer-session <opaque-id> [--supplements <absolute-json-array>] [--workspace <path>] [--json]
|
|
82
|
+
tiangong-ai research publication freeze <project-id> --manuscript <absolute-file> --assessment <absolute-json> --submission <absolute-json> --producer-agent codex|claude --producer-session <opaque-id> [--supplements <absolute-json-array>] [--workspace <path>] [--json]
|
|
81
83
|
tiangong-ai research publication review prepare <project-id> --role evidence|methods-reproducibility|domain-novelty|journal-editor --reviewer-agent codex|claude --reviewer-session <opaque-id> [--workspace <path>] [--json]
|
|
82
84
|
tiangong-ai research publication review submit <project-id> --role evidence|methods-reproducibility|domain-novelty|journal-editor --review <absolute-json> [--workspace <path>] [--json]
|
|
83
85
|
tiangong-ai research publication status <project-id> [--workspace <path>] [--json]
|
|
@@ -107,6 +109,10 @@ export function researchOrchestrationHelp() {
|
|
|
107
109
|
tiangong-ai research project evidence assessment record <project-id> --record <absolute-json> [--workspace <path>] [--json]
|
|
108
110
|
tiangong-ai research project evidence download bind <project-id> --candidate <id> --record <absolute-json> [--workspace <path>] [--json]
|
|
109
111
|
tiangong-ai research project evidence artifact register <project-id> --candidate <id> --path <absolute-file> [--download-binding <id> | --derived-from-artifact <id>] [--media-type <type>] [--source-url <https-url>] [--license <declared-license>] [--license-url <https-url>] [--host-type <type>] [--article-version <version>] [--workspace <path>] [--json]
|
|
112
|
+
tiangong-ai research project evidence decomposition record <project-id> --record <absolute-json> [--workspace <path>] [--json]
|
|
113
|
+
tiangong-ai research project evidence atom register <project-id> --record <absolute-json> [--workspace <path>] [--json]
|
|
114
|
+
tiangong-ai research project evidence content freeze <project-id> [--workspace <path>] [--json]
|
|
115
|
+
tiangong-ai research project evidence content status <project-id> [--workspace <path>] [--json]
|
|
110
116
|
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]
|
|
111
117
|
tiangong-ai research status [--project <project-id>] [--all] [--workspace <absolute-path>] [--json]
|
|
112
118
|
tiangong-ai research run [--project <project-id>] [--max-parallel <1-8>] [--max-cycles <1-100>] [--dry-run] [--progress-jsonl] [--workspace <absolute-path>] [--json]
|
|
@@ -124,6 +130,7 @@ async function runPublication(argv, io) {
|
|
|
124
130
|
manuscript: "string",
|
|
125
131
|
assessment: "string",
|
|
126
132
|
supplements: "string",
|
|
133
|
+
submission: "string",
|
|
127
134
|
"producer-agent": "string",
|
|
128
135
|
"producer-session": "string",
|
|
129
136
|
}, "research publication freeze");
|
|
@@ -133,8 +140,9 @@ async function runPublication(argv, io) {
|
|
|
133
140
|
const manuscriptPath = strictString(args, "manuscript");
|
|
134
141
|
const assessmentPath = strictString(args, "assessment");
|
|
135
142
|
const producerSessionId = strictString(args, "producer-session");
|
|
136
|
-
|
|
137
|
-
|
|
143
|
+
const submissionPath = strictString(args, "submission");
|
|
144
|
+
if (!manuscriptPath || !assessmentPath || !submissionPath || !producerSessionId) {
|
|
145
|
+
throw new CliError("research publication freeze requires --manuscript, --assessment, --submission, --producer-agent, and --producer-session.", { code: "RESEARCH_PUBLICATION_ARGUMENT_REQUIRED", exitCode: 2 });
|
|
138
146
|
}
|
|
139
147
|
const root = await workspaceFromArgs(args);
|
|
140
148
|
const supplementsPath = strictString(args, "supplements");
|
|
@@ -144,6 +152,7 @@ async function runPublication(argv, io) {
|
|
|
144
152
|
manuscriptPath,
|
|
145
153
|
assessmentPath,
|
|
146
154
|
supplementPaths: supplementsPath ? await readAbsolutePathArray(supplementsPath) : [],
|
|
155
|
+
submissionFiles: await readSubmissionFiles(submissionPath),
|
|
147
156
|
producerAgent: publicationAgent(strictString(args, "producer-agent"), "producer"),
|
|
148
157
|
producerSessionId,
|
|
149
158
|
}), args);
|
|
@@ -949,6 +958,66 @@ async function runProject(argv, io) {
|
|
|
949
958
|
writeJson(io, result, args);
|
|
950
959
|
return 0;
|
|
951
960
|
}
|
|
961
|
+
if (evidenceAction === "decomposition") {
|
|
962
|
+
const [decompositionAction, ...decompositionRest] = evidenceRest;
|
|
963
|
+
if (decompositionAction !== "record") {
|
|
964
|
+
throw unknownAction("research project evidence decomposition", decompositionAction ?? "");
|
|
965
|
+
}
|
|
966
|
+
const args = parseStrictArgs(decompositionRest, { ...WORKSPACE_OPTIONS, record: "string" }, "research project evidence decomposition record");
|
|
967
|
+
if (strictBoolean(args, "help"))
|
|
968
|
+
return writeHelp(io);
|
|
969
|
+
const projectId = onePositional(args.positionals, "research project evidence decomposition record");
|
|
970
|
+
const recordPath = strictString(args, "record");
|
|
971
|
+
if (!recordPath) {
|
|
972
|
+
throw new CliError("decomposition record requires --record.", {
|
|
973
|
+
code: "RESEARCH_DECOMPOSITION_INVALID",
|
|
974
|
+
exitCode: 2,
|
|
975
|
+
});
|
|
976
|
+
}
|
|
977
|
+
const root = await workspaceFromArgs(args);
|
|
978
|
+
const record = await readBoundedJsonRecord(recordPath, "--record", "RESEARCH_DECOMPOSITION_INVALID");
|
|
979
|
+
const result = await withWorkspaceLock(root, "research.decomposition.record", () => recordArtifactDecomposition({ root, projectId, value: record }));
|
|
980
|
+
writeJson(io, result, args);
|
|
981
|
+
return 0;
|
|
982
|
+
}
|
|
983
|
+
if (evidenceAction === "atom") {
|
|
984
|
+
const [atomAction, ...atomRest] = evidenceRest;
|
|
985
|
+
if (atomAction !== "register") {
|
|
986
|
+
throw unknownAction("research project evidence atom", atomAction ?? "");
|
|
987
|
+
}
|
|
988
|
+
const args = parseStrictArgs(atomRest, { ...WORKSPACE_OPTIONS, record: "string" }, "research project evidence atom register");
|
|
989
|
+
if (strictBoolean(args, "help"))
|
|
990
|
+
return writeHelp(io);
|
|
991
|
+
const projectId = onePositional(args.positionals, "research project evidence atom register");
|
|
992
|
+
const recordPath = strictString(args, "record");
|
|
993
|
+
if (!recordPath) {
|
|
994
|
+
throw new CliError("atom register requires --record.", {
|
|
995
|
+
code: "RESEARCH_EVIDENCE_ATOM_INVALID",
|
|
996
|
+
exitCode: 2,
|
|
997
|
+
});
|
|
998
|
+
}
|
|
999
|
+
const root = await workspaceFromArgs(args);
|
|
1000
|
+
const record = await readBoundedJsonRecord(recordPath, "--record", "RESEARCH_EVIDENCE_ATOM_INVALID");
|
|
1001
|
+
const result = await withWorkspaceLock(root, "research.evidence-atom.register", () => registerEvidenceAtom({ root, projectId, value: record }));
|
|
1002
|
+
writeJson(io, result, args);
|
|
1003
|
+
return 0;
|
|
1004
|
+
}
|
|
1005
|
+
if (evidenceAction === "content") {
|
|
1006
|
+
const [contentAction, ...contentRest] = evidenceRest;
|
|
1007
|
+
if (contentAction !== "freeze" && contentAction !== "status") {
|
|
1008
|
+
throw unknownAction("research project evidence content", contentAction ?? "");
|
|
1009
|
+
}
|
|
1010
|
+
const args = parseStrictArgs(contentRest, WORKSPACE_OPTIONS, `research project evidence content ${contentAction}`);
|
|
1011
|
+
if (strictBoolean(args, "help"))
|
|
1012
|
+
return writeHelp(io);
|
|
1013
|
+
const projectId = onePositional(args.positionals, `research project evidence content ${contentAction}`);
|
|
1014
|
+
const root = await workspaceFromArgs(args);
|
|
1015
|
+
const result = contentAction === "freeze"
|
|
1016
|
+
? await withWorkspaceLock(root, "research.evidence-content.freeze", () => freezeEvidenceContentSnapshot(root, projectId))
|
|
1017
|
+
: await loadCurrentEvidenceContentSnapshot(root, projectId);
|
|
1018
|
+
writeJson(io, result, args);
|
|
1019
|
+
return 0;
|
|
1020
|
+
}
|
|
952
1021
|
if (evidenceAction !== "fetch") {
|
|
953
1022
|
throw unknownAction("research project evidence", evidenceAction ?? "");
|
|
954
1023
|
}
|
|
@@ -1272,7 +1341,8 @@ async function runStatus(argv, io) {
|
|
|
1272
1341
|
projects: await Promise.all(projects.map(async (project) => {
|
|
1273
1342
|
const current = refreshProject(project);
|
|
1274
1343
|
const nativeStage = await inspectNativeResearchStage(root, current);
|
|
1275
|
-
const
|
|
1344
|
+
const evidencePipeline = await inspectEvidencePipelineForStatus(root, current);
|
|
1345
|
+
const snapshot = evidencePipeline.acquisition;
|
|
1276
1346
|
const readyPackage = nextReadyPackage(current)?.id ?? null;
|
|
1277
1347
|
const scientificReview = await inspectScientificReviewStatus(root, current.id);
|
|
1278
1348
|
const evidenceAccess = current.scientificDesign
|
|
@@ -1290,12 +1360,13 @@ async function runStatus(argv, io) {
|
|
|
1290
1360
|
handoff: current.handoff,
|
|
1291
1361
|
evidenceState: current.evidenceState,
|
|
1292
1362
|
snapshot,
|
|
1363
|
+
evidencePipeline,
|
|
1293
1364
|
nativeStage,
|
|
1294
1365
|
scientificReview,
|
|
1295
1366
|
evidenceAccess,
|
|
1296
1367
|
publication,
|
|
1297
1368
|
readyPackage,
|
|
1298
|
-
recommendedAction: projectRecommendedAction(root, current, readyPackage, nativeStage, scientificReview, publication),
|
|
1369
|
+
recommendedAction: projectRecommendedAction(root, current, readyPackage, nativeStage, scientificReview, evidencePipeline, publication),
|
|
1299
1370
|
usage: current.usage,
|
|
1300
1371
|
inputs: current.inputs,
|
|
1301
1372
|
packages: current.packages,
|
|
@@ -1306,6 +1377,94 @@ async function runStatus(argv, io) {
|
|
|
1306
1377
|
writeJson(io, result, args);
|
|
1307
1378
|
return 0;
|
|
1308
1379
|
}
|
|
1380
|
+
async function inspectEvidencePipelineForStatus(root, project) {
|
|
1381
|
+
const projectRoot = join(workspacePaths(root).projects, project.id);
|
|
1382
|
+
const acquisition = await inspectSnapshotForStatus(root, project.id);
|
|
1383
|
+
const contentPath = join(projectRoot, "outputs", "content-snapshot.json");
|
|
1384
|
+
let content = { status: "absent" };
|
|
1385
|
+
if (await pathExists(contentPath)) {
|
|
1386
|
+
try {
|
|
1387
|
+
const snapshot = await loadCurrentEvidenceContentSnapshot(root, project.id);
|
|
1388
|
+
content = {
|
|
1389
|
+
status: "verified",
|
|
1390
|
+
snapshotId: snapshot.snapshotId,
|
|
1391
|
+
snapshotSha256: snapshot.snapshotSha256,
|
|
1392
|
+
decompositionCount: snapshot.decompositions.length,
|
|
1393
|
+
atomCount: snapshot.atoms.length,
|
|
1394
|
+
sourceCount: snapshot.sourceCoverage.length,
|
|
1395
|
+
roleCount: snapshot.roleCoverage.length,
|
|
1396
|
+
insufficientRoleIds: snapshot.roleCoverage
|
|
1397
|
+
.filter((role) => role.decision === "insufficient")
|
|
1398
|
+
.map((role) => role.roleId),
|
|
1399
|
+
gate: snapshot.gate,
|
|
1400
|
+
};
|
|
1401
|
+
}
|
|
1402
|
+
catch (error) {
|
|
1403
|
+
content = {
|
|
1404
|
+
status: "invalid",
|
|
1405
|
+
code: error instanceof CliError ? error.code : "RESEARCH_EVIDENCE_CONTENT_SNAPSHOT_INVALID",
|
|
1406
|
+
};
|
|
1407
|
+
}
|
|
1408
|
+
}
|
|
1409
|
+
const inferencePath = join(projectRoot, "outputs", "inference-snapshot.json");
|
|
1410
|
+
let inference = { status: "absent" };
|
|
1411
|
+
if (await pathExists(inferencePath)) {
|
|
1412
|
+
try {
|
|
1413
|
+
const snapshot = await loadCurrentInferenceSnapshot(root, project.id);
|
|
1414
|
+
inference = {
|
|
1415
|
+
status: "verified",
|
|
1416
|
+
snapshotId: snapshot.snapshotId,
|
|
1417
|
+
snapshotSha256: snapshot.snapshotSha256,
|
|
1418
|
+
sourceCount: snapshot.sources.length,
|
|
1419
|
+
atomCount: snapshot.atoms.length,
|
|
1420
|
+
claimCount: snapshot.claims.length,
|
|
1421
|
+
artifactCount: snapshot.artifactSha256s.length,
|
|
1422
|
+
gate: snapshot.gate,
|
|
1423
|
+
};
|
|
1424
|
+
}
|
|
1425
|
+
catch (error) {
|
|
1426
|
+
inference = {
|
|
1427
|
+
status: "invalid",
|
|
1428
|
+
code: error instanceof CliError ? error.code : "RESEARCH_INFERENCE_SNAPSHOT_INVALID",
|
|
1429
|
+
};
|
|
1430
|
+
}
|
|
1431
|
+
}
|
|
1432
|
+
else if (acquisition.gate?.decision === "stop") {
|
|
1433
|
+
inference = { status: "blocked", gate: acquisition.gate };
|
|
1434
|
+
}
|
|
1435
|
+
else if (content.gate?.decision === "stop") {
|
|
1436
|
+
inference = { status: "blocked", gate: content.gate };
|
|
1437
|
+
}
|
|
1438
|
+
else if (project.scientificDesign && content.status !== "verified") {
|
|
1439
|
+
inference = {
|
|
1440
|
+
status: "blocked",
|
|
1441
|
+
code: "RESEARCH_EVIDENCE_CONTENT_SNAPSHOT_REQUIRED",
|
|
1442
|
+
};
|
|
1443
|
+
}
|
|
1444
|
+
const graphPath = join(projectRoot, "outputs", "claim-evidence-graph.json");
|
|
1445
|
+
let claimGraph = { status: "absent" };
|
|
1446
|
+
if (await pathExists(graphPath)) {
|
|
1447
|
+
try {
|
|
1448
|
+
const graph = await loadCurrentClaimEvidenceGraph(root, project.id);
|
|
1449
|
+
claimGraph = {
|
|
1450
|
+
status: "verified",
|
|
1451
|
+
graphId: graph.graphId,
|
|
1452
|
+
graphSha256: graph.graphSha256,
|
|
1453
|
+
analysisSha256: graph.analysisSha256,
|
|
1454
|
+
analysisRunId: graph.analysisRunId,
|
|
1455
|
+
nodeCount: graph.nodes.length,
|
|
1456
|
+
edgeCount: graph.edges.length,
|
|
1457
|
+
};
|
|
1458
|
+
}
|
|
1459
|
+
catch (error) {
|
|
1460
|
+
claimGraph = {
|
|
1461
|
+
status: "invalid",
|
|
1462
|
+
code: error instanceof CliError ? error.code : "RESEARCH_CLAIM_EVIDENCE_GRAPH_INVALID",
|
|
1463
|
+
};
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
return { acquisition, content, inference, claimGraph };
|
|
1467
|
+
}
|
|
1309
1468
|
async function inspectEvidenceAccessForStatus(root, projectId) {
|
|
1310
1469
|
try {
|
|
1311
1470
|
return await inspectEvidenceAccessStatus(root, projectId);
|
|
@@ -1352,6 +1511,8 @@ async function inspectSnapshotForStatus(root, projectId) {
|
|
|
1352
1511
|
parentSnapshotId: snapshot.parentSnapshotId,
|
|
1353
1512
|
sourceCount: snapshot.sources.length,
|
|
1354
1513
|
artifactCount: snapshot.artifacts.length,
|
|
1514
|
+
gapCount: snapshot.gaps.length,
|
|
1515
|
+
gate: snapshot.inferenceGate,
|
|
1355
1516
|
delta: snapshot.delta,
|
|
1356
1517
|
};
|
|
1357
1518
|
}
|
|
@@ -1374,7 +1535,7 @@ async function inspectPublicationForStatus(root, projectId) {
|
|
|
1374
1535
|
};
|
|
1375
1536
|
}
|
|
1376
1537
|
}
|
|
1377
|
-
function projectRecommendedAction(root, project, readyPackage, nativeStage, scientificReview, publication) {
|
|
1538
|
+
function projectRecommendedAction(root, project, readyPackage, nativeStage, scientificReview, evidencePipeline, publication) {
|
|
1378
1539
|
if (project.lineage.supersededBy) {
|
|
1379
1540
|
return `Continue with superseding project ${project.lineage.supersededBy}.`;
|
|
1380
1541
|
}
|
|
@@ -1398,6 +1559,23 @@ function projectRecommendedAction(root, project, readyPackage, nativeStage, scie
|
|
|
1398
1559
|
if (nativeStage.status === "active") {
|
|
1399
1560
|
return nativeStage.recommendedAction ?? "Resume the active native stage.";
|
|
1400
1561
|
}
|
|
1562
|
+
if (readyPackage === "analyze") {
|
|
1563
|
+
if (evidencePipeline.content.status === "absent") {
|
|
1564
|
+
return `Decompose every acquired full-text/data artifact, register exact evidence atoms, then freeze typed content: tiangong-ai research project evidence content freeze ${project.id} --workspace ${root}`;
|
|
1565
|
+
}
|
|
1566
|
+
if (evidencePipeline.content.status === "invalid") {
|
|
1567
|
+
return `Typed evidence content is invalid (${evidencePipeline.content.code ?? "unknown"}); repair exact decomposition/atom bindings before analysis.`;
|
|
1568
|
+
}
|
|
1569
|
+
if (evidencePipeline.content.gate?.decision === "stop") {
|
|
1570
|
+
return "Typed evidence coverage is insufficient; complete lawful gap filling or request a scope/access handoff instead of starting inference.";
|
|
1571
|
+
}
|
|
1572
|
+
if (evidencePipeline.acquisition.gate?.decision === "stop") {
|
|
1573
|
+
return "Frozen acquisition gaps block inference; request a scope/access handoff after all acquired content is decomposed instead of continuing substitute search.";
|
|
1574
|
+
}
|
|
1575
|
+
if (evidencePipeline.inference.status === "invalid") {
|
|
1576
|
+
return `Inference snapshot is invalid (${evidencePipeline.inference.code ?? "unknown"}); repair its frozen upstream bindings before analysis.`;
|
|
1577
|
+
}
|
|
1578
|
+
}
|
|
1401
1579
|
if (scientificReview.nextGate) {
|
|
1402
1580
|
const gate = scientificReview.nextGate;
|
|
1403
1581
|
if (gate.status === "stopped") {
|
|
@@ -1712,6 +1890,19 @@ async function readAbsolutePathArray(path, option = "supplements") {
|
|
|
1712
1890
|
}
|
|
1713
1891
|
return value;
|
|
1714
1892
|
}
|
|
1893
|
+
async function readSubmissionFiles(path) {
|
|
1894
|
+
const value = await readBoundedJsonRecord(path, "--submission", "RESEARCH_PUBLICATION_SUBMISSION_PACKAGE_INVALID");
|
|
1895
|
+
if (value.schemaVersion !== 1 ||
|
|
1896
|
+
!Array.isArray(value.files) ||
|
|
1897
|
+
value.files.some((file) => !isObject(file) ||
|
|
1898
|
+
typeof file.role !== "string" ||
|
|
1899
|
+
typeof file.path !== "string" ||
|
|
1900
|
+
!isAbsolute(file.path) ||
|
|
1901
|
+
resolve(file.path) !== file.path)) {
|
|
1902
|
+
throw new CliError("--submission must declare schemaVersion 1 and role/path entries with absolute canonical paths.", { code: "RESEARCH_PUBLICATION_SUBMISSION_PACKAGE_INVALID", exitCode: 2 });
|
|
1903
|
+
}
|
|
1904
|
+
return value.files;
|
|
1905
|
+
}
|
|
1715
1906
|
function integerOption(value, fallback, label) {
|
|
1716
1907
|
if (!value)
|
|
1717
1908
|
return fallback;
|