@tiangong-ai/cli 0.0.44 → 0.0.46
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 +5 -1
- package/README.md +35 -2
- package/dist/research/orchestration.js +71 -0
- package/dist/research/orchestration.js.map +1 -1
- package/dist/research/workspace/executor.js +10 -3
- package/dist/research/workspace/executor.js.map +1 -1
- package/dist/research/workspace/inference.js +6 -2
- package/dist/research/workspace/inference.js.map +1 -1
- package/dist/research/workspace/platform-capabilities.d.ts +25 -0
- package/dist/research/workspace/platform-capabilities.js +87 -0
- package/dist/research/workspace/platform-capabilities.js.map +1 -0
- package/dist/research/workspace/preflight.js +5 -0
- package/dist/research/workspace/preflight.js.map +1 -1
- package/dist/research/workspace/projects.js +10 -0
- package/dist/research/workspace/projects.js.map +1 -1
- package/dist/research/workspace/review-executor.js +29 -2
- package/dist/research/workspace/review-executor.js.map +1 -1
- package/dist/research/workspace/scientific-design.d.ts +5 -5
- package/dist/research/workspace/scientific-design.js +92 -16
- package/dist/research/workspace/scientific-design.js.map +1 -1
- package/dist/research/workspace/scientific-objects.d.ts +53 -0
- package/dist/research/workspace/scientific-objects.js +400 -0
- package/dist/research/workspace/scientific-objects.js.map +1 -0
- package/dist/research/workspace/scientific-review.d.ts +4 -0
- package/dist/research/workspace/scientific-review.js +87 -25
- 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 +15 -13
- package/dist/research/workspace/setup.js.map +1 -1
- package/dist/research/workspace/storage.d.ts +1 -0
- package/dist/research/workspace/storage.js +7 -0
- package/dist/research/workspace/storage.js.map +1 -1
- package/package.json +2 -1
|
@@ -0,0 +1,400 @@
|
|
|
1
|
+
import { lstat, readFile, realpath } from "node:fs/promises";
|
|
2
|
+
import { extname, isAbsolute, resolve, sep, win32 } from "node:path";
|
|
3
|
+
import { CliError } from "../../errors.js";
|
|
4
|
+
import { classifyPlatformPathRelation } from "./platform-capabilities.js";
|
|
5
|
+
import { canonicalJson, isObject, pathExists, resolveContained, sha256Bytes, sha256File, sha256Text, workspacePaths, writeBytesAtomic, writeJsonAtomic, } from "./storage.js";
|
|
6
|
+
export const SCIENTIFIC_OBJECT_KINDS = ["model-implementation", "environment-lock"];
|
|
7
|
+
const MAX_SCIENTIFIC_OBJECT_BYTES = 2 * 1024 * 1024;
|
|
8
|
+
const SHA256 = /^[a-f0-9]{64}$/;
|
|
9
|
+
const REGISTERED_OBJECT_LOCATOR = /^lineage\/objects\/([a-f0-9]{64})\/blob$/;
|
|
10
|
+
const REVIEWABLE_MEDIA_TYPE = /^(?:text\/[a-z0-9.+-]+|application\/(?:json|toml|yaml|x-yaml))$/;
|
|
11
|
+
export function parseScientificObjectKind(value) {
|
|
12
|
+
if (SCIENTIFIC_OBJECT_KINDS.includes(value)) {
|
|
13
|
+
return value;
|
|
14
|
+
}
|
|
15
|
+
throw scientificObjectInputError("Scientific object kind must be model-implementation or environment-lock.", "kind-invalid");
|
|
16
|
+
}
|
|
17
|
+
export async function registerScientificObject(input) {
|
|
18
|
+
const sourcePath = await exactExternalFile(input.root, input.path);
|
|
19
|
+
const info = await lstat(sourcePath);
|
|
20
|
+
if (info.size < 1 || info.size > MAX_SCIENTIFIC_OBJECT_BYTES) {
|
|
21
|
+
throw scientificObjectInputError(`Scientific object size must be 1-${MAX_SCIENTIFIC_OBJECT_BYTES} bytes.`, "size-invalid");
|
|
22
|
+
}
|
|
23
|
+
const bytes = await readFile(sourcePath);
|
|
24
|
+
const mediaType = normalizeScientificMediaType(input.mediaType ?? inferScientificMediaType(sourcePath));
|
|
25
|
+
validateReviewableBytes(bytes, mediaType);
|
|
26
|
+
const sha256 = sha256Bytes(bytes);
|
|
27
|
+
const objectLocator = scientificObjectLocator(sha256);
|
|
28
|
+
const recordLocator = scientificObjectRecordLocator(sha256, input.objectKind);
|
|
29
|
+
const objectPath = resolveContained(workspacePaths(input.root).control, objectLocator);
|
|
30
|
+
const recordPath = resolveContained(workspacePaths(input.root).control, recordLocator);
|
|
31
|
+
if (await pathExists(objectPath)) {
|
|
32
|
+
await assertImmutableBlob(objectPath, input.objectKind, sha256, bytes.byteLength);
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
await writeBytesAtomic(objectPath, bytes, 0o444);
|
|
36
|
+
}
|
|
37
|
+
if (await pathExists(recordPath)) {
|
|
38
|
+
const existing = await readAndVerifyScientificObjectRecord(input.root, {
|
|
39
|
+
objectKind: input.objectKind,
|
|
40
|
+
objectLocator,
|
|
41
|
+
expectedSha256: sha256,
|
|
42
|
+
});
|
|
43
|
+
if (existing.mediaType !== mediaType) {
|
|
44
|
+
throw scientificObjectBindingError("Scientific object metadata has drifted.", [
|
|
45
|
+
{
|
|
46
|
+
modelId: "unbound",
|
|
47
|
+
artifactKind: input.objectKind === "model-implementation" ? "implementation" : "environment-lock",
|
|
48
|
+
objectKind: input.objectKind,
|
|
49
|
+
reason: "media-type-unsupported",
|
|
50
|
+
},
|
|
51
|
+
]);
|
|
52
|
+
}
|
|
53
|
+
return existing;
|
|
54
|
+
}
|
|
55
|
+
const core = {
|
|
56
|
+
schemaVersion: 1,
|
|
57
|
+
kind: "tiangong-scientific-object",
|
|
58
|
+
objectKind: input.objectKind,
|
|
59
|
+
sha256,
|
|
60
|
+
bytes: bytes.byteLength,
|
|
61
|
+
mediaType,
|
|
62
|
+
hashBasis: "raw-file-bytes",
|
|
63
|
+
objectLocator,
|
|
64
|
+
recordLocator,
|
|
65
|
+
};
|
|
66
|
+
const record = {
|
|
67
|
+
...core,
|
|
68
|
+
recordSha256: sha256Text(canonicalJson(core)),
|
|
69
|
+
};
|
|
70
|
+
await writeJsonAtomic(recordPath, record, 0o444);
|
|
71
|
+
return record;
|
|
72
|
+
}
|
|
73
|
+
export async function inspectScientificObject(input) {
|
|
74
|
+
const match = REGISTERED_OBJECT_LOCATOR.exec(input.objectLocator);
|
|
75
|
+
if (!match) {
|
|
76
|
+
throw scientificObjectBindingError("Scientific object locator is not registered.", [
|
|
77
|
+
{
|
|
78
|
+
modelId: "unbound",
|
|
79
|
+
artifactKind: input.objectKind === "model-implementation" ? "implementation" : "environment-lock",
|
|
80
|
+
objectKind: input.objectKind,
|
|
81
|
+
reason: "source-not-registered",
|
|
82
|
+
},
|
|
83
|
+
]);
|
|
84
|
+
}
|
|
85
|
+
return readAndVerifyScientificObjectRecord(input.root, {
|
|
86
|
+
objectKind: input.objectKind,
|
|
87
|
+
objectLocator: input.objectLocator,
|
|
88
|
+
expectedSha256: match[1],
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
export async function resolveScientificObjectBinding(input) {
|
|
92
|
+
const registered = REGISTERED_OBJECT_LOCATOR.exec(input.objectLocator);
|
|
93
|
+
if (registered) {
|
|
94
|
+
if (registered[1] !== input.expectedSha256) {
|
|
95
|
+
throw bindingFailure(input.objectKind, "content-hash-mismatch");
|
|
96
|
+
}
|
|
97
|
+
const record = await readAndVerifyScientificObjectRecord(input.root, input);
|
|
98
|
+
return {
|
|
99
|
+
sourcePath: resolveContained(workspacePaths(input.root).control, record.objectLocator),
|
|
100
|
+
sha256: record.sha256,
|
|
101
|
+
bytes: record.bytes,
|
|
102
|
+
mediaType: record.mediaType,
|
|
103
|
+
objectKind: record.objectKind,
|
|
104
|
+
sourceLocator: record.objectLocator,
|
|
105
|
+
record,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
throw bindingFailure(input.objectKind, "source-not-registered");
|
|
109
|
+
}
|
|
110
|
+
export async function inspectScientificDesignObjectBindings(root, design) {
|
|
111
|
+
const issues = [];
|
|
112
|
+
for (const model of design.identity.modelStructures) {
|
|
113
|
+
if (model.implementationStatus === "executable-frozen") {
|
|
114
|
+
await inspectOne({
|
|
115
|
+
root,
|
|
116
|
+
modelId: model.id,
|
|
117
|
+
artifactKind: "implementation",
|
|
118
|
+
objectKind: "model-implementation",
|
|
119
|
+
objectLocator: model.implementationArtifactLocator,
|
|
120
|
+
expectedSha256: model.implementationArtifactSha256,
|
|
121
|
+
issues,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
if (model.environmentLockStatus === "exact-frozen") {
|
|
125
|
+
await inspectOne({
|
|
126
|
+
root,
|
|
127
|
+
modelId: model.id,
|
|
128
|
+
artifactKind: "environment-lock",
|
|
129
|
+
objectKind: "environment-lock",
|
|
130
|
+
objectLocator: model.environmentLockLocator,
|
|
131
|
+
expectedSha256: model.environmentLockSha256,
|
|
132
|
+
issues,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return issues;
|
|
137
|
+
}
|
|
138
|
+
export async function assertScientificDesignObjectBindings(root, design) {
|
|
139
|
+
const issues = await inspectScientificDesignObjectBindings(root, design);
|
|
140
|
+
if (issues.length) {
|
|
141
|
+
throw scientificObjectBindingError("Scientific design contains an unregistered or invalid frozen object.", issues);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
export function scientificObjectLocator(sha256) {
|
|
145
|
+
if (!SHA256.test(sha256)) {
|
|
146
|
+
throw scientificObjectInputError("Scientific object SHA-256 is invalid.", "sha256-invalid");
|
|
147
|
+
}
|
|
148
|
+
return `lineage/objects/${sha256}/blob`;
|
|
149
|
+
}
|
|
150
|
+
function scientificObjectRecordLocator(sha256, objectKind) {
|
|
151
|
+
return `lineage/objects/${sha256}/${objectKind}.json`;
|
|
152
|
+
}
|
|
153
|
+
async function inspectOne(input) {
|
|
154
|
+
if (!input.objectLocator || !input.expectedSha256) {
|
|
155
|
+
input.issues.push({
|
|
156
|
+
modelId: input.modelId,
|
|
157
|
+
artifactKind: input.artifactKind,
|
|
158
|
+
objectKind: input.objectKind,
|
|
159
|
+
reason: "source-not-registered",
|
|
160
|
+
});
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
try {
|
|
164
|
+
await resolveScientificObjectBinding({
|
|
165
|
+
root: input.root,
|
|
166
|
+
objectKind: input.objectKind,
|
|
167
|
+
objectLocator: input.objectLocator,
|
|
168
|
+
expectedSha256: input.expectedSha256,
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
catch (error) {
|
|
172
|
+
input.issues.push({
|
|
173
|
+
modelId: input.modelId,
|
|
174
|
+
artifactKind: input.artifactKind,
|
|
175
|
+
objectKind: input.objectKind,
|
|
176
|
+
reason: bindingReason(error),
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
async function readAndVerifyScientificObjectRecord(root, input) {
|
|
181
|
+
const recordLocator = scientificObjectRecordLocator(input.expectedSha256, input.objectKind);
|
|
182
|
+
const recordPath = resolveContained(workspacePaths(root).control, recordLocator);
|
|
183
|
+
const recordInfo = await lstat(recordPath).catch(() => undefined);
|
|
184
|
+
if (recordInfo && (!recordInfo.isFile() || recordInfo.isSymbolicLink())) {
|
|
185
|
+
throw bindingFailure(input.objectKind, "source-object-unsafe");
|
|
186
|
+
}
|
|
187
|
+
if (!recordInfo) {
|
|
188
|
+
const alternateKind = input.objectKind === "model-implementation" ? "environment-lock" : "model-implementation";
|
|
189
|
+
const alternate = resolveContained(workspacePaths(root).control, scientificObjectRecordLocator(input.expectedSha256, alternateKind));
|
|
190
|
+
if (await pathExists(alternate))
|
|
191
|
+
throw bindingFailure(input.objectKind, "kind-mismatch");
|
|
192
|
+
throw bindingFailure(input.objectKind, "source-not-registered");
|
|
193
|
+
}
|
|
194
|
+
let value;
|
|
195
|
+
try {
|
|
196
|
+
value = JSON.parse(await readFile(recordPath, "utf8"));
|
|
197
|
+
}
|
|
198
|
+
catch {
|
|
199
|
+
throw bindingFailure(input.objectKind, "record-invalid");
|
|
200
|
+
}
|
|
201
|
+
if (!isScientificObjectRecord(value)) {
|
|
202
|
+
throw bindingFailure(input.objectKind, "record-invalid");
|
|
203
|
+
}
|
|
204
|
+
const { recordSha256, ...core } = value;
|
|
205
|
+
if (value.objectKind !== input.objectKind ||
|
|
206
|
+
value.objectLocator !== input.objectLocator ||
|
|
207
|
+
value.recordLocator !== recordLocator ||
|
|
208
|
+
value.sha256 !== input.expectedSha256 ||
|
|
209
|
+
recordSha256 !== sha256Text(canonicalJson(core))) {
|
|
210
|
+
throw bindingFailure(input.objectKind, value.objectKind !== input.objectKind ? "kind-mismatch" : "record-invalid");
|
|
211
|
+
}
|
|
212
|
+
const objectPath = resolveContained(workspacePaths(root).control, value.objectLocator);
|
|
213
|
+
await assertImmutableBlob(objectPath, input.objectKind, value.sha256, value.bytes);
|
|
214
|
+
return value;
|
|
215
|
+
}
|
|
216
|
+
function isScientificObjectRecord(value) {
|
|
217
|
+
if (!isObject(value))
|
|
218
|
+
return false;
|
|
219
|
+
const allowed = new Set([
|
|
220
|
+
"schemaVersion",
|
|
221
|
+
"kind",
|
|
222
|
+
"objectKind",
|
|
223
|
+
"sha256",
|
|
224
|
+
"bytes",
|
|
225
|
+
"mediaType",
|
|
226
|
+
"hashBasis",
|
|
227
|
+
"objectLocator",
|
|
228
|
+
"recordLocator",
|
|
229
|
+
"recordSha256",
|
|
230
|
+
]);
|
|
231
|
+
return (Object.keys(value).every((key) => allowed.has(key)) &&
|
|
232
|
+
value.schemaVersion === 1 &&
|
|
233
|
+
value.kind === "tiangong-scientific-object" &&
|
|
234
|
+
SCIENTIFIC_OBJECT_KINDS.includes(value.objectKind) &&
|
|
235
|
+
typeof value.sha256 === "string" &&
|
|
236
|
+
SHA256.test(value.sha256) &&
|
|
237
|
+
Number.isSafeInteger(value.bytes) &&
|
|
238
|
+
Number(value.bytes) >= 1 &&
|
|
239
|
+
Number(value.bytes) <= MAX_SCIENTIFIC_OBJECT_BYTES &&
|
|
240
|
+
typeof value.mediaType === "string" &&
|
|
241
|
+
REVIEWABLE_MEDIA_TYPE.test(value.mediaType) &&
|
|
242
|
+
value.hashBasis === "raw-file-bytes" &&
|
|
243
|
+
typeof value.objectLocator === "string" &&
|
|
244
|
+
typeof value.recordLocator === "string" &&
|
|
245
|
+
typeof value.recordSha256 === "string" &&
|
|
246
|
+
SHA256.test(value.recordSha256));
|
|
247
|
+
}
|
|
248
|
+
async function exactExternalFile(root, path) {
|
|
249
|
+
if (!path || !isAbsolute(path) || resolve(path) !== path || path.includes("\0")) {
|
|
250
|
+
throw scientificObjectInputError("Scientific object path must be an explicit canonical absolute path.", "path-invalid");
|
|
251
|
+
}
|
|
252
|
+
const selectedInfo = await lstat(path).catch(() => undefined);
|
|
253
|
+
if (!selectedInfo?.isFile() || selectedInfo.isSymbolicLink()) {
|
|
254
|
+
throw scientificObjectInputError("Scientific object path must name one regular non-symlink file.", "path-unsafe");
|
|
255
|
+
}
|
|
256
|
+
const canonical = await realpath(path).catch(() => null);
|
|
257
|
+
if (!canonical) {
|
|
258
|
+
throw scientificObjectInputError("Scientific object path must be one regular non-symlink file.", "path-unsafe");
|
|
259
|
+
}
|
|
260
|
+
const lexicalControl = resolve(workspacePaths(root).control);
|
|
261
|
+
const control = await realpath(lexicalControl).catch(() => lexicalControl);
|
|
262
|
+
const relation = classifyPlatformPathRelation({
|
|
263
|
+
platform: process.platform,
|
|
264
|
+
root: control,
|
|
265
|
+
candidate: canonical,
|
|
266
|
+
});
|
|
267
|
+
if (relation !== "outside") {
|
|
268
|
+
throw scientificObjectInputError("Scientific object source must originate outside the research control directory.", "path-inside-control");
|
|
269
|
+
}
|
|
270
|
+
return canonical;
|
|
271
|
+
}
|
|
272
|
+
export function isContainedRelativePath(value) {
|
|
273
|
+
return (value !== ".." &&
|
|
274
|
+
!value.startsWith(`..${sep}`) &&
|
|
275
|
+
!value.startsWith("../") &&
|
|
276
|
+
!value.startsWith("..\\") &&
|
|
277
|
+
!isAbsolute(value) &&
|
|
278
|
+
!win32.isAbsolute(value));
|
|
279
|
+
}
|
|
280
|
+
async function assertImmutableBlob(path, objectKind, sha256, bytes) {
|
|
281
|
+
const info = await lstat(path).catch(() => undefined);
|
|
282
|
+
if (!info) {
|
|
283
|
+
throw bindingFailure(objectKind, "object-missing");
|
|
284
|
+
}
|
|
285
|
+
if (!info.isFile() || info.isSymbolicLink()) {
|
|
286
|
+
throw bindingFailure(objectKind, "source-object-unsafe");
|
|
287
|
+
}
|
|
288
|
+
if (info.size !== bytes || (await sha256File(path)) !== sha256) {
|
|
289
|
+
throw bindingFailure(objectKind, "content-hash-mismatch");
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
function normalizeScientificMediaType(value) {
|
|
293
|
+
const normalized = value.trim().toLowerCase().split(";", 1)[0] ?? "";
|
|
294
|
+
if (!REVIEWABLE_MEDIA_TYPE.test(normalized)) {
|
|
295
|
+
throw scientificObjectInputError("Scientific objects require a reviewable UTF-8 text, JSON, TOML, or YAML media type.", "media-type-unsupported");
|
|
296
|
+
}
|
|
297
|
+
return normalized;
|
|
298
|
+
}
|
|
299
|
+
function inferScientificMediaType(path) {
|
|
300
|
+
const extension = extname(path).toLowerCase();
|
|
301
|
+
const mediaTypes = {
|
|
302
|
+
".py": "text/x-python",
|
|
303
|
+
".js": "text/javascript",
|
|
304
|
+
".mjs": "text/javascript",
|
|
305
|
+
".cjs": "text/javascript",
|
|
306
|
+
".ts": "text/typescript",
|
|
307
|
+
".mts": "text/typescript",
|
|
308
|
+
".cts": "text/typescript",
|
|
309
|
+
".r": "text/x-r-source",
|
|
310
|
+
".jl": "text/x-julia",
|
|
311
|
+
".sh": "text/x-shellscript",
|
|
312
|
+
".lock": "text/plain",
|
|
313
|
+
".txt": "text/plain",
|
|
314
|
+
".json": "application/json",
|
|
315
|
+
".toml": "application/toml",
|
|
316
|
+
".yaml": "application/yaml",
|
|
317
|
+
".yml": "application/yaml",
|
|
318
|
+
};
|
|
319
|
+
const mediaType = mediaTypes[extension];
|
|
320
|
+
if (!mediaType) {
|
|
321
|
+
throw scientificObjectInputError("Cannot infer a reviewable scientific object media type; provide --media-type.", "media-type-unsupported");
|
|
322
|
+
}
|
|
323
|
+
return mediaType;
|
|
324
|
+
}
|
|
325
|
+
function validateReviewableBytes(bytes, mediaType) {
|
|
326
|
+
let text;
|
|
327
|
+
try {
|
|
328
|
+
text = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
|
329
|
+
}
|
|
330
|
+
catch {
|
|
331
|
+
throw scientificObjectInputError("Scientific object bytes must be valid UTF-8 for independent review.", "content-not-utf8");
|
|
332
|
+
}
|
|
333
|
+
if (text.includes("\0")) {
|
|
334
|
+
throw scientificObjectInputError("Scientific object text cannot contain NUL bytes.", "content-invalid");
|
|
335
|
+
}
|
|
336
|
+
if (mediaType === "application/json") {
|
|
337
|
+
try {
|
|
338
|
+
JSON.parse(text);
|
|
339
|
+
}
|
|
340
|
+
catch {
|
|
341
|
+
throw scientificObjectInputError("A scientific object declared as application/json must contain valid JSON.", "json-invalid");
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
function bindingReason(error) {
|
|
346
|
+
if (error instanceof CliError && isObject(error.details)) {
|
|
347
|
+
const reason = error.details.reason;
|
|
348
|
+
if ([
|
|
349
|
+
"source-not-registered",
|
|
350
|
+
"object-missing",
|
|
351
|
+
"source-object-unsafe",
|
|
352
|
+
"content-hash-mismatch",
|
|
353
|
+
"record-invalid",
|
|
354
|
+
"kind-mismatch",
|
|
355
|
+
"media-type-unsupported",
|
|
356
|
+
"not-reviewable-json",
|
|
357
|
+
"oversized",
|
|
358
|
+
].includes(String(reason))) {
|
|
359
|
+
return reason;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
return "record-invalid";
|
|
363
|
+
}
|
|
364
|
+
function bindingFailure(objectKind, reason) {
|
|
365
|
+
return new CliError("A scientific object failed its immutable binding.", {
|
|
366
|
+
code: "RESEARCH_SCIENTIFIC_OBJECT_BINDING_INVALID",
|
|
367
|
+
exitCode: 3,
|
|
368
|
+
details: { objectKind, reason, minimumAction: scientificObjectBindingAction(reason) },
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
function scientificObjectBindingError(message, issues) {
|
|
372
|
+
return new CliError(message, {
|
|
373
|
+
code: "RESEARCH_SCIENTIFIC_OBJECT_BINDING_INVALID",
|
|
374
|
+
exitCode: 3,
|
|
375
|
+
details: {
|
|
376
|
+
issues,
|
|
377
|
+
minimumAction: "Register each frozen external file with research scientific object register, copy its returned kind, SHA-256, and locator into a new design generation, then rerun preflight.",
|
|
378
|
+
},
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
function scientificObjectInputError(message, reason) {
|
|
382
|
+
return new CliError(message, {
|
|
383
|
+
code: "RESEARCH_SCIENTIFIC_OBJECT_INVALID",
|
|
384
|
+
exitCode: 2,
|
|
385
|
+
details: {
|
|
386
|
+
reason,
|
|
387
|
+
minimumAction: "Select one canonical regular non-symlink UTF-8 file outside .tiangong-research and register it with an explicit supported kind and media type.",
|
|
388
|
+
},
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
function scientificObjectBindingAction(reason) {
|
|
392
|
+
if (reason === "object-missing" || reason === "content-hash-mismatch") {
|
|
393
|
+
return "Restore the exact registered bytes from a trusted source or create a new authoritative design generation bound to a newly registered object.";
|
|
394
|
+
}
|
|
395
|
+
if (reason === "kind-mismatch") {
|
|
396
|
+
return "Register the source under the design field's exact object kind and bind the returned locator in a new authoritative design generation.";
|
|
397
|
+
}
|
|
398
|
+
return "Register the external source through research scientific object register and bind the exact returned record in a new authoritative design generation.";
|
|
399
|
+
}
|
|
400
|
+
//# sourceMappingURL=scientific-objects.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scientific-objects.js","sourceRoot":"","sources":["../../../src/research/workspace/scientific-objects.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { nextScientificGate } from "./projects.js";
|
|
2
|
+
import { type ScientificObjectKind } from "./scientific-objects.js";
|
|
2
3
|
import type { AgentKind, ProjectState, ScientificReviewRole, ScientificGateStatus } from "./types.js";
|
|
3
4
|
interface ScientificMechanicalIssue {
|
|
4
5
|
code: string;
|
|
@@ -19,6 +20,9 @@ interface ScientificReviewStageInput {
|
|
|
19
20
|
ownerId: string;
|
|
20
21
|
sourceLocator: string;
|
|
21
22
|
hashBasis: "raw-file-bytes";
|
|
23
|
+
mediaType: string;
|
|
24
|
+
objectKind: ScientificObjectKind | null;
|
|
25
|
+
registrationRecordSha256: string | null;
|
|
22
26
|
}
|
|
23
27
|
export interface ScientificReviewPacket {
|
|
24
28
|
schemaVersion: 1;
|
|
@@ -5,8 +5,9 @@ import { CliError } from "../../errors.js";
|
|
|
5
5
|
import { appendJournalEvent, verifyJournal } from "./journal.js";
|
|
6
6
|
import { loadProject, nextScientificGate, saveProject } from "./projects.js";
|
|
7
7
|
import { evaluateScientificDesign, parseScientificDesign, scientificDesignPolicyGaps, } from "./scientific-design.js";
|
|
8
|
+
import { resolveScientificObjectBinding } from "./scientific-objects.js";
|
|
8
9
|
import { sanitizeResearchValue } from "./sanitization.js";
|
|
9
|
-
import { canonicalJson, fileRecord, isObject, pathExists, resolveContained, sha256File, sha256Text, workspacePaths, writeJsonAtomic, writeTextAtomic, } from "./storage.js";
|
|
10
|
+
import { canonicalJson, fileRecord, isObject, pathExists, resolveContained, sha256File, sha256Text, workspacePaths, writeBytesAtomic, writeJsonAtomic, writeTextAtomic, } from "./storage.js";
|
|
10
11
|
import { loadWorkspaceConfig, withWorkspaceLock } from "./workspace.js";
|
|
11
12
|
const MAX_SCIENTIFIC_REVIEW_BYTES = 2 * 1024 * 1024;
|
|
12
13
|
const SHA256_PATTERN = "^[a-f0-9]{64}$";
|
|
@@ -725,7 +726,7 @@ async function stageInputRecords(root, project, role, design, assessment, canary
|
|
|
725
726
|
const projectRoot = join(paths.projects, project.id);
|
|
726
727
|
if (role === "research-design") {
|
|
727
728
|
const records = [];
|
|
728
|
-
const
|
|
729
|
+
const promoteLegacyJson = async (input) => {
|
|
729
730
|
const source = resolveContained(paths.control, input.sourceLocator);
|
|
730
731
|
const info = await lstat(source).catch(() => undefined);
|
|
731
732
|
if (!info?.isFile() || info.isSymbolicLink()) {
|
|
@@ -766,27 +767,38 @@ async function stageInputRecords(root, project, role, design, assessment, canary
|
|
|
766
767
|
ownerId: input.ownerId,
|
|
767
768
|
sourceLocator: input.sourceLocator,
|
|
768
769
|
hashBasis: "raw-file-bytes",
|
|
770
|
+
mediaType: "application/json",
|
|
771
|
+
objectKind: null,
|
|
772
|
+
registrationRecordSha256: null,
|
|
769
773
|
});
|
|
770
774
|
};
|
|
771
775
|
for (const model of design.identity.modelStructures) {
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
776
|
+
if (model.implementationStatus === "executable-frozen") {
|
|
777
|
+
records.push(await promoteRegisteredModelObject({
|
|
778
|
+
root,
|
|
779
|
+
projectId: project.id,
|
|
780
|
+
objectKind: "model-implementation",
|
|
781
|
+
sourceLocator: model.implementationArtifactLocator,
|
|
782
|
+
sha256: model.implementationArtifactSha256,
|
|
783
|
+
purpose: "model-implementation",
|
|
784
|
+
ownerId: model.id,
|
|
785
|
+
}));
|
|
786
|
+
}
|
|
787
|
+
if (model.environmentLockStatus === "exact-frozen") {
|
|
788
|
+
records.push(await promoteRegisteredModelObject({
|
|
789
|
+
root,
|
|
790
|
+
projectId: project.id,
|
|
791
|
+
objectKind: "environment-lock",
|
|
792
|
+
sourceLocator: model.environmentLockLocator,
|
|
793
|
+
sha256: model.environmentLockSha256,
|
|
794
|
+
purpose: "model-environment-lock",
|
|
795
|
+
ownerId: model.id,
|
|
796
|
+
}));
|
|
797
|
+
}
|
|
786
798
|
}
|
|
787
799
|
for (const gap of design.knownGaps) {
|
|
788
800
|
for (const artifact of gap.sourceArtifacts) {
|
|
789
|
-
await
|
|
801
|
+
await promoteLegacyJson({
|
|
790
802
|
sourceLocator: artifact.objectLocator,
|
|
791
803
|
sha256: artifact.sha256,
|
|
792
804
|
purpose: "inherited-gap",
|
|
@@ -819,6 +831,9 @@ async function stageInputRecords(root, project, role, design, assessment, canary
|
|
|
819
831
|
ownerId: requiredPackage,
|
|
820
832
|
sourceLocator,
|
|
821
833
|
hashBasis: "raw-file-bytes",
|
|
834
|
+
mediaType: "application/json",
|
|
835
|
+
objectKind: null,
|
|
836
|
+
registrationRecordSha256: null,
|
|
822
837
|
};
|
|
823
838
|
}));
|
|
824
839
|
if (role !== "evidence-construct") {
|
|
@@ -887,10 +902,47 @@ async function stageInputRecords(root, project, role, design, assessment, canary
|
|
|
887
902
|
ownerId: "evidence-construct",
|
|
888
903
|
sourceLocator: `native-canary:${sha256}`,
|
|
889
904
|
hashBasis: "raw-file-bytes",
|
|
905
|
+
mediaType: "application/json",
|
|
906
|
+
objectKind: null,
|
|
907
|
+
registrationRecordSha256: null,
|
|
890
908
|
});
|
|
891
909
|
}
|
|
892
910
|
return [...stageOutputs, ...canaryRecords];
|
|
893
911
|
}
|
|
912
|
+
async function promoteRegisteredModelObject(input) {
|
|
913
|
+
const resolvedObject = await resolveScientificObjectBinding({
|
|
914
|
+
root: input.root,
|
|
915
|
+
objectKind: input.objectKind,
|
|
916
|
+
objectLocator: input.sourceLocator,
|
|
917
|
+
expectedSha256: input.sha256,
|
|
918
|
+
});
|
|
919
|
+
const promotedLocator = `projects/${input.projectId}/scientific/lineage/objects/${input.sha256}/blob`;
|
|
920
|
+
const promotedPath = resolveContained(workspacePaths(input.root).control, promotedLocator);
|
|
921
|
+
if (await pathExists(promotedPath)) {
|
|
922
|
+
const promotedInfo = await lstat(promotedPath).catch(() => undefined);
|
|
923
|
+
if (!promotedInfo?.isFile() ||
|
|
924
|
+
promotedInfo.isSymbolicLink() ||
|
|
925
|
+
promotedInfo.size !== resolvedObject.bytes ||
|
|
926
|
+
(await sha256File(promotedPath)) !== input.sha256) {
|
|
927
|
+
throw scientificGateError("A promoted scientific design object failed its immutable binding.", "research-design");
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
else {
|
|
931
|
+
await writeBytesAtomic(promotedPath, await readFile(resolvedObject.sourcePath), 0o444);
|
|
932
|
+
}
|
|
933
|
+
return {
|
|
934
|
+
path: promotedLocator,
|
|
935
|
+
sha256: input.sha256,
|
|
936
|
+
bytes: resolvedObject.bytes,
|
|
937
|
+
purpose: input.purpose,
|
|
938
|
+
ownerId: input.ownerId,
|
|
939
|
+
sourceLocator: resolvedObject.sourceLocator,
|
|
940
|
+
hashBasis: "raw-file-bytes",
|
|
941
|
+
mediaType: resolvedObject.mediaType,
|
|
942
|
+
objectKind: input.objectKind,
|
|
943
|
+
registrationRecordSha256: resolvedObject.record.recordSha256,
|
|
944
|
+
};
|
|
945
|
+
}
|
|
894
946
|
async function assessmentEvidenceContext(root, project, role, stageInputs) {
|
|
895
947
|
if (role !== "evidence-construct")
|
|
896
948
|
return null;
|
|
@@ -1212,7 +1264,10 @@ function isScientificReviewPacket(value, projectId, role, finalPublicationReview
|
|
|
1212
1264
|
record.ownerId.length > 0 &&
|
|
1213
1265
|
typeof record.sourceLocator === "string" &&
|
|
1214
1266
|
record.sourceLocator.length > 0 &&
|
|
1215
|
-
record.hashBasis === "raw-file-bytes"
|
|
1267
|
+
record.hashBasis === "raw-file-bytes" &&
|
|
1268
|
+
typeof record.mediaType === "string" &&
|
|
1269
|
+
/^(?:text\/[a-z0-9.+-]+|application\/[a-z0-9.+-]+)$/u.test(record.mediaType) &&
|
|
1270
|
+
validStageInputObjectMetadata(record)) &&
|
|
1216
1271
|
isObject(value.assessment) &&
|
|
1217
1272
|
typeof value.assessment.sha256 === "string" &&
|
|
1218
1273
|
typeof value.assessment.objectLocator === "string" &&
|
|
@@ -1271,6 +1326,19 @@ function requiredGateRoles(stage) {
|
|
|
1271
1326
|
return ordered.slice(0, 1);
|
|
1272
1327
|
return ordered;
|
|
1273
1328
|
}
|
|
1329
|
+
function validStageInputObjectMetadata(record) {
|
|
1330
|
+
const expectedKind = record.purpose === "model-implementation"
|
|
1331
|
+
? "model-implementation"
|
|
1332
|
+
: record.purpose === "model-environment-lock"
|
|
1333
|
+
? "environment-lock"
|
|
1334
|
+
: null;
|
|
1335
|
+
if (expectedKind === null) {
|
|
1336
|
+
return record.objectKind === null && record.registrationRecordSha256 === null;
|
|
1337
|
+
}
|
|
1338
|
+
return (record.objectKind === expectedKind &&
|
|
1339
|
+
typeof record.registrationRecordSha256 === "string" &&
|
|
1340
|
+
new RegExp(SHA256_PATTERN).test(record.registrationRecordSha256));
|
|
1341
|
+
}
|
|
1274
1342
|
function containsSensitiveCanaryField(value) {
|
|
1275
1343
|
if (Array.isArray(value))
|
|
1276
1344
|
return value.some(containsSensitiveCanaryField);
|
|
@@ -1298,6 +1366,7 @@ function reviewInstructions(role) {
|
|
|
1298
1366
|
"Treat all mechanical failures as blocking; prose cannot upgrade them.",
|
|
1299
1367
|
"Use a fresh independent reviewer session and return the authoritative closed JSON schema.",
|
|
1300
1368
|
"Every stageInputs sha256 is the digest of raw file bytes at path; sourceLocator records provenance, while path is the promoted portable object that must be reviewed.",
|
|
1369
|
+
"Use mediaType and objectKind when reading model blobs; code and lock bytes are not JSON unless their recorded mediaType says application/json.",
|
|
1301
1370
|
"Do not infer field validation, causality, independence, or quantity scope beyond the design.",
|
|
1302
1371
|
"Interpret this gate within the declared lifecycle: three early scientific reviews precede four final publication reviews of the frozen manuscript.",
|
|
1303
1372
|
"A material post-review change must create a new authoritative generation and consume the declared revision reserve.",
|
|
@@ -1416,13 +1485,6 @@ function inheritedGapObjectError(role, gapId, artifactKind, reason) {
|
|
|
1416
1485
|
details: { role, gapId, artifactKind, reason },
|
|
1417
1486
|
});
|
|
1418
1487
|
}
|
|
1419
|
-
function modelArtifactObjectError(role, modelId, artifactKind, reason) {
|
|
1420
|
-
return new CliError("A frozen model object failed its immutable binding.", {
|
|
1421
|
-
code: "RESEARCH_SCIENTIFIC_GATE_INVALID",
|
|
1422
|
-
exitCode: 3,
|
|
1423
|
-
details: { role, modelId, artifactKind, reason },
|
|
1424
|
-
});
|
|
1425
|
-
}
|
|
1426
1488
|
function camelToCode(value) {
|
|
1427
1489
|
return value.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toUpperCase();
|
|
1428
1490
|
}
|