@themoltnet/agent-daemon 0.42.0 → 0.43.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.
Files changed (3) hide show
  1. package/README.md +36 -23
  2. package/dist/cli.js +1276 -1355
  3. package/package.json +9 -7
package/dist/cli.js CHANGED
@@ -5,10 +5,10 @@ import { Type } from "typebox";
5
5
  import "multiformats/cid";
6
6
  import "multiformats/codecs/json";
7
7
  import "multiformats/hashes/sha2";
8
- import { Value } from "typebox/value";
8
+ import "typebox/value";
9
9
  import { dirname, join, resolve } from "node:path";
10
10
  import { parseArgs, promisify } from "node:util";
11
- import { AgentRuntime, ApiTaskReporter, ApiTaskSource, PollingApiTaskSource } from "@themoltnet/agent-runtime";
11
+ import { AgentRuntime, ApiTaskReporter, ApiTaskSource, PollingApiTaskSource, resolveProfileWarmSessionTtlSec, resolveRuntimeProfile, resolveRuntimeProfiles, validateRuntimeProfilePrerequisites } from "@themoltnet/agent-runtime";
12
12
  import { GuestEnvironmentBoundaryError, assertGuestEnvironmentBoundary, createPiRetryTriage, findMainWorktree, isResolvedPathInsideRoot, normalizeRetryTriageResult, redactRetryTriageSecrets } from "@themoltnet/pi-runtime";
13
13
  import { execFile, execFileSync } from "node:child_process";
14
14
  import { createReadStream, createWriteStream, existsSync, mkdirSync, readdirSync, realpathSync, rmSync } from "node:fs";
@@ -23,6 +23,8 @@ import { ed25519 } from "@noble/curves/ed25519.js";
23
23
  import * as ed from "@noble/ed25519";
24
24
  import { createHash as createHash$1, randomBytes } from "crypto";
25
25
  import "@ipld/dag-cbor";
26
+ import "@noble/ciphers/chacha";
27
+ import "@noble/hashes/hkdf";
26
28
  import { once } from "node:events";
27
29
  import { pino, transport } from "pino";
28
30
  import { metrics } from "@opentelemetry/api";
@@ -39,64 +41,6 @@ import { mkdir, realpath, stat } from "node:fs/promises";
39
41
  import { pipeline } from "node:stream/promises";
40
42
  import { Writable } from "node:stream";
41
43
  import { createGzip } from "node:zlib";
42
- //#region ../../libs/tasks/src/context.ts
43
- /**
44
- * How an executor delivers a context entry to its underlying LLM.
45
- * V1 bindings only; Tier-2 (reference_file, mcp_resource, imported_file,
46
- * tool_response_seed, additional_context_hook) ship in a later slice.
47
- */
48
- var CONTEXT_BINDINGS = [
49
- "skill",
50
- "context_inline",
51
- "prompt_prefix",
52
- "user_inline"
53
- ];
54
- /** Maximum UTF-16 code units accepted in one ContextRef content field. */
55
- var CONTEXT_REF_MAX_CONTENT_LENGTH = 65536;
56
- var ContextBinding = Type.Unsafe(Type.Union(CONTEXT_BINDINGS.map((binding) => Type.Literal(binding)), { $id: "ContextBinding" }));
57
- /**
58
- * One context entry. Bytes are inlined: the proposer chose them, and the
59
- * task's `inputCid` already pins the entire input — including
60
- * `context[]` — so we don't need a separate per-entry hash, fetcher, or
61
- * flagged-content gate. Tasks reference rendered packs (or any other
62
- * external content) by copying their bytes into `content` at task
63
- * creation time.
64
- *
65
- * - `slug` — short identifier the daemon uses to disambiguate
66
- * entries. For `skill` binding it becomes the directory
67
- * name under the runtime's skill discovery path. Must be
68
- * kebab-case-safe (alphanumeric + dashes/underscores).
69
- * - `binding` — how the bytes are delivered to the LLM (see above).
70
- * - `content` — UTF-8 text. Capped at 65,536 UTF-16 code units per
71
- * entry; total per-task context bytes are bounded by the
72
- * soft `maxItems` cap and per-binding daemon limits.
73
- * Raised from 32 KiB in 2026-05 — protocol-heavy operator
74
- * skills (e.g. `.claude/skills/legreffier/SKILL.md`) ship
75
- * at ~35 KiB inline, and the original cap was sized for
76
- * short example skills, not the kind of skill the eval
77
- * substrate is dogfooded on (#943, #823).
78
- */
79
- var ContextRef = Type.Object({
80
- slug: Type.String({
81
- minLength: 1,
82
- maxLength: 64,
83
- pattern: "^[a-zA-Z0-9_-]+$"
84
- }),
85
- binding: ContextBinding,
86
- content: Type.String({
87
- minLength: 1,
88
- maxLength: CONTEXT_REF_MAX_CONTENT_LENGTH
89
- })
90
- }, {
91
- $id: "ContextRef",
92
- additionalProperties: false
93
- });
94
- /** Reusable input fragment for any task type. Soft cap at 5 items. */
95
- var TaskContext = Type.Array(ContextRef, {
96
- $id: "TaskContext",
97
- maxItems: 5
98
- });
99
- //#endregion
100
44
  //#region ../../libs/tasks/src/rubric.ts
101
45
  /**
102
46
  * Rubric — structured acceptance criteria used by judgment tasks.
@@ -199,380 +143,868 @@ function validateRubricWeights(rubric) {
199
143
  return null;
200
144
  }
201
145
  //#endregion
202
- //#region ../../libs/tasks/src/runtime-models.ts
146
+ //#region ../../libs/tasks/src/success-criteria.ts
203
147
  /**
204
- * Runtime model catalog: a list of supported provider/model couples that
205
- * MoltNet daemons can target. Backed by the `runtime_models` table.
148
+ * SuccessCriteria — proposer-stated acceptance criteria, evaluated in two
149
+ * complementary places.
206
150
  *
207
- * Scope is intrinsic to the row:
208
- * - `teamId == null` => global entry (MoltNet-seeded, read-only to most callers)
209
- * - `teamId != null` => team-owned custom entry
151
+ * Before this envelope existed, criteria were scattered: a vestigial
152
+ * `criteriaCid` column nobody resolved, free-form prose on
153
+ * `fulfill_brief.input`, and inline `rubric` / `criteria[]` fields on
154
+ * judgment-task inputs. None of those were machine-verifiable
155
+ * end-to-end.
210
156
  *
211
- * The REST API exposes a single shape regardless of scope; the team header
212
- * gates which rows are returned.
157
+ * This module defines a single, content-addressable envelope a proposer
158
+ * attaches to any task type. It has four orthogonal sections — pick
159
+ * whichever apply per task type:
160
+ *
161
+ * - `gates` Promise-level structural/process checks
162
+ * - `assertions` Declarative claims about output JSON
163
+ * - `rubric` Weighted-criteria scoring instrument, reused
164
+ * verbatim from `./rubric.ts`.
165
+ * - `sideEffects` Required process side-effects (e.g. diary entry)
166
+ *
167
+ * ## Two roles, two task types
168
+ *
169
+ * **Producer self-assessment** (fulfillment tasks: `fulfill_brief`,
170
+ * `curate_pack`, `render_pack`). The producer **LLM** evaluates the
171
+ * criteria against its own output and emits a `VerificationRecord`
172
+ * inside `output.verification`. The daemon is pure passthrough — it
173
+ * does not run `evaluateAssertions`, does not inspect the verification
174
+ * record. The REST API is dumb storage; it never re-runs assertions and
175
+ * never runs LLMs. The cross-field rule
176
+ * `requireVerificationWhenCriteriaPresent` enforces "verification
177
+ * required iff successCriteria present" at task-output validation time
178
+ * (server-side schema check). Self-assessment is a truthful self-rating,
179
+ * NOT enforcement — `verification.passed=false` does not block /complete
180
+ * and does not affect `acceptedAttemptN`. See
181
+ * `docs/use/tasks-and-runtime.md` for the full producer/judge flow.
182
+ *
183
+ * **Binding evaluation** (judgment tasks: `assess_brief`, `judge_pack`).
184
+ * A separate task whose IS the application of `successCriteria` to
185
+ * someone else's output. Different agent (enforced at claim time), same
186
+ * envelope. The judge's verdict is binding: this is the *gate* in the
187
+ * MoltNet model. The rubric inside `successCriteria.rubric` IS the job
188
+ * spec for the judge.
189
+ *
190
+ * The clean chain: producer task with `successCriteria` → producer
191
+ * self-assesses honestly → proposer (or automation) creates a downstream
192
+ * judgment task that references the same `successCriteria` (or a
193
+ * stricter rubric) → judgment task delivers the binding verdict.
194
+ *
195
+ * Storage: SuccessCriteria lives inline at `task.input.successCriteria`,
196
+ * pinned via the task's `inputCid`. No separate column or hash. When
197
+ * #881 lands, the `rubric` field can graduate to `{ rubricCid }` lookup
198
+ * without changing this envelope, and producer + judge tasks can pin
199
+ * the SAME rubric across the chain for end-to-end auditability.
213
200
  */
214
- var RuntimeModelProvider = Type.String({
215
- minLength: 1,
216
- maxLength: 100,
217
- pattern: "^[a-zA-Z0-9][a-zA-Z0-9._-]{0,99}$"
201
+ var SchemaCheckSpec = Type.Object({ schemaCid: Type.String({ minLength: 1 }) }, { additionalProperties: false });
202
+ var CidEqualsSpec = Type.Object({
203
+ path: Type.String({ minLength: 1 }),
204
+ expected: Type.String({ minLength: 1 })
205
+ }, { additionalProperties: false });
206
+ var SubmitToolCallGate = Type.Object({
207
+ id: Type.String({ minLength: 1 }),
208
+ kind: Type.Literal("submit-tool-call"),
209
+ description: Type.String({ minLength: 1 }),
210
+ required: Type.Boolean()
211
+ }, { additionalProperties: false });
212
+ var Gate = Type.Union([
213
+ SubmitToolCallGate,
214
+ Type.Object({
215
+ id: Type.String({ minLength: 1 }),
216
+ kind: Type.Literal("schema-check"),
217
+ spec: SchemaCheckSpec,
218
+ required: Type.Boolean()
219
+ }, { additionalProperties: false }),
220
+ Type.Object({
221
+ id: Type.String({ minLength: 1 }),
222
+ kind: Type.Literal("cid-equals"),
223
+ spec: CidEqualsSpec,
224
+ required: Type.Boolean()
225
+ }, { additionalProperties: false })
226
+ ], { $id: "Gate" });
227
+ var AssertionOp = Type.Union([
228
+ Type.Literal("exists"),
229
+ Type.Literal("equals"),
230
+ Type.Literal("matches"),
231
+ Type.Literal("in-range"),
232
+ Type.Literal("min-length")
233
+ ], { $id: "AssertionOp" });
234
+ var Assertion = Type.Object({
235
+ id: Type.String({ minLength: 1 }),
236
+ path: Type.String({ minLength: 1 }),
237
+ op: AssertionOp,
238
+ value: Type.Optional(Type.Unknown())
239
+ }, {
240
+ $id: "Assertion",
241
+ additionalProperties: false
218
242
  });
219
- var RuntimeModelName = Type.String({
220
- minLength: 1,
221
- maxLength: 200,
222
- pattern: "^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,199}$"
243
+ var SideEffectsSpec = Type.Object({
244
+ diaryEntryRequired: Type.Optional(Type.Boolean()),
245
+ diaryEntryTags: Type.Optional(Type.Array(Type.String({ minLength: 1 }))),
246
+ referencedEntries: Type.Optional(Type.Integer({ minimum: 0 }))
247
+ }, {
248
+ $id: "SideEffectsSpec",
249
+ additionalProperties: false
223
250
  });
224
- var RuntimeModelCapabilities = Type.Record(Type.String({
225
- minLength: 1,
226
- maxLength: 64
227
- }), Type.Union([
228
- Type.Boolean(),
229
- Type.Number(),
230
- Type.String({ maxLength: 256 })
231
- ]));
232
- Type.Object({
233
- id: Type.String({ format: "uuid" }),
234
- teamId: Type.Union([Type.String({ format: "uuid" }), Type.Null()]),
235
- provider: RuntimeModelProvider,
236
- model: RuntimeModelName,
237
- displayName: Type.Union([Type.String({ maxLength: 200 }), Type.Null()]),
238
- description: Type.Union([Type.String({ maxLength: 4096 }), Type.Null()]),
239
- capabilities: RuntimeModelCapabilities,
240
- isActive: Type.Boolean(),
241
- createdByAgentId: Type.Union([Type.String({ format: "uuid" }), Type.Null()]),
242
- createdByHumanId: Type.Union([Type.String({ format: "uuid" }), Type.Null()]),
243
- createdAt: Type.String({ format: "date-time" }),
244
- updatedAt: Type.String({ format: "date-time" })
251
+ var SuccessCriteria = Type.Object({
252
+ version: Type.Literal(1),
253
+ gates: Type.Optional(Type.Array(Gate)),
254
+ assertions: Type.Optional(Type.Array(Assertion)),
255
+ rubric: Type.Optional(Rubric),
256
+ minComposite: Type.Optional(Type.Number({
257
+ minimum: 0,
258
+ maximum: 1
259
+ })),
260
+ sideEffects: Type.Optional(SideEffectsSpec)
245
261
  }, {
246
- $id: "RuntimeModel",
262
+ $id: "SuccessCriteria",
263
+ additionalProperties: false
264
+ });
265
+ var VerificationResultStatus = Type.Union([
266
+ Type.Literal("pass"),
267
+ Type.Literal("fail"),
268
+ Type.Literal("skip")
269
+ ], { $id: "VerificationResultStatus" });
270
+ var VerificationResultKind = Type.Union([
271
+ Type.Literal("gate"),
272
+ Type.Literal("assertion"),
273
+ Type.Literal("rubric"),
274
+ Type.Literal("sideEffect")
275
+ ], { $id: "VerificationResultKind" });
276
+ var VerificationResult = Type.Object({
277
+ id: Type.String({ minLength: 1 }),
278
+ kind: VerificationResultKind,
279
+ status: VerificationResultStatus,
280
+ detail: Type.Optional(Type.String())
281
+ }, {
282
+ $id: "VerificationResult",
283
+ additionalProperties: false
284
+ });
285
+ var VerificationRecord = Type.Object({
286
+ inputCid: Type.String({ minLength: 1 }),
287
+ results: Type.Array(VerificationResult),
288
+ passed: Type.Boolean({ description: "True iff every verification result has status \"pass\" or \"skip\"; false when any result has status \"fail\"." })
289
+ }, {
290
+ $id: "VerificationRecord",
247
291
  additionalProperties: false
248
292
  });
249
293
  //#endregion
250
- //#region ../../libs/tasks/src/runtime-profile-context-recipes.ts
251
- var RUNTIME_PROFILE_CONTEXT_CATALOGUE = {
252
- version: 1,
253
- fragments: {
254
- "artifact-planner-v1": {
255
- binding: "prompt_prefix",
256
- content: "# Bounded artifact planner\n\n- The typed task facts, embedded bounded manifest, exact bound artifact references, registered tools, and runtime capability section are the complete contract. Do not search diaries, inspect a mounted repository, enumerate unrelated tasks or artifacts, modify a checkout, commit, branch, push, or contact GitHub.\n- Read only the exact artifact CIDs named by the task, and only when the embedded manifest does not provide enough evidence. Use the registered task-artifact tools for artifact access; never use shell or CLI wrappers to fetch artifacts, paginate, or discover them speculatively.\n- If the effective runtime exposes a local calculator or shell, use it only inside scratch for coverage accounting, budget arithmetic, and JSON validation. The runtime capability section and policy are authoritative; do not assume a static executable list.\n- Perform semantic classification and planning from supplied content and producer/consumer evidence. Do not substitute filename, directory, language, ecosystem, or repository-specific exclusion rules for evidence.\n- Write and upload exactly the requested versioned plan artifact, then reference its returned metadata through the registered submit-output tool. Do not emit a second prose or JSON representation.",
257
- slug: "artifact-planner-v1"
258
- },
259
- "accountable-delivery-v1": {
260
- binding: "prompt_prefix",
261
- content: "# Accountable delivery\n\n- Pair every commit made during this task with a signed diary entry created by the `moltnet_create_entry` custom tool. Put the returned id in a `MoltNet-Diary: <id>` commit trailer.\n- Keep commit signing enabled; do not bypass the agent git configuration.\n- Push a branch and open or update a pull request only when the task asks for it. For GitHub mutations, use the credential-bound `GH_TOKEN` command form required by the runtime kernel.\n- Keep changes, commits, and any requested pull request coherent enough to review independently.",
262
- slug: "accountable-delivery-v1"
263
- },
264
- "judgment-diary-v1": {
265
- binding: "prompt_prefix",
266
- content: "# Judgment diary discipline\n\n- For an `assess_brief`, `judge_pack`, or `pr_review` task, create a signed diary entry with the `moltnet_create_entry` custom tool before submitting the structured judgment. Capture the rationale and evidence that support the verdict.\n- Add the `judgment` tag and the active task type tag (`assess_brief`, `judge_pack`, or `pr_review`). For `judge_pack`, also add `rubric:<rubricId>` from the task facts.\n- Do not use a shell `moltnet entry` command: task provenance is injected only by the custom tool.",
267
- slug: "judgment-diary-v1"
268
- },
269
- "proactive-memory-v1": {
270
- binding: "prompt_prefix",
271
- content: "# Proactive memory use\n\n- Before non-trivial investigation, debugging, code changes, or review, check the task diary for relevant prior knowledge instead of waiting for a human to ask. Use `moltnet_diary_tags` for cheap reconnaissance, `moltnet_list_entries` when tags or task provenance are known, and `moltnet_search_entries` for semantic similarity. Do not search randomly: pass `taskFilter` for task-local or correlation-local queries, and pass `tags` / `entryTypes` for broader prior-knowledge queries using known tags such as `incident`, `decision`, or `scope:<area>`. Broaden only after constrained searches miss.\n- Before creating an `episodic` incident entry, search for similar incidents using the proposed title, root cause, error text, affected subsystem, and watch-for terms, filtered by `entryTypes: [\"episodic\", \"semantic\"]` and any known `scope:*` or task-provenance tags. If a close prior match exists, do not create an isolated duplicate: reference the prior entry in your response or diary content, update or link it when the new occurrence adds material evidence, or create a new recurrence entry only when the recurrence itself is important signal.\n- When you create a recurrence entry, include the prior matching entry id(s) in the content and explain what is new about this occurrence.",
272
- slug: "proactive-memory-v1"
273
- },
274
- "run-eval-direct-v1": {
275
- binding: "prompt_prefix",
276
- content: "# Direct evaluation run\n\nThe supplied scenario, typed task facts, injected context, and registered submit-output tool are the complete task contract. Do not search diaries, create diary entries, modify a repository, commit, branch, push, or open a pull request unless a task fact explicitly requires it. Submit the agent-authored payload in the first turn; correction turns exist only to recover a rejected or missing submission.",
277
- slug: "run-eval-direct-v1"
278
- },
279
- "task-diary-discipline-v1": {
280
- binding: "prompt_prefix",
281
- content: "# Task diary discipline\n\n- During a daemon task, create diary entries only through the `moltnet_create_entry` custom tool. It binds entries to the current task diary and injects task, type, attempt, and correlation provenance tags.\n- Do not shell out to `moltnet entry create`, `moltnet entry create-signed`, or any other `moltnet entry` subcommand from bash while a task is running. Those paths bypass the custom tool's task-tag injection, so task-filtered diary queries cannot find the entry.\n- You may add useful tags, but do not try to replace task provenance supplied by the runtime.",
282
- slug: "task-diary-discipline-v1"
283
- },
284
- "verification-and-artifacts-v1": {
285
- binding: "prompt_prefix",
286
- content: "# Verification and artifacts\n\n- Run relevant verification before submitting. When task facts include `successCriteria`, assess them honestly in the generated verification contract; a fail or skip with evidence is better than a fabricated pass.\n- The registered submit-output tool owns the exact agent submission schema and validation recovery. Use that schema; do not invent a JSON shape in prose.\n- Upload only task-relevant artifacts, and inspect each before uploading. Never upload secrets, credentials, API keys, auth tokens or headers, .env files, or personal or customer data; redact sensitive values, and prefer minimal, sanitized excerpts over whole logs, bundles, or datasets. Include artifact metadata only where the typed submit contract permits it.\n- If the task depends on prior artifacts, list and download the exact referenced artifact before judging or continuing that work.",
287
- slug: "verification-and-artifacts-v1"
288
- }
289
- },
290
- recipes: {
291
- "artifact-planner@v1": {
292
- description: "Minimal artifact-only context for bounded semantic classification and planning.",
293
- fragments: ["artifact-planner-v1"]
294
- },
295
- "run-eval-direct@v1": {
296
- description: "Minimal direct context for a short, isolated evaluation run.",
297
- fragments: ["run-eval-direct-v1"]
298
- },
299
- "standard-engineering@v1": {
300
- description: "Full opt-in operating guidance for engineering tasks that need diary research, accountable delivery, and verification discipline.",
301
- fragments: [
302
- "proactive-memory-v1",
303
- "task-diary-discipline-v1",
304
- "accountable-delivery-v1",
305
- "judgment-diary-v1",
306
- "verification-and-artifacts-v1"
307
- ]
308
- }
309
- }
310
- };
311
- function deepFreeze(value) {
312
- if (value && typeof value === "object") {
313
- for (const key of Object.keys(value)) deepFreeze(value[key]);
314
- Object.freeze(value);
315
- }
316
- return value;
317
- }
318
- deepFreeze(RUNTIME_PROFILE_CONTEXT_CATALOGUE);
319
- Object.freeze(Object.keys(RUNTIME_PROFILE_CONTEXT_CATALOGUE.recipes));
320
- //#endregion
321
- //#region ../../libs/models/src/credential-scopes.ts
322
- var CREDENTIAL_SCOPES = {
323
- AgentProfile: "agent:profile",
324
- ConnectorInvoke: "connector:invoke",
325
- CryptoSign: "crypto:sign",
326
- DiaryManage: "diary:manage",
327
- DiaryRead: "diary:read",
328
- DiaryWrite: "diary:write",
329
- HumanProfile: "human:profile",
330
- KeyManage: "key:manage",
331
- PackRead: "pack:read",
332
- PackWrite: "pack:write",
333
- RuntimeManage: "runtime:manage",
334
- RuntimeRead: "runtime:read",
335
- TaskClaim: "task:claim",
336
- TaskExecute: "task:execute",
337
- TaskManage: "task:manage",
338
- TaskRead: "task:read",
339
- TeamManage: "team:manage",
340
- TeamRead: "team:read"
341
- };
342
- var ALL_CREDENTIAL_SCOPES = Object.freeze(Object.values(CREDENTIAL_SCOPES));
343
- /**
344
- * Minimum grant for the agent daemon. Task credentials attenuate this further
345
- * to `task:execute` alone.
346
- */
347
- var AGENT_CREDENTIAL_SCOPES = [
348
- CREDENTIAL_SCOPES.AgentProfile,
349
- CREDENTIAL_SCOPES.RuntimeRead,
350
- CREDENTIAL_SCOPES.TaskRead,
351
- CREDENTIAL_SCOPES.TaskClaim,
352
- CREDENTIAL_SCOPES.TaskExecute
353
- ];
354
- Object.freeze(ALL_CREDENTIAL_SCOPES.filter((scope) => scope !== CREDENTIAL_SCOPES.HumanProfile));
355
- [
356
- CREDENTIAL_SCOPES.AgentProfile,
357
- CREDENTIAL_SCOPES.CryptoSign,
358
- CREDENTIAL_SCOPES.DiaryManage,
359
- CREDENTIAL_SCOPES.DiaryRead,
360
- CREDENTIAL_SCOPES.DiaryWrite,
361
- CREDENTIAL_SCOPES.HumanProfile,
362
- CREDENTIAL_SCOPES.PackRead,
363
- CREDENTIAL_SCOPES.PackWrite,
364
- CREDENTIAL_SCOPES.TaskExecute,
365
- CREDENTIAL_SCOPES.TaskManage,
366
- CREDENTIAL_SCOPES.TaskRead,
367
- CREDENTIAL_SCOPES.TeamManage,
368
- CREDENTIAL_SCOPES.TeamRead
369
- ].filter((scope) => scope !== CREDENTIAL_SCOPES.HumanProfile);
370
- //#endregion
371
- //#region ../../libs/models/src/preview-sign.ts
372
- function schemaRef$1(schema, id) {
373
- return Type.Unsafe(Type.Ref(id));
374
- }
375
- var PreviewSignBase64UrlSchema = Type.String({
376
- $id: "PreviewSignBase64Url",
377
- minLength: 1,
378
- maxLength: 5462,
379
- pattern: "^[A-Za-z0-9_-]+$"
380
- });
381
- var PreviewSignSha256Base64UrlSchema = Type.String({
382
- $id: "PreviewSignSha256Base64Url",
383
- minLength: 43,
384
- maxLength: 43,
385
- pattern: "^[A-Za-z0-9_-]+$"
386
- });
387
- var PreviewSignP256DerSignatureBase64UrlSchema = Type.String({
388
- $id: "PreviewSignP256DerSignatureBase64Url",
389
- minLength: 11,
390
- maxLength: 96,
391
- pattern: "^[A-Za-z0-9_-]+$"
392
- });
393
- var PreviewSignEs256PublicKeySchema = Type.Object({
394
- kty: Type.Literal(2),
395
- algorithm: Type.Literal(-7),
396
- curve: Type.Literal(1),
397
- x: schemaRef$1(PreviewSignSha256Base64UrlSchema, "PreviewSignSha256Base64Url"),
398
- y: schemaRef$1(PreviewSignSha256Base64UrlSchema, "PreviewSignSha256Base64Url")
294
+ //#region ../../libs/tasks/src/task-artifacts.ts
295
+ var TaskArtifact = Type.Object({
296
+ id: Type.String({ format: "uuid" }),
297
+ teamId: Type.String({ format: "uuid" }),
298
+ taskId: Type.String({ format: "uuid" }),
299
+ attemptN: Type.Union([Type.Integer({ minimum: 1 }), Type.Null()]),
300
+ kind: Type.String({
301
+ minLength: 1,
302
+ maxLength: 100
303
+ }),
304
+ title: Type.String({
305
+ minLength: 1,
306
+ maxLength: 255
307
+ }),
308
+ contentType: Type.String({
309
+ minLength: 1,
310
+ maxLength: 200
311
+ }),
312
+ contentEncoding: Type.Union([Type.String({
313
+ minLength: 1,
314
+ maxLength: 100
315
+ }), Type.Null()]),
316
+ sizeBytes: Type.Integer({ minimum: 0 }),
317
+ cid: Type.String({
318
+ minLength: 1,
319
+ maxLength: 100
320
+ }),
321
+ createdByAgentId: Type.Union([Type.String({ format: "uuid" }), Type.Null()]),
322
+ expiresAt: Type.Union([Type.String({ format: "date-time" }), Type.Null()]),
323
+ createdAt: Type.String({ format: "date-time" })
324
+ }, { $id: "TaskArtifact" });
325
+ Type.Object({
326
+ artifacts: Type.Array(TaskArtifact),
327
+ nextCursor: Type.Union([Type.String({ minLength: 1 }), Type.Null()])
328
+ }, { $id: "TaskArtifactList" });
329
+ Type.Object({
330
+ limit: Type.Optional(Type.Integer({
331
+ minimum: 1,
332
+ maximum: 100
333
+ })),
334
+ cursor: Type.Optional(Type.String({ minLength: 1 }))
399
335
  }, {
400
- $id: "PreviewSignEs256PublicKey",
336
+ $id: "ListTaskArtifactsQuery",
401
337
  additionalProperties: false
402
338
  });
403
- var PreviewSignEcdhEsHkdf256PublicKeySchema = Type.Object({
404
- kty: Type.Literal(2),
405
- algorithm: Type.Literal(-25),
406
- curve: Type.Literal(1),
407
- x: schemaRef$1(PreviewSignSha256Base64UrlSchema, "PreviewSignSha256Base64Url"),
408
- y: schemaRef$1(PreviewSignSha256Base64UrlSchema, "PreviewSignSha256Base64Url")
409
- }, {
410
- $id: "PreviewSignEcdhEsHkdf256PublicKey",
411
- additionalProperties: false
339
+ var HeaderSafeContentType = Type.String({
340
+ minLength: 1,
341
+ maxLength: 200,
342
+ pattern: "^[\\x21-\\x7e][\\x20-\\x7e]*$"
412
343
  });
413
- var PreviewSignEsp256PublicKeySchema = Type.Object({
414
- kty: Type.Literal(2),
415
- algorithm: Type.Literal(-9),
416
- curve: Type.Literal(1),
417
- x: schemaRef$1(PreviewSignSha256Base64UrlSchema, "PreviewSignSha256Base64Url"),
418
- y: schemaRef$1(PreviewSignSha256Base64UrlSchema, "PreviewSignSha256Base64Url")
344
+ var HeaderSafeContentEncoding = Type.String({
345
+ minLength: 1,
346
+ maxLength: 100,
347
+ pattern: "^[\\x21-\\x7e][\\x20-\\x7e]*$"
348
+ });
349
+ Type.Object({
350
+ kind: Type.String({
351
+ minLength: 1,
352
+ maxLength: 100
353
+ }),
354
+ title: Type.String({
355
+ minLength: 1,
356
+ maxLength: 255
357
+ }),
358
+ contentType: Type.Optional(HeaderSafeContentType),
359
+ contentEncoding: Type.Optional(HeaderSafeContentEncoding)
419
360
  }, {
420
- $id: "PreviewSignEsp256PublicKey",
361
+ $id: "UploadTaskArtifactQuery",
421
362
  additionalProperties: false
422
363
  });
423
- var PreviewSignArkgSeedPublicKeySchema = Type.Object({
424
- kty: Type.Literal(-65537),
425
- algorithm: Type.Literal(-65700),
426
- derivedAlgorithm: Type.Literal(-9),
427
- blindingKey: schemaRef$1(PreviewSignEs256PublicKeySchema, "PreviewSignEs256PublicKey"),
428
- kemKey: schemaRef$1(PreviewSignEcdhEsHkdf256PublicKeySchema, "PreviewSignEcdhEsHkdf256PublicKey")
429
- }, {
430
- $id: "PreviewSignArkgSeedPublicKey",
364
+ Type.String({
365
+ $id: "TaskArtifactContent",
366
+ description: "Task artifact content stream.",
367
+ format: "binary"
368
+ });
369
+ Type.Object({ taskId: Type.String({ format: "uuid" }) }, {
370
+ $id: "TaskArtifactTaskParams",
431
371
  additionalProperties: false
432
372
  });
433
- var PreviewSignPublicMaterialSchema = Type.Object({
434
- version: Type.Literal(1),
435
- outerCredentialId: schemaRef$1(PreviewSignBase64UrlSchema, "PreviewSignBase64Url"),
436
- outerPublicKey: schemaRef$1(PreviewSignEs256PublicKeySchema, "PreviewSignEs256PublicKey"),
437
- previewKeyHandle: schemaRef$1(PreviewSignBase64UrlSchema, "PreviewSignBase64Url"),
438
- seedPublicKey: schemaRef$1(PreviewSignArkgSeedPublicKeySchema, "PreviewSignArkgSeedPublicKey")
373
+ Type.Object({
374
+ taskId: Type.String({ format: "uuid" }),
375
+ attemptN: Type.Integer({ minimum: 1 })
439
376
  }, {
440
- $id: "PreviewSignPublicMaterial",
377
+ $id: "TaskArtifactAttemptParams",
441
378
  additionalProperties: false
442
379
  });
443
- var PreviewSignChallengeSchema = Type.Object({
444
- verificationMethod: Type.Literal("human-hardware-previewsign"),
445
- version: Type.Literal(1),
446
- envelope: schemaRef$1(PreviewSignBase64UrlSchema, "PreviewSignBase64Url"),
447
- digest: schemaRef$1(PreviewSignSha256Base64UrlSchema, "PreviewSignSha256Base64Url"),
448
- additionalArguments: schemaRef$1(PreviewSignBase64UrlSchema, "PreviewSignBase64Url"),
449
- outerCredentialId: schemaRef$1(PreviewSignBase64UrlSchema, "PreviewSignBase64Url"),
450
- outerPublicKey: schemaRef$1(PreviewSignEs256PublicKeySchema, "PreviewSignEs256PublicKey"),
451
- previewKeyHandle: schemaRef$1(PreviewSignBase64UrlSchema, "PreviewSignBase64Url")
380
+ Type.Object({
381
+ taskId: Type.String({ format: "uuid" }),
382
+ attemptN: Type.Integer({ minimum: 1 }),
383
+ cid: Type.String({
384
+ minLength: 1,
385
+ maxLength: 100
386
+ })
452
387
  }, {
453
- $id: "PreviewSignChallenge",
388
+ $id: "TaskArtifactContentParams",
454
389
  additionalProperties: false
455
390
  });
456
- var PreviewSignChallengeValueSchema = Type.Object({
457
- verificationMethod: Type.Literal("human-hardware-previewsign"),
458
- value: schemaRef$1(PreviewSignChallengeSchema, "PreviewSignChallenge")
391
+ Type.Object({
392
+ contentType: Type.Optional(HeaderSafeContentType),
393
+ contentEncoding: Type.Optional(HeaderSafeContentEncoding)
459
394
  }, {
460
- $id: "PreviewSignChallengeValue",
395
+ $id: "StageTaskArtifactQuery",
461
396
  additionalProperties: false
462
397
  });
463
- var PreviewSignChallengeOperationSchema = Type.Union([Type.Literal("credential-registration"), Type.Literal("signing-request")], { $id: "PreviewSignChallengeOperation" });
464
- var PreviewSignReceiptSchema = Type.Object({
465
- version: Type.Literal(1),
466
- signature: schemaRef$1(PreviewSignP256DerSignatureBase64UrlSchema, "PreviewSignP256DerSignatureBase64Url")
398
+ Type.Object({
399
+ cid: Type.String({
400
+ minLength: 1,
401
+ maxLength: 100
402
+ }),
403
+ sizeBytes: Type.Integer({ minimum: 0 }),
404
+ contentType: Type.String({
405
+ minLength: 1,
406
+ maxLength: 200
407
+ })
408
+ }, { $id: "StagedTaskArtifact" });
409
+ Type.Object({
410
+ taskId: Type.String({ format: "uuid" }),
411
+ cid: Type.String({
412
+ minLength: 1,
413
+ maxLength: 100
414
+ })
467
415
  }, {
468
- $id: "PreviewSignReceipt",
416
+ $id: "TaskArtifactTaskContentParams",
469
417
  additionalProperties: false
470
418
  });
471
- var PreviewSignReceiptValueSchema = Type.Object({
472
- verificationMethod: Type.Literal("human-hardware-previewsign"),
473
- value: schemaRef$1(PreviewSignReceiptSchema, "PreviewSignReceipt")
419
+ //#endregion
420
+ //#region ../../libs/tasks/src/task-types/assess-brief.ts
421
+ /**
422
+ * `assess_brief` — independently evaluate a fulfilled brief.
423
+ *
424
+ * output_kind: judgment
425
+ * criteria: required (`successCriteria.rubric` — same envelope as
426
+ * `judge_pack`)
427
+ * references: required (must reference the target `fulfill_brief` task)
428
+ *
429
+ * The assessor is a different agent from the producer (enforced by the
430
+ * server / runtime at claim time — not in the wire schema).
431
+ *
432
+ * The rubric in `successCriteria` IS the job spec — the assessor applies
433
+ * it to the target task's output and emits per-criterion scores. Other
434
+ * sections (`assertions`, `gates`, `sideEffects`) MAY be present and are
435
+ * evaluated against the *assessor's output*.
436
+ */
437
+ var ASSESS_BRIEF_TYPE = "assess_brief";
438
+ var AssessBriefInput = Type.Object({
439
+ targetTaskId: Type.String({ format: "uuid" }),
440
+ successCriteria: SuccessCriteria
474
441
  }, {
475
- $id: "PreviewSignReceiptValue",
442
+ $id: "AssessBriefInput",
443
+ additionalProperties: false
444
+ });
445
+ /** One score line. */
446
+ var AssessBriefScore = Type.Object({
447
+ criterionId: Type.String({ minLength: 1 }),
448
+ score: Type.Number({
449
+ minimum: 0,
450
+ maximum: 1
451
+ }),
452
+ rationale: Type.Optional(Type.String()),
453
+ evidence: Type.Optional(Type.Object({
454
+ commitsVerified: Type.Number(),
455
+ commitsTotal: Type.Number(),
456
+ signatureFailures: Type.Array(Type.String())
457
+ }, { additionalProperties: false }))
458
+ }, {
459
+ $id: "AssessBriefScore",
460
+ additionalProperties: false
461
+ });
462
+ var AssessBriefOutput = Type.Object({
463
+ scores: Type.Array(AssessBriefScore, { minItems: 1 }),
464
+ composite: Type.Number({
465
+ minimum: 0,
466
+ maximum: 1
467
+ }),
468
+ verdict: Type.String({ minLength: 1 }),
469
+ judgeModel: Type.Optional(Type.String())
470
+ }, {
471
+ $id: "AssessBriefOutput",
476
472
  additionalProperties: false
477
473
  });
478
- var previewSignSchemaContext = {
479
- PreviewSignBase64Url: PreviewSignBase64UrlSchema,
480
- PreviewSignSha256Base64Url: PreviewSignSha256Base64UrlSchema,
481
- PreviewSignP256DerSignatureBase64Url: PreviewSignP256DerSignatureBase64UrlSchema,
482
- PreviewSignEs256PublicKey: PreviewSignEs256PublicKeySchema,
483
- PreviewSignEcdhEsHkdf256PublicKey: PreviewSignEcdhEsHkdf256PublicKeySchema,
484
- PreviewSignEsp256PublicKey: PreviewSignEsp256PublicKeySchema,
485
- PreviewSignArkgSeedPublicKey: PreviewSignArkgSeedPublicKeySchema,
486
- PreviewSignPublicMaterial: PreviewSignPublicMaterialSchema,
487
- PreviewSignChallenge: PreviewSignChallengeSchema,
488
- PreviewSignChallengeValue: PreviewSignChallengeValueSchema,
489
- PreviewSignChallengeOperation: PreviewSignChallengeOperationSchema,
490
- PreviewSignReceipt: PreviewSignReceiptSchema,
491
- PreviewSignReceiptValue: PreviewSignReceiptValueSchema
492
- };
493
- //#endregion
494
- //#region ../../libs/models/src/verification-method.ts
495
474
  /**
496
- * Persisted and wire-level signing verification method identifiers.
475
+ * Async preflight (#1096):
476
+ * - `targetTaskId` resolves to a real task the caller can see.
477
+ * - The target is a `fulfill_brief` (you cannot grade an arbitrary
478
+ * task type as if it were a brief fulfillment).
479
+ * - Unless readiness checks are explicitly deferred, the target is
480
+ * `completed` with an accepted attempt — grading an in-flight or
481
+ * failed task would either race or grade nothing.
497
482
  *
498
- * This vocabulary is append-only. Never rename, remove, or change an existing
499
- * value: PostgreSQL rows, workflow inputs, and API clients persist these exact
500
- * strings. Future signing methods must add a new property and value.
483
+ * Agent-distinctness ("assessor ≠ producer") is a runtime / auth-
484
+ * layer concern and intentionally NOT checked here. It belongs in
485
+ * an auth-aware claim-time check.
501
486
  */
502
- var VERIFICATION_METHOD = {
503
- AgentEd25519: "agent-ed25519",
504
- HumanHardwarePreviewSign: "human-hardware-previewsign"
505
- };
506
- VERIFICATION_METHOD.AgentEd25519, VERIFICATION_METHOD.HumanHardwarePreviewSign;
487
+ async function validateAssessBriefInputAsync(input, ctx) {
488
+ const { targetTaskId } = input;
489
+ const errors = [];
490
+ const target = await ctx.resolveTask(targetTaskId);
491
+ if (!target) {
492
+ errors.push({
493
+ field: "targetTaskId",
494
+ message: `targetTaskId ${targetTaskId} does not resolve to a task you can read`
495
+ });
496
+ return errors;
497
+ }
498
+ if (target.taskType !== "fulfill_brief") errors.push({
499
+ field: "targetTaskId",
500
+ message: `targetTaskId ${targetTaskId} is a ${target.taskType}, not a fulfill_brief`
501
+ });
502
+ if (!ctx.deferReadinessChecks && (target.status !== "completed" || target.acceptedAttemptN === null)) errors.push({
503
+ field: "targetTaskId",
504
+ message: `targetTaskId ${targetTaskId} is not completed with an accepted attempt (status=${target.status}, acceptedAttemptN=${target.acceptedAttemptN})`
505
+ });
506
+ return errors;
507
+ }
507
508
  //#endregion
508
- //#region ../../libs/models/src/schemas.ts
509
- var UuidSchema = Type.String({
510
- format: "uuid",
511
- description: "UUID v4 identifier"
512
- });
513
- var TimestampSchema = Type.String({
514
- format: "date-time",
515
- description: "ISO 8601 timestamp"
516
- });
517
- var verificationMethodLiterals = [Type.Literal(VERIFICATION_METHOD.AgentEd25519), Type.Literal(VERIFICATION_METHOD.HumanHardwarePreviewSign)];
518
- Type.Union(verificationMethodLiterals, { description: "Stable signing verification method identifier" });
519
- var visibilityLiterals = [
520
- Type.Literal("private"),
521
- Type.Literal("moltnet"),
522
- Type.Literal("public")
523
- ];
524
- Type.Union(visibilityLiterals, { description: "Entry visibility level" });
525
- var ENTRY_TYPE_VALUES = [
526
- "episodic",
527
- "semantic",
528
- "procedural",
529
- "reflection"
530
- ];
531
- var entryTypeLiterals = [
509
+ //#region ../../libs/tasks/src/task-types/curate-pack.ts
510
+ /**
511
+ * `curate_pack` — select and rank diary entries into a context pack.
512
+ *
513
+ * output_kind: artifact
514
+ * criteria: not required (rubric-less curation recipe)
515
+ * references: optional (e.g. a prior rendered pack being re-curated)
516
+ *
517
+ * This is step 1 of the three-session attribution loop (#875). The agent
518
+ * runs a structured exploration over a diary — tag inventory, hybrid
519
+ * search, type/tag narrowing — and emits a ranked entry list via
520
+ * `moltnet_pack_create`. The prompt is deterministic given the input
521
+ * (no operator interaction), so two runs with the same input should
522
+ * converge on similar packs.
523
+ *
524
+ * Related: `render_pack`, `judge_pack`.
525
+ */
526
+ var CURATE_PACK_TYPE = "curate_pack";
527
+ var EntryTypeFilter = Type.Union([
532
528
  Type.Literal("episodic"),
533
529
  Type.Literal("semantic"),
534
530
  Type.Literal("procedural"),
535
531
  Type.Literal("reflection")
536
- ];
537
- var EntryTypeSchema = Type.Union(entryTypeLiterals, { description: "Entry memory type" });
538
- /** Regex fragment matching a single entry type value. */
539
- var ENTRY_TYPE_PATTERN = `(${ENTRY_TYPE_VALUES.join("|")})`;
540
- `${ENTRY_TYPE_PATTERN}${ENTRY_TYPE_PATTERN}`, ENTRY_TYPE_VALUES.length - 1;
541
- var PublicKeySchema = Type.String({
542
- pattern: "^ed25519:[A-Za-z0-9+/=]+$",
543
- description: "Ed25519 public key with prefix"
544
- });
545
- var FingerprintSchema = Type.String({
546
- pattern: "^[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}$",
547
- description: "Key fingerprint (A1B2-C3D4-E5F6-G7H8)"
548
- });
549
- Type.Object({
550
- title: Type.Optional(Type.String({ maxLength: 255 })),
551
- content: Type.String({
552
- minLength: 1,
553
- maxLength: 1e5
554
- }),
555
- tags: Type.Optional(Type.Array(Type.String({ maxLength: 128 }), { maxItems: 20 }))
532
+ ]);
533
+ var CuratePackInput = Type.Object({
534
+ diaryId: Type.String({ format: "uuid" }),
535
+ taskPrompt: Type.String({ minLength: 1 }),
536
+ entryTypes: Type.Optional(Type.Array(EntryTypeFilter, { minItems: 1 })),
537
+ tagFilters: Type.Optional(Type.Object({
538
+ include: Type.Optional(Type.Array(Type.String())),
539
+ exclude: Type.Optional(Type.Array(Type.String())),
540
+ prefix: Type.Optional(Type.String())
541
+ }, { additionalProperties: false })),
542
+ tokenBudget: Type.Optional(Type.Number({ minimum: 500 })),
543
+ recipe: Type.Optional(Type.Union([Type.Literal("topic-focused-v1"), Type.Literal("scope-inventory-v1")])),
544
+ successCriteria: Type.Optional(SuccessCriteria)
545
+ }, {
546
+ $id: "CuratePackInput",
547
+ additionalProperties: false
556
548
  });
557
- Type.Object({
558
- title: Type.Optional(Type.String({ maxLength: 255 })),
559
- content: Type.Optional(Type.String({
560
- minLength: 1,
561
- maxLength: 1e5
562
- })),
563
- tags: Type.Optional(Type.Array(Type.String({ maxLength: 128 }), { maxItems: 20 }))
549
+ /**
550
+ * Index of the curated pack plus the reasoning trace. The pack itself
551
+ * lives in the database (created via `moltnet_pack_create`); this output
552
+ * is the receipt.
553
+ */
554
+ var CuratePackOutput = Type.Object({
555
+ packId: Type.String({ format: "uuid" }),
556
+ packCid: Type.String({ minLength: 1 }),
557
+ entries: Type.Array(Type.Object({
558
+ entryId: Type.String({ format: "uuid" }),
559
+ rank: Type.Number({ minimum: 1 }),
560
+ rationale: Type.String({ minLength: 1 })
561
+ }, { additionalProperties: false }), { minItems: 1 }),
562
+ recipeParams: Type.Record(Type.String(), Type.Unknown()),
563
+ checkpoints: Type.Optional(Type.Array(Type.Object({
564
+ phase: Type.String({ minLength: 1 }),
565
+ candidateIds: Type.Array(Type.String({ format: "uuid" })),
566
+ droppedIds: Type.Optional(Type.Array(Type.String({ format: "uuid" }))),
567
+ notes: Type.String({ minLength: 1 })
568
+ }, { additionalProperties: false }))),
569
+ summary: Type.String({ minLength: 1 }),
570
+ verification: Type.Optional(VerificationRecord)
571
+ }, {
572
+ $id: "CuratePackOutput",
573
+ additionalProperties: false
564
574
  });
565
- Type.Object({
566
- query: Type.Optional(Type.String({
567
- minLength: 1,
568
- maxLength: 500
569
- })),
570
- tags: Type.Optional(Type.Array(Type.String({ maxLength: 128 }), {
571
- minItems: 1,
572
- maxItems: 20,
573
- description: "Filter: entry must have ALL specified tags"
574
- })),
575
- limit: Type.Optional(Type.Number({
575
+ //#endregion
576
+ //#region ../../libs/runtime-profiles/src/context.ts
577
+ /**
578
+ * How an executor delivers a context entry to its underlying LLM.
579
+ * V1 bindings only; Tier-2 (reference_file, mcp_resource, imported_file,
580
+ * tool_response_seed, additional_context_hook) ship in a later slice.
581
+ */
582
+ var CONTEXT_BINDINGS = [
583
+ "skill",
584
+ "context_inline",
585
+ "prompt_prefix",
586
+ "user_inline"
587
+ ];
588
+ /** Maximum UTF-16 code units accepted in one ContextRef content field. */
589
+ var CONTEXT_REF_MAX_CONTENT_LENGTH = 65536;
590
+ var ContextBinding = Type.Unsafe(Type.Union(CONTEXT_BINDINGS.map((binding) => Type.Literal(binding)), { $id: "ContextBinding" }));
591
+ /**
592
+ * One context entry. Bytes are inlined: the proposer chose them, and the
593
+ * task's `inputCid` already pins the entire input — including
594
+ * `context[]` — so we don't need a separate per-entry hash, fetcher, or
595
+ * flagged-content gate. Tasks reference rendered packs (or any other
596
+ * external content) by copying their bytes into `content` at task
597
+ * creation time.
598
+ *
599
+ * - `slug` — short identifier the daemon uses to disambiguate
600
+ * entries. For `skill` binding it becomes the directory
601
+ * name under the runtime's skill discovery path. Must be
602
+ * kebab-case-safe (alphanumeric + dashes/underscores).
603
+ * - `binding` — how the bytes are delivered to the LLM (see above).
604
+ * - `content` — UTF-8 text. Capped at 65,536 UTF-16 code units per
605
+ * entry; total per-task context bytes are bounded by the
606
+ * soft `maxItems` cap and per-binding daemon limits.
607
+ * Raised from 32 KiB in 2026-05 — protocol-heavy operator
608
+ * skills (e.g. `.claude/skills/legreffier/SKILL.md`) ship
609
+ * at ~35 KiB inline, and the original cap was sized for
610
+ * short example skills, not the kind of skill the eval
611
+ * substrate is dogfooded on (#943, #823).
612
+ */
613
+ var ContextRef = Type.Object({
614
+ slug: Type.String({
615
+ minLength: 1,
616
+ maxLength: 64,
617
+ pattern: "^[a-zA-Z0-9_-]+$"
618
+ }),
619
+ binding: ContextBinding,
620
+ content: Type.String({
621
+ minLength: 1,
622
+ maxLength: CONTEXT_REF_MAX_CONTENT_LENGTH
623
+ })
624
+ }, {
625
+ $id: "ContextRef",
626
+ additionalProperties: false
627
+ });
628
+ /** Reusable input fragment for any task type. Soft cap at 5 items. */
629
+ var TaskContext = Type.Array(ContextRef, {
630
+ $id: "TaskContext",
631
+ maxItems: 5
632
+ });
633
+ //#endregion
634
+ //#region ../../libs/runtime-profiles/src/runtime-models.ts
635
+ /**
636
+ * Runtime model catalog: a list of supported provider/model couples that
637
+ * MoltNet daemons can target. Backed by the `runtime_models` table.
638
+ *
639
+ * Scope is intrinsic to the row:
640
+ * - `teamId == null` => global entry (MoltNet-seeded, read-only to most callers)
641
+ * - `teamId != null` => team-owned custom entry
642
+ *
643
+ * The REST API exposes a single shape regardless of scope; the team header
644
+ * gates which rows are returned.
645
+ */
646
+ var RuntimeModelProvider = Type.String({
647
+ minLength: 1,
648
+ maxLength: 100,
649
+ pattern: "^[a-zA-Z0-9][a-zA-Z0-9._-]{0,99}$"
650
+ });
651
+ var RuntimeModelName = Type.String({
652
+ minLength: 1,
653
+ maxLength: 200,
654
+ pattern: "^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,199}$"
655
+ });
656
+ var RuntimeModelCapabilities = Type.Record(Type.String({
657
+ minLength: 1,
658
+ maxLength: 64
659
+ }), Type.Union([
660
+ Type.Boolean(),
661
+ Type.Number(),
662
+ Type.String({ maxLength: 256 })
663
+ ]));
664
+ Type.Object({
665
+ id: Type.String({ format: "uuid" }),
666
+ teamId: Type.Union([Type.String({ format: "uuid" }), Type.Null()]),
667
+ provider: RuntimeModelProvider,
668
+ model: RuntimeModelName,
669
+ displayName: Type.Union([Type.String({ maxLength: 200 }), Type.Null()]),
670
+ description: Type.Union([Type.String({ maxLength: 4096 }), Type.Null()]),
671
+ capabilities: RuntimeModelCapabilities,
672
+ isActive: Type.Boolean(),
673
+ createdByAgentId: Type.Union([Type.String({ format: "uuid" }), Type.Null()]),
674
+ createdByHumanId: Type.Union([Type.String({ format: "uuid" }), Type.Null()]),
675
+ createdAt: Type.String({ format: "date-time" }),
676
+ updatedAt: Type.String({ format: "date-time" })
677
+ }, {
678
+ $id: "RuntimeModel",
679
+ additionalProperties: false
680
+ });
681
+ //#endregion
682
+ //#region ../../libs/runtime-profiles/src/runtime-profile-context-recipes.ts
683
+ var RUNTIME_PROFILE_CONTEXT_CATALOGUE = {
684
+ version: 1,
685
+ fragments: {
686
+ "artifact-planner-v1": {
687
+ binding: "prompt_prefix",
688
+ content: "# Bounded artifact planner\n\n- The typed task facts, embedded bounded manifest, exact bound artifact references, registered tools, and runtime capability section are the complete contract. Do not search diaries, inspect a mounted repository, enumerate unrelated tasks or artifacts, modify a checkout, commit, branch, push, or contact GitHub.\n- Read only the exact artifact CIDs named by the task, and only when the embedded manifest does not provide enough evidence. Use the registered task-artifact tools for artifact access; never use shell or CLI wrappers to fetch artifacts, paginate, or discover them speculatively.\n- If the effective runtime exposes a local calculator or shell, use it only inside scratch for coverage accounting, budget arithmetic, and JSON validation. The runtime capability section and policy are authoritative; do not assume a static executable list.\n- Perform semantic classification and planning from supplied content and producer/consumer evidence. Do not substitute filename, directory, language, ecosystem, or repository-specific exclusion rules for evidence.\n- Write and upload exactly the requested versioned plan artifact, then reference its returned metadata through the registered submit-output tool. Do not emit a second prose or JSON representation.",
689
+ slug: "artifact-planner-v1"
690
+ },
691
+ "accountable-delivery-v1": {
692
+ binding: "prompt_prefix",
693
+ content: "# Accountable delivery\n\n- Pair every commit made during this task with a task-provenance diary entry created by the `moltnet_create_entry` custom tool. Put the returned id in a `MoltNet-Diary: <id>` commit trailer. The tool does not currently promise a content signature; never describe an entry as signed unless the active runtime exposes and verifies a signing capability.\n- Do not disable commit signing when the active runtime provides it. A host-authenticated guest has no injected signing key, so do not recover one from host configuration or claim an unsigned commit is signed.\n- Push a branch and open or update a pull request only when the task asks for it. Use a host-brokered GitHub placeholder only when the runtime kernel declares one; if no GitHub credential is active, the authenticated operation is unavailable.\n- Keep changes, commits, and any requested pull request coherent enough to review independently.",
694
+ slug: "accountable-delivery-v1"
695
+ },
696
+ "judgment-diary-v1": {
697
+ binding: "prompt_prefix",
698
+ content: "# Judgment diary discipline\n\n- For an `assess_brief`, `judge_pack`, or `pr_review` task, create a diary entry with the `moltnet_create_entry` custom tool before submitting the structured judgment. Capture the rationale and evidence that support the verdict. Do not claim a content signature unless the active runtime exposes and verifies a signing capability.\n- Add the `judgment` tag and the active task type tag (`assess_brief`, `judge_pack`, or `pr_review`). For `judge_pack`, also add `rubric:<rubricId>` from the task facts.\n- Do not use a shell `moltnet entry` command: task provenance is injected only by the custom tool.",
699
+ slug: "judgment-diary-v1"
700
+ },
701
+ "proactive-memory-v1": {
702
+ binding: "prompt_prefix",
703
+ content: "# Proactive memory use\n\n- Before non-trivial investigation, debugging, code changes, or review, check the task diary for relevant prior knowledge instead of waiting for a human to ask. Use `moltnet_diary_tags` for cheap reconnaissance, `moltnet_list_entries` when tags or task provenance are known, and `moltnet_search_entries` for semantic similarity. Do not search randomly: pass `taskFilter` for task-local or correlation-local queries, and pass `tags` / `entryTypes` for broader prior-knowledge queries using known tags such as `incident`, `decision`, or `scope:<area>`. Broaden only after constrained searches miss.\n- Before creating an `episodic` incident entry, search for similar incidents using the proposed title, root cause, error text, affected subsystem, and watch-for terms, filtered by `entryTypes: [\"episodic\", \"semantic\"]` and any known `scope:*` or task-provenance tags. If a close prior match exists, do not create an isolated duplicate: reference the prior entry in your response or diary content, update or link it when the new occurrence adds material evidence, or create a new recurrence entry only when the recurrence itself is important signal.\n- When you create a recurrence entry, include the prior matching entry id(s) in the content and explain what is new about this occurrence.",
704
+ slug: "proactive-memory-v1"
705
+ },
706
+ "run-eval-direct-v1": {
707
+ binding: "prompt_prefix",
708
+ content: "# Direct evaluation run\n\nThe supplied scenario, typed task facts, injected context, and registered submit-output tool are the complete task contract. Do not search diaries, create diary entries, modify a repository, commit, branch, push, or open a pull request unless a task fact explicitly requires it. Submit the agent-authored payload in the first turn; correction turns exist only to recover a rejected or missing submission.",
709
+ slug: "run-eval-direct-v1"
710
+ },
711
+ "task-diary-discipline-v1": {
712
+ binding: "prompt_prefix",
713
+ content: "# Task diary discipline\n\n- During a daemon task, create diary entries only through the `moltnet_create_entry` custom tool. It binds entries to the current task diary and injects task, type, attempt, and correlation provenance tags.\n- Do not shell out to `moltnet entry create`, `moltnet entry create-signed`, or any other `moltnet entry` subcommand from bash while a task is running. Those paths bypass the custom tool's task-tag injection, so task-filtered diary queries cannot find the entry.\n- You may add useful tags, but do not try to replace task provenance supplied by the runtime.",
714
+ slug: "task-diary-discipline-v1"
715
+ },
716
+ "verification-and-artifacts-v1": {
717
+ binding: "prompt_prefix",
718
+ content: "# Verification and artifacts\n\n- Run relevant verification before submitting. When task facts include `successCriteria`, assess them honestly in the generated verification contract; a fail or skip with evidence is better than a fabricated pass.\n- The registered submit-output tool owns the exact agent submission schema and validation recovery. Use that schema; do not invent a JSON shape in prose.\n- Upload only task-relevant artifacts, and inspect each before uploading. Never upload secrets, credentials, API keys, auth tokens or headers, .env files, or personal or customer data; redact sensitive values, and prefer minimal, sanitized excerpts over whole logs, bundles, or datasets. Include artifact metadata only where the typed submit contract permits it.\n- If the task depends on prior artifacts, list and download the exact referenced artifact before judging or continuing that work.",
719
+ slug: "verification-and-artifacts-v1"
720
+ }
721
+ },
722
+ recipes: {
723
+ "artifact-planner@v1": {
724
+ description: "Minimal artifact-only context for bounded semantic classification and planning.",
725
+ fragments: ["artifact-planner-v1"]
726
+ },
727
+ "run-eval-direct@v1": {
728
+ description: "Minimal direct context for a short, isolated evaluation run.",
729
+ fragments: ["run-eval-direct-v1"]
730
+ },
731
+ "standard-engineering@v1": {
732
+ description: "Full opt-in operating guidance for engineering tasks that need diary research, accountable delivery, and verification discipline.",
733
+ fragments: [
734
+ "proactive-memory-v1",
735
+ "task-diary-discipline-v1",
736
+ "accountable-delivery-v1",
737
+ "judgment-diary-v1",
738
+ "verification-and-artifacts-v1"
739
+ ]
740
+ }
741
+ }
742
+ };
743
+ function deepFreeze(value) {
744
+ if (value && typeof value === "object") {
745
+ for (const key of Object.keys(value)) deepFreeze(value[key]);
746
+ Object.freeze(value);
747
+ }
748
+ return value;
749
+ }
750
+ deepFreeze(RUNTIME_PROFILE_CONTEXT_CATALOGUE);
751
+ Object.freeze(Object.keys(RUNTIME_PROFILE_CONTEXT_CATALOGUE.recipes));
752
+ //#endregion
753
+ //#region ../../libs/models/src/credential-scopes.ts
754
+ var CREDENTIAL_SCOPES = {
755
+ AgentProfile: "agent:profile",
756
+ ConnectorInvoke: "connector:invoke",
757
+ CryptoSign: "crypto:sign",
758
+ DiaryManage: "diary:manage",
759
+ DiaryRead: "diary:read",
760
+ DiaryWrite: "diary:write",
761
+ HumanProfile: "human:profile",
762
+ KeyManage: "key:manage",
763
+ PackRead: "pack:read",
764
+ PackWrite: "pack:write",
765
+ RuntimeManage: "runtime:manage",
766
+ RuntimeRead: "runtime:read",
767
+ TaskClaim: "task:claim",
768
+ TaskExecute: "task:execute",
769
+ TaskManage: "task:manage",
770
+ TaskRead: "task:read",
771
+ TeamManage: "team:manage",
772
+ TeamRead: "team:read"
773
+ };
774
+ var ALL_CREDENTIAL_SCOPES = Object.freeze(Object.values(CREDENTIAL_SCOPES));
775
+ /**
776
+ * Minimum grant for the agent daemon. Task credentials attenuate this further
777
+ * to `task:execute` alone.
778
+ */
779
+ var AGENT_CREDENTIAL_SCOPES = [
780
+ CREDENTIAL_SCOPES.AgentProfile,
781
+ CREDENTIAL_SCOPES.RuntimeRead,
782
+ CREDENTIAL_SCOPES.TaskRead,
783
+ CREDENTIAL_SCOPES.TaskClaim,
784
+ CREDENTIAL_SCOPES.TaskExecute
785
+ ];
786
+ Object.freeze(ALL_CREDENTIAL_SCOPES.filter((scope) => scope !== CREDENTIAL_SCOPES.HumanProfile));
787
+ [
788
+ CREDENTIAL_SCOPES.AgentProfile,
789
+ CREDENTIAL_SCOPES.CryptoSign,
790
+ CREDENTIAL_SCOPES.DiaryManage,
791
+ CREDENTIAL_SCOPES.DiaryRead,
792
+ CREDENTIAL_SCOPES.DiaryWrite,
793
+ CREDENTIAL_SCOPES.HumanProfile,
794
+ CREDENTIAL_SCOPES.PackRead,
795
+ CREDENTIAL_SCOPES.PackWrite,
796
+ CREDENTIAL_SCOPES.TaskExecute,
797
+ CREDENTIAL_SCOPES.TaskManage,
798
+ CREDENTIAL_SCOPES.TaskRead,
799
+ CREDENTIAL_SCOPES.TeamManage,
800
+ CREDENTIAL_SCOPES.TeamRead
801
+ ].filter((scope) => scope !== CREDENTIAL_SCOPES.HumanProfile);
802
+ //#endregion
803
+ //#region ../../libs/models/src/preview-sign.ts
804
+ function schemaRef$1(schema, id) {
805
+ return Type.Unsafe(Type.Ref(id));
806
+ }
807
+ var PreviewSignBase64UrlSchema = Type.String({
808
+ $id: "PreviewSignBase64Url",
809
+ minLength: 1,
810
+ maxLength: 5462,
811
+ pattern: "^[A-Za-z0-9_-]+$"
812
+ });
813
+ var PreviewSignSha256Base64UrlSchema = Type.String({
814
+ $id: "PreviewSignSha256Base64Url",
815
+ minLength: 43,
816
+ maxLength: 43,
817
+ pattern: "^[A-Za-z0-9_-]+$"
818
+ });
819
+ var PreviewSignP256DerSignatureBase64UrlSchema = Type.String({
820
+ $id: "PreviewSignP256DerSignatureBase64Url",
821
+ minLength: 11,
822
+ maxLength: 96,
823
+ pattern: "^[A-Za-z0-9_-]+$"
824
+ });
825
+ var PreviewSignEs256PublicKeySchema = Type.Object({
826
+ kty: Type.Literal(2),
827
+ algorithm: Type.Literal(-7),
828
+ curve: Type.Literal(1),
829
+ x: schemaRef$1(PreviewSignSha256Base64UrlSchema, "PreviewSignSha256Base64Url"),
830
+ y: schemaRef$1(PreviewSignSha256Base64UrlSchema, "PreviewSignSha256Base64Url")
831
+ }, {
832
+ $id: "PreviewSignEs256PublicKey",
833
+ additionalProperties: false
834
+ });
835
+ var PreviewSignEcdhEsHkdf256PublicKeySchema = Type.Object({
836
+ kty: Type.Literal(2),
837
+ algorithm: Type.Literal(-25),
838
+ curve: Type.Literal(1),
839
+ x: schemaRef$1(PreviewSignSha256Base64UrlSchema, "PreviewSignSha256Base64Url"),
840
+ y: schemaRef$1(PreviewSignSha256Base64UrlSchema, "PreviewSignSha256Base64Url")
841
+ }, {
842
+ $id: "PreviewSignEcdhEsHkdf256PublicKey",
843
+ additionalProperties: false
844
+ });
845
+ var PreviewSignEsp256PublicKeySchema = Type.Object({
846
+ kty: Type.Literal(2),
847
+ algorithm: Type.Literal(-9),
848
+ curve: Type.Literal(1),
849
+ x: schemaRef$1(PreviewSignSha256Base64UrlSchema, "PreviewSignSha256Base64Url"),
850
+ y: schemaRef$1(PreviewSignSha256Base64UrlSchema, "PreviewSignSha256Base64Url")
851
+ }, {
852
+ $id: "PreviewSignEsp256PublicKey",
853
+ additionalProperties: false
854
+ });
855
+ var PreviewSignArkgSeedPublicKeySchema = Type.Object({
856
+ kty: Type.Literal(-65537),
857
+ algorithm: Type.Literal(-65700),
858
+ derivedAlgorithm: Type.Literal(-9),
859
+ blindingKey: schemaRef$1(PreviewSignEs256PublicKeySchema, "PreviewSignEs256PublicKey"),
860
+ kemKey: schemaRef$1(PreviewSignEcdhEsHkdf256PublicKeySchema, "PreviewSignEcdhEsHkdf256PublicKey")
861
+ }, {
862
+ $id: "PreviewSignArkgSeedPublicKey",
863
+ additionalProperties: false
864
+ });
865
+ var PreviewSignPublicMaterialSchema = Type.Object({
866
+ version: Type.Literal(1),
867
+ outerCredentialId: schemaRef$1(PreviewSignBase64UrlSchema, "PreviewSignBase64Url"),
868
+ outerPublicKey: schemaRef$1(PreviewSignEs256PublicKeySchema, "PreviewSignEs256PublicKey"),
869
+ previewKeyHandle: schemaRef$1(PreviewSignBase64UrlSchema, "PreviewSignBase64Url"),
870
+ seedPublicKey: schemaRef$1(PreviewSignArkgSeedPublicKeySchema, "PreviewSignArkgSeedPublicKey")
871
+ }, {
872
+ $id: "PreviewSignPublicMaterial",
873
+ additionalProperties: false
874
+ });
875
+ var PreviewSignChallengeSchema = Type.Object({
876
+ verificationMethod: Type.Literal("human-hardware-previewsign"),
877
+ version: Type.Literal(1),
878
+ envelope: schemaRef$1(PreviewSignBase64UrlSchema, "PreviewSignBase64Url"),
879
+ digest: schemaRef$1(PreviewSignSha256Base64UrlSchema, "PreviewSignSha256Base64Url"),
880
+ additionalArguments: schemaRef$1(PreviewSignBase64UrlSchema, "PreviewSignBase64Url"),
881
+ outerCredentialId: schemaRef$1(PreviewSignBase64UrlSchema, "PreviewSignBase64Url"),
882
+ outerPublicKey: schemaRef$1(PreviewSignEs256PublicKeySchema, "PreviewSignEs256PublicKey"),
883
+ previewKeyHandle: schemaRef$1(PreviewSignBase64UrlSchema, "PreviewSignBase64Url")
884
+ }, {
885
+ $id: "PreviewSignChallenge",
886
+ additionalProperties: false
887
+ });
888
+ var PreviewSignChallengeValueSchema = Type.Object({
889
+ verificationMethod: Type.Literal("human-hardware-previewsign"),
890
+ value: schemaRef$1(PreviewSignChallengeSchema, "PreviewSignChallenge")
891
+ }, {
892
+ $id: "PreviewSignChallengeValue",
893
+ additionalProperties: false
894
+ });
895
+ var PreviewSignChallengeOperationSchema = Type.Union([Type.Literal("credential-registration"), Type.Literal("signing-request")], { $id: "PreviewSignChallengeOperation" });
896
+ var PreviewSignReceiptSchema = Type.Object({
897
+ version: Type.Literal(1),
898
+ signature: schemaRef$1(PreviewSignP256DerSignatureBase64UrlSchema, "PreviewSignP256DerSignatureBase64Url")
899
+ }, {
900
+ $id: "PreviewSignReceipt",
901
+ additionalProperties: false
902
+ });
903
+ var PreviewSignReceiptValueSchema = Type.Object({
904
+ verificationMethod: Type.Literal("human-hardware-previewsign"),
905
+ value: schemaRef$1(PreviewSignReceiptSchema, "PreviewSignReceipt")
906
+ }, {
907
+ $id: "PreviewSignReceiptValue",
908
+ additionalProperties: false
909
+ });
910
+ var previewSignSchemaContext = {
911
+ PreviewSignBase64Url: PreviewSignBase64UrlSchema,
912
+ PreviewSignSha256Base64Url: PreviewSignSha256Base64UrlSchema,
913
+ PreviewSignP256DerSignatureBase64Url: PreviewSignP256DerSignatureBase64UrlSchema,
914
+ PreviewSignEs256PublicKey: PreviewSignEs256PublicKeySchema,
915
+ PreviewSignEcdhEsHkdf256PublicKey: PreviewSignEcdhEsHkdf256PublicKeySchema,
916
+ PreviewSignEsp256PublicKey: PreviewSignEsp256PublicKeySchema,
917
+ PreviewSignArkgSeedPublicKey: PreviewSignArkgSeedPublicKeySchema,
918
+ PreviewSignPublicMaterial: PreviewSignPublicMaterialSchema,
919
+ PreviewSignChallenge: PreviewSignChallengeSchema,
920
+ PreviewSignChallengeValue: PreviewSignChallengeValueSchema,
921
+ PreviewSignChallengeOperation: PreviewSignChallengeOperationSchema,
922
+ PreviewSignReceipt: PreviewSignReceiptSchema,
923
+ PreviewSignReceiptValue: PreviewSignReceiptValueSchema
924
+ };
925
+ //#endregion
926
+ //#region ../../libs/models/src/verification-method.ts
927
+ /**
928
+ * Persisted and wire-level signing verification method identifiers.
929
+ *
930
+ * This vocabulary is append-only. Never rename, remove, or change an existing
931
+ * value: PostgreSQL rows, workflow inputs, and API clients persist these exact
932
+ * strings. Future signing methods must add a new property and value.
933
+ */
934
+ var VERIFICATION_METHOD = {
935
+ AgentEd25519: "agent-ed25519",
936
+ HumanHardwarePreviewSign: "human-hardware-previewsign"
937
+ };
938
+ VERIFICATION_METHOD.AgentEd25519, VERIFICATION_METHOD.HumanHardwarePreviewSign;
939
+ //#endregion
940
+ //#region ../../libs/models/src/schemas.ts
941
+ var UuidSchema = Type.String({
942
+ format: "uuid",
943
+ description: "UUID v4 identifier"
944
+ });
945
+ var TimestampSchema = Type.String({
946
+ format: "date-time",
947
+ description: "ISO 8601 timestamp"
948
+ });
949
+ var verificationMethodLiterals = [Type.Literal(VERIFICATION_METHOD.AgentEd25519), Type.Literal(VERIFICATION_METHOD.HumanHardwarePreviewSign)];
950
+ Type.Union(verificationMethodLiterals, { description: "Stable signing verification method identifier" });
951
+ var visibilityLiterals = [
952
+ Type.Literal("private"),
953
+ Type.Literal("moltnet"),
954
+ Type.Literal("public")
955
+ ];
956
+ Type.Union(visibilityLiterals, { description: "Entry visibility level" });
957
+ var ENTRY_TYPE_VALUES = [
958
+ "episodic",
959
+ "semantic",
960
+ "procedural",
961
+ "reflection"
962
+ ];
963
+ var entryTypeLiterals = [
964
+ Type.Literal("episodic"),
965
+ Type.Literal("semantic"),
966
+ Type.Literal("procedural"),
967
+ Type.Literal("reflection")
968
+ ];
969
+ var EntryTypeSchema = Type.Union(entryTypeLiterals, { description: "Entry memory type" });
970
+ /** Regex fragment matching a single entry type value. */
971
+ var ENTRY_TYPE_PATTERN = `(${ENTRY_TYPE_VALUES.join("|")})`;
972
+ `${ENTRY_TYPE_PATTERN}${ENTRY_TYPE_PATTERN}`, ENTRY_TYPE_VALUES.length - 1;
973
+ var PublicKeySchema = Type.String({
974
+ pattern: "^ed25519:[A-Za-z0-9+/=]+$",
975
+ description: "Ed25519 public key with prefix"
976
+ });
977
+ var FingerprintSchema = Type.String({
978
+ pattern: "^[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}$",
979
+ description: "Key fingerprint (A1B2-C3D4-E5F6-G7H8)"
980
+ });
981
+ Type.Object({
982
+ title: Type.Optional(Type.String({ maxLength: 255 })),
983
+ content: Type.String({
984
+ minLength: 1,
985
+ maxLength: 1e5
986
+ }),
987
+ tags: Type.Optional(Type.Array(Type.String({ maxLength: 128 }), { maxItems: 20 }))
988
+ });
989
+ Type.Object({
990
+ title: Type.Optional(Type.String({ maxLength: 255 })),
991
+ content: Type.Optional(Type.String({
992
+ minLength: 1,
993
+ maxLength: 1e5
994
+ })),
995
+ tags: Type.Optional(Type.Array(Type.String({ maxLength: 128 }), { maxItems: 20 }))
996
+ });
997
+ Type.Object({
998
+ query: Type.Optional(Type.String({
999
+ minLength: 1,
1000
+ maxLength: 500
1001
+ })),
1002
+ tags: Type.Optional(Type.Array(Type.String({ maxLength: 128 }), {
1003
+ minItems: 1,
1004
+ maxItems: 20,
1005
+ description: "Filter: entry must have ALL specified tags"
1006
+ })),
1007
+ limit: Type.Optional(Type.Number({
576
1008
  minimum: 1,
577
1009
  maximum: 100,
578
1010
  default: 20
@@ -672,10 +1104,10 @@ Type.Object({
672
1104
  Type.Literal("completed"),
673
1105
  Type.Literal("failed")
674
1106
  ]),
675
- githubCode: Type.Optional(Type.String()),
1107
+ githubCode: Type.Optional(Type.String({ description: "GitHub manifest code sealed to the onboarding agent public key." })),
676
1108
  identityId: Type.Optional(Type.String()),
677
1109
  clientId: Type.Optional(Type.String()),
678
- clientSecret: Type.Optional(Type.String()),
1110
+ clientSecret: Type.Optional(Type.String({ description: "OAuth2 client secret sealed to the onboarding agent public key." })),
679
1111
  installationId: Type.Optional(Type.String())
680
1112
  });
681
1113
  Type.Object({
@@ -1156,936 +1588,506 @@ var SignerUuidSchema = Type.String({
1156
1588
  $id: "SignerUuid",
1157
1589
  pattern: "^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
1158
1590
  });
1159
- var SignerOperationSchema = Type.Union([
1160
- Type.Literal("credential-enrollment"),
1161
- Type.Literal("credential-registration"),
1162
- Type.Literal("signing-request")
1163
- ], { $id: "SignerOperation" });
1164
- var SignerChallengeOperationSchema = PreviewSignChallengeOperationSchema;
1165
- var SignerPreviewSignPublicMaterialSchema = PreviewSignPublicMaterialSchema;
1166
- var SignerPreviewSignChallengeValueSchema = PreviewSignChallengeValueSchema;
1167
- var SignerProblemSchema = Type.Object({
1168
- code: Type.String({ minLength: 1 }),
1169
- message: Type.String({ minLength: 1 })
1170
- }, {
1171
- $id: "SignerProblem",
1172
- additionalProperties: false
1173
- });
1174
- var SignerCeremonyParamsSchema = Type.Object({ ceremonyId: Type.Unsafe(schemaRef(SignerBase64UrlSchema)) }, {
1175
- $id: "SignerCeremonyParams",
1176
- additionalProperties: false
1177
- });
1178
- var SignerSessionSchema = Type.Object({
1179
- version: Type.Literal(1),
1180
- token: Type.Unsafe(schemaRef(SignerBase64UrlSchema)),
1181
- expiresAt: Type.String()
1182
- }, {
1183
- $id: "SignerSession",
1184
- additionalProperties: false
1185
- });
1186
- var SignerEnrollmentCeremonyRequestSchema = Type.Object({
1187
- version: Type.Literal(1),
1188
- operation: Type.Literal("credential-enrollment"),
1189
- label: Type.String({
1190
- minLength: 1,
1191
- maxLength: 255
1192
- }),
1193
- teamId: Type.Unsafe(schemaRef(SignerUuidSchema))
1194
- }, {
1195
- $id: "SignerEnrollmentCeremonyRequest",
1196
- additionalProperties: false
1197
- });
1198
- var SignerChallengeCeremonyRequestSchema = Type.Object({
1199
- version: Type.Literal(1),
1200
- operation: Type.Unsafe(schemaRef(SignerChallengeOperationSchema)),
1201
- resourceId: Type.Unsafe(schemaRef(SignerUuidSchema)),
1202
- challenge: Type.Unsafe(schemaRef(SignerPreviewSignChallengeValueSchema))
1203
- }, {
1204
- $id: "SignerChallengeCeremonyRequest",
1205
- additionalProperties: false
1206
- });
1207
- var SignerCeremonyRequestSchema = Type.Union([Type.Unsafe(schemaRef(SignerEnrollmentCeremonyRequestSchema)), Type.Unsafe(schemaRef(SignerChallengeCeremonyRequestSchema))], { $id: "SignerCeremonyRequest" });
1208
- var SignerCeremonySchema = Type.Object({
1209
- version: Type.Literal(1),
1210
- id: Type.Unsafe(schemaRef(SignerBase64UrlSchema)),
1211
- operation: Type.Unsafe(schemaRef(SignerOperationSchema)),
1212
- approvalUrl: Type.String(),
1213
- expiresAt: Type.String()
1214
- }, {
1215
- $id: "SignerCeremony",
1216
- additionalProperties: false
1217
- });
1218
- var SignerPendingResultSchema = Type.Object({
1219
- version: Type.Literal(1),
1220
- status: Type.Literal("pending"),
1221
- operation: Type.Unsafe(schemaRef(SignerOperationSchema))
1222
- }, {
1223
- $id: "SignerPendingResult",
1224
- additionalProperties: false
1225
- });
1226
- var SignerEnrollmentResultSchema = Type.Object({
1227
- version: Type.Literal(1),
1228
- status: Type.Literal("completed"),
1229
- operation: Type.Literal("credential-enrollment"),
1230
- publicMaterial: Type.Unsafe(schemaRef(SignerPreviewSignPublicMaterialSchema))
1231
- }, {
1232
- $id: "SignerEnrollmentResult",
1233
- additionalProperties: false
1234
- });
1235
- var SignerReceiptSchema = PreviewSignReceiptValueSchema;
1236
- var SignerSignatureResultSchema = Type.Object({
1237
- version: Type.Literal(1),
1238
- status: Type.Literal("completed"),
1239
- operation: Type.Unsafe(schemaRef(SignerChallengeOperationSchema)),
1240
- receipt: Type.Unsafe(schemaRef(SignerReceiptSchema))
1241
- }, {
1242
- $id: "SignerSignatureResult",
1243
- additionalProperties: false
1244
- });
1245
- var SignerFailedResultSchema = Type.Object({
1246
- version: Type.Literal(1),
1247
- status: Type.Literal("failed"),
1248
- operation: Type.Unsafe(schemaRef(SignerOperationSchema)),
1249
- code: Type.String(),
1250
- message: Type.String()
1251
- }, {
1252
- $id: "SignerFailedResult",
1253
- additionalProperties: false
1254
- });
1255
- var SignerCeremonyResultSchema = Type.Union([
1256
- Type.Unsafe(schemaRef(SignerPendingResultSchema)),
1257
- Type.Unsafe(schemaRef(SignerEnrollmentResultSchema)),
1258
- Type.Unsafe(schemaRef(SignerSignatureResultSchema)),
1259
- Type.Unsafe(schemaRef(SignerFailedResultSchema))
1260
- ], { $id: "SignerCeremonyResult" });
1261
- ({ ...previewSignSchemaContext }), schemaId(SignerUuidSchema), schemaId(SignerOperationSchema), schemaId(SignerProblemSchema), schemaId(SignerCeremonyParamsSchema), schemaId(SignerSessionSchema), schemaId(SignerEnrollmentCeremonyRequestSchema), schemaId(SignerChallengeCeremonyRequestSchema), schemaId(SignerCeremonyRequestSchema), schemaId(SignerCeremonySchema), schemaId(SignerPendingResultSchema), schemaId(SignerEnrollmentResultSchema), schemaId(SignerSignatureResultSchema), schemaId(SignerFailedResultSchema), schemaId(SignerCeremonyResultSchema);
1262
- //#endregion
1263
- //#region ../../libs/models/src/tool-enforcement.ts
1264
- var TOOL_ENFORCEMENT_VALUES = [
1265
- "off",
1266
- "watch",
1267
- "enforce"
1268
- ];
1269
- var toolEnforcementLiterals = [
1270
- Type.Literal(TOOL_ENFORCEMENT_VALUES[0]),
1271
- Type.Literal(TOOL_ENFORCEMENT_VALUES[1]),
1272
- Type.Literal(TOOL_ENFORCEMENT_VALUES[2])
1273
- ];
1274
- var ToolEnforcementSchema = Type.Union(toolEnforcementLiterals, { description: "Runtime tool-policy enforcement mode: off (inert), watch (audit only), enforce (block disallowed tools, fail-closed)." });
1275
- //#endregion
1276
- //#region ../../libs/tasks/src/runtime-profiles.ts
1277
- var RuntimeProfileName = Type.String({
1278
- minLength: 1,
1279
- maxLength: 100,
1280
- pattern: "^[a-zA-Z0-9][a-zA-Z0-9_-]{0,99}$"
1281
- });
1282
- var RuntimeProfileEnvName = Type.String({
1283
- minLength: 1,
1284
- maxLength: 128,
1285
- pattern: "^[A-Z_][A-Z0-9_]*$"
1286
- });
1287
- var RuntimeProfileToolName = Type.String({
1288
- minLength: 1,
1289
- maxLength: 128,
1290
- pattern: "^[a-zA-Z0-9._/-]+$"
1291
- });
1292
- var RUNTIME_PROFILE_RUNTIME_KIND_PATTERN = "^[a-z][a-z0-9._-]{0,99}$";
1293
- new RegExp(RUNTIME_PROFILE_RUNTIME_KIND_PATTERN);
1294
- var RuntimeProfileRuntimeKind = Type.String({
1295
- minLength: 1,
1296
- maxLength: 100,
1297
- pattern: RUNTIME_PROFILE_RUNTIME_KIND_PATTERN
1298
- });
1299
- var RuntimeProfileWorkspaceMode = Type.Union([
1300
- Type.Literal("none"),
1301
- Type.Literal("shared_mount"),
1302
- Type.Literal("dedicated_worktree")
1303
- ]);
1304
- /**
1305
- * Tool-policy enforcement mode for the profile's runtime `tool_call` gate:
1306
- * `off` (inert), `watch` (audit only), `enforce` (block disallowed tools,
1307
- * fail-closed). Read by the daemon via `GET /runtime-profiles/:id/allowed-tools`.
1308
- */
1309
- var RuntimeProfileToolEnforcement = ToolEnforcementSchema;
1310
- var RuntimeProfileAllowedWorkspaceModes = Type.Array(RuntimeProfileWorkspaceMode, {
1311
- minItems: 1,
1312
- maxItems: 3,
1313
- uniqueItems: true
1314
- });
1315
- var RuntimeProfileThinkingLevelOptions = [
1316
- Type.Literal("off"),
1317
- Type.Literal("minimal"),
1318
- Type.Literal("low"),
1319
- Type.Literal("medium"),
1320
- Type.Literal("high"),
1321
- Type.Literal("xhigh")
1322
- ];
1323
- Type.Union([...RuntimeProfileThinkingLevelOptions]);
1324
- var RuntimeProfileNullableThinkingLevel = Type.Union([...RuntimeProfileThinkingLevelOptions, Type.Null()]);
1325
- var RuntimeProfileNullableTemperature = Type.Union([Type.Null(), Type.Number({
1326
- minimum: 0,
1327
- maximum: 2
1328
- })]);
1329
- var RuntimeProfileNullableTopP = Type.Union([Type.Null(), Type.Number({
1330
- minimum: 0,
1331
- maximum: 1
1332
- })]);
1333
- var RuntimeProfileNullableTopK = Type.Union([Type.Integer({
1334
- minimum: 1,
1335
- maximum: 1e4
1336
- }), Type.Null()]);
1337
- var RuntimeProfileNullableMaxOutputTokens = Type.Union([Type.Integer({
1338
- minimum: 1,
1339
- maximum: 1e6
1340
- }), Type.Null()]);
1341
- var RuntimeProfileAllowedHost = Type.String({
1342
- minLength: 1,
1343
- maxLength: 255,
1344
- pattern: "^(?:\\*\\.)?(?:[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?)(?:\\.(?:[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?))*$"
1345
- });
1346
- var RuntimeProfileSandbox = Type.Object({
1347
- network: Type.Optional(Type.Object({
1348
- allowedHosts: Type.Optional(Type.Array(RuntimeProfileAllowedHost, { maxItems: 50 })),
1349
- allowedInternalHosts: Type.Optional(Type.Array(RuntimeProfileAllowedHost, { maxItems: 50 }))
1350
- }, { additionalProperties: false })),
1351
- vfs: Type.Optional(Type.Object({
1352
- shadow: Type.Optional(Type.Array(Type.String({
1353
- minLength: 1,
1354
- maxLength: 255
1355
- }), { maxItems: 100 })),
1356
- shadowMode: Type.Optional(Type.Union([Type.Literal("deny"), Type.Literal("tmpfs")]))
1357
- }, { additionalProperties: false })),
1358
- env: Type.Optional(Type.Record(RuntimeProfileEnvName, Type.String({ maxLength: 4096 }))),
1359
- hostExec: Type.Optional(Type.Object({ autoApprove: Type.Optional(Type.Literal(false)) }, { additionalProperties: false })),
1360
- resources: Type.Optional(Type.Object({
1361
- memory: Type.Optional(Type.String({
1362
- minLength: 2,
1363
- maxLength: 16,
1364
- pattern: "^[0-9]+[KMG]?$"
1365
- })),
1366
- cpus: Type.Optional(Type.Integer({
1367
- minimum: 1,
1368
- maximum: 32
1369
- }))
1370
- }, { additionalProperties: false }))
1371
- }, {
1372
- $id: "RuntimeProfileSandbox",
1373
- additionalProperties: false
1374
- });
1375
- var RuntimeProfileContext = Type.Object({
1376
- slug: Type.String({
1377
- minLength: 1,
1378
- maxLength: 64,
1379
- pattern: "^[a-zA-Z0-9_-]+$"
1380
- }),
1381
- binding: Type.Union([
1382
- Type.Literal("skill"),
1383
- Type.Literal("context_inline"),
1384
- Type.Literal("prompt_prefix"),
1385
- Type.Literal("user_inline")
1386
- ]),
1387
- content: Type.String({
1388
- minLength: 1,
1389
- maxLength: 65536
1390
- })
1391
- }, {
1392
- $id: "RuntimeProfileContext",
1393
- additionalProperties: false
1394
- });
1395
- var RuntimeProfileRef = Type.Object({ profileId: Type.String({ format: "uuid" }) }, {
1396
- $id: "RuntimeProfileRef",
1397
- additionalProperties: false
1398
- });
1399
- var RuntimeProfileLeaseTtlSec = Type.Integer({
1400
- minimum: 1,
1401
- maximum: 86400
1402
- });
1403
- var RuntimeProfileHeartbeatIntervalMs = Type.Integer({
1404
- minimum: 0,
1405
- maximum: 36e5
1406
- });
1407
- var RuntimeProfileMaxBatchSize = Type.Integer({
1408
- minimum: 1,
1409
- maximum: 1e3
1410
- });
1411
- var RuntimeProfileMaxTurns = Type.Integer({
1412
- minimum: 0,
1413
- maximum: 1e4
1591
+ var SignerOperationSchema = Type.Union([
1592
+ Type.Literal("credential-enrollment"),
1593
+ Type.Literal("credential-registration"),
1594
+ Type.Literal("signing-request")
1595
+ ], { $id: "SignerOperation" });
1596
+ var SignerChallengeOperationSchema = PreviewSignChallengeOperationSchema;
1597
+ var SignerPreviewSignPublicMaterialSchema = PreviewSignPublicMaterialSchema;
1598
+ var SignerPreviewSignChallengeValueSchema = PreviewSignChallengeValueSchema;
1599
+ var SignerProblemSchema = Type.Object({
1600
+ code: Type.String({ minLength: 1 }),
1601
+ message: Type.String({ minLength: 1 })
1602
+ }, {
1603
+ $id: "SignerProblem",
1604
+ additionalProperties: false
1414
1605
  });
1415
- var RuntimeProfileMaxBashTimeouts = Type.Integer({
1416
- minimum: 0,
1417
- maximum: 1e3
1606
+ var SignerCeremonyParamsSchema = Type.Object({ ceremonyId: Type.Unsafe(schemaRef(SignerBase64UrlSchema)) }, {
1607
+ $id: "SignerCeremonyParams",
1608
+ additionalProperties: false
1418
1609
  });
1419
- Type.Object({
1420
- id: Type.String({ format: "uuid" }),
1421
- teamId: Type.String({ format: "uuid" }),
1422
- name: RuntimeProfileName,
1423
- description: Type.Union([Type.String({ maxLength: 4096 }), Type.Null()]),
1424
- provider: Type.String({
1425
- minLength: 1,
1426
- maxLength: 100
1427
- }),
1428
- model: Type.String({
1429
- minLength: 1,
1430
- maxLength: 200
1431
- }),
1432
- thinkingLevel: RuntimeProfileNullableThinkingLevel,
1433
- temperature: RuntimeProfileNullableTemperature,
1434
- topP: RuntimeProfileNullableTopP,
1435
- topK: RuntimeProfileNullableTopK,
1436
- maxOutputTokens: RuntimeProfileNullableMaxOutputTokens,
1437
- runtimeKind: RuntimeProfileRuntimeKind,
1438
- sandbox: RuntimeProfileSandbox,
1439
- sessionStorageMode: Type.Literal("local"),
1440
- workspaceStorageMode: Type.Literal("local"),
1441
- defaultWorkspaceMode: Type.Union([RuntimeProfileWorkspaceMode, Type.Null()]),
1442
- allowedWorkspaceModes: RuntimeProfileAllowedWorkspaceModes,
1443
- sessionTtlSec: Type.Integer({
1444
- minimum: 1,
1445
- maximum: 86400
1446
- }),
1447
- workspaceTtlSec: Type.Integer({
1448
- minimum: 1,
1449
- maximum: 86400
1450
- }),
1451
- leaseTtlSec: RuntimeProfileLeaseTtlSec,
1452
- heartbeatIntervalMs: RuntimeProfileHeartbeatIntervalMs,
1453
- maxBatchSize: RuntimeProfileMaxBatchSize,
1454
- maxTurns: RuntimeProfileMaxTurns,
1455
- maxBashTimeouts: RuntimeProfileMaxBashTimeouts,
1456
- toolEnforcement: RuntimeProfileToolEnforcement,
1457
- requiredEnv: Type.Array(RuntimeProfileEnvName, { maxItems: 100 }),
1458
- requiredTools: Type.Array(RuntimeProfileToolName, { maxItems: 100 }),
1459
- requiredExecutables: Type.Array(RuntimeProfileToolName, { maxItems: 100 }),
1460
- context: Type.Array(RuntimeProfileContext, { maxItems: 5 }),
1461
- revision: Type.Integer({ minimum: 1 }),
1462
- definitionCid: Type.String({
1463
- minLength: 1,
1464
- maxLength: 100
1465
- }),
1466
- createdByAgentId: Type.Union([Type.String({ format: "uuid" }), Type.Null()]),
1467
- createdByHumanId: Type.Union([Type.String({ format: "uuid" }), Type.Null()]),
1468
- createdAt: Type.String({ format: "date-time" }),
1469
- updatedAt: Type.String({ format: "date-time" })
1610
+ var SignerSessionSchema = Type.Object({
1611
+ version: Type.Literal(1),
1612
+ token: Type.Unsafe(schemaRef(SignerBase64UrlSchema)),
1613
+ expiresAt: Type.String()
1470
1614
  }, {
1471
- $id: "RuntimeProfile",
1615
+ $id: "SignerSession",
1472
1616
  additionalProperties: false
1473
1617
  });
1474
- //#endregion
1475
- //#region ../../libs/tasks/src/runtime-sessions.ts
1476
- var RuntimeSessionKind = Type.Union([
1477
- Type.Literal("root"),
1478
- Type.Literal("extend"),
1479
- Type.Literal("fork")
1480
- ]);
1481
- var RuntimeSessionCheckpointKind = Type.Union([Type.Literal("attempt_final")]);
1482
- Type.Object({
1483
- id: Type.String({ format: "uuid" }),
1484
- teamId: Type.String({ format: "uuid" }),
1485
- taskId: Type.String({ format: "uuid" }),
1486
- attemptN: Type.Integer({ minimum: 1 }),
1487
- sourceSlotId: Type.Union([Type.String({ format: "uuid" }), Type.Null()]),
1488
- sourceRuntimeProfileId: Type.Union([Type.String({ format: "uuid" }), Type.Null()]),
1489
- sessionKind: RuntimeSessionKind,
1490
- parentSessionId: Type.Union([Type.String({ format: "uuid" }), Type.Null()]),
1491
- contentType: Type.String({
1492
- minLength: 1,
1493
- maxLength: 200
1494
- }),
1495
- contentEncoding: Type.Union([Type.String({
1496
- minLength: 1,
1497
- maxLength: 100
1498
- }), Type.Null()]),
1499
- sizeBytes: Type.Integer({ minimum: 0 }),
1500
- sha256: Type.String({
1501
- minLength: 64,
1502
- maxLength: 64
1503
- }),
1504
- storageClass: Type.String({
1618
+ var SignerEnrollmentCeremonyRequestSchema = Type.Object({
1619
+ version: Type.Literal(1),
1620
+ operation: Type.Literal("credential-enrollment"),
1621
+ label: Type.String({
1505
1622
  minLength: 1,
1506
- maxLength: 100
1623
+ maxLength: 255
1507
1624
  }),
1508
- checkpointKind: RuntimeSessionCheckpointKind,
1509
- uploadedAt: Type.String({ format: "date-time" })
1510
- }, { $id: "RuntimeSession" });
1511
- Type.Object({
1512
- sourceSlotId: Type.Optional(Type.String({ format: "uuid" })),
1513
- sourceRuntimeProfileId: Type.Optional(Type.String({ format: "uuid" })),
1514
- sessionKind: RuntimeSessionKind,
1515
- parentSessionId: Type.Optional(Type.String({ format: "uuid" }))
1625
+ teamId: Type.Unsafe(schemaRef(SignerUuidSchema))
1516
1626
  }, {
1517
- $id: "UploadRuntimeSessionQuery",
1627
+ $id: "SignerEnrollmentCeremonyRequest",
1518
1628
  additionalProperties: false
1519
1629
  });
1520
- Type.String({
1521
- $id: "RuntimeSessionContent",
1522
- description: "Runtime session content stream.",
1523
- format: "binary"
1630
+ var SignerChallengeCeremonyRequestSchema = Type.Object({
1631
+ version: Type.Literal(1),
1632
+ operation: Type.Unsafe(schemaRef(SignerChallengeOperationSchema)),
1633
+ resourceId: Type.Unsafe(schemaRef(SignerUuidSchema)),
1634
+ challenge: Type.Unsafe(schemaRef(SignerPreviewSignChallengeValueSchema))
1635
+ }, {
1636
+ $id: "SignerChallengeCeremonyRequest",
1637
+ additionalProperties: false
1524
1638
  });
1525
- Type.Object({
1526
- taskId: Type.String({ format: "uuid" }),
1527
- attemptN: Type.Integer({ minimum: 1 })
1639
+ var SignerCeremonyRequestSchema = Type.Union([Type.Unsafe(schemaRef(SignerEnrollmentCeremonyRequestSchema)), Type.Unsafe(schemaRef(SignerChallengeCeremonyRequestSchema))], { $id: "SignerCeremonyRequest" });
1640
+ var SignerCeremonySchema = Type.Object({
1641
+ version: Type.Literal(1),
1642
+ id: Type.Unsafe(schemaRef(SignerBase64UrlSchema)),
1643
+ operation: Type.Unsafe(schemaRef(SignerOperationSchema)),
1644
+ approvalUrl: Type.String(),
1645
+ expiresAt: Type.String()
1528
1646
  }, {
1529
- $id: "RuntimeSessionAttemptParams",
1647
+ $id: "SignerCeremony",
1530
1648
  additionalProperties: false
1531
1649
  });
1532
- //#endregion
1533
- //#region ../../libs/tasks/src/runtime-slots.ts
1534
- var RuntimeWorkspaceKind = Type.Union([
1535
- Type.Literal("origin"),
1536
- Type.Literal("fork"),
1537
- Type.Literal("scratch")
1538
- ]);
1539
- var RuntimeSlotState = Type.Union([Type.Literal("active"), Type.Literal("idle")]);
1540
- var RuntimeWorkspace = Type.Object({
1541
- id: Type.String({ format: "uuid" }),
1542
- teamId: Type.String({ format: "uuid" }),
1543
- workspaceId: Type.String({ minLength: 1 }),
1544
- worktreePath: Type.String({ minLength: 1 }),
1545
- worktreeBranch: Type.Union([Type.String({ minLength: 1 }), Type.Null()]),
1546
- kind: RuntimeWorkspaceKind,
1547
- createdAtMs: Type.Integer({ minimum: 0 }),
1548
- lastUsedAtMs: Type.Integer({ minimum: 0 })
1549
- }, { $id: "RuntimeWorkspace" });
1550
- var RuntimeSlot = Type.Object({
1551
- id: Type.String({ format: "uuid" }),
1552
- teamId: Type.String({ format: "uuid" }),
1553
- agentName: Type.String({
1554
- minLength: 1,
1555
- maxLength: 100
1556
- }),
1557
- runtimeProfileId: Type.Union([Type.String({ format: "uuid" }), Type.Null()]),
1558
- provider: Type.String({
1559
- minLength: 1,
1560
- maxLength: 100
1561
- }),
1562
- model: Type.String({
1563
- minLength: 1,
1564
- maxLength: 200
1565
- }),
1566
- slotKey: Type.String({ minLength: 1 }),
1567
- taskType: Type.String({
1568
- minLength: 1,
1569
- maxLength: 100
1570
- }),
1571
- state: RuntimeSlotState,
1572
- lastTaskId: Type.String({ format: "uuid" }),
1573
- lastAttemptN: Type.Integer({ minimum: 1 }),
1574
- sessionDir: Type.Union([Type.String({ minLength: 1 }), Type.Null()]),
1575
- sessionPath: Type.Union([Type.String({ minLength: 1 }), Type.Null()]),
1576
- workspaceRowId: Type.Union([Type.String({ format: "uuid" }), Type.Null()]),
1577
- createdAtMs: Type.Integer({ minimum: 0 }),
1578
- lastUsedAtMs: Type.Integer({ minimum: 0 }),
1579
- expiresAtMs: Type.Integer({ minimum: 0 })
1580
- }, { $id: "RuntimeSlot" });
1581
- var ResolvedRuntimeSlot = Type.Object({
1582
- slot: RuntimeSlot,
1583
- workspace: Type.Union([RuntimeWorkspace, Type.Null()])
1584
- }, { $id: "ResolvedRuntimeSlot" });
1585
- Type.Object({ items: Type.Array(ResolvedRuntimeSlot) }, { $id: "RuntimeSlotListResponse" });
1586
- Type.Object({
1587
- agentName: Type.String({
1588
- minLength: 1,
1589
- maxLength: 100
1590
- }),
1591
- runtimeProfileId: Type.String({ format: "uuid" }),
1592
- provider: Type.String({
1593
- minLength: 1,
1594
- maxLength: 100
1595
- }),
1596
- model: Type.String({
1597
- minLength: 1,
1598
- maxLength: 200
1599
- }),
1600
- slotKey: Type.String({ minLength: 1 }),
1601
- taskType: Type.String({
1602
- minLength: 1,
1603
- maxLength: 100
1604
- }),
1605
- sessionDir: Type.Optional(Type.String({ minLength: 1 })),
1606
- sessionPath: Type.Optional(Type.String({ minLength: 1 })),
1607
- workspaceId: Type.Optional(Type.String({ minLength: 1 })),
1608
- worktreePath: Type.Optional(Type.String({ minLength: 1 })),
1609
- worktreeBranch: Type.Optional(Type.String({ minLength: 1 })),
1610
- workspaceKind: Type.Optional(RuntimeWorkspaceKind),
1611
- lastTaskId: Type.String({ format: "uuid" }),
1612
- lastAttemptN: Type.Integer({ minimum: 1 })
1650
+ var SignerPendingResultSchema = Type.Object({
1651
+ version: Type.Literal(1),
1652
+ status: Type.Literal("pending"),
1653
+ operation: Type.Unsafe(schemaRef(SignerOperationSchema))
1613
1654
  }, {
1614
- $id: "BeginRuntimeSlotBody",
1655
+ $id: "SignerPendingResult",
1615
1656
  additionalProperties: false
1616
1657
  });
1617
- Type.Object({
1618
- agentName: Type.String({
1619
- minLength: 1,
1620
- maxLength: 100
1621
- }),
1622
- runtimeProfileId: Type.String({ format: "uuid" }),
1623
- provider: Type.String({
1624
- minLength: 1,
1625
- maxLength: 100
1626
- }),
1627
- model: Type.String({
1628
- minLength: 1,
1629
- maxLength: 200
1630
- }),
1631
- slotKey: Type.String({ minLength: 1 }),
1632
- taskId: Type.String({ format: "uuid" }),
1633
- attemptN: Type.Integer({ minimum: 1 }),
1634
- sessionPath: Type.Optional(Type.String({ minLength: 1 }))
1658
+ var SignerEnrollmentResultSchema = Type.Object({
1659
+ version: Type.Literal(1),
1660
+ status: Type.Literal("completed"),
1661
+ operation: Type.Literal("credential-enrollment"),
1662
+ publicMaterial: Type.Unsafe(schemaRef(SignerPreviewSignPublicMaterialSchema))
1635
1663
  }, {
1636
- $id: "FinishRuntimeSlotBody",
1664
+ $id: "SignerEnrollmentResult",
1637
1665
  additionalProperties: false
1638
1666
  });
1639
- Type.Object({
1640
- taskId: Type.String({ format: "uuid" }),
1641
- attemptN: Type.Integer({ minimum: 1 })
1667
+ var SignerReceiptSchema = PreviewSignReceiptValueSchema;
1668
+ var SignerSignatureResultSchema = Type.Object({
1669
+ version: Type.Literal(1),
1670
+ status: Type.Literal("completed"),
1671
+ operation: Type.Unsafe(schemaRef(SignerChallengeOperationSchema)),
1672
+ receipt: Type.Unsafe(schemaRef(SignerReceiptSchema))
1642
1673
  }, {
1643
- $id: "FindLatestRuntimeSlotForAttemptQuery",
1674
+ $id: "SignerSignatureResult",
1644
1675
  additionalProperties: false
1645
1676
  });
1646
- Type.Object({
1647
- agentName: Type.Optional(Type.String({
1648
- minLength: 1,
1649
- maxLength: 100
1650
- })),
1651
- runtimeProfileId: Type.Optional(Type.String({ format: "uuid" })),
1652
- state: Type.Optional(RuntimeSlotState),
1653
- limit: Type.Optional(Type.Integer({
1654
- minimum: 1,
1655
- maximum: 200
1656
- }))
1677
+ var SignerFailedResultSchema = Type.Object({
1678
+ version: Type.Literal(1),
1679
+ status: Type.Literal("failed"),
1680
+ operation: Type.Unsafe(schemaRef(SignerOperationSchema)),
1681
+ code: Type.String(),
1682
+ message: Type.String()
1657
1683
  }, {
1658
- $id: "ListRuntimeSlotsQuery",
1684
+ $id: "SignerFailedResult",
1659
1685
  additionalProperties: false
1660
1686
  });
1687
+ var SignerCeremonyResultSchema = Type.Union([
1688
+ Type.Unsafe(schemaRef(SignerPendingResultSchema)),
1689
+ Type.Unsafe(schemaRef(SignerEnrollmentResultSchema)),
1690
+ Type.Unsafe(schemaRef(SignerSignatureResultSchema)),
1691
+ Type.Unsafe(schemaRef(SignerFailedResultSchema))
1692
+ ], { $id: "SignerCeremonyResult" });
1693
+ ({ ...previewSignSchemaContext }), schemaId(SignerUuidSchema), schemaId(SignerOperationSchema), schemaId(SignerProblemSchema), schemaId(SignerCeremonyParamsSchema), schemaId(SignerSessionSchema), schemaId(SignerEnrollmentCeremonyRequestSchema), schemaId(SignerChallengeCeremonyRequestSchema), schemaId(SignerCeremonyRequestSchema), schemaId(SignerCeremonySchema), schemaId(SignerPendingResultSchema), schemaId(SignerEnrollmentResultSchema), schemaId(SignerSignatureResultSchema), schemaId(SignerFailedResultSchema), schemaId(SignerCeremonyResultSchema);
1661
1694
  //#endregion
1662
- //#region ../../libs/tasks/src/success-criteria.ts
1695
+ //#region ../../libs/models/src/tool-enforcement.ts
1696
+ var TOOL_ENFORCEMENT_VALUES = [
1697
+ "off",
1698
+ "watch",
1699
+ "enforce"
1700
+ ];
1701
+ var toolEnforcementLiterals = [
1702
+ Type.Literal(TOOL_ENFORCEMENT_VALUES[0]),
1703
+ Type.Literal(TOOL_ENFORCEMENT_VALUES[1]),
1704
+ Type.Literal(TOOL_ENFORCEMENT_VALUES[2])
1705
+ ];
1706
+ var ToolEnforcementSchema = Type.Union(toolEnforcementLiterals, { description: "Runtime tool-policy enforcement mode: off (inert), watch (audit only), enforce (block disallowed tools, fail-closed)." });
1707
+ //#endregion
1708
+ //#region ../../libs/runtime-profiles/src/runtime-profiles.ts
1709
+ var RuntimeProfileName = Type.String({
1710
+ minLength: 1,
1711
+ maxLength: 100,
1712
+ pattern: "^[a-zA-Z0-9][a-zA-Z0-9_-]{0,99}$"
1713
+ });
1714
+ var RuntimeProfileEnvName = Type.String({
1715
+ minLength: 1,
1716
+ maxLength: 128,
1717
+ pattern: "^[A-Z_][A-Z0-9_]*$"
1718
+ });
1719
+ var RuntimeProfileToolName = Type.String({
1720
+ minLength: 1,
1721
+ maxLength: 128,
1722
+ pattern: "^[a-zA-Z0-9._/-]+$"
1723
+ });
1724
+ var RUNTIME_PROFILE_RUNTIME_KIND_PATTERN = "^[a-z][a-z0-9._-]{0,99}$";
1725
+ new RegExp(RUNTIME_PROFILE_RUNTIME_KIND_PATTERN);
1726
+ var RuntimeProfileRuntimeKind = Type.String({
1727
+ minLength: 1,
1728
+ maxLength: 100,
1729
+ pattern: RUNTIME_PROFILE_RUNTIME_KIND_PATTERN
1730
+ });
1731
+ var RuntimeProfileWorkspaceMode = Type.Union([
1732
+ Type.Literal("none"),
1733
+ Type.Literal("shared_mount"),
1734
+ Type.Literal("dedicated_worktree")
1735
+ ]);
1663
1736
  /**
1664
- * SuccessCriteria — proposer-stated acceptance criteria, evaluated in two
1665
- * complementary places.
1666
- *
1667
- * Before this envelope existed, criteria were scattered: a vestigial
1668
- * `criteriaCid` column nobody resolved, free-form prose on
1669
- * `fulfill_brief.input`, and inline `rubric` / `criteria[]` fields on
1670
- * judgment-task inputs. None of those were machine-verifiable
1671
- * end-to-end.
1672
- *
1673
- * This module defines a single, content-addressable envelope a proposer
1674
- * attaches to any task type. It has four orthogonal sections — pick
1675
- * whichever apply per task type:
1676
- *
1677
- * - `gates` Promise-level structural/process checks
1678
- * - `assertions` Declarative claims about output JSON
1679
- * - `rubric` Weighted-criteria scoring instrument, reused
1680
- * verbatim from `./rubric.ts`.
1681
- * - `sideEffects` Required process side-effects (e.g. diary entry)
1682
- *
1683
- * ## Two roles, two task types
1684
- *
1685
- * **Producer self-assessment** (fulfillment tasks: `fulfill_brief`,
1686
- * `curate_pack`, `render_pack`). The producer **LLM** evaluates the
1687
- * criteria against its own output and emits a `VerificationRecord`
1688
- * inside `output.verification`. The daemon is pure passthrough — it
1689
- * does not run `evaluateAssertions`, does not inspect the verification
1690
- * record. The REST API is dumb storage; it never re-runs assertions and
1691
- * never runs LLMs. The cross-field rule
1692
- * `requireVerificationWhenCriteriaPresent` enforces "verification
1693
- * required iff successCriteria present" at task-output validation time
1694
- * (server-side schema check). Self-assessment is a truthful self-rating,
1695
- * NOT enforcement — `verification.passed=false` does not block /complete
1696
- * and does not affect `acceptedAttemptN`. See
1697
- * `docs/use/tasks-and-runtime.md` for the full producer/judge flow.
1698
- *
1699
- * **Binding evaluation** (judgment tasks: `assess_brief`, `judge_pack`).
1700
- * A separate task whose IS the application of `successCriteria` to
1701
- * someone else's output. Different agent (enforced at claim time), same
1702
- * envelope. The judge's verdict is binding: this is the *gate* in the
1703
- * MoltNet model. The rubric inside `successCriteria.rubric` IS the job
1704
- * spec for the judge.
1705
- *
1706
- * The clean chain: producer task with `successCriteria` → producer
1707
- * self-assesses honestly → proposer (or automation) creates a downstream
1708
- * judgment task that references the same `successCriteria` (or a
1709
- * stricter rubric) → judgment task delivers the binding verdict.
1710
- *
1711
- * Storage: SuccessCriteria lives inline at `task.input.successCriteria`,
1712
- * pinned via the task's `inputCid`. No separate column or hash. When
1713
- * #881 lands, the `rubric` field can graduate to `{ rubricCid }` lookup
1714
- * without changing this envelope, and producer + judge tasks can pin
1715
- * the SAME rubric across the chain for end-to-end auditability.
1737
+ * Tool-policy enforcement mode for the profile's runtime `tool_call` gate:
1738
+ * `off` (inert), `watch` (audit only), `enforce` (block disallowed tools,
1739
+ * fail-closed). Read by the daemon via `GET /runtime-profiles/:id/allowed-tools`.
1716
1740
  */
1717
- var SchemaCheckSpec = Type.Object({ schemaCid: Type.String({ minLength: 1 }) }, { additionalProperties: false });
1718
- var CidEqualsSpec = Type.Object({
1719
- path: Type.String({ minLength: 1 }),
1720
- expected: Type.String({ minLength: 1 })
1721
- }, { additionalProperties: false });
1722
- var SubmitToolCallGate = Type.Object({
1723
- id: Type.String({ minLength: 1 }),
1724
- kind: Type.Literal("submit-tool-call"),
1725
- description: Type.String({ minLength: 1 }),
1726
- required: Type.Boolean()
1727
- }, { additionalProperties: false });
1728
- var Gate = Type.Union([
1729
- SubmitToolCallGate,
1730
- Type.Object({
1731
- id: Type.String({ minLength: 1 }),
1732
- kind: Type.Literal("schema-check"),
1733
- spec: SchemaCheckSpec,
1734
- required: Type.Boolean()
1735
- }, { additionalProperties: false }),
1736
- Type.Object({
1737
- id: Type.String({ minLength: 1 }),
1738
- kind: Type.Literal("cid-equals"),
1739
- spec: CidEqualsSpec,
1740
- required: Type.Boolean()
1741
- }, { additionalProperties: false })
1742
- ], { $id: "Gate" });
1743
- var AssertionOp = Type.Union([
1744
- Type.Literal("exists"),
1745
- Type.Literal("equals"),
1746
- Type.Literal("matches"),
1747
- Type.Literal("in-range"),
1748
- Type.Literal("min-length")
1749
- ], { $id: "AssertionOp" });
1750
- var Assertion = Type.Object({
1751
- id: Type.String({ minLength: 1 }),
1752
- path: Type.String({ minLength: 1 }),
1753
- op: AssertionOp,
1754
- value: Type.Optional(Type.Unknown())
1755
- }, {
1756
- $id: "Assertion",
1757
- additionalProperties: false
1741
+ var RuntimeProfileToolEnforcement = ToolEnforcementSchema;
1742
+ var RuntimeProfileAllowedWorkspaceModes = Type.Array(RuntimeProfileWorkspaceMode, {
1743
+ minItems: 1,
1744
+ maxItems: 3,
1745
+ uniqueItems: true
1758
1746
  });
1759
- var SideEffectsSpec = Type.Object({
1760
- diaryEntryRequired: Type.Optional(Type.Boolean()),
1761
- diaryEntryTags: Type.Optional(Type.Array(Type.String({ minLength: 1 }))),
1762
- referencedEntries: Type.Optional(Type.Integer({ minimum: 0 }))
1763
- }, {
1764
- $id: "SideEffectsSpec",
1765
- additionalProperties: false
1747
+ var RuntimeProfileThinkingLevelOptions = [
1748
+ Type.Literal("off"),
1749
+ Type.Literal("minimal"),
1750
+ Type.Literal("low"),
1751
+ Type.Literal("medium"),
1752
+ Type.Literal("high"),
1753
+ Type.Literal("xhigh")
1754
+ ];
1755
+ Type.Union([...RuntimeProfileThinkingLevelOptions]);
1756
+ var RuntimeProfileNullableThinkingLevel = Type.Union([...RuntimeProfileThinkingLevelOptions, Type.Null()]);
1757
+ var RuntimeProfileNullableTemperature = Type.Union([Type.Null(), Type.Number({
1758
+ minimum: 0,
1759
+ maximum: 2
1760
+ })]);
1761
+ var RuntimeProfileNullableTopP = Type.Union([Type.Null(), Type.Number({
1762
+ minimum: 0,
1763
+ maximum: 1
1764
+ })]);
1765
+ var RuntimeProfileNullableTopK = Type.Union([Type.Integer({
1766
+ minimum: 1,
1767
+ maximum: 1e4
1768
+ }), Type.Null()]);
1769
+ var RuntimeProfileNullableMaxOutputTokens = Type.Union([Type.Integer({
1770
+ minimum: 1,
1771
+ maximum: 1e6
1772
+ }), Type.Null()]);
1773
+ var RuntimeProfileAllowedHost = Type.String({
1774
+ minLength: 1,
1775
+ maxLength: 255,
1776
+ pattern: "^(?:\\*\\.)?(?:[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?)(?:\\.(?:[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?))*$"
1766
1777
  });
1767
- var SuccessCriteria = Type.Object({
1768
- version: Type.Literal(1),
1769
- gates: Type.Optional(Type.Array(Gate)),
1770
- assertions: Type.Optional(Type.Array(Assertion)),
1771
- rubric: Type.Optional(Rubric),
1772
- minComposite: Type.Optional(Type.Number({
1773
- minimum: 0,
1774
- maximum: 1
1775
- })),
1776
- sideEffects: Type.Optional(SideEffectsSpec)
1778
+ var RuntimeProfileSandbox = Type.Object({
1779
+ network: Type.Optional(Type.Object({
1780
+ allowedHosts: Type.Optional(Type.Array(RuntimeProfileAllowedHost, { maxItems: 50 })),
1781
+ allowedInternalHosts: Type.Optional(Type.Array(RuntimeProfileAllowedHost, { maxItems: 50 }))
1782
+ }, { additionalProperties: false })),
1783
+ vfs: Type.Optional(Type.Object({
1784
+ shadow: Type.Optional(Type.Array(Type.String({
1785
+ minLength: 1,
1786
+ maxLength: 255
1787
+ }), { maxItems: 100 })),
1788
+ shadowMode: Type.Optional(Type.Union([Type.Literal("deny"), Type.Literal("tmpfs")]))
1789
+ }, { additionalProperties: false })),
1790
+ env: Type.Optional(Type.Record(RuntimeProfileEnvName, Type.String({ maxLength: 4096 }))),
1791
+ hostExec: Type.Optional(Type.Object({ autoApprove: Type.Optional(Type.Literal(false)) }, { additionalProperties: false })),
1792
+ resources: Type.Optional(Type.Object({
1793
+ memory: Type.Optional(Type.String({
1794
+ minLength: 2,
1795
+ maxLength: 16,
1796
+ pattern: "^[0-9]+[KMG]?$"
1797
+ })),
1798
+ cpus: Type.Optional(Type.Integer({
1799
+ minimum: 1,
1800
+ maximum: 32
1801
+ }))
1802
+ }, { additionalProperties: false }))
1777
1803
  }, {
1778
- $id: "SuccessCriteria",
1804
+ $id: "RuntimeProfileSandbox",
1779
1805
  additionalProperties: false
1780
1806
  });
1781
- var VerificationResultStatus = Type.Union([
1782
- Type.Literal("pass"),
1783
- Type.Literal("fail"),
1784
- Type.Literal("skip")
1785
- ], { $id: "VerificationResultStatus" });
1786
- var VerificationResultKind = Type.Union([
1787
- Type.Literal("gate"),
1788
- Type.Literal("assertion"),
1789
- Type.Literal("rubric"),
1790
- Type.Literal("sideEffect")
1791
- ], { $id: "VerificationResultKind" });
1792
- var VerificationResult = Type.Object({
1793
- id: Type.String({ minLength: 1 }),
1794
- kind: VerificationResultKind,
1795
- status: VerificationResultStatus,
1796
- detail: Type.Optional(Type.String())
1807
+ var RuntimeProfileContext = Type.Object({
1808
+ slug: Type.String({
1809
+ minLength: 1,
1810
+ maxLength: 64,
1811
+ pattern: "^[a-zA-Z0-9_-]+$"
1812
+ }),
1813
+ binding: Type.Union([
1814
+ Type.Literal("skill"),
1815
+ Type.Literal("context_inline"),
1816
+ Type.Literal("prompt_prefix"),
1817
+ Type.Literal("user_inline")
1818
+ ]),
1819
+ content: Type.String({
1820
+ minLength: 1,
1821
+ maxLength: 65536
1822
+ })
1797
1823
  }, {
1798
- $id: "VerificationResult",
1824
+ $id: "RuntimeProfileContext",
1799
1825
  additionalProperties: false
1800
1826
  });
1801
- var VerificationRecord = Type.Object({
1802
- inputCid: Type.String({ minLength: 1 }),
1803
- results: Type.Array(VerificationResult),
1804
- passed: Type.Boolean({ description: "True iff every verification result has status \"pass\" or \"skip\"; false when any result has status \"fail\"." })
1805
- }, {
1806
- $id: "VerificationRecord",
1827
+ var RuntimeProfileRef = Type.Object({ profileId: Type.String({ format: "uuid" }) }, {
1828
+ $id: "RuntimeProfileRef",
1807
1829
  additionalProperties: false
1808
1830
  });
1809
- //#endregion
1810
- //#region ../../libs/tasks/src/task-artifacts.ts
1811
- var TaskArtifact = Type.Object({
1831
+ var RuntimeProfileLeaseTtlSec = Type.Integer({
1832
+ minimum: 1,
1833
+ maximum: 86400
1834
+ });
1835
+ var RuntimeProfileHeartbeatIntervalMs = Type.Integer({
1836
+ minimum: 0,
1837
+ maximum: 36e5
1838
+ });
1839
+ var RuntimeProfileMaxBatchSize = Type.Integer({
1840
+ minimum: 1,
1841
+ maximum: 1e3
1842
+ });
1843
+ var RuntimeProfileMaxTurns = Type.Integer({
1844
+ minimum: 0,
1845
+ maximum: 1e4
1846
+ });
1847
+ var RuntimeProfileMaxBashTimeouts = Type.Integer({
1848
+ minimum: 0,
1849
+ maximum: 1e3
1850
+ });
1851
+ Type.Object({
1812
1852
  id: Type.String({ format: "uuid" }),
1813
1853
  teamId: Type.String({ format: "uuid" }),
1814
- taskId: Type.String({ format: "uuid" }),
1815
- attemptN: Type.Union([Type.Integer({ minimum: 1 }), Type.Null()]),
1816
- kind: Type.String({
1854
+ name: RuntimeProfileName,
1855
+ description: Type.Union([Type.String({ maxLength: 4096 }), Type.Null()]),
1856
+ provider: Type.String({
1817
1857
  minLength: 1,
1818
1858
  maxLength: 100
1819
1859
  }),
1820
- title: Type.String({
1821
- minLength: 1,
1822
- maxLength: 255
1823
- }),
1824
- contentType: Type.String({
1860
+ model: Type.String({
1825
1861
  minLength: 1,
1826
1862
  maxLength: 200
1827
1863
  }),
1828
- contentEncoding: Type.Union([Type.String({
1829
- minLength: 1,
1830
- maxLength: 100
1831
- }), Type.Null()]),
1832
- sizeBytes: Type.Integer({ minimum: 0 }),
1833
- cid: Type.String({
1864
+ thinkingLevel: RuntimeProfileNullableThinkingLevel,
1865
+ temperature: RuntimeProfileNullableTemperature,
1866
+ topP: RuntimeProfileNullableTopP,
1867
+ topK: RuntimeProfileNullableTopK,
1868
+ maxOutputTokens: RuntimeProfileNullableMaxOutputTokens,
1869
+ runtimeKind: RuntimeProfileRuntimeKind,
1870
+ sandbox: RuntimeProfileSandbox,
1871
+ sessionStorageMode: Type.Literal("local"),
1872
+ workspaceStorageMode: Type.Literal("local"),
1873
+ defaultWorkspaceMode: Type.Union([RuntimeProfileWorkspaceMode, Type.Null()]),
1874
+ allowedWorkspaceModes: RuntimeProfileAllowedWorkspaceModes,
1875
+ sessionTtlSec: Type.Integer({
1876
+ minimum: 1,
1877
+ maximum: 86400
1878
+ }),
1879
+ workspaceTtlSec: Type.Integer({
1880
+ minimum: 1,
1881
+ maximum: 86400
1882
+ }),
1883
+ leaseTtlSec: RuntimeProfileLeaseTtlSec,
1884
+ heartbeatIntervalMs: RuntimeProfileHeartbeatIntervalMs,
1885
+ maxBatchSize: RuntimeProfileMaxBatchSize,
1886
+ maxTurns: RuntimeProfileMaxTurns,
1887
+ maxBashTimeouts: RuntimeProfileMaxBashTimeouts,
1888
+ toolEnforcement: RuntimeProfileToolEnforcement,
1889
+ requiredEnv: Type.Array(RuntimeProfileEnvName, { maxItems: 100 }),
1890
+ requiredTools: Type.Array(RuntimeProfileToolName, { maxItems: 100 }),
1891
+ requiredExecutables: Type.Array(RuntimeProfileToolName, { maxItems: 100 }),
1892
+ context: Type.Array(RuntimeProfileContext, { maxItems: 5 }),
1893
+ revision: Type.Integer({ minimum: 1 }),
1894
+ definitionCid: Type.String({
1834
1895
  minLength: 1,
1835
1896
  maxLength: 100
1836
1897
  }),
1837
1898
  createdByAgentId: Type.Union([Type.String({ format: "uuid" }), Type.Null()]),
1838
- expiresAt: Type.Union([Type.String({ format: "date-time" }), Type.Null()]),
1839
- createdAt: Type.String({ format: "date-time" })
1840
- }, { $id: "TaskArtifact" });
1841
- Type.Object({
1842
- artifacts: Type.Array(TaskArtifact),
1843
- nextCursor: Type.Union([Type.String({ minLength: 1 }), Type.Null()])
1844
- }, { $id: "TaskArtifactList" });
1845
- Type.Object({
1846
- limit: Type.Optional(Type.Integer({
1847
- minimum: 1,
1848
- maximum: 100
1849
- })),
1850
- cursor: Type.Optional(Type.String({ minLength: 1 }))
1899
+ createdByHumanId: Type.Union([Type.String({ format: "uuid" }), Type.Null()]),
1900
+ createdAt: Type.String({ format: "date-time" }),
1901
+ updatedAt: Type.String({ format: "date-time" })
1851
1902
  }, {
1852
- $id: "ListTaskArtifactsQuery",
1903
+ $id: "RuntimeProfile",
1853
1904
  additionalProperties: false
1854
1905
  });
1855
- var HeaderSafeContentType = Type.String({
1856
- minLength: 1,
1857
- maxLength: 200,
1858
- pattern: "^[\\x21-\\x7e][\\x20-\\x7e]*$"
1859
- });
1860
- var HeaderSafeContentEncoding = Type.String({
1861
- minLength: 1,
1862
- maxLength: 100,
1863
- pattern: "^[\\x21-\\x7e][\\x20-\\x7e]*$"
1864
- });
1906
+ //#endregion
1907
+ //#region ../../libs/runtime-profiles/src/runtime-sessions.ts
1908
+ var RuntimeSessionKind = Type.Union([
1909
+ Type.Literal("root"),
1910
+ Type.Literal("extend"),
1911
+ Type.Literal("fork")
1912
+ ]);
1913
+ var RuntimeSessionCheckpointKind = Type.Union([Type.Literal("attempt_final")]);
1865
1914
  Type.Object({
1866
- kind: Type.String({
1915
+ id: Type.String({ format: "uuid" }),
1916
+ teamId: Type.String({ format: "uuid" }),
1917
+ taskId: Type.String({ format: "uuid" }),
1918
+ attemptN: Type.Integer({ minimum: 1 }),
1919
+ sourceSlotId: Type.Union([Type.String({ format: "uuid" }), Type.Null()]),
1920
+ sourceRuntimeProfileId: Type.Union([Type.String({ format: "uuid" }), Type.Null()]),
1921
+ sessionKind: RuntimeSessionKind,
1922
+ parentSessionId: Type.Union([Type.String({ format: "uuid" }), Type.Null()]),
1923
+ contentType: Type.String({
1924
+ minLength: 1,
1925
+ maxLength: 200
1926
+ }),
1927
+ contentEncoding: Type.Union([Type.String({
1867
1928
  minLength: 1,
1868
1929
  maxLength: 100
1930
+ }), Type.Null()]),
1931
+ sizeBytes: Type.Integer({ minimum: 0 }),
1932
+ sha256: Type.String({
1933
+ minLength: 64,
1934
+ maxLength: 64
1869
1935
  }),
1870
- title: Type.String({
1936
+ storageClass: Type.String({
1871
1937
  minLength: 1,
1872
- maxLength: 255
1938
+ maxLength: 100
1873
1939
  }),
1874
- contentType: Type.Optional(HeaderSafeContentType),
1875
- contentEncoding: Type.Optional(HeaderSafeContentEncoding)
1940
+ checkpointKind: RuntimeSessionCheckpointKind,
1941
+ uploadedAt: Type.String({ format: "date-time" })
1942
+ }, { $id: "RuntimeSession" });
1943
+ Type.Object({
1944
+ sourceSlotId: Type.Optional(Type.String({ format: "uuid" })),
1945
+ sourceRuntimeProfileId: Type.Optional(Type.String({ format: "uuid" })),
1946
+ sessionKind: RuntimeSessionKind,
1947
+ parentSessionId: Type.Optional(Type.String({ format: "uuid" }))
1876
1948
  }, {
1877
- $id: "UploadTaskArtifactQuery",
1949
+ $id: "UploadRuntimeSessionQuery",
1878
1950
  additionalProperties: false
1879
1951
  });
1880
1952
  Type.String({
1881
- $id: "TaskArtifactContent",
1882
- description: "Task artifact content stream.",
1953
+ $id: "RuntimeSessionContent",
1954
+ description: "Runtime session content stream.",
1883
1955
  format: "binary"
1884
1956
  });
1885
- Type.Object({ taskId: Type.String({ format: "uuid" }) }, {
1886
- $id: "TaskArtifactTaskParams",
1887
- additionalProperties: false
1888
- });
1889
1957
  Type.Object({
1890
1958
  taskId: Type.String({ format: "uuid" }),
1891
1959
  attemptN: Type.Integer({ minimum: 1 })
1892
1960
  }, {
1893
- $id: "TaskArtifactAttemptParams",
1961
+ $id: "RuntimeSessionAttemptParams",
1894
1962
  additionalProperties: false
1895
1963
  });
1896
- Type.Object({
1897
- taskId: Type.String({ format: "uuid" }),
1898
- attemptN: Type.Integer({ minimum: 1 }),
1899
- cid: Type.String({
1964
+ //#endregion
1965
+ //#region ../../libs/runtime-profiles/src/runtime-slots.ts
1966
+ var RuntimeWorkspaceKind = Type.Union([
1967
+ Type.Literal("origin"),
1968
+ Type.Literal("fork"),
1969
+ Type.Literal("scratch")
1970
+ ]);
1971
+ var RuntimeSlotState = Type.Union([Type.Literal("active"), Type.Literal("idle")]);
1972
+ var RuntimeWorkspace = Type.Object({
1973
+ id: Type.String({ format: "uuid" }),
1974
+ teamId: Type.String({ format: "uuid" }),
1975
+ workspaceId: Type.String({ minLength: 1 }),
1976
+ worktreePath: Type.String({ minLength: 1 }),
1977
+ worktreeBranch: Type.Union([Type.String({ minLength: 1 }), Type.Null()]),
1978
+ kind: RuntimeWorkspaceKind,
1979
+ createdAtMs: Type.Integer({ minimum: 0 }),
1980
+ lastUsedAtMs: Type.Integer({ minimum: 0 })
1981
+ }, { $id: "RuntimeWorkspace" });
1982
+ var RuntimeSlot = Type.Object({
1983
+ id: Type.String({ format: "uuid" }),
1984
+ teamId: Type.String({ format: "uuid" }),
1985
+ agentName: Type.String({
1900
1986
  minLength: 1,
1901
1987
  maxLength: 100
1902
- })
1903
- }, {
1904
- $id: "TaskArtifactContentParams",
1905
- additionalProperties: false
1906
- });
1907
- Type.Object({
1908
- contentType: Type.Optional(HeaderSafeContentType),
1909
- contentEncoding: Type.Optional(HeaderSafeContentEncoding)
1910
- }, {
1911
- $id: "StageTaskArtifactQuery",
1912
- additionalProperties: false
1913
- });
1988
+ }),
1989
+ runtimeProfileId: Type.Union([Type.String({ format: "uuid" }), Type.Null()]),
1990
+ provider: Type.String({
1991
+ minLength: 1,
1992
+ maxLength: 100
1993
+ }),
1994
+ model: Type.String({
1995
+ minLength: 1,
1996
+ maxLength: 200
1997
+ }),
1998
+ slotKey: Type.String({ minLength: 1 }),
1999
+ taskType: Type.String({
2000
+ minLength: 1,
2001
+ maxLength: 100
2002
+ }),
2003
+ state: RuntimeSlotState,
2004
+ lastTaskId: Type.String({ format: "uuid" }),
2005
+ lastAttemptN: Type.Integer({ minimum: 1 }),
2006
+ sessionDir: Type.Union([Type.String({ minLength: 1 }), Type.Null()]),
2007
+ sessionPath: Type.Union([Type.String({ minLength: 1 }), Type.Null()]),
2008
+ workspaceRowId: Type.Union([Type.String({ format: "uuid" }), Type.Null()]),
2009
+ createdAtMs: Type.Integer({ minimum: 0 }),
2010
+ lastUsedAtMs: Type.Integer({ minimum: 0 }),
2011
+ expiresAtMs: Type.Integer({ minimum: 0 })
2012
+ }, { $id: "RuntimeSlot" });
2013
+ var ResolvedRuntimeSlot = Type.Object({
2014
+ slot: RuntimeSlot,
2015
+ workspace: Type.Union([RuntimeWorkspace, Type.Null()])
2016
+ }, { $id: "ResolvedRuntimeSlot" });
2017
+ Type.Object({ items: Type.Array(ResolvedRuntimeSlot) }, { $id: "RuntimeSlotListResponse" });
1914
2018
  Type.Object({
1915
- cid: Type.String({
2019
+ agentName: Type.String({
1916
2020
  minLength: 1,
1917
2021
  maxLength: 100
1918
2022
  }),
1919
- sizeBytes: Type.Integer({ minimum: 0 }),
1920
- contentType: Type.String({
2023
+ runtimeProfileId: Type.String({ format: "uuid" }),
2024
+ provider: Type.String({
2025
+ minLength: 1,
2026
+ maxLength: 100
2027
+ }),
2028
+ model: Type.String({
1921
2029
  minLength: 1,
1922
2030
  maxLength: 200
1923
- })
1924
- }, { $id: "StagedTaskArtifact" });
1925
- Type.Object({
1926
- taskId: Type.String({ format: "uuid" }),
1927
- cid: Type.String({
2031
+ }),
2032
+ slotKey: Type.String({ minLength: 1 }),
2033
+ taskType: Type.String({
1928
2034
  minLength: 1,
1929
2035
  maxLength: 100
1930
- })
1931
- }, {
1932
- $id: "TaskArtifactTaskContentParams",
1933
- additionalProperties: false
1934
- });
1935
- //#endregion
1936
- //#region ../../libs/tasks/src/task-types/assess-brief.ts
1937
- /**
1938
- * `assess_brief` — independently evaluate a fulfilled brief.
1939
- *
1940
- * output_kind: judgment
1941
- * criteria: required (`successCriteria.rubric` — same envelope as
1942
- * `judge_pack`)
1943
- * references: required (must reference the target `fulfill_brief` task)
1944
- *
1945
- * The assessor is a different agent from the producer (enforced by the
1946
- * server / runtime at claim time — not in the wire schema).
1947
- *
1948
- * The rubric in `successCriteria` IS the job spec — the assessor applies
1949
- * it to the target task's output and emits per-criterion scores. Other
1950
- * sections (`assertions`, `gates`, `sideEffects`) MAY be present and are
1951
- * evaluated against the *assessor's output*.
1952
- */
1953
- var ASSESS_BRIEF_TYPE = "assess_brief";
1954
- var AssessBriefInput = Type.Object({
1955
- targetTaskId: Type.String({ format: "uuid" }),
1956
- successCriteria: SuccessCriteria
1957
- }, {
1958
- $id: "AssessBriefInput",
1959
- additionalProperties: false
1960
- });
1961
- /** One score line. */
1962
- var AssessBriefScore = Type.Object({
1963
- criterionId: Type.String({ minLength: 1 }),
1964
- score: Type.Number({
1965
- minimum: 0,
1966
- maximum: 1
1967
2036
  }),
1968
- rationale: Type.Optional(Type.String()),
1969
- evidence: Type.Optional(Type.Object({
1970
- commitsVerified: Type.Number(),
1971
- commitsTotal: Type.Number(),
1972
- signatureFailures: Type.Array(Type.String())
1973
- }, { additionalProperties: false }))
2037
+ sessionDir: Type.Optional(Type.String({ minLength: 1 })),
2038
+ sessionPath: Type.Optional(Type.String({ minLength: 1 })),
2039
+ workspaceId: Type.Optional(Type.String({ minLength: 1 })),
2040
+ worktreePath: Type.Optional(Type.String({ minLength: 1 })),
2041
+ worktreeBranch: Type.Optional(Type.String({ minLength: 1 })),
2042
+ workspaceKind: Type.Optional(RuntimeWorkspaceKind),
2043
+ lastTaskId: Type.String({ format: "uuid" }),
2044
+ lastAttemptN: Type.Integer({ minimum: 1 })
1974
2045
  }, {
1975
- $id: "AssessBriefScore",
2046
+ $id: "BeginRuntimeSlotBody",
1976
2047
  additionalProperties: false
1977
2048
  });
1978
- var AssessBriefOutput = Type.Object({
1979
- scores: Type.Array(AssessBriefScore, { minItems: 1 }),
1980
- composite: Type.Number({
1981
- minimum: 0,
1982
- maximum: 1
2049
+ Type.Object({
2050
+ agentName: Type.String({
2051
+ minLength: 1,
2052
+ maxLength: 100
1983
2053
  }),
1984
- verdict: Type.String({ minLength: 1 }),
1985
- judgeModel: Type.Optional(Type.String())
2054
+ runtimeProfileId: Type.String({ format: "uuid" }),
2055
+ provider: Type.String({
2056
+ minLength: 1,
2057
+ maxLength: 100
2058
+ }),
2059
+ model: Type.String({
2060
+ minLength: 1,
2061
+ maxLength: 200
2062
+ }),
2063
+ slotKey: Type.String({ minLength: 1 }),
2064
+ taskId: Type.String({ format: "uuid" }),
2065
+ attemptN: Type.Integer({ minimum: 1 }),
2066
+ sessionPath: Type.Optional(Type.String({ minLength: 1 }))
1986
2067
  }, {
1987
- $id: "AssessBriefOutput",
2068
+ $id: "FinishRuntimeSlotBody",
1988
2069
  additionalProperties: false
1989
2070
  });
1990
- /**
1991
- * Async preflight (#1096):
1992
- * - `targetTaskId` resolves to a real task the caller can see.
1993
- * - The target is a `fulfill_brief` (you cannot grade an arbitrary
1994
- * task type as if it were a brief fulfillment).
1995
- * - Unless readiness checks are explicitly deferred, the target is
1996
- * `completed` with an accepted attempt — grading an in-flight or
1997
- * failed task would either race or grade nothing.
1998
- *
1999
- * Agent-distinctness ("assessor ≠ producer") is a runtime / auth-
2000
- * layer concern and intentionally NOT checked here. It belongs in
2001
- * an auth-aware claim-time check.
2002
- */
2003
- async function validateAssessBriefInputAsync(input, ctx) {
2004
- const { targetTaskId } = input;
2005
- const errors = [];
2006
- const target = await ctx.resolveTask(targetTaskId);
2007
- if (!target) {
2008
- errors.push({
2009
- field: "targetTaskId",
2010
- message: `targetTaskId ${targetTaskId} does not resolve to a task you can read`
2011
- });
2012
- return errors;
2013
- }
2014
- if (target.taskType !== "fulfill_brief") errors.push({
2015
- field: "targetTaskId",
2016
- message: `targetTaskId ${targetTaskId} is a ${target.taskType}, not a fulfill_brief`
2017
- });
2018
- if (!ctx.deferReadinessChecks && (target.status !== "completed" || target.acceptedAttemptN === null)) errors.push({
2019
- field: "targetTaskId",
2020
- message: `targetTaskId ${targetTaskId} is not completed with an accepted attempt (status=${target.status}, acceptedAttemptN=${target.acceptedAttemptN})`
2021
- });
2022
- return errors;
2023
- }
2024
- //#endregion
2025
- //#region ../../libs/tasks/src/task-types/curate-pack.ts
2026
- /**
2027
- * `curate_pack` — select and rank diary entries into a context pack.
2028
- *
2029
- * output_kind: artifact
2030
- * criteria: not required (rubric-less curation recipe)
2031
- * references: optional (e.g. a prior rendered pack being re-curated)
2032
- *
2033
- * This is step 1 of the three-session attribution loop (#875). The agent
2034
- * runs a structured exploration over a diary — tag inventory, hybrid
2035
- * search, type/tag narrowing — and emits a ranked entry list via
2036
- * `moltnet_pack_create`. The prompt is deterministic given the input
2037
- * (no operator interaction), so two runs with the same input should
2038
- * converge on similar packs.
2039
- *
2040
- * Related: `render_pack`, `judge_pack`.
2041
- */
2042
- var CURATE_PACK_TYPE = "curate_pack";
2043
- var EntryTypeFilter = Type.Union([
2044
- Type.Literal("episodic"),
2045
- Type.Literal("semantic"),
2046
- Type.Literal("procedural"),
2047
- Type.Literal("reflection")
2048
- ]);
2049
- var CuratePackInput = Type.Object({
2050
- diaryId: Type.String({ format: "uuid" }),
2051
- taskPrompt: Type.String({ minLength: 1 }),
2052
- entryTypes: Type.Optional(Type.Array(EntryTypeFilter, { minItems: 1 })),
2053
- tagFilters: Type.Optional(Type.Object({
2054
- include: Type.Optional(Type.Array(Type.String())),
2055
- exclude: Type.Optional(Type.Array(Type.String())),
2056
- prefix: Type.Optional(Type.String())
2057
- }, { additionalProperties: false })),
2058
- tokenBudget: Type.Optional(Type.Number({ minimum: 500 })),
2059
- recipe: Type.Optional(Type.Union([Type.Literal("topic-focused-v1"), Type.Literal("scope-inventory-v1")])),
2060
- successCriteria: Type.Optional(SuccessCriteria)
2071
+ Type.Object({
2072
+ taskId: Type.String({ format: "uuid" }),
2073
+ attemptN: Type.Integer({ minimum: 1 })
2061
2074
  }, {
2062
- $id: "CuratePackInput",
2075
+ $id: "FindLatestRuntimeSlotForAttemptQuery",
2063
2076
  additionalProperties: false
2064
2077
  });
2065
- /**
2066
- * Index of the curated pack plus the reasoning trace. The pack itself
2067
- * lives in the database (created via `moltnet_pack_create`); this output
2068
- * is the receipt.
2069
- */
2070
- var CuratePackOutput = Type.Object({
2071
- packId: Type.String({ format: "uuid" }),
2072
- packCid: Type.String({ minLength: 1 }),
2073
- entries: Type.Array(Type.Object({
2074
- entryId: Type.String({ format: "uuid" }),
2075
- rank: Type.Number({ minimum: 1 }),
2076
- rationale: Type.String({ minLength: 1 })
2077
- }, { additionalProperties: false }), { minItems: 1 }),
2078
- recipeParams: Type.Record(Type.String(), Type.Unknown()),
2079
- checkpoints: Type.Optional(Type.Array(Type.Object({
2080
- phase: Type.String({ minLength: 1 }),
2081
- candidateIds: Type.Array(Type.String({ format: "uuid" })),
2082
- droppedIds: Type.Optional(Type.Array(Type.String({ format: "uuid" }))),
2083
- notes: Type.String({ minLength: 1 })
2084
- }, { additionalProperties: false }))),
2085
- summary: Type.String({ minLength: 1 }),
2086
- verification: Type.Optional(VerificationRecord)
2078
+ Type.Object({
2079
+ agentName: Type.Optional(Type.String({
2080
+ minLength: 1,
2081
+ maxLength: 100
2082
+ })),
2083
+ runtimeProfileId: Type.Optional(Type.String({ format: "uuid" })),
2084
+ state: Type.Optional(RuntimeSlotState),
2085
+ limit: Type.Optional(Type.Integer({
2086
+ minimum: 1,
2087
+ maximum: 200
2088
+ }))
2087
2089
  }, {
2088
- $id: "CuratePackOutput",
2090
+ $id: "ListRuntimeSlotsQuery",
2089
2091
  additionalProperties: false
2090
2092
  });
2091
2093
  //#endregion
@@ -3250,7 +3252,7 @@ Type.Object({
3250
3252
  allowedProfiles: Type.Array(RuntimeProfileRef, { maxItems: 16 }),
3251
3253
  status: TaskStatus,
3252
3254
  queuedAt: IsoTimestamp,
3253
- completedAt: Type.Union([IsoTimestamp, Type.Null()]),
3255
+ completedAt: Type.Union([IsoTimestamp, Type.Null()], { description: "First time the task entered completed, failed, cancelled, or expired; null until terminal." }),
3254
3256
  expiresAt: Type.Union([IsoTimestamp, Type.Null()]),
3255
3257
  cancelledByAgentId: Type.Union([Uuid, Type.Null()]),
3256
3258
  cancelledByHumanId: Type.Union([Uuid, Type.Null()]),
@@ -3360,9 +3362,9 @@ var COMMON_OPTIONAL_FLAGS = `\
3360
3362
  --guest-credential-mode <mode>
3361
3363
  Guest trust boundary: host-authenticated or
3362
3364
  guest-config. Defaults to host-authenticated for
3363
- agent-key and guest-config for OAuth2. Explicit
3364
- guest-config exposes the complete local agent
3365
- credential tree to the VM.
3365
+ both agent-key and OAuth2 authentication.
3366
+ Explicit guest-config exposes the complete local
3367
+ agent credential tree to the VM.
3366
3368
  --lease-ttl-sec <n> Sliding liveness window. Silence longer than
3367
3369
  this ends the attempt with lease_expired.
3368
3370
  Default: 300.
@@ -3538,16 +3540,18 @@ function isHelpFlag(args) {
3538
3540
  //#region src/lib/agent-context.ts
3539
3541
  /**
3540
3542
  * Guest credentials are an explicit trust decision, never an incidental
3541
- * consequence of files found on disk. Agent-key mode defaults to the
3542
- * configless host-authenticated boundary; OAuth2 keeps its config-backed
3543
- * behavior. OAuth2 cannot use the host-authenticated mode because its Agent is
3544
- * itself resolved from the local credential tree.
3543
+ * consequence of files found on disk. The guest boundary is independent of
3544
+ * how the daemon itself authenticates: both agent-key and OAuth2 default to
3545
+ * the host-authenticated boundary, where structured MoltNet operations reuse
3546
+ * the trusted host-side Agent and the guest receives no credential material.
3547
+ * OAuth2 still resolves that Agent from the local config and secret provider
3548
+ * on the host — reading `moltnet.json` on the host does not imply projecting
3549
+ * it into the guest. `guest-config` remains an explicit compatibility opt-in
3550
+ * for tasks that need credential-bearing guest-shell operations.
3545
3551
  */
3546
- function resolveDaemonGuestCredentialMode(authMode, requested) {
3552
+ function resolveDaemonGuestCredentialMode(requested) {
3547
3553
  if (requested !== void 0 && requested !== "guest-config" && requested !== "host-authenticated") throw new Error(`Invalid --guest-credential-mode "${requested}": expected guest-config or host-authenticated.`);
3548
- const mode = requested ?? (authMode === "agent-key" ? "host-authenticated" : "guest-config");
3549
- if (authMode === "oauth2" && mode === "host-authenticated") throw new Error("--guest-credential-mode host-authenticated requires agent-key authentication. OAuth2 requires the local agent configuration.");
3550
- return mode;
3554
+ return requested ?? "host-authenticated";
3551
3555
  }
3552
3556
  /**
3553
3557
  * Report which auth mode `connect()` will use, without ever reading the secret
@@ -3568,18 +3572,18 @@ function detectAuthMode(env) {
3568
3572
  *
3569
3573
  * Rules (see design entry edb848a1):
3570
3574
  * - The subject must be an `agent`; a human credential can never run the daemon.
3571
- * - A team-bound agent key (`credentialBinding.boundTeamId` set) must match the
3575
+ * - A team-bound agent key (`credentialBinding.bindingScope === 'team'`) must match the
3572
3576
  * `--team` the daemon was started with. A key is an immutable team ceiling, so
3573
3577
  * a mismatch would only surface as an obscure mid-poll 403 otherwise.
3574
- * - An unbound key or an OAuth2 identity (no `boundTeamId`) is accepted; normal
3575
- * team-scoped authorization governs those requests.
3578
+ * - An identity-scoped key or an OAuth2 identity is accepted; normal team-scoped
3579
+ * authorization governs those requests.
3576
3580
  */
3577
3581
  function assessStartupBinding(whoami, teamId) {
3578
3582
  if (whoami.subjectType !== "agent") return {
3579
3583
  ok: false,
3580
3584
  reason: `the daemon must authenticate as an agent, but whoami reported subjectType "${whoami.subjectType}". Provide agent credentials (an agent key or the agent's client id/secret).`
3581
3585
  };
3582
- const boundTeamId = whoami.credentialBinding?.boundTeamId;
3586
+ const boundTeamId = whoami.credentialBinding?.bindingScope === "team" ? whoami.credentialBinding.boundTeamId : void 0;
3583
3587
  if (teamId && boundTeamId && boundTeamId !== teamId) return {
3584
3588
  ok: false,
3585
3589
  reason: `the agent key is bound to team ${boundTeamId}, but the daemon was started with --team ${teamId}. Restart with --team ${boundTeamId}, or issue a key for team ${teamId}.`
@@ -3621,8 +3625,8 @@ async function validateStartupBinding(options) {
3621
3625
  async function resolveAgentContext(agentName, options = {}) {
3622
3626
  if (!/^[a-zA-Z0-9_-]+$/.test(agentName)) throw new Error(`Invalid agent name "${agentName}": must match /^[a-zA-Z0-9_-]+$/`);
3623
3627
  const roots = resolveCredentialRoots(options.agentRootDir);
3628
+ const guestCredentialMode = resolveDaemonGuestCredentialMode(options.guestCredentialMode);
3624
3629
  if (options.authMode === "agent-key") {
3625
- const guestCredentialMode = resolveDaemonGuestCredentialMode("agent-key", options.guestCredentialMode);
3626
3630
  const { rootDir, agentDir } = guestCredentialMode === "guest-config" ? resolveCompleteGuestCredentials(roots, agentName) : {
3627
3631
  rootDir: roots[0] ?? process.cwd(),
3628
3632
  agentDir: join(roots[0] ?? process.cwd(), ".moltnet", agentName)
@@ -3634,17 +3638,17 @@ async function resolveAgentContext(agentName, options = {}) {
3634
3638
  guestCredentialMode
3635
3639
  };
3636
3640
  }
3637
- resolveDaemonGuestCredentialMode("oauth2", options.guestCredentialMode);
3638
- for (const rootDir of roots) {
3639
- const agentDir = join(rootDir, ".moltnet", agentName);
3640
- if (existsSync(join(agentDir, "moltnet.json"))) return {
3641
- agentDir,
3642
- agentRootDir: rootDir,
3643
- agent: await connect({
3644
- configDir: agentDir,
3645
- secretProviders: createNodeSecretProviderRegistry()
3646
- }),
3647
- guestCredentialMode: "guest-config"
3641
+ const located = guestCredentialMode === "guest-config" ? resolveCompleteGuestCredentials(roots, agentName) : locateAgentConfig(roots, agentName);
3642
+ if (located) {
3643
+ const agent = await connect({
3644
+ configDir: located.agentDir,
3645
+ secretProviders: createNodeSecretProviderRegistry()
3646
+ });
3647
+ return {
3648
+ agentDir: located.agentDir,
3649
+ agentRootDir: located.rootDir,
3650
+ agent,
3651
+ guestCredentialMode
3648
3652
  };
3649
3653
  }
3650
3654
  const tried = roots.map((root) => join(root, ".moltnet", agentName));
@@ -3656,6 +3660,15 @@ function isTransientWhoamiError(error) {
3656
3660
  const statusCode = error.statusCode;
3657
3661
  return typeof statusCode === "number" && (statusCode === 408 || statusCode === 429 || statusCode >= 500);
3658
3662
  }
3663
+ function locateAgentConfig(roots, agentName) {
3664
+ for (const rootDir of roots) {
3665
+ const agentDir = join(rootDir, ".moltnet", agentName);
3666
+ if (existsSync(join(agentDir, "moltnet.json"))) return {
3667
+ rootDir,
3668
+ agentDir
3669
+ };
3670
+ }
3671
+ }
3659
3672
  function resolveCompleteGuestCredentials(roots, agentName) {
3660
3673
  const partial = [];
3661
3674
  for (const rootDir of roots) {
@@ -5032,102 +5045,6 @@ function runWithDaemonRuntimeContext(context, callback) {
5032
5045
  return storage.run(context, callback);
5033
5046
  }
5034
5047
  //#endregion
5035
- //#region src/lib/runtime-profile.ts
5036
- var RuntimeProfilePrerequisiteError = class extends Error {
5037
- constructor(profileName, missingEnv, missingTools, missingExecutables) {
5038
- const parts = [
5039
- missingEnv.length > 0 ? `missing env: ${missingEnv.join(", ")}` : null,
5040
- missingTools.length > 0 ? `missing tools: ${missingTools.join(", ")}` : null,
5041
- missingExecutables.length > 0 ? `missing guest executables: ${missingExecutables.join(", ")}` : null
5042
- ].filter(Boolean);
5043
- super(`Runtime profile "${profileName}" prerequisites are not satisfied: ${parts.join("; ")}`);
5044
- this.profileName = profileName;
5045
- this.missingEnv = missingEnv;
5046
- this.missingTools = missingTools;
5047
- this.missingExecutables = missingExecutables;
5048
- this.name = "RuntimeProfilePrerequisiteError";
5049
- }
5050
- };
5051
- var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
5052
- async function resolveRuntimeProfile(options) {
5053
- const profile = UUID_RE.test(options.profile) ? await options.agent.runtimeProfiles.get(options.profile) : await resolveProfileByName(options);
5054
- if (options.teamId && profile.teamId !== options.teamId) throw new Error(`Runtime profile "${options.profile}" belongs to team ${profile.teamId}, not ${options.teamId}.`);
5055
- if (!Value.Check(RuntimeProfileSandbox, profile.sandbox)) throw new Error(`Runtime profile "${profile.name}" contains unsupported sandbox fields.`);
5056
- return {
5057
- id: profile.id,
5058
- name: profile.name,
5059
- teamId: profile.teamId,
5060
- runtimeKind: profile.runtimeKind,
5061
- definitionCid: profile.definitionCid,
5062
- provider: profile.provider,
5063
- model: profile.model,
5064
- thinkingLevel: profile.thinkingLevel ?? null,
5065
- temperature: profile.temperature ?? null,
5066
- topP: profile.topP ?? null,
5067
- topK: profile.topK ?? null,
5068
- maxOutputTokens: profile.maxOutputTokens ?? null,
5069
- leaseTtlSec: profile.leaseTtlSec,
5070
- heartbeatIntervalMs: profile.heartbeatIntervalMs,
5071
- maxBatchSize: profile.maxBatchSize,
5072
- maxTurns: profile.maxTurns,
5073
- maxBashTimeouts: profile.maxBashTimeouts,
5074
- sessionTtlSec: profile.sessionTtlSec,
5075
- workspaceTtlSec: profile.workspaceTtlSec,
5076
- defaultWorkspaceMode: profile.defaultWorkspaceMode ?? null,
5077
- allowedWorkspaceModes: profile.allowedWorkspaceModes,
5078
- requiredEnv: profile.requiredEnv,
5079
- requiredTools: profile.requiredTools,
5080
- requiredExecutables: profile.requiredExecutables,
5081
- toolEnforcement: profile.toolEnforcement,
5082
- context: profile.context ?? [],
5083
- sandboxConfig: profile.sandbox,
5084
- mountPath: resolve(options.cwd),
5085
- source: `runtime-profile:${profile.id}`
5086
- };
5087
- }
5088
- async function resolveRuntimeProfiles(options) {
5089
- const seen = /* @__PURE__ */ new Set();
5090
- const out = [];
5091
- for (const profile of options.profiles) {
5092
- const resolved = await resolveRuntimeProfile({
5093
- agent: options.agent,
5094
- profile,
5095
- teamId: options.teamId,
5096
- cwd: options.cwd
5097
- });
5098
- if (seen.has(resolved.id)) continue;
5099
- seen.add(resolved.id);
5100
- out.push(resolved);
5101
- }
5102
- return out;
5103
- }
5104
- function validateRuntimeProfilePrerequisites(profile, env, inventory) {
5105
- const missingEnv = profile.requiredEnv.filter((name) => !env[name]);
5106
- const available = new Set(inventory?.tools ?? []);
5107
- const executableInventory = new Set(inventory?.executables ?? []);
5108
- const missingTools = profile.requiredTools.filter((tool) => !available.has(tool));
5109
- const missingExecutables = profile.requiredExecutables.filter((executable) => !executableInventory.has(executable));
5110
- if (missingEnv.length > 0 || missingTools.length > 0 || missingExecutables.length > 0) throw new RuntimeProfilePrerequisiteError(profile.name, missingEnv, missingTools, missingExecutables);
5111
- }
5112
- function resolveProfileWarmSessionTtlSec(profile) {
5113
- return Math.min(profile.sessionTtlSec, profile.workspaceTtlSec);
5114
- }
5115
- async function resolveProfileByName(options) {
5116
- if (!options.teamId) throw new Error(`Runtime profile name "${options.profile}" requires --team. Use a profile UUID when running without a team-scoped list.`);
5117
- const matches = (await options.agent.runtimeProfiles.list({ teamId: options.teamId })).items.filter((item) => item.name === options.profile);
5118
- if (matches.length === 0) throw new Error(`Runtime profile "${options.profile}" was not found in team ${options.teamId}.`);
5119
- if (matches.length > 1) throw new Error(`Runtime profile name "${options.profile}" is ambiguous in team ${options.teamId}. Use the profile UUID instead.`);
5120
- const profile = matches[0];
5121
- return {
5122
- ...profile,
5123
- thinkingLevel: profile.thinkingLevel ?? null,
5124
- temperature: profile.temperature ?? null,
5125
- topP: profile.topP ?? null,
5126
- topK: profile.topK ?? null,
5127
- maxOutputTokens: profile.maxOutputTokens ?? null
5128
- };
5129
- }
5130
- //#endregion
5131
5048
  //#region src/lib/runtime-profile-retry-triage.ts
5132
5049
  function createRuntimeProfileRetryTriage(options) {
5133
5050
  return createPiRetryTriage({
@@ -5924,7 +5841,9 @@ async function runPolling(opts) {
5924
5841
  rootLogger.info({
5925
5842
  authMode: cfg.authMode,
5926
5843
  subjectType: startupWhoami.subjectType,
5927
- boundTeamId: startupWhoami.credentialBinding?.boundTeamId ?? null,
5844
+ bindingScope: startupWhoami.credentialBinding?.bindingScope ?? null,
5845
+ credentialKeyId: startupWhoami.credentialBinding?.keyId ?? null,
5846
+ boundTeamId: startupWhoami.credentialBinding?.bindingScope === "team" ? startupWhoami.credentialBinding.boundTeamId : null,
5928
5847
  guestCredentialMode: ctx.guestCredentialMode,
5929
5848
  taskTypes: taskTypes.length > 0 ? taskTypes : ["*"],
5930
5849
  correlationId: values["correlation-id"] ?? null,
@@ -6208,7 +6127,8 @@ async function runPolling(opts) {
6208
6127
  onVmDiagnostic: (diagnostic) => {
6209
6128
  const fields = {
6210
6129
  event: diagnostic.event,
6211
- credentialMode: diagnostic.credentialMode
6130
+ credentialMode: diagnostic.credentialMode,
6131
+ ...diagnostic.brokeredSecretCount !== void 0 && { brokeredSecretCount: diagnostic.brokeredSecretCount }
6212
6132
  };
6213
6133
  if (diagnostic.level === "warning") taskLogger.warn(fields, diagnostic.message);
6214
6134
  else taskLogger.info(fields, diagnostic.message);
@@ -6574,7 +6494,8 @@ async function runOnce(argv, runtimeAdapter = defaultPiDaemonAdapter) {
6574
6494
  onVmDiagnostic: (diagnostic) => {
6575
6495
  const fields = {
6576
6496
  event: diagnostic.event,
6577
- credentialMode: diagnostic.credentialMode
6497
+ credentialMode: diagnostic.credentialMode,
6498
+ ...diagnostic.brokeredSecretCount !== void 0 && { brokeredSecretCount: diagnostic.brokeredSecretCount }
6578
6499
  };
6579
6500
  if (diagnostic.level === "warning") rootLogger.warn(fields, diagnostic.message);
6580
6501
  else rootLogger.info(fields, diagnostic.message);