portable-agent-layer 0.29.1 → 0.30.1

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.
@@ -251,7 +251,7 @@ async function renderSections(
251
251
  const tag = depth === 1 ? "h1" : depth === 2 ? "h2" : "h3";
252
252
  out.push(`<${tag} id="${s.id}">${escapeHtml(s.title)}</${tag}>`);
253
253
  out.push(htmlBody as string);
254
- if (s.subsections && s.subsections.length) {
254
+ if (s.subsections?.length) {
255
255
  out.push(await renderSections(s.subsections, contentDir, depth + 1));
256
256
  }
257
257
  }
@@ -273,10 +273,9 @@ function renderToc(sections: Section[]): string {
273
273
  }
274
274
 
275
275
  function renderCover(r: ConsultingReport, brand: Brand): string {
276
- const logo =
277
- brand.logoPath && brand.logoPath.length
278
- ? `<img class="logo" src="file://${brand.logoPath}" alt="${escapeHtml(brand.businessName)}">`
279
- : "";
276
+ const logo = brand.logoPath?.length
277
+ ? `<img class="logo" src="file://${brand.logoPath}" alt="${escapeHtml(brand.businessName)}">`
278
+ : "";
280
279
  const brandLabel = brand.brandLabel || `${brand.businessName} Assessment`;
281
280
  return `
282
281
  <div class="cover">
@@ -1,32 +1,69 @@
1
1
  ---
2
2
  name: create-skill
3
- description: Scaffold a new PAL skill from a description. Use when creating a new skill, adding a capability, or building a custom command.
4
- argument-hint: <skill description>
3
+ description: Scaffold a new PAL skill from a description. Use when creating a new skill, adding a capability, or building a custom command. Enforces general, assistant-facing, personally-clean skill writing.
4
+ argument-hint: <skill name> <skill description>
5
5
  ---
6
6
 
7
- When the user invokes /create-skill <name> <description>:
7
+ ## What makes a good PAL skill
8
8
 
9
- 1. Create a new markdown file in the skills/ directory
10
- 2. Use this template:
9
+ Before writing any skill, internalize these three rules. A skill that violates them gets re-written, not committed.
10
+
11
+ 1. **Pointed at the assistant, not the user.** A skill is *instructions you (the assistant) follow*. Write in second person addressing yourself ("read X", "extract Y", "output Z"). Prescriptive verbs, deterministic flow. It is **not** a user tutorial, marketing blurb, or README. The user reads `README.md`; you read `SKILL.md`.
12
+
13
+ 2. **Zero personal information.** No usernames, real names, employer names, project codenames, dataset names, hostnames, absolute home paths (`C:\Users\someone\…`), email addresses, or anecdotes about the author's own work. A skill must be reusable by any user. If the rule is "don't expand `~` on Windows cmd," that is the rule — don't add "because $username's primary shell is cmd." Personal context belongs in the user's private memory, never in the skill body.
14
+
15
+ 3. **General, not user-specific.** A skill describes a *workflow class* (e.g. "build a deck," "summarize a PDF," "lint a python file"), not a single user's habits. Use placeholders (`<deck-dir>`, `<input.pdf>`), not hardcoded paths. If the workflow only makes sense for one person, it is a memory entry or a personal hook, not a skill.
16
+
17
+ ## Skill anatomy
11
18
 
12
19
  ```markdown
13
20
  ---
14
- name: <name>
15
- description: <one-line description>
21
+ name: <slug> # the slash-command name; lowercase-kebab
22
+ description: <one sentence trigger> # WHEN to invoke (used by the dispatcher), not WHAT it does
23
+ argument-hint: <args> # optional; how the user passes input
16
24
  ---
17
25
 
18
- When the user invokes /<name> <args>:
26
+ ## Overview / Workflow
27
+
28
+ Numbered steps the assistant follows on invocation. Each step is concrete:
29
+ read this file, run this command, ask this question, output this format.
30
+
31
+ ## Output format
19
32
 
20
- 1. <step>
21
- 2. <step>
22
- 3. <step>
33
+ Exactly what the assistant returns to the user. Specify structure if the
34
+ caller will parse it; specify tone if the caller is a human.
23
35
 
24
- Output format:
25
- - <format specification>
36
+ ## When to use / Do NOT use
37
+
38
+ Two short lists. The "do not" list disambiguates this skill from neighbours
39
+ that would otherwise also match the user's request.
26
40
  ```
27
41
 
28
- 3. Validate the skill has:
29
- - Clear trigger (when to invoke)
30
- - Specific steps (not vague)
31
- - Defined output format
32
- - Reasonable scope (one skill, one job)
42
+ ## Workflow when the user invokes `/create-skill <name> <description>`
43
+
44
+ 1. Sanity-check the name and description against the three rules above. If the description leaks personal info ("a skill for me to clean my Notion db"), rewrite it to the general form ("clean a Notion database via the API") before scaffolding.
45
+ 2. Create `assets/skills/<name>/SKILL.md` in the repo (the canonical source). The installed copy at `~/.pal/skills/<name>/SKILL.md` may be a junction to this path — verify the user's setup before assuming.
46
+ 3. Populate the SKILL.md from the anatomy above. Required fields: `name`, `description`, body sections (Workflow, Output format, When to use). Add `argument-hint` if the skill takes arguments.
47
+ 4. If the skill needs runtime tooling (TypeScript, scripts, vendored assets), scaffold a `tools/` subdir alongside SKILL.md. Otherwise leave the skill markdown-only.
48
+ 5. Validate before declaring done:
49
+ - **Trigger clarity** — could a model decide *not* to invoke this skill from the description alone? If yes, tighten the description.
50
+ - **Step concreteness** — every step has a verb and an object; no "as needed" or "appropriately."
51
+ - **Output specification** — caller knows what they get back.
52
+ - **Scope discipline** — one skill, one job. If the skill needs section headers like "for case A do X, for case B do Y," it is two skills.
53
+ - **Personal-info scan** — grep the new SKILL.md for usernames, real names, absolute home paths, employer or project codenames; remove any hits.
54
+ - **Generality test** — could a stranger with the same workflow need use this unchanged? If no, factor the user-specific bits into memory.
55
+
56
+ ## Anti-patterns to refuse
57
+
58
+ - A SKILL.md whose description starts with "I want…" or "My …" — that's a journal entry, not a skill.
59
+ - Hardcoded paths under `C:\Users\<name>\…` or `/Users/<name>/…` — use `~` (and document the cmd.exe `%USERPROFILE%` alternative if Windows is in scope).
60
+ - Brand- or company-specific defaults baked into the skill body. Default brand colors, footer strings, etc. belong in *templates* (user data) or *config*, never in the skill.
61
+ - A description longer than ~30 words, or one that explains the implementation rather than the trigger.
62
+ - Skills that duplicate an existing skill's trigger surface. Read the existing skills index before scaffolding.
63
+
64
+ ## Output format
65
+
66
+ After scaffolding, return:
67
+ - The path of the created `SKILL.md`.
68
+ - A 2-3 sentence summary of the trigger and workflow.
69
+ - Any anti-pattern violations you caught and corrected during scaffolding (so the user learns the rule).
@@ -10,12 +10,18 @@ bun ~/.pal/skills/presentation/tools/setup-template.ts
10
10
 
11
11
  # per deck
12
12
  bun ~/.pal/skills/presentation/tools/new-deck.ts ~/decks/my-talk --template my-brand
13
- $EDITOR ~/decks/my-talk/content.md
14
- bun ~/.pal/skills/presentation/tools/present.ts ~/decks/my-talk
13
+ $EDITOR ~/decks/my-talk/slides/
14
+ bun ~/.pal/skills/presentation/tools/build.ts ~/decks/my-talk
15
+ # → ./my-talk/my-talk.html (and ./my-talk/my-talk.md — concatenated source)
16
+ # open the .html in your browser; refresh after each rebuild
15
17
  ```
16
18
 
17
- Layouts: title, section, content, two-column, image-text, quote, closing, agenda, table, comparison, code.
19
+ Output: `<cwd>/<deck-name>/<deck-name>.html` (self-contained) plus `<deck-name>.md` (concatenated source). Override the parent dir with `--out <dir>`; pass `--force` to overwrite an existing build.
18
20
 
19
- PDF export (v1.1): use the browser's print-to-PDF (`Cmd+P` in the open deck) Reveal supports `?print-pdf` query mode for clean page breaks. Standalone PDF tooling (decktape) deferred until requested.
21
+ Layouts (14): title, section, content, two-column, image-text, quote, closing, agenda, table, comparison, code, big-stat, metric-grid, pull-quote.
20
22
 
21
- PPTX import (v2): not yet supported.
23
+ Image utilities: `image-rounded`, `image-shadow`, `image-bleed`, `image-duotone`, `image-overlay`.
24
+
25
+ PDF export: use the browser's print-to-PDF (`Cmd+P` in the open deck) — Reveal supports `?print-pdf` query mode for clean page breaks. Standalone PDF tooling (decktape) deferred until requested.
26
+
27
+ PPTX import: not yet supported.
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: presentation
3
- description: Build branded HTML presentations from markdown using Reveal.js. Multi-template registry per user (each template = brand color, logo, fonts, footer, aspect). Per-deck workflow: scaffold → edit one markdown file per slide in slides/ → build → present. Output: single self-contained HTML. Use when creating slide decks, talks, workshop slides, lectures, or pitch decks.
4
- argument-hint: <deck-dir> to build, OR `setup-template` to add a brand template, OR `new <deck-dir> --template <name>` to scaffold a deck, OR `list-templates`, OR `present <deck-dir>`
3
+ description: Build branded HTML presentations from markdown using Reveal.js. Multi-template registry per user (each template = brand color, logo, fonts, footer, aspect). Per-deck workflow: scaffold → edit one markdown file per slide in slides/ → build → present. Output: a `<deck-name>/` subdir with a self-contained HTML and a concatenated markdown sibling. 14 layouts including data-display patterns (big-stat, metric-grid). Use when creating slide decks, talks, workshop slides, lectures, or pitch decks.
4
+ argument-hint: <deck-dir> to build, OR `setup-template` to add a brand template, OR `new <deck-dir> --template <name>` to scaffold a deck, OR `list-templates`
5
5
  ---
6
6
 
7
7
  ## Overview
@@ -66,18 +66,38 @@ Backwards compatible: if `slides/` doesn't exist, the build falls back to a sing
66
66
  ### Step 3: Build
67
67
 
68
68
  ```bash
69
- bun ~/.pal/skills/presentation/tools/build.ts <deck-dir>
69
+ bun ~/.pal/skills/presentation/tools/build.ts <deck-dir> [--out <dir>] [--force]
70
70
  ```
71
71
 
72
- Produces `<deck-dir>/dist/index.html` a single self-contained HTML file (CSS, JS, fonts, logo all inlined). Email it, USB-stick it, host it anywhere.
72
+ Output goes to `<out>/<deck-name>/`, where `<deck-name>` = the basename of `<deck-dir>`:
73
+
74
+ - `<deck-name>.md` — the concatenated source (all `slides/*.md` joined with `---` separators), written to disk **first** so you can inspect, diff, or feed it into other tooling.
75
+ - `<deck-name>.html` — the self-contained presentation (CSS, JS, fonts, logo all inlined). Email it, USB-stick it, host it anywhere.
76
+
77
+ Defaults: `--out` defaults to the current working directory. The `<deck-name>/` subdir is always created — even when `--out` is explicit — so multiple decks can coexist in one folder.
78
+
79
+ `--force` overwrites an existing build. Without it, the build refuses to clobber `<deck-name>.{md,html}`.
73
80
 
74
- ### Step 4: Present
81
+ ### Step 3.5 (optional but recommended): Lint with the doctor
75
82
 
76
83
  ```bash
77
- bun ~/.pal/skills/presentation/tools/present.ts <deck-dir>
84
+ bun ~/.pal/skills/presentation/tools/doctor.ts <deck-dir> [--strict]
78
85
  ```
79
86
 
80
- Builds (if missing or stale) and opens in the default browser. `F` = fullscreen, `S` = speaker notes window, `?` = keyboard shortcuts.
87
+ Catches authoring failures before you ever open the browser:
88
+
89
+ - Slide missing `data-layout` directive (silently defaults to `content`).
90
+ - Title or subtitle exceeding the visual budget (h1 > 60 chars, h2 > 100).
91
+ - Layout-content mismatch — `comparison` without a `<div class="compare">`, `metric-grid` without `<div class="metrics">`, `two-column` missing column wrappers, etc.
92
+ - Overflow heuristics — `agenda` > 10 items, `content` > 7 bullets, `code` block > 25 lines, `table` > 10 rows, `metric-grid` ≠ 3 metrics.
93
+ - Image referenced via `![](assets/...)` but the file is missing.
94
+ - Layout requirements — `big-stat` without an h1, `quote` / `pull-quote` without a `> blockquote`.
95
+
96
+ Exit codes: `0` = clean, `1` = errors found (or warnings under `--strict`), `2` = usage error. Run before each build in your iteration loop, or wire it into a pre-commit hook.
97
+
98
+ ### Step 4: Open
99
+
100
+ 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.
81
101
 
82
102
  ## Deck folder layout
83
103
 
@@ -89,11 +109,11 @@ Builds (if missing or stale) and opens in the default browser. `F` = fullscreen,
89
109
  │ ├── 002.md
90
110
  │ └── …
91
111
  ├── overrides.css # optional — per-deck CSS overrides
92
- ├── assets/ # images / videos referenced from slides/*.md
93
- └── dist/ # build output (gitignored automatically)
94
- └── index.html
112
+ └── assets/ # images / videos referenced from slides/*.md
95
113
  ```
96
114
 
115
+ Build output is **never** written inside `<deck-dir>` — it lands in `<out>/<deck-name>/` (default `<cwd>/<deck-name>/`). The scaffolder's `.gitignore` covers the case of running build from inside the deck-dir.
116
+
97
117
  (Legacy: a single `content.md` at the deck root still works — see Step 2.)
98
118
 
99
119
  ## Content conventions
@@ -137,21 +157,77 @@ Right content.
137
157
  ## Questions?
138
158
  ```
139
159
 
140
- ## Layouts (v1)
160
+ ## Layouts (v2 — 14 total)
141
161
 
142
162
  | Layout | When | Notes |
143
163
  |---|---|---|
144
- | `title` | Cover slide | Big title, optional subtitle, brand logo prominent |
145
- | `section` | Section divider | Full-bleed accent background, large white title |
164
+ | `title` | Cover slide | Big title, accent rule, brand logo prominent |
165
+ | `section` | Section divider | Full-bleed brand-primary gradient + accent rule |
146
166
  | `content` | Default | Title + bullets / paragraphs |
147
167
  | `two-column` | Side-by-side content | Use `<div class="col-left">` / `<div class="col-right">` |
148
168
  | `image-text` | Image + text combo | Use `<div class="image">` / `<div class="text">` |
149
- | `quote` | Big italic blockquote | Use markdown `>` syntax |
150
- | `closing` | Thank-you / Q&A | Mirrors title styling on accent BG |
169
+ | `quote` | Big italic blockquote | Use markdown `>` syntax; oversized accent glyph |
170
+ | `closing` | Thank-you / Q&A | Mirrors title styling on gradient brand BG |
151
171
  | `agenda` | Numbered list | Numbered ol, large type, generous whitespace |
152
- | `table` | Tabular data | Markdown tables, styled with zebra rows + accent header |
153
- | `comparison` | 2–3 option boxes side-by-side | Use `<div class="compare">` with `<div class="option">` children |
172
+ | `table` | Tabular data | Markdown tables with zebra rows + accent header |
173
+ | `comparison` | 2–3 option boxes side-by-side | Use `<div class="compare">` + `<div class="option">` children |
154
174
  | `code` | Code-focused | Triple-backtick fenced blocks with language tag |
175
+ | `big-stat` | One number does the work | `# 87%` + `## caption`. Wrap unit in `<em class="unit">%</em>` |
176
+ | `metric-grid` | 3-up KPI cards | `<div class="metrics">` with `<div class="metric">` children (`.label`, `.value`, `.delta.up\|.down`) |
177
+ | `pull-quote` | Oversized in-line quote | Display-font italic, accent rule on left, em-dashed attribution on a paragraph after |
178
+
179
+ ## Image utility classes
180
+
181
+ Composable on any `<img>` or wrapper element:
182
+
183
+ | Class | Effect |
184
+ |---|---|
185
+ | `image-rounded` | `--radius-md` corners |
186
+ | `image-shadow` | `--shadow-lg` drop |
187
+ | `image-bleed` | Fill container, `object-fit: cover` |
188
+ | `image-duotone` | Brand-tinted monochrome via filter chain |
189
+ | `image-overlay` | Adds a brand-gradient scrim from transparent → primary at 75% bottom |
190
+
191
+ ## Design tokens
192
+
193
+ The skill ships a token system in `theme-base/base.css`. Templates only declare two anchors (`--brand-primary`, `--brand-accent`); the rest derives via `color-mix(in oklch, …)`.
194
+
195
+ | Token group | Values |
196
+ |---|---|
197
+ | Color scales | `--brand-primary-{50..900}`, `--brand-accent-{50..900}`, `--neutral-{50..950}` |
198
+ | Semantic | `--brand-bg`, `--brand-fg`, `--brand-muted`, `--brand-surface`, `--brand-divider` |
199
+ | Type | `--text-{xs..6xl}`, `--text-display`, `--leading-*`, `--tracking-*` |
200
+ | Spacing | `--space-{0,px,0.5,1..7}` |
201
+ | Radius | `--radius-{sm,md,lg,xl,full}` |
202
+ | Shadow | `--shadow-{sm,md,lg,xl}` |
203
+ | Motion | `--duration-{fast,base,slow}`, `--ease-{out,in-out}` |
204
+
205
+ Templates that need to override a derived token (dark theme, brand-tinted surface) can do so in `template.css`.
206
+
207
+ ## After authoring slides — always surface the run commands
208
+
209
+ When you (the assistant) author or edit slides for the user, **end your response with the exact `build` command** the user can run themselves. The user's iteration loop is small manual edits in `slides/*.md` plus a browser refresh; they need the command in the conversation, not buried in docs.
210
+
211
+ Print this block as the closing of any turn that touches slides:
212
+
213
+ ```bash
214
+ # lint — catches overflow, missing assets, layout-content mismatches
215
+ # bash / PowerShell / Git Bash:
216
+ bun ~/.pal/skills/presentation/tools/doctor.ts <deck-dir>
217
+ # Windows cmd.exe:
218
+ bun %USERPROFILE%\.pal\skills\presentation\tools\doctor.ts <deck-dir>
219
+
220
+ # build — writes <cwd>/<deck-name>/<deck-name>.{html,md}
221
+ # bash / PowerShell / Git Bash:
222
+ bun ~/.pal/skills/presentation/tools/build.ts <deck-dir>
223
+ # Windows cmd.exe (no ~ expansion):
224
+ bun %USERPROFILE%\.pal\skills\presentation\tools\build.ts <deck-dir>
225
+
226
+ # add --out <dir> to override the output parent, --force to overwrite an existing build
227
+ # add --strict to doctor to promote warnings to errors
228
+ ```
229
+
230
+ Substitute `<deck-dir>` with the actual deck path. Do this even when you also ran the build yourself — the user wants the command on hand for their own re-runs. **On Windows, check the user's shell before printing**: `cmd.exe` does not expand `~`, so if the user runs commands from a `C:\…>` prompt, print the `%USERPROFILE%` form. PowerShell, Git Bash, WSL, and Mac/Linux all expand `~` correctly.
155
231
 
156
232
  ## Other commands
157
233
 
@@ -0,0 +1,6 @@
1
+ <!-- .slide: data-layout="big-stat" -->
2
+ # 87<em class="unit">%</em>
3
+
4
+ ## of customers stayed with us year-over-year — up from 71% in 2024
5
+
6
+ Note: big-stat is for moments where one number does the work of a whole slide. Use sparingly — once or twice per deck. The unit (%, $, k) goes in `<em class="unit">` so it scales smaller than the figure itself.
@@ -0,0 +1,22 @@
1
+ <!-- .slide: data-layout="metric-grid" -->
2
+ ## Q1 metrics at a glance
3
+
4
+ <div class="metrics">
5
+ <div class="metric">
6
+ <p class="label">MRR</p>
7
+ <p class="value">$48k</p>
8
+ <p class="delta up">+12% QoQ</p>
9
+ </div>
10
+ <div class="metric">
11
+ <p class="label">Active accounts</p>
12
+ <p class="value">1,284</p>
13
+ <p class="delta up">+204</p>
14
+ </div>
15
+ <div class="metric">
16
+ <p class="label">Churn</p>
17
+ <p class="value">2.1%</p>
18
+ <p class="delta down">−0.4 pp</p>
19
+ </div>
20
+ </div>
21
+
22
+ Note: metric-grid is a 3-up KPI strip. Each `.metric` block has a `.label`, `.value`, and optional `.delta` with `.up` / `.down` modifiers.
@@ -0,0 +1,6 @@
1
+ <!-- .slide: data-layout="pull-quote" -->
2
+ > The best way to predict the future is to build it — but only if you can also explain why anyone should care.
3
+
4
+ — A composite of every product strategy memo we've ever written
5
+
6
+ Note: pull-quote sits between section divider and quote. Bigger than a regular blockquote, italicized in the display font, anchored by an accent rule on the left and an em-dashed attribution underneath.
@@ -1,5 +1,5 @@
1
1
  <!-- .slide: data-layout="closing" -->
2
2
  # That's the lot
3
- ## All 11 layouts, one place
3
+ ## All 14 layouts, one place
4
4
 
5
- Note: If you saw all 11 distinct slide styles, the build pipeline is working. Edit theme-base/layouts.css to tune any of them brand-wide; edit your template's template.css to override colors per brand; edit overrides.css in a deck folder for one-off tweaks.
5
+ Note: If you saw all 14 distinct slide styles, the build pipeline is working. Edit theme-base/layouts.css to tune any of them brand-wide; edit your template's template.css to override colors per brand; edit overrides.css in a deck folder for one-off tweaks.
@@ -1,9 +1,10 @@
1
1
  # Deck folder
2
2
 
3
- Edit `content.md` — slides separated by `---` on its own line.
3
+ One markdown file per slide under `slides/`. Files are concatenated at build time in filename order (use leading zeros: `001.md`, `002.md`, …). **Don't put `---` separators inside slide files** the separator is added between files at build time.
4
4
 
5
5
  Build: `bun ~/.pal/skills/presentation/tools/build.ts .`
6
- Present: `bun ~/.pal/skills/presentation/tools/present.ts .`
6
+
7
+ Output lands at `<cwd>/<deck-name>/<deck-name>.html` — open it in your browser and refresh after each rebuild.
7
8
 
8
9
  Layout per slide:
9
10
  ```markdown
@@ -12,4 +13,4 @@ Layout per slide:
12
13
  - bullet
13
14
  ```
14
15
 
15
- Available layouts: title, section, content, two-column, image-text, quote, closing, agenda, table, comparison, code. See the skill's SKILL.md for details on each.
16
+ Available layouts: title, section, content, two-column, image-text, quote, closing, agenda, table, comparison, code, big-stat, metric-grid, pull-quote. See the skill's SKILL.md for details on each.