engineering-behavior-observatory 0.2.1
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/LICENSE +202 -0
- package/README.md +151 -0
- package/contracts/codex-app-server-0.150.1/manifest.json +25 -0
- package/contracts/codex-app-server-0.150.1/schema/InitializeParams.json +84 -0
- package/contracts/codex-app-server-0.150.1/schema/JSONRPCMessage.json +137 -0
- package/contracts/codex-app-server-0.150.1/schema/v2/ThreadReadParams.json +17 -0
- package/contracts/codex-app-server-0.150.1/schema/v2/ThreadTokenUsageUpdatedNotification.json +82 -0
- package/contracts/codex-app-server-0.150.1/schema/v2/TurnInterruptParams.json +17 -0
- package/contracts/codex-app-server-0.150.1/types/AskForApproval.ts +5 -0
- package/contracts/codex-app-server-0.150.1/types/ClientNotification.ts +5 -0
- package/contracts/codex-app-server-0.150.1/types/SandboxMode.ts +5 -0
- package/contracts/codex-app-server-0.150.1/types/ThreadReadParams.ts +9 -0
- package/contracts/codex-app-server-0.150.1/types/TokenUsageBreakdown.ts +5 -0
- package/contracts/codex-app-server-0.150.1/types/TurnInterruptParams.ts +5 -0
- package/contracts/codex-app-server-0.153.4/manifest.json +27 -0
- package/contracts/codex-app-server-0.153.4/schema/JSONRPCMessage.json +137 -0
- package/contracts/codex-app-server-0.153.4/schema/v1/InitializeParams.json +84 -0
- package/contracts/codex-app-server-0.153.4/schema/v2/ThreadReadParams.json +17 -0
- package/contracts/codex-app-server-0.153.4/schema/v2/ThreadStartParams.json +515 -0
- package/contracts/codex-app-server-0.153.4/schema/v2/ThreadTokenUsageUpdatedNotification.json +82 -0
- package/contracts/codex-app-server-0.153.4/schema/v2/TurnInterruptParams.json +17 -0
- package/contracts/codex-app-server-0.153.4/schema/v2/TurnStartParams.json +921 -0
- package/contracts/codex-app-server-0.153.4/types/AskForApproval.ts +5 -0
- package/contracts/codex-app-server-0.153.4/types/ClientNotification.ts +5 -0
- package/contracts/codex-app-server-0.153.4/types/SandboxMode.ts +5 -0
- package/contracts/codex-app-server-0.153.4/types/ThreadReadParams.ts +12 -0
- package/contracts/codex-app-server-0.153.4/types/TokenUsageBreakdown.ts +5 -0
- package/contracts/codex-app-server-0.153.4/types/TurnInterruptParams.ts +5 -0
- package/contracts/openhands-agent-server-v1.44.1.json +65 -0
- package/contracts/openhands-agent-server-v1.46.0.json +46 -0
- package/dist/contracts/codex-app-server-0.153.4/types/AskForApproval.d.ts +9 -0
- package/dist/contracts/codex-app-server-0.153.4/types/AskForApproval.js +2 -0
- package/dist/contracts/codex-app-server-0.153.4/types/ClientNotification.d.ts +3 -0
- package/dist/contracts/codex-app-server-0.153.4/types/ClientNotification.js +2 -0
- package/dist/contracts/codex-app-server-0.153.4/types/SandboxMode.d.ts +1 -0
- package/dist/contracts/codex-app-server-0.153.4/types/SandboxMode.js +2 -0
- package/dist/contracts/codex-app-server-0.153.4/types/ThreadReadParams.d.ts +10 -0
- package/dist/contracts/codex-app-server-0.153.4/types/ThreadReadParams.js +2 -0
- package/dist/contracts/codex-app-server-0.153.4/types/TokenUsageBreakdown.d.ts +8 -0
- package/dist/contracts/codex-app-server-0.153.4/types/TokenUsageBreakdown.js +2 -0
- package/dist/contracts/codex-app-server-0.153.4/types/TurnInterruptParams.d.ts +4 -0
- package/dist/contracts/codex-app-server-0.153.4/types/TurnInterruptParams.js +2 -0
- package/dist/src/agent-sdk-normalizer.d.ts +22 -0
- package/dist/src/agent-sdk-normalizer.js +995 -0
- package/dist/src/agent-sdk-run.d.ts +31 -0
- package/dist/src/agent-sdk-run.js +242 -0
- package/dist/src/agent-sdk-runner.d.ts +96 -0
- package/dist/src/agent-sdk-runner.js +407 -0
- package/dist/src/agent-sdk.d.ts +294 -0
- package/dist/src/agent-sdk.js +644 -0
- package/dist/src/aggregation.d.ts +183 -0
- package/dist/src/aggregation.js +513 -0
- package/dist/src/artifacts.d.ts +36 -0
- package/dist/src/artifacts.js +1372 -0
- package/dist/src/atlas-grafana.d.ts +377 -0
- package/dist/src/atlas-grafana.js +47 -0
- package/dist/src/atlas-html.d.ts +2 -0
- package/dist/src/atlas-html.js +34 -0
- package/dist/src/atlas.d.ts +130 -0
- package/dist/src/atlas.js +235 -0
- package/dist/src/behavior-assertions.d.ts +95 -0
- package/dist/src/behavior-assertions.js +154 -0
- package/dist/src/cli.d.ts +5 -0
- package/dist/src/cli.js +957 -0
- package/dist/src/codex-judge.d.ts +44 -0
- package/dist/src/codex-judge.js +214 -0
- package/dist/src/codex-run.d.ts +114 -0
- package/dist/src/codex-run.js +519 -0
- package/dist/src/codex.d.ts +187 -0
- package/dist/src/codex.js +1028 -0
- package/dist/src/contracts.d.ts +155 -0
- package/dist/src/contracts.js +866 -0
- package/dist/src/corpus.d.ts +67 -0
- package/dist/src/corpus.js +540 -0
- package/dist/src/cursor-sdk-runner.d.ts +81 -0
- package/dist/src/cursor-sdk-runner.js +362 -0
- package/dist/src/cursor-sdk.d.ts +81 -0
- package/dist/src/cursor-sdk.js +1078 -0
- package/dist/src/deepseek-adapter.d.ts +152 -0
- package/dist/src/deepseek-adapter.js +777 -0
- package/dist/src/exports.d.ts +69 -0
- package/dist/src/exports.js +966 -0
- package/dist/src/human-calibration.d.ts +167 -0
- package/dist/src/human-calibration.js +618 -0
- package/dist/src/index.d.ts +71 -0
- package/dist/src/index.js +38 -0
- package/dist/src/lifecycle.d.ts +196 -0
- package/dist/src/lifecycle.js +1889 -0
- package/dist/src/normalization-integrity.d.ts +128 -0
- package/dist/src/normalization-integrity.js +429 -0
- package/dist/src/openhands-run.d.ts +36 -0
- package/dist/src/openhands-run.js +415 -0
- package/dist/src/openhands.d.ts +130 -0
- package/dist/src/openhands.js +859 -0
- package/dist/src/pi.d.ts +203 -0
- package/dist/src/pi.js +1345 -0
- package/dist/src/process-protocol.d.ts +245 -0
- package/dist/src/process-protocol.js +1261 -0
- package/dist/src/retained-evidence.d.ts +12 -0
- package/dist/src/retained-evidence.js +201 -0
- package/dist/src/run-bundles.d.ts +193 -0
- package/dist/src/run-bundles.js +993 -0
- package/dist/src/scheduler.d.ts +109 -0
- package/dist/src/scheduler.js +1080 -0
- package/dist/src/semantic-judge.d.ts +194 -0
- package/dist/src/semantic-judge.js +875 -0
- package/dist/src/structural-observations.d.ts +124 -0
- package/dist/src/structural-observations.js +671 -0
- package/dist/src/task-packets.d.ts +115 -0
- package/dist/src/task-packets.js +683 -0
- package/dist/src/uniform-events.d.ts +120 -0
- package/dist/src/uniform-events.js +158 -0
- package/dist/src/verifiers.d.ts +116 -0
- package/dist/src/verifiers.js +819 -0
- package/dist/src/workspaces.d.ts +56 -0
- package/dist/src/workspaces.js +1314 -0
- package/docs/README.md +60 -0
- package/docs/development/README.md +71 -0
- package/docs/development/documentation-sync.md +58 -0
- package/docs/development/extension-contracts.md +307 -0
- package/docs/evaluation/README.md +48 -0
- package/docs/evaluation/aggregation.md +112 -0
- package/docs/evaluation/behavior-assertions.md +45 -0
- package/docs/evaluation/human-calibration.md +170 -0
- package/docs/evaluation/normalization-integrity.md +80 -0
- package/docs/evaluation/semantic-judge.md +188 -0
- package/docs/evaluation/structural-observations.md +84 -0
- package/docs/evaluation/uniform-events.md +131 -0
- package/docs/guides/atlas.md +144 -0
- package/docs/guides/evidence-and-sharing.md +100 -0
- package/docs/guides/operator-guide.md +424 -0
- package/docs/guides/quickstart.md +152 -0
- package/docs/guides/telemetry.md +66 -0
- package/docs/harnesses/README.md +31 -0
- package/docs/harnesses/claude-agent-sdk.md +61 -0
- package/docs/harnesses/codex-harness.md +174 -0
- package/docs/harnesses/cursor-sdk.md +149 -0
- package/docs/harnesses/deepseek-harness.md +134 -0
- package/docs/harnesses/openhands-agent-server.md +153 -0
- package/docs/harnesses/pi-sdk.md +66 -0
- package/docs/reference/README.md +19 -0
- package/docs/reference/agent-sdk-operational-runner.md +118 -0
- package/docs/reference/cli.md +114 -0
- package/docs/reference/contracts.md +222 -0
- package/docs/reference/run-bundle-contract.md +354 -0
- package/docs/reference/run-lifecycle.md +54 -0
- package/examples/cursor-sdk/README.md +11 -0
- package/examples/cursor-sdk/capture-profile.json +1 -0
- package/examples/cursor-sdk/harness.json +1 -0
- package/examples/cursor-sdk/model.json +1 -0
- package/examples/cursor-sdk/native-limits.json +1 -0
- package/examples/cursor-sdk/native-tool-policy.json +1 -0
- package/ontology/behavior-categories.v1.json +46 -0
- package/package.json +66 -0
- package/release/0.1.0/KNOWN_LIMITATIONS.md +35 -0
- package/release/0.1.0/README.md +46 -0
- package/release/0.1.0/reproducibility.json +61 -0
- package/release/0.2.0/KNOWN_LIMITATIONS.md +40 -0
- package/release/0.2.0/README.md +42 -0
- package/release/0.2.0/reproducibility.json +73 -0
- package/release/0.2.1/KNOWN_LIMITATIONS.md +18 -0
- package/release/0.2.1/README.md +63 -0
- package/release/0.2.1/reproducibility.json +73 -0
- package/release/README.md +13 -0
- package/schemas/aggregation.v1.json +293 -0
- package/schemas/behavior-assertions.v1.json +220 -0
- package/schemas/deepseek-runtime-composition.v1.schema.json +122 -0
- package/schemas/experiment.v1.schema.json +188 -0
- package/schemas/human-calibration.v1.json +336 -0
- package/schemas/normalization-integrity.v1.json +302 -0
- package/schemas/run-bundles/v1.json +1040 -0
- package/schemas/run-queue.v1.schema.json +206 -0
- package/schemas/semantic-judge.v1.json +380 -0
- package/schemas/structural-observations.v1.json +131 -0
- package/schemas/task-packet-freeze.v1.schema.json +106 -0
- package/schemas/task-packet.v1.schema.json +234 -0
- package/schemas/uniform-events/v1.json +289 -0
- package/scripts/atlas-grafana.sh +18 -0
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
# Task-packet and experiment contracts
|
|
2
|
+
|
|
3
|
+
The post-capture uniform event and adapter boundary is documented separately in
|
|
4
|
+
[uniform-events.md](../evaluation/uniform-events.md). Its schemas consume capture-qualified
|
|
5
|
+
native evidence; they are not task-authorship or experiment inputs.
|
|
6
|
+
|
|
7
|
+
EBO accepts externally authored task packets and experiment configurations as
|
|
8
|
+
versioned JSON documents. The schemas are the contract; this repository does
|
|
9
|
+
not contain an evaluation corpus or a fixed operating matrix.
|
|
10
|
+
|
|
11
|
+
## Task packets
|
|
12
|
+
|
|
13
|
+
`schemas/task-packet.v1.schema.json` divides a packet into two surfaces:
|
|
14
|
+
|
|
15
|
+
- `agentInput` is the only surface a workspace materializer may use. It holds
|
|
16
|
+
the public prompt, a digest-verified sanitized TAR+gzip v1 archive with
|
|
17
|
+
compressed-byte, expanded-byte, and member-count limits, and an explicit
|
|
18
|
+
workspace-relative allowlist. A materializer verifies the archive digest and
|
|
19
|
+
copies only entries selected by `includePaths`; it must not materialize a raw
|
|
20
|
+
repository checkout or an entry outside that allowlist.
|
|
21
|
+
- Its archive locator is a secret-free, bundle-relative logical path. URLs,
|
|
22
|
+
absolute local paths, credentials, and path traversal are invalid there. Its
|
|
23
|
+
resolver rejects links and paths that leave the real task-bundle root.
|
|
24
|
+
Include paths are canonical POSIX logical paths only; leading slashes, trailing
|
|
25
|
+
slashes, backslashes,
|
|
26
|
+
drive letters, UNC paths, and traversal forms are invalid.
|
|
27
|
+
Common framework filenames may use brackets, parentheses, `+`, and `@`;
|
|
28
|
+
spaces, colons, wildcard characters, and shell metacharacters remain invalid.
|
|
29
|
+
- `verified-archive-literal-paths-v1` resolves each literal from the sanitized
|
|
30
|
+
archive root. A file includes that file; a directory includes its complete
|
|
31
|
+
descendant tree. Wildcards are intentionally unsupported.
|
|
32
|
+
- `verified-archive-literal-paths-no-links-v1` adds the required v1 link rule:
|
|
33
|
+
enumerate every selected entry and selected directory descendant before copy,
|
|
34
|
+
then reject every non-file/non-directory entry. Links are never copied or dereferenced. Every
|
|
35
|
+
selected member name must be a canonical root-relative logical path before
|
|
36
|
+
joining either archive or workspace roots.
|
|
37
|
+
- Archive membership and allowlist selection use exact canonical POSIX names.
|
|
38
|
+
Case folding is used only to reject destination collisions across filesystems.
|
|
39
|
+
- `assessmentMode` is explicit. `observational` packets are the primary
|
|
40
|
+
open-ended task form and omit `restricted` entirely. `verified` packets use
|
|
41
|
+
`restricted` only for digest-addressed reference-solution and verifier
|
|
42
|
+
references; the packet cannot embed their contents.
|
|
43
|
+
|
|
44
|
+
The packet records repository provenance, a controlled perturbation, admission
|
|
45
|
+
review status, sharing classification, and SHA-256 digests for every frozen
|
|
46
|
+
component. Every digest has one authority: the safe fixture source, controlled
|
|
47
|
+
perturbation artifact, and restricted component references carry their own. The schema
|
|
48
|
+
does not claim a separate agent-input digest without defining its canonical
|
|
49
|
+
bytes; admission-freeze tooling owns the whole-packet identity.
|
|
50
|
+
|
|
51
|
+
`proposed` packets explicitly set `admission.review` to `null`. `admitted` and
|
|
52
|
+
`rejected` packets require a reviewer, RFC 3339 `date-time` evidence, and the
|
|
53
|
+
restricted review-record reference. Repository provenance is a credential-free
|
|
54
|
+
HTTPS repository URI, optionally on an explicit port, plus a full immutable Git
|
|
55
|
+
object ID. Branches and tags are not accepted. A verifier is required only for `verified`
|
|
56
|
+
packets; `referenceSolution.status` may be `not-provided` or `unsupported` for
|
|
57
|
+
verifier-only work. Controlled perturbation
|
|
58
|
+
content is either an external, digest-addressed artifact or an explicit
|
|
59
|
+
`not-applied`/`unsupported` state; EBO does not prescribe a task-authoring
|
|
60
|
+
taxonomy.
|
|
61
|
+
|
|
62
|
+
Before scheduling, EBO requires an admitted packet's review time to be a valid
|
|
63
|
+
RFC 3339 calendar timestamp and its review record. Verified packets additionally
|
|
64
|
+
require provided reference-solution and verifier bytes to match their pinned digests. The review record binds the
|
|
65
|
+
canonical pre-admission packet digest; the admitted packet can then hash its
|
|
66
|
+
review-record reference without requiring a circular digest. Each declared
|
|
67
|
+
materialization literal must select at least one verified archive file or
|
|
68
|
+
directory tree. A referenced controlled perturbation also hashes to its pinned
|
|
69
|
+
digest before scheduling; explicit unavailable states remain distinct from a
|
|
70
|
+
referenced artifact that fails to resolve.
|
|
71
|
+
|
|
72
|
+
### Admission and freeze
|
|
73
|
+
|
|
74
|
+
Task-packet tooling consumes an externally authored packet; it does not create
|
|
75
|
+
tasks or make a human review decision. `validate` checks the packet schema,
|
|
76
|
+
parses each declared TAR+gzip fixture, verifies its declared size/member/link
|
|
77
|
+
limits and literal allowlist, and resolves every declared perturbation,
|
|
78
|
+
mode-appropriate reference/verifier, and review-record digest. `admit` additionally
|
|
79
|
+
requires the recorded admission status to be `admitted` and a complete human
|
|
80
|
+
review.
|
|
81
|
+
|
|
82
|
+
`freeze` writes a sibling
|
|
83
|
+
[`ebo.task-packet-freeze/v1`](../../schemas/task-packet-freeze.v1.schema.json)
|
|
84
|
+
record. It records the assessment mode and stable SHA-256 digests for the
|
|
85
|
+
prompt, fixture, optional reference solution/verifier, review record,
|
|
86
|
+
controlled perturbation, and canonical packet. The review record binds the canonical packet content with its
|
|
87
|
+
`admission` field omitted, using its `preAdmissionDigest` field and avoiding a
|
|
88
|
+
circular reference. The aggregate digest is derived from those identities, the
|
|
89
|
+
packet locator, and the recorded `frozenAt` timestamp. Repeating a freeze for
|
|
90
|
+
unchanged content retains the first published record and its timestamp.
|
|
91
|
+
An existing freeze is never silently replaced after a component changes.
|
|
92
|
+
|
|
93
|
+
`status` compares the current packet and resolved bytes with the freeze record
|
|
94
|
+
and reports the named mismatching component before a later materializer or
|
|
95
|
+
scheduler can consume it. The model-visible projection is only `agentInput`;
|
|
96
|
+
verified-task reference solutions/verifier bytes and all review records remain restricted.
|
|
97
|
+
|
|
98
|
+
## Workspace materialization
|
|
99
|
+
|
|
100
|
+
`materializeWorkspace` accepts an admitted packet with a `frozen` status and
|
|
101
|
+
creates an attempt-identified directory outside the task bundle. It verifies
|
|
102
|
+
the digest-pinned TAR+gzip source, copies only the declared literal allowlist,
|
|
103
|
+
rejects links, special entries, traversal, and a selected `restricted/`
|
|
104
|
+
subtree, then normalizes private modes and timestamps before calculating the
|
|
105
|
+
`workspaceFingerprint` used for outcome binding and, when present, verification. The result's `startingDigest` is
|
|
106
|
+
the declared fixture digest; `workspaceDigest` is the normalized tree
|
|
107
|
+
fingerprint. Attempt roots and non-executable files use `0700` and `0600`;
|
|
108
|
+
executable archive or setup files retain the owner execute bit.
|
|
109
|
+
|
|
110
|
+
Setup callbacks receive the disposable workspace path and an invocation-owned
|
|
111
|
+
`{ spawn }` context. Child processes that setup needs to create must use that
|
|
112
|
+
context: each child is placed in a private process group and its group is
|
|
113
|
+
terminated before the fingerprint is calculated. This prevents cleanup from
|
|
114
|
+
mistaking unrelated coordinator processes for setup descendants. A setup step
|
|
115
|
+
must settle all in-process writes (including timers and promises) and must not
|
|
116
|
+
leave ambient child processes behind before returning; arbitrary filesystem
|
|
117
|
+
closures cannot be revoked without a sandbox. Stronger process isolation can
|
|
118
|
+
still be supplied by the evaluation environment. Call
|
|
119
|
+
`cleanupWorkspace(result, "success")` (or `result.cleanup("success")`) after a
|
|
120
|
+
successful attempt. A failed setup returns a failed lifecycle result;
|
|
121
|
+
`retainOnFailure: true` keeps its attempt path for inspection after normalizing
|
|
122
|
+
an owned tree to private modes, while the default removes it. Identity changes,
|
|
123
|
+
links, special entries, and paths that cannot be safely normalized are never
|
|
124
|
+
retained. Failure retention never changes the model-visible input surface or
|
|
125
|
+
the frozen packet.
|
|
126
|
+
|
|
127
|
+
## Experiments
|
|
128
|
+
|
|
129
|
+
`schemas/experiment.v1.schema.json` treats task, model, and harness sets;
|
|
130
|
+
trial count; ordering seed; coordinator wall-clock budget; and capture profile
|
|
131
|
+
as data. Each condition set is an ID-keyed map, so one identity can expand to
|
|
132
|
+
only one matrix condition. Every referenced configuration has a SHA-256 digest.
|
|
133
|
+
Each harness condition separately names source-specific native-limits and
|
|
134
|
+
native-tool-policy configurations; EBO does not define a shared turn count or
|
|
135
|
+
tool namespace.
|
|
136
|
+
|
|
137
|
+
Every experiment configuration reference is a portable bundle-relative logical
|
|
138
|
+
path, resolved from the experiment bundle root rather than the current working
|
|
139
|
+
directory. The resolver checks each component without following symbolic links
|
|
140
|
+
and rejects a path that leaves the real bundle root. URLs, absolute paths,
|
|
141
|
+
traversal, aliases such as `./`, and backslashes are invalid. A
|
|
142
|
+
`permuted` order also names a digest-pinned permutation-algorithm reference;
|
|
143
|
+
that versioned artifact defines how the supplied seed orders matrix cells. Each
|
|
144
|
+
resolved model, harness, native-limit, native-tool-policy, capture-profile, and
|
|
145
|
+
permutation artifact must hash to its pinned digest before scheduling.
|
|
146
|
+
|
|
147
|
+
`declared` ordering carries explicit task, model, and harness ID lists. Matrix
|
|
148
|
+
compilers use those lists, never object-property enumeration, and reject a list
|
|
149
|
+
unless it is an exact permutation of its condition-set IDs. Before expansion, a
|
|
150
|
+
compiler resolves every task packet, checks the reference digest, and requires
|
|
151
|
+
`admission.status` to be `admitted`. Capture profiles use the same digest-pinned
|
|
152
|
+
configuration-reference shape as other immutable experiment inputs.
|
|
153
|
+
|
|
154
|
+
For declared matrices, traversal is task outermost, then model, then harness,
|
|
155
|
+
with one-based trial replicas innermost. The compiler rejects duplicate task
|
|
156
|
+
packet digests across task IDs before expansion. The declared cell iterator is
|
|
157
|
+
lazy, so externally supplied trial counts do not allocate a full matrix.
|
|
158
|
+
|
|
159
|
+
The fixtures include a generic 18-cell matrix and a differently shaped matrix
|
|
160
|
+
to show that no study dimensions are built into the contract. Parsed numeric
|
|
161
|
+
controls are limited to JavaScript safe integers.
|
|
162
|
+
|
|
163
|
+
## Run queues
|
|
164
|
+
|
|
165
|
+
`compileRunQueue` expands an experiment into a persisted
|
|
166
|
+
`ebo.run-queue/v1` document. Every entry contains the task-packet freeze
|
|
167
|
+
identity, digest-pinned model and harness configuration references, and a
|
|
168
|
+
one-based trial identity; the queue also retains the selected capture-profile
|
|
169
|
+
reference and coordinator budget. A scheduling digest covers those controls,
|
|
170
|
+
the matrix, seed, and ordering policy; run IDs include that digest so
|
|
171
|
+
standalone consumers reject mutations to any persisted scheduling input. When
|
|
172
|
+
the API is used without a bundle root, each admitted task resolution must carry
|
|
173
|
+
the complete schema-valid freeze record that supplied task identities are
|
|
174
|
+
checked against. Freeze locators are distinct from every packet/configuration
|
|
175
|
+
artifact path and from each other; persisted custom locators are reused when
|
|
176
|
+
queues are revalidated without a bundle root.
|
|
177
|
+
|
|
178
|
+
The compiler supports sequential (`declared` is retained as its legacy name),
|
|
179
|
+
seeded-shuffle (`permuted` is retained as its legacy name), and balanced
|
|
180
|
+
interleaving. Interleaving round-robins the selected dimension (model by
|
|
181
|
+
default) and preserves every cell exactly once, including matrices whose
|
|
182
|
+
groups have different sizes. Configuration references are resolved before
|
|
183
|
+
compilation, and every task packet must have a matching, admitted freeze
|
|
184
|
+
record. A seeded-shuffle with a permutation reference reads that verified
|
|
185
|
+
artifact and currently accepts the declared `fisher-yates-v1` algorithm;
|
|
186
|
+
unknown algorithm definitions fail closed. The normalized queue records the
|
|
187
|
+
resolved algorithm name, so experiment-only validation remains reproducible;
|
|
188
|
+
passing a bundle root additionally rechecks the pinned artifact. Queue writes
|
|
189
|
+
use the existing atomic artifact writer and do not execute work or coordinate
|
|
190
|
+
across machines.
|
|
191
|
+
|
|
192
|
+
The CLI exposes `ebo matrix compile <experiment.json> <bundle-root>
|
|
193
|
+
<queue.json> [--freeze-locator <task-id>=<path>]`, `ebo queue inspect
|
|
194
|
+
<queue.json>`, and `ebo queue validate
|
|
195
|
+
<queue.json> [experiment.json] [--bundle-root <bundle-root>]`. Supplying the
|
|
196
|
+
bundle root lets queue validation recheck each freeze and pinned algorithm
|
|
197
|
+
artifact. The 18-cell fixture is only a generality test;
|
|
198
|
+
the compiler has no fixed task, model, harness, or trial count, subject to the
|
|
199
|
+
bounded 100,000-entry local queue limit; larger matrices require a future
|
|
200
|
+
streaming queue implementation.
|
|
201
|
+
|
|
202
|
+
## Agent SDK run configuration
|
|
203
|
+
|
|
204
|
+
`ebo.agent-sdk-config/v1` is the single discriminated contract behind the five
|
|
205
|
+
digest-pinned configuration artifacts a queue entry already references. The
|
|
206
|
+
`kind` values are `model`, `harness`, `native-limits`, `native-tool-policy`,
|
|
207
|
+
and `capture-profile`; `ebo agent-sdk run` resolves each reference through the
|
|
208
|
+
bundle resolver and validates the record before launching the Agent SDK. The
|
|
209
|
+
model record's `model` must equal the queue entry's model ID, the harness
|
|
210
|
+
adapter must be `claude-agent-sdk`, tool lists are arrays of unique nonempty
|
|
211
|
+
Agent SDK tool names, and `bypassPermissions` is accepted only with an explicit
|
|
212
|
+
`allowDangerouslySkipPermissions: true`. Duplicate JSON keys, unknown fields,
|
|
213
|
+
unsafe numbers, wrong kinds, digest mismatches, and malformed UTF-8 or JSON
|
|
214
|
+
fail before an attempt starts. Credentials and environment overrides are never
|
|
215
|
+
read from these files; authentication stays in the process environment, and
|
|
216
|
+
telemetry content flags default to false. A configured telemetry endpoint
|
|
217
|
+
without a receipt checker remains explicit `not-checked` receipt evidence. The
|
|
218
|
+
full runner specification is
|
|
219
|
+
[agent-sdk-operational-runner.md](agent-sdk-operational-runner.md).
|
|
220
|
+
|
|
221
|
+
Unknown schema versions and sharing classifications are invalid. Consumers must
|
|
222
|
+
validate a document before materializing a workspace or scheduling a run.
|
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
# Run-bundle contract
|
|
2
|
+
|
|
3
|
+
Run bundles retain the evidence needed to inspect one attempt without copying
|
|
4
|
+
native harness payloads into a common event model. This contract is versioned
|
|
5
|
+
as [`schemas/run-bundles/v1.json`](../../schemas/run-bundles/v1.json).
|
|
6
|
+
|
|
7
|
+
## Bundle layout
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
run-bundle/
|
|
11
|
+
manifest.json
|
|
12
|
+
session.jsonl
|
|
13
|
+
hooks.jsonl
|
|
14
|
+
telemetry/
|
|
15
|
+
workspace.patch
|
|
16
|
+
verifier.json # verified tasks only
|
|
17
|
+
capture-report.json
|
|
18
|
+
export/manifest.json
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
`manifest.json` is the run-manifest schema root. Its evidence descriptors are
|
|
22
|
+
the portable index: each gives an artifact ID, source, authority, media type,
|
|
23
|
+
SHA-256 digest, byte size, sharing class, bundle-relative path, and native type
|
|
24
|
+
and identity when the source provides them. Native content stays in the
|
|
25
|
+
referenced file. Artifact IDs are unique within a bundle, and every bundle
|
|
26
|
+
retains exactly one capture-report descriptor.
|
|
27
|
+
|
|
28
|
+
For TypeScript Agent SDK runs, `openClaudeAgentSdkHookCapture` creates the
|
|
29
|
+
no-clobber `hooks.jsonl` sink. Each source-specific record retains the complete
|
|
30
|
+
typed callback input, callback time, empty neutral callback output, abort-signal
|
|
31
|
+
state, and only the session, prompt, tool-use, agent, transcript, and working
|
|
32
|
+
directory identities the callback exposed. Because the native payload can
|
|
33
|
+
contain prompts, tool inputs, and local paths, the resulting artifact is
|
|
34
|
+
restricted evidence; later export policy must not treat the source file as a
|
|
35
|
+
sanitized derivative.
|
|
36
|
+
|
|
37
|
+
`hooks.jsonl` is authoritative for callback occurrence. Optional detailed-beta
|
|
38
|
+
hook spans are a separate timing capability and are not required to infer or
|
|
39
|
+
confirm an occurrence. If a hook append fails, the executor returns the neutral
|
|
40
|
+
empty hook output, keeps the agent operation running, and retains a bounded
|
|
41
|
+
capture warning in the attempt evidence.
|
|
42
|
+
|
|
43
|
+
All paths are bundle-relative. The schema rejects absolute and parent-traversal
|
|
44
|
+
paths; the shared artifact utilities will also resolve symlinks and verify
|
|
45
|
+
digests before use. Each retained path appears exactly once under a
|
|
46
|
+
case-folded portable identity. A sanitized
|
|
47
|
+
partner or public artifact therefore has its own retained path, and source bytes
|
|
48
|
+
cannot masquerade as another evidence class.
|
|
49
|
+
|
|
50
|
+
## Evidence authority
|
|
51
|
+
|
|
52
|
+
| Authority | Source of record | It can answer |
|
|
53
|
+
| --- | --- | --- |
|
|
54
|
+
| `semantic` | Native session and hook artifacts | What the agent and harness exchanged or observed |
|
|
55
|
+
| `timing-resource` | Native telemetry | Timing, tokens, cost, and resource observations |
|
|
56
|
+
| `outcome` | Workspace and optional verified-task artifacts | What changed and, only for verified tasks, whether executable assertions passed |
|
|
57
|
+
| `capture` | Capture report | Which evidence is available, missing, or unsupported |
|
|
58
|
+
| `export` | Export manifest | Which approved artifacts were prepared for sharing |
|
|
59
|
+
|
|
60
|
+
The contract does not describe a uniform event ontology or attach semantic
|
|
61
|
+
quality labels. Source-specific records remain authoritative until a later,
|
|
62
|
+
capture-qualified normalization step.
|
|
63
|
+
|
|
64
|
+
Evidence kind and authority are fixed pairs: sessions and hooks are semantic;
|
|
65
|
+
telemetry is timing-resource; workspace and verifier records are outcome; the
|
|
66
|
+
capture report is capture; and the export manifest is export.
|
|
67
|
+
|
|
68
|
+
## Attempt and terminal semantics
|
|
69
|
+
|
|
70
|
+
A run identifies the declared task/model/harness condition. An attempt is one
|
|
71
|
+
execution of that run; retries get a new attempt ID and must point at `retryOf`.
|
|
72
|
+
`retryOf` cannot name the attempt itself. No attempt replaces prior evidence.
|
|
73
|
+
When a run declares a native session ID, it retains at least one session
|
|
74
|
+
reference naming that same native session, with at least one parsed native
|
|
75
|
+
record.
|
|
76
|
+
The same rule applies to a declared native trace ID and retained telemetry
|
|
77
|
+
evidence. Runtime components are unique by source, name, and version.
|
|
78
|
+
|
|
79
|
+
`runtime` is a non-empty list of source-specific components, each with source,
|
|
80
|
+
name, and version. One component's source or name and version represents the
|
|
81
|
+
declared harness. An Agent SDK run can record SDK and CLI components; an Agent
|
|
82
|
+
Server run can record only its server component. No integration invents an
|
|
83
|
+
absent SDK or CLI identity.
|
|
84
|
+
|
|
85
|
+
`terminal` separates these conditions:
|
|
86
|
+
|
|
87
|
+
| Terminal state | Failure class | Stop reason |
|
|
88
|
+
| --- | --- | --- |
|
|
89
|
+
| `completed` | `none` | `none` |
|
|
90
|
+
| `failed` | `infrastructure` or `task` | `none` |
|
|
91
|
+
| `stopped` | `none` | `budget` or `policy` |
|
|
92
|
+
| `interrupted` | `infrastructure` | `none` |
|
|
93
|
+
|
|
94
|
+
Every run declares `assessmentMode`. `observational` is the primary mode for
|
|
95
|
+
open-ended engineering work: a `completed` terminal means execution ended
|
|
96
|
+
normally with retained workspace evidence, not that the task was correct or
|
|
97
|
+
stakeholder-approved. It has no verifier artifact. `verified` preserves the
|
|
98
|
+
existing verifier-backed completion and task-failure semantics.
|
|
99
|
+
|
|
100
|
+
Capture incompleteness is not a task or infrastructure failure class. It is a
|
|
101
|
+
capture-report qualification with an explicit missing-evidence reason.
|
|
102
|
+
|
|
103
|
+
## Qualification
|
|
104
|
+
|
|
105
|
+
`capture-report/v1` records `semantic`, `timingResource`, and `outcome`
|
|
106
|
+
capabilities separately. A `qualified` report requires available semantic and
|
|
107
|
+
outcome evidence and checked timing-resource evidence. For observational runs,
|
|
108
|
+
workspace evidence satisfies the outcome capability; verified runs also require
|
|
109
|
+
their verifier evidence. Missing optional beta spans are recorded as
|
|
110
|
+
`optional-beta-unavailable` affecting `timing-resource`; they never assert that
|
|
111
|
+
semantic evidence is missing. Every unavailable capability has an explicit
|
|
112
|
+
missing-evidence entry; optional-beta-unavailable affects timing-resource only.
|
|
113
|
+
An available capability requires an indexed artifact with that authority. The
|
|
114
|
+
embedded capture report must also name the containing bundle. An `incomplete`
|
|
115
|
+
report remains a valid retained partial bundle but is not capture-qualified.
|
|
116
|
+
Missing-evidence effects cannot contradict a capability reported as available.
|
|
117
|
+
`unsupported` and `not-checked` reasons each match their corresponding
|
|
118
|
+
capability status.
|
|
119
|
+
|
|
120
|
+
An artifact may retain `sharingClass: unknown` when capture cannot classify it.
|
|
121
|
+
Exports fail closed: unknown artifacts and unknown export classes are never
|
|
122
|
+
ready or exported.
|
|
123
|
+
|
|
124
|
+
The final capture report for a direct Agent SDK attempt also retains the exact
|
|
125
|
+
SDK/CLI capability profile, effective model/tool/permission/budget
|
|
126
|
+
configuration, and expected hook set used for qualification. Its
|
|
127
|
+
`structuralQualification` field preserves the resulting dimension statuses and
|
|
128
|
+
reason codes. These are capture facts, not behavioral judgments, and remain
|
|
129
|
+
internal until the export policy produces an approved derivative.
|
|
130
|
+
|
|
131
|
+
Real package-manager workspaces may declare a bounded outcome projection:
|
|
132
|
+
directory names such as `node_modules` and `coverage`, source `.gitignore`
|
|
133
|
+
rules, and empty-directory omission. EBO copies the final workspace, applies
|
|
134
|
+
that policy without mutating the live attempt, records the policy in the
|
|
135
|
+
capture report, and then verifies the resulting patch or snapshot. Link and
|
|
136
|
+
hard-link rejection remains unchanged. Hook serialization warnings are retained
|
|
137
|
+
in the Agent SDK capture report and qualify the hook dimension as a gap rather
|
|
138
|
+
than erasing an otherwise complete native session and hook stream.
|
|
139
|
+
|
|
140
|
+
`captureClaudeAgentSdkRun` is the single-run production composition boundary.
|
|
141
|
+
It reuses the existing lifecycle, caller-supplied workspace coordinator,
|
|
142
|
+
passive Agent SDK sinks, optional verified-task result, assembler, and qualifier. It neither
|
|
143
|
+
reads a run queue nor retries an attempt; an operational runner may call it once
|
|
144
|
+
for each already-resolved queue entry.
|
|
145
|
+
|
|
146
|
+
`qualifyRunBundle` performs the post-capture structural check without adding a
|
|
147
|
+
new artifact dialect. Its report evaluates attempt identity, session evidence,
|
|
148
|
+
pinned hook capability versus observed callbacks, telemetry receipt and
|
|
149
|
+
optional timing, workspace outcome, assessment mode, any required verified-task result, terminal classification,
|
|
150
|
+
and sharing classification independently. The overall result is `qualified`,
|
|
151
|
+
`qualified-with-gaps`, or `unqualified`, with stable reason codes and the named
|
|
152
|
+
evidence ID. Optional detailed-beta timing and a missing collector receipt are
|
|
153
|
+
timing gaps; missing or malformed semantic/outcome evidence, an unusable patch,
|
|
154
|
+
or contradictory capture-report facts are unqualified. The report contains no
|
|
155
|
+
behavioral or semantic-quality judgment.
|
|
156
|
+
|
|
157
|
+
An explicit `unsupported` capture-report capability remains qualified and is
|
|
158
|
+
reported as `unsupported`, not rewritten as missing evidence. Qualification
|
|
159
|
+
caps every retained artifact read at 64 MiB; larger evidence is rejected with
|
|
160
|
+
`ARTIFACT_TOO_LARGE` before whole-file parsing. Parsed session records and raw
|
|
161
|
+
telemetry payloads are not retained in the qualification report.
|
|
162
|
+
|
|
163
|
+
Session qualification requires the descriptor, manifest, and every observed
|
|
164
|
+
native session identity to agree. Hook JSONL must contain at least one pinned
|
|
165
|
+
callback in `hook`, `hook_event_name`, or a source-specific `type`; unrelated
|
|
166
|
+
nonempty JSON does not count as hook evidence. A telemetry artifact without a
|
|
167
|
+
collector receipt is a `TELEMETRY_RECEIPT_MISSING` gap, including the supported
|
|
168
|
+
usage-only path.
|
|
169
|
+
|
|
170
|
+
Qualification reuses manifest schema checks, descriptor digest/path readback,
|
|
171
|
+
mode-appropriate outcome binding, and export-manifest validation. When a
|
|
172
|
+
workspace patch is present, callers supply the admitted starting fixture so the
|
|
173
|
+
patch can be checked with `git apply --check`; omission leaves an explicit
|
|
174
|
+
`WORKSPACE_PATCH_NOT_CHECKED` gap.
|
|
175
|
+
|
|
176
|
+
## Portable export
|
|
177
|
+
|
|
178
|
+
`createPortableRunBundleExport` reads a qualified run bundle without changing
|
|
179
|
+
it and creates a separate partner or public derivative tree. Its policy fixes
|
|
180
|
+
the artifact and string byte limits plus caller-supplied sensitive values. The
|
|
181
|
+
exporter also removes credential-bearing environment values, local paths and
|
|
182
|
+
usernames, hidden-reasoning fields, and disallowed raw API bodies. Run,
|
|
183
|
+
attempt, bundle, session, and trace identities are replaced consistently so
|
|
184
|
+
cross-artifact correlation survives without exposing native identifiers.
|
|
185
|
+
|
|
186
|
+
The export allowlist covers JSONL session/hooks, JSON telemetry,
|
|
187
|
+
text workspace patches, JSON verifier/capture reports, and text verifier
|
|
188
|
+
diagnostics. Unknown classifications and unrecognized kind/media pairs stop
|
|
189
|
+
the export. Restricted workspace snapshots may be retained up to 128 MiB for
|
|
190
|
+
qualification, but portable exports explicitly exclude them as
|
|
191
|
+
`unsupported-workspace-snapshot`; opaque archive bytes never pass through the
|
|
192
|
+
text sanitizer. Existing source export manifests are likewise excluded and
|
|
193
|
+
recorded rather than recursively exported.
|
|
194
|
+
|
|
195
|
+
The derivative `export-manifest/v1` records each portable artifact's source
|
|
196
|
+
digest, every applied transformation, each exclusion, the effective policy
|
|
197
|
+
digest, and rewritten correlations. Creation reports success only after
|
|
198
|
+
`readPortableRunBundleExport` rechecks schema, paths, digests, sizes,
|
|
199
|
+
references, policy, JSON/JSONL structure, and a final secret scan. A failed
|
|
200
|
+
creation removes its newly-created destination tree; an existing destination
|
|
201
|
+
is never replaced.
|
|
202
|
+
|
|
203
|
+
The remainder of this verifier section applies only to `verified` tasks.
|
|
204
|
+
Verifier results cannot contradict their assertions: passed results have no
|
|
205
|
+
failed assertion, while failed results retain at least one failed assertion.
|
|
206
|
+
Assertion IDs are unique, and a retained verifier result names the containing
|
|
207
|
+
bundle. Completed runs retain passed verifier results; task-failed runs retain
|
|
208
|
+
at least one failed verifier result and may retain independent passed results.
|
|
209
|
+
Both verified outcomes require retained verifier and workspace evidence; workspace
|
|
210
|
+
evidence alone cannot establish task pass or task failure. A passed verifier
|
|
211
|
+
result contains only passed assertions and, when retained, an exit code of zero.
|
|
212
|
+
Every passed or failed verifier also names the retained workspace artifact and
|
|
213
|
+
digest it evaluated.
|
|
214
|
+
|
|
215
|
+
The executor receives both the retained workspace artifact reference and a
|
|
216
|
+
separate live-workspace fingerprint; the executor options require the retained
|
|
217
|
+
workspace reference to carry that same fingerprint. The v1 live-workspace fingerprint hashes
|
|
218
|
+
the root and sorted descendant relative paths, entry kinds, permission mode
|
|
219
|
+
bits, reproducible modification times, and file bytes; hard-linked files,
|
|
220
|
+
symbolic links, and unsupported entry kinds are rejected. POSIX snapshots use
|
|
221
|
+
the metadata-preserving system copy path with nanosecond modification times;
|
|
222
|
+
the Windows fallback uses Node's reproducible millisecond precision. The
|
|
223
|
+
fingerprint must
|
|
224
|
+
match the live workspace before and after its private snapshot is created. The
|
|
225
|
+
executor then evaluates that detached snapshot, while the artifact digest
|
|
226
|
+
remains the digest of the retained workspace evidence. The complete executor
|
|
227
|
+
result records the snapshot fingerprint alongside the workspace reference, and
|
|
228
|
+
manifest workspace descriptors may carry it for later terminal binding checks.
|
|
229
|
+
|
|
230
|
+
Verifier execution uses a small subprocess boundary. The executor resolves the
|
|
231
|
+
digest-pinned restricted verifier from its task-bundle root, stages it in a
|
|
232
|
+
private trusted subdirectory separate from the snapshot, and invokes the pinned
|
|
233
|
+
Node runtime with the staged verifier path followed by the snapshot workspace
|
|
234
|
+
path. Launcher options cannot replace the staged entry point, and the child
|
|
235
|
+
environment contains only fixed coordinator variables; `PATH` points to a
|
|
236
|
+
dedicated empty trusted-stage directory, while Node preload, POSIX dynamic-loader,
|
|
237
|
+
shell-startup, and interpreter module-path injection are unavailable. Verifier
|
|
238
|
+
tools must be invoked by absolute pinned paths. Normal completion is reported
|
|
239
|
+
over a parent-owned extra stdio channel rather than a marker file or inherited
|
|
240
|
+
environment variable, so ordinary workspace descendants cannot recreate it. The
|
|
241
|
+
restricted implementation and any
|
|
242
|
+
reference solution remain outside that workspace. `.mjs`/`.cjs` locators retain
|
|
243
|
+
their module semantics; ambiguous `.js` or extensionless artifacts default to
|
|
244
|
+
CommonJS unless the caller supplies `moduleFormat: "module"`, and explicit
|
|
245
|
+
formats cannot contradict an unambiguous suffix. The verifier writes one JSON
|
|
246
|
+
object to stdout:
|
|
247
|
+
|
|
248
|
+
```json
|
|
249
|
+
{
|
|
250
|
+
"assertions": [
|
|
251
|
+
{ "id": "unit-tests", "status": "passed" },
|
|
252
|
+
{ "id": "lint", "status": "failed" }
|
|
253
|
+
]
|
|
254
|
+
}
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
Each assertion object contains exactly `id` and `status`; undeclared fields,
|
|
258
|
+
non-string statuses, duplicate IDs, and IDs longer than 256 characters are
|
|
259
|
+
verifier errors rather than silently normalized away.
|
|
260
|
+
|
|
261
|
+
The executor records the selected verifier's locator, digest, and module format, the assertion
|
|
262
|
+
list, `durationMs`, observed `exitCode` when the process exits normally, and a
|
|
263
|
+
`status` of `passed`, `failed`, or `error`. A run manifest may declare the
|
|
264
|
+
task-bound verifier reference under `run.verifier`; manifest validation then
|
|
265
|
+
requires each retained unsanitized verifier result to identify that same
|
|
266
|
+
reference. A valid assertion failure is a task failure; timeout, crash, invalid
|
|
267
|
+
UTF-8/JSON, duplicate or invalid assertion, and an exit/assertion contradiction
|
|
268
|
+
are verifier errors. A failed assertion therefore requires a nonzero verifier
|
|
269
|
+
exit; a zero exit paired with a failure is not a task result. `not-run` remains
|
|
270
|
+
available for a caller that records a verifier which was never started, and its
|
|
271
|
+
assertions must all be `not-run`. Stdout
|
|
272
|
+
and stderr are drained without an unbounded buffer and persisted to private
|
|
273
|
+
files while the process runs, so a partial attempt retains output even when
|
|
274
|
+
execution ends abnormally. A timeout terminates the verifier process group (or
|
|
275
|
+
process tree on Windows). Each retained stream is represented by an
|
|
276
|
+
execution-specific diagnostic reference with a `stream` (`stdout` or `stderr`),
|
|
277
|
+
bundle-relative `locator`, SHA-256 `digest`, retained `sizeBytes`, and a
|
|
278
|
+
`truncated` flag. Sanitized verifier results may retain diagnostics only when
|
|
279
|
+
each one carries a source diagnostic origin and points to a separately
|
|
280
|
+
classified `diagnostic` evidence sidecar. The sidecar's path, digest, and size
|
|
281
|
+
must match exactly, and it must be included in the export. The result remains
|
|
282
|
+
valid even when diagnostics are truncated.
|
|
283
|
+
The `durationMs` and `diagnostics` fields are optional for older v1 records;
|
|
284
|
+
new executor results include both. An `error` result requires a nonempty
|
|
285
|
+
explanation and may omit `workspace` when the verifier failed before a
|
|
286
|
+
workspace was available; it must not invent a workspace binding. Coordinator
|
|
287
|
+
failures such as timeout, launch, parse, or
|
|
288
|
+
cleanup errors are recorded in the result's `error` field; the native stderr
|
|
289
|
+
diagnostic remains byte-for-byte separate. `error` is not valid on passed or
|
|
290
|
+
failed results. Sanitized verifier derivatives preserve `durationMs` and
|
|
291
|
+
`error`; sensitive error text may use `errorRedacted: true` with the literal
|
|
292
|
+
`[redacted]`, but cannot be replaced by an unmarked claim. The process-group boundary cannot
|
|
293
|
+
contain a verifier that deliberately creates a new POSIX session; callers that
|
|
294
|
+
run untrusted verifiers need an OS sandbox or equivalent isolation boundary.
|
|
295
|
+
|
|
296
|
+
The result serializer validates `verifier-result/v1` before writing it. The
|
|
297
|
+
diagnostic references are read back and digest-checked before the result is
|
|
298
|
+
saved, so a result cannot point at missing or changed diagnostic bytes. Result
|
|
299
|
+
paths use no-clobber persistence: an existing result, manifest, or other
|
|
300
|
+
retained evidence file is never replaced by a later verifier write, and a
|
|
301
|
+
crash between the no-clobber link and temporary-name cleanup is recovered on
|
|
302
|
+
the next verified read. Manifest
|
|
303
|
+
validation also cross-checks each retained verifier's `bundleId` and workspace
|
|
304
|
+
artifact ID/digest against the containing bundle's retained evidence. The
|
|
305
|
+
`manifest.json` path and its descendants are reserved for the containing
|
|
306
|
+
manifest and cannot be used for verifier results or diagnostic directories.
|
|
307
|
+
The CLI applies duplicate-key detection to standalone verifier JSON before
|
|
308
|
+
parsing, just as manifest-nested verifier artifacts and subprocess output are
|
|
309
|
+
checked before interpretation. Manifest validation requires a retained passed
|
|
310
|
+
verifier for a completed verified run and a retained failed verifier for a
|
|
311
|
+
task-failed run, and checks each verifier's status against that terminal
|
|
312
|
+
outcome before the bundle is accepted. Observational completion instead
|
|
313
|
+
requires retained workspace evidence and rejects verifier evidence.
|
|
314
|
+
|
|
315
|
+
## Sharing boundary
|
|
316
|
+
|
|
317
|
+
A partner export that lists restricted native artifacts is `blocked`. A `ready`
|
|
318
|
+
or `exported` package resolves every artifact ID and requires every descriptor
|
|
319
|
+
to have the export's exact sharing class. A public package therefore cannot
|
|
320
|
+
bypass lookup or classification, and both partner and public packages need
|
|
321
|
+
separately sanitized artifacts. Each such descriptor records `sanitizedFrom`
|
|
322
|
+
with the retained source artifact ID and digest, and has a distinct bundle path;
|
|
323
|
+
changing a native artifact's sharing class is not sanitization. The export pipeline performs the actual
|
|
324
|
+
sanitization and readback; the v1 contract fixture makes the unsafe direct
|
|
325
|
+
reference visibly blocked. A ready or exported manifest also names its
|
|
326
|
+
containing bundle before its artifact list is approved. Ready and exported
|
|
327
|
+
manifests contain at least one non-export evidence artifact; blocked and
|
|
328
|
+
unrequested records may be empty but still name their containing bundle.
|
|
329
|
+
|
|
330
|
+
The contract is intentionally only a declaration. Schema loading, safe path
|
|
331
|
+
resolution, atomic persistence, and byte-level digest verification are shared
|
|
332
|
+
artifact primitives delivered separately; no runner, adapter, exporter, or
|
|
333
|
+
evaluation behavior is defined here.
|
|
334
|
+
|
|
335
|
+
## Fixtures
|
|
336
|
+
|
|
337
|
+
The four small fixtures under `test/fixtures/run-bundles/` establish the
|
|
338
|
+
contract boundary:
|
|
339
|
+
|
|
340
|
+
- `complete`: all five evidence authorities are referenced.
|
|
341
|
+
- `task-failed`: a verifier-backed task failure is distinct from infrastructure
|
|
342
|
+
failure.
|
|
343
|
+
- `interrupted`: retained semantic evidence plus an incomplete capture report;
|
|
344
|
+
no outcome evidence is invented.
|
|
345
|
+
- `telemetry-incomplete`: semantic and outcome evidence remain available while
|
|
346
|
+
optional beta telemetry is explicitly absent.
|
|
347
|
+
|
|
348
|
+
The checked-in Node contract test runs the schema, cross-descriptor uniqueness,
|
|
349
|
+
sharing-path and export boundaries, capture-report correlation, capability
|
|
350
|
+
evidence, artifact references/digests, retry identity, and representative
|
|
351
|
+
rejected records. The later shared artifact validator reuses these fixtures; it
|
|
352
|
+
owns filesystem hardening and persistence rather than a second contract.
|
|
353
|
+
The build script clears compiled output first, and its regression test proves a
|
|
354
|
+
stale compiled test cannot survive into test discovery.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Run lifecycle and process protocol
|
|
2
|
+
|
|
3
|
+
`src/lifecycle.ts` owns one declared run cell and one attempt. A run is
|
|
4
|
+
identified by task, model, and harness IDs; an attempt gets a fresh ID and
|
|
5
|
+
number. `retryAttempt` links a later attempt with `retryOf`, so callers must
|
|
6
|
+
choose a distinct record/evidence path. Attempt paths are reserved before any
|
|
7
|
+
callback runs; an existing record path is never reopened by a new execution,
|
|
8
|
+
and the runner never retries implicitly.
|
|
9
|
+
|
|
10
|
+
The guarded attempt phases are:
|
|
11
|
+
|
|
12
|
+
```text
|
|
13
|
+
created -> setup -> running -> verifying -> cleaning -> terminal
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Setup, harness execution, optional verifier execution, cleanup, and evidence flushing
|
|
17
|
+
are injected callbacks. Setup and harness drivers can register independent
|
|
18
|
+
shutdown handles for in-flight processes. `executeRunAttempt` passes an
|
|
19
|
+
`AbortSignal`, enforces the coordinator and harness budgets, and records phase
|
|
20
|
+
timestamps in an
|
|
21
|
+
`ebo.attempt/v1` record. Each record declares `observational` or `verified`
|
|
22
|
+
assessment. An observational attempt skips the verifying phase; normal harness
|
|
23
|
+
termination plus retained workspace evidence is execution completion, not task
|
|
24
|
+
success. Only a failed verifier on a verified task with retained workspace
|
|
25
|
+
evidence is a task failure; a harness-declared task result without verifier
|
|
26
|
+
evidence remains an infrastructure failure. A verifier execution error, setup
|
|
27
|
+
error, harness error, or cleanup error after an otherwise successful run is
|
|
28
|
+
also infrastructure evidence. A verified completed attempt needs both a passed
|
|
29
|
+
verifier and a retained workspace artifact; an observational completed attempt
|
|
30
|
+
needs the workspace artifact and carries no verifier evidence. Missing capture flush support is
|
|
31
|
+
explicit as `capture-incomplete` and does not become a task failure.
|
|
32
|
+
|
|
33
|
+
`src/process-protocol.ts` is a narrow process boundary, not a JSON-RPC
|
|
34
|
+
implementation. `ProtocolProcess` parses newline-delimited JSON only to reject
|
|
35
|
+
malformed stdout, keeps stdout machine-only, and drains bounded stderr into a
|
|
36
|
+
diagnostic result (and optional `stderrPath`). `ProtocolEvidenceRecorder`
|
|
37
|
+
retains raw frames plus caller-supplied request, response, notification,
|
|
38
|
+
completion, and capability observations. Drivers provide method names,
|
|
39
|
+
correlation IDs, native identities, and completion evidence; the runner does
|
|
40
|
+
not infer prompt completion or map records into EBO event families.
|
|
41
|
+
|
|
42
|
+
JSONL records are flushed and fsynced as they arrive. Valid frames retain their
|
|
43
|
+
original line text alongside parsed data, so duplicate keys or large numeric
|
|
44
|
+
IDs cannot be silently rewritten by a JavaScript round trip. The stdout line
|
|
45
|
+
limit is enforced while bytes are consumed. When a caller supplies a JSONL
|
|
46
|
+
writer, the process derives a conservative effective stdout limit from that
|
|
47
|
+
writer's per-record envelope capacity so retaining both raw and parsed frame
|
|
48
|
+
evidence cannot turn a valid frame into an append failure. In-memory
|
|
49
|
+
observations use a bounded tail; the JSONL file remains the complete source
|
|
50
|
+
record. Interruption and malformed output therefore leave a readable partial
|
|
51
|
+
evidence file and a process result with launch identity, exit/signal state, and
|
|
52
|
+
termination reason.
|
|
53
|
+
`shutdown()` and `interrupt()` are explicit operations; no process retry is
|
|
54
|
+
performed.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Cursor SDK input example
|
|
2
|
+
|
|
3
|
+
These five records are the minimal Cursor-specific inputs referenced by an EBO
|
|
4
|
+
experiment. Copy them into the caller-owned bundle, replace the model
|
|
5
|
+
placeholder with an exact ID returned by `Cursor.models.list()`, compute the
|
|
6
|
+
normal EBO artifact digests, and reference them from the experiment's model,
|
|
7
|
+
harness, native-limits, native-tool-policy, and capture-profile fields.
|
|
8
|
+
|
|
9
|
+
Use the standard `task-packet admit`, `task-packet freeze`, `matrix compile`,
|
|
10
|
+
`queue validate`, and `cursor run` commands. No Cursor-specific preparation
|
|
11
|
+
script or cloud agent is required.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"schemaVersion":"ebo.cursor-sdk-config/v1","kind":"capture-profile","nativeOtlp":"unsupported","workspaceOutcome":{"excludeDirectoryNames":["node_modules"]}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"schemaVersion":"ebo.cursor-sdk-config/v1","kind":"harness","adapter":"cursor-sdk","sdkVersion":"1.0.31"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"schemaVersion":"ebo.cursor-sdk-config/v1","kind":"model","provider":"cursor","model":{"id":"REPLACE_WITH_EXACT_CATALOG_MODEL"}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"schemaVersion":"ebo.cursor-sdk-config/v1","kind":"native-limits","shutdownGraceMs":2000,"maxNativeRecordBytes":16777216}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"schemaVersion":"ebo.cursor-sdk-config/v1","kind":"native-tool-policy","tools":["read","edit","grep","glob","ls"],"disallowedTools":["shell","task","mcp","webSearch","webFetch"],"sandbox":{"enabled":false},"settingSources":[],"autoReview":false,"enableAgentRetries":false}
|