@tangle-network/agent-eval 0.115.3 → 0.116.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 (68) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/analyst/index.d.ts +8 -10
  3. package/dist/analyst/index.js +27 -22
  4. package/dist/analyst/index.js.map +1 -1
  5. package/dist/{analyst-C8HHvfJp.d.ts → analyst-CFBc14Wc.d.ts} +1 -1
  6. package/dist/{analyze-runs-BYHg6Irm.d.ts → analyze-runs-0rz_m29H.d.ts} +3 -3
  7. package/dist/belief-state/index.d.ts +3 -3
  8. package/dist/benchmarks/index.d.ts +7 -3
  9. package/dist/benchmarks/index.js +4 -4
  10. package/dist/campaign/index.d.ts +212 -23
  11. package/dist/campaign/index.js +19 -4
  12. package/dist/{chunk-ADYLPOSX.js → chunk-3274WNK7.js} +427 -93
  13. package/dist/chunk-3274WNK7.js.map +1 -0
  14. package/dist/{chunk-I6LVHOV3.js → chunk-7GKEAIAD.js} +2 -2
  15. package/dist/{chunk-5S5NJ63F.js → chunk-CIUOICJT.js} +747 -2
  16. package/dist/chunk-CIUOICJT.js.map +1 -0
  17. package/dist/{chunk-KG4TD7EQ.js → chunk-GSW3OBHK.js} +1283 -181
  18. package/dist/chunk-GSW3OBHK.js.map +1 -0
  19. package/dist/chunk-MPHTT5HE.js +74 -0
  20. package/dist/chunk-MPHTT5HE.js.map +1 -0
  21. package/dist/{chunk-WSBUZMBU.js → chunk-NBSS5NDZ.js} +3 -3
  22. package/dist/{code-agent-session-D-g04tcy.d.ts → code-agent-session-CdxteG0y.d.ts} +1 -1
  23. package/dist/contract/index.d.ts +19 -19
  24. package/dist/contract/index.js +5 -3
  25. package/dist/contract/index.js.map +1 -1
  26. package/dist/{control-CcBiAEnn.d.ts → control-DbcDxouY.d.ts} +1 -1
  27. package/dist/control.d.ts +2 -2
  28. package/dist/{default-registry-DltpYR5u.d.ts → default-registry-DDfv22MQ.d.ts} +2 -1
  29. package/dist/{gepa-dne9JDPL.d.ts → gepa-CQelRtuC.d.ts} +10 -8
  30. package/dist/hosted/index.d.ts +8 -4
  31. package/dist/{index-BTEpx9He.d.ts → index-DbCXJfZ1.d.ts} +2 -2
  32. package/dist/index.d.ts +27 -30
  33. package/dist/index.js +26 -20
  34. package/dist/index.js.map +1 -1
  35. package/dist/{insight-report-IwwvqZZv.d.ts → insight-report-oMVxDTxl.d.ts} +1 -1
  36. package/dist/{integrity-qemeBAyx.d.ts → integrity-C6PZ73iC.d.ts} +1 -1
  37. package/dist/kind-factory-DWOvXjR_.d.ts +171 -0
  38. package/dist/meta-eval/index.d.ts +2 -2
  39. package/dist/multishot/index.d.ts +6 -2
  40. package/dist/openapi.json +1 -1
  41. package/dist/policy-edit-Clb2v6Oa.d.ts +708 -0
  42. package/dist/{pre-registration-D8h7ZxNL.d.ts → pre-registration--vU0mMtD.d.ts} +4 -4
  43. package/dist/{provenance-Bibyg1U9.d.ts → provenance-BbVagC68.d.ts} +26 -14
  44. package/dist/{release-report-CCtzajxP.d.ts → release-report-CamNDe90.d.ts} +2 -2
  45. package/dist/reporting.d.ts +4 -4
  46. package/dist/{researcher-Dq-EtpbE.d.ts → researcher-Dwbo_Fxx.d.ts} +5 -5
  47. package/dist/rl.d.ts +11 -9
  48. package/dist/{rubric-predictive-validity-DYTLjGWu.d.ts → rubric-predictive-validity-BIdf9h4R.d.ts} +1 -1
  49. package/dist/{run-record-B7RTi_ix.d.ts → run-record-CZmcpWPo.d.ts} +1 -1
  50. package/dist/{runtime-trajectory-Dws7Kpgi.d.ts → runtime-trajectory-CC0jx9ql.d.ts} +1 -1
  51. package/dist/{semantic-concept-judge-DxJmRkyJ.d.ts → semantic-concept-judge-CKjePUMh.d.ts} +3 -3
  52. package/dist/{store-C1YxJDEK.d.ts → store-9cAScOcb.d.ts} +132 -1
  53. package/dist/{summary-report-BJ5aNwZ1.d.ts → summary-report-DTNgQycC.d.ts} +1 -1
  54. package/dist/traces.d.ts +6 -8
  55. package/dist/{types-C5gJrOVT.d.ts → types-Ca_63YSD.d.ts} +59 -2
  56. package/docs/design/loop-taxonomy.md +1 -2
  57. package/package.json +1 -1
  58. package/dist/chunk-5S5NJ63F.js.map +0 -1
  59. package/dist/chunk-ADYLPOSX.js.map +0 -1
  60. package/dist/chunk-KG4TD7EQ.js.map +0 -1
  61. package/dist/chunk-QMXXSNC4.js +0 -761
  62. package/dist/chunk-QMXXSNC4.js.map +0 -1
  63. package/dist/kind-factory-DcNg13sZ.d.ts +0 -508
  64. package/dist/llm-client-DyqEH4jH.d.ts +0 -265
  65. package/dist/policy-edit-RLn8GWof.d.ts +0 -103
  66. package/dist/raw-provider-sink-C46HDghv.d.ts +0 -132
  67. /package/dist/{chunk-I6LVHOV3.js.map → chunk-7GKEAIAD.js.map} +0 -0
  68. /package/dist/{chunk-WSBUZMBU.js.map → chunk-NBSS5NDZ.js.map} +0 -0
@@ -12,7 +12,7 @@ import {
12
12
  runImprovementLoop,
13
13
  surfaceContentHash,
14
14
  surfaceHash
15
- } from "./chunk-ADYLPOSX.js";
15
+ } from "./chunk-3274WNK7.js";
16
16
  import {
17
17
  estimateCost,
18
18
  isModelPriced
@@ -26,17 +26,23 @@ import {
26
26
  } from "./chunk-FAOEFFRT.js";
27
27
  import {
28
28
  Mutex,
29
- admitPolicyEdit,
30
- applyPolicyEditToSurface,
31
- clamp01,
32
- isPolicyEdit,
33
- policyEditsFromFindings
34
- } from "./chunk-QMXXSNC4.js";
29
+ clamp01
30
+ } from "./chunk-MPHTT5HE.js";
35
31
  import {
36
32
  AnalystRegistry,
37
33
  DEFAULT_TRACE_ANALYST_KINDS,
38
- createTraceAnalystKind
39
- } from "./chunk-5S5NJ63F.js";
34
+ POLICY_EDIT_AXES,
35
+ POLICY_EDIT_TARGET_SURFACES,
36
+ admitPolicyEdit,
37
+ applyPolicyEditToSurface,
38
+ assertNoJudgeVerdict,
39
+ createTraceAnalystKind,
40
+ isPolicyEdit,
41
+ makePolicyEdit,
42
+ makePolicyEditCandidateRecord,
43
+ policyEditsFromFindings,
44
+ validatePolicyEditCandidateRecord
45
+ } from "./chunk-CIUOICJT.js";
40
46
  import {
41
47
  eProcess,
42
48
  mcnemar,
@@ -63,7 +69,8 @@ import {
63
69
  canonicalize
64
70
  } from "./chunk-VSMTAMNK.js";
65
71
  import {
66
- callLlm
72
+ callLlm,
73
+ callLlmJson
67
74
  } from "./chunk-GY4SYVPJ.js";
68
75
  import {
69
76
  AgentEvalError,
@@ -5130,10 +5137,16 @@ function compositeProposer(opts) {
5130
5137
  const surface = isCandidate ? proposal.surface : proposal;
5131
5138
  const label = isCandidate ? proposal.label : "candidate";
5132
5139
  const rationale = isCandidate ? proposal.rationale : "";
5140
+ const candidateRecord = isCandidate ? proposal.candidateRecord : void 0;
5133
5141
  const key = surfaceContentHash(surface);
5134
5142
  if (seen.has(key)) continue;
5135
5143
  seen.add(key);
5136
- pool.push({ surface, label: `${member.kind}:${label}`, rationale });
5144
+ pool.push({
5145
+ surface,
5146
+ label: `${member.kind}:${label}`,
5147
+ rationale,
5148
+ ...candidateRecord ? { candidateRecord } : {}
5149
+ });
5137
5150
  }
5138
5151
  } catch (err) {
5139
5152
  errors.push(`${member.kind}: ${err instanceof Error ? err.message : String(err)}`);
@@ -5264,6 +5277,1153 @@ ${findings.slice(0, 800)}`,
5264
5277
  });
5265
5278
  }
5266
5279
 
5280
+ // src/campaign/proposers/llm-policy-edit.ts
5281
+ import { z } from "zod";
5282
+
5283
+ // src/campaign/proposers/policy-edit.ts
5284
+ function policyEditProposer(opts = {}) {
5285
+ return {
5286
+ kind: "policy-edit",
5287
+ async propose(ctx) {
5288
+ const edits = materializePolicyEdits(opts.edits ?? ctx.findings, opts.findingOptions);
5289
+ const limit = Math.max(
5290
+ 0,
5291
+ Math.min(opts.maxCandidates ?? ctx.populationSize, ctx.populationSize)
5292
+ );
5293
+ const out = [];
5294
+ const seen = /* @__PURE__ */ new Set([surfaceContentHash(ctx.currentSurface)]);
5295
+ if (limit === 0) return out;
5296
+ for (const edit of edits) {
5297
+ const admission = admitPolicyEdit(edit, opts.admission);
5298
+ opts.onAdmission?.(admission);
5299
+ if (admission.decision !== "admit") continue;
5300
+ const surface = coerceCandidateSurface(applyPolicyEditToSurface(ctx.currentSurface, edit));
5301
+ const hash = surfaceContentHash(surface);
5302
+ if (seen.has(hash)) continue;
5303
+ seen.add(hash);
5304
+ out.push({
5305
+ surface,
5306
+ label: `policy-edit:${edit.axis}`,
5307
+ rationale: `${edit.editId} expected ${edit.expectedGain.direction} ${edit.expectedGain.metric} by ${edit.expectedGain.amount}; source findings [${edit.source.findingIds.join(", ")}]`,
5308
+ candidateRecord: makePolicyEditCandidateRecord(edit)
5309
+ });
5310
+ if (out.length >= limit) break;
5311
+ }
5312
+ return out;
5313
+ }
5314
+ };
5315
+ }
5316
+ function materializePolicyEdits(inputs, findingOptions) {
5317
+ const edits = [];
5318
+ const findings = [];
5319
+ for (const input of inputs) {
5320
+ if (isPolicyEdit(input)) {
5321
+ edits.push(input);
5322
+ } else if (isAnalystFindingLike(input)) {
5323
+ findings.push(input);
5324
+ }
5325
+ }
5326
+ if (findings.length > 0) edits.push(...policyEditsFromFindings(findings, findingOptions));
5327
+ return edits;
5328
+ }
5329
+ function isAnalystFindingLike(input) {
5330
+ if (!input || typeof input !== "object") return false;
5331
+ const obj = input;
5332
+ return typeof obj.finding_id === "string" && typeof obj.analyst_id === "string" && typeof obj.claim === "string" && Array.isArray(obj.evidence_refs);
5333
+ }
5334
+ function coerceCandidateSurface(surface) {
5335
+ if (typeof surface === "string") return surface;
5336
+ if (surface && typeof surface === "object") {
5337
+ const obj = surface;
5338
+ if (obj.kind === "code" && typeof obj.worktreeRef === "string") {
5339
+ assertCodeSurfaceIdentity(surface);
5340
+ return surface;
5341
+ }
5342
+ return JSON.stringify(surface, null, 2);
5343
+ }
5344
+ throw new Error("policyEditProposer: policy edit produced an unsupported surface");
5345
+ }
5346
+
5347
+ // src/campaign/proposers/policy-edit-author-context.ts
5348
+ function selectPolicyEditAuthorRows(rows, options) {
5349
+ assertPositiveSafeInteger(options.limit, "limit");
5350
+ const unique2 = /* @__PURE__ */ new Map();
5351
+ for (const row of rows) {
5352
+ if (!row.scenarioId || row.scenarioId.trim() !== row.scenarioId) {
5353
+ throw new Error("selectPolicyEditAuthorRows: scenarioId must be trimmed and non-empty");
5354
+ }
5355
+ if (!Number.isFinite(row.composite)) {
5356
+ throw new Error(
5357
+ `selectPolicyEditAuthorRows: composite must be finite for '${row.scenarioId}'`
5358
+ );
5359
+ }
5360
+ if (unique2.has(row.scenarioId)) continue;
5361
+ const reference = options.referenceByScenario?.get(row.scenarioId);
5362
+ if (reference !== void 0 && !Number.isFinite(reference)) {
5363
+ throw new Error(
5364
+ `selectPolicyEditAuthorRows: reference must be finite for '${row.scenarioId}'`
5365
+ );
5366
+ }
5367
+ unique2.set(row.scenarioId, {
5368
+ row,
5369
+ delta: reference === void 0 ? null : row.composite - reference
5370
+ });
5371
+ }
5372
+ const hardest = [...unique2.values()].sort(
5373
+ (a, b) => a.row.composite - b.row.composite || compareScenarioId(a.row, b.row)
5374
+ );
5375
+ const regressions = [...unique2.values()].filter((entry) => entry.delta !== null && entry.delta < 0).sort((a, b) => a.delta - b.delta || compareScenarioId(a.row, b.row));
5376
+ const improvements = [...unique2.values()].filter((entry) => entry.delta !== null && entry.delta > 0).sort((a, b) => b.delta - a.delta || compareScenarioId(a.row, b.row));
5377
+ const rankings = [hardest, regressions, improvements];
5378
+ const maxDepth = Math.max(...rankings.map((ranking) => ranking.length), 0);
5379
+ const selected = [];
5380
+ const selectedIds = /* @__PURE__ */ new Set();
5381
+ for (let depth = 0; depth < maxDepth && selected.length < options.limit; depth += 1) {
5382
+ for (const ranking of rankings) {
5383
+ const entry = ranking[depth];
5384
+ if (!entry || selectedIds.has(entry.row.scenarioId)) continue;
5385
+ selected.push(entry.row);
5386
+ selectedIds.add(entry.row.scenarioId);
5387
+ if (selected.length === options.limit) break;
5388
+ }
5389
+ }
5390
+ return selected;
5391
+ }
5392
+ function assertPolicyEditAuthorContextBudget(value, maxChars) {
5393
+ assertPositiveSafeInteger(maxChars, "maxChars");
5394
+ const json = JSON.stringify(value);
5395
+ if (json === void 0) {
5396
+ throw new Error("assertPolicyEditAuthorContextBudget: value must serialize to JSON");
5397
+ }
5398
+ const actualChars = json.length;
5399
+ if (actualChars > maxChars) {
5400
+ throw new Error(
5401
+ `assertPolicyEditAuthorContextBudget: serialized JSON exceeds budget (actualChars=${actualChars}, maxChars=${maxChars})`
5402
+ );
5403
+ }
5404
+ return { json, actualChars, maxChars };
5405
+ }
5406
+ function compareScenarioId(a, b) {
5407
+ return a.scenarioId < b.scenarioId ? -1 : a.scenarioId > b.scenarioId ? 1 : 0;
5408
+ }
5409
+ function assertPositiveSafeInteger(value, name) {
5410
+ if (!Number.isSafeInteger(value) || value <= 0) {
5411
+ throw new Error(`${name} must be a positive safe integer (got ${value})`);
5412
+ }
5413
+ }
5414
+
5415
+ // src/campaign/proposers/llm-policy-edit.ts
5416
+ var JSON_POLICY_EDIT_TARGET_SURFACES = [
5417
+ "prompt",
5418
+ "tool-contract",
5419
+ "runtime-config",
5420
+ "memory",
5421
+ "agent-profile"
5422
+ ];
5423
+ var NonEmptyStringSchema = z.string().trim().min(1);
5424
+ var JsonValueSchema = z.lazy(
5425
+ () => z.union([
5426
+ z.string(),
5427
+ z.number().finite(),
5428
+ z.boolean(),
5429
+ z.null(),
5430
+ z.array(JsonValueSchema),
5431
+ z.record(NonEmptyStringSchema, JsonValueSchema)
5432
+ ])
5433
+ );
5434
+ var AuthoredJsonChangeSchema = z.discriminatedUnion("mode", [
5435
+ z.object({
5436
+ kind: z.literal("json"),
5437
+ mode: z.literal("set"),
5438
+ path: NonEmptyStringSchema,
5439
+ value: JsonValueSchema
5440
+ }).strict(),
5441
+ z.object({
5442
+ kind: z.literal("json"),
5443
+ mode: z.literal("merge"),
5444
+ path: NonEmptyStringSchema,
5445
+ value: JsonValueSchema
5446
+ }).strict(),
5447
+ z.object({
5448
+ kind: z.literal("json"),
5449
+ mode: z.literal("remove"),
5450
+ path: NonEmptyStringSchema
5451
+ }).strict()
5452
+ ]);
5453
+ var AuthoredPolicyEditSchema = z.object({
5454
+ axis: z.enum(POLICY_EDIT_AXES),
5455
+ target: z.object({
5456
+ surface: z.enum(POLICY_EDIT_TARGET_SURFACES),
5457
+ path: NonEmptyStringSchema,
5458
+ label: NonEmptyStringSchema.max(200).nullable()
5459
+ }).strict(),
5460
+ change: AuthoredJsonChangeSchema,
5461
+ claim: NonEmptyStringSchema.max(2e3),
5462
+ expectedGain: z.object({
5463
+ metric: NonEmptyStringSchema.max(400),
5464
+ direction: z.enum(["increase", "decrease"]),
5465
+ amount: z.number().finite().positive(),
5466
+ unit: z.enum(["absolute", "relative", "percent", "score"]).nullable(),
5467
+ rationale: NonEmptyStringSchema.max(2e3).nullable()
5468
+ }).strict(),
5469
+ confidence: z.number().finite().min(0).max(1),
5470
+ risk: z.enum(["low", "medium", "high", "unknown"]),
5471
+ source: z.object({
5472
+ findingKeys: z.array(NonEmptyStringSchema).min(1).refine((ids) => new Set(ids).size === ids.length, "findingKeys must be unique")
5473
+ }).strict(),
5474
+ rationale: NonEmptyStringSchema.max(4e3).nullable(),
5475
+ validationPlan: NonEmptyStringSchema.max(2e3).nullable()
5476
+ }).strict();
5477
+ var PolicyEditAuthorResponseSchema = z.object({
5478
+ edits: z.array(AuthoredPolicyEditSchema)
5479
+ }).strict();
5480
+ var POLICY_EDIT_AUTHOR_JSON_SCHEMA = {
5481
+ type: "object",
5482
+ additionalProperties: false,
5483
+ required: ["edits"],
5484
+ properties: {
5485
+ edits: {
5486
+ type: "array",
5487
+ items: {
5488
+ type: "object",
5489
+ additionalProperties: false,
5490
+ required: [
5491
+ "axis",
5492
+ "target",
5493
+ "change",
5494
+ "claim",
5495
+ "expectedGain",
5496
+ "confidence",
5497
+ "risk",
5498
+ "source",
5499
+ "rationale",
5500
+ "validationPlan"
5501
+ ],
5502
+ properties: {
5503
+ axis: { type: "string", enum: [...POLICY_EDIT_AXES] },
5504
+ target: {
5505
+ type: "object",
5506
+ additionalProperties: false,
5507
+ required: ["surface", "path", "label"],
5508
+ properties: {
5509
+ surface: { type: "string", enum: [...POLICY_EDIT_TARGET_SURFACES] },
5510
+ path: { type: "string", minLength: 1 },
5511
+ label: { type: ["string", "null"], maxLength: 200 }
5512
+ }
5513
+ },
5514
+ change: {
5515
+ anyOf: [
5516
+ {
5517
+ type: "object",
5518
+ additionalProperties: false,
5519
+ required: ["kind", "mode", "path", "value"],
5520
+ properties: {
5521
+ kind: { const: "json" },
5522
+ mode: { const: "set" },
5523
+ path: { type: "string", minLength: 1 },
5524
+ value: {}
5525
+ }
5526
+ },
5527
+ {
5528
+ type: "object",
5529
+ additionalProperties: false,
5530
+ required: ["kind", "mode", "path", "value"],
5531
+ properties: {
5532
+ kind: { const: "json" },
5533
+ mode: { const: "merge" },
5534
+ path: { type: "string", minLength: 1 },
5535
+ value: {}
5536
+ }
5537
+ },
5538
+ {
5539
+ type: "object",
5540
+ additionalProperties: false,
5541
+ required: ["kind", "mode", "path"],
5542
+ properties: {
5543
+ kind: { const: "json" },
5544
+ mode: { const: "remove" },
5545
+ path: { type: "string", minLength: 1 }
5546
+ }
5547
+ }
5548
+ ]
5549
+ },
5550
+ claim: { type: "string", minLength: 1, maxLength: 2e3 },
5551
+ expectedGain: {
5552
+ type: "object",
5553
+ additionalProperties: false,
5554
+ required: ["metric", "direction", "amount", "unit", "rationale"],
5555
+ properties: {
5556
+ metric: { type: "string", minLength: 1, maxLength: 400 },
5557
+ direction: { type: "string", enum: ["increase", "decrease"] },
5558
+ amount: { type: "number", exclusiveMinimum: 0 },
5559
+ unit: {
5560
+ type: ["string", "null"],
5561
+ enum: ["absolute", "relative", "percent", "score", null]
5562
+ },
5563
+ rationale: { type: ["string", "null"], maxLength: 2e3 }
5564
+ }
5565
+ },
5566
+ confidence: { type: "number", minimum: 0, maximum: 1 },
5567
+ risk: { type: "string", enum: ["low", "medium", "high", "unknown"] },
5568
+ source: {
5569
+ type: "object",
5570
+ additionalProperties: false,
5571
+ required: ["findingKeys"],
5572
+ properties: {
5573
+ findingKeys: {
5574
+ type: "array",
5575
+ minItems: 1,
5576
+ uniqueItems: true,
5577
+ items: { type: "string", minLength: 1 }
5578
+ }
5579
+ }
5580
+ },
5581
+ rationale: { type: ["string", "null"], maxLength: 4e3 },
5582
+ validationPlan: { type: ["string", "null"], maxLength: 2e3 }
5583
+ }
5584
+ }
5585
+ }
5586
+ }
5587
+ };
5588
+ function policyEditAuthorJsonSchema(maxItems, targetSurface, allowedJsonPaths, objectives) {
5589
+ const schema = JSON.parse(JSON.stringify(POLICY_EDIT_AUTHOR_JSON_SCHEMA));
5590
+ const properties = schema.properties;
5591
+ const edits = properties.edits;
5592
+ edits.maxItems = maxItems;
5593
+ const item = edits.items;
5594
+ const itemProperties = item.properties;
5595
+ const target = itemProperties.target;
5596
+ const targetProperties = target.properties;
5597
+ targetProperties.surface = { type: "string", enum: [targetSurface] };
5598
+ targetProperties.path = { type: "string", enum: [...allowedJsonPaths] };
5599
+ const change = itemProperties.change;
5600
+ for (const variant of change.anyOf) {
5601
+ const variantProperties = variant.properties;
5602
+ variantProperties.path = { type: "string", enum: [...allowedJsonPaths] };
5603
+ }
5604
+ const expectedGain = itemProperties.expectedGain;
5605
+ const gainProperties = expectedGain.properties;
5606
+ gainProperties.metric = { type: "string", enum: objectives.map((objective) => objective.key) };
5607
+ gainProperties.direction = {
5608
+ type: "string",
5609
+ enum: [...new Set(objectives.map((objective) => objective.direction))]
5610
+ };
5611
+ gainProperties.unit = {
5612
+ type: "string",
5613
+ enum: [...new Set(objectives.map((objective) => objective.unit))]
5614
+ };
5615
+ return schema;
5616
+ }
5617
+ var DEFAULT_POLICY_EDIT_HISTORY_LIMITS = Object.freeze({
5618
+ generations: 4,
5619
+ candidatesPerGeneration: 16,
5620
+ scenariosPerCandidate: 12,
5621
+ findings: 32,
5622
+ authorContextChars: 2e5
5623
+ });
5624
+ var POLICY_EDIT_AUTHOR_SYSTEM = [
5625
+ "You author strictly typed PolicyEdit candidates over one JSON surface.",
5626
+ 'Return exactly one JSON object with shape {"edits":[...]}; emit an empty edits array when no evidence supports a change.',
5627
+ `axis must be one of: ${POLICY_EDIT_AXES.join(", ")}.`,
5628
+ `target.surface must be one of: ${POLICY_EDIT_TARGET_SURFACES.join(", ")}.`,
5629
+ "target.path and change.path must be the same caller-allowed JSON path.",
5630
+ 'change must be exactly one operation: {"kind":"json","mode":"set","path":string,"value":json}, {"kind":"json","mode":"merge","path":string,"value":json}, or {"kind":"json","mode":"remove","path":string}.',
5631
+ "Nullable fields required by the response schema must be null when they do not apply.",
5632
+ "Every edit must cite one or more supplied finding keys in source.findingKeys. Do not emit persistent finding IDs, analyst IDs, or evidence references; the caller binds those from the cited findings.",
5633
+ "Treat expectedGain and confidence as forecasts, never as measured evidence. Learn from baselineOutcome, incumbentOutcome, and observedDeltaFromParent.",
5634
+ "Do not invent a finding, path, field, score, or task fact. Do not include schemaVersion, editId, metadata, prose, or undeclared keys."
5635
+ ].join("\n");
5636
+ function llmPolicyEditProposer(opts) {
5637
+ const allowedJsonPaths = validateAllowedJsonPaths(opts.allowedJsonPaths);
5638
+ const allowedPathSet = new Set(allowedJsonPaths);
5639
+ const objectives = validateObjectives(opts.objectives);
5640
+ const objectiveByKey = new Map(objectives.map((objective) => [objective.key, objective]));
5641
+ requireNonEmpty(opts.model, "model");
5642
+ requireNonEmpty(opts.target, "target");
5643
+ if (!JSON_POLICY_EDIT_TARGET_SURFACES.includes(opts.targetSurface)) {
5644
+ throw new Error(
5645
+ `llmPolicyEditProposer: targetSurface '${opts.targetSurface}' is not a JSON-backed surface`
5646
+ );
5647
+ }
5648
+ if (opts.maxCandidates !== void 0 && (!Number.isSafeInteger(opts.maxCandidates) || opts.maxCandidates < 0)) {
5649
+ throw new Error("llmPolicyEditProposer: maxCandidates must be a non-negative safe integer");
5650
+ }
5651
+ const admissionMode = opts.admissionMode ?? "evidence-only";
5652
+ if (admissionMode !== "evidence-only" && admissionMode !== "strict") {
5653
+ throw new Error("llmPolicyEditProposer: admissionMode must be 'evidence-only' or 'strict'");
5654
+ }
5655
+ if (opts.admission && admissionMode !== "strict") {
5656
+ throw new Error("llmPolicyEditProposer: admission thresholds require admissionMode: 'strict'");
5657
+ }
5658
+ const historyLimits = validateHistoryLimits({
5659
+ ...opts.maxHistoryGenerations === void 0 ? {} : { maxGenerations: opts.maxHistoryGenerations },
5660
+ ...opts.maxHistoryCandidatesPerGeneration === void 0 ? {} : { maxCandidatesPerGeneration: opts.maxHistoryCandidatesPerGeneration },
5661
+ ...opts.maxScenariosPerCandidate === void 0 ? {} : { maxScenariosPerCandidate: opts.maxScenariosPerCandidate },
5662
+ ...opts.scenarioIdTransform === void 0 ? {} : { scenarioIdTransform: opts.scenarioIdTransform }
5663
+ });
5664
+ const maxFindings = positiveLimit(
5665
+ opts.maxFindings ?? DEFAULT_POLICY_EDIT_HISTORY_LIMITS.findings,
5666
+ "maxFindings"
5667
+ );
5668
+ const maxAuthorContextChars = positiveLimit(
5669
+ opts.maxAuthorContextChars ?? DEFAULT_POLICY_EDIT_HISTORY_LIMITS.authorContextChars,
5670
+ "maxAuthorContextChars"
5671
+ );
5672
+ return {
5673
+ kind: "llm-policy-edit",
5674
+ async propose(ctx) {
5675
+ const limit = Math.min(ctx.populationSize, opts.maxCandidates ?? ctx.populationSize);
5676
+ if (limit <= 0) return [];
5677
+ const currentSurface = parseJsonSurface(ctx.currentSurface);
5678
+ assertSearchOutcome(ctx.baselineOutcome, "baselineOutcome");
5679
+ assertSearchOutcome(ctx.incumbentOutcome, "incumbentOutcome");
5680
+ assertMeasuredCompositesInScale(ctx, objectives[0]);
5681
+ const scenarioIds = createScenarioIdProjector(historyLimits.scenarioIdTransform);
5682
+ registerOutcomeScenarioIds(ctx.baselineOutcome, scenarioIds);
5683
+ registerOutcomeScenarioIds(ctx.incumbentOutcome, scenarioIds);
5684
+ registerHistoryScenarioIds(ctx.history.slice(-historyLimits.maxGenerations), scenarioIds);
5685
+ assertSurfaceIsTaskAgnostic(
5686
+ { currentSurface, allowedJsonPaths, objectives, targetSurface: opts.targetSurface },
5687
+ scenarioIds
5688
+ );
5689
+ const measuredSources = measuredSourceMeasurements(ctx);
5690
+ const findings = citableFindings(ctx.findings, measuredSources, maxFindings);
5691
+ const findingByKey = new Map(
5692
+ findings.map((finding, index) => [`finding-${index + 1}`, finding])
5693
+ );
5694
+ const authorContext = {
5695
+ target: scenarioIds.sanitize(opts.target),
5696
+ targetSurface: opts.targetSurface,
5697
+ allowedJsonPaths,
5698
+ objectives,
5699
+ candidateCount: limit,
5700
+ generation: ctx.generation,
5701
+ currentSurface,
5702
+ findings: findings.map(
5703
+ (finding, index) => renderFinding(finding, `finding-${index + 1}`, scenarioIds, measuredSources)
5704
+ ),
5705
+ baselineOutcome: projectOutcome(
5706
+ ctx.baselineOutcome,
5707
+ scenarioIds,
5708
+ historyLimits.maxScenariosPerCandidate
5709
+ ),
5710
+ incumbentOutcome: projectOutcome(
5711
+ ctx.incumbentOutcome,
5712
+ scenarioIds,
5713
+ historyLimits.maxScenariosPerCandidate,
5714
+ ctx.baselineOutcome
5715
+ ),
5716
+ history: projectPolicyEditHistoryWithProjector(
5717
+ ctx.history,
5718
+ historyLimits,
5719
+ scenarioIds,
5720
+ objectiveByKey
5721
+ )
5722
+ };
5723
+ const responseSchema = policyEditAuthorJsonSchema(
5724
+ limit,
5725
+ opts.targetSurface,
5726
+ allowedJsonPaths,
5727
+ objectives
5728
+ );
5729
+ assertPolicyEditAuthorContextBudget(
5730
+ { system: POLICY_EDIT_AUTHOR_SYSTEM, authorContext, responseSchema },
5731
+ maxAuthorContextChars
5732
+ );
5733
+ const userContent = JSON.stringify(authorContext);
5734
+ const { value } = await callLlmJson(
5735
+ {
5736
+ model: opts.model,
5737
+ messages: [
5738
+ { role: "system", content: POLICY_EDIT_AUTHOR_SYSTEM },
5739
+ {
5740
+ role: "user",
5741
+ content: userContent
5742
+ }
5743
+ ],
5744
+ jsonSchema: {
5745
+ name: "policy_edit_author",
5746
+ schema: responseSchema
5747
+ },
5748
+ temperature: opts.temperature ?? 0.2,
5749
+ maxTokens: opts.maxTokens ?? 6e3,
5750
+ timeoutMs: opts.timeoutMs
5751
+ },
5752
+ { ...opts.llm, signal: ctx.signal }
5753
+ );
5754
+ const response = parseAuthorResponse(value);
5755
+ if (response.edits.length > limit) {
5756
+ throw new Error(
5757
+ `llmPolicyEditProposer: author returned ${response.edits.length} edits for ${limit} candidate slots`
5758
+ );
5759
+ }
5760
+ const edits = response.edits.map(
5761
+ (draft) => bindAuthoredEdit(
5762
+ draft,
5763
+ findingByKey,
5764
+ opts.targetSurface,
5765
+ allowedPathSet,
5766
+ objectiveByKey,
5767
+ ctx.incumbentOutcome?.composite ?? ctx.baselineOutcome?.composite
5768
+ )
5769
+ );
5770
+ return policyEditProposer({
5771
+ edits,
5772
+ admission: admissionMode === "strict" ? opts.admission : {
5773
+ minScore: 0,
5774
+ minExpectedGain: 0,
5775
+ allowHighRisk: true,
5776
+ requireEvidence: true
5777
+ },
5778
+ maxCandidates: limit,
5779
+ onAdmission: opts.onAdmission
5780
+ }).propose(ctx);
5781
+ }
5782
+ };
5783
+ }
5784
+ function projectPolicyEditHistory(history, options = {}) {
5785
+ const limits = validateHistoryLimits(options);
5786
+ const objectiveByKey = new Map(
5787
+ (options.objectives ? validateObjectives(options.objectives) : []).map((objective) => [
5788
+ objective.key,
5789
+ objective
5790
+ ])
5791
+ );
5792
+ const scenarioIds = createScenarioIdProjector(limits.scenarioIdTransform);
5793
+ registerHistoryScenarioIds(history.slice(-limits.maxGenerations), scenarioIds);
5794
+ return projectPolicyEditHistoryWithProjector(history, limits, scenarioIds, objectiveByKey);
5795
+ }
5796
+ function projectPolicyEditHistoryWithProjector(history, limits, scenarioIds, objectiveByKey) {
5797
+ const retainedHistory = history.slice(-limits.maxGenerations);
5798
+ const candidateByHash = new Map(
5799
+ retainedHistory.flatMap(
5800
+ (record) => record.candidates.map((candidate) => [candidate.surfaceHash, candidate])
5801
+ )
5802
+ );
5803
+ return retainedHistory.map((record) => {
5804
+ const candidates = selectHistoryCandidates(record, limits.maxCandidatesPerGeneration);
5805
+ const hashes = new Set(candidates.map((candidate) => candidate.surfaceHash));
5806
+ return {
5807
+ generationIndex: record.generationIndex,
5808
+ promoted: record.promoted.filter((hash) => hashes.has(hash)).map((hash) => scenarioIds.sanitize(hash)),
5809
+ candidates: candidates.map(
5810
+ (candidate) => projectHistoryCandidate(
5811
+ candidate,
5812
+ scenarioIds,
5813
+ limits.maxScenariosPerCandidate,
5814
+ candidate.parentSurfaceHash ? candidateByHash.get(candidate.parentSurfaceHash)?.scenarios : void 0,
5815
+ objectiveByKey
5816
+ )
5817
+ )
5818
+ };
5819
+ });
5820
+ }
5821
+ function selectHistoryCandidates(record, limit) {
5822
+ const promotionOrder = new Map(record.promoted.map((hash, index) => [hash, index]));
5823
+ const promoted = [...record.candidates].filter((candidate) => promotionOrder.has(candidate.surfaceHash)).sort((a, b) => promotionOrder.get(a.surfaceHash) - promotionOrder.get(b.surfaceHash));
5824
+ const selected = promoted.slice(0, limit);
5825
+ const selectedHashes = new Set(selected.map((candidate) => candidate.surfaceHash));
5826
+ const remaining = [...record.candidates].filter((candidate) => !promotionOrder.has(candidate.surfaceHash)).sort((a, b) => b.composite - a.composite || a.surfaceHash.localeCompare(b.surfaceHash));
5827
+ let high = 0;
5828
+ let low = remaining.length - 1;
5829
+ let takeLow = selected.length > 0;
5830
+ while (selected.length < limit && high <= low) {
5831
+ const candidate = takeLow ? remaining[low--] : remaining[high++];
5832
+ takeLow = !takeLow;
5833
+ if (!candidate || selectedHashes.has(candidate.surfaceHash)) continue;
5834
+ selected.push(candidate);
5835
+ selectedHashes.add(candidate.surfaceHash);
5836
+ }
5837
+ return selected;
5838
+ }
5839
+ function projectHistoryCandidate(candidate, scenarioIds, maxScenarios, parentScenarios, objectiveByKey) {
5840
+ const referenceByScenario = parentScenarios ? new Map(parentScenarios.map((scenario) => [scenario.scenarioId, scenario.composite])) : void 0;
5841
+ const selectedScenarios = selectPolicyEditAuthorRows(candidate.scenarios, {
5842
+ limit: maxScenarios,
5843
+ ...referenceByScenario ? { referenceByScenario } : {}
5844
+ });
5845
+ const validatedRecord = candidate.candidateRecord ? validatePolicyEditCandidateRecord(candidate.candidateRecord) : void 0;
5846
+ return {
5847
+ surfaceHash: scenarioIds.sanitize(candidate.surfaceHash),
5848
+ parentSurfaceHash: candidate.parentSurfaceHash ? scenarioIds.sanitize(candidate.parentSurfaceHash) : null,
5849
+ parentComposite: candidate.parentComposite ?? null,
5850
+ label: candidate.label ? scenarioIds.sanitize(candidate.label) : null,
5851
+ rationale: candidate.rationale ? scenarioIds.sanitize(candidate.rationale) : null,
5852
+ composite: candidate.composite,
5853
+ observedDeltaFromParent: candidate.observedDeltaFromParent ?? null,
5854
+ eligibleForPromotion: candidate.eligibleForPromotion ?? null,
5855
+ coverage: candidate.coverage ? {
5856
+ expectedCells: candidate.coverage.expectedCells,
5857
+ scorableCells: candidate.coverage.scorableCells,
5858
+ // `cellId` embeds the raw scenario ID. The aggregate reason is useful
5859
+ // for search, but the identifier must not bypass scenarioIdTransform.
5860
+ unscorableCells: [...candidate.coverage.unscorableCells].sort((a, b) => a.cellId.localeCompare(b.cellId)).slice(0, maxScenarios).map((cell) => ({ reason: scenarioIds.sanitize(cell.reason) }))
5861
+ } : null,
5862
+ // GenerationCandidate.ci95 is currently a placeholder [composite, composite],
5863
+ // not a measured interval. Keep it out of author context until it is real.
5864
+ dimensions: sanitizeDimensions(candidate.dimensions, scenarioIds),
5865
+ scenarios: selectedScenarios.map((scenario) => {
5866
+ return {
5867
+ scenarioId: scenarioIds.project(scenario.scenarioId),
5868
+ composite: scenario.composite,
5869
+ notes: scenario.notes ? scenarioIds.sanitize(scenario.notes) : null
5870
+ };
5871
+ }),
5872
+ candidateEdit: validatedRecord ? summarizeCandidateEdit(validatedRecord, scenarioIds) : null,
5873
+ forecastCalibration: forecastCalibration(candidate, validatedRecord, objectiveByKey)
5874
+ };
5875
+ }
5876
+ function projectOutcome(outcome, scenarioIds, maxScenarios, reference = void 0) {
5877
+ if (!outcome) return null;
5878
+ const referenceByScenario = reference ? new Map(reference.scenarios.map((scenario) => [scenario.scenarioId, scenario.composite])) : void 0;
5879
+ const selectedScenarios = selectPolicyEditAuthorRows(outcome.scenarios, {
5880
+ limit: maxScenarios,
5881
+ ...referenceByScenario ? { referenceByScenario } : {}
5882
+ });
5883
+ return {
5884
+ split: "search",
5885
+ generation: outcome.generation,
5886
+ surfaceHash: scenarioIds.sanitize(outcome.surfaceHash),
5887
+ composite: outcome.composite,
5888
+ dimensions: sanitizeDimensions(outcome.dimensions, scenarioIds),
5889
+ scenarios: selectedScenarios.map((scenario) => {
5890
+ return {
5891
+ scenarioId: scenarioIds.project(scenario.scenarioId),
5892
+ composite: scenario.composite,
5893
+ notes: scenario.notes ? scenarioIds.sanitize(scenario.notes) : null
5894
+ };
5895
+ }),
5896
+ coverage: { ...outcome.coverage }
5897
+ };
5898
+ }
5899
+ function createScenarioIdProjector(transform) {
5900
+ const aliases = /* @__PURE__ */ new Map();
5901
+ const originals = /* @__PURE__ */ new Map();
5902
+ return {
5903
+ project(scenarioId) {
5904
+ const known = aliases.get(scenarioId);
5905
+ if (known) return known;
5906
+ const alias = transform(scenarioId);
5907
+ if (!alias || alias.trim() !== alias) {
5908
+ throw new Error(
5909
+ "llmPolicyEditProposer: scenarioIdTransform must return a trimmed non-empty string"
5910
+ );
5911
+ }
5912
+ const collision = originals.get(alias);
5913
+ if (collision && collision !== scenarioId) {
5914
+ throw new Error(
5915
+ `llmPolicyEditProposer: scenarioIdTransform collision for '${collision}' and '${scenarioId}'`
5916
+ );
5917
+ }
5918
+ const aliasIsAnotherOriginal = aliases.has(alias) && alias !== scenarioId;
5919
+ const originalIsAnotherAlias = originals.has(scenarioId) && originals.get(scenarioId) !== scenarioId;
5920
+ if (aliasIsAnotherOriginal || originalIsAnotherAlias) {
5921
+ throw new Error(
5922
+ "llmPolicyEditProposer: scenarioIdTransform aliases overlap raw scenario IDs"
5923
+ );
5924
+ }
5925
+ aliases.set(scenarioId, alias);
5926
+ originals.set(alias, scenarioId);
5927
+ return alias;
5928
+ },
5929
+ sanitize(text) {
5930
+ const originalsByLength = [...aliases.keys()].sort((a, b) => b.length - a.length);
5931
+ if (originalsByLength.length === 0) return text;
5932
+ const pattern = new RegExp(
5933
+ `(^|[^A-Za-z0-9_-])(${originalsByLength.map(escapeRegExp).join("|")})(?=$|[^A-Za-z0-9_-])`,
5934
+ "g"
5935
+ );
5936
+ return text.replace(
5937
+ pattern,
5938
+ (_match, prefix, original) => `${prefix}${aliases.get(original) ?? original}`
5939
+ );
5940
+ }
5941
+ };
5942
+ }
5943
+ function escapeRegExp(value) {
5944
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
5945
+ }
5946
+ function sourceKey(surfaceHash2, generation) {
5947
+ return `${surfaceHash2}@${generation}`;
5948
+ }
5949
+ function measuredSourceMeasurements(ctx) {
5950
+ const measurements = /* @__PURE__ */ new Map();
5951
+ const add = (measurement) => {
5952
+ measurements.set(sourceKey(measurement.surfaceHash, measurement.generation), measurement);
5953
+ };
5954
+ if (ctx.baselineOutcome) {
5955
+ add({
5956
+ surfaceHash: ctx.baselineOutcome.surfaceHash,
5957
+ generation: ctx.baselineOutcome.generation,
5958
+ composite: ctx.baselineOutcome.composite,
5959
+ parentComposite: null,
5960
+ observedDeltaFromParent: null,
5961
+ eligibleForPromotion: true,
5962
+ coverage: { ...ctx.baselineOutcome.coverage }
5963
+ });
5964
+ }
5965
+ for (const record of ctx.history) {
5966
+ for (const candidate of record.candidates) {
5967
+ add({
5968
+ surfaceHash: candidate.surfaceHash,
5969
+ generation: record.generationIndex,
5970
+ composite: candidate.composite,
5971
+ parentComposite: candidate.parentComposite ?? null,
5972
+ observedDeltaFromParent: candidate.observedDeltaFromParent ?? null,
5973
+ eligibleForPromotion: candidate.eligibleForPromotion === true,
5974
+ coverage: candidate.coverage ? {
5975
+ expectedCells: candidate.coverage.expectedCells,
5976
+ scorableCells: candidate.coverage.scorableCells
5977
+ } : { expectedCells: 0, scorableCells: 0 }
5978
+ });
5979
+ }
5980
+ }
5981
+ if (ctx.incumbentOutcome) {
5982
+ const generation = ctx.incumbentOutcome.generation;
5983
+ const key = sourceKey(ctx.incumbentOutcome.surfaceHash, generation);
5984
+ if (!measurements.has(key)) {
5985
+ add({
5986
+ surfaceHash: ctx.incumbentOutcome.surfaceHash,
5987
+ generation,
5988
+ composite: ctx.incumbentOutcome.composite,
5989
+ parentComposite: null,
5990
+ observedDeltaFromParent: null,
5991
+ eligibleForPromotion: true,
5992
+ coverage: { ...ctx.incumbentOutcome.coverage }
5993
+ });
5994
+ }
5995
+ }
5996
+ return measurements;
5997
+ }
5998
+ function validateFindingSource(source, measured) {
5999
+ if (source.kind === "global") {
6000
+ requireNonEmpty(source.label, "global finding source label");
6001
+ return;
6002
+ }
6003
+ if (!measured.has(sourceKey(source.surfaceHash, source.generation))) {
6004
+ throw new Error(
6005
+ `llmPolicyEditProposer: finding source ${source.surfaceHash}@${source.generation} is not a measured surface`
6006
+ );
6007
+ }
6008
+ }
6009
+ function sameFindingSource(a, b) {
6010
+ if (a.kind !== b.kind) return false;
6011
+ return a.kind === "surface" && b.kind === "surface" ? a.surfaceHash === b.surfaceHash && a.generation === b.generation : a.kind === "global" && b.kind === "global" && a.label === b.label;
6012
+ }
6013
+ function summarizeCandidateEdit(record, scenarioIds) {
6014
+ const edit = record.policyEdit;
6015
+ return {
6016
+ editId: edit.editId,
6017
+ axis: edit.axis,
6018
+ target: sanitizeAuthorValue(edit.target, scenarioIds),
6019
+ change: sanitizeAuthorValue(edit.change, scenarioIds),
6020
+ claim: scenarioIds.sanitize(edit.claim),
6021
+ expectedGain: sanitizeAuthorValue(edit.expectedGain, scenarioIds),
6022
+ confidence: edit.confidence,
6023
+ risk: edit.risk,
6024
+ sourceFindingIds: edit.source.findingIds.map((id) => scenarioIds.sanitize(id)),
6025
+ rationale: edit.rationale ? scenarioIds.sanitize(edit.rationale) : null,
6026
+ validationPlan: edit.validationPlan ? scenarioIds.sanitize(edit.validationPlan) : null
6027
+ };
6028
+ }
6029
+ function sanitizeAuthorValue(value, scenarioIds) {
6030
+ if (typeof value === "string") return scenarioIds.sanitize(value);
6031
+ if (Array.isArray(value)) return value.map((item) => sanitizeAuthorValue(item, scenarioIds));
6032
+ if (value && typeof value === "object") {
6033
+ return Object.fromEntries(
6034
+ Object.entries(value).map(([key, child]) => [
6035
+ scenarioIds.sanitize(key),
6036
+ sanitizeAuthorValue(child, scenarioIds)
6037
+ ])
6038
+ );
6039
+ }
6040
+ return value;
6041
+ }
6042
+ function sanitizeDimensions(dimensions, scenarioIds) {
6043
+ const sanitized = /* @__PURE__ */ new Map();
6044
+ for (const [key, value] of Object.entries(dimensions)) {
6045
+ const projected = scenarioIds.sanitize(key);
6046
+ const prior = sanitized.get(projected);
6047
+ if (prior && prior.original !== key) {
6048
+ throw new Error(
6049
+ `llmPolicyEditProposer: pseudonymized dimension key collision for '${prior.original}' and '${key}'`
6050
+ );
6051
+ }
6052
+ sanitized.set(projected, { original: key, value });
6053
+ }
6054
+ return Object.fromEntries([...sanitized].map(([key, entry]) => [key, entry.value]));
6055
+ }
6056
+ function forecastCalibration(candidate, record, objectiveByKey) {
6057
+ if (!record || candidate.observedDeltaFromParent === void 0) return null;
6058
+ const forecast = record.policyEdit.expectedGain;
6059
+ const objective = objectiveByKey.get(forecast.metric);
6060
+ if (!objective || objective.key !== "search.composite") return null;
6061
+ if (forecast.direction !== objective.direction || forecast.unit !== objective.unit) return null;
6062
+ if (forecast.amount > objective.scale.max - objective.scale.min) return null;
6063
+ const predictedDelta = forecast.amount;
6064
+ return {
6065
+ objectiveKey: objective.key,
6066
+ predictedDelta,
6067
+ observedDelta: candidate.observedDeltaFromParent,
6068
+ residual: candidate.observedDeltaFromParent - predictedDelta
6069
+ };
6070
+ }
6071
+ function assertSearchOutcome(outcome, field) {
6072
+ if (outcome && outcome.split !== "search") {
6073
+ throw new Error(`llmPolicyEditProposer: ${field} must be a search-split outcome`);
6074
+ }
6075
+ }
6076
+ function assertMeasuredCompositesInScale(ctx, objective) {
6077
+ const assertInScale = (value, field) => {
6078
+ if (!Number.isFinite(value) || value < objective.scale.min || value > objective.scale.max) {
6079
+ throw new Error(
6080
+ `llmPolicyEditProposer: ${field} ${value} is outside objective '${objective.key}' scale [${objective.scale.min}, ${objective.scale.max}]`
6081
+ );
6082
+ }
6083
+ };
6084
+ const assertOutcome = (outcome, field) => {
6085
+ if (!outcome) return;
6086
+ assertInScale(outcome.composite, `${field}.composite`);
6087
+ for (const [index, scenario] of outcome.scenarios.entries()) {
6088
+ assertInScale(scenario.composite, `${field}.scenarios[${index}].composite`);
6089
+ }
6090
+ };
6091
+ assertOutcome(ctx.baselineOutcome, "baselineOutcome");
6092
+ assertOutcome(ctx.incumbentOutcome, "incumbentOutcome");
6093
+ for (const [generationIndex, generation] of ctx.history.entries()) {
6094
+ for (const [candidateIndex, candidate] of generation.candidates.entries()) {
6095
+ const field = `history[${generationIndex}].candidates[${candidateIndex}]`;
6096
+ assertInScale(candidate.composite, `${field}.composite`);
6097
+ if (candidate.parentComposite !== void 0) {
6098
+ assertInScale(candidate.parentComposite, `${field}.parentComposite`);
6099
+ }
6100
+ for (const [scenarioIndex, scenario] of candidate.scenarios.entries()) {
6101
+ assertInScale(scenario.composite, `${field}.scenarios[${scenarioIndex}].composite`);
6102
+ }
6103
+ }
6104
+ }
6105
+ }
6106
+ function assertSurfaceIsTaskAgnostic(value, scenarioIds) {
6107
+ const serialized = JSON.stringify(value);
6108
+ if (scenarioIds.sanitize(serialized) !== serialized) {
6109
+ throw new Error(
6110
+ "llmPolicyEditProposer: current JSON surface or signature contains a raw scenario identifier"
6111
+ );
6112
+ }
6113
+ }
6114
+ function registerOutcomeScenarioIds(outcome, scenarioIds) {
6115
+ for (const scenario of outcome?.scenarios ?? []) scenarioIds.project(scenario.scenarioId);
6116
+ }
6117
+ function registerHistoryScenarioIds(history, scenarioIds) {
6118
+ for (const record of history) {
6119
+ for (const candidate of record.candidates) {
6120
+ for (const scenario of candidate.scenarios) scenarioIds.project(scenario.scenarioId);
6121
+ for (const cell of candidate.coverage?.unscorableCells ?? []) {
6122
+ const separator = cell.cellId.lastIndexOf(":");
6123
+ if (separator <= 0 || !/^\d+$/.test(cell.cellId.slice(separator + 1))) continue;
6124
+ scenarioIds.project(cell.cellId.slice(0, separator));
6125
+ }
6126
+ }
6127
+ }
6128
+ }
6129
+ function validateHistoryLimits(options) {
6130
+ const maxGenerations = options.maxGenerations ?? DEFAULT_POLICY_EDIT_HISTORY_LIMITS.generations;
6131
+ const maxCandidatesPerGeneration = options.maxCandidatesPerGeneration ?? DEFAULT_POLICY_EDIT_HISTORY_LIMITS.candidatesPerGeneration;
6132
+ const maxScenariosPerCandidate = options.maxScenariosPerCandidate ?? DEFAULT_POLICY_EDIT_HISTORY_LIMITS.scenariosPerCandidate;
6133
+ if (!Number.isSafeInteger(maxGenerations) || maxGenerations <= 0) {
6134
+ throw new Error("llmPolicyEditProposer: maxHistoryGenerations must be a positive safe integer");
6135
+ }
6136
+ if (!Number.isSafeInteger(maxCandidatesPerGeneration) || maxCandidatesPerGeneration <= 0) {
6137
+ throw new Error(
6138
+ "llmPolicyEditProposer: maxHistoryCandidatesPerGeneration must be a positive safe integer"
6139
+ );
6140
+ }
6141
+ if (!Number.isSafeInteger(maxScenariosPerCandidate) || maxScenariosPerCandidate <= 0) {
6142
+ throw new Error(
6143
+ "llmPolicyEditProposer: maxScenariosPerCandidate must be a positive safe integer"
6144
+ );
6145
+ }
6146
+ return {
6147
+ maxGenerations,
6148
+ maxCandidatesPerGeneration,
6149
+ maxScenariosPerCandidate,
6150
+ scenarioIdTransform: options.scenarioIdTransform ?? ((scenarioId) => scenarioId)
6151
+ };
6152
+ }
6153
+ function validateObjectives(inputs) {
6154
+ if (inputs.length === 0) {
6155
+ throw new Error("llmPolicyEditProposer: objectives must not be empty");
6156
+ }
6157
+ const seen = /* @__PURE__ */ new Set();
6158
+ return inputs.map((input) => {
6159
+ requireNonEmpty(input.key, "objective key");
6160
+ if (seen.has(input.key)) {
6161
+ throw new Error(`llmPolicyEditProposer: duplicate objective '${input.key}'`);
6162
+ }
6163
+ seen.add(input.key);
6164
+ if (input.split !== "search") {
6165
+ throw new Error(`llmPolicyEditProposer: objective '${input.key}' must use the search split`);
6166
+ }
6167
+ if (input.key !== "search.composite") {
6168
+ throw new Error(
6169
+ `llmPolicyEditProposer: objective '${input.key}' is not yet measurable; use 'search.composite'`
6170
+ );
6171
+ }
6172
+ if (input.direction !== "increase") {
6173
+ throw new Error(
6174
+ `llmPolicyEditProposer: objective '${input.key}' must increase because search promotes larger composite scores`
6175
+ );
6176
+ }
6177
+ if (!Number.isFinite(input.scale.min) || !Number.isFinite(input.scale.max) || input.scale.max <= input.scale.min) {
6178
+ throw new Error(`llmPolicyEditProposer: objective '${input.key}' has an invalid scale`);
6179
+ }
6180
+ if (input.unit !== "score") {
6181
+ throw new Error(`llmPolicyEditProposer: objective '${input.key}' must use raw score deltas`);
6182
+ }
6183
+ return {
6184
+ key: input.key,
6185
+ split: "search",
6186
+ direction: input.direction,
6187
+ scale: { ...input.scale },
6188
+ unit: input.unit
6189
+ };
6190
+ });
6191
+ }
6192
+ function positiveLimit(value, field) {
6193
+ if (!Number.isSafeInteger(value) || value <= 0) {
6194
+ throw new Error(`llmPolicyEditProposer: ${field} must be a positive safe integer`);
6195
+ }
6196
+ return value;
6197
+ }
6198
+ function parseAuthorResponse(value) {
6199
+ const parsed = PolicyEditAuthorResponseSchema.safeParse(value);
6200
+ if (parsed.success) return parsed.data;
6201
+ const issues = parsed.error.issues.map((issue) => `${issue.path.join(".") || "<root>"}: ${issue.message}`).join("; ");
6202
+ throw new Error(`llmPolicyEditProposer: invalid PolicyEdit response: ${issues}`);
6203
+ }
6204
+ function bindAuthoredEdit(draft, findingByKey, targetSurface, allowedPaths, objectiveByKey, currentComposite) {
6205
+ if (draft.target.surface !== targetSurface) {
6206
+ throw new Error(
6207
+ `llmPolicyEditProposer: target surface '${draft.target.surface}' does not match '${targetSurface}'`
6208
+ );
6209
+ }
6210
+ if (draft.target.path !== draft.change.path) {
6211
+ throw new Error("llmPolicyEditProposer: target.path must equal change.path");
6212
+ }
6213
+ if (!allowedPaths.has(draft.change.path)) {
6214
+ throw new Error(
6215
+ `llmPolicyEditProposer: JSON path '${draft.change.path}' is outside allowedJsonPaths`
6216
+ );
6217
+ }
6218
+ const cited = draft.source.findingKeys.map((findingKey) => {
6219
+ const finding = findingByKey.get(findingKey);
6220
+ if (!finding) {
6221
+ throw new Error(
6222
+ `llmPolicyEditProposer: edit cites unknown or uncitable finding key '${findingKey}'`
6223
+ );
6224
+ }
6225
+ return finding;
6226
+ });
6227
+ const evidenceRefs = uniqueEvidenceRefs(cited.flatMap((finding) => finding.evidenceRefs));
6228
+ if (evidenceRefs.length === 0) {
6229
+ throw new Error("llmPolicyEditProposer: authored edit has no cited evidence");
6230
+ }
6231
+ const objective = objectiveByKey.get(draft.expectedGain.metric);
6232
+ if (!objective) {
6233
+ throw new Error(
6234
+ `llmPolicyEditProposer: unknown forecast objective '${draft.expectedGain.metric}'`
6235
+ );
6236
+ }
6237
+ if (draft.expectedGain.direction !== objective.direction) {
6238
+ throw new Error(
6239
+ `llmPolicyEditProposer: forecast direction for '${objective.key}' must be '${objective.direction}'`
6240
+ );
6241
+ }
6242
+ if (draft.expectedGain.unit !== objective.unit) {
6243
+ throw new Error(
6244
+ `llmPolicyEditProposer: forecast unit for '${objective.key}' must be '${objective.unit}'`
6245
+ );
6246
+ }
6247
+ const maxGain = currentComposite === void 0 ? objective.scale.max - objective.scale.min : objective.scale.max - currentComposite;
6248
+ if (draft.expectedGain.amount > maxGain) {
6249
+ throw new Error(
6250
+ `llmPolicyEditProposer: forecast amount for '${objective.key}' exceeds the available score headroom`
6251
+ );
6252
+ }
6253
+ const expectedGain = {
6254
+ metric: draft.expectedGain.metric,
6255
+ direction: draft.expectedGain.direction,
6256
+ amount: draft.expectedGain.amount,
6257
+ ...draft.expectedGain.unit ? { unit: draft.expectedGain.unit } : {},
6258
+ ...draft.expectedGain.rationale ? { rationale: draft.expectedGain.rationale } : {}
6259
+ };
6260
+ const init = {
6261
+ axis: draft.axis,
6262
+ target: {
6263
+ surface: draft.target.surface,
6264
+ path: draft.target.path,
6265
+ ...draft.target.label ? { label: draft.target.label } : {}
6266
+ },
6267
+ change: draft.change,
6268
+ claim: draft.claim,
6269
+ expectedGain,
6270
+ confidence: draft.confidence,
6271
+ risk: draft.risk,
6272
+ source: {
6273
+ findingIds: [...new Set(cited.map((finding) => finding.finding.finding_id))],
6274
+ analystIds: [...new Set(cited.map((finding) => finding.finding.analyst_id))],
6275
+ evidenceRefs
6276
+ },
6277
+ ...draft.rationale ? { rationale: draft.rationale } : {},
6278
+ ...draft.validationPlan ? { validationPlan: draft.validationPlan } : {}
6279
+ };
6280
+ return makePolicyEdit(init);
6281
+ }
6282
+ function parseJsonSurface(surface) {
6283
+ if (typeof surface !== "string") {
6284
+ throw new Error("llmPolicyEditProposer: currentSurface must be serialized JSON");
6285
+ }
6286
+ let parsed;
6287
+ try {
6288
+ parsed = JSON.parse(surface);
6289
+ } catch {
6290
+ throw new Error("llmPolicyEditProposer: currentSurface must be valid JSON");
6291
+ }
6292
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
6293
+ throw new Error("llmPolicyEditProposer: currentSurface JSON root must be an object");
6294
+ }
6295
+ return parsed;
6296
+ }
6297
+ function citableFindings(inputs, measuredSources, limit) {
6298
+ if (inputs.length === 0) {
6299
+ throw new Error("llmPolicyEditProposer: at least one analyst finding is required");
6300
+ }
6301
+ const findings = [];
6302
+ for (const input of inputs) {
6303
+ if (!isPolicyEditFindingInput(input)) {
6304
+ throw new Error(
6305
+ "llmPolicyEditProposer: ctx.findings must contain attributed PolicyEditFindingInput rows"
6306
+ );
6307
+ }
6308
+ findings.push(input.finding);
6309
+ }
6310
+ assertNoJudgeVerdict(findings, "llmPolicyEditProposer");
6311
+ const grouped = /* @__PURE__ */ new Map();
6312
+ for (const input of inputs) {
6313
+ validateFindingSource(input.source, measuredSources);
6314
+ if (input.finding.evidence_refs.length === 0) continue;
6315
+ const existing = grouped.get(input.finding.finding_id);
6316
+ if (existing) {
6317
+ if (existing.finding.analyst_id !== input.finding.analyst_id || existing.finding.area !== input.finding.area || existing.finding.claim !== input.finding.claim || existing.finding.subject !== input.finding.subject) {
6318
+ throw new Error(
6319
+ `llmPolicyEditProposer: finding '${input.finding.finding_id}' has conflicting content`
6320
+ );
6321
+ }
6322
+ if (!existing.sources.some((source) => sameFindingSource(source, input.source))) {
6323
+ existing.sources.push(input.source);
6324
+ }
6325
+ existing.evidenceRefs = uniqueEvidenceRefs([
6326
+ ...existing.evidenceRefs,
6327
+ ...input.finding.evidence_refs
6328
+ ]);
6329
+ continue;
6330
+ }
6331
+ grouped.set(input.finding.finding_id, {
6332
+ finding: input.finding,
6333
+ sources: [input.source],
6334
+ evidenceRefs: uniqueEvidenceRefs(input.finding.evidence_refs)
6335
+ });
6336
+ }
6337
+ if (grouped.size === 0) {
6338
+ throw new Error("llmPolicyEditProposer: no evidence-bearing findings are available");
6339
+ }
6340
+ const severityRank = {
6341
+ critical: 0,
6342
+ high: 1,
6343
+ medium: 2,
6344
+ low: 3,
6345
+ info: 4
6346
+ };
6347
+ return [...grouped.values()].sort(
6348
+ (a, b) => severityRank[a.finding.severity] - severityRank[b.finding.severity] || b.finding.confidence - a.finding.confidence || a.finding.finding_id.localeCompare(b.finding.finding_id)
6349
+ ).slice(0, limit);
6350
+ }
6351
+ function isAnalystFindingLike2(input) {
6352
+ if (!input || typeof input !== "object") return false;
6353
+ const value = input;
6354
+ return typeof value.finding_id === "string" && typeof value.analyst_id === "string" && typeof value.claim === "string" && Array.isArray(value.evidence_refs);
6355
+ }
6356
+ function isPolicyEditFindingInput(input) {
6357
+ if (!input || typeof input !== "object") return false;
6358
+ const value = input;
6359
+ return isAnalystFindingLike2(value.finding) && isFindingSource(value.source);
6360
+ }
6361
+ function isFindingSource(input) {
6362
+ if (!input || typeof input !== "object") return false;
6363
+ const value = input;
6364
+ if (value.kind === "surface") {
6365
+ return typeof value.surfaceHash === "string" && Number.isSafeInteger(value.generation);
6366
+ }
6367
+ return value.kind === "global" && typeof value.label === "string" && value.label.trim().length > 0;
6368
+ }
6369
+ function renderFinding(context, findingKey, scenarioIds, measuredSources) {
6370
+ const { finding } = context;
6371
+ return {
6372
+ findingKey,
6373
+ sources: context.sources.map(
6374
+ (source) => source.kind === "surface" ? {
6375
+ ...measuredSources.get(sourceKey(source.surfaceHash, source.generation)),
6376
+ surfaceHash: scenarioIds.sanitize(source.surfaceHash),
6377
+ kind: "surface"
6378
+ } : { kind: "global", label: scenarioIds.sanitize(source.label) }
6379
+ ),
6380
+ analystId: scenarioIds.sanitize(finding.analyst_id),
6381
+ area: scenarioIds.sanitize(finding.area),
6382
+ severity: finding.severity,
6383
+ subject: finding.subject ? scenarioIds.sanitize(finding.subject) : null,
6384
+ claim: scenarioIds.sanitize(finding.claim),
6385
+ rationale: finding.rationale ? scenarioIds.sanitize(finding.rationale) : null,
6386
+ recommendedAction: finding.recommended_action ? scenarioIds.sanitize(finding.recommended_action) : null,
6387
+ validationPlan: finding.validation_plan ? scenarioIds.sanitize(finding.validation_plan) : null,
6388
+ confidence: finding.confidence,
6389
+ evidenceRefs: context.evidenceRefs.map((ref) => ({
6390
+ kind: ref.kind,
6391
+ uri: scenarioIds.sanitize(ref.uri),
6392
+ excerpt: ref.excerpt ? scenarioIds.sanitize(ref.excerpt) : null
6393
+ }))
6394
+ };
6395
+ }
6396
+ function uniqueEvidenceRefs(refs) {
6397
+ const seen = /* @__PURE__ */ new Set();
6398
+ return refs.filter((ref) => {
6399
+ const key = JSON.stringify([ref.kind, ref.uri, ref.excerpt ?? null]);
6400
+ if (seen.has(key)) return false;
6401
+ seen.add(key);
6402
+ return true;
6403
+ });
6404
+ }
6405
+ function validateAllowedJsonPaths(paths) {
6406
+ if (paths.length === 0) {
6407
+ throw new Error("llmPolicyEditProposer: allowedJsonPaths must not be empty");
6408
+ }
6409
+ for (const path of paths) {
6410
+ if (!path || path.trim() !== path) {
6411
+ throw new Error(
6412
+ "llmPolicyEditProposer: allowedJsonPaths must contain trimmed non-empty paths"
6413
+ );
6414
+ }
6415
+ }
6416
+ if (new Set(paths).size !== paths.length) {
6417
+ throw new Error("llmPolicyEditProposer: allowedJsonPaths must be unique");
6418
+ }
6419
+ return [...paths];
6420
+ }
6421
+ function requireNonEmpty(value, field) {
6422
+ if (!value || value.trim() !== value) {
6423
+ throw new Error(`llmPolicyEditProposer: ${field} must be a trimmed non-empty string`);
6424
+ }
6425
+ }
6426
+
5267
6427
  // src/campaign/proposers/memory.ts
5268
6428
  var BLOCK_START2 = "<!-- BEGIN curated-memory (auto-managed by memoryCurationProposer) -->";
5269
6429
  var BLOCK_END2 = "<!-- END curated-memory -->";
@@ -5344,69 +6504,6 @@ ${block}
5344
6504
  };
5345
6505
  }
5346
6506
 
5347
- // src/campaign/proposers/policy-edit.ts
5348
- function policyEditProposer(opts = {}) {
5349
- return {
5350
- kind: "policy-edit",
5351
- async propose(ctx) {
5352
- const edits = materializePolicyEdits(opts.edits ?? ctx.findings, opts.findingOptions);
5353
- const limit = Math.max(
5354
- 0,
5355
- Math.min(opts.maxCandidates ?? ctx.populationSize, ctx.populationSize)
5356
- );
5357
- const out = [];
5358
- if (limit === 0) return out;
5359
- for (const edit of edits) {
5360
- const admission = admitPolicyEdit(edit, opts.admission);
5361
- opts.onAdmission?.(admission);
5362
- if (admission.decision !== "admit") continue;
5363
- const surface = coerceCandidateSurface(applyPolicyEditToSurface(ctx.currentSurface, edit));
5364
- if (sameSurface(ctx.currentSurface, surface)) continue;
5365
- out.push({
5366
- surface,
5367
- label: `policy-edit:${edit.axis}`,
5368
- rationale: `${edit.editId} expected ${edit.expectedGain.direction} ${edit.expectedGain.metric} by ${edit.expectedGain.amount}; source findings [${edit.source.findingIds.join(", ")}]`
5369
- });
5370
- if (out.length >= limit) break;
5371
- }
5372
- return out;
5373
- }
5374
- };
5375
- }
5376
- function materializePolicyEdits(inputs, findingOptions) {
5377
- const edits = [];
5378
- const findings = [];
5379
- for (const input of inputs) {
5380
- if (isPolicyEdit(input)) {
5381
- edits.push(input);
5382
- } else if (isAnalystFindingLike(input)) {
5383
- findings.push(input);
5384
- }
5385
- }
5386
- if (findings.length > 0) edits.push(...policyEditsFromFindings(findings, findingOptions));
5387
- return edits;
5388
- }
5389
- function isAnalystFindingLike(input) {
5390
- if (!input || typeof input !== "object") return false;
5391
- const obj = input;
5392
- return typeof obj.finding_id === "string" && typeof obj.analyst_id === "string" && typeof obj.claim === "string" && Array.isArray(obj.evidence_refs);
5393
- }
5394
- function coerceCandidateSurface(surface) {
5395
- if (typeof surface === "string") return surface;
5396
- if (surface && typeof surface === "object") {
5397
- const obj = surface;
5398
- if (obj.kind === "code" && typeof obj.worktreeRef === "string") {
5399
- assertCodeSurfaceIdentity(surface);
5400
- return surface;
5401
- }
5402
- return JSON.stringify(surface, null, 2);
5403
- }
5404
- throw new Error("policyEditProposer: policy edit produced an unsupported surface");
5405
- }
5406
- function sameSurface(a, b) {
5407
- return surfaceContentHash(a) === surfaceContentHash(b);
5408
- }
5409
-
5410
6507
  // src/campaign/proposers/trace-analyst.ts
5411
6508
  import { ai } from "@ax-llm/ax";
5412
6509
  function renderFindings(findings) {
@@ -5518,7 +6615,7 @@ function selectDiscriminative(signals, k, opts) {
5518
6615
  import { createHash as createHash7 } from "crypto";
5519
6616
  import { existsSync as existsSync4, readFileSync as readFileSync4 } from "fs";
5520
6617
  import { resolve as resolve2 } from "path";
5521
- import { z as z2 } from "zod";
6618
+ import { z as z3 } from "zod";
5522
6619
 
5523
6620
  // src/campaign/search-ledger-errors.ts
5524
6621
  var SearchLedgerError = class extends ValidationError {
@@ -5545,7 +6642,7 @@ import {
5545
6642
  } from "fs";
5546
6643
  import { hostname } from "os";
5547
6644
  import { dirname as dirname2 } from "path";
5548
- import { z } from "zod";
6645
+ import { z as z2 } from "zod";
5549
6646
  function appendSearchLedgerLine(path, line) {
5550
6647
  mkdirSync2(dirname2(path), { recursive: true });
5551
6648
  const fd = openSync(path, constants.O_CREAT | constants.O_WRONLY | constants.O_APPEND, 384);
@@ -5639,10 +6736,10 @@ function readOwner(lockPath) {
5639
6736
  cause: error
5640
6737
  });
5641
6738
  }
5642
- const parsed = z.object({
5643
- pid: z.number().int().positive().safe(),
5644
- host: z.string().trim().min(1),
5645
- nonce: z.string().trim().min(1)
6739
+ const parsed = z2.object({
6740
+ pid: z2.number().int().positive().safe(),
6741
+ host: z2.string().trim().min(1),
6742
+ nonce: z2.string().trim().min(1)
5646
6743
  }).strict().safeParse(raw);
5647
6744
  if (!parsed.success) {
5648
6745
  throw new SearchLedgerIntegrityError(
@@ -5672,82 +6769,82 @@ function unlinkIfExists(path) {
5672
6769
 
5673
6770
  // src/campaign/search-ledger.ts
5674
6771
  var SEARCH_LEDGER_SCHEMA = "tangle.search-ledger.v1";
5675
- var NON_EMPTY = z2.string().min(1).refine((value) => value.trim() === value, "must not contain surrounding whitespace");
5676
- var HASH = z2.string().regex(/^sha256:[a-f0-9]{64}$/);
5677
- var LINEAGE_NODE_ID = z2.string().regex(/^[a-f0-9]{16}$/);
5678
- var IMMUTABLE_REVISION = z2.string().regex(/^(?:[a-f0-9]{40}|[a-f0-9]{64}|sha256:[a-f0-9]{64}|sha512:[A-Za-z0-9+/=]+)$/);
5679
- var ISO_TIMESTAMP = z2.string().regex(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z$/).refine((value) => Number.isFinite(Date.parse(value)), "invalid timestamp");
5680
- var NON_NEGATIVE_INT = z2.number().int().nonnegative().safe();
5681
- var FINITE_NUMBER = z2.number().finite();
5682
- var ArtifactRefSchema = z2.object({
6772
+ var NON_EMPTY = z3.string().min(1).refine((value) => value.trim() === value, "must not contain surrounding whitespace");
6773
+ var HASH = z3.string().regex(/^sha256:[a-f0-9]{64}$/);
6774
+ var LINEAGE_NODE_ID = z3.string().regex(/^[a-f0-9]{16}$/);
6775
+ var IMMUTABLE_REVISION = z3.string().regex(/^(?:[a-f0-9]{40}|[a-f0-9]{64}|sha256:[a-f0-9]{64}|sha512:[A-Za-z0-9+/=]+)$/);
6776
+ var ISO_TIMESTAMP = z3.string().regex(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z$/).refine((value) => Number.isFinite(Date.parse(value)), "invalid timestamp");
6777
+ var NON_NEGATIVE_INT = z3.number().int().nonnegative().safe();
6778
+ var FINITE_NUMBER = z3.number().finite();
6779
+ var ArtifactRefSchema = z3.object({
5683
6780
  role: NON_EMPTY,
5684
6781
  uri: NON_EMPTY,
5685
6782
  sha256: HASH,
5686
6783
  byteLength: NON_NEGATIVE_INT
5687
6784
  }).strict();
5688
- var SourceRefSchema = z2.object({
6785
+ var SourceRefSchema = z3.object({
5689
6786
  uri: NON_EMPTY,
5690
6787
  revision: IMMUTABLE_REVISION
5691
6788
  }).strict();
5692
- var FailureReasonSchema = z2.object({
6789
+ var FailureReasonSchema = z3.object({
5693
6790
  code: NON_EMPTY,
5694
6791
  message: NON_EMPTY
5695
6792
  }).strict();
5696
6793
  var EventBaseShape = {
5697
6794
  eventId: NON_EMPTY,
5698
6795
  occurredAt: ISO_TIMESTAMP,
5699
- artifacts: z2.array(ArtifactRefSchema).min(1)
6796
+ artifacts: z3.array(ArtifactRefSchema).min(1)
5700
6797
  };
5701
- var OperationKindSchema = z2.enum([
6798
+ var OperationKindSchema = z3.enum([
5702
6799
  "candidate-generation",
5703
6800
  "analysis",
5704
6801
  "selection",
5705
6802
  "judge",
5706
6803
  "other"
5707
6804
  ]);
5708
- var SearchPlannedSchema = z2.object({
6805
+ var SearchPlannedSchema = z3.object({
5709
6806
  ...EventBaseShape,
5710
- kind: z2.literal("search-planned"),
5711
- plan: z2.object({
5712
- candidateSlots: z2.array(
5713
- z2.object({
6807
+ kind: z3.literal("search-planned"),
6808
+ plan: z3.object({
6809
+ candidateSlots: z3.array(
6810
+ z3.object({
5714
6811
  slotId: NON_EMPTY,
5715
6812
  generationOperationId: NON_EMPTY
5716
6813
  }).strict()
5717
6814
  ).min(1),
5718
- tasks: z2.array(
5719
- z2.object({
6815
+ tasks: z3.array(
6816
+ z3.object({
5720
6817
  taskId: NON_EMPTY,
5721
6818
  source: SourceRefSchema,
5722
6819
  benchmark: SourceRefSchema,
5723
- maxAttempts: z2.number().int().positive().safe()
6820
+ maxAttempts: z3.number().int().positive().safe()
5724
6821
  }).strict()
5725
6822
  ).min(1),
5726
- operations: z2.array(
5727
- z2.object({
6823
+ operations: z3.array(
6824
+ z3.object({
5728
6825
  operationId: NON_EMPTY,
5729
6826
  kind: OperationKindSchema
5730
6827
  }).strict()
5731
6828
  ).min(1)
5732
6829
  }).strict()
5733
6830
  }).strict();
5734
- var CandidateRegisteredSchema = z2.object({
6831
+ var CandidateRegisteredSchema = z3.object({
5735
6832
  ...EventBaseShape,
5736
- kind: z2.literal("candidate-registered"),
6833
+ kind: z3.literal("candidate-registered"),
5737
6834
  slotId: NON_EMPTY,
5738
6835
  generationOperationId: NON_EMPTY,
5739
6836
  candidateId: NON_EMPTY,
5740
- lineage: z2.object({
6837
+ lineage: z3.object({
5741
6838
  lineageNodeId: LINEAGE_NODE_ID,
5742
- parentCandidateIds: z2.array(NON_EMPTY),
6839
+ parentCandidateIds: z3.array(NON_EMPTY),
5743
6840
  generation: NON_NEGATIVE_INT,
5744
6841
  proposer: NON_EMPTY,
5745
6842
  proposerSource: SourceRefSchema
5746
6843
  }).strict(),
5747
- surfaces: z2.array(
5748
- z2.object({
6844
+ surfaces: z3.array(
6845
+ z3.object({
5749
6846
  surfaceId: NON_EMPTY,
5750
- kind: z2.enum([
6847
+ kind: z3.enum([
5751
6848
  "prompt",
5752
6849
  "tool-contract",
5753
6850
  "runtime-config",
@@ -5761,69 +6858,69 @@ var CandidateRegisteredSchema = z2.object({
5761
6858
  }).strict()
5762
6859
  ).min(1)
5763
6860
  }).strict();
5764
- var CandidateSlotClosedSchema = z2.object({
6861
+ var CandidateSlotClosedSchema = z3.object({
5765
6862
  ...EventBaseShape,
5766
- kind: z2.literal("candidate-slot-closed"),
6863
+ kind: z3.literal("candidate-slot-closed"),
5767
6864
  slotId: NON_EMPTY,
5768
6865
  generationOperationId: NON_EMPTY,
5769
6866
  reason: FailureReasonSchema
5770
6867
  }).strict();
5771
- var KnownTokensSchema = z2.object({
5772
- status: z2.literal("known"),
6868
+ var KnownTokensSchema = z3.object({
6869
+ status: z3.literal("known"),
5773
6870
  inputTokens: NON_NEGATIVE_INT,
5774
6871
  outputTokens: NON_NEGATIVE_INT,
5775
6872
  cachedTokens: NON_NEGATIVE_INT
5776
6873
  }).strict();
5777
- var UnknownSchema = z2.object({
5778
- status: z2.literal("unknown"),
6874
+ var UnknownSchema = z3.object({
6875
+ status: z3.literal("unknown"),
5779
6876
  reason: NON_EMPTY
5780
6877
  }).strict();
5781
- var KnownCostSchema = z2.object({
5782
- status: z2.literal("known"),
5783
- usd: z2.number().finite().nonnegative(),
5784
- source: z2.enum(["provider", "pricing-table", "free"])
6878
+ var KnownCostSchema = z3.object({
6879
+ status: z3.literal("known"),
6880
+ usd: z3.number().finite().nonnegative(),
6881
+ source: z3.enum(["provider", "pricing-table", "free"])
5785
6882
  }).strict().superRefine((cost, ctx) => {
5786
6883
  if (cost.source === "free" && cost.usd !== 0) {
5787
6884
  ctx.addIssue({ code: "custom", message: "free cost source must have usd 0" });
5788
6885
  }
5789
6886
  });
5790
- var UnknownCostSchema = z2.object({
5791
- status: z2.literal("unknown"),
5792
- knownLowerBoundUsd: z2.number().finite().nonnegative(),
6887
+ var UnknownCostSchema = z3.object({
6888
+ status: z3.literal("unknown"),
6889
+ knownLowerBoundUsd: z3.number().finite().nonnegative(),
5793
6890
  reason: NON_EMPTY
5794
6891
  }).strict();
5795
- var AccountingSchema = z2.object({
5796
- tokens: z2.discriminatedUnion("status", [KnownTokensSchema, UnknownSchema]),
5797
- cost: z2.discriminatedUnion("status", [KnownCostSchema, UnknownCostSchema])
6892
+ var AccountingSchema = z3.object({
6893
+ tokens: z3.discriminatedUnion("status", [KnownTokensSchema, UnknownSchema]),
6894
+ cost: z3.discriminatedUnion("status", [KnownCostSchema, UnknownCostSchema])
5798
6895
  }).strict();
5799
- var MetricsSchema = z2.record(NON_EMPTY, FINITE_NUMBER).superRefine((metrics, ctx) => {
6896
+ var MetricsSchema = z3.record(NON_EMPTY, FINITE_NUMBER).superRefine((metrics, ctx) => {
5800
6897
  for (const key of Object.keys(metrics)) {
5801
6898
  if (key === "__proto__" || key === "constructor" || key === "prototype") {
5802
6899
  ctx.addIssue({ code: "custom", message: `unsafe metric key ${key}` });
5803
6900
  }
5804
6901
  }
5805
6902
  });
5806
- var OutcomeSchema = z2.discriminatedUnion("status", [
5807
- z2.object({
5808
- status: z2.literal("passed"),
6903
+ var OutcomeSchema = z3.discriminatedUnion("status", [
6904
+ z3.object({
6905
+ status: z3.literal("passed"),
5809
6906
  score: FINITE_NUMBER,
5810
6907
  metrics: MetricsSchema
5811
6908
  }).strict(),
5812
- z2.object({
5813
- status: z2.literal("failed"),
6909
+ z3.object({
6910
+ status: z3.literal("failed"),
5814
6911
  score: FINITE_NUMBER,
5815
6912
  metrics: MetricsSchema,
5816
6913
  failure: FailureReasonSchema
5817
6914
  }).strict(),
5818
- z2.object({
5819
- status: z2.literal("errored"),
6915
+ z3.object({
6916
+ status: z3.literal("errored"),
5820
6917
  metrics: MetricsSchema,
5821
- error: FailureReasonSchema.extend({ retryable: z2.boolean() }).strict()
6918
+ error: FailureReasonSchema.extend({ retryable: z3.boolean() }).strict()
5822
6919
  }).strict()
5823
6920
  ]);
5824
- var EffectSchema = z2.discriminatedUnion("status", [
5825
- z2.object({
5826
- status: z2.literal("measured"),
6921
+ var EffectSchema = z3.discriminatedUnion("status", [
6922
+ z3.object({
6923
+ status: z3.literal("measured"),
5827
6924
  metric: NON_EMPTY,
5828
6925
  baselineValue: FINITE_NUMBER,
5829
6926
  candidateValue: FINITE_NUMBER,
@@ -5835,17 +6932,17 @@ var EffectSchema = z2.discriminatedUnion("status", [
5835
6932
  ctx.addIssue({ code: "custom", message: "delta must equal candidateValue - baselineValue" });
5836
6933
  }
5837
6934
  }),
5838
- z2.object({
5839
- status: z2.literal("not-measured"),
6935
+ z3.object({
6936
+ status: z3.literal("not-measured"),
5840
6937
  reason: NON_EMPTY
5841
6938
  }).strict()
5842
6939
  ]);
5843
- var SurfaceEvidenceSchema = z2.object({
6940
+ var SurfaceEvidenceSchema = z3.object({
5844
6941
  surfaceId: NON_EMPTY,
5845
- fired: z2.boolean(),
6942
+ fired: z3.boolean(),
5846
6943
  firingCount: NON_NEGATIVE_INT,
5847
6944
  effect: EffectSchema,
5848
- evidence: z2.array(ArtifactRefSchema).min(1)
6945
+ evidence: z3.array(ArtifactRefSchema).min(1)
5849
6946
  }).strict().superRefine((evidence, ctx) => {
5850
6947
  if (evidence.fired && evidence.firingCount === 0) {
5851
6948
  ctx.addIssue({ code: "custom", message: "a fired surface must have firingCount >= 1" });
@@ -5863,15 +6960,15 @@ var SurfaceEvidenceSchema = z2.object({
5863
6960
  });
5864
6961
  }
5865
6962
  });
5866
- var TaskAttemptedSchema = z2.object({
6963
+ var TaskAttemptedSchema = z3.object({
5867
6964
  ...EventBaseShape,
5868
- kind: z2.literal("task-attempted"),
6965
+ kind: z3.literal("task-attempted"),
5869
6966
  candidateId: NON_EMPTY,
5870
6967
  runId: NON_EMPTY,
5871
6968
  attemptIndex: NON_NEGATIVE_INT,
5872
- task: z2.object({ taskId: NON_EMPTY, source: SourceRefSchema }).strict(),
5873
- identity: z2.object({
5874
- model: z2.object({
6969
+ task: z3.object({ taskId: NON_EMPTY, source: SourceRefSchema }).strict(),
6970
+ identity: z3.object({
6971
+ model: z3.object({
5875
6972
  provider: NON_EMPTY,
5876
6973
  snapshot: NON_EMPTY.refine(
5877
6974
  modelHasSnapshot,
@@ -5883,17 +6980,17 @@ var TaskAttemptedSchema = z2.object({
5883
6980
  }).strict(),
5884
6981
  outcome: OutcomeSchema,
5885
6982
  accounting: AccountingSchema,
5886
- surfaceEvidence: z2.array(SurfaceEvidenceSchema).min(1)
6983
+ surfaceEvidence: z3.array(SurfaceEvidenceSchema).min(1)
5887
6984
  }).strict();
5888
- var SearchOperationRecordedSchema = z2.object({
6985
+ var SearchOperationRecordedSchema = z3.object({
5889
6986
  ...EventBaseShape,
5890
- kind: z2.literal("search-operation-recorded"),
6987
+ kind: z3.literal("search-operation-recorded"),
5891
6988
  operationId: NON_EMPTY,
5892
6989
  operationKind: OperationKindSchema,
5893
- execution: z2.discriminatedUnion("kind", [
5894
- z2.object({
5895
- kind: z2.literal("model"),
5896
- model: z2.object({
6990
+ execution: z3.discriminatedUnion("kind", [
6991
+ z3.object({
6992
+ kind: z3.literal("model"),
6993
+ model: z3.object({
5897
6994
  provider: NON_EMPTY,
5898
6995
  snapshot: NON_EMPTY.refine(
5899
6996
  modelHasSnapshot,
@@ -5902,51 +6999,51 @@ var SearchOperationRecordedSchema = z2.object({
5902
6999
  }).strict(),
5903
7000
  source: SourceRefSchema
5904
7001
  }).strict(),
5905
- z2.object({
5906
- kind: z2.literal("deterministic"),
7002
+ z3.object({
7003
+ kind: z3.literal("deterministic"),
5907
7004
  source: SourceRefSchema
5908
7005
  }).strict()
5909
7006
  ]),
5910
- outcome: z2.discriminatedUnion("status", [
5911
- z2.object({ status: z2.literal("completed") }).strict(),
5912
- z2.object({
5913
- status: z2.literal("partial"),
7007
+ outcome: z3.discriminatedUnion("status", [
7008
+ z3.object({ status: z3.literal("completed") }).strict(),
7009
+ z3.object({
7010
+ status: z3.literal("partial"),
5914
7011
  failure: FailureReasonSchema
5915
7012
  }).strict(),
5916
- z2.object({
5917
- status: z2.literal("failed"),
7013
+ z3.object({
7014
+ status: z3.literal("failed"),
5918
7015
  failure: FailureReasonSchema
5919
7016
  }).strict()
5920
7017
  ]),
5921
7018
  accounting: AccountingSchema
5922
7019
  }).strict();
5923
- var CandidateDecidedSchema = z2.object({
7020
+ var CandidateDecidedSchema = z3.object({
5924
7021
  ...EventBaseShape,
5925
- kind: z2.literal("candidate-decided"),
7022
+ kind: z3.literal("candidate-decided"),
5926
7023
  candidateId: NON_EMPTY,
5927
- decision: z2.discriminatedUnion("status", [
5928
- z2.object({ status: z2.literal("selected") }).strict(),
5929
- z2.object({
5930
- status: z2.literal("rejected"),
7024
+ decision: z3.discriminatedUnion("status", [
7025
+ z3.object({ status: z3.literal("selected") }).strict(),
7026
+ z3.object({
7027
+ status: z3.literal("rejected"),
5931
7028
  reason: FailureReasonSchema
5932
7029
  }).strict()
5933
7030
  ])
5934
7031
  }).strict();
5935
- var SearchCompletedSchema = z2.object({
7032
+ var SearchCompletedSchema = z3.object({
5936
7033
  ...EventBaseShape,
5937
- kind: z2.literal("search-completed"),
5938
- result: z2.discriminatedUnion("status", [
5939
- z2.object({
5940
- status: z2.literal("selected"),
7034
+ kind: z3.literal("search-completed"),
7035
+ result: z3.discriminatedUnion("status", [
7036
+ z3.object({
7037
+ status: z3.literal("selected"),
5941
7038
  candidateId: NON_EMPTY
5942
7039
  }).strict(),
5943
- z2.object({
5944
- status: z2.literal("all-rejected"),
7040
+ z3.object({
7041
+ status: z3.literal("all-rejected"),
5945
7042
  reason: FailureReasonSchema
5946
7043
  }).strict()
5947
7044
  ])
5948
7045
  }).strict();
5949
- var EventSchema = z2.discriminatedUnion("kind", [
7046
+ var EventSchema = z3.discriminatedUnion("kind", [
5950
7047
  SearchPlannedSchema,
5951
7048
  CandidateRegisteredSchema,
5952
7049
  CandidateSlotClosedSchema,
@@ -5955,11 +7052,11 @@ var EventSchema = z2.discriminatedUnion("kind", [
5955
7052
  CandidateDecidedSchema,
5956
7053
  SearchCompletedSchema
5957
7054
  ]);
5958
- var EntrySchema = z2.object({
5959
- schema: z2.literal(SEARCH_LEDGER_SCHEMA),
7055
+ var EntrySchema = z3.object({
7056
+ schema: z3.literal(SEARCH_LEDGER_SCHEMA),
5960
7057
  campaignId: NON_EMPTY,
5961
7058
  sequence: NON_NEGATIVE_INT,
5962
- previousHash: z2.union([HASH, z2.null()]),
7059
+ previousHash: z3.union([HASH, z3.null()]),
5963
7060
  event: EventSchema,
5964
7061
  entryHash: HASH
5965
7062
  }).strict();
@@ -7297,8 +8394,13 @@ export {
7297
8394
  aceProposer,
7298
8395
  compositeProposer,
7299
8396
  haloProposer,
7300
- memoryCurationProposer,
7301
8397
  policyEditProposer,
8398
+ selectPolicyEditAuthorRows,
8399
+ assertPolicyEditAuthorContextBudget,
8400
+ DEFAULT_POLICY_EDIT_HISTORY_LIMITS,
8401
+ llmPolicyEditProposer,
8402
+ projectPolicyEditHistory,
8403
+ memoryCurationProposer,
7302
8404
  traceAnalystProposer,
7303
8405
  scoreDiscrimination,
7304
8406
  selectDiscriminative,
@@ -7316,4 +8418,4 @@ export {
7316
8418
  verifyCodeSurface,
7317
8419
  resolveWorktreePath
7318
8420
  };
7319
- //# sourceMappingURL=chunk-KG4TD7EQ.js.map
8421
+ //# sourceMappingURL=chunk-GSW3OBHK.js.map