pi-continual-harness 0.6.0 → 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-continual-harness",
3
- "version": "0.6.0",
3
+ "version": "0.6.2",
4
4
  "description": "Online self-improvement layer for pi. A unified, in-trajectory harness-state store (prompt notes, memory, skill descriptions, sub-agent specs) with a manual /refine that proposes evidence-backed structured CRUD deltas. Composes with pi-reflect (offline) and pi-mem (storage); owns only the online optimizer layer. Inspired by Continual Harness (arXiv 2605.09998) and ACE (arXiv 2510.04618).",
5
5
  "keywords": [
6
6
  "pi-package",
@@ -35,7 +35,9 @@
35
35
  "node": ">=20.0.0"
36
36
  },
37
37
  "peerDependencies": {
38
- "@earendil-works/pi-coding-agent": ">=0.74.0"
38
+ "@earendil-works/pi-coding-agent": ">=0.74.0",
39
+ "@earendil-works/pi-ai": ">=0.74.0",
40
+ "typebox": ">=1.0.0"
39
41
  },
40
42
  "devDependencies": {
41
43
  "@earendil-works/pi-coding-agent": ">=0.74.0",
package/src/proposer.ts CHANGED
@@ -43,6 +43,8 @@ export interface CompleteOptions {
43
43
  export interface CompleteResult {
44
44
  /** The assistant's text response. */
45
45
  text: string;
46
+ /** The resolved model label ("provider/id"), for accurate audit telemetry. */
47
+ model?: string;
46
48
  /** Token usage, when the provider reports it (for the audit trail). */
47
49
  usage?: { input: number; output: number };
48
50
  }
package/src/refine.ts CHANGED
@@ -98,15 +98,28 @@ export async function runRefine(
98
98
  const proposedDeltas = result.deltas ?? [];
99
99
 
100
100
  let applied = 0;
101
+ let applyError: string | undefined;
101
102
  if (proposedDeltas.length > 0) {
102
103
  // Direct-apply path (rule-based / model proposers): persist each batch the
103
104
  // same way harness_mutate does, so /tree rollback covers these too.
104
- const appliedDeltas = applyDeltas(
105
- proposedDeltas.map((d) => d.delta),
106
- (snapshot, ver) => pi.appendEntry("harness-state", { state: snapshot, version: ver }),
107
- );
108
- applied = appliedDeltas.length;
109
- ctx.ui.notify(`Proposer "${proposer.name}" applied ${applied} delta(s) directly.`, "info");
105
+ // applyDeltas is all-or-nothing and re-throws on a bad delta — e.g. a model
106
+ // proposer's delete-then-update of the same id, or an id removed by a prune
107
+ // race during the await above. It rolls back in-memory state before throwing,
108
+ // so we surface the failure as an audited no-op rather than crashing /refine.
109
+ try {
110
+ const appliedDeltas = applyDeltas(
111
+ proposedDeltas.map((d) => d.delta),
112
+ (snapshot, ver) => pi.appendEntry("harness-state", { state: snapshot, version: ver }),
113
+ );
114
+ applied = appliedDeltas.length;
115
+ ctx.ui.notify(`Proposer "${proposer.name}" applied ${applied} delta(s) directly.`, "info");
116
+ } catch (err) {
117
+ applyError = (err as Error).message;
118
+ ctx.ui.notify(
119
+ `Proposer "${proposer.name}" batch failed: ${applyError} (0 applied, rolled back).`,
120
+ "warning",
121
+ );
122
+ }
110
123
  }
111
124
 
112
125
  // Audit trail (branchable via /tree). `source` distinguishes manual /refine
@@ -123,6 +136,8 @@ export async function runRefine(
123
136
  // Hidden model spend made visible: dedicated-model proposers report what the
124
137
  // call cost (model, tokens, latency, ok/error). Absent for rule-based/steering.
125
138
  ...(result.modelCall ? { modelCall: result.modelCall } : {}),
139
+ // When a direct-apply batch failed mid-application (rolled back), record why.
140
+ ...(applyError ? { applyError } : {}),
126
141
  });
127
142
 
128
143
  if (commit) {
@@ -248,6 +263,9 @@ function buildComplete(
248
263
  const usage = assistant.usage;
249
264
  return {
250
265
  text,
266
+ // Surface the resolved model so a dedicated-model proposer can label its
267
+ // audit telemetry accurately instead of a vague "active".
268
+ model: `${model.provider}/${model.id}`,
251
269
  ...(usage ? { usage: { input: usage.input, output: usage.output } } : {}),
252
270
  };
253
271
  };