portable-agent-layer 0.8.1 → 0.10.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/assets/templates/AGENTS.md.template +6 -0
- package/assets/templates/STEERING-RULES.md +23 -0
- package/package.json +2 -2
- package/src/hooks/LoadContext.ts +1 -4
- package/src/hooks/handlers/rating.ts +9 -49
- package/src/hooks/handlers/reflect-trigger.ts +83 -0
- package/src/hooks/handlers/relationship.ts +8 -5
- package/src/hooks/handlers/session-name.ts +8 -6
- package/src/hooks/handlers/work-learning.ts +1 -0
- package/src/hooks/handlers/work-session.ts +16 -3
- package/src/hooks/lib/claude-md.ts +12 -2
- package/src/hooks/lib/context.ts +31 -21
- package/src/hooks/lib/graduation.ts +6 -4
- package/src/hooks/lib/learning-store.ts +7 -117
- package/src/hooks/lib/log.ts +1 -3
- package/src/hooks/lib/opinions.ts +191 -0
- package/src/hooks/lib/relationship.ts +5 -4
- package/src/hooks/lib/security.ts +3 -0
- package/src/hooks/lib/stop.ts +3 -0
- package/src/hooks/lib/text-similarity.ts +125 -0
- package/src/hooks/lib/work-tracking.ts +1 -1
- package/src/targets/opencode/install.ts +6 -2
- package/src/targets/opencode/plugin.ts +20 -171
- package/src/tools/analyze.ts +49 -15
- package/src/tools/opinion.ts +250 -0
- package/src/tools/relationship-reflect.ts +215 -105
- package/src/hooks/lib/prompts.ts +0 -11
- package/src/tools/eval-principles.ts +0 -234
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* RelationshipReflect — Periodic reflection on relationship patterns.
|
|
4
4
|
*
|
|
5
|
-
* Reads recent relationship notes and ratings to
|
|
6
|
-
* -
|
|
7
|
-
* -
|
|
8
|
-
* -
|
|
5
|
+
* Reads recent relationship notes and ratings to:
|
|
6
|
+
* - Promote recurring O/B notes into tracked opinions with confidence
|
|
7
|
+
* - Update confidence on existing opinions via supporting evidence
|
|
8
|
+
* - Generate a summary report
|
|
9
9
|
*
|
|
10
10
|
* Usage:
|
|
11
11
|
* bun run tool:reflect # Reflect on last 7 days
|
|
@@ -16,7 +16,17 @@
|
|
|
16
16
|
import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
17
17
|
import { resolve } from "node:path";
|
|
18
18
|
import { parseArgs } from "node:util";
|
|
19
|
+
import {
|
|
20
|
+
addEvidence,
|
|
21
|
+
createOpinion,
|
|
22
|
+
findSimilarOpinion,
|
|
23
|
+
getLastReflectDate,
|
|
24
|
+
readOpinions,
|
|
25
|
+
saveOpinion,
|
|
26
|
+
setLastReflectDate,
|
|
27
|
+
} from "../hooks/lib/opinions";
|
|
19
28
|
import { palHome } from "../hooks/lib/paths";
|
|
29
|
+
import { similarity } from "../hooks/lib/text-similarity";
|
|
20
30
|
|
|
21
31
|
// ── Paths ──
|
|
22
32
|
|
|
@@ -34,28 +44,18 @@ interface Rating {
|
|
|
34
44
|
}
|
|
35
45
|
|
|
36
46
|
interface ParsedNote {
|
|
37
|
-
type: "W" | "O";
|
|
47
|
+
type: "W" | "O" | "B";
|
|
38
48
|
text: string;
|
|
39
49
|
confidence?: number;
|
|
40
50
|
date: string;
|
|
41
51
|
time: string;
|
|
42
52
|
}
|
|
43
53
|
|
|
44
|
-
interface
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
opinions: OpinionSummary[];
|
|
50
|
-
worldFacts: string[];
|
|
51
|
-
ratingCorrelation: string[];
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
interface OpinionSummary {
|
|
55
|
-
text: string;
|
|
56
|
-
occurrences: number;
|
|
57
|
-
avgConfidence: number;
|
|
58
|
-
dates: string[];
|
|
54
|
+
interface OpinionChange {
|
|
55
|
+
statement: string;
|
|
56
|
+
action: "created" | "strengthened";
|
|
57
|
+
oldConfidence?: number;
|
|
58
|
+
newConfidence: number;
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
// ── Note Parsing ──
|
|
@@ -68,7 +68,7 @@ function loadNotes(daysBack: number): ParsedNote[] {
|
|
|
68
68
|
const notes: ParsedNote[] = [];
|
|
69
69
|
|
|
70
70
|
for (const monthDir of readdirSync(RELATIONSHIP_DIR).sort().reverse()) {
|
|
71
|
-
if (monthDir
|
|
71
|
+
if (!/^\d{4}-\d{2}$/.test(monthDir)) continue;
|
|
72
72
|
const monthPath = resolve(RELATIONSHIP_DIR, monthDir);
|
|
73
73
|
|
|
74
74
|
let files: string[];
|
|
@@ -96,13 +96,13 @@ function loadNotes(daysBack: number): ParsedNote[] {
|
|
|
96
96
|
continue;
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
// O(c=0.85): text
|
|
100
|
-
const
|
|
101
|
-
if (
|
|
99
|
+
// O(c=0.85): text or B(c=0.85): text
|
|
100
|
+
const obMatch = line.match(/^- ([OB])\(c=([\d.]+)\):\s*(.+)$/);
|
|
101
|
+
if (obMatch) {
|
|
102
102
|
notes.push({
|
|
103
|
-
type: "O",
|
|
104
|
-
confidence: Number.parseFloat(
|
|
105
|
-
text:
|
|
103
|
+
type: obMatch[1] as "O" | "B",
|
|
104
|
+
confidence: Number.parseFloat(obMatch[2]),
|
|
105
|
+
text: obMatch[3],
|
|
106
106
|
date: dateStr,
|
|
107
107
|
time: currentTime,
|
|
108
108
|
});
|
|
@@ -152,39 +152,115 @@ function loadRatings(daysBack: number): Rating[] {
|
|
|
152
152
|
);
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
-
// ──
|
|
155
|
+
// ── Opinion Promotion ──
|
|
156
|
+
|
|
157
|
+
function promoteToOpinions(notes: ParsedNote[], dryRun: boolean): OpinionChange[] {
|
|
158
|
+
const changes: OpinionChange[] = [];
|
|
159
|
+
const opinions = readOpinions();
|
|
160
|
+
const lastReflect = getLastReflectDate();
|
|
161
|
+
|
|
162
|
+
// Only O and B notes become opinions, skip already-processed notes
|
|
163
|
+
const opinionNotes = notes.filter(
|
|
164
|
+
(n) => (n.type === "O" || n.type === "B") && (!lastReflect || n.date > lastReflect)
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
// Group similar notes together
|
|
168
|
+
const groups = new Map<string, ParsedNote[]>();
|
|
169
|
+
for (const note of opinionNotes) {
|
|
170
|
+
let matched = false;
|
|
171
|
+
for (const [key, group] of groups) {
|
|
172
|
+
if (similarity(note.text, key) >= 0.3) {
|
|
173
|
+
group.push(note);
|
|
174
|
+
matched = true;
|
|
175
|
+
break;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
if (!matched) {
|
|
179
|
+
groups.set(note.text, [note]);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
for (const [representative, group] of groups) {
|
|
184
|
+
// Check against existing opinions
|
|
185
|
+
const existing = findSimilarOpinion(representative, opinions);
|
|
186
|
+
|
|
187
|
+
if (existing) {
|
|
188
|
+
// Add supporting evidence for each new note
|
|
189
|
+
let updated = existing;
|
|
190
|
+
for (const note of group) {
|
|
191
|
+
updated = addEvidence(updated, "supporting", note.text.slice(0, 120));
|
|
192
|
+
}
|
|
156
193
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
194
|
+
if (updated.confidence !== existing.confidence) {
|
|
195
|
+
changes.push({
|
|
196
|
+
statement: existing.statement,
|
|
197
|
+
action: "strengthened",
|
|
198
|
+
oldConfidence: existing.confidence,
|
|
199
|
+
newConfidence: updated.confidence,
|
|
200
|
+
});
|
|
201
|
+
if (!dryRun) saveOpinion(updated);
|
|
202
|
+
}
|
|
203
|
+
} else if (group.length >= 2) {
|
|
204
|
+
// New opinion — requires at least 2 occurrences
|
|
205
|
+
const opinion = createOpinion(representative, `${group.length}x in reflect period`);
|
|
206
|
+
changes.push({
|
|
207
|
+
statement: representative,
|
|
208
|
+
action: "created",
|
|
209
|
+
newConfidence: opinion.confidence,
|
|
210
|
+
});
|
|
211
|
+
if (!dryRun) saveOpinion(opinion);
|
|
212
|
+
}
|
|
168
213
|
}
|
|
169
214
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
215
|
+
return changes;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// ── Analysis ──
|
|
219
|
+
|
|
220
|
+
interface OpinionSummary {
|
|
221
|
+
text: string;
|
|
222
|
+
occurrences: number;
|
|
223
|
+
avgConfidence: number;
|
|
224
|
+
dates: string[];
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function groupNoteOccurrences(notes: ParsedNote[]): OpinionSummary[] {
|
|
228
|
+
const opNotes = notes.filter((n) => n.type === "O" || n.type === "B");
|
|
229
|
+
const groups = new Map<
|
|
230
|
+
string,
|
|
231
|
+
{ confidences: number[]; dates: string[]; text: string }
|
|
232
|
+
>();
|
|
233
|
+
|
|
234
|
+
for (const note of opNotes) {
|
|
235
|
+
let matched = false;
|
|
236
|
+
for (const [key, group] of groups) {
|
|
237
|
+
if (similarity(note.text, key) >= 0.3) {
|
|
238
|
+
if (note.confidence !== undefined) group.confidences.push(note.confidence);
|
|
239
|
+
group.dates.push(note.date);
|
|
240
|
+
matched = true;
|
|
241
|
+
break;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
if (!matched) {
|
|
245
|
+
groups.set(note.text, {
|
|
246
|
+
text: note.text,
|
|
247
|
+
confidences: note.confidence !== undefined ? [note.confidence] : [],
|
|
248
|
+
dates: [note.date],
|
|
249
|
+
});
|
|
250
|
+
}
|
|
185
251
|
}
|
|
186
252
|
|
|
187
|
-
return
|
|
253
|
+
return [...groups.values()]
|
|
254
|
+
.map((g) => ({
|
|
255
|
+
text: g.text,
|
|
256
|
+
occurrences: g.dates.length,
|
|
257
|
+
avgConfidence:
|
|
258
|
+
g.confidences.length > 0
|
|
259
|
+
? g.confidences.reduce((a, b) => a + b, 0) / g.confidences.length
|
|
260
|
+
: 0,
|
|
261
|
+
dates: [...new Set(g.dates)],
|
|
262
|
+
}))
|
|
263
|
+
.sort((a, b) => b.occurrences - a.occurrences);
|
|
188
264
|
}
|
|
189
265
|
|
|
190
266
|
function correlateRatings(ratings: Rating[]): string[] {
|
|
@@ -219,48 +295,53 @@ function correlateRatings(ratings: Rating[]): string[] {
|
|
|
219
295
|
return correlations;
|
|
220
296
|
}
|
|
221
297
|
|
|
222
|
-
|
|
298
|
+
// ── Report ──
|
|
299
|
+
|
|
300
|
+
function formatReport(
|
|
301
|
+
period: string,
|
|
223
302
|
notes: ParsedNote[],
|
|
224
303
|
ratings: Rating[],
|
|
225
|
-
|
|
226
|
-
):
|
|
304
|
+
opinionChanges: OpinionChange[]
|
|
305
|
+
): string {
|
|
306
|
+
const date = new Date().toISOString().slice(0, 10);
|
|
227
307
|
const avgRating =
|
|
228
308
|
ratings.length > 0 ? ratings.reduce((s, r) => s + r.rating, 0) / ratings.length : 0;
|
|
309
|
+
const summaries = groupNoteOccurrences(notes);
|
|
310
|
+
const worldFacts = notes.filter((n) => n.type === "W").map((n) => n.text);
|
|
311
|
+
const ratingInsights = correlateRatings(ratings);
|
|
229
312
|
|
|
230
|
-
return {
|
|
231
|
-
period,
|
|
232
|
-
totalNotes: notes.length,
|
|
233
|
-
totalRatings: ratings.length,
|
|
234
|
-
avgRating,
|
|
235
|
-
opinions: groupOpinions(notes),
|
|
236
|
-
worldFacts: notes
|
|
237
|
-
.filter((n) => n.type === "W")
|
|
238
|
-
.map((n) => n.text)
|
|
239
|
-
.slice(0, 10),
|
|
240
|
-
ratingCorrelation: correlateRatings(ratings),
|
|
241
|
-
};
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
// ── Report ──
|
|
245
|
-
|
|
246
|
-
function formatReport(result: ReflectionResult): string {
|
|
247
|
-
const date = new Date().toISOString().slice(0, 10);
|
|
248
313
|
const lines: string[] = [
|
|
249
314
|
"# Relationship Reflection",
|
|
250
315
|
"",
|
|
251
|
-
`**Period:** ${
|
|
316
|
+
`**Period:** ${period}`,
|
|
252
317
|
`**Generated:** ${date}`,
|
|
253
|
-
`**Notes analyzed:** ${
|
|
254
|
-
`**Ratings analyzed:** ${
|
|
255
|
-
`**Average Rating:** ${
|
|
318
|
+
`**Notes analyzed:** ${notes.length}`,
|
|
319
|
+
`**Ratings analyzed:** ${ratings.length}`,
|
|
320
|
+
`**Average Rating:** ${avgRating.toFixed(1)}/10`,
|
|
256
321
|
"",
|
|
257
322
|
"---",
|
|
258
323
|
"",
|
|
259
324
|
];
|
|
260
325
|
|
|
261
|
-
if (
|
|
326
|
+
if (opinionChanges.length > 0) {
|
|
327
|
+
lines.push("## Opinion Changes", "");
|
|
328
|
+
for (const change of opinionChanges) {
|
|
329
|
+
if (change.action === "created") {
|
|
330
|
+
lines.push(
|
|
331
|
+
`- **NEW** (${Math.round(change.newConfidence * 100)}%): ${change.statement}`
|
|
332
|
+
);
|
|
333
|
+
} else {
|
|
334
|
+
lines.push(
|
|
335
|
+
`- **+** ${Math.round(change.oldConfidence ?? 0 * 100)}% → ${Math.round(change.newConfidence * 100)}%: ${change.statement}`
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
lines.push("");
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
if (summaries.length > 0) {
|
|
262
343
|
lines.push("## Recurring Opinions", "");
|
|
263
|
-
for (const op of
|
|
344
|
+
for (const op of summaries) {
|
|
264
345
|
lines.push(
|
|
265
346
|
`- **${op.text}**`,
|
|
266
347
|
` Seen ${op.occurrences}x | Avg confidence: ${op.avgConfidence.toFixed(2)} | Dates: ${op.dates.join(", ")}`,
|
|
@@ -269,17 +350,17 @@ function formatReport(result: ReflectionResult): string {
|
|
|
269
350
|
}
|
|
270
351
|
}
|
|
271
352
|
|
|
272
|
-
if (
|
|
353
|
+
if (worldFacts.length > 0) {
|
|
273
354
|
lines.push("## World Facts Observed", "");
|
|
274
|
-
for (const fact of
|
|
355
|
+
for (const fact of worldFacts.slice(0, 10)) {
|
|
275
356
|
lines.push(`- ${fact}`);
|
|
276
357
|
}
|
|
277
358
|
lines.push("");
|
|
278
359
|
}
|
|
279
360
|
|
|
280
|
-
if (
|
|
361
|
+
if (ratingInsights.length > 0) {
|
|
281
362
|
lines.push("## Rating Insights", "");
|
|
282
|
-
for (const c of
|
|
363
|
+
for (const c of ratingInsights) {
|
|
283
364
|
lines.push(`- ${c}`);
|
|
284
365
|
}
|
|
285
366
|
lines.push("");
|
|
@@ -288,7 +369,7 @@ function formatReport(result: ReflectionResult): string {
|
|
|
288
369
|
return lines.join("\n");
|
|
289
370
|
}
|
|
290
371
|
|
|
291
|
-
function writeReport(
|
|
372
|
+
function writeReport(report: string, period: string): string {
|
|
292
373
|
if (!existsSync(REFLECTION_DIR)) mkdirSync(REFLECTION_DIR, { recursive: true });
|
|
293
374
|
|
|
294
375
|
const date = new Date().toISOString().slice(0, 10);
|
|
@@ -296,7 +377,7 @@ function writeReport(result: ReflectionResult, period: string): string {
|
|
|
296
377
|
const filename = `${date}_${slug}-reflection.md`;
|
|
297
378
|
const filepath = resolve(REFLECTION_DIR, filename);
|
|
298
379
|
|
|
299
|
-
writeFileSync(filepath,
|
|
380
|
+
writeFileSync(filepath, report, "utf-8");
|
|
300
381
|
return filepath;
|
|
301
382
|
}
|
|
302
383
|
|
|
@@ -313,50 +394,79 @@ const { values } = parseArgs({
|
|
|
313
394
|
|
|
314
395
|
if (values.help) {
|
|
315
396
|
console.log(`
|
|
316
|
-
RelationshipReflect — Periodic reflection
|
|
397
|
+
RelationshipReflect — Periodic reflection + opinion promotion
|
|
398
|
+
|
|
399
|
+
Reads recent relationship notes and ratings. Promotes recurring
|
|
400
|
+
observations (O/B types) into tracked opinions with confidence scoring.
|
|
317
401
|
|
|
318
402
|
Usage:
|
|
319
403
|
bun run tool:reflect Reflect on last 7 days (default)
|
|
320
404
|
bun run tool:reflect -- --month Reflect on last 30 days
|
|
321
405
|
bun run tool:reflect -- --dry-run Preview without writing
|
|
322
406
|
|
|
323
|
-
Output:
|
|
407
|
+
Output:
|
|
408
|
+
- Updates memory/relationship/opinions.json (confidence tracking)
|
|
409
|
+
- Creates reflection report in memory/relationship/reflections/
|
|
324
410
|
`);
|
|
325
411
|
process.exit(0);
|
|
326
412
|
}
|
|
327
413
|
|
|
328
414
|
const daysBack = values.month ? 30 : 7;
|
|
329
415
|
const period = values.month ? "Monthly" : "Weekly";
|
|
416
|
+
const dryRun = values["dry-run"] ?? false;
|
|
330
417
|
|
|
331
418
|
const notes = loadNotes(daysBack);
|
|
332
419
|
const ratings = loadRatings(daysBack);
|
|
333
420
|
|
|
334
|
-
console.log(`Loaded ${notes.length}
|
|
335
|
-
console.log(`Loaded ${ratings.length} ratings
|
|
421
|
+
console.log(`Loaded ${notes.length} notes from last ${daysBack} days`);
|
|
422
|
+
console.log(`Loaded ${ratings.length} ratings`);
|
|
336
423
|
|
|
337
424
|
if (notes.length === 0 && ratings.length === 0) {
|
|
338
425
|
console.log("No data to analyze");
|
|
339
426
|
process.exit(0);
|
|
340
427
|
}
|
|
341
428
|
|
|
342
|
-
|
|
429
|
+
// Promote notes to opinions
|
|
430
|
+
const opinionChanges = promoteToOpinions(notes, dryRun);
|
|
343
431
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
console.log(
|
|
432
|
+
const avgRating =
|
|
433
|
+
ratings.length > 0 ? ratings.reduce((s, r) => s + r.rating, 0) / ratings.length : 0;
|
|
434
|
+
console.log(`\nAverage Rating: ${avgRating.toFixed(1)}/10`);
|
|
347
435
|
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
436
|
+
const summaries = groupNoteOccurrences(notes);
|
|
437
|
+
console.log(`Observations: ${summaries.length} unique`);
|
|
438
|
+
|
|
439
|
+
if (opinionChanges.length > 0) {
|
|
440
|
+
console.log(`\nOpinion changes:`);
|
|
441
|
+
for (const change of opinionChanges) {
|
|
442
|
+
if (change.action === "created") {
|
|
443
|
+
console.log(
|
|
444
|
+
` + NEW (${Math.round(change.newConfidence * 100)}%) ${change.statement.slice(0, 80)}`
|
|
445
|
+
);
|
|
446
|
+
} else {
|
|
447
|
+
console.log(
|
|
448
|
+
` ~ ${Math.round(change.oldConfidence ?? 0 * 100)}% → ${Math.round(change.newConfidence * 100)}% ${change.statement.slice(0, 80)}`
|
|
449
|
+
);
|
|
450
|
+
}
|
|
354
451
|
}
|
|
452
|
+
} else {
|
|
453
|
+
console.log("\nNo opinion changes");
|
|
355
454
|
}
|
|
356
455
|
|
|
357
|
-
if (
|
|
358
|
-
console.log("\n[DRY RUN] Would write reflection report");
|
|
456
|
+
if (dryRun) {
|
|
457
|
+
console.log("\n[DRY RUN] Would write reflection report + update opinions");
|
|
359
458
|
} else {
|
|
360
|
-
const
|
|
459
|
+
const report = formatReport(period, notes, ratings, opinionChanges);
|
|
460
|
+
const filepath = writeReport(report, period);
|
|
461
|
+
setLastReflectDate(new Date().toISOString().slice(0, 10));
|
|
361
462
|
console.log(`\nCreated reflection report: ${filepath}`);
|
|
463
|
+
|
|
464
|
+
const opinions = readOpinions();
|
|
465
|
+
const high = opinions.filter((o) => o.confidence >= 0.85);
|
|
466
|
+
if (high.length > 0) {
|
|
467
|
+
console.log(`\nHigh-confidence opinions (injected into context):`);
|
|
468
|
+
for (const o of high) {
|
|
469
|
+
console.log(` [${Math.round(o.confidence * 100)}%] ${o.statement.slice(0, 80)}`);
|
|
470
|
+
}
|
|
471
|
+
}
|
|
362
472
|
}
|
package/src/hooks/lib/prompts.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shared prompt fragments — single source of truth for inference instructions.
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
/** Principle extraction instruction for failed interactions. */
|
|
6
|
-
export const FAILURE_PRINCIPLE_PROMPT =
|
|
7
|
-
"Write one actionable sentence that would prevent this issue from happening again. If no clear lesson, leave principle empty. Be concise.";
|
|
8
|
-
|
|
9
|
-
/** Principle extraction instruction for session learnings. */
|
|
10
|
-
export const LEARNING_PRINCIPLE_PROMPT =
|
|
11
|
-
"If this session taught a reusable lesson, write one actionable sentence that would prevent the same issue in the future. If no clear lesson, leave empty. Be concise.";
|