@tiangong-ai/cli 0.0.59 → 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.
- package/AGENTS.md +2 -2
- package/README.md +126 -21
- package/dist/research/orchestration.js +101 -44
- package/dist/research/orchestration.js.map +1 -1
- package/dist/research/workspace/acquisition-forecast.d.ts +3 -0
- package/dist/research/workspace/acquisition-forecast.js +28 -3
- package/dist/research/workspace/acquisition-forecast.js.map +1 -1
- package/dist/research/workspace/acquisition-revision.d.ts +13 -0
- package/dist/research/workspace/acquisition-revision.js +142 -0
- package/dist/research/workspace/acquisition-revision.js.map +1 -0
- package/dist/research/workspace/acquisition.d.ts +3 -1
- package/dist/research/workspace/acquisition.js +67 -35
- package/dist/research/workspace/acquisition.js.map +1 -1
- package/dist/research/workspace/analysis-run.d.ts +2 -0
- package/dist/research/workspace/analysis-run.js +28 -0
- package/dist/research/workspace/analysis-run.js.map +1 -0
- package/dist/research/workspace/artifacts.d.ts +3 -0
- package/dist/research/workspace/artifacts.js +13 -0
- package/dist/research/workspace/artifacts.js.map +1 -1
- package/dist/research/workspace/audit-bundle.d.ts +5 -0
- package/dist/research/workspace/audit-bundle.js +17 -0
- package/dist/research/workspace/audit-bundle.js.map +1 -1
- package/dist/research/workspace/content-evidence.d.ts +3 -0
- package/dist/research/workspace/content-evidence.js +149 -22
- package/dist/research/workspace/content-evidence.js.map +1 -1
- package/dist/research/workspace/project-authority.d.ts +21 -0
- package/dist/research/workspace/project-authority.js +186 -0
- package/dist/research/workspace/project-authority.js.map +1 -0
- package/dist/research/workspace/project-mutations.d.ts +26 -0
- package/dist/research/workspace/project-mutations.js +330 -0
- package/dist/research/workspace/project-mutations.js.map +1 -0
- package/dist/research/workspace/projects.d.ts +2 -1
- package/dist/research/workspace/projects.js +132 -91
- package/dist/research/workspace/projects.js.map +1 -1
- package/dist/research/workspace/publication-workflow.d.ts +3 -0
- package/dist/research/workspace/publication-workflow.js +15 -3
- package/dist/research/workspace/publication-workflow.js.map +1 -1
- package/dist/research/workspace/runtime.d.ts +5 -0
- package/dist/research/workspace/runtime.js +83 -54
- package/dist/research/workspace/runtime.js.map +1 -1
- package/dist/research/workspace/schemas.d.ts +6 -0
- package/dist/research/workspace/schemas.js +13 -2
- package/dist/research/workspace/schemas.js.map +1 -1
- package/dist/research/workspace/scientific-review-execution.js +2 -0
- package/dist/research/workspace/scientific-review-execution.js.map +1 -1
- package/dist/research/workspace/scientific-review.d.ts +3 -1
- package/dist/research/workspace/scientific-review.js +9 -2
- package/dist/research/workspace/scientific-review.js.map +1 -1
- package/dist/research/workspace/setup-catalog.js +2 -2
- package/dist/research/workspace/task-acceptance.d.ts +126 -0
- package/dist/research/workspace/task-acceptance.js +480 -0
- package/dist/research/workspace/task-acceptance.js.map +1 -0
- package/dist/research/workspace/task-audit.d.ts +12 -0
- package/dist/research/workspace/task-audit.js +181 -0
- package/dist/research/workspace/task-audit.js.map +1 -0
- package/dist/research/workspace/task-contract.d.ts +139 -0
- package/dist/research/workspace/task-contract.js +485 -0
- package/dist/research/workspace/task-contract.js.map +1 -0
- package/dist/research/workspace/workspace.js +11 -8
- package/dist/research/workspace/workspace.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-09-
|
|
21
|
-
lastReviewedCommit:
|
|
20
|
+
lastReviewedAt: 2026-09-03
|
|
21
|
+
lastReviewedCommit: 06dadef170ab79c19eef9a35663e86fdee22479b
|
|
22
22
|
---
|
|
23
23
|
|
|
24
24
|
# Tiangong AI CLI Contract
|
package/README.md
CHANGED
|
@@ -12,8 +12,8 @@ checkPaths:
|
|
|
12
12
|
- package.json
|
|
13
13
|
- bin/**
|
|
14
14
|
- src/**
|
|
15
|
-
lastReviewedAt: 2026-09-
|
|
16
|
-
lastReviewedCommit:
|
|
15
|
+
lastReviewedAt: 2026-09-03
|
|
16
|
+
lastReviewedCommit: 06dadef170ab79c19eef9a35663e86fdee22479b
|
|
17
17
|
---
|
|
18
18
|
|
|
19
19
|
# Tiangong AI CLI
|
|
@@ -712,9 +712,15 @@ submission manifest must bind distinct absolute files for cover letter, title
|
|
|
712
712
|
page, reporting checklist, data availability, code availability, and source
|
|
713
713
|
data; figure/table index, extended data, and supplementary methods are optional.
|
|
714
714
|
`research publication freeze` then content-addresses the Policy, scientific
|
|
715
|
-
design and early reviews, acquisition/content/inference snapshots,
|
|
715
|
+
design and early reviews, acquisition/content/inference snapshots, mode-bound
|
|
716
716
|
analysis, Claim-Evidence Graph, base outputs, manuscript, assessment,
|
|
717
717
|
supplements, role-complete submission files, and reproducibility manifest.
|
|
718
|
+
Computational/mixed analysis still requires reproduced metadata with exact
|
|
719
|
+
implementation/environment bindings. Qualitative analysis uses
|
|
720
|
+
`status: not-applicable`, null command/seed and empty implementation/environment
|
|
721
|
+
lists; it must not invent a computation. Both paths retain the same evidence,
|
|
722
|
+
graph, Policy and independent-review checks. Metadata alone is not proof that
|
|
723
|
+
a computation was executed.
|
|
718
724
|
Exactly four fresh independent sessions review that frozen generation:
|
|
719
725
|
evidence, methods/reproducibility, domain/novelty, and journal-editor. A revised
|
|
720
726
|
manuscript invalidates prior reviews. Every reviewer must use the configured
|
|
@@ -1016,6 +1022,14 @@ deficits; exit `0` means only potential eligibility, never successful atom
|
|
|
1016
1022
|
registration, content freeze, independence certification, or review. Pending
|
|
1017
1023
|
input materialization, decomposition, and exact atom assignments remain
|
|
1018
1024
|
explicit. Re-run after material acquisition changes, not after every atom.
|
|
1025
|
+
`submissionGate` separately reports deterministic acquire-submit blockers;
|
|
1026
|
+
`potentially-ready` is not an inference/content pass. An accepted binary without
|
|
1027
|
+
required readable content stops before submission, while an honest incomplete
|
|
1028
|
+
audit may still freeze its limitations and separate inference-stop decision.
|
|
1029
|
+
An admitted local PDF/Office file alone is not producer-readable. Forecast uses
|
|
1030
|
+
the same media rules as artifact registration and reports a missing readable
|
|
1031
|
+
derivative unless a verified readable artifact or admitted text/context input
|
|
1032
|
+
is available. This classification does not reread or decode the binary again.
|
|
1019
1033
|
Flat `sourceTypeRequirements` arrays mean **all-of**. A design may instead use
|
|
1020
1034
|
`{"allOf":["academic-paper"],"anyOf":["government","industry"],"atLeast":{"count":2,"from":["academic-paper","government","industry"]}}`;
|
|
1021
1035
|
every present group applies, and counts use distinct types. Forecast, typed
|
|
@@ -1370,27 +1384,118 @@ read-only under `outputs/revisions/synthesize/<sha256>/report.md`; review and
|
|
|
1370
1384
|
closure are invalidated, while unchanged discovery, acquisition, content,
|
|
1371
1385
|
inference, analysis, and graph objects remain bound.
|
|
1372
1386
|
|
|
1373
|
-
Recovery
|
|
1374
|
-
|
|
1375
|
-
|
|
1387
|
+
Recovery forks have one journal commit point. Before `project.forked` commits,
|
|
1388
|
+
their target is staging, not an authoritative project; the original source
|
|
1389
|
+
remains authoritative. Status, run and native/reviewer admission share that
|
|
1390
|
+
same verified lineage view. A source typed-content snapshot is revalidated
|
|
1376
1391
|
and re-signed for the target generation instead of copying its project-bound
|
|
1377
1392
|
hash. Top-journal generations may resume only through `acquire`, because the
|
|
1378
1393
|
target-specific scientific design must complete fresh evidence-construct and
|
|
1379
|
-
pilot-methods reviews before analysis.
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
`
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
+
pilot-methods reviews before analysis.
|
|
1395
|
+
|
|
1396
|
+
After process interruption, repeat the same explicit fork request. The next
|
|
1397
|
+
lease holder settles only hash-bound CLI-owned pending operations: before
|
|
1398
|
+
commit it retains the interrupted target under
|
|
1399
|
+
`lineage/interrupted-project-mutations/<operation-id>/target`, outside the
|
|
1400
|
+
project namespace; after commit it finishes source/ledger projections. Exact
|
|
1401
|
+
committed replay returns the existing target without recopying evidence or
|
|
1402
|
+
repeating provider work. A different request for that target is a conflict.
|
|
1403
|
+
An unchanged completed retry request is likewise acknowledged without another
|
|
1404
|
+
revision or attempt. A subsequent real failure can still be retried normally.
|
|
1405
|
+
|
|
1406
|
+
Unknown targets, symlink replacements, modified source state and invalid
|
|
1407
|
+
recovery metadata are not overwritten or deleted. Resolve the reported
|
|
1408
|
+
`RESEARCH_PROJECT_RECOVERY_REQUIRED` conflict or restore a trusted backup before
|
|
1409
|
+
retrying; do not forge control files. Read-only status ignores never-committed
|
|
1410
|
+
directories without project state and reports existing uncommitted derived
|
|
1411
|
+
states as invalid. Missing state for a committed project is still an error.
|
|
1412
|
+
Recovery does not truncate a corrupt journal or claim power-loss durability.
|
|
1413
|
+
|
|
1414
|
+
To repair completed acquisition before any analysis attempt, prefer an explicit
|
|
1415
|
+
same-project revision when question, Policy, design, and requirements are unchanged:
|
|
1416
|
+
|
|
1417
|
+
```bash
|
|
1418
|
+
tiangong-ai research project evidence acquisition revise PROJECT \
|
|
1419
|
+
--expected-snapshot <current-acquisition-sha256> \
|
|
1420
|
+
--reason "Add the verified readable derivative before analysis" \
|
|
1421
|
+
--workspace /absolute/workspace --json
|
|
1422
|
+
```
|
|
1423
|
+
|
|
1424
|
+
This reopens acquire, preserves discovery, exact artifacts/receipts, historical
|
|
1425
|
+
snapshot bytes, budgets already spent, and the research-design approval. It
|
|
1426
|
+
invalidates evidence-construct and pilot-methods approvals because their evidence
|
|
1427
|
+
changed. Add `--include-discovery` only when new sources must be discovered or
|
|
1428
|
+
admitted; that explicitly reopens discover then acquire without a new project or
|
|
1429
|
+
automatic provider call. Prepare the returned stage, reuse unchanged objects,
|
|
1430
|
+
forecast once per meaningful batch, submit the complete revised audit, and rebuild
|
|
1431
|
+
typed content. Exact revision replay is idempotent. Stale snapshots, active native
|
|
1432
|
+
sessions, unresolved handoffs, inference freezes, and later attempts are refused.
|
|
1433
|
+
|
|
1434
|
+
Changed failed/limited decomposition records can be superseded under a descendant
|
|
1435
|
+
acquisition snapshot; unchanged records are reused. Single and batch intake share
|
|
1436
|
+
this rule. Historical records remain immutable, and atoms from deselected artifacts
|
|
1437
|
+
cannot fill current coverage. Same-snapshot conflicting extraction still fails.
|
|
1438
|
+
|
|
1439
|
+
Actual question/Policy/design changes or post-analysis work require the existing
|
|
1440
|
+
fork/addendum flow. Pre-feature snapshots without immutable evidence records cannot
|
|
1441
|
+
be repaired in place; use `research project fork SOURCE --to TARGET
|
|
1442
|
+
--resume-through discover` to reuse discovery/receipts/artifacts, or explicitly
|
|
1443
|
+
start a new generation. There is no automatic migration. A top-journal successor
|
|
1444
|
+
requires a Policy approved for TARGET and `--design`, `--design-producer-agent`,
|
|
1445
|
+
and `--design-producer-session`; it cannot inherit scientific approval.
|
|
1446
|
+
|
|
1447
|
+
### Original task, current scope, and actual checks
|
|
1448
|
+
|
|
1449
|
+
For a new research project, record a small original-requirement checklist after
|
|
1450
|
+
project initialization and before any producer execution or scientific review.
|
|
1451
|
+
The native host authors the content; the CLI owns its schema and hash bindings:
|
|
1452
|
+
|
|
1453
|
+
```bash
|
|
1454
|
+
tiangong-ai research schema show task-contract --json
|
|
1455
|
+
tiangong-ai research project task define PROJECT \
|
|
1456
|
+
--input /absolute/task.json --workspace /absolute/workspace --json
|
|
1457
|
+
tiangong-ai research project task status PROJECT --workspace /absolute/workspace --json
|
|
1458
|
+
```
|
|
1459
|
+
|
|
1460
|
+
Each requirement has a stable ID, acceptance condition, `checkKind` (`evidence`,
|
|
1461
|
+
`computation`, or `proof`), and optional bindings to existing design claims and
|
|
1462
|
+
coverage dimensions. Original wording cannot be overwritten. Old projects without
|
|
1463
|
+
a task remain explicitly unassessed rather than retrospectively accepted.
|
|
1464
|
+
|
|
1465
|
+
Before analysis, use `research schema show task-scope-change` and
|
|
1466
|
+
`project task scope propose PROJECT --input FILE --expected-contract SHA` to
|
|
1467
|
+
propose a change. Review the returned `changes.details` before/after values, then
|
|
1468
|
+
approve only with both `--proposal SHA` and `--confirm-change SHA` on
|
|
1469
|
+
`project task scope approve`. A generic continue instruction is not scope consent.
|
|
1470
|
+
The record is an **operator confirmation**, not authenticated proof of a human's
|
|
1471
|
+
identity. Scope approval does not rewrite scientific design or evidence floors;
|
|
1472
|
+
it invalidates prior scoped scientific reviews. Withdrawn original requirements
|
|
1473
|
+
remain visible and a fork/addendum retains original history without inheriting
|
|
1474
|
+
task completion.
|
|
1475
|
+
|
|
1476
|
+
Use `research schema show task-acceptance` and
|
|
1477
|
+
`project task acceptance record PROJECT --input FILE` after acquisition and
|
|
1478
|
+
between native stages. Records bind the exact requirement version, source/atom/
|
|
1479
|
+
finding IDs, and explicitly selected bounded UTF-8 result files. The declared
|
|
1480
|
+
command is stored only by hash and is **not executed by this command**. Raw result
|
|
1481
|
+
bytes are copied into immutable hash-addressed objects; secrets and control-store
|
|
1482
|
+
sources are rejected. Positive/negative computational outcomes need a command and
|
|
1483
|
+
results; failed, inconclusive, and not-run checks remain honest without invented
|
|
1484
|
+
results. All records say `trust=native-observation`, `executionCertified=false`.
|
|
1485
|
+
|
|
1486
|
+
One unchanged result blob is stored and included once per reviewer context. The
|
|
1487
|
+
existing independent review receives the original request, original/current
|
|
1488
|
+
requirements, exact checks and results, and returns a bound `taskAssessment`;
|
|
1489
|
+
there is no additional default paid review round. Missing current checks stop
|
|
1490
|
+
before review, and stale/failed/inconclusive checks cannot be promoted to answered.
|
|
1491
|
+
Publication packets and portable audit verification retain these relationships;
|
|
1492
|
+
hash integrity does not prove execution, scientific validity, or editorial acceptance.
|
|
1493
|
+
|
|
1494
|
+
`project task status` and each `research run` project summary report original and
|
|
1495
|
+
current task completion separately from workflow completion and publication verdict.
|
|
1496
|
+
A completed workflow or approved reduced scope must not be described as satisfying
|
|
1497
|
+
unanswered original requirements. Use the selected runtime's help/schema discovery
|
|
1498
|
+
once before adopting these commands; they are not an implicit runtime upgrade.
|
|
1394
1499
|
|
|
1395
1500
|
## Research Search
|
|
1396
1501
|
|
|
@@ -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
|
|
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 (
|
|
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.
|
|
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
|
|
1607
|
-
const
|
|
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.
|
|
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.
|
|
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,
|
|
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)))
|