agenr 1.9.1 → 1.9.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/CHANGELOG.md CHANGED
@@ -2,6 +2,25 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [1.9.2] - 2026-04-12
6
+
7
+ Surgeon proposal-resolution hardening and claim-key progress-output patch release.
8
+
9
+ ### Changed
10
+
11
+ - **Claim-key preview progress output is less misleading.** Preview-only `claim_key_quality` lines no longer print applied or proposal counts before entry adjudication has actually started.
12
+
13
+ ### Fixed
14
+
15
+ - **Malformed eligible proposals no longer fail the whole autonomous run.** Proposal resolution now rejects invalid auto-apply candidates per proposal and continues through the rest of the backlog.
16
+ - **Ambiguous entity-family convergence proposals stay on the manual-review path.** Multi-target family-convergence proposals are no longer marked eligible for autonomous apply.
17
+
18
+ ### Validation
19
+
20
+ Changes since last push to `origin/master`:
21
+
22
+ - Fix surgeon proposal resolution and progress output
23
+
5
24
  ## [1.9.1] - 2026-04-12
6
25
 
7
26
  Supersession stall-recovery and review-order guard patch release.
@@ -1055,7 +1055,7 @@ function registerAgenrOpenClawTools(api, servicesPromise, logger) {
1055
1055
  var openclaw_plugin_default = {
1056
1056
  id: "agenr",
1057
1057
  name: "agenr",
1058
- version: "1.9.0",
1058
+ version: "1.9.1",
1059
1059
  description: "agenr memory plugin for OpenClaw",
1060
1060
  kind: "memory",
1061
1061
  contracts: {
package/dist/cli.js CHANGED
@@ -8204,7 +8204,7 @@ async function runClaimKeyQualityPass(options, deps) {
8204
8204
  rationale: buildSurgeonProposalLifecycleRationale(buildEntityFamilyConvergenceRationale(candidate), proposalLifecycle),
8205
8205
  confidence: candidate.confidence,
8206
8206
  source: canonicalEntityPrefix ? "entity_family_canonical_candidate" : "entity_family_ambiguous",
8207
- eligibleForApply: canonicalEntityPrefix !== null,
8207
+ eligibleForApply: proposedClaimKeys.length === 1,
8208
8208
  createdAt: options.now().toISOString()
8209
8209
  });
8210
8210
  await persistProposal(proposal, {
@@ -8247,7 +8247,7 @@ async function runClaimKeyQualityPass(options, deps) {
8247
8247
  ),
8248
8248
  confidence: candidate.confidence,
8249
8249
  source: "entity_family_collision",
8250
- eligibleForApply: true,
8250
+ eligibleForApply: false,
8251
8251
  createdAt: options.now().toISOString()
8252
8252
  });
8253
8253
  await persistProposal(proposal, {
@@ -12767,6 +12767,7 @@ async function runProposalResolutionPass(input, deps) {
12767
12767
  });
12768
12768
  let appliedCount = 0;
12769
12769
  let rejectedInactiveCount = 0;
12770
+ let rejectedInvalidCount = 0;
12770
12771
  let noChangeCount = 0;
12771
12772
  const updatedEntryIds = /* @__PURE__ */ new Set();
12772
12773
  emitProposalResolutionProgress(input.reportProgress, {
@@ -12776,6 +12777,7 @@ async function runProposalResolutionPass(input, deps) {
12776
12777
  processedProposals: 0,
12777
12778
  appliedCount,
12778
12779
  rejectedInactiveCount,
12780
+ rejectedInvalidCount,
12779
12781
  noChangeCount,
12780
12782
  targetedEntryCount: updatedEntryIds.size
12781
12783
  });
@@ -12789,7 +12791,35 @@ async function runProposalResolutionPass(input, deps) {
12789
12791
  }
12790
12792
  for (const [index, item] of backlog.entries()) {
12791
12793
  const proposal = item.proposal;
12792
- const targetClaimKey = resolveSurgeonProposalApplyTarget(proposal);
12794
+ let targetClaimKey;
12795
+ try {
12796
+ targetClaimKey = resolveSurgeonProposalApplyTarget(proposal);
12797
+ } catch (error) {
12798
+ const message = error instanceof Error ? error.message : String(error);
12799
+ await deps.port.reviewProposal({
12800
+ proposalId: proposal.id,
12801
+ status: "rejected",
12802
+ reason: message,
12803
+ reviewedAt: input.now().toISOString(),
12804
+ appliedActionCount: 0
12805
+ });
12806
+ rejectedInvalidCount += 1;
12807
+ emitProposalResolutionProgress(input.reportProgress, {
12808
+ apply: input.apply,
12809
+ status: "proposal_processed",
12810
+ totalProposals: backlog.length,
12811
+ processedProposals: index + 1,
12812
+ appliedCount,
12813
+ rejectedInactiveCount,
12814
+ rejectedInvalidCount,
12815
+ noChangeCount,
12816
+ targetedEntryCount: updatedEntryIds.size,
12817
+ proposalId: proposal.id,
12818
+ issueKind: proposal.issueKind,
12819
+ outcome: "rejected_invalid"
12820
+ });
12821
+ continue;
12822
+ }
12793
12823
  const reasoning = buildSurgeonProposalReviewReason(proposal, "Autonomous eligible proposal resolution.");
12794
12824
  const proposalEntryIds = [];
12795
12825
  if (input.apply) {
@@ -12830,6 +12860,7 @@ async function runProposalResolutionPass(input, deps) {
12830
12860
  processedProposals: index + 1,
12831
12861
  appliedCount,
12832
12862
  rejectedInactiveCount,
12863
+ rejectedInvalidCount,
12833
12864
  noChangeCount,
12834
12865
  targetedEntryCount: updatedEntryIds.size,
12835
12866
  proposalId: proposal.id,
@@ -12845,6 +12876,7 @@ async function runProposalResolutionPass(input, deps) {
12845
12876
  processedProposals: index + 1,
12846
12877
  appliedCount,
12847
12878
  rejectedInactiveCount,
12879
+ rejectedInvalidCount,
12848
12880
  noChangeCount,
12849
12881
  targetedEntryCount: updatedEntryIds.size,
12850
12882
  proposalId: proposal.id,
@@ -12893,6 +12925,7 @@ async function runProposalResolutionPass(input, deps) {
12893
12925
  processedProposals: index + 1,
12894
12926
  appliedCount,
12895
12927
  rejectedInactiveCount,
12928
+ rejectedInvalidCount,
12896
12929
  noChangeCount,
12897
12930
  targetedEntryCount: updatedEntryIds.size,
12898
12931
  proposalId: proposal.id,
@@ -12900,7 +12933,7 @@ async function runProposalResolutionPass(input, deps) {
12900
12933
  outcome: input.apply ? "applied" : "dry_run"
12901
12934
  });
12902
12935
  }
12903
- if (appliedCount === 0 && rejectedInactiveCount === 0) {
12936
+ if (appliedCount === 0 && rejectedInactiveCount === 0 && rejectedInvalidCount === 0) {
12904
12937
  emitProposalResolutionProgress(input.reportProgress, {
12905
12938
  apply: input.apply,
12906
12939
  status: "stalled",
@@ -12908,6 +12941,7 @@ async function runProposalResolutionPass(input, deps) {
12908
12941
  processedProposals: backlog.length,
12909
12942
  appliedCount,
12910
12943
  rejectedInactiveCount,
12944
+ rejectedInvalidCount,
12911
12945
  noChangeCount,
12912
12946
  targetedEntryCount: updatedEntryIds.size
12913
12947
  });
@@ -12925,6 +12959,7 @@ async function runProposalResolutionPass(input, deps) {
12925
12959
  processedProposals: backlog.length,
12926
12960
  appliedCount,
12927
12961
  rejectedInactiveCount,
12962
+ rejectedInvalidCount,
12928
12963
  noChangeCount,
12929
12964
  targetedEntryCount: updatedEntryIds.size
12930
12965
  });
@@ -12936,7 +12971,10 @@ async function runProposalResolutionPass(input, deps) {
12936
12971
  observations: [
12937
12972
  `Processed ${appliedCount} eligible surgeon proposal${appliedCount === 1 ? "" : "s"}.`,
12938
12973
  `${updatedEntryIds.size} entr${updatedEntryIds.size === 1 ? "y was" : "ies were"} targeted by proposal resolution.`,
12939
- ...rejectedInactiveCount > 0 ? [`Rejected ${rejectedInactiveCount} stale eligible proposal${rejectedInactiveCount === 1 ? "" : "s"} whose target entries were no longer active.`] : []
12974
+ ...rejectedInactiveCount > 0 ? [`Rejected ${rejectedInactiveCount} stale eligible proposal${rejectedInactiveCount === 1 ? "" : "s"} whose target entries were no longer active.`] : [],
12975
+ ...rejectedInvalidCount > 0 ? [
12976
+ `Rejected ${rejectedInvalidCount} malformed eligible proposal${rejectedInvalidCount === 1 ? "" : "s"} that did not resolve to exactly one safe claim-key target.`
12977
+ ] : []
12940
12978
  ],
12941
12979
  recommendations: ["Leave non-eligible surgeon proposals on the manual review path."]
12942
12980
  },
@@ -12953,6 +12991,7 @@ function emitProposalResolutionProgress(reporter, input) {
12953
12991
  processedProposals: input.processedProposals,
12954
12992
  appliedCount: input.appliedCount,
12955
12993
  rejectedInactiveCount: input.rejectedInactiveCount,
12994
+ rejectedInvalidCount: input.rejectedInvalidCount,
12956
12995
  noChangeCount: input.noChangeCount,
12957
12996
  targetedEntryCount: input.targetedEntryCount,
12958
12997
  proposalId: input.proposalId,
@@ -16313,8 +16352,8 @@ function handleClaimKeyQualityEvent(event, verbose) {
16313
16352
  const previewTotal = formatOptionalCount(event.previewTotal);
16314
16353
  const previewCompleted = formatOptionalCount(event.previewCompleted);
16315
16354
  const previewSuffix = previewTotal > 0 ? `, preview ${previewCompleted}/${previewTotal}` : "";
16316
- const progressMsg = `${stageLabel}: ${event.completed}/${event.total} ${event.unitLabel}${previewSuffix}, ${appliedTotal} applied, ${event.counts.proposalsEmitted} proposals${skippedSummary}, ${formatElapsed(event.elapsedMs)}`;
16317
- if (verbose) {
16355
+ const progressMsg = event.status === "preview_progress" ? `${stageLabel}: ${event.completed}/${event.total} ${event.unitLabel}${previewSuffix}${skippedSummary}, ${formatElapsed(event.elapsedMs)}` : `${stageLabel}: ${event.completed}/${event.total} ${event.unitLabel}${previewSuffix}, ${appliedTotal} applied, ${event.counts.proposalsEmitted} proposals${skippedSummary}, ${formatElapsed(event.elapsedMs)}`;
16356
+ if (verbose && event.status !== "preview_progress") {
16318
16357
  const detail = ` (normalize ${event.counts.appliedNormalizations}/${event.counts.identifiedNormalizations}, backfill ${event.counts.appliedBackfills}/${event.counts.identifiedBackfills}, metadata ${event.counts.appliedMetadataRewrites}/${event.counts.identifiedMetadataRewrites}, family ${event.counts.appliedEntityFamilyConvergences}/${event.counts.identifiedEntityFamilyConvergences})`;
16319
16358
  writeStderr(` ${ui.dim(progressMsg + detail)}`);
16320
16359
  } else {
@@ -16334,18 +16373,18 @@ function handleProposalResolutionEvent(event, verbose) {
16334
16373
  const outcome = event.outcome ? `, ${formatProposalResolutionOutcome(event.outcome)}` : "";
16335
16374
  const verboseSuffix = verbose && event.proposalId ? ` ${ui.dim(`(${event.proposalId}${event.issueKind ? `, ${event.issueKind}` : ""})`)}` : "";
16336
16375
  writeStderr(
16337
- ` ${ui.dim(`proposal_resolution: ${event.processedProposals}/${event.totalProposals} proposals, applied ${event.appliedCount}, inactive ${event.rejectedInactiveCount}, no-op ${event.noChangeCount}, targeted ${event.targetedEntryCount}${outcome}`)}${verboseSuffix}`
16376
+ ` ${ui.dim(`proposal_resolution: ${event.processedProposals}/${event.totalProposals} proposals, applied ${event.appliedCount}, inactive ${event.rejectedInactiveCount}, invalid ${event.rejectedInvalidCount}, no-op ${event.noChangeCount}, targeted ${event.targetedEntryCount}${outcome}`)}${verboseSuffix}`
16338
16377
  );
16339
16378
  return;
16340
16379
  }
16341
16380
  case "completed":
16342
16381
  writeStderr(
16343
- ` ${ui.success(`proposal_resolution complete: applied ${event.appliedCount}, inactive ${event.rejectedInactiveCount}, no-op ${event.noChangeCount}, targeted ${event.targetedEntryCount}`)}`
16382
+ ` ${ui.success(`proposal_resolution complete: applied ${event.appliedCount}, inactive ${event.rejectedInactiveCount}, invalid ${event.rejectedInvalidCount}, no-op ${event.noChangeCount}, targeted ${event.targetedEntryCount}`)}`
16344
16383
  );
16345
16384
  return;
16346
16385
  case "stalled":
16347
16386
  writeStderr(
16348
- ` ${ui.warn(`proposal_resolution stalled: ${event.processedProposals}/${event.totalProposals} proposals, applied ${event.appliedCount}, inactive ${event.rejectedInactiveCount}, no-op ${event.noChangeCount}, targeted ${event.targetedEntryCount}`)}`
16387
+ ` ${ui.warn(`proposal_resolution stalled: ${event.processedProposals}/${event.totalProposals} proposals, applied ${event.appliedCount}, inactive ${event.rejectedInactiveCount}, invalid ${event.rejectedInvalidCount}, no-op ${event.noChangeCount}, targeted ${event.targetedEntryCount}`)}`
16349
16388
  );
16350
16389
  return;
16351
16390
  default:
@@ -16487,6 +16526,8 @@ function formatProposalResolutionOutcome(outcome) {
16487
16526
  return "previewed";
16488
16527
  case "rejected_inactive":
16489
16528
  return "rejected inactive";
16529
+ case "rejected_invalid":
16530
+ return "rejected invalid";
16490
16531
  case "no_change":
16491
16532
  return "no change";
16492
16533
  default:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agenr",
3
- "version": "1.9.1",
3
+ "version": "1.9.2",
4
4
  "description": "Agent memory - local-first knowledge infrastructure for AI agents",
5
5
  "type": "module",
6
6
  "bin": {