portable-agent-layer 0.35.0 → 0.37.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.
Files changed (108) hide show
  1. package/README.md +2 -1
  2. package/assets/skills/analyze-pdf/tools/pdf-download.ts +1 -1
  3. package/assets/skills/analyze-youtube/tools/youtube-analyze.ts +1 -1
  4. package/assets/skills/consulting-report/tools/dev.ts +2 -2
  5. package/assets/skills/consulting-report/tools/generate-pdf.ts +9 -9
  6. package/assets/skills/consulting-report/tools/scaffold.ts +2 -2
  7. package/assets/skills/create-pdf/tools/md-to-html-pdf.ts +2 -2
  8. package/assets/skills/opinion/tools/opinion.ts +3 -2
  9. package/assets/skills/presentation/SKILL.md +1 -1
  10. package/assets/skills/presentation/tools/doctor.ts +2 -5
  11. package/assets/skills/presentation/tools/lib/inline.ts +6 -11
  12. package/assets/skills/presentation/tools/lib/lint-helpers.ts +2 -2
  13. package/assets/skills/presentation/tools/lib/lint-rules.ts +5 -2
  14. package/assets/skills/presentation/tools/setup-template.ts +10 -7
  15. package/assets/skills/projects/SKILL.md +44 -21
  16. package/assets/skills/research/tools/gemini-search.ts +2 -2
  17. package/assets/skills/research/tools/grok-search.ts +2 -2
  18. package/assets/skills/research/tools/perplexity-search.ts +2 -2
  19. package/assets/skills/telos/SKILL.md +7 -52
  20. package/assets/skills/telos/tools/update-telos.ts +0 -1
  21. package/assets/templates/PAL/ALGORITHM.md +54 -5
  22. package/assets/templates/PAL/PROJECT_LIFECYCLE.md +48 -0
  23. package/assets/templates/PAL/README.md +1 -1
  24. package/assets/templates/PAL/STEERING_RULES.md +4 -0
  25. package/assets/templates/PAL/SYSTEM_ARCHITECTURE.md +32 -17
  26. package/assets/templates/PAL/WORK_TRACKING.md +1 -1
  27. package/assets/templates/hooks.codex.json +44 -0
  28. package/assets/templates/hooks.cursor.json +11 -5
  29. package/assets/templates/pal-settings.json +1 -3
  30. package/assets/templates/settings.claude.json +2 -1
  31. package/package.json +2 -1
  32. package/src/cli/index.ts +112 -14
  33. package/src/cli/migrate.ts +299 -0
  34. package/src/cli/setup-identity.ts +3 -3
  35. package/src/cli/setup-telos.ts +12 -80
  36. package/src/hooks/CompactRecover.ts +11 -5
  37. package/src/hooks/LoadContext.ts +35 -11
  38. package/src/hooks/PreCompactPersist.ts +26 -34
  39. package/src/hooks/SecurityValidator.ts +43 -21
  40. package/src/hooks/StopOrchestrator.ts +4 -1
  41. package/src/hooks/UserPromptOrchestrator.ts +4 -2
  42. package/src/hooks/handlers/auto-graduate.ts +2 -2
  43. package/src/hooks/handlers/backup.ts +3 -3
  44. package/src/hooks/handlers/context-digests.ts +74 -0
  45. package/src/hooks/handlers/failure.ts +5 -3
  46. package/src/hooks/handlers/inject-retrieval.ts +29 -6
  47. package/src/hooks/handlers/persist-last-exchange.ts +76 -0
  48. package/src/hooks/handlers/rating.ts +2 -1
  49. package/src/hooks/handlers/readme-sync.ts +3 -2
  50. package/src/hooks/handlers/session-intelligence.ts +17 -93
  51. package/src/hooks/handlers/session-name.ts +2 -2
  52. package/src/hooks/handlers/synthesis.ts +5 -2
  53. package/src/hooks/handlers/update-counts.ts +3 -2
  54. package/src/hooks/lib/agent.ts +20 -18
  55. package/src/hooks/lib/claude-md.ts +69 -14
  56. package/src/hooks/lib/context.ts +92 -246
  57. package/src/hooks/lib/entities.ts +7 -7
  58. package/src/hooks/lib/frontmatter.ts +4 -4
  59. package/src/hooks/lib/graduation.ts +7 -6
  60. package/src/hooks/lib/inference.ts +6 -2
  61. package/src/hooks/lib/learning-category.ts +1 -1
  62. package/src/hooks/lib/learning-store.ts +6 -1
  63. package/src/hooks/lib/notify.ts +2 -2
  64. package/src/hooks/lib/opinions.ts +3 -3
  65. package/src/hooks/lib/paths.ts +2 -0
  66. package/src/hooks/lib/projects.ts +142 -74
  67. package/src/hooks/lib/readme-sync.ts +1 -1
  68. package/src/hooks/lib/relationship.ts +4 -16
  69. package/src/hooks/lib/retrieval-index.ts +5 -3
  70. package/src/hooks/lib/retrieval.ts +11 -12
  71. package/src/hooks/lib/security.ts +24 -18
  72. package/src/hooks/lib/semi-static.ts +188 -0
  73. package/src/hooks/lib/session-names.ts +1 -1
  74. package/src/hooks/lib/settings.ts +1 -1
  75. package/src/hooks/lib/setup.ts +2 -65
  76. package/src/hooks/lib/signals.ts +2 -2
  77. package/src/hooks/lib/stdin.ts +1 -1
  78. package/src/hooks/lib/stop.ts +16 -6
  79. package/src/hooks/lib/token-usage.ts +1 -2
  80. package/src/hooks/lib/transcript.ts +1 -1
  81. package/src/hooks/lib/wisdom.ts +5 -5
  82. package/src/hooks/lib/work-tracking.ts +8 -14
  83. package/src/targets/claude/uninstall.ts +1 -1
  84. package/src/targets/codex/install.ts +95 -0
  85. package/src/targets/codex/uninstall.ts +70 -0
  86. package/src/targets/copilot/install.ts +39 -8
  87. package/src/targets/copilot/uninstall.ts +58 -17
  88. package/src/targets/cursor/install.ts +8 -0
  89. package/src/targets/cursor/uninstall.ts +18 -1
  90. package/src/targets/lib.ts +166 -14
  91. package/src/targets/opencode/install.ts +29 -1
  92. package/src/targets/opencode/plugin.ts +23 -12
  93. package/src/targets/opencode/uninstall.ts +30 -3
  94. package/src/tools/agent/algorithm-reflect.ts +1 -1
  95. package/src/tools/agent/analyze.ts +18 -18
  96. package/src/tools/agent/handoff-note.ts +116 -0
  97. package/src/tools/agent/project.ts +375 -75
  98. package/src/tools/agent/relationship-note.ts +51 -0
  99. package/src/tools/agent/synthesize.ts +6 -42
  100. package/src/tools/agent/thread.ts +15 -14
  101. package/src/tools/agent/wisdom-frame.ts +9 -3
  102. package/src/tools/import.ts +1 -1
  103. package/src/tools/relationship-reflect.ts +15 -13
  104. package/src/tools/self-model.ts +23 -19
  105. package/src/tools/session-summary.ts +3 -3
  106. package/src/tools/token-cost.ts +15 -16
  107. package/assets/skills/telos/tools/update-projects.ts +0 -106
  108. package/assets/templates/telos/PROJECTS.md +0 -7
@@ -1,11 +1,12 @@
1
1
  /**
2
2
  * PAL — opencode uninstaller (TypeScript)
3
- * Removes plugin and AGENTS.md.
3
+ * Removes plugin, AGENTS.md, and PAL entries from config.json.
4
4
  */
5
5
 
6
- import { unlinkSync } from "node:fs";
6
+ import { existsSync, readFileSync, statSync, unlinkSync, writeFileSync } from "node:fs";
7
7
  import { resolve } from "node:path";
8
8
  import { platform } from "../../hooks/lib/paths";
9
+ import { getSemiStaticSources } from "../../hooks/lib/semi-static";
9
10
  import { log, removeAgentsFromOpencode, removePalDocs, removeSkills } from "../lib";
10
11
 
11
12
  const OC_GLOBAL_DIR = platform.opencodeDir() || "";
@@ -41,7 +42,7 @@ if (removedAgents.length > 0)
41
42
  // --- Remove PAL system docs ---
42
43
  removePalDocs();
43
44
 
44
- // --- Remove AGENTS.md and CLAUDE.md symlink ---
45
+ // --- Remove AGENTS.md and CLAUDE.md ---
45
46
  const agentsMd = resolve(OC_GLOBAL_DIR, "AGENTS.md");
46
47
  const claudeMd = resolve(PAL_CLAUDE_DIR, "CLAUDE.md");
47
48
  try {
@@ -57,4 +58,30 @@ try {
57
58
  /* gone */
58
59
  }
59
60
 
61
+ // --- Remove PAL entries from config.json instructions[] ---
62
+ const configPath = resolve(OC_GLOBAL_DIR, "config.json");
63
+ if (existsSync(configPath) && statSync(configPath).size > 0) {
64
+ try {
65
+ const ocConfig = JSON.parse(readFileSync(configPath, "utf-8")) as Record<
66
+ string,
67
+ unknown
68
+ >;
69
+ if (Array.isArray(ocConfig.instructions)) {
70
+ const palFiles = new Set(getSemiStaticSources().map((s) => s.path));
71
+ const filtered = (ocConfig.instructions as string[]).filter(
72
+ (p) => !palFiles.has(p)
73
+ );
74
+ if (filtered.length === 0) {
75
+ delete ocConfig.instructions;
76
+ } else {
77
+ ocConfig.instructions = filtered;
78
+ }
79
+ writeFileSync(configPath, `${JSON.stringify(ocConfig, null, 2)}\n`, "utf-8");
80
+ log.success("Removed PAL entries from config.json instructions[]");
81
+ }
82
+ } catch {
83
+ log.warn("Could not clean config.json instructions[] — check manually");
84
+ }
85
+ }
86
+
60
87
  log.success("opencode uninstall complete");
@@ -40,7 +40,7 @@ function reflectionsPath(): string {
40
40
  return resolve(dir, "algorithm-reflections.jsonl");
41
41
  }
42
42
 
43
- export function appendReflection(reflection: AlgorithmReflection): {
43
+ function appendReflection(reflection: AlgorithmReflection): {
44
44
  success: boolean;
45
45
  message: string;
46
46
  path: string;
@@ -34,25 +34,26 @@ export function printReport(result: AnalysisResult): void {
34
34
 
35
35
  if (result.ratings) {
36
36
  const r = result.ratings;
37
- const avgColor = r.average >= 7 ? c.green : r.average <= 4 ? c.red : c.yellow;
37
+ const lowOrMid = r.average <= 4 ? c.red : c.yellow;
38
+ const avgColor = r.average >= 7 ? c.green : lowOrMid;
39
+ const ratingStr = `${r.average.toFixed(1)}/10`;
40
+ const lowStr = `Low (≤4): ${r.low.count}`;
41
+ const highStr = `High (≥7): ${r.high.count}`;
38
42
  console.log(
39
- `\n ${c.bold("Ratings:")} ${avgColor(`${r.average.toFixed(1)}/10`)} avg (${r.total} total)`
40
- );
41
- console.log(
42
- ` ${c.red(`Low (≤4): ${r.low.count}`)} | ${c.green(`High (≥7): ${r.high.count}`)}`
43
+ `\n ${c.bold("Ratings:")} ${avgColor(ratingStr)} avg (${r.total} total)`
43
44
  );
45
+ console.log(` ${c.red(lowStr)} | ${c.green(highStr)}`);
44
46
  }
45
47
 
46
48
  if (result.candidates.length > 0) {
47
- console.log(
48
- `\n ${c.bold(c.green(`Graduation Report — ${result.candidates.length} pattern(s) detected`))}\n`
49
- );
49
+ const graduationHeader = `Graduation Report — ${result.candidates.length} pattern(s) detected`;
50
+ console.log(`\n ${c.bold(c.green(graduationHeader))}\n`);
50
51
  console.log(` ${c.dim("─────────────────────────────────────────────────")}\n`);
51
52
 
52
53
  for (const candidate of result.candidates) {
53
- console.log(
54
- ` ${c.cyan(`[${candidate.domain}]`)} ${c.bold(`${candidate.entries.length}x`)} occurrences`
55
- );
54
+ const domain = `[${candidate.domain}]`;
55
+ const count = `${candidate.entries.length}x`;
56
+ console.log(` ${c.cyan(domain)} ${c.bold(count)} occurrences`);
56
57
  console.log("");
57
58
 
58
59
  for (const entry of candidate.entries) {
@@ -72,9 +73,8 @@ export function printReport(result: AnalysisResult): void {
72
73
  }
73
74
 
74
75
  console.log("");
75
- console.log(
76
- ` Target frame: ${c.magenta(`memory/wisdom/frames/${candidate.domain}.md`)}`
77
- );
76
+ const framePath = `memory/wisdom/frames/${candidate.domain}.md`;
77
+ console.log(` Target frame: ${c.magenta(framePath)}`);
78
78
  console.log(` ${c.dim("─────────────────────────────────────────────────")}\n`);
79
79
  }
80
80
  }
@@ -82,9 +82,9 @@ export function printReport(result: AnalysisResult): void {
82
82
  if (result.emerging.length > 0) {
83
83
  console.log(` ${c.bold(c.yellow("Emerging (2x — one more to graduate)"))}\n`);
84
84
  for (const group of result.emerging) {
85
- console.log(
86
- ` ${c.cyan(`[${group.domain}]`)} ${c.bold(`${group.entries.length}x`)}`
87
- );
85
+ const domain = `[${group.domain}]`;
86
+ const count = `${group.entries.length}x`;
87
+ console.log(` ${c.cyan(domain)} ${c.bold(count)}`);
88
88
  for (const entry of group.entries) {
89
89
  const sourceType = entry.source.startsWith("failure:") ? "failure" : "learning";
90
90
  const tag =
@@ -154,4 +154,4 @@ async function run() {
154
154
  printReport(result);
155
155
  }
156
156
 
157
- if (import.meta.main) run();
157
+ if (import.meta.main) await run();
@@ -0,0 +1,116 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * HandoffNote — Write or clear a handoff note for the current project.
4
+ *
5
+ * Called in the ALGORITHM LEARN phase when work is unfinished.
6
+ * Written by Claude in-session — no inference call needed.
7
+ *
8
+ * Usage:
9
+ * bun ~/.pal/tools/handoff-note.ts --title "what we were doing" --text "what remains + next steps"
10
+ * bun ~/.pal/tools/handoff-note.ts --done # mark completed, suppress next-session injection
11
+ */
12
+
13
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
14
+ import { resolve } from "node:path";
15
+ import { parseArgs } from "node:util";
16
+ import { ensureDir, paths } from "../../hooks/lib/paths";
17
+
18
+ interface HandoffEntry {
19
+ timestamp: string;
20
+ title: string;
21
+ status: "in-progress" | "completed";
22
+ handoff: string;
23
+ artifacts: string[];
24
+ }
25
+
26
+ function handoffPath(): string {
27
+ return resolve(ensureDir(paths.state()), "last-handoff.json");
28
+ }
29
+
30
+ function readHandoffs(): Record<string, HandoffEntry> {
31
+ const p = handoffPath();
32
+ if (!existsSync(p)) return {};
33
+ try {
34
+ return JSON.parse(readFileSync(p, "utf-8"));
35
+ } catch {
36
+ return {};
37
+ }
38
+ }
39
+
40
+ function writeHandoffs(handoffs: Record<string, HandoffEntry>): void {
41
+ const entries = Object.entries(handoffs);
42
+ const trimmed = entries.length > 20 ? Object.fromEntries(entries.slice(-20)) : handoffs;
43
+ writeFileSync(handoffPath(), JSON.stringify(trimmed, null, 2), "utf-8");
44
+ }
45
+
46
+ function writeHandoffNote(
47
+ cwd: string,
48
+ title: string,
49
+ text: string,
50
+ done: boolean
51
+ ): { success: boolean; message: string } {
52
+ const handoffs = readHandoffs();
53
+ handoffs[cwd] = {
54
+ timestamp: new Date().toISOString(),
55
+ title,
56
+ status: done ? "completed" : "in-progress",
57
+ handoff: text,
58
+ artifacts: [],
59
+ };
60
+ writeHandoffs(handoffs);
61
+ return {
62
+ success: true,
63
+ message: done ? "Handoff cleared (marked completed)" : "Handoff note written",
64
+ };
65
+ }
66
+
67
+ function run() {
68
+ const { values } = parseArgs({
69
+ args: Bun.argv.slice(2),
70
+ options: {
71
+ title: { type: "string" },
72
+ text: { type: "string" },
73
+ done: { type: "boolean" },
74
+ help: { type: "boolean", short: "h" },
75
+ },
76
+ });
77
+
78
+ if (values.help) {
79
+ console.log(`
80
+ HandoffNote — Write a handoff note for the current project
81
+
82
+ Usage:
83
+ bun ~/.pal/tools/handoff-note.ts --title "what we were doing" --text "what remains"
84
+ bun ~/.pal/tools/handoff-note.ts --done # mark session completed
85
+
86
+ Arguments:
87
+ --title Brief title of what was being worked on (5-10 words)
88
+ --text What remains unfinished — decisions made, next steps, blockers
89
+ --done Mark as completed; suppresses "pick up where you left off" injection
90
+
91
+ Output: writes to memory/state/last-handoff.json keyed by cwd
92
+ `);
93
+ process.exit(0);
94
+ }
95
+
96
+ if (values.done) {
97
+ const result = writeHandoffNote(
98
+ process.cwd(),
99
+ values.title || "session",
100
+ values.text || "",
101
+ true
102
+ );
103
+ console.log(JSON.stringify(result, null, 2));
104
+ process.exit(0);
105
+ }
106
+
107
+ if (!values.title || !values.text) {
108
+ console.error("Required: --title and --text (or --done to close)");
109
+ process.exit(1);
110
+ }
111
+
112
+ const result = writeHandoffNote(process.cwd(), values.title, values.text, false);
113
+ console.log(JSON.stringify(result, null, 2));
114
+ }
115
+
116
+ if (import.meta.main) run();