portable-agent-layer 0.13.0 → 0.14.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/package.json
CHANGED
|
@@ -37,8 +37,8 @@ export interface Opinion {
|
|
|
37
37
|
// ── Confidence Deltas (matching original PAI) ──
|
|
38
38
|
|
|
39
39
|
const CONFIDENCE_DELTAS: Record<EvidenceType, number> = {
|
|
40
|
-
supporting: 0.
|
|
41
|
-
counter: -0.
|
|
40
|
+
supporting: 0.05,
|
|
41
|
+
counter: -0.1,
|
|
42
42
|
confirmation: 0.1,
|
|
43
43
|
contradiction: -0.2,
|
|
44
44
|
};
|
|
@@ -130,13 +130,13 @@ export function findSimilarOpinion(
|
|
|
130
130
|
return null;
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
-
/** Create a new opinion from a recurring note. Starts at confidence 0.
|
|
133
|
+
/** Create a new opinion from a recurring note. Starts at confidence 0.60. */
|
|
134
134
|
export function createOpinion(statement: string, source: string): Opinion {
|
|
135
135
|
const now = new Date().toISOString().slice(0, 10);
|
|
136
136
|
return {
|
|
137
137
|
id: slugify(statement),
|
|
138
138
|
statement,
|
|
139
|
-
confidence: 0.
|
|
139
|
+
confidence: 0.6,
|
|
140
140
|
category: classifyCategory(statement),
|
|
141
141
|
evidence: [{ date: now, type: "supporting", source }],
|
|
142
142
|
created: now,
|
|
@@ -144,12 +144,19 @@ export function createOpinion(statement: string, source: string): Opinion {
|
|
|
144
144
|
};
|
|
145
145
|
}
|
|
146
146
|
|
|
147
|
-
/**
|
|
147
|
+
/** Check if an opinion already has evidence with this exact source text. */
|
|
148
|
+
export function hasEvidence(opinion: Opinion, source: string): boolean {
|
|
149
|
+
return opinion.evidence.some((e) => e.source === source);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/** Add evidence to an opinion and adjust its confidence. No-op if duplicate. */
|
|
148
153
|
export function addEvidence(
|
|
149
154
|
opinion: Opinion,
|
|
150
155
|
type: EvidenceType,
|
|
151
156
|
source: string
|
|
152
157
|
): Opinion {
|
|
158
|
+
if (hasEvidence(opinion, source)) return opinion;
|
|
159
|
+
|
|
153
160
|
const now = new Date().toISOString().slice(0, 10);
|
|
154
161
|
const delta = CONFIDENCE_DELTAS[type];
|
|
155
162
|
const newConfidence = Math.min(
|
|
@@ -100,6 +100,32 @@ const STOP_WORDS = new Set([
|
|
|
100
100
|
"own",
|
|
101
101
|
]);
|
|
102
102
|
|
|
103
|
+
/** Strip common English suffixes to normalize word forms. Applied twice to handle stacked suffixes. */
|
|
104
|
+
function stemOnce(word: string): string {
|
|
105
|
+
if (word.length <= 4) return word;
|
|
106
|
+
return word
|
|
107
|
+
.replace(/(?<=.{4})tion$/, "")
|
|
108
|
+
.replace(/(?<=.{4})sion$/, "")
|
|
109
|
+
.replace(/(?<=.{4})ment$/, "")
|
|
110
|
+
.replace(/(?<=.{3})ness$/, "")
|
|
111
|
+
.replace(/(?<=.{3})ings$/, "")
|
|
112
|
+
.replace(/(?<=.{3})ing$/, "")
|
|
113
|
+
.replace(/(?<=.{3})ies$/, "y")
|
|
114
|
+
.replace(/(?<=.{3})ive$/, "")
|
|
115
|
+
.replace(/(?<=.{3})ous$/, "")
|
|
116
|
+
.replace(/(?<=.{3})ful$/, "")
|
|
117
|
+
.replace(/(?<=.{3})ally$/, "")
|
|
118
|
+
.replace(/(?<=.{3})ly$/, "")
|
|
119
|
+
.replace(/(?<=.{3})ed$/, "")
|
|
120
|
+
.replace(/(?<=.{3})er$/, "")
|
|
121
|
+
.replace(/(?<=.{3})es$/, "")
|
|
122
|
+
.replace(/(?<=.{3})s$/, "");
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function stem(word: string): string {
|
|
126
|
+
return stemOnce(stemOnce(word));
|
|
127
|
+
}
|
|
128
|
+
|
|
103
129
|
export function extractKeywords(text: string): Set<string> {
|
|
104
130
|
return new Set(
|
|
105
131
|
text
|
|
@@ -107,6 +133,8 @@ export function extractKeywords(text: string): Set<string> {
|
|
|
107
133
|
.replace(/[^a-z0-9\s-]/g, " ")
|
|
108
134
|
.split(/\s+/)
|
|
109
135
|
.filter((w) => w.length > 2 && !STOP_WORDS.has(w))
|
|
136
|
+
.map((w) => stem(w))
|
|
137
|
+
.filter((w) => w.length > 2)
|
|
110
138
|
);
|
|
111
139
|
}
|
|
112
140
|
|
|
@@ -20,10 +20,8 @@ import {
|
|
|
20
20
|
addEvidence,
|
|
21
21
|
createOpinion,
|
|
22
22
|
findSimilarOpinion,
|
|
23
|
-
getLastReflectDate,
|
|
24
23
|
readOpinions,
|
|
25
24
|
saveOpinion,
|
|
26
|
-
setLastReflectDate,
|
|
27
25
|
} from "../hooks/lib/opinions";
|
|
28
26
|
import { palHome } from "../hooks/lib/paths";
|
|
29
27
|
import { similarity } from "../hooks/lib/text-similarity";
|
|
@@ -157,12 +155,9 @@ function loadRatings(daysBack: number): Rating[] {
|
|
|
157
155
|
function promoteToOpinions(notes: ParsedNote[], dryRun: boolean): OpinionChange[] {
|
|
158
156
|
const changes: OpinionChange[] = [];
|
|
159
157
|
const opinions = readOpinions();
|
|
160
|
-
const lastReflect = getLastReflectDate();
|
|
161
158
|
|
|
162
|
-
//
|
|
163
|
-
const opinionNotes = notes.filter(
|
|
164
|
-
(n) => n.type === "O" && (!lastReflect || n.date > lastReflect)
|
|
165
|
-
);
|
|
159
|
+
// All O notes in the window — deduplication happens at the evidence level
|
|
160
|
+
const opinionNotes = notes.filter((n) => n.type === "O");
|
|
166
161
|
|
|
167
162
|
// Group similar notes together
|
|
168
163
|
const groups = new Map<string, ParsedNote[]>();
|
|
@@ -202,7 +197,11 @@ function promoteToOpinions(notes: ParsedNote[], dryRun: boolean): OpinionChange[
|
|
|
202
197
|
}
|
|
203
198
|
} else if (group.length >= 2) {
|
|
204
199
|
// New opinion — requires at least 2 occurrences
|
|
205
|
-
|
|
200
|
+
// Store individual note texts as evidence so re-runs deduplicate correctly
|
|
201
|
+
let opinion = createOpinion(representative, group[0].text.slice(0, 120));
|
|
202
|
+
for (const note of group.slice(1)) {
|
|
203
|
+
opinion = addEvidence(opinion, "supporting", note.text.slice(0, 120));
|
|
204
|
+
}
|
|
206
205
|
changes.push({
|
|
207
206
|
statement: representative,
|
|
208
207
|
action: "created",
|
|
@@ -458,7 +457,6 @@ if (dryRun) {
|
|
|
458
457
|
} else {
|
|
459
458
|
const report = formatReport(period, notes, ratings, opinionChanges);
|
|
460
459
|
const filepath = writeReport(report, period);
|
|
461
|
-
setLastReflectDate(new Date().toISOString().slice(0, 10));
|
|
462
460
|
console.log(`\nCreated reflection report: ${filepath}`);
|
|
463
461
|
|
|
464
462
|
const opinions = readOpinions();
|