@odla-ai/harness 0.2.0 → 0.3.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.
@@ -1996,6 +1996,55 @@ function validateOptions(options) {
1996
1996
  }
1997
1997
  }
1998
1998
 
1999
+ // src/code-memory.ts
2000
+ import { closure } from "@odla-ai/graph";
2001
+ var MAX_MEMORY_BODY = 4e3;
2002
+ function validateMemory(memory) {
2003
+ if (!memory.subject.includes(":")) {
2004
+ throw new TypeError(`memory subject must be a graph node id, got "${memory.subject}"`);
2005
+ }
2006
+ const body = memory.body.trim();
2007
+ if (!body) throw new TypeError("a memory needs a body");
2008
+ if (body.length > MAX_MEMORY_BODY) throw new TypeError("memory body exceeds its bound");
2009
+ if (!memory.authorId.trim()) throw new TypeError("a memory needs an author");
2010
+ }
2011
+ async function recallAbout(store, subjects, options = {}) {
2012
+ const limit = options.limit ?? 20;
2013
+ const wanted = options.graph ? [...closure(options.graph, subjects, {
2014
+ direction: "out",
2015
+ maxDepth: options.depth ?? 1,
2016
+ ...options.kinds ? { kinds: options.kinds } : {}
2017
+ })] : [...subjects];
2018
+ const found = await store.recall(wanted, limit * 2);
2019
+ return found.filter((memory) => !memory.supersededBy).slice(0, limit);
2020
+ }
2021
+ function renderMemories(memories) {
2022
+ if (memories.length === 0) return "";
2023
+ const lines = memories.map((memory) => {
2024
+ const source = memory.evidence ? ` [${memory.evidence.kind}:${memory.evidence.ref}]` : " [unverified]";
2025
+ return `- (${memory.kind}) ${memory.subject}${source}
2026
+ ${memory.body.replace(/\s+/g, " ").slice(0, 400)}`;
2027
+ });
2028
+ return [
2029
+ "What previous runs learned about this code. A hazard cost an attempt to find;",
2030
+ "an unverified note is one agent's opinion. Treat them accordingly.",
2031
+ ...lines
2032
+ ].join("\n");
2033
+ }
2034
+ function hazardFromAttempt(input) {
2035
+ const body = [
2036
+ `Attempt ${input.attempt} at "${input.goal.slice(0, 200)}" failed its proof.`,
2037
+ input.feedback.replace(/\s+/g, " ").slice(0, MAX_MEMORY_BODY - 300)
2038
+ ].join(" ");
2039
+ return input.touched.slice(0, 10).map((path) => ({
2040
+ subject: path.includes(":") ? path : `file:${path}`,
2041
+ kind: "hazard",
2042
+ body,
2043
+ evidence: { kind: "gate", ref: input.verificationId },
2044
+ authorId: input.authorId
2045
+ }));
2046
+ }
2047
+
1999
2048
  // src/code-goal-runner.ts
2000
2049
  async function runGoal(spec, attempt) {
2001
2050
  assertBudget(spec.budget);
@@ -2192,6 +2241,9 @@ function pursueRuntimeGoal(input) {
2192
2241
  return { gatePassed: false, feedback: "", tokens: outcome.tokens, error: outcome.error };
2193
2242
  }
2194
2243
  const verdict = await input.gate(attempt);
2244
+ if (!verdict.passed && input.memory) {
2245
+ await rememberFailure(input, attempt, verdict.feedback);
2246
+ }
2195
2247
  return {
2196
2248
  gatePassed: verdict.passed,
2197
2249
  feedback: verdict.feedback,
@@ -2202,6 +2254,25 @@ function pursueRuntimeGoal(input) {
2202
2254
  }
2203
2255
  );
2204
2256
  }
2257
+ async function rememberFailure(input, attempt, feedback) {
2258
+ if (!input.memory || !feedback.trim()) return;
2259
+ try {
2260
+ const touched = await input.touched?.(attempt) ?? [];
2261
+ if (touched.length === 0) return;
2262
+ for (const memory of hazardFromAttempt({
2263
+ goal: input.spec.goal,
2264
+ attempt,
2265
+ feedback,
2266
+ touched,
2267
+ verificationId: `goal-${attempt}`,
2268
+ authorId: input.memory.authorId
2269
+ })) {
2270
+ validateMemory(memory);
2271
+ await input.memory.store.remember(memory);
2272
+ }
2273
+ } catch {
2274
+ }
2275
+ }
2205
2276
  function goalEventLine(event) {
2206
2277
  if (event.type === "attempt_started") return `Goal attempt ${event.attempt} starting.`;
2207
2278
  if (event.type === "attempt_failed") return `Attempt ${event.attempt} did not satisfy the proof.`;
@@ -2562,7 +2633,12 @@ export {
2562
2633
  createCodeRuntimeInference,
2563
2634
  registeredFiles,
2564
2635
  createCodeToolBroker,
2636
+ MAX_MEMORY_BODY,
2637
+ validateMemory,
2638
+ recallAbout,
2639
+ renderMemories,
2640
+ hazardFromAttempt,
2565
2641
  runGoal,
2566
2642
  CodePiRuntimeEngine
2567
2643
  };
2568
- //# sourceMappingURL=chunk-5FFR7U4L.js.map
2644
+ //# sourceMappingURL=chunk-U2OFMIAW.js.map