agenr 1.8.1 → 1.9.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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,70 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [1.9.0] - 2026-04-12
6
+
7
+ Surgeon autonomy, review-flow hardening, and CLI/runtime polish release.
8
+
9
+ ### Added
10
+
11
+ - **Surgeon autonomy control plane v1.** Agenr now ships the first full surgeon autonomy control plane with stronger proposal-review flow, improved review ownership, and better runtime state handling across autonomous passes.
12
+ - **Architecture review skill.** Added a dedicated architecture review skill to support repository-level structural review work alongside the surgeon and planning toolchain updates in this release window.
13
+
14
+ ### Changed
15
+
16
+ - **Surgeon architecture and runtime boundaries are cleaner.** Surgeon logic was refactored across app, adapter, and domain seams, with generalized prompts across corpus domains, tighter runtime safeguards, simplified run flow, and more coherent completion/progress accounting.
17
+ - **CLI and trace output are more structured.** Surgeon console output, startup summaries, progress rendering, and trace logging were tightened so autonomous runs are easier to monitor and debug.
18
+ - **Local development scaffolding stays out of git status.** `.gitignore` now excludes the repo-local skills directory to keep local agent tooling from polluting release and day-to-day workflow status.
19
+
20
+ ### Fixed
21
+
22
+ - **Autonomous surgeon passes recover more reliably.** Fixed proposal-loop stalling, autonomous backup handling, trace directory handling, exhausted-review completion, and repeat supersession-review suppression so long-running surgeon activity can finish cleanly.
23
+
24
+ ### Validation
25
+
26
+ Changes since last push to `origin/master`:
27
+
28
+ - Clean up surgeon CLI output with structured progress and chalk formatting
29
+ - Simplify surgeon run flow
30
+ - Fix surgeon trace directory handling
31
+ - Compact surgeon trace logging
32
+ - Implement surgeon autonomy control plane v1
33
+ - Fix surgeon autonomous proposal loop
34
+ - Fix surgeon autonomous backup and progress stalling
35
+ - Stabilize surgeon retirement and proposal passes
36
+ - Generalize surgeon prompts across corpus domains
37
+ - Add first-principles planning skill
38
+ - Tighten surgeon runtime safeguards
39
+ - Update `.gitignore` to include skills directory
40
+ - Remove first-principles planning skill and associated OpenAI agent configuration files
41
+ - Finish supersession completion on exhausted reviews
42
+ - Improve surgeon progress accounting and console output
43
+ - Suppress repeat supersession review and polish surgeon CLI output
44
+ - Add architecture review skill
45
+ - Refactor surgeon architecture boundaries
46
+ - Clarify surgeon pass startup summaries
47
+
48
+ ## [1.8.2] - 2026-04-12
49
+
50
+ Temporal parsing and ingest workflow polish patch release.
51
+
52
+ ### Changed
53
+
54
+ - **Relative time parsing now accepts small spelled-out amounts.** Episode temporal-window parsing now recognizes natural language queries such as "two days ago" for small relative ranges, improving recall routing for conversational phrasing.
55
+ - **Local Cursor scaffolding stays out of repo status.** `.gitignore` now excludes local Cursor rules and skills directories so release work and day-to-day development stay focused on product changes.
56
+
57
+ ### Fixed
58
+
59
+ - **Ingest progress propagation now reaches the CLI consistently.** The ingestion app and CLI layers now forward progress events end-to-end so long-running ingest runs surface stage updates reliably.
60
+
61
+ ### Validation
62
+
63
+ Changes since last push to `origin/master`:
64
+
65
+ - Update `.gitignore` to exclude cursor rules and skills directories
66
+ - Enhance temporal parsing with small spelled-out relative amounts
67
+ - Enhance ingestion process with progress event propagation
68
+
5
69
  ## [1.8.1] - 2026-04-11
6
70
 
7
71
  Ingest concurrency and progress reporting patch release.
@@ -7,7 +7,7 @@ import {
7
7
  parseTuiSessionKey,
8
8
  readOpenClawSessionsStore,
9
9
  storeEntriesDetailed
10
- } from "../../chunk-O45JQ6O3.js";
10
+ } from "../../chunk-I6A6DPNF.js";
11
11
  import {
12
12
  EMBEDDING_DIMENSIONS,
13
13
  ENTRY_TYPES,
@@ -24,7 +24,7 @@ import {
24
24
  resolveEmbeddingModel,
25
25
  runUnifiedRecall,
26
26
  validateTemporalValidityRange
27
- } from "../../chunk-LVDQXSHP.js";
27
+ } from "../../chunk-EMRMV2QR.js";
28
28
  import {
29
29
  resolveClaimSlotPolicy
30
30
  } from "../../chunk-GUDCFFRV.js";
@@ -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.8.1",
1058
+ version: "1.9.0",
1059
1059
  description: "agenr memory plugin for OpenClaw",
1060
1060
  kind: "memory",
1061
1061
  contracts: {
@@ -1932,6 +1932,10 @@ var CREATE_SURGEON_RUN_PROPOSALS_REVIEW_STATUS_INDEX_SQL = `
1932
1932
  CREATE INDEX IF NOT EXISTS idx_surgeon_run_proposals_review_status
1933
1933
  ON surgeon_run_proposals(review_status)
1934
1934
  `;
1935
+ var CREATE_SURGEON_RUN_PROPOSALS_OPEN_ISSUE_INDEX_SQL = `
1936
+ CREATE INDEX IF NOT EXISTS idx_surgeon_run_proposals_open_issue
1937
+ ON surgeon_run_proposals(review_status, group_id, issue_kind)
1938
+ `;
1935
1939
  var CREATE_META_TABLE_SQL = `
1936
1940
  CREATE TABLE IF NOT EXISTS _meta (
1937
1941
  key TEXT PRIMARY KEY,
@@ -2055,6 +2059,7 @@ var SCHEMA_STATEMENTS = [
2055
2059
  CREATE_SURGEON_RUN_PROPOSALS_GROUP_ID_INDEX_SQL,
2056
2060
  CREATE_SURGEON_RUN_PROPOSALS_CREATED_AT_INDEX_SQL,
2057
2061
  CREATE_SURGEON_RUN_PROPOSALS_REVIEW_STATUS_INDEX_SQL,
2062
+ CREATE_SURGEON_RUN_PROPOSALS_OPEN_ISSUE_INDEX_SQL,
2058
2063
  CREATE_META_TABLE_SQL,
2059
2064
  CREATE_ENTRIES_CONTENT_HASH_INDEX_SQL,
2060
2065
  CREATE_ENTRIES_NORM_CONTENT_HASH_INDEX_SQL,
@@ -4094,6 +4099,20 @@ function parseTimestamp(value) {
4094
4099
  // src/core/episode/temporal-window.ts
4095
4100
  var DAY_IN_MILLISECONDS = 24 * 60 * 60 * 1e3;
4096
4101
  var DEFAULT_ANCHOR_RADIUS_DAYS = 3;
4102
+ var RELATIVE_NUMBER_WORDS = /* @__PURE__ */ new Map([
4103
+ ["one", 1],
4104
+ ["two", 2],
4105
+ ["three", 3],
4106
+ ["four", 4],
4107
+ ["five", 5],
4108
+ ["six", 6],
4109
+ ["seven", 7],
4110
+ ["eight", 8],
4111
+ ["nine", 9],
4112
+ ["ten", 10],
4113
+ ["eleven", 11],
4114
+ ["twelve", 12]
4115
+ ]);
4097
4116
  var MONTH_INDEX = /* @__PURE__ */ new Map([
4098
4117
  ["january", 0],
4099
4118
  ["february", 1],
@@ -4243,9 +4262,9 @@ function parseTemporalWindow(text, now = /* @__PURE__ */ new Date()) {
4243
4262
  now: referenceNow
4244
4263
  });
4245
4264
  }
4246
- const relativeMatch = lower.match(/\b(\d+)\s+(day|days|week|weeks|month|months)\s+ago\b/);
4265
+ const relativeMatch = lower.match(/\b(\d+|one|two|three|four|five|six|seven|eight|nine|ten|eleven|twelve)\s+(day|days|week|weeks|month|months)\s+ago\b/);
4247
4266
  if (relativeMatch?.[1] && relativeMatch[2]) {
4248
- const amount = Number(relativeMatch[1]);
4267
+ const amount = parseRelativeAmount(relativeMatch[1]);
4249
4268
  if (Number.isFinite(amount) && amount > 0) {
4250
4269
  const unit = relativeMatch[2];
4251
4270
  if (unit.startsWith("day")) {
@@ -4446,6 +4465,12 @@ function buildLocalDateAtNoon(year, month, day) {
4446
4465
  }
4447
4466
  return parsed;
4448
4467
  }
4468
+ function parseRelativeAmount(value) {
4469
+ if (/^\d+$/u.test(value)) {
4470
+ return Number(value);
4471
+ }
4472
+ return RELATIVE_NUMBER_WORDS.get(value) ?? Number.NaN;
4473
+ }
4449
4474
  function resolveWeekStartDay() {
4450
4475
  try {
4451
4476
  const locale = Intl.DateTimeFormat().resolvedOptions().locale;
@@ -22,7 +22,7 @@ import {
22
22
  readOptionalString,
23
23
  readRequiredString,
24
24
  validateTemporalValidityRange
25
- } from "./chunk-LVDQXSHP.js";
25
+ } from "./chunk-EMRMV2QR.js";
26
26
  import {
27
27
  compactClaimKey,
28
28
  describeClaimKeyNormalizationFailure,
@@ -2737,7 +2737,7 @@ async function extractClaimKeyDecision(entry, llm, config, options = {}) {
2737
2737
  async function getEntityHints(db) {
2738
2738
  return db.getDistinctClaimKeyPrefixes();
2739
2739
  }
2740
- async function runBatchClaimExtraction(results, ports, config, concurrency = 10, onWarning, onDiagnostic) {
2740
+ async function runBatchClaimExtraction(results, ports, config, concurrency = 10, onWarning, onDiagnostic, onProgress) {
2741
2741
  if (!config.enabled) {
2742
2742
  return /* @__PURE__ */ new Map();
2743
2743
  }
@@ -2748,6 +2748,8 @@ async function runBatchClaimExtraction(results, ports, config, concurrency = 10,
2748
2748
  const retryEntries = [];
2749
2749
  const stageSize = normalizeClaimExtractionConcurrency(concurrency);
2750
2750
  const orderedEntries = results.flatMap((result) => result.entries);
2751
+ const totalEligibleEntries = orderedEntries.filter((entry) => !entry.claim_key && config.eligibleTypes.includes(entry.type)).length;
2752
+ let completedPrimaryEntries = 0;
2751
2753
  for (let stageStart = 0; stageStart < orderedEntries.length; stageStart += stageSize) {
2752
2754
  const stageEntries = orderedEntries.slice(stageStart, stageStart + stageSize);
2753
2755
  const stageRequests = [];
@@ -2774,11 +2776,22 @@ async function runBatchClaimExtraction(results, ports, config, concurrency = 10,
2774
2776
  hintSnapshot: buildClaimExtractionHintSnapshot(hintState, entry)
2775
2777
  });
2776
2778
  }
2777
- const stageDecisions = await Promise.all(
2778
- stageRequests.map(async ({ entry, hintSnapshot }) => ({
2779
- entry,
2780
- decision: await extractBatchClaimKeyDecision(entry, llm, config, hintSnapshot, onWarning)
2781
- }))
2779
+ const stageDecisions = await executeClaimExtractionStageRequests(
2780
+ stageRequests,
2781
+ llm,
2782
+ config,
2783
+ onWarning,
2784
+ completedPrimaryEntries,
2785
+ totalEligibleEntries,
2786
+ (completedEntries, totalEntries) => {
2787
+ completedPrimaryEntries = completedEntries;
2788
+ onProgress?.({
2789
+ phase: "primary",
2790
+ completedEntries,
2791
+ totalEntries,
2792
+ totalEligibleEntries
2793
+ });
2794
+ }
2782
2795
  );
2783
2796
  for (const { entry, decision } of stageDecisions) {
2784
2797
  diagnostics.set(entry, decision.diagnostic);
@@ -2792,16 +2805,30 @@ async function runBatchClaimExtraction(results, ports, config, concurrency = 10,
2792
2805
  }
2793
2806
  }
2794
2807
  if (retryEntries.length > 0 && extractedEntries.size > 0) {
2795
- for (let stageStart = 0; stageStart < retryEntries.length; stageStart += stageSize) {
2796
- const stageRequests = retryEntries.slice(stageStart, stageStart + stageSize).filter((entry) => !entry.claim_key).map((entry) => ({
2808
+ const retryEligibleEntries = retryEntries.filter((entry) => !entry.claim_key);
2809
+ const totalRetryEntries = retryEligibleEntries.length;
2810
+ let completedRetryEntries = 0;
2811
+ for (let stageStart = 0; stageStart < retryEligibleEntries.length; stageStart += stageSize) {
2812
+ const stageRequests = retryEligibleEntries.slice(stageStart, stageStart + stageSize).map((entry) => ({
2797
2813
  entry,
2798
2814
  hintSnapshot: buildClaimExtractionHintSnapshot(hintState, entry)
2799
2815
  }));
2800
- const stageDecisions = await Promise.all(
2801
- stageRequests.map(async ({ entry, hintSnapshot }) => ({
2802
- entry,
2803
- decision: await extractBatchClaimKeyDecision(entry, llm, config, hintSnapshot, onWarning)
2804
- }))
2816
+ const stageDecisions = await executeClaimExtractionStageRequests(
2817
+ stageRequests,
2818
+ llm,
2819
+ config,
2820
+ onWarning,
2821
+ completedRetryEntries,
2822
+ totalRetryEntries,
2823
+ (completedEntries, totalEntries) => {
2824
+ completedRetryEntries = completedEntries;
2825
+ onProgress?.({
2826
+ phase: "retry",
2827
+ completedEntries,
2828
+ totalEntries,
2829
+ totalEligibleEntries
2830
+ });
2831
+ }
2805
2832
  );
2806
2833
  for (const { entry, decision } of stageDecisions) {
2807
2834
  diagnostics.set(entry, decision.diagnostic);
@@ -2824,6 +2851,20 @@ async function runBatchClaimExtraction(results, ports, config, concurrency = 10,
2824
2851
  }
2825
2852
  return extractedEntries;
2826
2853
  }
2854
+ async function executeClaimExtractionStageRequests(stageRequests, llm, config, onWarning, initialCompletedEntries, totalEntries, onProgress) {
2855
+ let completedEntries = initialCompletedEntries;
2856
+ return Promise.all(
2857
+ stageRequests.map(async ({ entry, hintSnapshot }) => {
2858
+ const decision = await extractBatchClaimKeyDecision(entry, llm, config, hintSnapshot, onWarning);
2859
+ completedEntries += 1;
2860
+ onProgress(completedEntries, totalEntries);
2861
+ return {
2862
+ entry,
2863
+ decision
2864
+ };
2865
+ })
2866
+ );
2867
+ }
2827
2868
  function normalizeClaimExtractionConcurrency(value) {
2828
2869
  if (!Number.isInteger(value) || value <= 0) {
2829
2870
  return 10;