portable-agent-layer 0.5.0 → 0.6.1

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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "portable-agent-layer",
3
- "version": "0.5.0",
3
+ "version": "0.6.1",
4
4
  "description": "PAL — Portable Agent Layer: persistent personal context for AI coding assistants",
5
5
  "type": "module",
6
6
  "bin": {
@@ -46,6 +46,7 @@ interface GraduationState {
46
46
 
47
47
  export interface GraduationResult {
48
48
  candidates: PatternGroup[];
49
+ emerging: PatternGroup[];
49
50
  graduated: GraduatedEntry[];
50
51
  updated: GraduatedEntry[];
51
52
  }
@@ -354,7 +355,7 @@ function groupPatterns(entries: LearningEntry[]): PatternGroup[] {
354
355
  }
355
356
  }
356
357
 
357
- return groups.filter((g) => g.entries.length >= MIN_OCCURRENCES);
358
+ return groups.filter((g) => g.entries.length >= 2);
358
359
  }
359
360
 
360
361
  // ── State Management ──
@@ -409,9 +410,12 @@ export function graduate(): GraduationResult {
409
410
  `Collected ${failures.length} failures, ${learnings.length} learnings`
410
411
  );
411
412
 
412
- const candidates = groupPatterns(all);
413
+ const allGroups = groupPatterns(all);
414
+ const candidates = allGroups.filter((g) => g.entries.length >= MIN_OCCURRENCES);
415
+ const emerging = allGroups.filter((g) => g.entries.length === 2);
413
416
  const result: GraduationResult = {
414
417
  candidates,
418
+ emerging,
415
419
  graduated: [],
416
420
  updated: [],
417
421
  };
@@ -13,8 +13,8 @@ import { graduate } from "../hooks/lib/graduation";
13
13
 
14
14
  const result = graduate();
15
15
 
16
- if (result.candidates.length === 0) {
17
- console.log("\n No recurring patterns found (need 3+ similar entries).\n");
16
+ if (result.candidates.length === 0 && result.emerging.length === 0) {
17
+ console.log("\n No recurring patterns found.\n");
18
18
  process.exit(0);
19
19
  }
20
20
 
@@ -51,5 +51,29 @@ for (const candidate of result.candidates) {
51
51
  console.log(" ─────────────────────────────────────────────────\n");
52
52
  }
53
53
 
54
- console.log(" To crystallize: add a line to the wisdom frame file.");
55
- console.log(" Format: - Your principle here [CRYSTAL: 85%]\n");
54
+ if (result.emerging.length > 0) {
55
+ console.log(` Emerging (2x one more to graduate)\n`);
56
+ for (const group of result.emerging) {
57
+ const principles = [
58
+ ...new Set(group.entries.map((e) => e.principle).filter((p) => p.length > 0)),
59
+ ];
60
+ console.log(` [${group.domain}] ${group.entries.length}x`);
61
+ for (const entry of group.entries) {
62
+ const sourceType = entry.source.startsWith("failure:") ? "failure" : "learning";
63
+ console.log(
64
+ ` ${entry.date || "unknown"} [${sourceType}] ${entry.text.slice(0, 80)}`
65
+ );
66
+ }
67
+ if (principles.length > 0) {
68
+ for (const p of principles) {
69
+ console.log(` → ${p}`);
70
+ }
71
+ }
72
+ console.log("");
73
+ }
74
+ }
75
+
76
+ if (result.candidates.length > 0) {
77
+ console.log(" To crystallize: add a line to the wisdom frame file.");
78
+ console.log(" Format: - Your principle here [CRYSTAL: 85%]\n");
79
+ }
@@ -18,8 +18,9 @@ const { values: args } = parseArgs({
18
18
  const sessionId = args.session;
19
19
  if (!sessionId) process.exit(0);
20
20
 
21
- const HOME = process.env.HOME ?? "~";
22
- const claudeDir = resolve(HOME, ".claude", "projects");
21
+ import { homedir } from "node:os";
22
+
23
+ const claudeDir = resolve(homedir(), ".claude", "projects");
23
24
 
24
25
  // ── Find the JSONL file containing this session ──
25
26