portable-agent-layer 0.35.0 → 0.36.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/README.md +1 -1
- package/assets/skills/projects/SKILL.md +0 -1
- package/assets/skills/telos/SKILL.md +7 -52
- package/assets/templates/PAL/ALGORITHM.md +28 -3
- package/assets/templates/PAL/PROJECT_LIFECYCLE.md +48 -0
- package/assets/templates/PAL/README.md +1 -1
- package/assets/templates/PAL/STEERING_RULES.md +4 -0
- package/assets/templates/PAL/SYSTEM_ARCHITECTURE.md +32 -17
- package/assets/templates/PAL/WORK_TRACKING.md +1 -1
- package/assets/templates/pal-settings.json +1 -3
- package/assets/templates/settings.claude.json +2 -1
- package/package.json +1 -1
- package/src/cli/setup-telos.ts +12 -79
- package/src/hooks/LoadContext.ts +22 -10
- package/src/hooks/handlers/context-digests.ts +74 -0
- package/src/hooks/handlers/session-intelligence.ts +9 -86
- package/src/hooks/lib/claude-md.ts +69 -14
- package/src/hooks/lib/context.ts +57 -139
- package/src/hooks/lib/relationship.ts +3 -3
- package/src/hooks/lib/security.ts +2 -0
- package/src/hooks/lib/semi-static.ts +186 -0
- package/src/hooks/lib/setup.ts +0 -5
- package/src/hooks/lib/stop.ts +3 -0
- package/src/targets/claude/uninstall.ts +1 -1
- package/src/targets/copilot/install.ts +39 -8
- package/src/targets/copilot/uninstall.ts +58 -17
- package/src/targets/cursor/install.ts +8 -0
- package/src/targets/cursor/uninstall.ts +18 -1
- package/src/targets/lib.ts +26 -0
- package/src/targets/opencode/install.ts +29 -1
- package/src/targets/opencode/plugin.ts +1 -1
- package/src/targets/opencode/uninstall.ts +30 -3
- package/src/tools/agent/handoff-note.ts +116 -0
- package/src/tools/agent/relationship-note.ts +51 -0
- package/src/tools/relationship-reflect.ts +2 -2
- package/src/tools/self-model.ts +4 -4
- package/assets/templates/telos/PROJECTS.md +0 -7
|
@@ -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
|
+
export 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();
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* RelationshipNote — Write a B entry to today's relationship log.
|
|
4
|
+
*
|
|
5
|
+
* Called in the ALGORITHM LEARN phase. Claude writes the B entry directly
|
|
6
|
+
* from full session context — no inference call needed.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* bun ~/.pal/tools/relationship-note.ts --b "what I did this session"
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { parseArgs } from "node:util";
|
|
13
|
+
import { appendNotes } from "../../hooks/lib/relationship";
|
|
14
|
+
|
|
15
|
+
function run() {
|
|
16
|
+
const { values } = parseArgs({
|
|
17
|
+
args: Bun.argv.slice(2),
|
|
18
|
+
options: {
|
|
19
|
+
b: { type: "string" },
|
|
20
|
+
help: { type: "boolean", short: "h" },
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
if (values.help) {
|
|
25
|
+
console.log(`
|
|
26
|
+
RelationshipNote — Append a B entry to today's relationship log
|
|
27
|
+
|
|
28
|
+
Usage:
|
|
29
|
+
bun ~/.pal/tools/relationship-note.ts --b "description"
|
|
30
|
+
|
|
31
|
+
Arguments:
|
|
32
|
+
--b What happened this session (1-2 sentences, first-person, specific)
|
|
33
|
+
|
|
34
|
+
Output: appends to memory/relationship/YYYY-MM/YYYY-MM-DD.md
|
|
35
|
+
`);
|
|
36
|
+
process.exit(0);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (!values.b) {
|
|
40
|
+
console.error("Required: --b");
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
appendNotes([{ type: "Session", text: values.b }]);
|
|
45
|
+
|
|
46
|
+
console.log(
|
|
47
|
+
JSON.stringify({ success: true, message: "Relationship note written" }, null, 2)
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (import.meta.main) run();
|
|
@@ -37,7 +37,7 @@ interface Rating {
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
interface ParsedNote {
|
|
40
|
-
type: "W" | "O" | "
|
|
40
|
+
type: "W" | "O" | "Session";
|
|
41
41
|
text: string;
|
|
42
42
|
confidence?: number;
|
|
43
43
|
date: string;
|
|
@@ -94,7 +94,7 @@ export function loadNotes(daysBack: number): ParsedNote[] {
|
|
|
94
94
|
const obMatch = line.match(/^- ([OB])\(c=([\d.]+)\):\s*(.+)$/);
|
|
95
95
|
if (obMatch) {
|
|
96
96
|
notes.push({
|
|
97
|
-
type: obMatch[1] as "O" | "
|
|
97
|
+
type: obMatch[1] as "O" | "Session",
|
|
98
98
|
confidence: Number.parseFloat(obMatch[2]),
|
|
99
99
|
text: obMatch[3],
|
|
100
100
|
date: dateStr,
|
package/src/tools/self-model.ts
CHANGED
|
@@ -71,7 +71,7 @@ interface AlgorithmReflection {
|
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
interface RelationshipNote {
|
|
74
|
-
type: "O" | "W" | "
|
|
74
|
+
type: "O" | "W" | "Session";
|
|
75
75
|
content: string;
|
|
76
76
|
confidence?: number;
|
|
77
77
|
date: string;
|
|
@@ -292,9 +292,9 @@ function readRelationshipNotes(since: Date): RelationshipNote[] {
|
|
|
292
292
|
continue;
|
|
293
293
|
}
|
|
294
294
|
|
|
295
|
-
const behaviorMatch = noteContent.match(/^
|
|
295
|
+
const behaviorMatch = noteContent.match(/^Session:\s*(.+)$/);
|
|
296
296
|
if (behaviorMatch) {
|
|
297
|
-
notes.push({ type: "
|
|
297
|
+
notes.push({ type: "Session", content: behaviorMatch[1], date: dateStr });
|
|
298
298
|
}
|
|
299
299
|
}
|
|
300
300
|
}
|
|
@@ -376,7 +376,7 @@ function gatherData(days: number): SelfModelData {
|
|
|
376
376
|
wisdomFrames,
|
|
377
377
|
graduated,
|
|
378
378
|
reflections,
|
|
379
|
-
behaviorNotes: relNotes.filter((n) => n.type === "
|
|
379
|
+
behaviorNotes: relNotes.filter((n) => n.type === "Session").map((n) => n.content),
|
|
380
380
|
wisdomNotes: relNotes.filter((n) => n.type === "W").map((n) => n.content),
|
|
381
381
|
selfObservations: reflections.map((r) => r.q1).filter(Boolean),
|
|
382
382
|
algorithmObservations: reflections.map((r) => r.q2).filter(Boolean),
|