agenr 0.9.71 → 0.9.72
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
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.9.72] - 2026-03-06
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- Online dedup no longer allows a higher-tier incoming entry (`core > permanent > temporary`) to end in `SKIP` against a lower-tier existing row. Higher-tier `SKIP` outcomes are now overridden to a safe `UPDATE` that preserves existing content while promoting the stored expiry.
|
|
8
|
+
- The near-exact semantic duplicate fast path now blocks `SKIP` for higher-tier incoming entries and only auto-promotes when the subjects still align; otherwise it falls through to a non-skip path instead of swallowing the stronger lifecycle.
|
|
9
|
+
- Added regression coverage for higher-tier `SKIP` overrides in both the store pipeline and the CLI `store` path, while preserving allowed equal-tier and lower-tier `SKIP` behavior.
|
|
10
|
+
- Extended `verify:dist` to fail release builds unless the bundled runtime contains the higher-tier `SKIP` guard and reproduces the live failure shape as an `UPDATE` in the built artifact.
|
|
11
|
+
|
|
3
12
|
## [0.9.71] - 2026-03-06
|
|
4
13
|
|
|
5
14
|
### Fixed
|
|
@@ -6693,6 +6693,31 @@ var TODO_COMPLETION_NEGATION_PATTERN = /\b(?:not|never)\b(?:\W+\w+){0,2}\W*$|\bn
|
|
|
6693
6693
|
var TODO_COMPLETION_SIGNAL_PATTERNS = TODO_COMPLETION_SIGNALS.map(
|
|
6694
6694
|
(signal) => new RegExp(`\\b${signal.split(/\s+/).map(escapeRegExp).join("\\s+")}\\b`, "gi")
|
|
6695
6695
|
);
|
|
6696
|
+
function incomingExpiryOutranksExisting(existingExpiry, incomingExpiry) {
|
|
6697
|
+
return incomingExpiry !== existingExpiry && resolveHigherExpiry(existingExpiry, incomingExpiry) === incomingExpiry;
|
|
6698
|
+
}
|
|
6699
|
+
function buildExpiryPromotionUpdate(params) {
|
|
6700
|
+
return {
|
|
6701
|
+
decision: {
|
|
6702
|
+
entry: params.entry,
|
|
6703
|
+
action: "updated",
|
|
6704
|
+
reason: params.reason,
|
|
6705
|
+
similarity: params.candidate.similarity,
|
|
6706
|
+
matchedEntryId: params.candidate.entry.id,
|
|
6707
|
+
matchedEntry: params.candidate.entry,
|
|
6708
|
+
sameSubject: resolveSameSubject(params.entry.subject, params.candidate.entry.subject),
|
|
6709
|
+
llm_action: params.llmDecision?.action,
|
|
6710
|
+
llm_reasoning: params.llmDecision?.reasoning
|
|
6711
|
+
},
|
|
6712
|
+
mutation: {
|
|
6713
|
+
kind: "update",
|
|
6714
|
+
matchedEntry: params.candidate.entry,
|
|
6715
|
+
similarity: params.candidate.similarity,
|
|
6716
|
+
mergedContent: params.candidate.entry.content,
|
|
6717
|
+
llmDecision: params.llmDecision
|
|
6718
|
+
}
|
|
6719
|
+
};
|
|
6720
|
+
}
|
|
6696
6721
|
function stripPossessives(s) {
|
|
6697
6722
|
return s.replace(/['\u2018\u2019]s\b/g, "").replace(/['\u2018\u2019](?=\s|$)/g, "");
|
|
6698
6723
|
}
|
|
@@ -6766,19 +6791,30 @@ async function planEntryAction(db, entry, embedding, contentHash, options) {
|
|
|
6766
6791
|
const similarity = topMatch?.similarity ?? 0;
|
|
6767
6792
|
const sameSubject = topMatch ? resolveSameSubject(entry.subject, topMatch.entry.subject) : false;
|
|
6768
6793
|
const sameType = topMatch ? entry.type === topMatch.entry.type : false;
|
|
6794
|
+
const topMatchNeedsExpiryPromotion = topMatch !== void 0 && incomingExpiryOutranksExisting(topMatch.entry.expiry, entry.expiry);
|
|
6769
6795
|
if (topMatch && similarity >= AUTO_SKIP_THRESHOLD && sameType) {
|
|
6770
|
-
|
|
6771
|
-
|
|
6772
|
-
|
|
6773
|
-
|
|
6774
|
-
|
|
6775
|
-
|
|
6776
|
-
|
|
6777
|
-
|
|
6778
|
-
|
|
6779
|
-
|
|
6780
|
-
|
|
6781
|
-
|
|
6796
|
+
if (topMatchNeedsExpiryPromotion) {
|
|
6797
|
+
if (sameSubject) {
|
|
6798
|
+
return buildExpiryPromotionUpdate({
|
|
6799
|
+
entry,
|
|
6800
|
+
candidate: topMatch,
|
|
6801
|
+
reason: "near-exact duplicate promoted existing entry expiry"
|
|
6802
|
+
});
|
|
6803
|
+
}
|
|
6804
|
+
} else {
|
|
6805
|
+
return {
|
|
6806
|
+
decision: {
|
|
6807
|
+
entry,
|
|
6808
|
+
action: "skipped",
|
|
6809
|
+
reason: "near-exact semantic duplicate",
|
|
6810
|
+
similarity,
|
|
6811
|
+
matchedEntryId: topMatch.entry.id,
|
|
6812
|
+
matchedEntry: topMatch.entry,
|
|
6813
|
+
sameSubject
|
|
6814
|
+
},
|
|
6815
|
+
mutation: { kind: "none" }
|
|
6816
|
+
};
|
|
6817
|
+
}
|
|
6782
6818
|
}
|
|
6783
6819
|
if (topMatch && similarity >= SMART_DEDUP_THRESHOLD && sameSubject && sameType) {
|
|
6784
6820
|
return {
|
|
@@ -6953,6 +6989,23 @@ async function planEntryAction(db, entry, embedding, contentHash, options) {
|
|
|
6953
6989
|
};
|
|
6954
6990
|
}
|
|
6955
6991
|
if (llmDecision.action === "SKIP") {
|
|
6992
|
+
if (incomingExpiryOutranksExisting(candidate.entry.expiry, entry.expiry)) {
|
|
6993
|
+
const overrideReasoning = [
|
|
6994
|
+
llmDecision.reasoning,
|
|
6995
|
+
`SKIP is disallowed because incoming expiry ${entry.expiry} outranks existing ${candidate.entry.expiry}; preserving existing content and promoting expiry via UPDATE.`
|
|
6996
|
+
].filter((part) => part.trim().length > 0).join(" ");
|
|
6997
|
+
return buildExpiryPromotionUpdate({
|
|
6998
|
+
entry,
|
|
6999
|
+
candidate,
|
|
7000
|
+
reason: "online dedup SKIP overridden to UPDATE for higher-tier incoming entry",
|
|
7001
|
+
llmDecision: {
|
|
7002
|
+
action: "UPDATE",
|
|
7003
|
+
target_id: candidate.entry.id,
|
|
7004
|
+
merged_content: candidate.entry.content,
|
|
7005
|
+
reasoning: overrideReasoning
|
|
7006
|
+
}
|
|
7007
|
+
});
|
|
7008
|
+
}
|
|
6956
7009
|
return {
|
|
6957
7010
|
decision: {
|
|
6958
7011
|
entry,
|
package/dist/cli-main.js
CHANGED
|
@@ -71,7 +71,7 @@ import {
|
|
|
71
71
|
toRecord,
|
|
72
72
|
updateRecallMetadata,
|
|
73
73
|
warnIfLocked
|
|
74
|
-
} from "./chunk-
|
|
74
|
+
} from "./chunk-5XOV72MD.js";
|
|
75
75
|
import {
|
|
76
76
|
APP_VERSION,
|
|
77
77
|
DEFAULT_DB_PATH,
|
|
@@ -18142,12 +18142,12 @@ function registerMaintainCommand(program) {
|
|
|
18142
18142
|
"--only <tasks>",
|
|
18143
18143
|
"Comma-separated task names: quality,edge-decay,clusters,conflicts,consolidation,retirement,reflection"
|
|
18144
18144
|
).option("--prune-edges", "When edge decay runs, delete edges below the configured decay floor").option("--verbose", "Show detailed per-task output").action(async (opts) => {
|
|
18145
|
-
const { runMaintainCommand } = await import("./maintain-
|
|
18145
|
+
const { runMaintainCommand } = await import("./maintain-73ULONFM.js");
|
|
18146
18146
|
const result = await runMaintainCommand(opts);
|
|
18147
18147
|
process.exitCode = result.exitCode;
|
|
18148
18148
|
});
|
|
18149
18149
|
maintainCommand.command("history").description("Show past maintenance runs").option("--db <path>", "Database path override").option("--limit <n>", "Max runs to show (default: 10)", parseIntOption).option("--json", "Output as JSON").action(async (opts) => {
|
|
18150
|
-
const { runMaintainHistoryCommand } = await import("./maintain-
|
|
18150
|
+
const { runMaintainHistoryCommand } = await import("./maintain-73ULONFM.js");
|
|
18151
18151
|
const result = await runMaintainHistoryCommand(opts);
|
|
18152
18152
|
process.exitCode = result.exitCode;
|
|
18153
18153
|
});
|