@forwardimpact/outpost 3.9.0 → 3.11.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.
Files changed (40) hide show
  1. package/package.json +1 -1
  2. package/src/kb-manager.js +27 -1
  3. package/templates/.claude/agents/chief-of-staff.md +9 -7
  4. package/templates/.claude/agents/concierge.md +6 -4
  5. package/templates/.claude/agents/head-hunter.md +6 -4
  6. package/templates/.claude/agents/librarian.md +14 -10
  7. package/templates/.claude/agents/postman.md +6 -4
  8. package/templates/.claude/agents/recruiter.md +8 -5
  9. package/templates/.claude/skills/anarlog-follow/SKILL.md +2 -2
  10. package/templates/.claude/skills/anarlog-follow/references/coaching.md +3 -3
  11. package/templates/.claude/skills/anarlog-trim/SKILL.md +9 -3
  12. package/templates/.claude/skills/candidate-report/SKILL.md +4 -3
  13. package/templates/.claude/skills/changelog/SKILL.md +10 -10
  14. package/templates/.claude/skills/deck-create/SKILL.md +23 -22
  15. package/templates/.claude/skills/deck-review/SKILL.md +36 -26
  16. package/templates/.claude/skills/deck-review/assets/slide-annotator.js +100 -15
  17. package/templates/.claude/skills/doc-create/SKILL.md +17 -16
  18. package/templates/.claude/skills/extract-entities/SKILL.md +7 -4
  19. package/templates/.claude/skills/extract-entities/references/recruitment.md +13 -3
  20. package/templates/.claude/skills/meeting-prep/SKILL.md +5 -3
  21. package/templates/.claude/skills/organize-files/SKILL.md +9 -5
  22. package/templates/.claude/skills/person-identify/SKILL.md +2 -2
  23. package/templates/.claude/skills/person-lookup/SKILL.md +3 -3
  24. package/templates/.claude/skills/req-decide/SKILL.md +4 -2
  25. package/templates/.claude/skills/req-forget/references/report-template.md +1 -1
  26. package/templates/.claude/skills/req-scan/references/fallbacks.md +3 -3
  27. package/templates/.claude/skills/req-scan/references/sources.md +5 -5
  28. package/templates/.claude/skills/req-screen/SKILL.md +4 -2
  29. package/templates/.claude/skills/req-track/SKILL.md +19 -15
  30. package/templates/.claude/skills/req-track/references/fields.md +4 -2
  31. package/templates/.claude/skills/req-workday/SKILL.md +4 -2
  32. package/templates/.claude/skills/req-workday/references/status-mapping.md +1 -1
  33. package/templates/.claude/skills/req-workday/references/templates.md +3 -1
  34. package/templates/.claude/skills/sync-apple-calendar/SKILL.md +6 -2
  35. package/templates/.claude/skills/sync-apple-mail/SKILL.md +3 -1
  36. package/templates/.claude/skills/sync-apple-mail/references/SCHEMA.md +1 -1
  37. package/templates/.claude/skills/sync-teams/SKILL.md +13 -1
  38. package/templates/.claude/skills/sync-teams/scripts/idb-reader.mjs +67 -34
  39. package/templates/.claude/skills/upstream-instructions/SKILL.md +2 -1
  40. package/templates/CLAUDE.md +27 -38
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forwardimpact/outpost",
3
- "version": "3.9.0",
3
+ "version": "3.11.0",
4
4
  "description": "Personal operations center — context from email, calendar, and knowledge assembled so preparation is continuous, not a morning scramble.",
5
5
  "homepage": "https://www.forwardimpact.team",
6
6
  "repository": {
package/src/kb-manager.js CHANGED
@@ -2,7 +2,7 @@
2
2
  * KBManager — knowledge base init/update operations.
3
3
  */
4
4
 
5
- import { join, dirname, resolve } from "node:path";
5
+ import { join, dirname, resolve, basename } from "node:path";
6
6
  import { homedir } from "node:os";
7
7
  import { createLogger } from "@forwardimpact/libtelemetry";
8
8
 
@@ -214,6 +214,7 @@ export class KBManager {
214
214
  await this.#ensureDir(join(dest, d));
215
215
 
216
216
  await this.copyBundledFiles(templateDir, dest);
217
+ await this.#linkIntoDocuments(dest);
217
218
 
218
219
  this.#logger.info(
219
220
  `Knowledge base initialized at ${dest}\n\nNext steps:\n 1. cd ${dest} && npx apm install\n 2. claude\n 3. Run the person-identify skill to populate your identity`,
@@ -221,6 +222,31 @@ export class KBManager {
221
222
  return { ok: true, value: { dest } };
222
223
  }
223
224
 
225
+ /**
226
+ * Create a navigation symlink at `~/Documents/<name>` pointing to the KB.
227
+ * The KB data itself stays under the XDG data home, outside TCC-protected
228
+ * folders — this is only a convenience pointer so the KB is easy to find and
229
+ * open from Finder. Best-effort: a pre-existing entry is left untouched, and
230
+ * any failure (e.g. macOS denying write access to `~/Documents`) is logged,
231
+ * never fatal, because the KB is already provisioned at `dest`.
232
+ * @param {string} dest - Absolute path to the provisioned KB.
233
+ * @returns {Promise<void>}
234
+ */
235
+ async #linkIntoDocuments(dest) {
236
+ const link = join(homedir(), "Documents", basename(dest));
237
+ if (await this.#exists(link)) {
238
+ this.#logger.info(` Skipped ${link}: already exists`);
239
+ return;
240
+ }
241
+ try {
242
+ await this.#ensureDir(dirname(link));
243
+ await this.#fs.symlink(dest, link, "dir");
244
+ this.#logger.info(` Linked ${link} -> ${dest}`);
245
+ } catch (err) {
246
+ this.#logger.info(` Could not link into ~/Documents: ${err.message}`);
247
+ }
248
+ }
249
+
224
250
  /**
225
251
  * Update an existing knowledge base with the latest bundled files.
226
252
  * @param {string} targetPath
@@ -14,16 +14,18 @@ single briefing.
14
14
 
15
15
  ## Priorities
16
16
 
17
- `Knowledge/Priorities/` is the backbone of every briefing. Read it each wake (it
18
- is also listed under Inputs) and frame the whole briefing around what advances or
19
- threatens the user's priorities.
17
+ `Knowledge/Priorities/` is the backbone of every briefing. Read it and
18
+ `Knowledge/Conditions/` (the live constraints that shape how priorities are
19
+ pursued see Operating Context in CLAUDE.md) each wake (both are also listed
20
+ under Inputs) and frame the whole briefing around what advances or threatens the
21
+ user's priorities.
20
22
 
21
23
  - **Always consider them.** Tie the schedule, the top actions, and the pipeline
22
24
  back to the priority each one serves.
23
25
  - **Always escalate risks.** Consolidate every `## Priority Watch` flag from the
24
26
  sibling triage files — plus anything you find in your own reads — into a
25
- `## Priority Watch` section in the briefing, each item naming the priority, the
26
- evidence, and the risk. A signal that could contradict, block, or slow a
27
+ `## Priority Watch` section in the briefing, each item naming the priority,
28
+ the evidence, and the risk. A signal that could contradict, block, or slow a
27
29
  priority is the most important thing the briefing surfaces.
28
30
 
29
31
  ## Inputs
@@ -37,7 +39,7 @@ authoritative current-state summaries:
37
39
  - `~/.cache/fit/outpost/state/recruiter_triage.md`
38
40
  - `~/.cache/fit/outpost/state/head_hunter_triage.md`
39
41
 
40
- Plus directly: `Knowledge/Priorities/`, `Drafts/`,
42
+ Plus directly: `Knowledge/Priorities/`, `Knowledge/Conditions/`, `Drafts/`,
41
43
  `~/.cache/fit/outpost/apple_calendar/`, and unchecked `- [ ]` items in
42
44
  `Knowledge/`.
43
45
 
@@ -64,7 +66,7 @@ and "Still Outstanding".
64
66
 
65
67
  ## Output
66
68
 
67
- ```
69
+ ```text
68
70
  Decision: {morning/evening} briefing — {key insight about today}
69
71
  Action: Created Briefings/{YYYY-MM-DD}-{morning|evening}.md
70
72
  ```
@@ -18,11 +18,13 @@ recordings.
18
18
 
19
19
  ## Priorities
20
20
 
21
- At the start of every wake, before acting, read `Knowledge/Priorities/`. The
22
- user's priorities are the lens for all your work this wake.
21
+ At the start of every wake, before acting, read `Knowledge/Priorities/` and
22
+ `Knowledge/Conditions/` (which constrains them see Operating Context in
23
+ CLAUDE.md). The user's priorities are the lens for all your work this wake.
23
24
 
24
25
  - **Always consider them.** Weigh each action against whether it advances a
25
- priority, and favour work that does.
26
+ priority, and favour work that does. Let the active conditions shape how you
27
+ act on it.
26
28
  - **Always flag risks.** When you encounter a chat, email, transcript, or any
27
29
  other signal that could **contradict, block, or slow** a priority, record it
28
30
  under a `## Priority Watch` heading in your triage report — name the priority,
@@ -53,7 +55,7 @@ over **anarlog-process** (catch-up work).
53
55
 
54
56
  After acting, emit exactly:
55
57
 
56
- ```
58
+ ```text
57
59
  Decision: {what you observed and why you chose this action}
58
60
  Action: {what you did, e.g. "meeting-prep for 2pm with Sarah Chen"}
59
61
  Priority Watch: {priority at risk + one-line why, or "none"}
@@ -21,11 +21,13 @@ benchmark promising matches, and write prospect notes for the user to review.
21
21
 
22
22
  ## Priorities
23
23
 
24
- At the start of every wake, before acting, read `Knowledge/Priorities/`. The
25
- user's priorities are the lens for all your work this wake.
24
+ At the start of every wake, before acting, read `Knowledge/Priorities/` and
25
+ `Knowledge/Conditions/` (which constrains them see Operating Context in
26
+ CLAUDE.md). The user's priorities are the lens for all your work this wake.
26
27
 
27
28
  - **Always consider them.** Weigh each action against whether it advances a
28
- priority, and favour work that does.
29
+ priority, and favour work that does. Let the active conditions shape how you
30
+ act on it.
29
31
  - **Always flag risks.** When you encounter a chat, email, transcript, or any
30
32
  other signal that could **contradict, block, or slow** a priority, record it
31
33
  under a `## Priority Watch` heading in your triage report — name the priority,
@@ -63,7 +65,7 @@ wake — the chief-of-staff reads it.
63
65
 
64
66
  ## Output
65
67
 
66
- ```
68
+ ```text
67
69
  Decision: {source chosen and why}
68
70
  Action: {what was scanned, e.g. "scanned HN Who Wants to Be Hired March 2026, 47 posts"}
69
71
  Prospects: {N} new ({strong} strong, {moderate} moderate), {total} total
@@ -16,11 +16,13 @@ you process new data into the knowledge graph and keep everything organized.
16
16
 
17
17
  ## Priorities
18
18
 
19
- At the start of every wake, before acting, read `Knowledge/Priorities/`. The
20
- user's priorities are the lens for all your work this wake.
19
+ At the start of every wake, before acting, read `Knowledge/Priorities/` and
20
+ `Knowledge/Conditions/` (which constrains them see Operating Context in
21
+ CLAUDE.md). The user's priorities are the lens for all your work this wake.
21
22
 
22
23
  - **Always consider them.** Weigh each action against whether it advances a
23
- priority, and favour work that does.
24
+ priority, and favour work that does. Let the active conditions shape how you
25
+ act on it.
24
26
  - **Always flag risks.** When you encounter a chat, email, transcript, or any
25
27
  other signal that could **contradict, block, or slow** a priority, record it
26
28
  under a `## Priority Watch` heading in your triage report — name the priority,
@@ -31,18 +33,20 @@ user's priorities are the lens for all your work this wake.
31
33
 
32
34
  Assess what needs processing:
33
35
 
34
- 1. Check for unprocessed synced files (mail and calendar data):
36
+ 1. Check for unprocessed synced files (mail and calendar data):
35
37
 
36
- node .claude/skills/extract-entities/scripts/state.mjs check
38
+ ```text
39
+ node .claude/skills/extract-entities/scripts/state.mjs check
40
+ ```
37
41
 
38
- 2. Count existing knowledge graph entities:
42
+ 2. Count existing knowledge graph entities:
39
43
 
40
- ls Knowledge/People/ Knowledge/Organizations/ Knowledge/Projects/
41
- Knowledge/Topics/ Knowledge/Priorities/ 2>/dev/null | wc -l
44
+ ls Knowledge/People/ Knowledge/Organizations/ Knowledge/Projects/
45
+ Knowledge/Topics/ Knowledge/Priorities/ 2>/dev/null | wc -l
42
46
 
43
47
  Write triage results to `~/.cache/fit/outpost/state/librarian_triage.md`:
44
48
 
45
- ```
49
+ ```text
46
50
  # Knowledge Triage — {YYYY-MM-DD HH:MM}
47
51
  ## Pending Processing
48
52
  - {count} unprocessed synced files
@@ -64,7 +68,7 @@ Choose the most valuable action:
64
68
 
65
69
  After acting, output exactly:
66
70
 
67
- ```
71
+ ```text
68
72
  Decision: {what you observed and why you chose this action}
69
73
  Action: {what you did, e.g. "extract-entities on 7 files"}
70
74
  Priority Watch: {priority at risk + one-line why, or "none"}
@@ -17,11 +17,13 @@ and Teams, triage what's new, take the most valuable action.
17
17
 
18
18
  ## Priorities
19
19
 
20
- At the start of every wake, before acting, read `Knowledge/Priorities/`. The
21
- user's priorities are the lens for all your work this wake.
20
+ At the start of every wake, before acting, read `Knowledge/Priorities/` and
21
+ `Knowledge/Conditions/` (which constrains them see Operating Context in
22
+ CLAUDE.md). The user's priorities are the lens for all your work this wake.
22
23
 
23
24
  - **Always consider them.** Weigh each action against whether it advances a
24
- priority, and favour work that does.
25
+ priority, and favour work that does. Let the active conditions shape how you
26
+ act on it.
25
27
  - **Always flag risks.** When you encounter a chat, email, transcript, or any
26
28
  other signal that could **contradict, block, or slow** a priority, record it
27
29
  under a `## Priority Watch` heading in your triage report — name the priority,
@@ -54,7 +56,7 @@ email only.
54
56
 
55
57
  After acting, emit exactly:
56
58
 
57
- ```
59
+ ```text
58
60
  Decision: {what you observed and why you chose this action}
59
61
  Action: {what you did, e.g. "draft-emails for thread 123"}
60
62
  Priority Watch: {priority at risk + one-line why, or "none"}
@@ -22,11 +22,13 @@ assessment and recommendation references the standard.
22
22
 
23
23
  ## Priorities
24
24
 
25
- At the start of every wake, before acting, read `Knowledge/Priorities/`. The
26
- user's priorities are the lens for all your work this wake.
25
+ At the start of every wake, before acting, read `Knowledge/Priorities/` and
26
+ `Knowledge/Conditions/` (which constrains them see Operating Context in
27
+ CLAUDE.md). The user's priorities are the lens for all your work this wake.
27
28
 
28
29
  - **Always consider them.** Weigh each action against whether it advances a
29
- priority, and favour work that does.
30
+ priority, and favour work that does. Let the active conditions shape how you
31
+ act on it.
30
32
  - **Always flag risks.** When you encounter a chat, email, transcript, or any
31
33
  other signal that could **contradict, block, or slow** a priority, record it
32
34
  under a `## Priority Watch` heading in your triage report — name the priority,
@@ -60,11 +62,12 @@ screen > sync. Stage 3 **never** triggers automatically — only on user request
60
62
 
61
63
  Triage state goes to `~/.cache/fit/outpost/state/recruiter_triage.md` every wake
62
64
  (the chief-of-staff reads it): needs-action by stage, recently processed
63
- candidates, pipeline totals by stage/track, aggregate diversity, retention flags.
65
+ candidates, pipeline totals by stage/track, aggregate diversity, retention
66
+ flags.
64
67
 
65
68
  ## Output
66
69
 
67
- ```
70
+ ```text
68
71
  Decision: {observation and chosen action}
69
72
  Action: {e.g. "req-screen for John Smith against J060 forward-deployed"}
70
73
  Stage: {1 | 2 | sync | erasure}
@@ -101,8 +101,8 @@ interactions.
101
101
  #### 5. Load type-specific context
102
102
 
103
103
  **Interviews:** read `Knowledge/Candidates/{Name}/{brief,screening,panel}.md`,
104
- look up the `Req` field's matching `Knowledge/Roles/*.md`, and load standard
105
- expectations:
104
+ look up the `Req` field's matching `Knowledge/Roles/*.md` file (check the
105
+ `**Status:**` field for context), and load standard expectations:
106
106
 
107
107
  ```bash
108
108
  bunx fit-pathway job {discipline} {level} --track={track}
@@ -6,7 +6,7 @@ Reference for `anarlog-follow` Phases 2 and 3.
6
6
 
7
7
  ### For interviews
8
8
 
9
- ```
9
+ ```text
10
10
  Following: {Title}
11
11
  Type: {Interview type}
12
12
  Candidate: {Name} — {current role} at {employer}
@@ -27,7 +27,7 @@ Watching for: {specific signals at this interview stage}
27
27
 
28
28
  ### For general meetings
29
29
 
30
- ```
30
+ ```text
31
31
  Following: {Title}
32
32
  Attendees: {names with roles}
33
33
 
@@ -66,7 +66,7 @@ Suggested topics:
66
66
 
67
67
  Output **only when actionable**. Each nudge: 1–3 lines max.
68
68
 
69
- ```
69
+ ```text
70
70
  Probe deeper: {Name} mentioned {topic} — ask for a specific example
71
71
  Gap: screening flagged {skill} as uncertain. Try: "{question}"
72
72
  Confirmed: {Name} demonstrated {skill} at {level} — "{brief quote}"
@@ -46,9 +46,11 @@ Run this skill:
46
46
  ### Step 0 — Validate the session
47
47
 
48
48
  1. Confirm the session directory exists:
49
- ```
49
+
50
+ ```text
50
51
  ~/Library/Application Support/anarlog/sessions/{uuid}/
51
52
  ```
53
+
52
54
  2. Confirm `transcript.json` exists and has at least one transcript with words.
53
55
  3. Read `_meta.json` to get the session title for context.
54
56
 
@@ -132,7 +134,8 @@ json.dump(data, open(path, 'w'), indent=2)
132
134
  ```
133
135
 
134
136
  4. Print a summary:
135
- ```
137
+
138
+ ```text
136
139
  Trimmed: {title}
137
140
  Before: {original_words} words, {original_duration}
138
141
  After: {new_words} words, {new_duration}
@@ -147,11 +150,14 @@ people who did not consent to being recorded. The full audio file must be
147
150
  deleted to respect participant privacy.
148
151
 
149
152
  1. Delete the audio file:
153
+
150
154
  ```bash
151
155
  rm "~/Library/Application Support/anarlog/sessions/{uuid}/audio.mp3"
152
156
  ```
157
+
153
158
  2. Confirm deletion and inform the user:
154
- ```
159
+
160
+ ```text
155
161
  Audio deleted: audio.mp3 removed (recording contained unconsented content beyond the meeting)
156
162
  ```
157
163
 
@@ -50,7 +50,8 @@ before deciding whether to invest interview time.
50
50
  - [ ] Verdict class matches the overall assessment.
51
51
  - [ ] Report fits on a single A4 page (browser print preview).
52
52
  - [ ] CSS is inlined in the `<style>` block.
53
- - [ ] Footer shows the author name and role from `~/.cache/fit/outpost/state/identity.md`.
53
+ - [ ] Footer shows the author name and role from
54
+ `~/.cache/fit/outpost/state/identity.md`.
54
55
  - [ ] Written as if the candidate will read it; no special-category data.
55
56
 
56
57
  </do_confirm_checklist>
@@ -61,7 +62,7 @@ before deciding whether to invest interview time.
61
62
 
62
63
  Read whatever exists for the candidate:
63
64
 
64
- ```
65
+ ```text
65
66
  Knowledge/Candidates/{Name}/brief.md # required
66
67
  Knowledge/Candidates/{Name}/screening.md # if produced by req-screen
67
68
  Knowledge/Candidates/{Name}/interview-*.md # if produced by req-assess
@@ -118,7 +119,7 @@ preview overflows, cut content.
118
119
 
119
120
  Save the completed HTML to:
120
121
 
121
- ```
122
+ ```text
122
123
  Drafts/{Recipient}-{CandidateSurname}-Report.html
123
124
  ```
124
125
 
@@ -11,8 +11,8 @@ teammates syncing the same filesystem can see what changed and why.
11
11
 
12
12
  This tracks **graph content** — notes under `Knowledge/People/`,
13
13
  `Organizations/`, `Projects/`, `Topics/`, `Candidates/`, `Priorities/`, and the
14
- other subdirectories. It does **not** track changes to instructions (`CLAUDE.md`,
15
- agents, skills) — that is the `upstream-instructions` skill's job.
14
+ other subdirectories. It does **not** track changes to instructions
15
+ (`CLAUDE.md`, agents, skills) — that is the `upstream-instructions` skill's job.
16
16
 
17
17
  ## Trigger
18
18
 
@@ -40,16 +40,16 @@ agents, skills) — that is the `upstream-instructions` skill's job.
40
40
 
41
41
  ## Ethics
42
42
 
43
- `Knowledge/` is shared with the team. Every entry obeys the KB's integrity rules:
44
- objective and factual, work-relevant, no personal judgments. Assume the person a
45
- note is about will read its changelog entry. Describe **what changed in the
46
- graph**, not opinions about the people in it.
43
+ `Knowledge/` is shared with the team. Every entry obeys the KB's integrity
44
+ rules: objective and factual, work-relevant, no personal judgments. Assume the
45
+ person a note is about will read its changelog entry. Describe
46
+ **what changed in the graph**, not opinions about the people in it.
47
47
 
48
48
  <do_confirm_checklist goal="Verify the changelog is accurate and shareable">
49
49
 
50
50
  - [ ] Exactly one `Knowledge/CHANGELOG.md`; no stray per-folder changelogs.
51
- - [ ] Every entry names its **Scope** — the specific note(s) or folder(s) touched,
52
- by full path.
51
+ - [ ] Every entry names its **Scope** — the specific note(s) or folder(s)
52
+ touched, by full path.
53
53
  - [ ] Each entry has **Who** (author, from identity), **What**, and **Why**.
54
54
  - [ ] Descriptions are specific enough to be useful (not "updated some notes").
55
55
  - [ ] Dates are the date the change was actually made, not guessed.
@@ -104,8 +104,8 @@ Scope lists every note touched.
104
104
 
105
105
  ### 4. Write the changelog
106
106
 
107
- Create or update `Knowledge/CHANGELOG.md` (newest first). Group entries under one
108
- heading per day; one bullet per logical change:
107
+ Create or update `Knowledge/CHANGELOG.md` (newest first). Group entries under
108
+ one heading per day; one bullet per logical change:
109
109
 
110
110
  ```markdown
111
111
  # Knowledge Changelog
@@ -32,18 +32,18 @@ Run when the user asks to create a presentation, slide deck, or pitch deck.
32
32
 
33
33
  ## Workflow
34
34
 
35
- 1. Check `Knowledge/` for relevant context about the company, product, team,
36
- etc.
37
- 2. Ensure Playwright is installed:
38
- `bun install playwright && bunx playwright install chromium`
39
- 3. Create an HTML file at `/tmp/outpost-presentation.html` with slides
40
- (1280x720px each)
41
- 4. Include the required CSS from [references/slide.css](references/slide.css)
42
- 5. Run the conversion script:
35
+ 1. Check `Knowledge/` for relevant context about the company, product, team,
36
+ etc.
37
+ 2. Ensure Playwright is installed:
38
+ `bun install playwright && bunx playwright install chromium`
39
+ 3. Create an HTML file at `/tmp/outpost-presentation.html` with slides
40
+ (1280x720px each)
41
+ 4. Include the required CSS from [references/slide.css](references/slide.css)
42
+ 5. Run the conversion script:
43
43
 
44
44
  node scripts/convert-to-pdf.mjs
45
45
 
46
- 6. Tell the user: "Your presentation is ready at ~/Desktop/presentation.pdf"
46
+ 6. Tell the user: "Your presentation is ready at ~/Desktop/presentation.pdf"
47
47
 
48
48
  **Do NOT show HTML code to the user. Just create the PDF and deliver it.**
49
49
 
@@ -82,28 +82,29 @@ selecting/copying text on a slide, and typing into overlay tools (e.g. the
82
82
  2. **No click-to-advance.** Do NOT add click regions on the slide/stage that
83
83
  navigate (e.g. "click left/right third"). They fire on the mouse-up that ends
84
84
  a text-selection drag and jump the slide unexpectedly.
85
- 3. **No spacebar, PageUp/PageDown, or other global key bindings.** Space conflicts
86
- with typing in overlay inputs; the rest are redundant and surprising.
87
- 4. **A progress indicator may be clickable**, but it must live in the footer/chrome
88
- and never overlap slide content.
85
+ 3. **No spacebar, PageUp/PageDown, or other global key bindings.** Space
86
+ conflicts with typing in overlay inputs; the rest are redundant and
87
+ surprising.
88
+ 4. **A progress indicator may be clickable**, but it must live in the
89
+ footer/chrome and never overlap slide content.
89
90
  5. **Expose `window.deckGoto(index)`** (0-based) right after the slide-show
90
- function, so review/overlay tools can jump to a slide without simulating clicks
91
- or keys:
91
+ function, so review/overlay tools can jump to a slide without simulating
92
+ clicks or keys:
92
93
 
93
94
  function go(n) { /* ...show slide n... */ }
94
95
  window.deckGoto = go;
95
96
 
96
- 6. **Keep the hint honest** — the on-screen nav hint should read `← → to navigate`
97
- (don't advertise click/space).
97
+ 6. **Keep the hint honest** — the on-screen nav hint should read
98
+ `← → to navigate` (don't advertise click/space).
98
99
  7. **Use stable structural hooks.** Make each slide one element with class
99
100
  `.slide`, and put the slide-number label (if any) in a `.slide-num` element.
100
101
  The review overlay defaults to these selectors to detect and index slides.
101
102
 
102
- These rules keep decks compatible with the **`deck-review`** skill, which installs
103
- the `slide-annotator.js` review overlay (highlight text on a slide → sidecar JSON
104
- of feedback that an agent acts on). After producing an interactive HTML deck, you
105
- can offer to run `deck-review` to make it reviewable; see that skill for the
106
- install steps and the sidecar JSON schema.
103
+ These rules keep decks compatible with the **`deck-review`** skill, which
104
+ installs the `slide-annotator.js` review overlay (highlight text on a slide →
105
+ sidecar JSON of feedback that an agent acts on). After producing an interactive
106
+ HTML deck, you can offer to run `deck-review` to make it reviewable; see that
107
+ skill for the install steps and the sidecar JSON schema.
107
108
 
108
109
  ## Constraints
109
110
 
@@ -8,9 +8,10 @@ compatibility: Standalone HTML deck opened in a Chromium-based browser (Chrome/E
8
8
 
9
9
  Install the self-contained `slide-annotator.js` overlay onto an HTML deck so the
10
10
  user can **highlight text on a slide and save the feedback as a sidecar JSON**.
11
- Each annotation carries a robust anchor (exact text + surrounding context + slide)
12
- and, once the folder is connected, the resolved **source line, column and context
13
- lines** — so an agent can locate and edit the exact text in small iterations.
11
+ Each annotation carries a robust anchor (exact text + surrounding context +
12
+ slide) and, once the folder is connected, the resolved
13
+ **source line, column and context lines** — so an agent can locate and edit the
14
+ exact text in small iterations.
14
15
 
15
16
  This is the companion to **`deck-create`**: decks produced by `deck-create`
16
17
  already follow the navigation/structure standards this overlay needs, and this
@@ -19,8 +20,8 @@ overlay is designed to drop onto them with one script tag.
19
20
  ## Trigger
20
21
 
21
22
  Run when the user asks to add review / annotation / highlight / comment / markup
22
- capability to a deck, "make this deck reviewable", or to set up a feedback loop on
23
- slides.
23
+ capability to a deck, "make this deck reviewable", or to set up a feedback loop
24
+ on slides.
24
25
 
25
26
  ## Inputs
26
27
 
@@ -46,10 +47,10 @@ slides.
46
47
  - **Slide selector** — each slide is one element with a stable class
47
48
  (default `.slide`). If the deck uses a different class, note it for step 4.
48
49
  - **Navigation hook** — the deck exposes `window.deckGoto(index)` (0-based).
49
- If it has a slideshow function (e.g. `go(n)`) but no hook, add one line right
50
- after it: `window.deckGoto = go;`. Without it the overlay still works (the
51
- panel's *Go* button falls back to `scrollIntoView`), but it can't jump to a
52
- hidden slide precisely.
50
+ If it has a slideshow function (e.g. `go(n)`) but no hook, add one line
51
+ right after it: `window.deckGoto = go;`. Without it the overlay still works
52
+ (the panel's *Go* button falls back to `scrollIntoView`), but it can't jump
53
+ to a hidden slide precisely.
53
54
  - Optionally a slide-number label element (default `.slide-num`) for nicer
54
55
  labels in the panel — purely cosmetic.
55
56
 
@@ -57,8 +58,8 @@ slides.
57
58
  **same directory as the deck**. Resolve `~` to `$HOME`; pass the Write/copy a
58
59
  full path.
59
60
 
60
- 4. **Inject the script tag** immediately before `</body>` (idempotent — skip if a
61
- `slide-annotator` script tag is already present):
61
+ 4. **Inject the script tag** immediately before `</body>` (idempotent — skip if
62
+ a `slide-annotator` script tag is already present):
62
63
 
63
64
  ```html
64
65
  <!-- Review overlay: highlight text on a slide → sidecar JSON. Self-contained, optional. -->
@@ -86,22 +87,30 @@ follow:
86
87
  | Navigation hook | `window.deckGoto(index)` (0-based) | panel "Go" jumps to the right slide |
87
88
  | Arrow-keys-only navigation, **no** click-to-advance / spacebar | — | text selection + typing in the overlay must not move slides |
88
89
 
89
- If a deck violates the last row (has click-to-advance), the overlay's click guard
90
- only suppresses the click that ends a text-selection drag, so it degrades
90
+ If a deck violates the last row (has click-to-advance), the overlay's click
91
+ guard only suppresses the click that ends a text-selection drag, so it degrades
91
92
  gracefully — but the correct fix is to make the deck arrow-keys-only per
92
93
  `deck-create`'s *Navigation & Event Standards*.
93
94
 
94
95
  ## Using the overlay (tell the user)
95
96
 
96
97
  1. Open the deck in Chrome and click **✎ Review** (bottom-left).
97
- 2. **Select text** on a slide → a popover lets you add an optional note → **Add**.
98
- The highlight appears and **autosaves to `localStorage`** immediately.
99
- 3. Click **Connect folder** once and pick the deck's folder. From then on **Save**
100
- writes a real `‹deck›.annotations.json` next to the deck, and the tool reads the
101
- deck's own source to fill in **source line / column / context** for each
102
- highlight. (If the browser blocks folder access on `file://`, **Save**
103
- downloads the JSON instead move it next to the deck.)
104
- 4. Navigation while reviewing is the deck's normal **← / →** (the overlay's own
98
+ 2. **Select text** on a slide → a popover lets you add an optional note →
99
+ **Add**. The highlight appears and **autosaves to `localStorage`**
100
+ immediately.
101
+ 3. Click **Connect folder** once and pick the deck's folder. From then on
102
+ **Save** writes a real `‹deck›.annotations.json` next to the deck, and the
103
+ tool reads the deck's own source to fill in
104
+ **source line / column / context** for each highlight. (If the browser blocks
105
+ folder access on `file://`, **Save** downloads the JSON instead move it
106
+ next to the deck.)
107
+ 4. The connected folder is **remembered across reloads** (the directory handle
108
+ is stored in IndexedDB, keyed per deck). After a reload the tool reconnects
109
+ silently if the browser still grants access; otherwise the button reads
110
+ **Reconnect folder** and a single click re-grants permission without
111
+ re-picking the folder. (Browsers require a user gesture to re-grant, so the
112
+ one click can't be avoided; clearing site data forgets the folder.)
113
+ 5. Navigation while reviewing is the deck's normal **← / →** (the overlay's own
105
114
  keystrokes never leak to the deck).
106
115
 
107
116
  ## Acting on the feedback (the review loop)
@@ -143,14 +152,15 @@ When the user says "work the annotations":
143
152
 
144
153
  ## Removing the overlay (for final delivery)
145
154
 
146
- To hand off a clean presentation, delete the injected `<script src="slide-annotator.js" …>`
147
- line and the `slide-annotator.js` file. Leaving the `window.deckGoto = go;` line in
148
- the deck is harmless.
155
+ To hand off a clean presentation, delete the injected
156
+ `<script src="slide-annotator.js" …>` line and the `slide-annotator.js` file.
157
+ Leaving the `window.deckGoto = go;` line in the deck is harmless.
149
158
 
150
159
  ## Constraints
151
160
 
152
161
  - Keep `slide-annotator.js` **dependency-free and host-agnostic** — it must work
153
162
  on any static HTML page, not just `deck-create` output.
154
- - Edit the tool **here** (`assets/slide-annotator.js`) as the source of truth, then
155
- re-install onto decks. Don't fork per-deck copies with divergent behavior.
163
+ - Edit the tool **here** (`assets/slide-annotator.js`) as the source of truth,
164
+ then re-install onto decks. Don't fork per-deck copies with divergent
165
+ behavior.
156
166
  - Never auto-send or upload annotations anywhere — the sidecar JSON stays local.