@forwardimpact/outpost 3.12.1 → 3.13.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 (85) hide show
  1. package/package.json +3 -2
  2. package/src/kb-manager.js +58 -5
  3. package/src/kb-validator.js +762 -0
  4. package/src/outpost.js +73 -8
  5. package/templates/.claude/agents/chief-of-staff.md +14 -6
  6. package/templates/.claude/agents/concierge.md +9 -2
  7. package/templates/.claude/agents/head-hunter.md +9 -2
  8. package/templates/.claude/agents/librarian.md +11 -4
  9. package/templates/.claude/agents/postman.md +9 -2
  10. package/templates/.claude/agents/recruiter.md +9 -2
  11. package/templates/.claude/skills/anarlog-follow/SKILL.md +53 -29
  12. package/templates/.claude/skills/anarlog-follow/references/sessions.md +52 -0
  13. package/templates/.claude/skills/anarlog-process/SKILL.md +88 -45
  14. package/templates/.claude/skills/anarlog-process/references/extraction.md +19 -11
  15. package/templates/.claude/skills/anarlog-process/references/sessions.md +92 -58
  16. package/templates/.claude/skills/anarlog-process/scripts/scan.mjs +404 -163
  17. package/templates/.claude/skills/candidate-report/SKILL.md +12 -9
  18. package/templates/.claude/skills/changelog/SKILL.md +106 -56
  19. package/templates/.claude/skills/deck-create/SKILL.md +60 -2
  20. package/templates/.claude/skills/deck-review/SKILL.md +4 -1
  21. package/templates/.claude/skills/deck-summarize/SKILL.md +6 -2
  22. package/templates/.claude/skills/deck-summarize/references/brief-template.md +1 -1
  23. package/templates/.claude/skills/doc-collab/SKILL.md +16 -11
  24. package/templates/.claude/skills/doc-create/SKILL.md +6 -3
  25. package/templates/.claude/skills/draft-emails/SKILL.md +31 -25
  26. package/templates/.claude/skills/draft-emails/references/template.md +1 -1
  27. package/templates/.claude/skills/draft-emails/scripts/scan-emails.mjs +14 -8
  28. package/templates/.claude/skills/draft-emails/scripts/send-email.mjs +9 -3
  29. package/templates/.claude/skills/extract-entities/SKILL.md +17 -16
  30. package/templates/.claude/skills/extract-entities/references/TEMPLATES.md +2 -1
  31. package/templates/.claude/skills/extract-entities/references/conditions.md +6 -5
  32. package/templates/.claude/skills/extract-entities/references/links.md +34 -10
  33. package/templates/.claude/skills/extract-entities/references/recruitment.md +15 -10
  34. package/templates/.claude/skills/extract-entities/references/resolution.md +1 -1
  35. package/templates/.claude/skills/extract-entities/references/sources.md +1 -1
  36. package/templates/.claude/skills/extract-entities/references/templates-conditions.md +10 -4
  37. package/templates/.claude/skills/extract-entities/references/templates-people-orgs.md +29 -10
  38. package/templates/.claude/skills/extract-entities/references/templates-priorities.md +8 -2
  39. package/templates/.claude/skills/extract-entities/references/templates-projects-topics.md +19 -7
  40. package/templates/.claude/skills/meeting-prep/SKILL.md +23 -18
  41. package/templates/.claude/skills/organize-files/SKILL.md +3 -0
  42. package/templates/.claude/skills/person-identify/SKILL.md +58 -10
  43. package/templates/.claude/skills/person-identify/scripts/identify.sh +110 -11
  44. package/templates/.claude/skills/person-lookup/SKILL.md +8 -3
  45. package/templates/.claude/skills/person-lookup/scripts/lookup.sh +27 -1
  46. package/templates/.claude/skills/req-assess/SKILL.md +19 -11
  47. package/templates/.claude/skills/req-assess/references/interview-template.md +6 -1
  48. package/templates/.claude/skills/req-assess/references/panel-template.md +5 -1
  49. package/templates/.claude/skills/req-bundle/SKILL.md +164 -0
  50. package/templates/.claude/skills/req-bundle/references/matching.md +70 -0
  51. package/templates/.claude/skills/req-bundle/references/pdf-structure.md +74 -0
  52. package/templates/.claude/skills/req-bundle/scripts/split-bundle.mjs +377 -0
  53. package/templates/.claude/skills/req-decide/SKILL.md +26 -18
  54. package/templates/.claude/skills/req-decide/references/template.md +2 -2
  55. package/templates/.claude/skills/req-forget/SKILL.md +39 -22
  56. package/templates/.claude/skills/req-forget/references/classify.md +12 -10
  57. package/templates/.claude/skills/req-forget/references/locations.md +27 -22
  58. package/templates/.claude/skills/req-forget/references/report-template.md +23 -15
  59. package/templates/.claude/skills/req-scan/SKILL.md +6 -3
  60. package/templates/.claude/skills/req-scan/references/template.md +11 -1
  61. package/templates/.claude/skills/req-screen/SKILL.md +78 -34
  62. package/templates/.claude/skills/req-screen/references/rubric.md +38 -42
  63. package/templates/.claude/skills/req-screen/references/scoring.md +79 -0
  64. package/templates/.claude/skills/req-screen/references/template.md +26 -14
  65. package/templates/.claude/skills/req-track/SKILL.md +44 -44
  66. package/templates/.claude/skills/req-track/references/fields.md +18 -15
  67. package/templates/.claude/skills/req-track/references/overlays.md +42 -0
  68. package/templates/.claude/skills/req-track/references/signals.md +2 -2
  69. package/templates/.claude/skills/req-track/references/templates.md +28 -27
  70. package/templates/.claude/skills/req-workday/SKILL.md +49 -20
  71. package/templates/.claude/skills/req-workday/references/brief.md +81 -0
  72. package/templates/.claude/skills/req-workday/references/templates.md +6 -73
  73. package/templates/.claude/skills/req-workday/references/xlsx-format.md +19 -0
  74. package/templates/.claude/skills/req-workday/scripts/parse-workday.mjs +96 -20
  75. package/templates/.claude/skills/send-chat/SKILL.md +11 -11
  76. package/templates/.claude/skills/sync-apple-calendar/SKILL.md +3 -0
  77. package/templates/.claude/skills/sync-apple-mail/SKILL.md +3 -0
  78. package/templates/.claude/skills/sync-teams/SKILL.md +3 -0
  79. package/templates/.claude/skills/upstream-instructions/SKILL.md +8 -5
  80. package/templates/.claude/skills/upstream-instructions/references/examples.md +3 -3
  81. package/templates/CLAUDE.md +96 -87
  82. package/templates/MIGRATION.md +359 -0
  83. package/templates/registry.yaml +25 -0
  84. package/templates/.claude/skills/anarlog-follow/scripts/follow.mjs +0 -243
  85. package/templates/.claude/skills/anarlog-trim/SKILL.md +0 -186
package/src/outpost.js CHANGED
@@ -7,7 +7,7 @@
7
7
  // fit-outpost init [name] Initialize a knowledge base by name (default: Team)
8
8
  // fit-outpost update [path] Update KB with latest CLAUDE.md, agents and skills (defaults to current directory)
9
9
  // fit-outpost stop Gracefully stop daemon and all running agents
10
- // fit-outpost validate Validate agent definitions exist
10
+ // fit-outpost validate [path] Validate agent definitions and knowledge bases
11
11
  // fit-outpost status Show agent status
12
12
  // fit-outpost --help Show this help
13
13
  //
@@ -27,6 +27,7 @@ import { StateManager } from "./state-manager.js";
27
27
  import { AgentRunner } from "./agent-runner.js";
28
28
  import { Scheduler, formatLocalTime } from "./scheduler.js";
29
29
  import { KBManager } from "./kb-manager.js";
30
+ import { validateKnowledgeBase } from "./kb-validator.js";
30
31
  import { SocketServer, requestShutdown, requestWake } from "./socket-server.js";
31
32
  import {
32
33
  readPosture,
@@ -40,12 +41,12 @@ const SHARE_DIR = "/usr/local/share/fit-outpost";
40
41
 
41
42
  /**
42
43
  * Build the CLI definition. This object is byte-identical to the libcli
43
- * definition that the golden capture used. So `--help` and `--version` output
44
- * stays stable.
44
+ * definition that the golden capture used, and `test/golden.test.js`
45
+ * enforces that contract. So `--help` and `--version` output stays stable.
45
46
  * @param {string} version
46
47
  * @returns {object}
47
48
  */
48
- function buildDefinition(version) {
49
+ export function buildDefinition(version) {
49
50
  return {
50
51
  name: "fit-outpost",
51
52
  version,
@@ -72,7 +73,11 @@ function buildDefinition(version) {
72
73
  name: "stop",
73
74
  description: "Gracefully stop daemon and all running agents",
74
75
  },
75
- { name: "validate", description: "Validate agent definitions exist" },
76
+ {
77
+ name: "validate",
78
+ args: "[path]",
79
+ description: "Validate agent definitions and knowledge bases",
80
+ },
76
81
  { name: "status", description: "Show agent status" },
77
82
  {
78
83
  name: "posture",
@@ -83,7 +88,10 @@ function buildDefinition(version) {
83
88
  globalOptions: {
84
89
  help: { type: "boolean", short: "h", description: "Show this help" },
85
90
  version: { type: "boolean", description: "Show version" },
86
- json: { type: "boolean", description: "JSON output (with --help)" },
91
+ json: {
92
+ type: "boolean",
93
+ description: "JSON output (with --help and validate)",
94
+ },
87
95
  },
88
96
  documentation: [
89
97
  {
@@ -375,7 +383,59 @@ export async function run(runtime, version) {
375
383
  return !!found;
376
384
  }
377
385
 
386
+ /**
387
+ * Render one knowledge finding as a report line. Baselined findings warn.
388
+ * @param {import("./kb-validator.js").Finding} f
389
+ * @returns {string}
390
+ */
391
+ function formatFinding(f) {
392
+ const prefix = f.baselined ? "warn: " : "";
393
+ if (f.path !== undefined) {
394
+ return `${prefix}${f.path} ${f.kind}${f.message ? ` — ${f.message}` : ""}`;
395
+ }
396
+ return `${prefix}${f.file}:${f.line} ${f.kind} ${f.link ?? f.property}`;
397
+ }
398
+
399
+ /**
400
+ * Render one KB root's findings as report lines through the logger.
401
+ * @param {string} root - Absolute KB root path.
402
+ * @param {import("./kb-validator.js").Finding[]} findings
403
+ * @returns {void}
404
+ */
405
+ function reportFindings(root, findings) {
406
+ logger.info(`\nKnowledge base: ${root}`);
407
+ for (const f of findings) logger.info(` ${formatFinding(f)}`);
408
+ if (findings.length === 0) logger.info(" OK");
409
+ }
410
+
411
+ /**
412
+ * Run the knowledge checks over each KB root. With `--json` the merged
413
+ * findings array is the only stdout, so tooling can parse it. A root the
414
+ * validator cannot read (a mistyped path, a malformed registry or
415
+ * baseline) fails with one clean error line instead of a stack trace.
416
+ * @param {string[]} roots - Absolute KB root paths.
417
+ * @returns {Promise<number>} 1 when any finding is not baselined, else 0.
418
+ */
419
+ async function runKnowledgeChecks(roots) {
420
+ const all = [];
421
+ for (const root of roots) {
422
+ let result;
423
+ try {
424
+ result = await validateKnowledgeBase(root, runtime);
425
+ } catch (err) {
426
+ cli.error(`validate failed for ${root}: ${err.message}`);
427
+ return 1;
428
+ }
429
+ if (!values.json) reportFindings(root, result.findings);
430
+ all.push(...result.findings);
431
+ }
432
+ if (values.json) proc.stdout.write(`${JSON.stringify(all)}\n`);
433
+ return all.some((f) => !f.baselined) ? 1 : 0;
434
+ }
435
+
378
436
  async function validate() {
437
+ if (args[0]) return runKnowledgeChecks([expandPath(args[0])]);
438
+
379
439
  const config = await loadConfig();
380
440
  const agents = Object.entries(config.agents || {});
381
441
  if (agents.length === 0) {
@@ -391,7 +451,12 @@ export async function run(runtime, version) {
391
451
  }
392
452
 
393
453
  logger.info(errors > 0 ? `\n${errors} error(s).` : "\nAll OK.");
394
- return errors > 0 ? 1 : 0;
454
+ // The logger writes to stderr, so with --json the findings array stays
455
+ // the only stdout even on the no-path form.
456
+ const kbRoots = [
457
+ ...new Set(agents.map(([, a]) => a.kb).filter(Boolean)),
458
+ ].map(expandPath);
459
+ return Math.max(errors ? 1 : 0, await runKnowledgeChecks(kbRoots));
395
460
  }
396
461
 
397
462
  // --- CLI entry point -------------------------------------------------------
@@ -399,7 +464,7 @@ export async function run(runtime, version) {
399
464
  const parsed = cli.parse(proc.argv.slice(2));
400
465
  if (!parsed) return 0;
401
466
 
402
- const { positionals } = parsed;
467
+ const { positionals, values } = parsed;
403
468
  const [command, ...args] = positionals;
404
469
 
405
470
  await fs.mkdir(OUTPOST_HOME, { recursive: true });
@@ -12,10 +12,17 @@ You are the chief of staff. You are the user's executive assistant. On each
12
12
  wake, synthesize what matters across email, calendar, and the knowledge graph
13
13
  into a single briefing.
14
14
 
15
+ ## Tiers
16
+
17
+ Read: every tier present
18
+ Write: none (the output is personal `Briefings/`)
19
+ Stamp the frontmatter standard per CLAUDE.md on every note you write.
20
+ Aggregate outputs over narrower-tier sources go to `0-Draft/`.
21
+
15
22
  ## Priorities
16
23
 
17
- `Knowledge/Priorities/` is the backbone of every briefing. Read it and
18
- `Knowledge/Conditions/` on each wake. `Knowledge/Conditions/` holds the live
24
+ `Priorities/` notes in every tier present are the backbone of every briefing.
25
+ Read them and `Conditions/` on each wake. Conditions hold the live
19
26
  constraints that shape how you pursue the priorities. See Operating Context in
20
27
  CLAUDE.md. The Inputs section below also lists both folders. Frame the whole
21
28
  briefing around what advances or threatens the user's priorities.
@@ -39,9 +46,9 @@ authoritative current-state summaries:
39
46
  - `~/.cache/fit/outpost/state/recruiter_triage.md`
40
47
  - `~/.cache/fit/outpost/state/head_hunter_triage.md`
41
48
 
42
- Also read these directly: `Knowledge/Priorities/`, `Knowledge/Conditions/`,
43
- `Drafts/`, `~/.cache/fit/outpost/apple_calendar/`, and unchecked `- [ ]` items
44
- in `Knowledge/`.
49
+ Also read these directly: `Priorities/` and `Conditions/` in every tier,
50
+ `0-Draft/`, `~/.cache/fit/outpost/apple_calendar/`, and unchecked `- [ ]`
51
+ items across the tiers.
45
52
 
46
53
  ## Routing
47
54
 
@@ -51,7 +58,8 @@ in `Knowledge/`.
51
58
  | Noon or later | `Briefings/{YYYY-MM-DD}-evening.md` |
52
59
 
53
60
  A briefing covers: today's schedule with prep status, top three priority actions
54
- linked to `[[Priorities/...]]`, priority progress, a **Priority Watch** section
61
+ linked with tier-prefixed links (`[[3-Team/Priorities/...]]`), priority
62
+ progress, a **Priority Watch** section
55
63
  that consolidates the priority risks the agents flagged, inbox snapshot
56
64
  (urgent / awaiting reply), open commitments, recruitment pipeline summary, and a
57
65
  heads-up section. Evening briefings replace "Priority Actions" with "What
@@ -16,10 +16,17 @@ You are the concierge. You are the user's scheduling assistant. On each wake,
16
16
  keep the calendar current, prepare for upcoming meetings, and process completed
17
17
  meeting recordings.
18
18
 
19
+ ## Tiers
20
+
21
+ Read: every tier present
22
+ Write: `3-Team`
23
+ Stamp the frontmatter standard per CLAUDE.md on every note you write.
24
+ Aggregate outputs over narrower-tier sources go to `0-Draft/`.
25
+
19
26
  ## Priorities
20
27
 
21
- At the start of every wake, before you act, read `Knowledge/Priorities/` and
22
- `Knowledge/Conditions/`. The conditions constrain the priorities. See Operating
28
+ At the start of every wake, before you act, read `Priorities/` and `Conditions/`
29
+ in every tier present. The conditions constrain the priorities. See Operating
23
30
  Context in CLAUDE.md. The user's priorities are the lens for all your work this
24
31
  wake.
25
32
 
@@ -19,10 +19,17 @@ Benchmark promising matches. Write prospect notes for the user to review.
19
19
 
20
20
  **You never contact candidates.** Outreach is the user's call.
21
21
 
22
+ ## Tiers
23
+
24
+ Read: every tier present
25
+ Write: `2-Confidential`
26
+ Stamp the frontmatter standard per CLAUDE.md on every note you write.
27
+ Aggregate outputs over narrower-tier sources go to `0-Draft/`.
28
+
22
29
  ## Priorities
23
30
 
24
- At the start of every wake, before you act, read `Knowledge/Priorities/` and
25
- `Knowledge/Conditions/`. The conditions constrain the priorities. See Operating
31
+ At the start of every wake, before you act, read `Priorities/` and `Conditions/`
32
+ in every tier present. The conditions constrain the priorities. See Operating
26
33
  Context in CLAUDE.md. The user's priorities are the lens for all your work this
27
34
  wake.
28
35
 
@@ -14,10 +14,17 @@ skills:
14
14
  You are the librarian. You are the user's knowledge curator. On each wake,
15
15
  process new data into the knowledge graph and keep everything organized.
16
16
 
17
+ ## Tiers
18
+
19
+ Read: every tier present
20
+ Write: `3-Team`
21
+ Stamp the frontmatter standard per CLAUDE.md on every note you write.
22
+ Aggregate outputs over narrower-tier sources go to `0-Draft/`.
23
+
17
24
  ## Priorities
18
25
 
19
- At the start of every wake, before you act, read `Knowledge/Priorities/` and
20
- `Knowledge/Conditions/`. The conditions constrain the priorities. See Operating
26
+ At the start of every wake, before you act, read `Priorities/` and `Conditions/`
27
+ in every tier present. The conditions constrain the priorities. See Operating
21
28
  Context in CLAUDE.md. The user's priorities are the lens for all your work this
22
29
  wake.
23
30
 
@@ -42,8 +49,8 @@ Assess what to process:
42
49
 
43
50
  2. Count existing knowledge graph entities:
44
51
 
45
- ls Knowledge/People/ Knowledge/Organizations/ Knowledge/Projects/
46
- Knowledge/Topics/ Knowledge/Priorities/ 2>/dev/null | wc -l
52
+ ls 3-Team/People/ 3-Team/Organizations/ 3-Team/Projects/ 3-Team/Topics/
53
+ 3-Team/Priorities/ 2>/dev/null | wc -l
47
54
 
48
55
  Write triage results to `~/.cache/fit/outpost/state/librarian_triage.md`:
49
56
 
@@ -15,10 +15,17 @@ skills:
15
15
  You are the postman. You are the user's communication gatekeeper. On each wake,
16
16
  sync mail and Teams, triage what is new, and take the most valuable action.
17
17
 
18
+ ## Tiers
19
+
20
+ Read: every tier present
21
+ Write: `0-Draft`
22
+ Stamp the frontmatter standard per CLAUDE.md on every note you write.
23
+ Aggregate outputs over narrower-tier sources go to `0-Draft/`.
24
+
18
25
  ## Priorities
19
26
 
20
- At the start of every wake, before you act, read `Knowledge/Priorities/` and
21
- `Knowledge/Conditions/`. The conditions constrain the priorities. See Operating
27
+ At the start of every wake, before you act, read `Priorities/` and `Conditions/`
28
+ in every tier present. The conditions constrain the priorities. See Operating
22
29
  Context in CLAUDE.md. The user's priorities are the lens for all your work this
23
30
  wake.
24
31
 
@@ -21,10 +21,17 @@ You are the recruiter. You are the user's engineering recruitment specialist.
21
21
  The `fit-pathway` CLI is the single source of truth for "good engineering".
22
22
  Every assessment and recommendation references the standard.
23
23
 
24
+ ## Tiers
25
+
26
+ Read: every tier present
27
+ Write: `2-Confidential`
28
+ Stamp the frontmatter standard per CLAUDE.md on every note you write.
29
+ Aggregate outputs over narrower-tier sources go to `0-Draft/`.
30
+
24
31
  ## Priorities
25
32
 
26
- At the start of every wake, before you act, read `Knowledge/Priorities/` and
27
- `Knowledge/Conditions/`. The conditions constrain the priorities. See Operating
33
+ At the start of every wake, before you act, read `Priorities/` and `Conditions/`
34
+ in every tier present. The conditions constrain the priorities. See Operating
28
35
  Context in CLAUDE.md. The user's priorities are the lens for all your work this
29
36
  wake.
30
37
 
@@ -10,6 +10,9 @@ description: >
10
10
 
11
11
  # Anarlog Follow
12
12
 
13
+ Write tier: none
14
+ Frontmatter: none
15
+
13
16
  Follow a live Anarlog recording. Read the transcript as it grows. Coach the user
14
17
  through the meeting in real time. Gather knowledge-base context once before the
15
18
  session. Then poll the transcript. Provide actionable nudges as new content
@@ -23,16 +26,24 @@ appears.
23
26
 
24
27
  ## Prerequisites
25
28
 
26
- - Anarlog installed. Sessions live at
27
- `~/Library/Application Support/anarlog/sessions/`.
29
+ - Anarlog installed. Meetings live in its local SQLite database (`app.db`).
30
+ Read them only through Anarlog's typed, read-only interfaces. Prefer the
31
+ **Anarlog MCP tools** (`list_meetings`, `get_meeting`,
32
+ `get_meeting_transcript`) when the MCP server is connected. Fall back to the
33
+ **`anarlog` CLI with `--json`** otherwise. Never `grep`, crawl `sessions/`,
34
+ or query SQLite directly. See Anarlog's own `AGENTS.md`
35
+ (`~/Library/Application Support/anarlog/AGENTS.md`).
28
36
  - An active or about-to-start session.
29
37
  - A populated knowledge base (attendee / candidate context).
30
38
 
31
39
  ## Inputs
32
40
 
33
- - Live `transcript.json` (it grows during the session).
34
- - `Knowledge/People/`, `Knowledge/Candidates/{Name}/{brief,screening,panel}.md`,
35
- `Knowledge/Roles/`, `Knowledge/Organizations/`, `Knowledge/Projects/`.
41
+ - The live meeting transcript, via `get_meeting_transcript` (MCP) or
42
+ `anarlog --json meetings transcript <id>` (CLI). See
43
+ [references/sessions.md](references/sessions.md) for both interfaces.
44
+ - `3-Team/People/`,
45
+ `2-Confidential/Candidates/{Name}/{brief,screening,panel}.md`,
46
+ `2-Confidential/Roles/`, `3-Team/Organizations/`, `3-Team/Projects/`.
36
47
  - `~/.cache/fit/outpost/apple_calendar/*.json` for context.
37
48
 
38
49
  ## Outputs
@@ -62,22 +73,30 @@ appears.
62
73
 
63
74
  #### 1. Find the active session
64
75
 
76
+ No interface exposes a "recording now" signal. The only liveness signal is the
77
+ most recently written `audio.mp3` on disk. This is the one deliberate
78
+ filesystem read in this skill. All content reads go through Anarlog's
79
+ interfaces. The session directory name **is** the meeting ID:
80
+
65
81
  ```bash
66
- node .claude/skills/anarlog-follow/scripts/follow.mjs --detect
82
+ find "$HOME/Library/Application Support/anarlog/sessions" -maxdepth 2 \
83
+ -name "audio.mp3" -exec stat -f "%m %N" {} \; | sort -rn | head -5
67
84
  ```
68
85
 
69
- The script returns the most recently modified session, whether it is live, and
70
- its title. If nothing changed in the last 5 minutes, warn the user. Ask whether
71
- to follow a specific session. If more than one session could be active, confirm
72
- with the user.
86
+ Take the top result's parent directory name as the candidate meeting ID. If
87
+ its mtime is more than 5 minutes old, warn the user. Ask whether to follow a
88
+ specific meeting. If more than one session could be active, confirm with the
89
+ user.
73
90
 
74
- #### 2. Read session metadata
91
+ #### 2. Read meeting metadata
92
+
93
+ MCP: `get_meeting({ meeting_id })`. CLI fallback:
75
94
 
76
95
  ```bash
77
- node .claude/skills/anarlog-follow/scripts/follow.mjs <session-id> --meta
96
+ anarlog --json meetings get <meeting-id>
78
97
  ```
79
98
 
80
- Capture **title**, **created_at**, **participants**.
99
+ Capture **title**, **created_at**, **participants** from `data`.
81
100
 
82
101
  #### 3. Classify the meeting type
83
102
 
@@ -92,8 +111,8 @@ Phase 2 and the dimensions you track in Phase 3.
92
111
  Extract the names from the title and the participant list. For each name:
93
112
 
94
113
  ```bash
95
- rg -l "{name}" Knowledge/People/
96
- rg -l "{name}" Knowledge/Candidates/
114
+ rg -l "{name}" 3-Team/People/
115
+ rg -l "{name}" 2-Confidential/Candidates/
97
116
  ```
98
117
 
99
118
  Read each note you find for role, organization, history, open items, and prior
@@ -101,16 +120,17 @@ interactions.
101
120
 
102
121
  #### 5. Load type-specific context
103
122
 
104
- **Interviews:** read `Knowledge/Candidates/{Name}/{brief,screening,panel}.md`.
105
- Look up the `Req` field's matching `Knowledge/Roles/*.md` file. Check its
106
- `**Status:**` field for context. Then load the standard expectations:
123
+ **Interviews:** read
124
+ `2-Confidential/Candidates/{Name}/{brief,screening,panel}.md`. Look up the `Req`
125
+ field's matching `2-Confidential/Roles/*.md` file. Check its `**Status:**` field
126
+ for context. Then load the standard expectations:
107
127
 
108
128
  ```bash
109
129
  bunx fit-pathway job {discipline} {level} --track={track}
110
130
  ```
111
131
 
112
132
  **General meetings:** read attendee People notes plus referenced
113
- Project/Organization notes. Check open tasks: `rg "{name}" Knowledge/Tasks/`.
133
+ Project/Organization notes. Check open tasks: `rg "{name}" 3-Team/Tasks/`.
114
134
 
115
135
  #### 6. Build the coaching brief
116
136
 
@@ -122,20 +142,24 @@ it to the user.
122
142
 
123
143
  #### 7. Read new transcript content
124
144
 
125
- First read (no `--after`):
126
-
127
- ```bash
128
- node .claude/skills/anarlog-follow/scripts/follow.mjs <session-id>
129
- ```
130
-
131
- Subsequent reads (pass the last word ID):
145
+ MCP: `get_meeting_transcript({ meeting_id, offset, limit: 500 })`. CLI
146
+ fallback:
132
147
 
133
148
  ```bash
134
- node .claude/skills/anarlog-follow/scripts/follow.mjs <session-id> --after <last-word-id>
149
+ anarlog --json meetings transcript <meeting-id> --offset <offset> --limit 500
135
150
  ```
136
151
 
137
- The script returns JSON with grouped text segments, channel labels, and the next
138
- last-word ID.
152
+ First read: `offset` = 0. Each later read: `offset` = the `pagination.total`
153
+ from the previous read. That fetches only the words added since then. When a
154
+ page comes back full and `next_offset < pagination.total`, keep paging with
155
+ `next_offset` until you catch up. Track `total` across reads. It is your next
156
+ offset.
157
+
158
+ `data.words` is a flat array of `{ channel, text, start_ms, end_ms }`. Group
159
+ consecutive words into segments yourself. Start a new segment on a channel
160
+ change or a >3s gap between one word's `end_ms` and the next word's
161
+ `start_ms`. Channel `0` = user. Channel `1`+ = guest(s) (a heuristic, per
162
+ Anarlog's own docs).
139
163
 
140
164
  #### 8. Analyze new content
141
165
 
@@ -0,0 +1,52 @@
1
+ # Anarlog Meeting Data
2
+
3
+ Reference for `anarlog-follow` Phases 1 and 3. Anarlog stores meetings in a
4
+ local SQLite database (`~/Library/Application Support/anarlog/app.db`). Read
5
+ them through Anarlog's typed, read-only interfaces. Its own `AGENTS.md`
6
+ (`~/Library/Application Support/anarlog/AGENTS.md`) is explicit:
7
+
8
+ > Use Anarlog's typed, read-only interfaces for meeting data. Do not use
9
+ > `find`, `grep`, `rg`, filesystem crawling, or direct SQLite queries.
10
+
11
+ **Prefer the MCP tools** when the `anarlog` MCP server is connected. **Fall
12
+ back to the CLI** (`anarlog --json ...`) otherwise. Never guess a meeting ID.
13
+ Phase 1 resolves it from the freshest `audio.mp3` on disk (the one signal
14
+ neither interface exposes). Every other read goes through one of the two
15
+ interfaces below.
16
+
17
+ ## `get_meeting` / `meetings get <id>`
18
+
19
+ MCP: `get_meeting({ meeting_id })`. CLI:
20
+ `anarlog --json meetings get <meeting-id>`.
21
+
22
+ Returns `title`, `created_at`, `participants` (`{ human_id, display_name,
23
+ email, role, job_title, organization_name }`, often sparse), `note`,
24
+ `summaries`, `action_items`. For a live meeting, `note` and `summaries` are
25
+ usually thin or empty. That is expected. They fill in once the meeting ends.
26
+ Use this once per session, in Phase 1 Step 2, to capture the pre-meeting brief
27
+ inputs.
28
+
29
+ ## `get_meeting_transcript` / `meetings transcript <id>`
30
+
31
+ MCP: `get_meeting_transcript({ meeting_id, offset, limit })`. CLI:
32
+ `anarlog --json meetings transcript <meeting-id> --offset <n> --limit <n>`
33
+ (`limit` capped at 500 by both interfaces).
34
+
35
+ ```json
36
+ { "meeting_id": "…", "text": "Yeah, so the overall …",
37
+ "words": [ { "channel": 0, "text": " Yeah,", "start_ms": 0, "end_ms": 400 } ] }
38
+ ```
39
+
40
+ `pagination.total` is the running word count. Use it as the next poll's
41
+ `offset` so you fetch only the words added since the last read. Page with
42
+ `next_offset` when a single poll returns a full page and more remain. Channel
43
+ `0` = user, channel `1`+ = guest(s) — a heuristic, not guaranteed.
44
+
45
+ ## The one filesystem exception: liveness detection
46
+
47
+ Neither interface reports which meeting is currently recording. The only
48
+ signal for that lives on disk: the most recently written `audio.mp3` under
49
+ `~/Library/Application Support/anarlog/sessions/{uuid}/`, where the directory
50
+ name is the meeting ID. This skill touches the filesystem for exactly that one
51
+ lookup (Phase 1 Step 1) and nothing else. Every read of meeting *content*
52
+ goes through `get_meeting` / `get_meeting_transcript`.