@vela-science/canopus 0.5.1 → 0.6.0
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/CHANGELOG.md +18 -0
- package/README.md +22 -9
- package/dist/src/cli.js +58 -3
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +1 -0
- package/dist/src/product/doctor.js +2 -2
- package/dist/src/projection/publication.d.ts +36 -0
- package/dist/src/projection/publication.js +47 -0
- package/dist/src/projection/run.d.ts +8 -2
- package/dist/src/projection/run.js +17 -3
- package/dist/src/run.js +8 -0
- package/dist/src/vela/cli.js +1 -1
- package/docs/RUN_RECORD.md +26 -15
- package/package.json +1 -1
- package/schemas/run.v1.json +220 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.6.0 - 2026-07-20
|
|
4
|
+
|
|
5
|
+
- Type completed-run evidence by stage as `worker_observations`,
|
|
6
|
+
`verifier_observations`, and `standing_caveats`, while preserving read
|
|
7
|
+
compatibility for immutable `canopus.run.v0` records.
|
|
8
|
+
- Add `canopus publish-run`, which emits a sanitized public projection, root
|
|
9
|
+
manifest, exact pending-proposal commands, and read-only Observatory import
|
|
10
|
+
descriptor without landing, signing, pushing, deploying, or accepting.
|
|
11
|
+
- Compose against Vela 0.912.0 and its proposal-scoped verifier attachment and
|
|
12
|
+
reproduction surfaces.
|
|
13
|
+
|
|
14
|
+
## 0.5.2 - 2026-07-20
|
|
15
|
+
|
|
16
|
+
- Compose against Vela 0.911.1 so same-actor retries of `vela work` return the
|
|
17
|
+
exact active session without appending a second lease event.
|
|
18
|
+
- Preserve the 0.911.0 cold-use run and registration as immutable diagnostic
|
|
19
|
+
evidence; any focused retry remains separate and never rewrites that record.
|
|
20
|
+
|
|
3
21
|
## 0.5.1 - 2026-07-20
|
|
4
22
|
|
|
5
23
|
- Preserve exact pending-result replay roots instead of recomputing a receipt
|
package/README.md
CHANGED
|
@@ -38,8 +38,8 @@ Mission → GPT-5.6 → artifact → verifier → Receipt → Defer.
|
|
|
38
38
|
**90 seconds — inspect the shipped product:**
|
|
39
39
|
|
|
40
40
|
```sh
|
|
41
|
-
bunx @vela-science/canopus@0.
|
|
42
|
-
bunx @vela-science/canopus@0.
|
|
41
|
+
bunx @vela-science/canopus@0.6.0 --version
|
|
42
|
+
bunx @vela-science/canopus@0.6.0 profile validate sidon-a24-at-least-7194-gpt56-v3
|
|
43
43
|
```
|
|
44
44
|
|
|
45
45
|
**Full workflow — reproduce without rebuilding Canopus:**
|
|
@@ -56,22 +56,35 @@ vela reproduce .
|
|
|
56
56
|
Run the provenance-backed public package with Bun:
|
|
57
57
|
|
|
58
58
|
```sh
|
|
59
|
-
bunx @vela-science/canopus@0.
|
|
59
|
+
bunx @vela-science/canopus@0.6.0 --version
|
|
60
60
|
```
|
|
61
61
|
|
|
62
62
|
Inspect a clean frontier, then run its first ranked producer offer:
|
|
63
63
|
|
|
64
64
|
```sh
|
|
65
|
-
bunx @vela-science/canopus@0.
|
|
66
|
-
bunx @vela-science/canopus@0.
|
|
67
|
-
bunx @vela-science/canopus@0.
|
|
68
|
-
bunx @vela-science/canopus@0.
|
|
65
|
+
bunx @vela-science/canopus@0.6.0 doctor /path/to/frontier
|
|
66
|
+
bunx @vela-science/canopus@0.6.0 run /path/to/frontier --first
|
|
67
|
+
bunx @vela-science/canopus@0.6.0 inspect latest
|
|
68
|
+
bunx @vela-science/canopus@0.6.0 replay /path/to/run.json
|
|
69
69
|
```
|
|
70
70
|
|
|
71
|
+
Export a completed Defer run without publishing or mutating anything:
|
|
72
|
+
|
|
73
|
+
```sh
|
|
74
|
+
canopus publish-run /path/to/run.json --mission /path/to/mission.json \
|
|
75
|
+
--repository https://github.com/vela-science/<frontier> \
|
|
76
|
+
--output ./public-evidence
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
The new directory contains `public-run.json`, `root-manifest.json`, exact
|
|
80
|
+
pending-state commands, and a read-only Observatory import descriptor. Run v1
|
|
81
|
+
separates worker observations, verifier observations, and caveats that remain
|
|
82
|
+
standing after verification; historical run v0 records remain inspectable.
|
|
83
|
+
|
|
71
84
|
Use `--no-land` for a diagnostic mission that cannot change the source frontier:
|
|
72
85
|
|
|
73
86
|
```sh
|
|
74
|
-
bunx @vela-science/canopus@0.
|
|
87
|
+
bunx @vela-science/canopus@0.6.0 run /path/to/frontier --first --no-land
|
|
75
88
|
```
|
|
76
89
|
|
|
77
90
|
`doctor` binds the exact Vela, Codex, Git, frontier, packet, profile, and verifier
|
|
@@ -112,7 +125,7 @@ commits, run roots, audit evidence, and nonclaims live in
|
|
|
112
125
|
|
|
113
126
|
## Development
|
|
114
127
|
|
|
115
|
-
Requires Bun 1.3.12, Vela 0.
|
|
128
|
+
Requires Bun 1.3.12, Vela 0.912.0, Codex CLI 0.144.6, and Docker. The built
|
|
116
129
|
package also runs under Node 22 or 24; unsupported odd-numbered Node releases
|
|
117
130
|
are rejected rather than silently treated as supported.
|
|
118
131
|
|
package/dist/src/cli.js
CHANGED
|
@@ -3,7 +3,7 @@ import os from "node:os";
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import process from "node:process";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
|
-
import { readdir, stat, writeFile } from "node:fs/promises";
|
|
6
|
+
import { mkdir, mkdtemp, readdir, rename, rm, stat, writeFile } from "node:fs/promises";
|
|
7
7
|
import { parseMission } from "./contracts/mission.js";
|
|
8
8
|
import { CodexExecEngine } from "./engines/codex-exec.js";
|
|
9
9
|
import { CodexToolsNativeEngine } from "./engines/codex-tools-native.js";
|
|
@@ -12,6 +12,7 @@ import { parseDiagnosticRunRecord, projectDiagnosticRun } from "./projection/dia
|
|
|
12
12
|
import { parseFailureRecord, projectFailure } from "./projection/failure.js";
|
|
13
13
|
import { parseRunRecord, projectRun } from "./projection/run.js";
|
|
14
14
|
import { projectPublicRun } from "./projection/public-run.js";
|
|
15
|
+
import { buildPublicationBundle } from "./projection/publication.js";
|
|
15
16
|
import { doctorProduct } from "./product/doctor.js";
|
|
16
17
|
import { replayProduct } from "./product/replay.js";
|
|
17
18
|
import { runProduct } from "./product/run.js";
|
|
@@ -35,6 +36,8 @@ Primary workflow:
|
|
|
35
36
|
canopus inspect [run.json | latest]
|
|
36
37
|
canopus public-run <run.json> --mission <mission.json> \
|
|
37
38
|
--repository <public-url> --output <file>
|
|
39
|
+
canopus publish-run <run.json> --mission <mission.json> \
|
|
40
|
+
--repository <public-url> --output <new-directory>
|
|
38
41
|
canopus replay <run.json>
|
|
39
42
|
canopus withdraw [frontier] [--run <run.json|latest>] --reason <text>
|
|
40
43
|
|
|
@@ -104,6 +107,15 @@ Generates one canonical, sanitized canopus.public-run.v1 projection from a
|
|
|
104
107
|
submission-ready completed run. Raw worker logs, homes, credentials, private
|
|
105
108
|
paths, and unrestricted transcripts are never copied.`;
|
|
106
109
|
}
|
|
110
|
+
function publishRunUsage() {
|
|
111
|
+
return `Usage:
|
|
112
|
+
canopus publish-run <run.json> --mission <mission.json> \\
|
|
113
|
+
--repository <public-url> --output <new-directory>
|
|
114
|
+
|
|
115
|
+
Creates a sanitized public projection, root manifest, proposal-scoped pending
|
|
116
|
+
commands, and a read-only Vela Observatory import descriptor. It never lands,
|
|
117
|
+
signs, accepts, pushes, or deploys.`;
|
|
118
|
+
}
|
|
107
119
|
function withdrawUsage() {
|
|
108
120
|
return `Usage:
|
|
109
121
|
canopus withdraw [frontier] [--run <run.json|latest>] --reason <text>
|
|
@@ -464,6 +476,44 @@ async function publicRunCommand(file, rest) {
|
|
|
464
476
|
projection_root: contentDigest(projection),
|
|
465
477
|
})}\n`);
|
|
466
478
|
}
|
|
479
|
+
async function publishRunCommand(file, rest) {
|
|
480
|
+
if (file === undefined)
|
|
481
|
+
throw new Error("publish-run requires one completed run file");
|
|
482
|
+
const values = options(rest, ["--mission", "--repository", "--output"]);
|
|
483
|
+
const record = parseRunRecord(await jsonFile(file));
|
|
484
|
+
const mission = parseMission(await jsonFile(required(values, "--mission")));
|
|
485
|
+
const bundle = buildPublicationBundle({
|
|
486
|
+
record,
|
|
487
|
+
mission,
|
|
488
|
+
repository: required(values, "--repository"),
|
|
489
|
+
});
|
|
490
|
+
const output = path.resolve(required(values, "--output"));
|
|
491
|
+
const parent = path.dirname(output);
|
|
492
|
+
await mkdir(parent, { recursive: true, mode: 0o755 });
|
|
493
|
+
const temporary = await mkdtemp(path.join(parent, `.${path.basename(output)}.tmp-`));
|
|
494
|
+
try {
|
|
495
|
+
await Promise.all([
|
|
496
|
+
writeFile(path.join(temporary, "public-run.json"), canonicalJson(bundle.projection), { flag: "wx", mode: 0o644 }),
|
|
497
|
+
writeFile(path.join(temporary, "pending-commands.json"), canonicalJson(bundle.pendingCommands), { flag: "wx", mode: 0o644 }),
|
|
498
|
+
writeFile(path.join(temporary, "web-import.json"), canonicalJson(bundle.webImport), { flag: "wx", mode: 0o644 }),
|
|
499
|
+
writeFile(path.join(temporary, "root-manifest.json"), canonicalJson(bundle.manifest), { flag: "wx", mode: 0o644 }),
|
|
500
|
+
]);
|
|
501
|
+
await rename(temporary, output);
|
|
502
|
+
}
|
|
503
|
+
catch (error) {
|
|
504
|
+
await rm(temporary, { recursive: true, force: true });
|
|
505
|
+
throw error;
|
|
506
|
+
}
|
|
507
|
+
process.stdout.write(`${JSON.stringify({
|
|
508
|
+
ok: true,
|
|
509
|
+
command: "publish-run",
|
|
510
|
+
run_id: bundle.projection.run_id,
|
|
511
|
+
output,
|
|
512
|
+
projection_root: contentDigest(bundle.projection),
|
|
513
|
+
bundle_root: contentDigest(bundle.manifest),
|
|
514
|
+
authority_effect: "none",
|
|
515
|
+
})}\n`);
|
|
516
|
+
}
|
|
467
517
|
async function withdrawCommand(args) {
|
|
468
518
|
const parsed = productOptions(args, ["--run", "--reason"], []);
|
|
469
519
|
if (parsed.positional.length > 1)
|
|
@@ -506,8 +556,9 @@ async function main(argv) {
|
|
|
506
556
|
: command === "doctor" ? doctorUsage()
|
|
507
557
|
: command === "replay" ? replayUsage()
|
|
508
558
|
: command === "public-run" ? publicRunUsage()
|
|
509
|
-
: command === "
|
|
510
|
-
:
|
|
559
|
+
: command === "publish-run" ? publishRunUsage()
|
|
560
|
+
: command === "withdraw" ? withdrawUsage()
|
|
561
|
+
: usage()}\n`);
|
|
511
562
|
return;
|
|
512
563
|
}
|
|
513
564
|
if (command === "doctor") {
|
|
@@ -522,6 +573,10 @@ async function main(argv) {
|
|
|
522
573
|
await publicRunCommand(file, rest);
|
|
523
574
|
return;
|
|
524
575
|
}
|
|
576
|
+
if (command === "publish-run") {
|
|
577
|
+
await publishRunCommand(file, rest);
|
|
578
|
+
return;
|
|
579
|
+
}
|
|
525
580
|
if (command === "withdraw") {
|
|
526
581
|
await withdrawCommand(argv.slice(1));
|
|
527
582
|
return;
|
package/dist/src/index.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export * from "./activity/store.js";
|
|
|
9
9
|
export * from "./candidate/validate.js";
|
|
10
10
|
export * from "./util/canonical.js";
|
|
11
11
|
export * from "./projection/public-run.js";
|
|
12
|
+
export * from "./projection/publication.js";
|
|
12
13
|
export * from "./util/command.js";
|
|
13
14
|
export * from "./util/files.js";
|
|
14
15
|
export * from "./roles.js";
|
package/dist/src/index.js
CHANGED
|
@@ -9,6 +9,7 @@ export * from "./activity/store.js";
|
|
|
9
9
|
export * from "./candidate/validate.js";
|
|
10
10
|
export * from "./util/canonical.js";
|
|
11
11
|
export * from "./projection/public-run.js";
|
|
12
|
+
export * from "./projection/publication.js";
|
|
12
13
|
export * from "./util/command.js";
|
|
13
14
|
export * from "./util/files.js";
|
|
14
15
|
export * from "./roles.js";
|
|
@@ -120,8 +120,8 @@ export async function doctorProduct(options) {
|
|
|
120
120
|
runtimeIdentity({ name: "vela", cwd: frontier, home: runtime, runner }),
|
|
121
121
|
runtimeIdentity({ name: "git", cwd: frontier, home: runtime, runner }),
|
|
122
122
|
]);
|
|
123
|
-
if (vela.version !== "vela 0.
|
|
124
|
-
throw new Error(`Canopus ${CANOPUS_VERSION} requires vela 0.
|
|
123
|
+
if (vela.version !== "vela 0.912.0") {
|
|
124
|
+
throw new Error(`Canopus ${CANOPUS_VERSION} requires vela 0.912.0, observed ${vela.version}`);
|
|
125
125
|
}
|
|
126
126
|
const [status, offer, gitStatus] = await Promise.all([
|
|
127
127
|
jsonCommand({ runner, argv: [vela.binary, "status", ".", "--json"], cwd: frontier, home: runtime, label: "vela status" }),
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { Mission } from "../contracts/mission.js";
|
|
2
|
+
import type { RunRecord } from "./run.js";
|
|
3
|
+
import { projectPublicRun } from "./public-run.js";
|
|
4
|
+
export interface PublicationBundle {
|
|
5
|
+
projection: ReturnType<typeof projectPublicRun>;
|
|
6
|
+
pendingCommands: {
|
|
7
|
+
schema: "canopus.pending-commands.v1";
|
|
8
|
+
authority: "none";
|
|
9
|
+
proposal_id: string;
|
|
10
|
+
commands: Array<{
|
|
11
|
+
purpose: string;
|
|
12
|
+
authority: string;
|
|
13
|
+
command: string;
|
|
14
|
+
}>;
|
|
15
|
+
};
|
|
16
|
+
webImport: {
|
|
17
|
+
schema: "vela-web.canopus-import.v1";
|
|
18
|
+
authority: "read_only";
|
|
19
|
+
run_id: string;
|
|
20
|
+
projection_path: "public-run.json";
|
|
21
|
+
projection_root: string;
|
|
22
|
+
route: "defer";
|
|
23
|
+
accepted_state_delta: 0;
|
|
24
|
+
};
|
|
25
|
+
manifest: {
|
|
26
|
+
schema: "canopus.publication-manifest.v1";
|
|
27
|
+
authority: "none";
|
|
28
|
+
run_id: string;
|
|
29
|
+
files: Record<string, string>;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
export declare function buildPublicationBundle(options: {
|
|
33
|
+
record: RunRecord;
|
|
34
|
+
mission: Mission;
|
|
35
|
+
repository: string;
|
|
36
|
+
}): PublicationBundle;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { contentDigest } from "../util/canonical.js";
|
|
2
|
+
import { projectPublicRun } from "./public-run.js";
|
|
3
|
+
export function buildPublicationBundle(options) {
|
|
4
|
+
const projection = projectPublicRun(options);
|
|
5
|
+
const pendingCommands = {
|
|
6
|
+
schema: "canopus.pending-commands.v1",
|
|
7
|
+
authority: "none",
|
|
8
|
+
proposal_id: projection.policy.proposal_id,
|
|
9
|
+
commands: [
|
|
10
|
+
{
|
|
11
|
+
purpose: "reproduce_pending_artifact",
|
|
12
|
+
authority: "read_only",
|
|
13
|
+
command: `vela reproduce . --proposal ${projection.policy.proposal_id} --json`,
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
purpose: "inspect_review_material",
|
|
17
|
+
authority: "read_only",
|
|
18
|
+
command: `vela review show . ${projection.policy.proposal_id} --json`,
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
purpose: "retain_independent_verifier_evidence",
|
|
22
|
+
authority: "evidence_only",
|
|
23
|
+
command: `vela verify attach . <attachment.json> --proposal ${projection.policy.proposal_id} --as verifier:<actor> --json`,
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
};
|
|
27
|
+
const webImport = {
|
|
28
|
+
schema: "vela-web.canopus-import.v1",
|
|
29
|
+
authority: "read_only",
|
|
30
|
+
run_id: projection.run_id,
|
|
31
|
+
projection_path: "public-run.json",
|
|
32
|
+
projection_root: contentDigest(projection),
|
|
33
|
+
route: "defer",
|
|
34
|
+
accepted_state_delta: 0,
|
|
35
|
+
};
|
|
36
|
+
const manifest = {
|
|
37
|
+
schema: "canopus.publication-manifest.v1",
|
|
38
|
+
authority: "none",
|
|
39
|
+
run_id: projection.run_id,
|
|
40
|
+
files: {
|
|
41
|
+
"pending-commands.json": contentDigest(pendingCommands),
|
|
42
|
+
"public-run.json": contentDigest(projection),
|
|
43
|
+
"web-import.json": contentDigest(webImport),
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
return { projection, pendingCommands, webImport, manifest };
|
|
47
|
+
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { MissionRoots } from "../contracts/mission.js";
|
|
2
|
-
export declare const RUN_RECORD_SCHEMA: "canopus.run.
|
|
2
|
+
export declare const RUN_RECORD_SCHEMA: "canopus.run.v1";
|
|
3
|
+
export declare const LEGACY_RUN_RECORD_SCHEMA: "canopus.run.v0";
|
|
3
4
|
export declare const RUN_PROJECTION_SCHEMA: "canopus.run-projection.v0";
|
|
4
5
|
export interface RunRecord {
|
|
5
|
-
schema: typeof RUN_RECORD_SCHEMA;
|
|
6
|
+
schema: typeof RUN_RECORD_SCHEMA | typeof LEGACY_RUN_RECORD_SCHEMA;
|
|
6
7
|
run_id: string;
|
|
7
8
|
status: "completed";
|
|
8
9
|
authority: "non_authoritative";
|
|
@@ -25,6 +26,11 @@ export interface RunRecord {
|
|
|
25
26
|
}>;
|
|
26
27
|
caveats: string[];
|
|
27
28
|
};
|
|
29
|
+
observations?: {
|
|
30
|
+
worker_observations: string[];
|
|
31
|
+
verifier_observations: string[];
|
|
32
|
+
standing_caveats: string[];
|
|
33
|
+
};
|
|
28
34
|
verifier: {
|
|
29
35
|
status: "passed" | "failed" | "error";
|
|
30
36
|
sandbox: "macos_sandbox" | "container_network_denied";
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { arrayAt, enumAt, exactKeys, gitObjectAt, integerAt, objectAt, relativePathAt, sha256At, stringAt, } from "../contracts/validation.js";
|
|
2
|
-
export const RUN_RECORD_SCHEMA = "canopus.run.
|
|
2
|
+
export const RUN_RECORD_SCHEMA = "canopus.run.v1";
|
|
3
|
+
export const LEGACY_RUN_RECORD_SCHEMA = "canopus.run.v0";
|
|
3
4
|
export const RUN_PROJECTION_SCHEMA = "canopus.run-projection.v0";
|
|
4
5
|
function literal(value, expected, at) {
|
|
5
6
|
if (value !== expected)
|
|
@@ -24,10 +25,12 @@ function nullableCount(value, at) {
|
|
|
24
25
|
}
|
|
25
26
|
export function parseRunRecord(value) {
|
|
26
27
|
const record = objectAt(value, "run");
|
|
28
|
+
const schema = enumAt(record.schema, "run.schema", [RUN_RECORD_SCHEMA, LEGACY_RUN_RECORD_SCHEMA]);
|
|
27
29
|
exactKeys(record, [
|
|
28
30
|
"schema", "run_id", "status", "authority", "external_gate_credit", "mission",
|
|
29
31
|
"candidate", "verifier", "landing", "final_roots", "reproduction", "budget",
|
|
30
|
-
|
|
32
|
+
...(schema === RUN_RECORD_SCHEMA ? ["observations"] : []),
|
|
33
|
+
], schema === LEGACY_RUN_RECORD_SCHEMA ? ["observations"] : [], "run");
|
|
31
34
|
const mission = objectAt(record.mission, "run.mission");
|
|
32
35
|
exactKeys(mission, ["id", "target", "digest", "starting_roots"], [], "run.mission");
|
|
33
36
|
const candidate = objectAt(record.candidate, "run.candidate");
|
|
@@ -48,8 +51,18 @@ export function parseRunRecord(value) {
|
|
|
48
51
|
"research_elapsed_ms", "research_processes", "research_output_bytes", "prompt_bytes",
|
|
49
52
|
"artifact_bytes", "attempts", "observed_tokens",
|
|
50
53
|
], [], "run.budget");
|
|
54
|
+
const observations = record.observations === undefined ? undefined : (() => {
|
|
55
|
+
const stages = objectAt(record.observations, "run.observations");
|
|
56
|
+
exactKeys(stages, ["worker_observations", "verifier_observations", "standing_caveats"], [], "run.observations");
|
|
57
|
+
const strings = (value, at) => arrayAt(value, at, { max: 16 }, (item, itemAt) => stringAt(item, itemAt, { min: 1, max: 4096 }));
|
|
58
|
+
return {
|
|
59
|
+
worker_observations: strings(stages.worker_observations, "run.observations.worker_observations"),
|
|
60
|
+
verifier_observations: strings(stages.verifier_observations, "run.observations.verifier_observations"),
|
|
61
|
+
standing_caveats: strings(stages.standing_caveats, "run.observations.standing_caveats"),
|
|
62
|
+
};
|
|
63
|
+
})();
|
|
51
64
|
return {
|
|
52
|
-
schema
|
|
65
|
+
schema,
|
|
53
66
|
run_id: stringAt(record.run_id, "run.run_id", { min: 5, max: 128 }),
|
|
54
67
|
status: literal(record.status, "completed", "run.status"),
|
|
55
68
|
authority: literal(record.authority, "non_authoritative", "run.authority"),
|
|
@@ -76,6 +89,7 @@ export function parseRunRecord(value) {
|
|
|
76
89
|
}),
|
|
77
90
|
caveats: arrayAt(candidate.caveats, "run.candidate.caveats", { max: 10 }, (item, at) => stringAt(item, at, { min: 1, max: 4096 })),
|
|
78
91
|
},
|
|
92
|
+
...(observations === undefined ? {} : { observations }),
|
|
79
93
|
verifier: {
|
|
80
94
|
status: enumAt(verifier.status, "run.verifier.status", ["passed", "failed", "error"]),
|
|
81
95
|
sandbox: enumAt(verifier.sandbox, "run.verifier.sandbox", ["macos_sandbox", "container_network_denied"]),
|
package/dist/src/run.js
CHANGED
|
@@ -576,6 +576,14 @@ export async function runCanopus(options) {
|
|
|
576
576
|
artifacts: candidate.artifacts,
|
|
577
577
|
caveats: candidate.caveats,
|
|
578
578
|
},
|
|
579
|
+
observations: {
|
|
580
|
+
worker_observations: candidate.observations,
|
|
581
|
+
verifier_observations: [
|
|
582
|
+
`Frozen verifier passed in ${verifier.sandbox}.`,
|
|
583
|
+
`Verifier stdout ${verifier.record.stdout_digest}; stderr ${verifier.record.stderr_digest}.`,
|
|
584
|
+
],
|
|
585
|
+
standing_caveats: candidate.caveats,
|
|
586
|
+
},
|
|
579
587
|
verifier: {
|
|
580
588
|
status: verifier.status,
|
|
581
589
|
sandbox: verifier.sandbox,
|
package/dist/src/vela/cli.js
CHANGED
|
@@ -432,7 +432,7 @@ export class VelaClient {
|
|
|
432
432
|
if (replay.source_hash !== undefined) {
|
|
433
433
|
assertEqual(normalizeSha256(replay.source_hash, "vela check.replay.source_hash"), checkCurrent, "Vela source snapshot");
|
|
434
434
|
}
|
|
435
|
-
const proof = version === "0.900.0" || version === "0.900.1" || version === "0.900.2" || version === "0.901.0" || version === "0.910.0" || version === "0.911.0"
|
|
435
|
+
const proof = version === "0.900.0" || version === "0.900.1" || version === "0.900.2" || version === "0.901.0" || version === "0.910.0" || version === "0.911.0" || version === "0.911.1" || version === "0.912.0"
|
|
436
436
|
? {
|
|
437
437
|
ok: true,
|
|
438
438
|
command: "status_root_projection",
|
package/docs/RUN_RECORD.md
CHANGED
|
@@ -9,8 +9,8 @@ A completed run writes these local records beneath its run root:
|
|
|
9
9
|
- `worker-final.json`: the exact final worker response;
|
|
10
10
|
- `worker-stderr.bin`: the bounded raw worker stderr stream;
|
|
11
11
|
- `engine-result.json`: the parsed worker outcome and usage;
|
|
12
|
-
- `run.json`: the compact run record, exact roots, landing result, costs,
|
|
13
|
-
clean-clone reproduction result;
|
|
12
|
+
- `run.json`: the compact run record, exact roots, landing result, costs,
|
|
13
|
+
clean-clone reproduction result, and stage-typed observations;
|
|
14
14
|
- `evidence-manifest.json`: content roots for the worker, run, candidate,
|
|
15
15
|
artifacts, verifier result, Receipt when present, and final frontier roots;
|
|
16
16
|
- `projection.json`: a read-only view for another consumer;
|
|
@@ -30,25 +30,36 @@ so in its schema and can be rebuilt with `canopus inspect run.json`. Deleting
|
|
|
30
30
|
the run-record files must not change Vela replay, a policy route, or accepted
|
|
31
31
|
state.
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
Completed runs now use `canopus.run.v1`. Its `observations` object separates
|
|
34
|
+
three claims that must not be collapsed:
|
|
35
|
+
|
|
36
|
+
- `worker_observations`: what the model reported or attempted;
|
|
37
|
+
- `verifier_observations`: what the frozen mechanical verifier established;
|
|
38
|
+
- `standing_caveats`: limitations that remain true after verification.
|
|
39
|
+
|
|
40
|
+
Immutable `canopus.run.v0` records remain readable and replayable. Canopus does
|
|
41
|
+
not rewrite them to manufacture the new evidence categories.
|
|
42
|
+
|
|
43
|
+
For a public evidence surface, generate the publication bundle only after the
|
|
44
|
+
successful run has reached Defer with zero accepted-state delta and matched
|
|
45
|
+
clean-clone replay:
|
|
36
46
|
|
|
37
47
|
```bash
|
|
38
|
-
canopus
|
|
48
|
+
canopus publish-run /local/run/run.json \
|
|
39
49
|
--mission /local/run/mission/mission.json \
|
|
40
50
|
--repository https://github.com/vela-science/formal-conjectures-frontier \
|
|
41
|
-
--output
|
|
51
|
+
--output ./public-evidence
|
|
42
52
|
```
|
|
43
53
|
|
|
44
|
-
`canopus.public-run.v1`
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
commands
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
54
|
+
The new directory contains the `canopus.public-run.v1` projection, an exact
|
|
55
|
+
root manifest, read-only Observatory import data, and commands to reproduce or
|
|
56
|
+
inspect the pending proposal and retain additional verifier evidence. The
|
|
57
|
+
commands do not accept, publish, push, deploy, or cross a human authority
|
|
58
|
+
boundary. The public projection contains only mission and model identity, a
|
|
59
|
+
bounded activity summary, claim and caveats, artifact/verifier/Receipt roots,
|
|
60
|
+
route, accepted delta, usage, source/final commits, and reproduction commands.
|
|
61
|
+
It cannot export a failed or admitted run. Never publish the raw run directory,
|
|
62
|
+
isolated homes, authentication, private paths, or unrestricted logs.
|
|
52
63
|
|
|
53
64
|
The run root also contains isolated checkouts and content-addressed artifacts.
|
|
54
65
|
The landing clone uses a disposable attached branch so Vela can publish exact
|
package/package.json
CHANGED
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://vela.science/schemas/canopus/run.v1.json",
|
|
4
|
+
"title": "Canopus completed run v1",
|
|
5
|
+
"description": "A non-authoritative completed-run record with worker observations, mechanical verifier observations, and caveats that remain standing after verification.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": [
|
|
9
|
+
"schema",
|
|
10
|
+
"run_id",
|
|
11
|
+
"status",
|
|
12
|
+
"authority",
|
|
13
|
+
"external_gate_credit",
|
|
14
|
+
"mission",
|
|
15
|
+
"candidate",
|
|
16
|
+
"observations",
|
|
17
|
+
"verifier",
|
|
18
|
+
"landing",
|
|
19
|
+
"final_roots",
|
|
20
|
+
"reproduction",
|
|
21
|
+
"budget"
|
|
22
|
+
],
|
|
23
|
+
"properties": {
|
|
24
|
+
"schema": { "const": "canopus.run.v1" },
|
|
25
|
+
"run_id": { "type": "string", "minLength": 5, "maxLength": 128 },
|
|
26
|
+
"status": { "const": "completed" },
|
|
27
|
+
"authority": { "const": "non_authoritative" },
|
|
28
|
+
"external_gate_credit": { "const": false },
|
|
29
|
+
"mission": {
|
|
30
|
+
"type": "object",
|
|
31
|
+
"additionalProperties": false,
|
|
32
|
+
"required": ["id", "target", "digest", "starting_roots"],
|
|
33
|
+
"properties": {
|
|
34
|
+
"id": { "type": "string", "minLength": 1, "maxLength": 134 },
|
|
35
|
+
"target": { "type": "string", "minLength": 1, "maxLength": 256 },
|
|
36
|
+
"digest": { "$ref": "#/$defs/sha256" },
|
|
37
|
+
"starting_roots": { "$ref": "#/$defs/roots" }
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"candidate": {
|
|
41
|
+
"type": "object",
|
|
42
|
+
"additionalProperties": false,
|
|
43
|
+
"required": ["digest", "status", "claim", "artifacts", "caveats"],
|
|
44
|
+
"properties": {
|
|
45
|
+
"digest": { "$ref": "#/$defs/sha256" },
|
|
46
|
+
"status": { "enum": ["success", "null", "failed"] },
|
|
47
|
+
"claim": { "type": "string", "minLength": 1, "maxLength": 8192 },
|
|
48
|
+
"artifacts": {
|
|
49
|
+
"type": "array",
|
|
50
|
+
"maxItems": 10,
|
|
51
|
+
"items": {
|
|
52
|
+
"type": "object",
|
|
53
|
+
"additionalProperties": false,
|
|
54
|
+
"required": ["path", "kind", "digest", "bytes"],
|
|
55
|
+
"properties": {
|
|
56
|
+
"path": { "$ref": "#/$defs/relativePath" },
|
|
57
|
+
"kind": { "type": "string", "minLength": 1, "maxLength": 128 },
|
|
58
|
+
"digest": { "$ref": "#/$defs/sha256" },
|
|
59
|
+
"bytes": { "type": "integer", "minimum": 0, "maximum": 1073741824 }
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
"caveats": { "$ref": "#/$defs/caveats" }
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
"observations": {
|
|
67
|
+
"type": "object",
|
|
68
|
+
"additionalProperties": false,
|
|
69
|
+
"required": ["worker_observations", "verifier_observations", "standing_caveats"],
|
|
70
|
+
"properties": {
|
|
71
|
+
"worker_observations": { "$ref": "#/$defs/observations" },
|
|
72
|
+
"verifier_observations": { "$ref": "#/$defs/observations" },
|
|
73
|
+
"standing_caveats": { "$ref": "#/$defs/observations" }
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
"verifier": {
|
|
77
|
+
"type": "object",
|
|
78
|
+
"additionalProperties": false,
|
|
79
|
+
"required": ["status", "sandbox", "record"],
|
|
80
|
+
"properties": {
|
|
81
|
+
"status": { "enum": ["passed", "failed", "error"] },
|
|
82
|
+
"sandbox": { "enum": ["macos_sandbox", "container_network_denied"] },
|
|
83
|
+
"record": {
|
|
84
|
+
"type": "object",
|
|
85
|
+
"additionalProperties": false,
|
|
86
|
+
"required": [
|
|
87
|
+
"argv",
|
|
88
|
+
"executable_digest",
|
|
89
|
+
"exit_code",
|
|
90
|
+
"stdout_digest",
|
|
91
|
+
"stderr_digest",
|
|
92
|
+
"duration_ms"
|
|
93
|
+
],
|
|
94
|
+
"properties": {
|
|
95
|
+
"argv": {
|
|
96
|
+
"type": "array",
|
|
97
|
+
"minItems": 1,
|
|
98
|
+
"maxItems": 64,
|
|
99
|
+
"items": { "type": "string", "maxLength": 4096 }
|
|
100
|
+
},
|
|
101
|
+
"executable_digest": { "$ref": "#/$defs/sha256" },
|
|
102
|
+
"exit_code": { "type": "integer", "minimum": -1, "maximum": 255 },
|
|
103
|
+
"stdout_digest": { "$ref": "#/$defs/sha256" },
|
|
104
|
+
"stderr_digest": { "$ref": "#/$defs/sha256" },
|
|
105
|
+
"duration_ms": { "type": "integer", "minimum": 0, "maximum": 3600000 }
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
"landing": {
|
|
111
|
+
"type": "object",
|
|
112
|
+
"additionalProperties": false,
|
|
113
|
+
"required": [
|
|
114
|
+
"operation_id",
|
|
115
|
+
"receipt_root",
|
|
116
|
+
"proposal_id",
|
|
117
|
+
"route",
|
|
118
|
+
"original_route",
|
|
119
|
+
"accepted_event_delta",
|
|
120
|
+
"publication_state"
|
|
121
|
+
],
|
|
122
|
+
"properties": {
|
|
123
|
+
"operation_id": { "type": "string", "minLength": 1, "maxLength": 256 },
|
|
124
|
+
"receipt_root": { "$ref": "#/$defs/sha256" },
|
|
125
|
+
"proposal_id": { "type": "string", "minLength": 1, "maxLength": 256 },
|
|
126
|
+
"route": { "enum": ["permit", "defer", "exact_retry"] },
|
|
127
|
+
"original_route": {
|
|
128
|
+
"oneOf": [
|
|
129
|
+
{ "enum": ["permit", "defer"] },
|
|
130
|
+
{ "type": "null" }
|
|
131
|
+
]
|
|
132
|
+
},
|
|
133
|
+
"accepted_event_delta": {
|
|
134
|
+
"oneOf": [
|
|
135
|
+
{ "type": "integer", "minimum": 0 },
|
|
136
|
+
{ "type": "null" }
|
|
137
|
+
]
|
|
138
|
+
},
|
|
139
|
+
"publication_state": { "type": "string", "minLength": 1, "maxLength": 4096 }
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
"final_roots": { "$ref": "#/$defs/roots" },
|
|
143
|
+
"reproduction": {
|
|
144
|
+
"type": "object",
|
|
145
|
+
"additionalProperties": false,
|
|
146
|
+
"required": ["matched", "roots", "verifier_status", "stdout_digest", "stderr_digest"],
|
|
147
|
+
"properties": {
|
|
148
|
+
"matched": { "const": true },
|
|
149
|
+
"roots": { "$ref": "#/$defs/roots" },
|
|
150
|
+
"verifier_status": { "enum": ["passed", "failed", "error"] },
|
|
151
|
+
"stdout_digest": { "$ref": "#/$defs/sha256" },
|
|
152
|
+
"stderr_digest": { "$ref": "#/$defs/sha256" }
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
"budget": {
|
|
156
|
+
"type": "object",
|
|
157
|
+
"additionalProperties": false,
|
|
158
|
+
"required": [
|
|
159
|
+
"research_elapsed_ms",
|
|
160
|
+
"research_processes",
|
|
161
|
+
"research_output_bytes",
|
|
162
|
+
"prompt_bytes",
|
|
163
|
+
"artifact_bytes",
|
|
164
|
+
"attempts",
|
|
165
|
+
"observed_tokens"
|
|
166
|
+
],
|
|
167
|
+
"properties": {
|
|
168
|
+
"research_elapsed_ms": { "$ref": "#/$defs/nonnegativeInteger" },
|
|
169
|
+
"research_processes": { "$ref": "#/$defs/nonnegativeInteger" },
|
|
170
|
+
"research_output_bytes": { "$ref": "#/$defs/nonnegativeInteger" },
|
|
171
|
+
"prompt_bytes": { "$ref": "#/$defs/nonnegativeInteger" },
|
|
172
|
+
"artifact_bytes": { "$ref": "#/$defs/nonnegativeInteger" },
|
|
173
|
+
"attempts": { "$ref": "#/$defs/nonnegativeInteger" },
|
|
174
|
+
"observed_tokens": { "$ref": "#/$defs/nonnegativeInteger" }
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
},
|
|
178
|
+
"$defs": {
|
|
179
|
+
"sha256": {
|
|
180
|
+
"type": "string",
|
|
181
|
+
"pattern": "^sha256:[0-9a-f]{64}$"
|
|
182
|
+
},
|
|
183
|
+
"gitObject": {
|
|
184
|
+
"type": "string",
|
|
185
|
+
"pattern": "^[0-9a-f]{40,64}$"
|
|
186
|
+
},
|
|
187
|
+
"relativePath": {
|
|
188
|
+
"type": "string",
|
|
189
|
+
"minLength": 1,
|
|
190
|
+
"maxLength": 4096,
|
|
191
|
+
"pattern": "^(?!/)(?!.*(?:^|/)\\.\\.(?:/|$)).+$"
|
|
192
|
+
},
|
|
193
|
+
"roots": {
|
|
194
|
+
"type": "object",
|
|
195
|
+
"additionalProperties": false,
|
|
196
|
+
"required": ["git_commit", "git_tree", "vela_event_log", "vela_snapshot"],
|
|
197
|
+
"properties": {
|
|
198
|
+
"git_commit": { "$ref": "#/$defs/gitObject" },
|
|
199
|
+
"git_tree": { "$ref": "#/$defs/gitObject" },
|
|
200
|
+
"vela_event_log": { "$ref": "#/$defs/sha256" },
|
|
201
|
+
"vela_snapshot": { "$ref": "#/$defs/sha256" }
|
|
202
|
+
}
|
|
203
|
+
},
|
|
204
|
+
"observations": {
|
|
205
|
+
"type": "array",
|
|
206
|
+
"maxItems": 16,
|
|
207
|
+
"items": { "type": "string", "minLength": 1, "maxLength": 4096 }
|
|
208
|
+
},
|
|
209
|
+
"caveats": {
|
|
210
|
+
"type": "array",
|
|
211
|
+
"maxItems": 10,
|
|
212
|
+
"items": { "type": "string", "minLength": 1, "maxLength": 4096 }
|
|
213
|
+
},
|
|
214
|
+
"nonnegativeInteger": {
|
|
215
|
+
"type": "integer",
|
|
216
|
+
"minimum": 0,
|
|
217
|
+
"maximum": 9007199254740991
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|