@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.
Files changed (33) hide show
  1. package/AGENTS.md +5 -1
  2. package/README.md +35 -2
  3. package/dist/research/orchestration.js +71 -0
  4. package/dist/research/orchestration.js.map +1 -1
  5. package/dist/research/workspace/executor.js +10 -3
  6. package/dist/research/workspace/executor.js.map +1 -1
  7. package/dist/research/workspace/inference.js +6 -2
  8. package/dist/research/workspace/inference.js.map +1 -1
  9. package/dist/research/workspace/platform-capabilities.d.ts +25 -0
  10. package/dist/research/workspace/platform-capabilities.js +87 -0
  11. package/dist/research/workspace/platform-capabilities.js.map +1 -0
  12. package/dist/research/workspace/preflight.js +5 -0
  13. package/dist/research/workspace/preflight.js.map +1 -1
  14. package/dist/research/workspace/projects.js +10 -0
  15. package/dist/research/workspace/projects.js.map +1 -1
  16. package/dist/research/workspace/review-executor.js +29 -2
  17. package/dist/research/workspace/review-executor.js.map +1 -1
  18. package/dist/research/workspace/scientific-design.d.ts +5 -5
  19. package/dist/research/workspace/scientific-design.js +92 -16
  20. package/dist/research/workspace/scientific-design.js.map +1 -1
  21. package/dist/research/workspace/scientific-objects.d.ts +53 -0
  22. package/dist/research/workspace/scientific-objects.js +400 -0
  23. package/dist/research/workspace/scientific-objects.js.map +1 -0
  24. package/dist/research/workspace/scientific-review.d.ts +4 -0
  25. package/dist/research/workspace/scientific-review.js +87 -25
  26. package/dist/research/workspace/scientific-review.js.map +1 -1
  27. package/dist/research/workspace/setup-catalog.js +2 -2
  28. package/dist/research/workspace/setup.js +15 -13
  29. package/dist/research/workspace/setup.js.map +1 -1
  30. package/dist/research/workspace/storage.d.ts +1 -0
  31. package/dist/research/workspace/storage.js +7 -0
  32. package/dist/research/workspace/storage.js.map +1 -1
  33. 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 promote = async (input) => {
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
- await promote({
773
- sourceLocator: model.implementationArtifactLocator,
774
- sha256: model.implementationArtifactSha256,
775
- purpose: "model-implementation",
776
- ownerId: model.id,
777
- onFailure: (reason) => modelArtifactObjectError(role, model.id, "implementation", reason),
778
- });
779
- await promote({
780
- sourceLocator: model.environmentLockLocator,
781
- sha256: model.environmentLockSha256,
782
- purpose: "model-environment-lock",
783
- ownerId: model.id,
784
- onFailure: (reason) => modelArtifactObjectError(role, model.id, "environment-lock", reason),
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 promote({
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
  }