portable-agent-layer 0.14.1 → 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
- Use the update tool for all changes. It validates the file, creates a backup, appends content, and logs the change:
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-telos.ts PROJECTS.md "| Side Project | In progress | Medium | Description |" "Added Side Project"
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 3: Updating goals**
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 append updated goals
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, update, and log changes to TELOS files.
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "portable-agent-layer",
3
- "version": "0.14.1",
3
+ "version": "0.15.0",
4
4
  "description": "PAL — Portable Agent Layer: persistent personal context for AI coding assistants",
5
5
  "type": "module",
6
6
  "bin": {