@tiangong-ai/cli 0.0.42 → 0.0.44
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 +3 -2
- package/README.md +87 -24
- package/dist/research/orchestration.js +318 -14
- package/dist/research/orchestration.js.map +1 -1
- package/dist/research/setup-command.js +13 -1
- package/dist/research/setup-command.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 +100 -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/executor.d.ts +9 -0
- package/dist/research/workspace/executor.js +161 -4
- package/dist/research/workspace/executor.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/preflight.d.ts +2 -0
- package/dist/research/workspace/preflight.js +6 -2
- package/dist/research/workspace/preflight.js.map +1 -1
- package/dist/research/workspace/projects.js +17 -1
- 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 +314 -3
- package/dist/research/workspace/publication-workflow.js.map +1 -1
- package/dist/research/workspace/review-executor.d.ts +50 -0
- package/dist/research/workspace/review-executor.js +854 -0
- package/dist/research/workspace/review-executor.js.map +1 -0
- package/dist/research/workspace/runtime.js +194 -45
- 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 +22 -2
- package/dist/research/workspace/setup-catalog.js.map +1 -1
- package/dist/research/workspace/setup-declarative.d.ts +4 -0
- package/dist/research/workspace/setup-declarative.js +16 -1
- package/dist/research/workspace/setup-declarative.js.map +1 -1
- package/dist/research/workspace/setup-wizard.js +46 -3
- package/dist/research/workspace/setup-wizard.js.map +1 -1
- package/dist/research/workspace/setup.d.ts +3 -1
- package/dist/research/workspace/setup.js +77 -19
- package/dist/research/workspace/setup.js.map +1 -1
- package/dist/research/workspace/types.d.ts +43 -1
- package/dist/research/workspace/workspace.js +62 -5
- package/dist/research/workspace/workspace.js.map +1 -1
- package/package.json +1 -1
|
@@ -6,6 +6,7 @@ import { parseStrictArgs, strictBoolean, strictString } from "../strict-args.js"
|
|
|
6
6
|
import { researchSetupHelp, runResearchSetupCommand } from "./setup-command.js";
|
|
7
7
|
import { loadCapabilityDeclarations, lockCapabilities, verifyCapabilities, } from "./workspace/capabilities.js";
|
|
8
8
|
import { inspectResearchContext } from "./workspace/context.js";
|
|
9
|
+
import { packageVersion } from "./workspace/constants.js";
|
|
9
10
|
import { setCapabilityCredentialFromEnvironment } from "./workspace/credentials.js";
|
|
10
11
|
import { configureExternalSkillProfile, doctorExternalCapabilities, EXTERNAL_SKILL_CONTEXT_PROFILE, EXTERNAL_SKILL_MEDIA_PROFILE, EXTERNAL_SKILL_PROFILE, importExternalCapability, inspectExternalSkillCatalog, } from "./workspace/external-skills.js";
|
|
11
12
|
import { appendJournalEvent } from "./workspace/journal.js";
|
|
@@ -13,13 +14,16 @@ import { fetchNativeCandidateSource } from "./workspace/broker.js";
|
|
|
13
14
|
import { registerEvidenceArtifact } from "./workspace/artifacts.js";
|
|
14
15
|
import { exportProjectAuditBundle, verifyProjectAuditBundle } from "./workspace/audit-bundle.js";
|
|
15
16
|
import { loadCurrentEvidenceSnapshot } from "./workspace/acquisition.js";
|
|
17
|
+
import { freezeEvidenceContentSnapshot, loadCurrentEvidenceContentSnapshot, recordArtifactDecomposition, registerEvidenceAtom, } from "./workspace/content-evidence.js";
|
|
16
18
|
import { inspectDiscoveryProgress } from "./workspace/discovery-status.js";
|
|
17
19
|
import { inspectEvidenceAccessStatus } from "./workspace/evidence-exhaustion.js";
|
|
18
20
|
import { recordDiscoveryAssessmentBatch } from "./workspace/discovery.js";
|
|
19
21
|
import { bindEvidenceDownload } from "./workspace/downloads.js";
|
|
20
22
|
import { registerNativeDiscoveryCandidate } from "./workspace/evidence-ledger.js";
|
|
21
23
|
import { recordNativeResearchActivity } from "./workspace/native-activity.js";
|
|
24
|
+
import { inspectReviewerBridgeStatus, startReviewerBridgeSidecar, } from "./workspace/review-executor.js";
|
|
22
25
|
import { readAndVerifyProjectInputPlan } from "./workspace/input-plan.js";
|
|
26
|
+
import { loadCurrentClaimEvidenceGraph, loadCurrentInferenceSnapshot, } from "./workspace/inference.js";
|
|
23
27
|
import { addProjectInput, createProjectAddendum, initializeProject, forkProject, listProjects, loadProject, nextReadyPackage, normalizeEvidenceRequirements, refreshProject, retryProjectPackage, setProjectDisposition, } from "./workspace/projects.js";
|
|
24
28
|
import { evaluateProjectPreflight } from "./workspace/preflight.js";
|
|
25
29
|
import { closePublication, freezePublicationManuscript, inspectPublicationStatus, preparePublicationReview, publicationAssessmentSchema, publicationReviewSchema, submitPublicationReview, } from "./workspace/publication-workflow.js";
|
|
@@ -29,8 +33,8 @@ import { abortNativeResearchStage, inspectNativeResearchStage, prepareNativeRese
|
|
|
29
33
|
import { schemaForStage } from "./workspace/schemas.js";
|
|
30
34
|
import { readAndVerifyScientificDesign, scientificDesignSchema, } from "./workspace/scientific-design.js";
|
|
31
35
|
import { inspectScientificReviewStatus, prepareScientificReview, scientificGateAssessmentSchema, scientificReviewSchema, submitScientificReview, } from "./workspace/scientific-review.js";
|
|
32
|
-
import { pathExists, sha256Text, workspacePaths } from "./workspace/storage.js";
|
|
33
|
-
import { doctorResearchWorkspace, initializeResearchWorkspace, requireResearchWorkspace, withWorkspaceLock, } from "./workspace/workspace.js";
|
|
36
|
+
import { isObject, pathExists, sha256Text, workspacePaths } from "./workspace/storage.js";
|
|
37
|
+
import { doctorResearchWorkspace, initializeResearchWorkspace, loadWorkspaceConfig, requireResearchWorkspace, withWorkspaceLock, } from "./workspace/workspace.js";
|
|
34
38
|
const COMMON_OPTIONS = { help: "boolean", json: "boolean" };
|
|
35
39
|
const WORKSPACE_OPTIONS = { ...COMMON_OPTIONS, workspace: "string" };
|
|
36
40
|
export async function runResearchOrchestrationCommand(subcommand, argv, io) {
|
|
@@ -40,6 +44,8 @@ export async function runResearchOrchestrationCommand(subcommand, argv, io) {
|
|
|
40
44
|
return runResearchSetupCommand(argv, io);
|
|
41
45
|
if (subcommand === "workspace")
|
|
42
46
|
return runWorkspace(argv, io);
|
|
47
|
+
if (subcommand === "reviewer")
|
|
48
|
+
return runReviewer(argv, io);
|
|
43
49
|
if (subcommand === "capability")
|
|
44
50
|
return runCapability(argv, io);
|
|
45
51
|
if (subcommand === "policy")
|
|
@@ -63,6 +69,9 @@ export function researchOrchestrationHelp() {
|
|
|
63
69
|
tiangong-ai research context inspect [--path <absolute-path>] [--json]
|
|
64
70
|
tiangong-ai research workspace init <absolute-path> [--name <name>] [--mode smoke-test|production-research] [--json]
|
|
65
71
|
tiangong-ai research workspace doctor [--workspace <absolute-path>] [--agent-smoke] [--capability-smoke] [--json]
|
|
72
|
+
tiangong-ai research reviewer serve --state-dir <absolute-private-directory> [--workspace <absolute-path>] [--json]
|
|
73
|
+
tiangong-ai research reviewer status [--workspace <absolute-path>] [--json]
|
|
74
|
+
tiangong-ai research reviewer doctor --confirm-agent-smoke-cost [--workspace <absolute-path>] [--json]
|
|
66
75
|
tiangong-ai research capability catalog [--path <absolute-path>] [--workspace <absolute-path>] [--skill-root <absolute-path>] [--json]
|
|
67
76
|
tiangong-ai research capability configure [--profile ${EXTERNAL_SKILL_PROFILE}|${EXTERNAL_SKILL_CONTEXT_PROFILE}|${EXTERNAL_SKILL_MEDIA_PROFILE}] [--skill-root <absolute-path>] [--workspace <absolute-path>] [--json]
|
|
68
77
|
tiangong-ai research capability import --definition <absolute-json> [--workspace <absolute-path>] [--json]
|
|
@@ -77,7 +86,7 @@ export function researchOrchestrationHelp() {
|
|
|
77
86
|
tiangong-ai research policy validate <project-id> [--workspace <path>] [--json]
|
|
78
87
|
tiangong-ai research policy approve <project-id> --confirm [--acknowledge-defaults] [--workspace <path>] [--json]
|
|
79
88
|
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]
|
|
89
|
+
tiangong-ai research publication freeze <project-id> --manuscript <absolute-file> --assessment <absolute-json> --submission <absolute-json> --producer-agent codex|claude|workbuddy|codebuddy --producer-session <opaque-id> [--supplements <absolute-json-array>] [--workspace <path>] [--json]
|
|
81
90
|
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
91
|
tiangong-ai research publication review submit <project-id> --role evidence|methods-reproducibility|domain-novelty|journal-editor --review <absolute-json> [--workspace <path>] [--json]
|
|
83
92
|
tiangong-ai research publication status <project-id> [--workspace <path>] [--json]
|
|
@@ -98,7 +107,7 @@ export function researchOrchestrationHelp() {
|
|
|
98
107
|
tiangong-ai research project scientific status <project-id> [--workspace <path>] [--json]
|
|
99
108
|
tiangong-ai research project audit export <project-id> --output <absolute-new-directory> [--workspace <path>] [--json]
|
|
100
109
|
tiangong-ai research project audit verify --bundle <absolute-directory> [--json]
|
|
101
|
-
tiangong-ai research project stage prepare <project-id> --stage discover|acquire|analyze|synthesize --host-agent codex|claude [--workspace <path>] [--json]
|
|
110
|
+
tiangong-ai research project stage prepare <project-id> --stage discover|acquire|analyze|synthesize --host-agent codex|claude|workbuddy|codebuddy [--workspace <path>] [--json]
|
|
102
111
|
tiangong-ai research project stage submit <project-id> --session <id> --output <absolute-json> [--confirm-model <id>] [--workspace <path>] [--json]
|
|
103
112
|
tiangong-ai research project stage abort <project-id> --session <id> [--workspace <path>] [--json]
|
|
104
113
|
tiangong-ai research project evidence fetch <project-id> --request <absolute-json> [--workspace <path>] [--json]
|
|
@@ -107,6 +116,10 @@ export function researchOrchestrationHelp() {
|
|
|
107
116
|
tiangong-ai research project evidence assessment record <project-id> --record <absolute-json> [--workspace <path>] [--json]
|
|
108
117
|
tiangong-ai research project evidence download bind <project-id> --candidate <id> --record <absolute-json> [--workspace <path>] [--json]
|
|
109
118
|
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]
|
|
119
|
+
tiangong-ai research project evidence decomposition record <project-id> --record <absolute-json> [--workspace <path>] [--json]
|
|
120
|
+
tiangong-ai research project evidence atom register <project-id> --record <absolute-json> [--workspace <path>] [--json]
|
|
121
|
+
tiangong-ai research project evidence content freeze <project-id> [--workspace <path>] [--json]
|
|
122
|
+
tiangong-ai research project evidence content status <project-id> [--workspace <path>] [--json]
|
|
110
123
|
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
124
|
tiangong-ai research status [--project <project-id>] [--all] [--workspace <absolute-path>] [--json]
|
|
112
125
|
tiangong-ai research run [--project <project-id>] [--max-parallel <1-8>] [--max-cycles <1-100>] [--dry-run] [--progress-jsonl] [--workspace <absolute-path>] [--json]
|
|
@@ -114,6 +127,92 @@ export function researchOrchestrationHelp() {
|
|
|
114
127
|
${researchSetupHelp()}
|
|
115
128
|
`;
|
|
116
129
|
}
|
|
130
|
+
async function runReviewer(argv, io) {
|
|
131
|
+
const [action, ...rest] = argv;
|
|
132
|
+
if (!action || action === "--help" || action === "-h")
|
|
133
|
+
return writeHelp(io);
|
|
134
|
+
if (action === "status") {
|
|
135
|
+
const args = parseStrictArgs(rest, WORKSPACE_OPTIONS, "research reviewer status");
|
|
136
|
+
if (strictBoolean(args, "help"))
|
|
137
|
+
return writeHelp(io);
|
|
138
|
+
if (args.positionals.length)
|
|
139
|
+
throw unknownAction("research reviewer status", args.positionals[0]);
|
|
140
|
+
const root = await workspaceFromArgs(args);
|
|
141
|
+
writeJson(io, await inspectReviewerBridgeStatus(root), args);
|
|
142
|
+
return 0;
|
|
143
|
+
}
|
|
144
|
+
if (action === "doctor") {
|
|
145
|
+
const args = parseStrictArgs(rest, { ...WORKSPACE_OPTIONS, "confirm-agent-smoke-cost": "boolean" }, "research reviewer doctor");
|
|
146
|
+
if (strictBoolean(args, "help"))
|
|
147
|
+
return writeHelp(io);
|
|
148
|
+
if (args.positionals.length)
|
|
149
|
+
throw unknownAction("research reviewer doctor", args.positionals[0]);
|
|
150
|
+
if (!strictBoolean(args, "confirm-agent-smoke-cost")) {
|
|
151
|
+
throw new CliError("Reviewer doctor requires explicit model-cost confirmation.", {
|
|
152
|
+
code: "RESEARCH_REVIEW_BRIDGE_CONFIRMATION_REQUIRED",
|
|
153
|
+
exitCode: 3,
|
|
154
|
+
details: {
|
|
155
|
+
minimumAction: "Rerun with --confirm-agent-smoke-cost after reviewing reviewer provider quota and cost.",
|
|
156
|
+
},
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
const root = await workspaceFromArgs(args);
|
|
160
|
+
const result = await doctorResearchWorkspace(root, {
|
|
161
|
+
agentSmoke: true,
|
|
162
|
+
environment: io.env,
|
|
163
|
+
});
|
|
164
|
+
writeJson(io, result, args);
|
|
165
|
+
return result.status === "ready" ? 0 : 3;
|
|
166
|
+
}
|
|
167
|
+
if (action === "serve") {
|
|
168
|
+
const args = parseStrictArgs(rest, { ...WORKSPACE_OPTIONS, "state-dir": "string" }, "research reviewer serve");
|
|
169
|
+
if (strictBoolean(args, "help"))
|
|
170
|
+
return writeHelp(io);
|
|
171
|
+
if (args.positionals.length)
|
|
172
|
+
throw unknownAction("research reviewer serve", args.positionals[0]);
|
|
173
|
+
const stateDirectory = strictString(args, "state-dir");
|
|
174
|
+
if (!stateDirectory ||
|
|
175
|
+
!isAbsolute(stateDirectory) ||
|
|
176
|
+
resolve(stateDirectory) !== stateDirectory) {
|
|
177
|
+
throw new CliError("Reviewer sidecar --state-dir must be an explicit absolute directory.", {
|
|
178
|
+
code: "RESEARCH_REVIEW_BRIDGE_STATE_INVALID",
|
|
179
|
+
exitCode: 2,
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
const root = await workspaceFromArgs(args);
|
|
183
|
+
const sidecar = await startReviewerBridgeSidecar({
|
|
184
|
+
root,
|
|
185
|
+
stateDirectory,
|
|
186
|
+
environment: io.env,
|
|
187
|
+
});
|
|
188
|
+
writeJson(io, {
|
|
189
|
+
status: "ready",
|
|
190
|
+
workspaceId: sidecar.workspaceId,
|
|
191
|
+
packageVersion: packageVersion(),
|
|
192
|
+
keyFingerprint: sidecar.keyFingerprint,
|
|
193
|
+
supportedActions: ["execute", "fingerprint", "status"],
|
|
194
|
+
}, args);
|
|
195
|
+
try {
|
|
196
|
+
await waitForReviewerSidecarTermination();
|
|
197
|
+
}
|
|
198
|
+
finally {
|
|
199
|
+
await sidecar.close();
|
|
200
|
+
}
|
|
201
|
+
return 0;
|
|
202
|
+
}
|
|
203
|
+
throw unknownAction("research reviewer", action);
|
|
204
|
+
}
|
|
205
|
+
async function waitForReviewerSidecarTermination() {
|
|
206
|
+
await new Promise((resolvePromise) => {
|
|
207
|
+
const stop = () => {
|
|
208
|
+
process.off("SIGINT", stop);
|
|
209
|
+
process.off("SIGTERM", stop);
|
|
210
|
+
resolvePromise();
|
|
211
|
+
};
|
|
212
|
+
process.once("SIGINT", stop);
|
|
213
|
+
process.once("SIGTERM", stop);
|
|
214
|
+
});
|
|
215
|
+
}
|
|
117
216
|
async function runPublication(argv, io) {
|
|
118
217
|
const [action, ...rest] = argv;
|
|
119
218
|
if (!action || action === "--help" || action === "-h")
|
|
@@ -124,6 +223,7 @@ async function runPublication(argv, io) {
|
|
|
124
223
|
manuscript: "string",
|
|
125
224
|
assessment: "string",
|
|
126
225
|
supplements: "string",
|
|
226
|
+
submission: "string",
|
|
127
227
|
"producer-agent": "string",
|
|
128
228
|
"producer-session": "string",
|
|
129
229
|
}, "research publication freeze");
|
|
@@ -133,8 +233,9 @@ async function runPublication(argv, io) {
|
|
|
133
233
|
const manuscriptPath = strictString(args, "manuscript");
|
|
134
234
|
const assessmentPath = strictString(args, "assessment");
|
|
135
235
|
const producerSessionId = strictString(args, "producer-session");
|
|
136
|
-
|
|
137
|
-
|
|
236
|
+
const submissionPath = strictString(args, "submission");
|
|
237
|
+
if (!manuscriptPath || !assessmentPath || !submissionPath || !producerSessionId) {
|
|
238
|
+
throw new CliError("research publication freeze requires --manuscript, --assessment, --submission, --producer-agent, and --producer-session.", { code: "RESEARCH_PUBLICATION_ARGUMENT_REQUIRED", exitCode: 2 });
|
|
138
239
|
}
|
|
139
240
|
const root = await workspaceFromArgs(args);
|
|
140
241
|
const supplementsPath = strictString(args, "supplements");
|
|
@@ -144,6 +245,7 @@ async function runPublication(argv, io) {
|
|
|
144
245
|
manuscriptPath,
|
|
145
246
|
assessmentPath,
|
|
146
247
|
supplementPaths: supplementsPath ? await readAbsolutePathArray(supplementsPath) : [],
|
|
248
|
+
submissionFiles: await readSubmissionFiles(submissionPath),
|
|
147
249
|
producerAgent: publicationAgent(strictString(args, "producer-agent"), "producer"),
|
|
148
250
|
producerSessionId,
|
|
149
251
|
}), args);
|
|
@@ -949,6 +1051,66 @@ async function runProject(argv, io) {
|
|
|
949
1051
|
writeJson(io, result, args);
|
|
950
1052
|
return 0;
|
|
951
1053
|
}
|
|
1054
|
+
if (evidenceAction === "decomposition") {
|
|
1055
|
+
const [decompositionAction, ...decompositionRest] = evidenceRest;
|
|
1056
|
+
if (decompositionAction !== "record") {
|
|
1057
|
+
throw unknownAction("research project evidence decomposition", decompositionAction ?? "");
|
|
1058
|
+
}
|
|
1059
|
+
const args = parseStrictArgs(decompositionRest, { ...WORKSPACE_OPTIONS, record: "string" }, "research project evidence decomposition record");
|
|
1060
|
+
if (strictBoolean(args, "help"))
|
|
1061
|
+
return writeHelp(io);
|
|
1062
|
+
const projectId = onePositional(args.positionals, "research project evidence decomposition record");
|
|
1063
|
+
const recordPath = strictString(args, "record");
|
|
1064
|
+
if (!recordPath) {
|
|
1065
|
+
throw new CliError("decomposition record requires --record.", {
|
|
1066
|
+
code: "RESEARCH_DECOMPOSITION_INVALID",
|
|
1067
|
+
exitCode: 2,
|
|
1068
|
+
});
|
|
1069
|
+
}
|
|
1070
|
+
const root = await workspaceFromArgs(args);
|
|
1071
|
+
const record = await readBoundedJsonRecord(recordPath, "--record", "RESEARCH_DECOMPOSITION_INVALID");
|
|
1072
|
+
const result = await withWorkspaceLock(root, "research.decomposition.record", () => recordArtifactDecomposition({ root, projectId, value: record }));
|
|
1073
|
+
writeJson(io, result, args);
|
|
1074
|
+
return 0;
|
|
1075
|
+
}
|
|
1076
|
+
if (evidenceAction === "atom") {
|
|
1077
|
+
const [atomAction, ...atomRest] = evidenceRest;
|
|
1078
|
+
if (atomAction !== "register") {
|
|
1079
|
+
throw unknownAction("research project evidence atom", atomAction ?? "");
|
|
1080
|
+
}
|
|
1081
|
+
const args = parseStrictArgs(atomRest, { ...WORKSPACE_OPTIONS, record: "string" }, "research project evidence atom register");
|
|
1082
|
+
if (strictBoolean(args, "help"))
|
|
1083
|
+
return writeHelp(io);
|
|
1084
|
+
const projectId = onePositional(args.positionals, "research project evidence atom register");
|
|
1085
|
+
const recordPath = strictString(args, "record");
|
|
1086
|
+
if (!recordPath) {
|
|
1087
|
+
throw new CliError("atom register requires --record.", {
|
|
1088
|
+
code: "RESEARCH_EVIDENCE_ATOM_INVALID",
|
|
1089
|
+
exitCode: 2,
|
|
1090
|
+
});
|
|
1091
|
+
}
|
|
1092
|
+
const root = await workspaceFromArgs(args);
|
|
1093
|
+
const record = await readBoundedJsonRecord(recordPath, "--record", "RESEARCH_EVIDENCE_ATOM_INVALID");
|
|
1094
|
+
const result = await withWorkspaceLock(root, "research.evidence-atom.register", () => registerEvidenceAtom({ root, projectId, value: record }));
|
|
1095
|
+
writeJson(io, result, args);
|
|
1096
|
+
return 0;
|
|
1097
|
+
}
|
|
1098
|
+
if (evidenceAction === "content") {
|
|
1099
|
+
const [contentAction, ...contentRest] = evidenceRest;
|
|
1100
|
+
if (contentAction !== "freeze" && contentAction !== "status") {
|
|
1101
|
+
throw unknownAction("research project evidence content", contentAction ?? "");
|
|
1102
|
+
}
|
|
1103
|
+
const args = parseStrictArgs(contentRest, WORKSPACE_OPTIONS, `research project evidence content ${contentAction}`);
|
|
1104
|
+
if (strictBoolean(args, "help"))
|
|
1105
|
+
return writeHelp(io);
|
|
1106
|
+
const projectId = onePositional(args.positionals, `research project evidence content ${contentAction}`);
|
|
1107
|
+
const root = await workspaceFromArgs(args);
|
|
1108
|
+
const result = contentAction === "freeze"
|
|
1109
|
+
? await withWorkspaceLock(root, "research.evidence-content.freeze", () => freezeEvidenceContentSnapshot(root, projectId))
|
|
1110
|
+
: await loadCurrentEvidenceContentSnapshot(root, projectId);
|
|
1111
|
+
writeJson(io, result, args);
|
|
1112
|
+
return 0;
|
|
1113
|
+
}
|
|
952
1114
|
if (evidenceAction !== "fetch") {
|
|
953
1115
|
throw unknownAction("research project evidence", evidenceAction ?? "");
|
|
954
1116
|
}
|
|
@@ -1245,6 +1407,7 @@ async function runStatus(argv, io) {
|
|
|
1245
1407
|
return writeHelp(io);
|
|
1246
1408
|
rejectPositionals(args.positionals, "research status");
|
|
1247
1409
|
const root = await workspaceFromArgs(args);
|
|
1410
|
+
const config = await loadWorkspaceConfig(root);
|
|
1248
1411
|
const selectedProject = strictString(args, "project");
|
|
1249
1412
|
const workspaceProjects = await listProjects(root);
|
|
1250
1413
|
const allProjects = selectedProject
|
|
@@ -1260,6 +1423,20 @@ async function runStatus(argv, io) {
|
|
|
1260
1423
|
project.status !== "abandoned");
|
|
1261
1424
|
const result = {
|
|
1262
1425
|
workspace: root,
|
|
1426
|
+
execution: {
|
|
1427
|
+
producer: {
|
|
1428
|
+
host: config.producer.agent,
|
|
1429
|
+
model: config.producer.model,
|
|
1430
|
+
mode: config.producer.executionMode,
|
|
1431
|
+
},
|
|
1432
|
+
reviewer: {
|
|
1433
|
+
agent: config.reviewer.agent,
|
|
1434
|
+
model: config.reviewer.model,
|
|
1435
|
+
mode: config.reviewer.executionMode,
|
|
1436
|
+
transport: config.reviewerExecution.transport,
|
|
1437
|
+
isolationProvider: config.reviewerExecution.isolationProvider,
|
|
1438
|
+
},
|
|
1439
|
+
},
|
|
1263
1440
|
hiddenSupersededProjects: selectedProject || strictBoolean(args, "all")
|
|
1264
1441
|
? 0
|
|
1265
1442
|
: workspaceProjects.filter((project) => project.lineage.supersededBy !== null).length,
|
|
@@ -1272,7 +1449,8 @@ async function runStatus(argv, io) {
|
|
|
1272
1449
|
projects: await Promise.all(projects.map(async (project) => {
|
|
1273
1450
|
const current = refreshProject(project);
|
|
1274
1451
|
const nativeStage = await inspectNativeResearchStage(root, current);
|
|
1275
|
-
const
|
|
1452
|
+
const evidencePipeline = await inspectEvidencePipelineForStatus(root, current);
|
|
1453
|
+
const snapshot = evidencePipeline.acquisition;
|
|
1276
1454
|
const readyPackage = nextReadyPackage(current)?.id ?? null;
|
|
1277
1455
|
const scientificReview = await inspectScientificReviewStatus(root, current.id);
|
|
1278
1456
|
const evidenceAccess = current.scientificDesign
|
|
@@ -1290,12 +1468,13 @@ async function runStatus(argv, io) {
|
|
|
1290
1468
|
handoff: current.handoff,
|
|
1291
1469
|
evidenceState: current.evidenceState,
|
|
1292
1470
|
snapshot,
|
|
1471
|
+
evidencePipeline,
|
|
1293
1472
|
nativeStage,
|
|
1294
1473
|
scientificReview,
|
|
1295
1474
|
evidenceAccess,
|
|
1296
1475
|
publication,
|
|
1297
1476
|
readyPackage,
|
|
1298
|
-
recommendedAction: projectRecommendedAction(root, current, readyPackage, nativeStage, scientificReview, publication),
|
|
1477
|
+
recommendedAction: projectRecommendedAction(root, current, readyPackage, nativeStage, scientificReview, evidencePipeline, publication),
|
|
1299
1478
|
usage: current.usage,
|
|
1300
1479
|
inputs: current.inputs,
|
|
1301
1480
|
packages: current.packages,
|
|
@@ -1306,6 +1485,94 @@ async function runStatus(argv, io) {
|
|
|
1306
1485
|
writeJson(io, result, args);
|
|
1307
1486
|
return 0;
|
|
1308
1487
|
}
|
|
1488
|
+
async function inspectEvidencePipelineForStatus(root, project) {
|
|
1489
|
+
const projectRoot = join(workspacePaths(root).projects, project.id);
|
|
1490
|
+
const acquisition = await inspectSnapshotForStatus(root, project.id);
|
|
1491
|
+
const contentPath = join(projectRoot, "outputs", "content-snapshot.json");
|
|
1492
|
+
let content = { status: "absent" };
|
|
1493
|
+
if (await pathExists(contentPath)) {
|
|
1494
|
+
try {
|
|
1495
|
+
const snapshot = await loadCurrentEvidenceContentSnapshot(root, project.id);
|
|
1496
|
+
content = {
|
|
1497
|
+
status: "verified",
|
|
1498
|
+
snapshotId: snapshot.snapshotId,
|
|
1499
|
+
snapshotSha256: snapshot.snapshotSha256,
|
|
1500
|
+
decompositionCount: snapshot.decompositions.length,
|
|
1501
|
+
atomCount: snapshot.atoms.length,
|
|
1502
|
+
sourceCount: snapshot.sourceCoverage.length,
|
|
1503
|
+
roleCount: snapshot.roleCoverage.length,
|
|
1504
|
+
insufficientRoleIds: snapshot.roleCoverage
|
|
1505
|
+
.filter((role) => role.decision === "insufficient")
|
|
1506
|
+
.map((role) => role.roleId),
|
|
1507
|
+
gate: snapshot.gate,
|
|
1508
|
+
};
|
|
1509
|
+
}
|
|
1510
|
+
catch (error) {
|
|
1511
|
+
content = {
|
|
1512
|
+
status: "invalid",
|
|
1513
|
+
code: error instanceof CliError ? error.code : "RESEARCH_EVIDENCE_CONTENT_SNAPSHOT_INVALID",
|
|
1514
|
+
};
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1517
|
+
const inferencePath = join(projectRoot, "outputs", "inference-snapshot.json");
|
|
1518
|
+
let inference = { status: "absent" };
|
|
1519
|
+
if (await pathExists(inferencePath)) {
|
|
1520
|
+
try {
|
|
1521
|
+
const snapshot = await loadCurrentInferenceSnapshot(root, project.id);
|
|
1522
|
+
inference = {
|
|
1523
|
+
status: "verified",
|
|
1524
|
+
snapshotId: snapshot.snapshotId,
|
|
1525
|
+
snapshotSha256: snapshot.snapshotSha256,
|
|
1526
|
+
sourceCount: snapshot.sources.length,
|
|
1527
|
+
atomCount: snapshot.atoms.length,
|
|
1528
|
+
claimCount: snapshot.claims.length,
|
|
1529
|
+
artifactCount: snapshot.artifactSha256s.length,
|
|
1530
|
+
gate: snapshot.gate,
|
|
1531
|
+
};
|
|
1532
|
+
}
|
|
1533
|
+
catch (error) {
|
|
1534
|
+
inference = {
|
|
1535
|
+
status: "invalid",
|
|
1536
|
+
code: error instanceof CliError ? error.code : "RESEARCH_INFERENCE_SNAPSHOT_INVALID",
|
|
1537
|
+
};
|
|
1538
|
+
}
|
|
1539
|
+
}
|
|
1540
|
+
else if (acquisition.gate?.decision === "stop") {
|
|
1541
|
+
inference = { status: "blocked", gate: acquisition.gate };
|
|
1542
|
+
}
|
|
1543
|
+
else if (content.gate?.decision === "stop") {
|
|
1544
|
+
inference = { status: "blocked", gate: content.gate };
|
|
1545
|
+
}
|
|
1546
|
+
else if (project.scientificDesign && content.status !== "verified") {
|
|
1547
|
+
inference = {
|
|
1548
|
+
status: "blocked",
|
|
1549
|
+
code: "RESEARCH_EVIDENCE_CONTENT_SNAPSHOT_REQUIRED",
|
|
1550
|
+
};
|
|
1551
|
+
}
|
|
1552
|
+
const graphPath = join(projectRoot, "outputs", "claim-evidence-graph.json");
|
|
1553
|
+
let claimGraph = { status: "absent" };
|
|
1554
|
+
if (await pathExists(graphPath)) {
|
|
1555
|
+
try {
|
|
1556
|
+
const graph = await loadCurrentClaimEvidenceGraph(root, project.id);
|
|
1557
|
+
claimGraph = {
|
|
1558
|
+
status: "verified",
|
|
1559
|
+
graphId: graph.graphId,
|
|
1560
|
+
graphSha256: graph.graphSha256,
|
|
1561
|
+
analysisSha256: graph.analysisSha256,
|
|
1562
|
+
analysisRunId: graph.analysisRunId,
|
|
1563
|
+
nodeCount: graph.nodes.length,
|
|
1564
|
+
edgeCount: graph.edges.length,
|
|
1565
|
+
};
|
|
1566
|
+
}
|
|
1567
|
+
catch (error) {
|
|
1568
|
+
claimGraph = {
|
|
1569
|
+
status: "invalid",
|
|
1570
|
+
code: error instanceof CliError ? error.code : "RESEARCH_CLAIM_EVIDENCE_GRAPH_INVALID",
|
|
1571
|
+
};
|
|
1572
|
+
}
|
|
1573
|
+
}
|
|
1574
|
+
return { acquisition, content, inference, claimGraph };
|
|
1575
|
+
}
|
|
1309
1576
|
async function inspectEvidenceAccessForStatus(root, projectId) {
|
|
1310
1577
|
try {
|
|
1311
1578
|
return await inspectEvidenceAccessStatus(root, projectId);
|
|
@@ -1352,6 +1619,8 @@ async function inspectSnapshotForStatus(root, projectId) {
|
|
|
1352
1619
|
parentSnapshotId: snapshot.parentSnapshotId,
|
|
1353
1620
|
sourceCount: snapshot.sources.length,
|
|
1354
1621
|
artifactCount: snapshot.artifacts.length,
|
|
1622
|
+
gapCount: snapshot.gaps.length,
|
|
1623
|
+
gate: snapshot.inferenceGate,
|
|
1355
1624
|
delta: snapshot.delta,
|
|
1356
1625
|
};
|
|
1357
1626
|
}
|
|
@@ -1374,7 +1643,7 @@ async function inspectPublicationForStatus(root, projectId) {
|
|
|
1374
1643
|
};
|
|
1375
1644
|
}
|
|
1376
1645
|
}
|
|
1377
|
-
function projectRecommendedAction(root, project, readyPackage, nativeStage, scientificReview, publication) {
|
|
1646
|
+
function projectRecommendedAction(root, project, readyPackage, nativeStage, scientificReview, evidencePipeline, publication) {
|
|
1378
1647
|
if (project.lineage.supersededBy) {
|
|
1379
1648
|
return `Continue with superseding project ${project.lineage.supersededBy}.`;
|
|
1380
1649
|
}
|
|
@@ -1398,6 +1667,23 @@ function projectRecommendedAction(root, project, readyPackage, nativeStage, scie
|
|
|
1398
1667
|
if (nativeStage.status === "active") {
|
|
1399
1668
|
return nativeStage.recommendedAction ?? "Resume the active native stage.";
|
|
1400
1669
|
}
|
|
1670
|
+
if (readyPackage === "analyze") {
|
|
1671
|
+
if (evidencePipeline.content.status === "absent") {
|
|
1672
|
+
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}`;
|
|
1673
|
+
}
|
|
1674
|
+
if (evidencePipeline.content.status === "invalid") {
|
|
1675
|
+
return `Typed evidence content is invalid (${evidencePipeline.content.code ?? "unknown"}); repair exact decomposition/atom bindings before analysis.`;
|
|
1676
|
+
}
|
|
1677
|
+
if (evidencePipeline.content.gate?.decision === "stop") {
|
|
1678
|
+
return "Typed evidence coverage is insufficient; complete lawful gap filling or request a scope/access handoff instead of starting inference.";
|
|
1679
|
+
}
|
|
1680
|
+
if (evidencePipeline.acquisition.gate?.decision === "stop") {
|
|
1681
|
+
return "Frozen acquisition gaps block inference; request a scope/access handoff after all acquired content is decomposed instead of continuing substitute search.";
|
|
1682
|
+
}
|
|
1683
|
+
if (evidencePipeline.inference.status === "invalid") {
|
|
1684
|
+
return `Inference snapshot is invalid (${evidencePipeline.inference.code ?? "unknown"}); repair its frozen upstream bindings before analysis.`;
|
|
1685
|
+
}
|
|
1686
|
+
}
|
|
1401
1687
|
if (scientificReview.nextGate) {
|
|
1402
1688
|
const gate = scientificReview.nextGate;
|
|
1403
1689
|
if (gate.status === "stopped") {
|
|
@@ -1432,7 +1718,7 @@ function projectRecommendedAction(root, project, readyPackage, nativeStage, scie
|
|
|
1432
1718
|
: "Inspect the blocking package and use explicit retry or fork recovery.";
|
|
1433
1719
|
}
|
|
1434
1720
|
if (readyPackage && ["discover", "acquire", "analyze", "synthesize"].includes(readyPackage)) {
|
|
1435
|
-
return `Prepare native ${readyPackage}: tiangong-ai research project stage prepare ${project.id} --stage ${readyPackage} --host-agent <codex|claude> --workspace ${root}`;
|
|
1721
|
+
return `Prepare native ${readyPackage}: tiangong-ai research project stage prepare ${project.id} --stage ${readyPackage} --host-agent <codex|claude|workbuddy|codebuddy> --workspace ${root}`;
|
|
1436
1722
|
}
|
|
1437
1723
|
return readyPackage === "review"
|
|
1438
1724
|
? `Run the independent reviewer package: tiangong-ai research run --project ${project.id} --workspace ${root}`
|
|
@@ -1553,9 +1839,10 @@ function nativeProducerStage(value) {
|
|
|
1553
1839
|
});
|
|
1554
1840
|
}
|
|
1555
1841
|
function nativeHostAgent(value) {
|
|
1556
|
-
if (value === "codex" || value === "claude")
|
|
1842
|
+
if (value === "codex" || value === "claude" || value === "workbuddy" || value === "codebuddy") {
|
|
1557
1843
|
return value;
|
|
1558
|
-
|
|
1844
|
+
}
|
|
1845
|
+
throw new CliError("--host-agent must be codex, claude, workbuddy, or codebuddy.", {
|
|
1559
1846
|
code: "RESEARCH_NATIVE_HOST_INVALID",
|
|
1560
1847
|
exitCode: 2,
|
|
1561
1848
|
});
|
|
@@ -1668,9 +1955,13 @@ function scientificReviewRole(value) {
|
|
|
1668
1955
|
});
|
|
1669
1956
|
}
|
|
1670
1957
|
function publicationAgent(value, label) {
|
|
1671
|
-
|
|
1958
|
+
const producer = label.includes("producer");
|
|
1959
|
+
if (value === "codex" ||
|
|
1960
|
+
value === "claude" ||
|
|
1961
|
+
(producer && (value === "workbuddy" || value === "codebuddy"))) {
|
|
1672
1962
|
return value;
|
|
1673
|
-
|
|
1963
|
+
}
|
|
1964
|
+
throw new CliError(`--${label}-agent must be ${producer ? "codex, claude, workbuddy, or codebuddy" : "codex or claude"}.`, {
|
|
1674
1965
|
code: "RESEARCH_PUBLICATION_AGENT_INVALID",
|
|
1675
1966
|
exitCode: 2,
|
|
1676
1967
|
});
|
|
@@ -1712,6 +2003,19 @@ async function readAbsolutePathArray(path, option = "supplements") {
|
|
|
1712
2003
|
}
|
|
1713
2004
|
return value;
|
|
1714
2005
|
}
|
|
2006
|
+
async function readSubmissionFiles(path) {
|
|
2007
|
+
const value = await readBoundedJsonRecord(path, "--submission", "RESEARCH_PUBLICATION_SUBMISSION_PACKAGE_INVALID");
|
|
2008
|
+
if (value.schemaVersion !== 1 ||
|
|
2009
|
+
!Array.isArray(value.files) ||
|
|
2010
|
+
value.files.some((file) => !isObject(file) ||
|
|
2011
|
+
typeof file.role !== "string" ||
|
|
2012
|
+
typeof file.path !== "string" ||
|
|
2013
|
+
!isAbsolute(file.path) ||
|
|
2014
|
+
resolve(file.path) !== file.path)) {
|
|
2015
|
+
throw new CliError("--submission must declare schemaVersion 1 and role/path entries with absolute canonical paths.", { code: "RESEARCH_PUBLICATION_SUBMISSION_PACKAGE_INVALID", exitCode: 2 });
|
|
2016
|
+
}
|
|
2017
|
+
return value.files;
|
|
2018
|
+
}
|
|
1715
2019
|
function integerOption(value, fallback, label) {
|
|
1716
2020
|
if (!value)
|
|
1717
2021
|
return fallback;
|