portable-agent-layer 0.34.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/presentation/SKILL.md +2 -0
- package/assets/skills/presentation/demo/slides/004-content.md +27 -1
- package/assets/skills/presentation/theme-base/base.css +206 -0
- package/assets/skills/presentation/theme-base/skeleton.html +49 -0
- package/assets/skills/presentation/tools/lib/lint-rules.ts +25 -0
- package/assets/skills/projects/SKILL.md +0 -1
- package/assets/skills/telos/SKILL.md +7 -52
- package/assets/templates/AGENTS.md.template +2 -1
- 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
package/README.md
CHANGED
|
@@ -102,7 +102,7 @@ pal cli install # all available (default)
|
|
|
102
102
|
| Claude Code | Full | Yes | Yes | Yes | Yes |
|
|
103
103
|
| opencode | Full | Yes | Yes (plugin) | Yes | Yes |
|
|
104
104
|
| Cursor | Full | Yes | Yes | Yes (injected via hook) | Yes |
|
|
105
|
-
| GitHub Copilot | Full | Yes | Yes | Yes (via copilot
|
|
105
|
+
| GitHub Copilot | Full | Yes | Yes | Yes (via `~/.copilot/instructions/*.instructions.md`) | Yes |
|
|
106
106
|
| Codex | Partial | Yes | No | Yes | No |
|
|
107
107
|
|
|
108
108
|
---
|
|
@@ -103,6 +103,8 @@ Exit codes: `0` = clean, `1` = errors found (or warnings under `--strict`), `2`
|
|
|
103
103
|
|
|
104
104
|
Open `<out>/<deck-name>/<deck-name>.html` in your browser. Iterate by editing a slide, re-running the build, and refreshing the tab. Reveal shortcuts: `F` = fullscreen, `S` = speaker notes window, `?` = keyboard shortcuts, `Esc` = overview.
|
|
105
105
|
|
|
106
|
+
**Print / PDF view with trainer notes.** Open the built HTML in your browser and press Cmd/Ctrl-P (no special URL param needed). The print stream interleaves trainer notes between slides — `[Slide 1][Notes 1][Slide 2][Notes 2]…` — so flipping pages reads in delivery order. Long notes flow across multiple pages. Slides without a `Note:` block produce no extra page. Each notes page carries a header identifying the source slide. Limitation: a single fenced code block inside notes cannot break across pages — the doctor warns at 30 lines (`notes-code-too-long`); split the block or shorten the example.
|
|
107
|
+
|
|
106
108
|
## Deck folder layout
|
|
107
109
|
|
|
108
110
|
```
|
|
@@ -9,4 +9,30 @@ The default. Title at top, body below.
|
|
|
9
9
|
- And this
|
|
10
10
|
- **Bold**, *italic*, `inline code`, [links](https://example.com)
|
|
11
11
|
|
|
12
|
-
Note:
|
|
12
|
+
Note:
|
|
13
|
+
- [Reveal.js print docs](https://revealjs.com/pdf-export/)
|
|
14
|
+
- Why this slide demonstrates print-with-notes
|
|
15
|
+
- Long enough to cross a page break in the trainer print-out
|
|
16
|
+
- Mixes link, bullet hierarchy, blockquote, inline code
|
|
17
|
+
- Lets you verify the multi-page flow without authoring a fixture deck
|
|
18
|
+
- Default layout — when to leave it off
|
|
19
|
+
- You want title + body, no special shape
|
|
20
|
+
- You want the layout-agnostic spacing rules to kick in
|
|
21
|
+
- You want the doctor to skip layout-shape checks
|
|
22
|
+
- Bullet hygiene reminder (per SKILL.md)
|
|
23
|
+
- 2–15 words at top level, 2–10 at sub
|
|
24
|
+
- No prose paragraphs — the `prose-paragraph-in-body` rule will warn
|
|
25
|
+
- Em-dash continuation in bullets is also flagged
|
|
26
|
+
- Quote example
|
|
27
|
+
> Slides are a delivery surface, not a document. Prose belongs in notes.
|
|
28
|
+
- Anticipated questions
|
|
29
|
+
- "Why a 30-line cap on notes code blocks?" — single `<pre>` blocks don't break across printed pages; longer blocks clip
|
|
30
|
+
- "Can I disable the trainer-notes printout?" — yes, remove the notes injection block from the `.then()` in skeleton.html in your local override
|
|
31
|
+
- "Does the speaker view (S key) still work?" — yes, the injection only affects print, not the speaker view path
|
|
32
|
+
- Forward references
|
|
33
|
+
- more on layout-specific rules in the `code` and `table` slides
|
|
34
|
+
- more on print-view polish in `base.css` under "Trainer notes in print"
|
|
35
|
+
- Closing beats
|
|
36
|
+
- The print-with-notes feature exists so a trainer can hand a delegate a printed deck and a printed prep packet at once
|
|
37
|
+
- Ordering is `[Slide 1][Notes 1][Slide 2][Notes 2]…` so flipping pages reads in delivery order
|
|
38
|
+
- Slides without a `Note:` block produce zero extra pages — title cards stay clean
|
|
@@ -436,3 +436,209 @@ html.print-pdf .reveal .slides .pdf-page {
|
|
|
436
436
|
margin: 16px auto !important;
|
|
437
437
|
}
|
|
438
438
|
}
|
|
439
|
+
|
|
440
|
+
/* ── Trainer notes in print (Cmd+P on the regular URL)
|
|
441
|
+
* skeleton.html injects a `.print-notes-page` div after each slide section that
|
|
442
|
+
* has speaker notes. On screen they are invisible; Cmd+P produces the ordering
|
|
443
|
+
* [Slide N][Notes N][Slide N+1][Notes N+1]…. Long notes flow across multiple
|
|
444
|
+
* pages. Slides with no Note: block produce no extra page.
|
|
445
|
+
*
|
|
446
|
+
* Key mechanics:
|
|
447
|
+
* • `page-break-after: always` on sections forces each slide to end at a page
|
|
448
|
+
* boundary even if its content is shorter than the page height.
|
|
449
|
+
* • `page-break-before/after: always` on .print-notes-page ensures the notes
|
|
450
|
+
* block starts on a fresh page and the next slide starts on a fresh page.
|
|
451
|
+
* • `break-inside: auto` lets long notes flow across pages naturally. */
|
|
452
|
+
@media print {
|
|
453
|
+
html:not(.print-pdf) .reveal .slides > section {
|
|
454
|
+
page-break-after: always !important;
|
|
455
|
+
break-after: always !important;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
html:not(.print-pdf) .reveal .slides > .print-notes-page {
|
|
459
|
+
display: block !important;
|
|
460
|
+
page-break-before: always !important;
|
|
461
|
+
break-before: always !important;
|
|
462
|
+
page-break-after: always !important;
|
|
463
|
+
break-after: always !important;
|
|
464
|
+
page-break-inside: auto;
|
|
465
|
+
break-inside: auto;
|
|
466
|
+
overflow: visible !important;
|
|
467
|
+
position: static !important;
|
|
468
|
+
min-height: 0 !important;
|
|
469
|
+
padding: 36px 56px 56px 56px;
|
|
470
|
+
box-sizing: border-box;
|
|
471
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
|
472
|
+
"Helvetica Neue", Arial, sans-serif;
|
|
473
|
+
font-size: 13pt;
|
|
474
|
+
line-height: 1.5;
|
|
475
|
+
color: #111;
|
|
476
|
+
background: #fff;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
html:not(.print-pdf) .reveal .slides > .print-notes-page ul,
|
|
480
|
+
html:not(.print-pdf) .reveal .slides > .print-notes-page ol {
|
|
481
|
+
margin: 0.4em 0 0.8em 0;
|
|
482
|
+
padding-left: 1.4em;
|
|
483
|
+
}
|
|
484
|
+
html:not(.print-pdf) .reveal .slides > .print-notes-page li {
|
|
485
|
+
margin: 0.15em 0;
|
|
486
|
+
}
|
|
487
|
+
html:not(.print-pdf) .reveal .slides > .print-notes-page a {
|
|
488
|
+
color: var(--brand-primary, #0040c2);
|
|
489
|
+
text-decoration: underline;
|
|
490
|
+
}
|
|
491
|
+
html:not(.print-pdf) .reveal .slides > .print-notes-page code {
|
|
492
|
+
font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
|
|
493
|
+
font-size: 0.92em;
|
|
494
|
+
background: #f4f4f4;
|
|
495
|
+
padding: 1px 4px;
|
|
496
|
+
border-radius: 3px;
|
|
497
|
+
}
|
|
498
|
+
html:not(.print-pdf) .reveal .slides > .print-notes-page pre {
|
|
499
|
+
font-size: 0.92em;
|
|
500
|
+
line-height: 1.4;
|
|
501
|
+
background: #f4f4f4;
|
|
502
|
+
padding: 8px 12px;
|
|
503
|
+
border-radius: 4px;
|
|
504
|
+
white-space: pre-wrap;
|
|
505
|
+
overflow: visible;
|
|
506
|
+
}
|
|
507
|
+
html:not(.print-pdf) .reveal .slides > .print-notes-page blockquote {
|
|
508
|
+
margin: 0.6em 0 0.6em 1em;
|
|
509
|
+
padding-left: 0.8em;
|
|
510
|
+
border-left: 2px solid #a0a0a0;
|
|
511
|
+
color: #444;
|
|
512
|
+
font-style: italic;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
/* Slide-context header: "Notes — slide N <slide title>" */
|
|
516
|
+
html:not(.print-pdf) .reveal .slides > .print-notes-page .print-notes-header {
|
|
517
|
+
display: flex;
|
|
518
|
+
align-items: baseline;
|
|
519
|
+
gap: 0.8em;
|
|
520
|
+
margin: 0 0 24px 0;
|
|
521
|
+
padding: 0 0 10px 0;
|
|
522
|
+
border-bottom: 1.5pt solid var(--brand-primary, #0040c2);
|
|
523
|
+
-webkit-print-color-adjust: exact;
|
|
524
|
+
print-color-adjust: exact;
|
|
525
|
+
}
|
|
526
|
+
html:not(.print-pdf) .reveal .slides > .print-notes-page .print-notes-label {
|
|
527
|
+
font-size: 11pt;
|
|
528
|
+
font-weight: 600;
|
|
529
|
+
text-transform: uppercase;
|
|
530
|
+
letter-spacing: 0.05em;
|
|
531
|
+
color: var(--brand-primary, #0040c2);
|
|
532
|
+
white-space: nowrap;
|
|
533
|
+
}
|
|
534
|
+
html:not(.print-pdf) .reveal .slides > .print-notes-page .print-notes-title {
|
|
535
|
+
font-size: 13pt;
|
|
536
|
+
font-weight: 500;
|
|
537
|
+
color: #222;
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
/* ── Per-slide print chrome (logo + slide number)
|
|
542
|
+
* skeleton.html injects `.print-logo` and `.print-slide-number` into every
|
|
543
|
+
* section. On screen: invisible. In Cmd+P print: positioned at the same
|
|
544
|
+
* bottom corners as the screen-mode chrome, once per slide page.
|
|
545
|
+
*
|
|
546
|
+
* The screen-mode equivalents (.slides::after logo and .slides > .slide-number)
|
|
547
|
+
* are suppressed in print because they are positioned relative to .slides — a
|
|
548
|
+
* container that spans all pages in Cmd+P mode, putting them at the very end
|
|
549
|
+
* of the document rather than on each individual slide. */
|
|
550
|
+
@media print {
|
|
551
|
+
/* Suppress the screen-mode global chrome */
|
|
552
|
+
html:not(.print-pdf) .reveal .slides::after,
|
|
553
|
+
html:not(.print-pdf) .reveal .slides > .slide-number {
|
|
554
|
+
display: none !important;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
/* Sections must be position:relative so absolute children anchor to the
|
|
558
|
+
* slide page, not to the full-document .slides container. */
|
|
559
|
+
html:not(.print-pdf) .reveal .slides > section {
|
|
560
|
+
position: relative !important;
|
|
561
|
+
/* Ensure background images (logos) print on all browsers. */
|
|
562
|
+
-webkit-print-color-adjust: exact !important;
|
|
563
|
+
print-color-adjust: exact !important;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
html:not(.print-pdf) .reveal .slides > section .print-logo {
|
|
567
|
+
display: block !important;
|
|
568
|
+
position: absolute;
|
|
569
|
+
bottom: 1.5rem;
|
|
570
|
+
right: 1.5rem;
|
|
571
|
+
width: 90px;
|
|
572
|
+
height: 28px;
|
|
573
|
+
background: var(--brand-logo) no-repeat right bottom / contain;
|
|
574
|
+
opacity: 0.55;
|
|
575
|
+
pointer-events: none;
|
|
576
|
+
-webkit-print-color-adjust: exact;
|
|
577
|
+
print-color-adjust: exact;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
html:not(.print-pdf) .reveal .slides > section .print-slide-number {
|
|
581
|
+
display: block !important;
|
|
582
|
+
position: absolute;
|
|
583
|
+
bottom: 1.5rem;
|
|
584
|
+
left: 1.5rem;
|
|
585
|
+
font-family: var(--font-body, sans-serif);
|
|
586
|
+
font-size: 9pt;
|
|
587
|
+
font-weight: 400;
|
|
588
|
+
line-height: 28px;
|
|
589
|
+
color: #71717A;
|
|
590
|
+
letter-spacing: 0.05em;
|
|
591
|
+
pointer-events: none;
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
/* ── Layout-specific print overrides
|
|
596
|
+
* Reveal's vendored print CSS forces several properties with !important on
|
|
597
|
+
* heading and paragraph elements, which clobbers layout-specific design intent:
|
|
598
|
+
* • h1-h6: font-size (28–20pt), color (#000), text-align (left),
|
|
599
|
+
* letter-spacing (normal), line-height (normal)
|
|
600
|
+
* • p, li, td: font-size (20pt), color (#000)
|
|
601
|
+
*
|
|
602
|
+
* We beat these by pairing higher-specificity selectors with !important.
|
|
603
|
+
* Reveal's rules are scoped to `html:not(.print-pdf) .reveal h1` — specificity
|
|
604
|
+
* (0,2,1). Our layout-scoped rules use `html:not(.print-pdf) .reveal
|
|
605
|
+
* section[data-layout="…"] h1` — specificity (0,3,2), which wins. */
|
|
606
|
+
@media print {
|
|
607
|
+
/* big-stat — restore the dominant number that Reveal shrinks to 28pt */
|
|
608
|
+
html:not(.print-pdf) .reveal section[data-layout="big-stat"] h1 {
|
|
609
|
+
font-size: 96pt !important;
|
|
610
|
+
color: var(--brand-primary, #0E1335) !important;
|
|
611
|
+
text-align: center !important;
|
|
612
|
+
letter-spacing: -0.025em !important;
|
|
613
|
+
line-height: 0.9 !important;
|
|
614
|
+
font-weight: 800 !important;
|
|
615
|
+
-webkit-print-color-adjust: exact !important;
|
|
616
|
+
print-color-adjust: exact !important;
|
|
617
|
+
}
|
|
618
|
+
html:not(.print-pdf) .reveal section[data-layout="big-stat"] h2,
|
|
619
|
+
html:not(.print-pdf) .reveal section[data-layout="big-stat"] p {
|
|
620
|
+
color: #71717A !important;
|
|
621
|
+
text-align: center !important;
|
|
622
|
+
font-weight: 400 !important;
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
/* quote / pull-quote — Reveal forces p { font-size: 20pt !important }, but
|
|
626
|
+
* blockquote text lives in p elements. `inherit` re-derives the size from the
|
|
627
|
+
* blockquote element (var(--text-xl) / var(--text-2xl)), restoring design intent. */
|
|
628
|
+
html:not(.print-pdf) .reveal section[data-layout="quote"] blockquote p,
|
|
629
|
+
html:not(.print-pdf) .reveal section[data-layout="pull-quote"] blockquote p {
|
|
630
|
+
font-size: inherit !important;
|
|
631
|
+
color: inherit !important;
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
/* Screen: injected notes pages are invisible. The `@media print` block above
|
|
636
|
+
* restores display:block. Using !important because Reveal may globally set
|
|
637
|
+
* visibility rules on .slides children. */
|
|
638
|
+
@media screen {
|
|
639
|
+
.reveal .slides > .print-notes-page,
|
|
640
|
+
.reveal .slides > section .print-logo,
|
|
641
|
+
.reveal .slides > section .print-slide-number {
|
|
642
|
+
display: none !important;
|
|
643
|
+
}
|
|
644
|
+
}
|
|
@@ -47,6 +47,55 @@ Reveal.initialize({
|
|
|
47
47
|
const sn = document.querySelector('.reveal > .slide-number');
|
|
48
48
|
const slides = document.querySelector('.reveal .slides');
|
|
49
49
|
if (sn && slides) slides.appendChild(sn);
|
|
50
|
+
|
|
51
|
+
// Inject print-only chrome (logo + slide number) into every section, and a
|
|
52
|
+
// `.print-notes-page` after each section that has notes. All injected elements
|
|
53
|
+
// are display:none on screen; Cmd+P produces [Slide N][Notes N]… ordering.
|
|
54
|
+
const sections = document.querySelectorAll('.reveal .slides > section');
|
|
55
|
+
const totalSlides = sections.length;
|
|
56
|
+
let slideNum = 0;
|
|
57
|
+
for (const section of sections) {
|
|
58
|
+
slideNum++;
|
|
59
|
+
|
|
60
|
+
const logoEl = document.createElement('div');
|
|
61
|
+
logoEl.className = 'print-logo';
|
|
62
|
+
section.appendChild(logoEl);
|
|
63
|
+
|
|
64
|
+
const numEl = document.createElement('div');
|
|
65
|
+
numEl.className = 'print-slide-number';
|
|
66
|
+
numEl.textContent = `${slideNum} / ${totalSlides}`;
|
|
67
|
+
section.appendChild(numEl);
|
|
68
|
+
|
|
69
|
+
const notesEl = section.querySelector('aside.notes');
|
|
70
|
+
if (!notesEl?.innerHTML.trim()) continue;
|
|
71
|
+
|
|
72
|
+
const heading = section.querySelector('h1, h2, h3');
|
|
73
|
+
const title = heading ? heading.textContent.trim() : '';
|
|
74
|
+
|
|
75
|
+
const page = document.createElement('div');
|
|
76
|
+
page.className = 'print-notes-page';
|
|
77
|
+
|
|
78
|
+
const hdr = document.createElement('header');
|
|
79
|
+
hdr.className = 'print-notes-header';
|
|
80
|
+
const label = document.createElement('span');
|
|
81
|
+
label.className = 'print-notes-label';
|
|
82
|
+
label.textContent = `Notes — slide ${slideNum}`;
|
|
83
|
+
hdr.appendChild(label);
|
|
84
|
+
if (title) {
|
|
85
|
+
const titleSpan = document.createElement('span');
|
|
86
|
+
titleSpan.className = 'print-notes-title';
|
|
87
|
+
titleSpan.textContent = title;
|
|
88
|
+
hdr.appendChild(titleSpan);
|
|
89
|
+
}
|
|
90
|
+
page.appendChild(hdr);
|
|
91
|
+
|
|
92
|
+
const body = document.createElement('div');
|
|
93
|
+
body.className = 'print-notes-content';
|
|
94
|
+
body.innerHTML = notesEl.innerHTML;
|
|
95
|
+
page.appendChild(body);
|
|
96
|
+
|
|
97
|
+
section.insertAdjacentElement('afterend', page);
|
|
98
|
+
}
|
|
50
99
|
});
|
|
51
100
|
</script>
|
|
52
101
|
</body>
|
|
@@ -632,6 +632,31 @@ export const RULES: Rule[] = [
|
|
|
632
632
|
},
|
|
633
633
|
},
|
|
634
634
|
|
|
635
|
+
{
|
|
636
|
+
// Notes get printed as separate pages with `showNotes: 'separate-page'`.
|
|
637
|
+
// Browsers split long *list* content across pages cleanly, but a single
|
|
638
|
+
// fenced code block inside notes is one indivisible element — if it runs
|
|
639
|
+
// longer than one printed page it gets clipped. Warn at 30 lines so the
|
|
640
|
+
// author can split or shorten before the trainer discovers it on paper.
|
|
641
|
+
name: "notes-code-too-long",
|
|
642
|
+
scope: "slide",
|
|
643
|
+
check: (ctx) => {
|
|
644
|
+
const notes = extractNotes(ctx.body);
|
|
645
|
+
if (!notes.trim()) return [];
|
|
646
|
+
const findings: Finding[] = [];
|
|
647
|
+
for (const n of codeBlockLineCounts(notes)) {
|
|
648
|
+
if (n > 30) {
|
|
649
|
+
findings.push({
|
|
650
|
+
rule: "notes-code-too-long",
|
|
651
|
+
severity: "W",
|
|
652
|
+
msg: `notes code block has ${n} lines — won't break across printed pages cleanly (limit 30)`,
|
|
653
|
+
});
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
return findings;
|
|
657
|
+
},
|
|
658
|
+
},
|
|
659
|
+
|
|
635
660
|
// ── Deck-scope rules (Tier 3) ───────────────────────────────────────────
|
|
636
661
|
|
|
637
662
|
{
|
|
@@ -101,7 +101,6 @@ User: "mark <project> as complete"
|
|
|
101
101
|
- **Don't dump the full JSON.** Summarize. The user can ask for the raw payload.
|
|
102
102
|
- **Don't write without confirming the field choice on ambiguous "store" requests.** A "fact" sticks forever; a "next step" implies follow-up — these are different commitments.
|
|
103
103
|
- **Don't edit the JSON files directly.** Always use the CLI — it timestamps `updated` and keeps the schema valid.
|
|
104
|
-
- **Don't re-introduce `~/.pal/telos/PROJECTS.md`.** That file and its `update-projects.ts` tool are deprecated. The legacy `telos` skill carries a deprecation notice for this reason.
|
|
105
104
|
- **Don't confuse `add-fact` with the `telos` skill's `LEARNED.md` or `IDEAS.md`.** Project facts are scoped to one project; TELOS lessons are cross-cutting.
|
|
106
105
|
|
|
107
106
|
## Rules
|
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: telos
|
|
3
|
-
description: Personal context management. Use when discussing goals, beliefs, challenges, identity, updating telos, life context, changing a goal,
|
|
3
|
+
description: Personal context management. Use when discussing goals, beliefs, challenges, identity, updating telos, life context, changing a goal, what do I believe, current obstacles, mission, or strategies.
|
|
4
4
|
argument-hint: [area to view or update]
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
> ⚠️ **DEPRECATION NOTICE — Project management has moved.**
|
|
8
|
-
> Project tracking is now handled by the `projects` skill, backed by `~/.pal/tools/project.ts` and per-project state in `~/.pal/memory/state/progress/`. **Do not use this skill for projects.** The `PROJECTS.md` references and `update-projects.ts` tool below are legacy and slated for removal — they remain only because the initial setup wizard (`src/cli/setup-telos.ts`) still depends on them. For anything project-related, invoke the `projects` skill.
|
|
9
|
-
|
|
10
7
|
Manage the user's TELOS files — the persistent personal context that drives PAL.
|
|
11
8
|
|
|
12
9
|
## TELOS Files
|
|
@@ -16,7 +13,6 @@ All files live in `~/.pal/telos/`:
|
|
|
16
13
|
| File | Contains |
|
|
17
14
|
|------|----------|
|
|
18
15
|
| `GOALS.md` | Short/medium/long-term goals |
|
|
19
|
-
| `PROJECTS.md` | Active projects, status, priority |
|
|
20
16
|
| `BELIEFS.md` | Core principles and values |
|
|
21
17
|
| `CHALLENGES.md` | Current obstacles |
|
|
22
18
|
| `MISSION.md` | Purpose and direction |
|
|
@@ -32,33 +28,18 @@ Read the file directly from `~/.pal/telos/` when the user asks about any area. S
|
|
|
32
28
|
|
|
33
29
|
## Updating
|
|
34
30
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
For all files except PROJECTS.md — appends content, creates backup, logs the change:
|
|
31
|
+
Appends content, creates backup, logs the change:
|
|
38
32
|
|
|
39
33
|
```bash
|
|
40
34
|
bun ~/.pal/skills/telos/tools/update-telos.ts <FILE> "<content>" "<description>"
|
|
41
35
|
```
|
|
42
36
|
|
|
43
|
-
### Projects (upsert by ID)
|
|
44
|
-
|
|
45
|
-
For PROJECTS.md — upserts a row by the ID column. Replaces if the ID exists, appends if new:
|
|
46
|
-
|
|
47
|
-
```bash
|
|
48
|
-
bun ~/.pal/skills/telos/tools/update-projects.ts <id> "<row>" "<description>"
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
The ID is the first column of the table. Use short, lowercase, kebab-case slugs (e.g., `my-project`, `side-gig`).
|
|
52
|
-
|
|
53
37
|
## Routing
|
|
54
38
|
|
|
55
39
|
| Intent | Action |
|
|
56
40
|
|--------|--------|
|
|
57
|
-
| "what am I working on", "my projects", "priorities" | Read `PROJECTS.md`, summarize active work |
|
|
58
41
|
| "my goals", "what are my goals" | Read `GOALS.md`, present current state |
|
|
59
|
-
| "update goals/
|
|
60
|
-
| "add a project", "new project" | Read `PROJECTS.md`, confirm with user, run update tool |
|
|
61
|
-
| "complete/remove a project" | Read `PROJECTS.md`, confirm with user, update status via tool |
|
|
42
|
+
| "update goals/beliefs/challenges" | Read the target file, discuss changes with user, then run update tool |
|
|
62
43
|
| "what do I believe", "my principles" | Read `BELIEFS.md` |
|
|
63
44
|
| "current obstacles", "challenges" | Read `CHALLENGES.md` |
|
|
64
45
|
| "I learned something", "lesson" | Discuss, then append to `LEARNED.md` via tool |
|
|
@@ -67,38 +48,12 @@ The ID is the first column of the table. Use short, lowercase, kebab-case slugs
|
|
|
67
48
|
|
|
68
49
|
## Examples
|
|
69
50
|
|
|
70
|
-
**
|
|
71
|
-
```
|
|
72
|
-
User: "what am I working on?"
|
|
73
|
-
→ Read PROJECTS.md
|
|
74
|
-
→ Summarize active work by priority — don't list every column
|
|
75
|
-
→ Highlight status changes, blockers, what needs attention
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
**Example 2: Adding a project**
|
|
79
|
-
```
|
|
80
|
-
User: "add my new side project"
|
|
81
|
-
→ Ask: "What's the project name, status, and priority?"
|
|
82
|
-
→ User provides details
|
|
83
|
-
→ Show the row you'll add, confirm
|
|
84
|
-
→ Run: bun ~/.pal/skills/telos/tools/update-projects.ts side-project "| side-project | Side Project | In progress | Medium | Description |" "Added Side Project"
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
**Example 3: Updating a project**
|
|
88
|
-
```
|
|
89
|
-
User: "mark X as complete"
|
|
90
|
-
→ Read PROJECTS.md, find the entry and its ID
|
|
91
|
-
→ Show updated row, confirm
|
|
92
|
-
→ Run: bun ~/.pal/skills/telos/tools/update-projects.ts some-id "| some-id | Project Name | Complete | High | ... |" "Marked project as complete"
|
|
93
|
-
→ The existing row is replaced, not duplicated
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
**Example 4: Updating goals**
|
|
51
|
+
**Updating goals**
|
|
97
52
|
```
|
|
98
53
|
User: "I finished the migration, update my goals"
|
|
99
54
|
→ Read GOALS.md to see current state
|
|
100
55
|
→ Discuss what changed — what's done, what's next
|
|
101
|
-
→ Run tool with
|
|
56
|
+
→ Run tool with updated content
|
|
102
57
|
→ Remind: CLAUDE.md regenerates next session
|
|
103
58
|
```
|
|
104
59
|
|
|
@@ -106,8 +61,8 @@ User: "I finished the migration, update my goals"
|
|
|
106
61
|
|
|
107
62
|
- **Don't dump raw file contents.** Summarize what's relevant to the user's question. They can ask for the full file if needed.
|
|
108
63
|
- **Don't update without confirming.** Always show what you'll change and get a "yes" before running the tool.
|
|
109
|
-
- **Don't create new TELOS files.** Only the
|
|
110
|
-
- **Don't mix TELOS with identity.** AI/principal identity lives in `pal-settings.json`, not TELOS. TELOS is personal context — goals, beliefs,
|
|
64
|
+
- **Don't create new TELOS files.** Only the 9 listed files are valid. If something doesn't fit, suggest the closest match.
|
|
65
|
+
- **Don't mix TELOS with identity.** AI/principal identity lives in `pal-settings.json`, not TELOS. TELOS is personal context — goals, beliefs, challenges.
|
|
111
66
|
- **Don't reference stale data.** If TELOS was loaded earlier in the session via context routing, re-read the file before updating — it may have changed.
|
|
112
67
|
|
|
113
68
|
## Rules
|
|
@@ -55,6 +55,7 @@ Start your response with the following header in this mode:
|
|
|
55
55
|
|
|
56
56
|
- **Mandatory output format** — Every response MUST use exactly one of the output formats above (ALGORITHM, NATIVE, or MINIMAL). No freeform output.
|
|
57
57
|
- **Response format before questions** — Always complete the current response format output FIRST, then invoke AskUserQuestion at the end.
|
|
58
|
+
- **Named project → resume first** — Whenever the user references a project by name in ANY mode, run `bun ~/.pal/tools/project.ts resume <slug>` before any file search or task execution. The project record has paths, context, and handoff notes that make manual searching unnecessary.
|
|
58
59
|
|
|
59
60
|
---
|
|
60
61
|
|
|
@@ -73,7 +74,7 @@ Load context on-demand by reading the file at the path listed. Only load what th
|
|
|
73
74
|
| Opinion tracking | `~/.pal/docs/OPINION_TRACKING.md` |
|
|
74
75
|
| Steering rules | `~/.pal/docs/STEERING_RULES.md` |
|
|
75
76
|
| Algorithm (complex work phases) | `~/.pal/docs/ALGORITHM.md` |
|
|
76
|
-
| Project lifecycle (
|
|
77
|
+
| Project lookup AND lifecycle (find paths, resume state, register, manage) | `~/.pal/skills/projects/SKILL.md` |
|
|
77
78
|
|
|
78
79
|
### User Context (TELOS)
|
|
79
80
|
|
|
@@ -206,7 +206,32 @@ bun ~/.pal/tools/algorithm-reflect.ts --task "description" --criteria N --passed
|
|
|
206
206
|
--q1 "self reflection" --q2 "algorithm reflection" --q3 "AI reflection"
|
|
207
207
|
```
|
|
208
208
|
|
|
209
|
-
**3.
|
|
209
|
+
**3. Relationship note** — write one Session entry capturing what was done this session:
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
bun ~/.pal/tools/relationship-note.ts --b "description"
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
- 1-2 sentences, first-person, specific — name the actual system/file/concept worked on
|
|
216
|
+
- ✓ "Debugged the React Query cache split logic and resolved stuck message state in the onFinish callback"
|
|
217
|
+
- ✗ "Helped with memory improvements" — too vague, no system named
|
|
218
|
+
- Skip only if the session was a trivial lookup or typo fix (same rule as step 2)
|
|
219
|
+
|
|
220
|
+
**4. Handoff note** — if work is unfinished, write what remains so the next session can pick up immediately:
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
# Work still in progress:
|
|
224
|
+
bun ~/.pal/tools/handoff-note.ts --title "what we were doing" --text "what remains, decisions made, next steps"
|
|
225
|
+
|
|
226
|
+
# Work finished — clear any previous in-progress handoff:
|
|
227
|
+
bun ~/.pal/tools/handoff-note.ts --done --title "what we completed"
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
- Write if anything is left mid-flight: unfinished implementation, open decision, partially debugged issue
|
|
231
|
+
- Skip if the session fully resolved everything it set out to do
|
|
232
|
+
- `--text` should answer: what's next, what was decided, what to watch out for
|
|
233
|
+
|
|
234
|
+
**5. Open Threads** — for each unresolved question, decision, or follow-up that came up during this session:
|
|
210
235
|
|
|
211
236
|
```bash
|
|
212
237
|
bun ~/.pal/tools/thread.ts --add --title "brief title" --context "why it matters, what needs to happen"
|
|
@@ -218,7 +243,7 @@ Only add threads that genuinely need follow-up. Resolve existing threads if this
|
|
|
218
243
|
bun ~/.pal/tools/thread.ts --resolve --id <id>
|
|
219
244
|
```
|
|
220
245
|
|
|
221
|
-
**
|
|
246
|
+
**6. Opinion capture** — scan the conversation for moments where the user:
|
|
222
247
|
- Confirmed something you did: "yes exactly", "keep doing that", "10 rated", accepted without pushback
|
|
223
248
|
- Corrected something you did: "no", "don't do that", "stop", "that's not what I meant"
|
|
224
249
|
- Revealed a preference by repeating a pattern (asked for concise answers twice, always checked PAI first, etc.)
|
|
@@ -237,7 +262,7 @@ bun ~/.pal/skills/opinion/tools/opinion.ts add "the preference" --category commu
|
|
|
237
262
|
|
|
238
263
|
Skip if nothing in the conversation touched preferences or working style.
|
|
239
264
|
|
|
240
|
-
**
|
|
265
|
+
**7. Wisdom Frame** (Extended+ only) — if the session produced a genuine, reusable insight:
|
|
241
266
|
|
|
242
267
|
```bash
|
|
243
268
|
bun ~/.pal/tools/wisdom-frame.ts --domain <domain> --observation "insight" [--type principle|contextual-rule|anti-pattern|evolution]
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Project Lifecycle
|
|
2
|
+
|
|
3
|
+
You (the AI) own the project lifecycle. Project state lives in `~/.pal/memory/state/progress/{slug}.json`, one file per project, managed via `bun ~/.pal/tools/project.ts`. Active projects are auto-injected into every SessionStart context regardless of cwd.
|
|
4
|
+
|
|
5
|
+
## When to invoke the CLI
|
|
6
|
+
|
|
7
|
+
**Proactive registration.** When SessionStart context says `💡 cwd <path> is not yet registered; suggest registering if substantive work begins`, AND the user starts substantive work (not just "hi"), surface the suggestion conversationally before the second tool call: *"I see we're in `<basename>` and it's not registered yet — want me to add it as a project?"*
|
|
8
|
+
|
|
9
|
+
- **Default name** = the FULL last path segment of `cwd`, lowercased. For `/repos/portable-agent-layer` the default is `portable-agent-layer`. Never split on `-`.
|
|
10
|
+
- **Confirm before creating.** Never auto-create without explicit user approval ("yes", "do it", "register").
|
|
11
|
+
- **Capture objectives in conversation.** If the user accepts but doesn't volunteer objectives, ask one short question; or infer from the last few messages and confirm.
|
|
12
|
+
|
|
13
|
+
**Append as you go.** When the user describes plans, blockers, or decisions during normal work, invoke the relevant subcommand to keep state current — that's the dynamism this system is built for.
|
|
14
|
+
|
|
15
|
+
| user says | you call |
|
|
16
|
+
|---|---|
|
|
17
|
+
| "let's also add X" / "we should handle Y next" | `add-next <name> "..."` |
|
|
18
|
+
| "we're blocked on Z" / "Z is blocking this" | `add-blocker <name> "..."` |
|
|
19
|
+
| "the objective here is to ship X by Y" | `add-objective <name> "..."` |
|
|
20
|
+
| "the API base is at Z" / "tech stack is Bun + TS" — stable, reference-flavored facts | `add-fact <name> "..."` |
|
|
21
|
+
| "we decided to use A because B" | `add-decision <name> "A" "B"` |
|
|
22
|
+
| "let's pause this" / "shelve it" | `pause <name>` |
|
|
23
|
+
| "we shipped" / "this is done" | `complete <name>` |
|
|
24
|
+
|
|
25
|
+
**Don't** invoke for fleeting comments, hypotheticals, or things the user is just thinking through. Wait for a clear declarative ("let's add X", "Z is blocking us"), not a question or musing.
|
|
26
|
+
|
|
27
|
+
## When NOT to suggest registration
|
|
28
|
+
|
|
29
|
+
- cwd has no project marker (`.git`, `package.json`, `pyproject.toml`, `Cargo.toml`, `go.mod`, etc.) — it's a notes folder, not a project.
|
|
30
|
+
- The user is clearly browsing or doing a one-off task.
|
|
31
|
+
- An ancestor of multiple registered projects is the cwd (e.g. `~/Development/git/`) — that's browse mode by design.
|
|
32
|
+
- You're unsure. Err toward not registering.
|
|
33
|
+
|
|
34
|
+
## CLI cheat sheet
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
list show all projects
|
|
38
|
+
create [name] [--path PATH] [--objectives X] register (defaults: name=basename(cwd), path=cwd)
|
|
39
|
+
resume <name> print full project JSON
|
|
40
|
+
complete | archive | pause | unpause <name> change status
|
|
41
|
+
add-fact | add-objective | add-next | add-blocker <name> "text"
|
|
42
|
+
add-decision <name> "decision" "rationale"
|
|
43
|
+
add-handoff <name> "text"
|
|
44
|
+
rm-fact | rm-objective | rm-next | rm-blocker <name> <index>
|
|
45
|
+
rm <name> delete the project file (rare; prefer archive)
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The Stop hook auto-touches `updated` (and optionally writes a `handoff`) whenever cwd resolves to an active project — you don't need to refresh timestamps manually.
|
|
@@ -21,7 +21,7 @@ PAL is a persistent, cross-platform, cross-agent layer for portable AI workflows
|
|
|
21
21
|
tools/ # Agent CLI tools (symlink → repo src/tools/agent/)
|
|
22
22
|
skills/ # Installed skills (symlinks → assets/skills/)
|
|
23
23
|
telos/ # User life context (TELOS)
|
|
24
|
-
MISSION.md, GOALS.md,
|
|
24
|
+
MISSION.md, GOALS.md, BELIEFS.md,
|
|
25
25
|
CHALLENGES.md, STRATEGIES.md, IDEAS.md, LEARNED.md,
|
|
26
26
|
MODELS.md, NARRATIVES.md
|
|
27
27
|
|
|
@@ -45,3 +45,7 @@ Correct: Review your recent actions → find the mistake → fix it → explain
|
|
|
45
45
|
**Act on what you know.** When tracked opinions or relationship notes reveal user preferences, apply them to your behavior. If you know the user prefers concise responses, be concise. If they prefer manual commits, never offer to commit.
|
|
46
46
|
Bad: Memory says user dislikes verbose summaries → you write a 3-paragraph recap after every change.
|
|
47
47
|
Correct: Memory says user dislikes verbose summaries → you keep the summary to one line.
|
|
48
|
+
|
|
49
|
+
**Don't trust, verify.** When adding a test or asserting a change works, prove it by making it fail first. A test that passes without ever being broken demonstrates nothing — it may be testing the wrong thing or nothing at all. Break it intentionally, confirm it fails for the right reason, then restore it.
|
|
50
|
+
Bad: Add a test, see it green, move on. The test may pass vacuously.
|
|
51
|
+
Correct: Add the test → run it green → break the code it covers → confirm it goes red → restore → now it's a real test.
|