portable-agent-layer 0.14.0 → 0.15.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.
|
@@ -29,12 +29,24 @@ Read the file directly from `~/.agents/PAL/telos/` when the user asks about any
|
|
|
29
29
|
|
|
30
30
|
## Updating
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
### General TELOS files (append)
|
|
33
|
+
|
|
34
|
+
For all files except PROJECTS.md — appends content, creates backup, logs the change:
|
|
33
35
|
|
|
34
36
|
```bash
|
|
35
37
|
bun ~/.agents/skills/telos/tools/update-telos.ts <FILE> "<content>" "<description>"
|
|
36
38
|
```
|
|
37
39
|
|
|
40
|
+
### Projects (upsert by ID)
|
|
41
|
+
|
|
42
|
+
For PROJECTS.md — upserts a row by the ID column. Replaces if the ID exists, appends if new:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
bun ~/.agents/skills/telos/tools/update-projects.ts <id> "<row>" "<description>"
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The ID is the first column of the table. Use short, lowercase, kebab-case slugs (e.g., `my-project`, `side-gig`).
|
|
49
|
+
|
|
38
50
|
## Routing
|
|
39
51
|
|
|
40
52
|
| Intent | Action |
|
|
@@ -66,15 +78,24 @@ User: "add my new side project"
|
|
|
66
78
|
→ Ask: "What's the project name, status, and priority?"
|
|
67
79
|
→ User provides details
|
|
68
80
|
→ Show the row you'll add, confirm
|
|
69
|
-
→ Run: bun ~/.agents/skills/telos/tools/update-
|
|
81
|
+
→ Run: bun ~/.agents/skills/telos/tools/update-projects.ts side-project "| side-project | Side Project | In progress | Medium | Description |" "Added Side Project"
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**Example 3: Updating a project**
|
|
85
|
+
```
|
|
86
|
+
User: "mark X as complete"
|
|
87
|
+
→ Read PROJECTS.md, find the entry and its ID
|
|
88
|
+
→ Show updated row, confirm
|
|
89
|
+
→ Run: bun ~/.agents/skills/telos/tools/update-projects.ts some-id "| some-id | Project Name | Complete | High | ... |" "Marked project as complete"
|
|
90
|
+
→ The existing row is replaced, not duplicated
|
|
70
91
|
```
|
|
71
92
|
|
|
72
|
-
**Example
|
|
93
|
+
**Example 4: Updating goals**
|
|
73
94
|
```
|
|
74
95
|
User: "I finished the migration, update my goals"
|
|
75
96
|
→ Read GOALS.md to see current state
|
|
76
97
|
→ Discuss what changed — what's done, what's next
|
|
77
|
-
→ Run tool to
|
|
98
|
+
→ Run tool with --id to update existing goal entry
|
|
78
99
|
→ Remind: CLAUDE.md regenerates next session
|
|
79
100
|
```
|
|
80
101
|
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* UpdateProjects — Upsert a project row in PROJECTS.md by ID.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* bun update-projects.ts <id> "<row>" "<description>"
|
|
7
|
+
*
|
|
8
|
+
* - <id> is the value in the first column (e.g., "my-proj", "side-gig")
|
|
9
|
+
* - <row> is the full table row including the ID column (e.g., "| my-proj | My Project | Done | High | ... |")
|
|
10
|
+
* - If a row with that ID exists, it is replaced
|
|
11
|
+
* - If no row with that ID exists, it is appended
|
|
12
|
+
* - Creates a timestamped backup before modifying
|
|
13
|
+
* - Logs the change to updates.md
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import {
|
|
17
|
+
copyFileSync,
|
|
18
|
+
existsSync,
|
|
19
|
+
mkdirSync,
|
|
20
|
+
readFileSync,
|
|
21
|
+
writeFileSync,
|
|
22
|
+
} from "node:fs";
|
|
23
|
+
import { resolve } from "node:path";
|
|
24
|
+
import { palHome } from "../../../../src/hooks/lib/paths";
|
|
25
|
+
|
|
26
|
+
const TELOS_DIR = resolve(palHome(), "telos");
|
|
27
|
+
const BACKUPS_DIR = resolve(TELOS_DIR, "backups");
|
|
28
|
+
const UPDATES_LOG = resolve(TELOS_DIR, "updates.md");
|
|
29
|
+
const PROJECTS_FILE = resolve(TELOS_DIR, "PROJECTS.md");
|
|
30
|
+
|
|
31
|
+
function timestamp(): string {
|
|
32
|
+
const now = new Date();
|
|
33
|
+
const pad = (n: number) => n.toString().padStart(2, "0");
|
|
34
|
+
return `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}-${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function isoDate(): string {
|
|
38
|
+
return new Date().toISOString().replace("T", " ").slice(0, 19);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const args = process.argv.slice(2);
|
|
42
|
+
const id = args[0];
|
|
43
|
+
const row = args[1];
|
|
44
|
+
const description = args[2];
|
|
45
|
+
|
|
46
|
+
if (!id || !row || !description) {
|
|
47
|
+
console.error('Usage: bun update-projects.ts <id> "<row>" "<description>"');
|
|
48
|
+
console.error(
|
|
49
|
+
'\nExample: bun update-projects.ts my-proj "| my-proj | My Project | In progress | High | Notes |" "Added My Project"'
|
|
50
|
+
);
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Backup
|
|
55
|
+
mkdirSync(BACKUPS_DIR, { recursive: true });
|
|
56
|
+
if (existsSync(PROJECTS_FILE)) {
|
|
57
|
+
const backupName = `PROJECTS-${timestamp()}.md`;
|
|
58
|
+
copyFileSync(PROJECTS_FILE, resolve(BACKUPS_DIR, backupName));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const existing = existsSync(PROJECTS_FILE) ? readFileSync(PROJECTS_FILE, "utf-8") : "";
|
|
62
|
+
|
|
63
|
+
const escapedId = id.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
64
|
+
const idPattern = new RegExp(`^\\|\\s*${escapedId}\\s*\\|.*$`, "m");
|
|
65
|
+
let mode: "replaced" | "appended";
|
|
66
|
+
|
|
67
|
+
if (idPattern.test(existing)) {
|
|
68
|
+
const updated = existing.replace(idPattern, row.trim());
|
|
69
|
+
writeFileSync(PROJECTS_FILE, updated, "utf-8");
|
|
70
|
+
mode = "replaced";
|
|
71
|
+
} else {
|
|
72
|
+
const separator = existing.trim() ? "\n" : "";
|
|
73
|
+
writeFileSync(
|
|
74
|
+
PROJECTS_FILE,
|
|
75
|
+
`${existing.trimEnd()}${separator}${row.trim()}\n`,
|
|
76
|
+
"utf-8"
|
|
77
|
+
);
|
|
78
|
+
mode = "appended";
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Log change
|
|
82
|
+
const logEntry = `- **${isoDate()}** — \`PROJECTS.md\` [${id}]: ${description}`;
|
|
83
|
+
const existingLog = existsSync(UPDATES_LOG)
|
|
84
|
+
? readFileSync(UPDATES_LOG, "utf-8")
|
|
85
|
+
: "# TELOS Updates\n";
|
|
86
|
+
writeFileSync(UPDATES_LOG, `${existingLog.trimEnd()}\n${logEntry}\n`, "utf-8");
|
|
87
|
+
|
|
88
|
+
console.log(
|
|
89
|
+
JSON.stringify(
|
|
90
|
+
{
|
|
91
|
+
file: "PROJECTS.md",
|
|
92
|
+
id,
|
|
93
|
+
mode,
|
|
94
|
+
backed_up: true,
|
|
95
|
+
logged: true,
|
|
96
|
+
description,
|
|
97
|
+
},
|
|
98
|
+
null,
|
|
99
|
+
2
|
|
100
|
+
)
|
|
101
|
+
);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
/**
|
|
3
|
-
* UpdateTelos — Validate, backup,
|
|
3
|
+
* UpdateTelos — Validate, backup, append, and log changes to TELOS files.
|
|
4
4
|
*
|
|
5
5
|
* Usage:
|
|
6
6
|
* bun update-telos.ts <file> "<content>" "<description>"
|
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
* - Creates a timestamped backup before modifying
|
|
10
10
|
* - Appends content (preserves existing)
|
|
11
11
|
* - Logs the change to updates.md
|
|
12
|
+
*
|
|
13
|
+
* For PROJECTS.md upserts (add/update by ID), use update-projects.ts instead.
|
|
12
14
|
*/
|
|
13
15
|
|
|
14
16
|
import {
|
|
@@ -34,7 +36,6 @@ const VALID_FILES = [
|
|
|
34
36
|
"MISSION.md",
|
|
35
37
|
"MODELS.md",
|
|
36
38
|
"NARRATIVES.md",
|
|
37
|
-
"PROJECTS.md",
|
|
38
39
|
"STRATEGIES.md",
|
|
39
40
|
];
|
|
40
41
|
|
package/package.json
CHANGED
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
findSimilarOpinion,
|
|
23
23
|
readOpinions,
|
|
24
24
|
saveOpinion,
|
|
25
|
+
setLastReflectDate,
|
|
25
26
|
} from "../hooks/lib/opinions";
|
|
26
27
|
import { palHome } from "../hooks/lib/paths";
|
|
27
28
|
import { similarity } from "../hooks/lib/text-similarity";
|
|
@@ -457,6 +458,7 @@ if (dryRun) {
|
|
|
457
458
|
} else {
|
|
458
459
|
const report = formatReport(period, notes, ratings, opinionChanges);
|
|
459
460
|
const filepath = writeReport(report, period);
|
|
461
|
+
setLastReflectDate(new Date().toISOString().slice(0, 10));
|
|
460
462
|
console.log(`\nCreated reflection report: ${filepath}`);
|
|
461
463
|
|
|
462
464
|
const opinions = readOpinions();
|