harn-stdlib 0.10.96

Embedded Harn standard library source catalog
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
// std/agent/crystallization_curator.harn
//
// Agentic write-side of cross-session crystallization. Pattern memory supplies
// bounded evidence; a normal Harn agent loop decides whether and how to turn it
// into a reusable skill, MCP tool, workflow, or hybrid. Deterministic code only
// validates the terminal proposal contract and evidence membership.
import { agent_loop } from "std/agent/loop"
import {
  pattern_learning_observations,
  pattern_learning_pending,
  pattern_learning_record_curated_batch,
} from "std/agent/pattern_knowledge"
import { command_run } from "std/command"
import { tool_registry_from } from "std/tools"

const CURATOR_SCHEMA = "harn.crystallization.curator.v1"

const CURATOR_VALIDATION_TIMEOUT_MS: int = 120000

fn cc_text(value) -> string {
  return regex_replace(r"\s+", " ", to_string(value ?? "").trim())
    ?? to_string(value ?? "").trim()
}

/**
 * Run trusted, fixed-argv toolchain commands under the curator's owning
 * capability sandbox. `workspace_paths` retains Harn's in-process filesystem
 * and launch-cwd checks while avoiding an unsupported nested macOS sandbox-exec
 * around the fixed Harn argv. Candidate effects remain capability mediated.
 */
fn cc_toolchain_command_options(overrides = nil) -> dict {
  const cwd = cc_text(overrides?.cwd)
  const isolated_runtime = if cwd == "" {
    {LANG: "en_US.UTF-8", TERM: "dumb"}
  } else {
    {
      HARN_PROJECT_ROOT: cwd,
      HARN_STATE_DIR: path_join(cwd, ".harn-state"),
      LANG: "en_US.UTF-8",
      TERM: "dumb",
    }
  }
  return {sandbox_profile: "workspace_paths", env_mode: "replace", env: isolated_runtime}
    + (overrides
    ?? {})
}

fn cc_recent_evidence(harness: Harness, options = nil) -> list {
  const supplied = options?.evidence
  const all = if type_of(supplied) == "list" {
    supplied
  } else {
    pattern_learning_observations(harness, options)
  }
  const limit = min(max(1, options?.evidence_limit ?? 12), 40)
  const start = max(0, len(all) - limit)
  return all[start:len(all)]
}

fn cc_evidence_cards(evidence: list) -> list {
  return (evidence ?? []).map(
    { item ->
      return {
        id: item?.id,
        session_id: item?.session_id,
        prompt: item?.prompt,
        tool_sequence: item?.tool_sequence ?? [],
        observed_at: item?.observed_at,
        outcome: item?.outcome,
      }
    },
  )
    .to_list()
}

fn cc_session_ids(evidence: list) -> list {
  let out = []
  for item in evidence ?? [] {
    const id = cc_text(item?.session_id)
    if id != "" && !out.contains(id) {
      out = out + [id]
    }
  }
  return out
}

fn cc_prompt(evidence: list, pending: list) -> dict {
  const cards = cc_evidence_cards(evidence)
  const system = """
You are Burin's crystallization curator. You inspect completed coding-agent sessions and decide whether repeated or strongly reusable work should become a durable project capability.

Think like a senior harness engineer, not a sequence miner. Infer intent, invariants, repository conventions, useful parameters, failure recovery, and the narrowest reusable interface. A capability may be a skill, an executable Harn MCP tool, a Harn workflow that mixes deterministic and agentic stages, or a hybrid. It is correct to propose nothing.

Use inspect_session_evidence when the summary cards are insufficient and a card supplies a non-empty session_id; when none does, the cards are the complete evidence available. Before authoring an executable proposal, retrieve the narrow Harn guides you need with lookup_harn_skill; harn-language plus harn-mcp or harn-orchestration and harn-testing are usually sufficient. For an MCP tool, call scaffold_harn_tool before authoring: it projects Harn's current canonical generator into the single-file package shape accepted here, so do not reconstruct an older tool API from memory. Search compiler-owned global function names with search_harn_builtins instead of guessing APIs. For every executable proposal, author Harn language—not Rust, TypeScript, Python, or pseudocode—and call validate_harn_candidate on the complete source. Repair it until the compiler and authored tests report pass. Test pure helpers for deterministic rendering and validation, and also exercise at least one representative success path through the public tool registry. A workspace-writing tool must annotate `kind: "edit"` and `side_effect_level: "workspace_write"`. Return its producer facts with `agent_tool_handler_result`: successful data must carry `mutation_status: "applied"` plus the complete repo-relative `changed_paths` list (or `mutation_status: "unchanged"` when it proved the requested state already existed). When the tool can deterministically reread and prove every changed artifact, include `verification: agent_tool_postcondition(changed_paths)` only after those checks pass; never certify an unchecked write. Its tests must assert the dispatch envelope's typed mutation and postcondition receipts and the real filesystem effects, not merely its plan. In an MCP server, fs.project_root() is the capability package while fs.cwd() is the consumer workspace: apply consumer-repository effects relative to fs.cwd(). Finish by calling submit_crystallization_batch exactly once successfully with zero to three proposals. A rejected submission is feedback: repair and resubmit. Never claim evidence you did not inspect. Do not encode secrets, machine-specific absolute paths, or transcript-specific ids into an artifact.

Each executable proposal must include complete Harn source in artifact.source and a deterministic user-test suite in artifact.test_source. Set artifact.entrypoint to server.harn for harn_tool/hybrid proposals or workflow.harn for harn_workflow proposals. MCP server source must be runnable with `harn serve mcp server.harn`; tests must be runnable with `harn test test.harn`. Keep external effects behind Harness capabilities, declare capabilities and side effects, preserve approval boundaries, and prefer a small semantic interface over replaying incidental low-level calls.

Treat authored tests as falsifiers for the repository contract, not liveness checks. For every representative success path, assert the exact externally consumed outputs—such as normalized paths, command arguments, generated names, status fields, and ordering—not only `ok`, non-empty output, or a generic substring. Include at least one held-out compositional input that was not copied from an evidence card (for example a multiword identifier when the evidence names were single words). A tool that dispatches successfully but returns a malformed path or subtly wrong receipt must fail admission.

Harn tests are `pipeline test_name(harness: Harness, task) { assert_eq(...) }` and may import public helpers from `./server`. Do not use `use`, `struct`, `Vec`, `Result`, attributes, macros, references, or other Rust syntax.

These examples define breadth, not templates:

1. Repeated package verification may become verify_package(package): one MCP tool that runs the repository's typecheck, tests, and lint with failure receipts. The insight is the verified contract, not argv-position extraction.
2. Repeated pull-request babysitting may become monitor_merge_candidate(repo, pr): a durable Harn workflow that observes checks and reviews, parks on triggers, classifies safe transitions agentically, and never merges without the configured policy boundary.
3. Repeated creation of framework objects in a language with weak AST support may become add_framework_entity(name, fields): a tool that studies nearby exemplars, renders the repository-specific files, applies hash-guarded edits, and runs the framework's own validation. It may retain a bounded agentic step when deterministic parsing is not reliable.

Prefer proposals that compress reasoning while preserving or improving correctness. Reject coincidental repetition, tasks with unstable semantics, and capabilities already covered by the pending or installed library.
"""
  const message = """
Review this bounded evidence window and the existing pending capability cards.

<evidence_cards>
${json_stringify(cards)}
</evidence_cards>

<existing_pending>
${json_stringify(pending ?? [])}
</existing_pending>

Call submit_crystallization_batch when your analysis is complete.
"""
  return {system: system, message: message}
}

fn cc_allowed_session(args: dict, allowed: list) -> string {
  const id = cc_text(args?.session_id)
  if id == "" || !allowed.contains(id) {
    throw "inspect_session_evidence: session_id is outside this evidence window"
  }
  return id
}

fn cc_validate_artifact(harness: Harness, artifact: dict, options = nil) -> dict {
  const source = to_string(artifact?.source ?? "")
  const test_source = to_string(artifact?.test_source ?? "")
  const entrypoint = cc_text(artifact?.entrypoint)
  const injected = options?.validator
  if injected != nil {
    const checked = injected(source)
    return checked + {artifact: artifact}
  }
  if !["server.harn", "workflow.harn"].contains(entrypoint) {
    return {outcome: "fail", error: "entrypoint must be server.harn or workflow.harn"}
  }
  const import_path = entrypoint == "server.harn" ? "./server" : "./workflow"
  if !test_source.contains(import_path) || !test_source.contains("assert") {
    return {
      outcome: "fail",
      error: "test_source must import `" + import_path + "` and assert observable helper behavior",
    }
  }
  const dir = harness.fs.mkdtemp_in_workspace("harn-curator-")
  return try {
    harness.fs.write_text(path_join(dir, entrypoint), source)
    harness.fs.write_text(path_join(dir, "test.harn"), test_source)
    const formatted = command_run(
      harness.tools,
      [cc_harn_binary(harness.env, options), "fmt", entrypoint, "test.harn"],
      cc_toolchain_command_options(
        {cwd: dir, timeout_ms: options?.validation_timeout_ms ?? CURATOR_VALIDATION_TIMEOUT_MS},
      ),
    )
    if !(formatted?.success ?? false) {
      harness.fs.delete(dir)
      return {
        outcome: "fail",
        error: "harn fmt failed",
        format_stdout: to_string(formatted?.stdout ?? "")[0:4000],
        format_stderr: to_string(formatted?.stderr ?? "")[0:4000],
      }
    }
    const normalized_source = harness.fs.read_text(path_join(dir, entrypoint))
    const normalized_test = harness.fs.read_text(path_join(dir, "test.harn"))
    const check = command_run(
      harness.tools,
      [cc_harn_binary(harness.env, options), "check", "--strict", entrypoint, "test.harn"],
      cc_toolchain_command_options(
        {cwd: dir, timeout_ms: options?.validation_timeout_ms ?? CURATOR_VALIDATION_TIMEOUT_MS},
      ),
    )
    let tested = {}
    if check?.success ?? false {
      tested = command_run(
        harness.tools,
        [cc_harn_binary(harness.env, options), "test", "test.harn"],
        cc_toolchain_command_options(
          {cwd: dir, timeout_ms: options?.validation_timeout_ms ?? CURATOR_VALIDATION_TIMEOUT_MS},
        ),
      )
    }
    harness.fs.delete(dir)
    const passed = (check?.success ?? false) && (tested?.success ?? false)
    const diagnostics = {
      outcome: passed ? "pass" : "fail",
      check_status: check?.status,
      check_timed_out: check?.timed_out ?? false,
      check_stdout: to_string(check?.stdout ?? "")[0:4000],
      check_stderr: to_string(check?.stderr ?? "")[0:4000],
      test_status: tested?.status,
      test_timed_out: tested?.timed_out ?? false,
      test_stdout: to_string(tested?.stdout ?? "")[0:4000],
      test_stderr: to_string(tested?.stderr ?? "")[0:4000],
    }
    // The model already owns the submitted source. Re-echoing both complete
    // files on every failed compiler turn multiplies context and prompt-cache
    // writes without adding information. Return formatter-normalized files only
    // on success, where the terminal persistence boundary needs them.
    return passed ? diagnostics
      + {
      artifact: artifact + {source: normalized_source, test_source: normalized_test},
    } : diagnostics
  } catch (e) {
    harness.fs.delete(dir)
    return {outcome: "fail", error: to_string(e)}
  }
}

fn cc_harn_binary(env: HarnessEnv, options = nil) -> string {
  return options?.harn_binary ?? env.get("HARN_BIN") ?? "harn"
}

fn cc_lookup_skill(
  capabilities: {env: HarnessEnv, fs: HarnessFs, tools: HarnessTools},
  raw_name,
  options = nil,
) -> dict {
  const name = cc_text(raw_name)
  const allowed = [
    "harn-language",
    "harn-agent",
    "harn-mcp",
    "harn-testing",
    "harn-orchestration",
    "harn-product-quality",
  ]
  if !allowed.contains(name) {
    throw "lookup_harn_skill: unsupported guide `" + name + "`"
  }
  const dir = capabilities.fs.mkdtemp_in_workspace("harn-curator-guide-")
  const result = try {
    const executed = command_run(
      capabilities.tools,
      [cc_harn_binary(capabilities.env, options), "skill", "get", name, "--full"],
      cc_toolchain_command_options({cwd: dir, timeout_ms: options?.guide_timeout_ms ?? 30000}),
    )
    capabilities.fs.delete(dir)
    executed
  } catch (e) {
    capabilities.fs.delete(dir)
    throw e
  }
  const stdout = to_string(result?.stdout ?? "")
  const stderr = to_string(result?.stderr ?? "")
  return {
    name: name,
    success: result?.success ?? false,
    guide: stdout[0:min(len(stdout), options?.guide_max_bytes ?? 16000)],
    stderr: stderr[0:min(len(stderr), 2000)],
  }
}

fn cc_scaffold_tool(
  capabilities: {env: HarnessEnv, fs: HarnessFs, tools: HarnessTools},
  raw_name,
  raw_description,
  options = nil,
) -> dict {
  const name = regex_replace(r"[^a-zA-Z0-9_-]+", "-", cc_text(raw_name)) ?? "capability"
  const description = cc_text(raw_description)
  const dir = capabilities.fs.mkdtemp_in_workspace("harn-tool-scaffold-")
  return try {
    const generated = command_run(
      capabilities.tools,
      [
        cc_harn_binary(capabilities.env, options),
        "tool",
        "new",
        name,
        "--description",
        description,
        "--dir",
        dir,
        "--force",
      ],
      cc_toolchain_command_options({cwd: dir, timeout_ms: options?.guide_timeout_ms ?? 30000}),
    )
    if !(generated?.success ?? false) {
      capabilities.fs.delete(dir)
      return {success: false, stderr: to_string(generated?.stderr ?? "")[0:4000]}
    }
    const library = capabilities.fs.read_text(path_join(dir, "lib/tools.harn"))
    const server = capabilities.fs.read_text(path_join(dir, "server.harn"))
    const test = capabilities.fs.read_text(path_join(dir, "tests/test_tool.harn"))
    const projected_server = library + "\n\n"
      + server.replace(
      "import { tools } from \"lib/tools\"\n\n",
      "",
    )
    const projected_test = test.replace(
      "import { tools } from \"../lib/tools\"",
      "import { tools } from \"./server\"",
    )
    capabilities.fs.delete(dir)
    return {
      success: true,
      entrypoint: "server.harn",
      source: projected_server,
      test_source: projected_test,
      note:
        "Rename and adapt this generated package. Preserve tool_define schema validation and dispatch-level success tests; assert real filesystem effects for workspace-writing tools, use fs.cwd() for the consumer workspace, and keep public pure helpers directly testable.",
    }
  } catch (e) {
    capabilities.fs.delete(dir)
    return {success: false, error: to_string(e)}
  }
}

fn cc_search_builtins(
  capabilities: {env: HarnessEnv, fs: HarnessFs, tools: HarnessTools},
  raw_query,
  options = nil,
) -> dict {
  const query = lowercase(cc_text(raw_query))
  const terms = query.split(" ").filter({ term -> len(term) >= 2 }).to_list()
  if len(terms) == 0 {
    return {success: false, error: "query must contain at least one two-character term"}
  }
  const dir = capabilities.fs.mkdtemp_in_workspace("harn-curator-catalog-")
  const result = try {
    const executed = command_run(
      capabilities.tools,
      [cc_harn_binary(capabilities.env, options), "contracts", "builtins", "--pretty", "false"],
      cc_toolchain_command_options(
        {
          cwd: dir,
          timeout_ms: options?.guide_timeout_ms ?? 30000,
          capture: {max_inline_bytes: options?.catalog_max_bytes ?? 2000000},
        },
      ),
    )
    capabilities.fs.delete(dir)
    executed
  } catch (e) {
    capabilities.fs.delete(dir)
    throw e
  }
  if !(result?.success ?? false) {
    return {success: false, stderr: to_string(result?.stderr ?? "")[0:4000]}
  }
  const catalog = try {
    json_parse(to_string(result?.stdout ?? "{}"))
  } catch (e) {
    return {success: false, error: "invalid contracts catalog: " + to_string(e)}
  }
  let primary = []
  let secondary = []
  for builtin in catalog?.builtins ?? [] {
    const name = lowercase(to_string(builtin?.name ?? ""))
    const exposure = to_string(builtin?.contract?.exposure?.kind ?? "")
    if name.starts_with("__") || !(builtin?.parser_known ?? false)
      || exposure == "runtime_internal" {
      continue
    }
    const projected = {
      name: builtin?.name,
      exposure: exposure,
      return_types: builtin?.return_types ?? [],
      parser_known: true,
    }
    if terms.any({ term -> name == term || name.starts_with(term) || term.starts_with(name) }) {
      primary = primary + [projected]
    } else if terms.any({ term -> name.contains(term) }) {
      secondary = secondary + [projected]
    }
  }
  let matches = primary
  for item in secondary {
    if len(matches) >= 40 {
      break
    }
    matches = matches + [item]
  }
  if len(matches) > 40 {
    matches = matches[0:40]
  }
  return {success: true, query: query, matches: matches}
}

fn cc_prepare_valid_proposals(harness: Harness, proposals: list, options = nil) -> list {
  let prepared = []
  for proposal in proposals ?? [] {
    if proposal?.kind == "skill" {
      prepared = prepared + [proposal]
      continue
    }
    const checked = cc_validate_artifact(harness, proposal?.artifact ?? {}, options)
    if checked?.outcome != "pass" {
      throw "submit_crystallization_batch: executable package did not pass strict check and authored tests; repair it before resubmitting.\n"
        + json_stringify(
        checked,
      )
    }
    prepared = prepared + [proposal + {artifact: checked.artifact}]
  }
  return prepared
}

fn cc_tools(harness: Harness, evidence: list, options = nil) {
  const allowed_sessions = cc_session_ids(evidence)
  return tool_registry_from(
    [
      {
        name: "inspect_session_evidence",
        description:
          "Inspect the persisted transcript snapshot for one session in the curator's evidence window.",
        parameters: {session_id: {type: "string"}},
        returns: {type: "object"},
        handler: { args ->
          const session_id = cc_allowed_session(args, allowed_sessions)
          return harness.agent.snapshot(session_id)
        },
        annotations: {kind: "lookup", readOnlyHint: true, side_effect_level: "read_only"},
      },
      {
        name: "lookup_harn_skill",
        description:
          "Retrieve an authoritative Harn authoring guide before writing unfamiliar language, MCP, orchestration, testing, or product-quality code.",
        parameters: {
          name: {
            type: "string",
            enum: [
              "harn-language",
              "harn-agent",
              "harn-mcp",
              "harn-testing",
              "harn-orchestration",
              "harn-product-quality",
            ],
          },
        },
        returns: {type: "object"},
        handler: { args ->
          cc_lookup_skill(
            {env: harness.env, fs: harness.fs, tools: harness.tools},
            args?.name,
            options,
          )
        },
        annotations: {kind: "lookup", readOnlyHint: true, side_effect_level: "process"},
      },
      {
        name: "scaffold_harn_tool",
        description:
          "Generate a compiler-current single-file Harn MCP tool and authored-test starting point from Harn's canonical tool package generator.",
        parameters: {name: {type: "string"}, description: {type: "string"}},
        returns: {type: "object"},
        handler: { args ->
          cc_scaffold_tool(
            {env: harness.env, fs: harness.fs, tools: harness.tools},
            args?.name,
            args?.description,
            options,
          )
        },
        annotations: {kind: "read", side_effect_level: "read_only"},
      },
      {
        name: "search_harn_builtins",
        description:
          "Search Harn's compiler/runtime-owned builtin contract catalog by semantic name terms. Use before guessing global function names or importing a builtin from stdlib.",
        parameters: {
          query: {
            type: "string",
            description:
              "Space-separated API concepts such as 'character case string' or 'json parse'.",
          },
        },
        returns: {type: "object"},
        handler: { args ->
          cc_search_builtins(
            {env: harness.env, fs: harness.fs, tools: harness.tools},
            args?.query,
            options,
          )
        },
        annotations: {kind: "read", side_effect_level: "read_only"},
      },
      {
        name: "validate_harn_candidate",
        description:
          "Compile-check complete agent-authored Harn source and return bounded diagnostics. Use this before submitting every executable proposal.",
        parameters: {
          entrypoint: {type: "string", enum: ["server.harn", "workflow.harn"]},
          source: {type: "string"},
          test_source: {type: "string"},
        },
        returns: {type: "object"},
        handler: { args -> cc_validate_artifact(harness, args, options) },
        annotations: {kind: "verification", readOnlyHint: true, side_effect_level: "process"},
      },
      {
        name: "submit_crystallization_batch",
        description:
          "Submit the curator's final zero-to-three typed capability proposals for validation and review.",
        parameters: {
          proposals: {
            type: "array",
            maxItems: 3,
            items: {
              type: "object",
              properties: {
                kind: {type: "string", enum: ["skill", "harn_tool", "harn_workflow", "hybrid"]},
                name: {
                  type: "string",
                  description:
                    "Capability name; the boundary canonicalizes reasonable words or underscores to a lowercase hyphenated slug.",
                },
                title: {type: "string"},
                description: {type: "string"},
                when_to_use: {type: "string"},
                body: {type: "string"},
                evidence_ids: {type: "array", items: {type: "string"}, minItems: 1},
                capabilities: {type: "array", items: {type: "string"}},
                side_effects: {type: "array", items: {type: "string"}},
                artifact: {
                  type: "object",
                  properties: {
                    entrypoint: {type: "string"},
                    tool_names: {type: "array", items: {type: "string"}},
                    source: {type: "string"},
                    test_source: {type: "string"},
                  },
                },
              },
              required: [
                "kind",
                "name",
                "title",
                "description",
                "when_to_use",
                "body",
                "evidence_ids",
              ],
            },
          },
        },
        returns: {type: "object"},
        handler: { args ->
          const proposals = cc_prepare_valid_proposals(harness, args?.proposals ?? [], options)
          return pattern_learning_record_curated_batch(
            harness,
            args + {proposals: proposals},
            evidence,
            options,
          )
        },
        annotations: {kind: "record", side_effect_level: "store_write"},
      },
    ],
  )
}

/**
 * Run one bounded agentic crystallization review over recent session evidence.
 * The semantic decision is made by the model; Harn constrains evidence access,
 * proposal shape, cost, iterations, and durable review state.
 *
 * @effects: [agent, llm, store.read, store.write]
 * @errors: []
 * @api_stability: experimental
 */
pub fn crystallization_curate(harness: Harness, options = nil) -> dict {
  const evidence = cc_recent_evidence(harness, options)
  if len(evidence) == 0 {
    return {schema: CURATOR_SCHEMA, status: "no_evidence", proposals: []}
  }
  const pending_before = pattern_learning_pending(harness, options)
  const prompts = cc_prompt(evidence, pending_before)
  const route = options?.agent ?? {}
  let agent_options = route
    + {
    tools: cc_tools(harness, evidence, options),
    allowed_tools: [
      "inspect_session_evidence",
      "lookup_harn_skill",
      "scaffold_harn_tool",
      "search_harn_builtins",
      "validate_harn_candidate",
      "submit_crystallization_batch",
    ],
    require_successful_tools: ["submit_crystallization_batch"],
    stop_after_successful_tools: ["submit_crystallization_batch"],
    loop_until_done: true,
    max_iterations: min(max(2, route?.max_iterations ?? 8), 24),
    max_nudges: 2,
    session_id: route?.session_id ?? ("crystallization-curator-" + harness.random.uuid_v7()),
    budget: route?.budget ?? {max_cost_usd: 0.75, max_total_tokens: 60000},
  }
  if route?.provider == nil
    && route?.model == nil
    && route?.models == nil
    && route?.ladder == nil {
    agent_options = agent_options + {ladder: "frugal"}
  }
  const result = agent_loop(harness, prompts.message, prompts.system, agent_options)
  const pending_after = pattern_learning_pending(harness, options)
  const proposals = pending_after.filter({ item -> item?.source == "agent_curator" }).to_list()
  return {
    schema: CURATOR_SCHEMA,
    status: result?.terminal?.kind ?? result?.status ?? "unknown",
    curator_session_id: result?.session_id,
    evidence_count: len(evidence),
    proposal_count: len(proposals),
    proposals: proposals,
    agent_result: result,
  }
}