@forwardimpact/outpost 3.0.3
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/LICENSE +201 -0
- package/README.md +15 -0
- package/bin/fit-outpost.js +3 -0
- package/config/scheduler.json +34 -0
- package/package.json +63 -0
- package/src/agent-runner.js +189 -0
- package/src/index.js +5 -0
- package/src/kb-manager.js +228 -0
- package/src/outpost.js +417 -0
- package/src/scheduler.js +195 -0
- package/src/socket-server.js +336 -0
- package/src/state-manager.js +126 -0
- package/templates/.claude/agents/chief-of-staff.md +58 -0
- package/templates/.claude/agents/concierge.md +46 -0
- package/templates/.claude/agents/head-hunter.md +57 -0
- package/templates/.claude/agents/librarian.md +60 -0
- package/templates/.claude/agents/postman.md +47 -0
- package/templates/.claude/agents/recruiter.md +63 -0
- package/templates/.claude/settings.json +88 -0
- package/templates/.claude/skills/candidate-report/SKILL.md +139 -0
- package/templates/.claude/skills/candidate-report/references/report-template.html +203 -0
- package/templates/.claude/skills/candidate-report/references/report.css +438 -0
- package/templates/.claude/skills/candidate-report/references/rubric.md +76 -0
- package/templates/.claude/skills/candidate-report/scripts/render-pdf.mjs +48 -0
- package/templates/.claude/skills/deck-create/SKILL.md +75 -0
- package/templates/.claude/skills/deck-create/references/slide.css +35 -0
- package/templates/.claude/skills/deck-create/scripts/convert-to-pdf.mjs +47 -0
- package/templates/.claude/skills/deck-summarize/SKILL.md +139 -0
- package/templates/.claude/skills/deck-summarize/references/brief-template.md +85 -0
- package/templates/.claude/skills/deck-summarize/scripts/extract-pptx.mjs +210 -0
- package/templates/.claude/skills/doc-collab/SKILL.md +112 -0
- package/templates/.claude/skills/doc-create/SKILL.md +105 -0
- package/templates/.claude/skills/doc-create/scripts/convert-to-pdf.mjs +50 -0
- package/templates/.claude/skills/draft-emails/SKILL.md +141 -0
- package/templates/.claude/skills/draft-emails/references/template.md +26 -0
- package/templates/.claude/skills/draft-emails/scripts/scan-emails.mjs +66 -0
- package/templates/.claude/skills/draft-emails/scripts/send-email.mjs +139 -0
- package/templates/.claude/skills/extract-entities/SKILL.md +187 -0
- package/templates/.claude/skills/extract-entities/references/TEMPLATES.md +14 -0
- package/templates/.claude/skills/extract-entities/references/conditions.md +55 -0
- package/templates/.claude/skills/extract-entities/references/content.md +104 -0
- package/templates/.claude/skills/extract-entities/references/links.md +48 -0
- package/templates/.claude/skills/extract-entities/references/recruitment.md +57 -0
- package/templates/.claude/skills/extract-entities/references/resolution.md +71 -0
- package/templates/.claude/skills/extract-entities/references/sources.md +70 -0
- package/templates/.claude/skills/extract-entities/references/templates-conditions.md +36 -0
- package/templates/.claude/skills/extract-entities/references/templates-goals-priorities.md +63 -0
- package/templates/.claude/skills/extract-entities/references/templates-people-orgs.md +67 -0
- package/templates/.claude/skills/extract-entities/references/templates-projects-topics.md +68 -0
- package/templates/.claude/skills/extract-entities/scripts/state.mjs +131 -0
- package/templates/.claude/skills/hyprnote-follow/SKILL.md +174 -0
- package/templates/.claude/skills/hyprnote-follow/references/coaching.md +118 -0
- package/templates/.claude/skills/hyprnote-follow/references/debrief.md +59 -0
- package/templates/.claude/skills/hyprnote-follow/references/meeting-types.md +14 -0
- package/templates/.claude/skills/hyprnote-follow/scripts/follow.mjs +243 -0
- package/templates/.claude/skills/hyprnote-process/SKILL.md +147 -0
- package/templates/.claude/skills/hyprnote-process/references/extraction.md +84 -0
- package/templates/.claude/skills/hyprnote-process/references/sessions.md +81 -0
- package/templates/.claude/skills/hyprnote-process/scripts/scan.mjs +246 -0
- package/templates/.claude/skills/hyprnote-trim/SKILL.md +177 -0
- package/templates/.claude/skills/manage-tasks/SKILL.md +152 -0
- package/templates/.claude/skills/manage-tasks/references/format.md +73 -0
- package/templates/.claude/skills/meeting-prep/SKILL.md +180 -0
- package/templates/.claude/skills/organize-files/SKILL.md +146 -0
- package/templates/.claude/skills/organize-files/scripts/organize-by-type.mjs +105 -0
- package/templates/.claude/skills/organize-files/scripts/summarize.mjs +91 -0
- package/templates/.claude/skills/req-assess/SKILL.md +137 -0
- package/templates/.claude/skills/req-assess/references/interview-template.md +62 -0
- package/templates/.claude/skills/req-assess/references/panel-template.md +117 -0
- package/templates/.claude/skills/req-assess/references/rubric.md +65 -0
- package/templates/.claude/skills/req-decide/SKILL.md +163 -0
- package/templates/.claude/skills/req-decide/references/rubric.md +63 -0
- package/templates/.claude/skills/req-decide/references/template.md +118 -0
- package/templates/.claude/skills/req-forget/SKILL.md +154 -0
- package/templates/.claude/skills/req-forget/references/classify.md +23 -0
- package/templates/.claude/skills/req-forget/references/locations.md +59 -0
- package/templates/.claude/skills/req-forget/references/report-template.md +67 -0
- package/templates/.claude/skills/req-scan/SKILL.md +145 -0
- package/templates/.claude/skills/req-scan/references/fallbacks.md +76 -0
- package/templates/.claude/skills/req-scan/references/filters.md +83 -0
- package/templates/.claude/skills/req-scan/references/sources.md +76 -0
- package/templates/.claude/skills/req-scan/references/state.md +54 -0
- package/templates/.claude/skills/req-scan/references/template.md +36 -0
- package/templates/.claude/skills/req-scan/scripts/state.mjs +396 -0
- package/templates/.claude/skills/req-screen/SKILL.md +151 -0
- package/templates/.claude/skills/req-screen/references/rubric.md +94 -0
- package/templates/.claude/skills/req-screen/references/template.md +91 -0
- package/templates/.claude/skills/req-track/SKILL.md +189 -0
- package/templates/.claude/skills/req-track/references/fields.md +114 -0
- package/templates/.claude/skills/req-track/references/signals.md +42 -0
- package/templates/.claude/skills/req-track/references/statuses.md +32 -0
- package/templates/.claude/skills/req-track/references/templates.md +127 -0
- package/templates/.claude/skills/req-workday/SKILL.md +162 -0
- package/templates/.claude/skills/req-workday/references/field-mapping.md +40 -0
- package/templates/.claude/skills/req-workday/references/status-mapping.md +38 -0
- package/templates/.claude/skills/req-workday/references/templates.md +126 -0
- package/templates/.claude/skills/req-workday/references/xlsx-format.md +56 -0
- package/templates/.claude/skills/req-workday/scripts/parse-workday.mjs +313 -0
- package/templates/.claude/skills/send-chat/SKILL.md +170 -0
- package/templates/.claude/skills/sync-apple-calendar/SKILL.md +145 -0
- package/templates/.claude/skills/sync-apple-calendar/references/SCHEMA.md +80 -0
- package/templates/.claude/skills/sync-apple-calendar/scripts/query.mjs +307 -0
- package/templates/.claude/skills/sync-apple-calendar/scripts/sync.mjs +332 -0
- package/templates/.claude/skills/sync-apple-mail/SKILL.md +151 -0
- package/templates/.claude/skills/sync-apple-mail/references/SCHEMA.md +115 -0
- package/templates/.claude/skills/sync-apple-mail/scripts/parse-emlx.mjs +389 -0
- package/templates/.claude/skills/sync-apple-mail/scripts/sync-helpers.mjs +372 -0
- package/templates/.claude/skills/sync-apple-mail/scripts/sync.mjs +239 -0
- package/templates/.claude/skills/sync-teams/SKILL.md +177 -0
- package/templates/.claude/skills/sync-teams/scripts/idb-reader.mjs +147 -0
- package/templates/.claude/skills/sync-teams/scripts/leveldb-reader.mjs +288 -0
- package/templates/.claude/skills/sync-teams/scripts/sync.mjs +381 -0
- package/templates/.claude/skills/upstream-skill/SKILL.md +130 -0
- package/templates/.claude/skills/upstream-skill/references/examples.md +80 -0
- package/templates/.claude/skills/weekly-update/SKILL.md +141 -0
- package/templates/.claude/skills/weekly-update/references/template.md +55 -0
- package/templates/CLAUDE.md +134 -0
- package/templates/USER.md +3 -0
- package/templates/apm.yml +5 -0
- package/templates/knowledge/Briefings/.gitkeep +0 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Goal and Priority Templates
|
|
2
|
+
|
|
3
|
+
Goals and Priorities are **never auto-created** by `extract-entities`. They are
|
|
4
|
+
set deliberately by the user. These templates are for manual creation only —
|
|
5
|
+
`extract-entities` and `hyprnote-process` only **link to** and **update progress
|
|
6
|
+
on** existing notes.
|
|
7
|
+
|
|
8
|
+
## Priorities
|
|
9
|
+
|
|
10
|
+
```markdown
|
|
11
|
+
# {Priority Name}
|
|
12
|
+
|
|
13
|
+
## About
|
|
14
|
+
{2-3 sentences: what this strategic direction means and why it matters}
|
|
15
|
+
|
|
16
|
+
**Status:** {active|paused|retired}
|
|
17
|
+
**Owner:** [[People/{Person}]]
|
|
18
|
+
**Set:** {YYYY-MM-DD}
|
|
19
|
+
|
|
20
|
+
## What this means
|
|
21
|
+
{Bullet list of concrete implications — what does pursuing this priority look like?}
|
|
22
|
+
|
|
23
|
+
## Goals
|
|
24
|
+
{Time-bound targets that ladder to this priority — backlinks to knowledge/Goals/}
|
|
25
|
+
|
|
26
|
+
## Projects
|
|
27
|
+
- [[Projects/{Project}]] — {relationship}
|
|
28
|
+
|
|
29
|
+
## Key facts
|
|
30
|
+
{substantive facts only — leave empty if none}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Goals
|
|
34
|
+
|
|
35
|
+
```markdown
|
|
36
|
+
# {Goal Name}
|
|
37
|
+
|
|
38
|
+
## Info
|
|
39
|
+
**Priority:** [[Priorities/{Priority}]]
|
|
40
|
+
**Status:** {on track|at risk|off track|achieved|abandoned}
|
|
41
|
+
**Owner:** [[People/{Person}]]
|
|
42
|
+
**Target date:** {YYYY-MM-DD}
|
|
43
|
+
**Set:** {YYYY-MM-DD}
|
|
44
|
+
|
|
45
|
+
## Outcome
|
|
46
|
+
{1-2 sentences: what measurable success looks like}
|
|
47
|
+
|
|
48
|
+
## Blockers
|
|
49
|
+
{Active Conditions that impede this goal — link to knowledge/Conditions/}
|
|
50
|
+
- [[Conditions/{Condition}]] — {impact on this goal}
|
|
51
|
+
|
|
52
|
+
## Projects
|
|
53
|
+
- [[Projects/{Project}]] — {how it contributes}
|
|
54
|
+
|
|
55
|
+
## Progress
|
|
56
|
+
- **{YYYY-MM-DD}**: {Update on progress toward the outcome}
|
|
57
|
+
|
|
58
|
+
## Key facts
|
|
59
|
+
{substantive facts only — leave empty if none}
|
|
60
|
+
|
|
61
|
+
## Risks
|
|
62
|
+
{known risks to achieving this goal — leave empty if none}
|
|
63
|
+
```
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# People and Organization Templates
|
|
2
|
+
|
|
3
|
+
## People
|
|
4
|
+
|
|
5
|
+
```markdown
|
|
6
|
+
# {Full Name}
|
|
7
|
+
|
|
8
|
+
## Info
|
|
9
|
+
**Role:** {role or inferred role with qualifier}
|
|
10
|
+
**Organization:** [[Organizations/{organization}]]
|
|
11
|
+
**Reports to:** [[People/{{Person}}]]
|
|
12
|
+
**Email:** {email}
|
|
13
|
+
**Aliases:** {comma-separated variants}
|
|
14
|
+
**First met:** {YYYY-MM-DD}
|
|
15
|
+
**Last seen:** {YYYY-MM-DD}
|
|
16
|
+
|
|
17
|
+
## Summary
|
|
18
|
+
{2-3 sentences: who they are, why you know them, what you're working on}
|
|
19
|
+
|
|
20
|
+
## Connected to
|
|
21
|
+
- [[Organizations/{Org}]] — works at
|
|
22
|
+
- [[People/{Person}]] — {relationship}
|
|
23
|
+
- [[Projects/{Project}]] — {role}
|
|
24
|
+
|
|
25
|
+
## Activity
|
|
26
|
+
- **{YYYY-MM-DD}** ({meeting|email|voice memo}): {Summary with [[Folder/Name]] links}
|
|
27
|
+
|
|
28
|
+
## Key facts
|
|
29
|
+
{substantive facts only — leave empty if none}
|
|
30
|
+
|
|
31
|
+
## Open items
|
|
32
|
+
{commitments and next steps only — leave empty if none}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Organizations
|
|
36
|
+
|
|
37
|
+
```markdown
|
|
38
|
+
# {Organization Name}
|
|
39
|
+
|
|
40
|
+
## Info
|
|
41
|
+
**Type:** {company|team|institution}
|
|
42
|
+
**Industry:** {industry}
|
|
43
|
+
**Relationship:** {customer|prospect|partner|vendor}
|
|
44
|
+
**Domain:** {primary email domain}
|
|
45
|
+
**Aliases:** {comma-separated}
|
|
46
|
+
**First met:** {YYYY-MM-DD}
|
|
47
|
+
**Last seen:** {YYYY-MM-DD}
|
|
48
|
+
|
|
49
|
+
## Summary
|
|
50
|
+
{2-3 sentences}
|
|
51
|
+
|
|
52
|
+
## People
|
|
53
|
+
- [[People/{Person}]] — {role}
|
|
54
|
+
|
|
55
|
+
## Contacts
|
|
56
|
+
{for transactional contacts who don't get their own notes}
|
|
57
|
+
|
|
58
|
+
## Projects
|
|
59
|
+
- [[Projects/{Project}]] — {relationship}
|
|
60
|
+
|
|
61
|
+
## Activity
|
|
62
|
+
- **{YYYY-MM-DD}** ({type}): {Summary}
|
|
63
|
+
|
|
64
|
+
## Key facts
|
|
65
|
+
|
|
66
|
+
## Open items
|
|
67
|
+
```
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Project and Topic Templates
|
|
2
|
+
|
|
3
|
+
## Projects
|
|
4
|
+
|
|
5
|
+
```markdown
|
|
6
|
+
# {Project Name}
|
|
7
|
+
|
|
8
|
+
## Info
|
|
9
|
+
**Type:** {deal|product|initiative|hiring}
|
|
10
|
+
**Status:** {active|planning|on hold|completed|cancelled}
|
|
11
|
+
**Started:** {YYYY-MM-DD}
|
|
12
|
+
**Last activity:** {YYYY-MM-DD}
|
|
13
|
+
|
|
14
|
+
## Summary
|
|
15
|
+
{2-3 sentences}
|
|
16
|
+
|
|
17
|
+
## Goals
|
|
18
|
+
- [[Goals/{Goal}]] — {how this project contributes}
|
|
19
|
+
|
|
20
|
+
## People
|
|
21
|
+
- [[People/{Person}]] — {role}
|
|
22
|
+
|
|
23
|
+
## Organizations
|
|
24
|
+
- [[Organizations/{Org}]] — {relationship}
|
|
25
|
+
|
|
26
|
+
## Related
|
|
27
|
+
- [[Priorities/{Priority}]] — {relationship}
|
|
28
|
+
- [[Topics/{Topic}]] — {relationship}
|
|
29
|
+
|
|
30
|
+
## Timeline
|
|
31
|
+
**{YYYY-MM-DD}** ({type})
|
|
32
|
+
{What happened with [[links]]}
|
|
33
|
+
|
|
34
|
+
## Decisions
|
|
35
|
+
- **{YYYY-MM-DD}**: {Decision}. {Rationale}.
|
|
36
|
+
|
|
37
|
+
## Open items
|
|
38
|
+
|
|
39
|
+
## Key facts
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Topics
|
|
43
|
+
|
|
44
|
+
```markdown
|
|
45
|
+
# {Topic Name}
|
|
46
|
+
|
|
47
|
+
## About
|
|
48
|
+
{1-2 sentences}
|
|
49
|
+
|
|
50
|
+
**Keywords:** {comma-separated}
|
|
51
|
+
**Aliases:** {other references}
|
|
52
|
+
**First mentioned:** {YYYY-MM-DD}
|
|
53
|
+
**Last mentioned:** {YYYY-MM-DD}
|
|
54
|
+
|
|
55
|
+
## Related
|
|
56
|
+
- [[People/{Person}]] — {relationship}
|
|
57
|
+
- [[Organizations/{Org}]] — {relationship}
|
|
58
|
+
|
|
59
|
+
## Log
|
|
60
|
+
**{YYYY-MM-DD}** ({type}: {title})
|
|
61
|
+
{Summary with [[links]]}
|
|
62
|
+
|
|
63
|
+
## Decisions
|
|
64
|
+
|
|
65
|
+
## Open items
|
|
66
|
+
|
|
67
|
+
## Key facts
|
|
68
|
+
```
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* Manage graph_processed state for entity extraction.
|
|
4
|
+
*
|
|
5
|
+
* Tracks which source files (synced emails and calendar events) have already
|
|
6
|
+
* been processed by the extract-entities skill. The `check` command lists files
|
|
7
|
+
* that are new or changed since their last recorded hash; `update` marks files
|
|
8
|
+
* as processed by storing their current SHA-256 hash.
|
|
9
|
+
*
|
|
10
|
+
* State is persisted as a TSV file at
|
|
11
|
+
* ~/.cache/fit/outpost/state/graph_processed (path<TAB>hash).
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
if (process.argv.includes("-h") || process.argv.includes("--help")) {
|
|
15
|
+
console.log(`state — manage graph_processed state for entity extraction
|
|
16
|
+
|
|
17
|
+
Usage:
|
|
18
|
+
node scripts/state.mjs check List new/changed files
|
|
19
|
+
node scripts/state.mjs update <path> [<path>…] Mark files as processed
|
|
20
|
+
node scripts/state.mjs -h|--help Show this help message
|
|
21
|
+
|
|
22
|
+
State file: ~/.cache/fit/outpost/state/graph_processed (TSV: path<TAB>hash)`);
|
|
23
|
+
process.exit(0);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
import { createHash } from "node:crypto";
|
|
27
|
+
import {
|
|
28
|
+
existsSync,
|
|
29
|
+
mkdirSync,
|
|
30
|
+
readFileSync,
|
|
31
|
+
readdirSync,
|
|
32
|
+
statSync,
|
|
33
|
+
writeFileSync,
|
|
34
|
+
} from "node:fs";
|
|
35
|
+
import { homedir } from "node:os";
|
|
36
|
+
import { join } from "node:path";
|
|
37
|
+
|
|
38
|
+
const HOME = homedir();
|
|
39
|
+
const STATE_FILE = join(HOME, ".cache/fit/outpost/state/graph_processed");
|
|
40
|
+
const SOURCE_DIRS = [
|
|
41
|
+
join(HOME, ".cache/fit/outpost/apple_mail"),
|
|
42
|
+
join(HOME, ".cache/fit/outpost/apple_calendar"),
|
|
43
|
+
join(HOME, ".cache/fit/outpost/teams_chat"),
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
/** Compute SHA-256 hash of a file. */
|
|
47
|
+
function fileHash(filePath) {
|
|
48
|
+
const data = readFileSync(filePath);
|
|
49
|
+
return createHash("sha256").update(data).digest("hex");
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Load the state file into a Map of {path → hash}. */
|
|
53
|
+
function loadState() {
|
|
54
|
+
const state = new Map();
|
|
55
|
+
if (!existsSync(STATE_FILE)) return state;
|
|
56
|
+
const text = readFileSync(STATE_FILE, "utf-8");
|
|
57
|
+
for (const line of text.split("\n")) {
|
|
58
|
+
if (!line) continue;
|
|
59
|
+
const idx = line.indexOf("\t");
|
|
60
|
+
if (idx === -1) continue;
|
|
61
|
+
state.set(line.slice(0, idx), line.slice(idx + 1));
|
|
62
|
+
}
|
|
63
|
+
return state;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** Write the full state Map back to the state file. */
|
|
67
|
+
function saveState(state) {
|
|
68
|
+
const dir = join(HOME, ".cache/fit/outpost/state");
|
|
69
|
+
mkdirSync(dir, { recursive: true });
|
|
70
|
+
const entries = [...state.entries()].sort((a, b) => a[0].localeCompare(b[0]));
|
|
71
|
+
const text = entries.length
|
|
72
|
+
? entries.map(([p, h]) => `${p}\t${h}`).join("\n") + "\n"
|
|
73
|
+
: "";
|
|
74
|
+
writeFileSync(STATE_FILE, text);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** Find source files that are new or have changed since last processing. */
|
|
78
|
+
function check() {
|
|
79
|
+
const state = loadState();
|
|
80
|
+
const newFiles = [];
|
|
81
|
+
for (const dir of SOURCE_DIRS) {
|
|
82
|
+
if (!existsSync(dir)) continue;
|
|
83
|
+
for (const name of readdirSync(dir)) {
|
|
84
|
+
const filePath = join(dir, name);
|
|
85
|
+
const stat = statSync(filePath, { throwIfNoEntry: false });
|
|
86
|
+
if (!stat || !stat.isFile()) continue;
|
|
87
|
+
const h = fileHash(filePath);
|
|
88
|
+
if (state.get(filePath) !== h) {
|
|
89
|
+
newFiles.push(filePath);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
newFiles.sort();
|
|
94
|
+
for (const f of newFiles) {
|
|
95
|
+
console.log(f);
|
|
96
|
+
}
|
|
97
|
+
return newFiles.length;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/** Mark files as processed by updating their hashes in state. */
|
|
101
|
+
function update(filePaths) {
|
|
102
|
+
const state = loadState();
|
|
103
|
+
for (const fp of filePaths) {
|
|
104
|
+
if (!existsSync(fp)) {
|
|
105
|
+
console.error(`Warning: File not found: ${fp}`);
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
state.set(fp, fileHash(fp));
|
|
109
|
+
}
|
|
110
|
+
saveState(state);
|
|
111
|
+
console.log(`Updated ${filePaths.length} file(s) in graph state`);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// --- CLI ---
|
|
115
|
+
|
|
116
|
+
const args = process.argv.slice(2);
|
|
117
|
+
const cmd = args[0];
|
|
118
|
+
|
|
119
|
+
if (cmd === "check") {
|
|
120
|
+
const count = check();
|
|
121
|
+
console.error(`\n${count} file(s) to process`);
|
|
122
|
+
} else if (cmd === "update" && args.length >= 2) {
|
|
123
|
+
update(args.slice(1));
|
|
124
|
+
} else {
|
|
125
|
+
console.error(
|
|
126
|
+
"Usage:\n" +
|
|
127
|
+
" node scripts/state.mjs check\n" +
|
|
128
|
+
" node scripts/state.mjs update <file-path> [<file-path> …]",
|
|
129
|
+
);
|
|
130
|
+
process.exit(1);
|
|
131
|
+
}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: hyprnote-follow
|
|
3
|
+
description: >
|
|
4
|
+
Follow a live Hyprnote session in real-time, coaching the user through a
|
|
5
|
+
meeting or interview. Understands context from the session title, knowledge
|
|
6
|
+
base, and candidate pipeline. Provides talking points, flags gaps in
|
|
7
|
+
coverage, and suggests follow-up questions as the conversation unfolds.
|
|
8
|
+
Use when the user asks to follow, shadow, or coach them through a live meeting.
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Hyprnote Follow
|
|
12
|
+
|
|
13
|
+
Follow a live Hyprnote recording, read the transcript as it grows, and coach the
|
|
14
|
+
user through the meeting in real time. Gather knowledge-base context once before
|
|
15
|
+
the session, then poll the transcript and provide actionable nudges as new
|
|
16
|
+
content appears.
|
|
17
|
+
|
|
18
|
+
## Trigger
|
|
19
|
+
|
|
20
|
+
- The user asks to follow, shadow, or coach them through a live meeting.
|
|
21
|
+
- "Follow my meeting", "coach me", "shadow this call".
|
|
22
|
+
- The user starts a Hyprnote recording and wants real-time support.
|
|
23
|
+
|
|
24
|
+
## Prerequisites
|
|
25
|
+
|
|
26
|
+
- Hyprnote installed; sessions at
|
|
27
|
+
`~/Library/Application Support/hyprnote/sessions/`.
|
|
28
|
+
- An active or about-to-start session.
|
|
29
|
+
- Knowledge base populated (attendee / candidate context).
|
|
30
|
+
|
|
31
|
+
## Inputs
|
|
32
|
+
|
|
33
|
+
- Live `transcript.json` (growing during the session).
|
|
34
|
+
- `knowledge/People/`, `knowledge/Candidates/{Name}/{brief,screening,panel}.md`,
|
|
35
|
+
`knowledge/Roles/`, `knowledge/Organizations/`, `knowledge/Projects/`.
|
|
36
|
+
- `~/.cache/fit/outpost/apple_calendar/*.json` for context.
|
|
37
|
+
|
|
38
|
+
## Outputs
|
|
39
|
+
|
|
40
|
+
- Real-time coaching messages printed to the user.
|
|
41
|
+
- **No files are written.** This skill is purely advisory.
|
|
42
|
+
|
|
43
|
+
<do_confirm_checklist goal="Verify the follow session was useful and read-only">
|
|
44
|
+
|
|
45
|
+
- [ ] Active session detected and confirmed with the user.
|
|
46
|
+
- [ ] Meeting type classified from the title.
|
|
47
|
+
- [ ] Knowledge-base context gathered for all attendees.
|
|
48
|
+
- [ ] For interviews: standard expectations and screening focus areas loaded.
|
|
49
|
+
- [ ] Coaching nudges were actionable and concise (1–3 lines each).
|
|
50
|
+
- [ ] Coverage gaps tracked and surfaced before the meeting ended.
|
|
51
|
+
- [ ] End-of-meeting detected; debrief provided.
|
|
52
|
+
- [ ] Next steps offered (`req-assess` / `hyprnote-process`); user decided
|
|
53
|
+
whether to run them.
|
|
54
|
+
- [ ] No files were modified during the session.
|
|
55
|
+
|
|
56
|
+
</do_confirm_checklist>
|
|
57
|
+
|
|
58
|
+
## Procedure
|
|
59
|
+
|
|
60
|
+
### Phase 1 — Detect and connect
|
|
61
|
+
|
|
62
|
+
#### 1. Find the active session
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
node .claude/skills/hyprnote-follow/scripts/follow.mjs --detect
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Returns the most recently modified session, whether it's live, and its title. If
|
|
69
|
+
nothing has been modified in the last 5 minutes, warn the user and ask whether
|
|
70
|
+
to follow a specific session. If multiple sessions could be active, confirm with
|
|
71
|
+
the user.
|
|
72
|
+
|
|
73
|
+
#### 2. Read session metadata
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
node .claude/skills/hyprnote-follow/scripts/follow.mjs <session-id> --meta
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Capture **title**, **created_at**, **participants**.
|
|
80
|
+
|
|
81
|
+
#### 3. Classify the meeting type
|
|
82
|
+
|
|
83
|
+
Title pattern → type → coaching focus:
|
|
84
|
+
[references/meeting-types.md](references/meeting-types.md). The type drives
|
|
85
|
+
Phase 2 context loading and Phase 3 dimensions.
|
|
86
|
+
|
|
87
|
+
### Phase 2 — Gather context (once)
|
|
88
|
+
|
|
89
|
+
#### 4. Resolve attendees
|
|
90
|
+
|
|
91
|
+
Extract names from title and participant list. For each:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
rg -l "{name}" knowledge/People/
|
|
95
|
+
rg -l "{name}" knowledge/Candidates/
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Read matching notes for role, organization, history, open items, prior
|
|
99
|
+
interactions.
|
|
100
|
+
|
|
101
|
+
#### 5. Load type-specific context
|
|
102
|
+
|
|
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:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
bunx fit-pathway job {discipline} {level} --track={track}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
**General meetings:** read attendee People notes plus referenced
|
|
112
|
+
Project/Organization notes. Check open tasks: `rg "{name}" knowledge/Tasks/`.
|
|
113
|
+
|
|
114
|
+
#### 6. Build the coaching brief
|
|
115
|
+
|
|
116
|
+
Synthesize gathered context into the pre-meeting brief format in
|
|
117
|
+
[references/coaching.md](references/coaching.md#pre-meeting-brief-format) and
|
|
118
|
+
print it to the user.
|
|
119
|
+
|
|
120
|
+
### Phase 3 — Follow loop
|
|
121
|
+
|
|
122
|
+
#### 7. Read new transcript content
|
|
123
|
+
|
|
124
|
+
First read (no `--after`):
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
node .claude/skills/hyprnote-follow/scripts/follow.mjs <session-id>
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Subsequent reads (pass the last word ID):
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
node .claude/skills/hyprnote-follow/scripts/follow.mjs <session-id> --after <last-word-id>
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Returns JSON with grouped text segments, channel labels, and the next last-word
|
|
137
|
+
ID.
|
|
138
|
+
|
|
139
|
+
#### 8. Analyze new content
|
|
140
|
+
|
|
141
|
+
Track the dimensions in
|
|
142
|
+
[references/coaching.md](references/coaching.md#dimensions-to-track) — interview
|
|
143
|
+
vs. general — and apply the [principles](references/coaching.md#principles) and
|
|
144
|
+
[constraints](references/coaching.md#constraints).
|
|
145
|
+
|
|
146
|
+
#### 9. Provide coaching
|
|
147
|
+
|
|
148
|
+
Output only when actionable. Use the
|
|
149
|
+
[coaching output formats](references/coaching.md#coaching-output-formats). Keep
|
|
150
|
+
each nudge 1–3 lines.
|
|
151
|
+
|
|
152
|
+
#### 10. Detect meeting end
|
|
153
|
+
|
|
154
|
+
Watch for: farewells ("bye", "take care", "have a good day"), wrap-up phrases
|
|
155
|
+
("that's all", "let's wrap", "I'll let you go"), or final thank-yous with no
|
|
156
|
+
substantive follow-up. When detected, move to Phase 4.
|
|
157
|
+
|
|
158
|
+
#### 11. Loop cadence
|
|
159
|
+
|
|
160
|
+
**Do not use `sleep` or timed loops.** After each coaching output, read the next
|
|
161
|
+
batch immediately — natural cadence emerges from read/analyze/output. On two
|
|
162
|
+
consecutive empty reads, ask the user whether the meeting has ended.
|
|
163
|
+
|
|
164
|
+
### Phase 4 — Wrap-up
|
|
165
|
+
|
|
166
|
+
#### 12–13. Debrief
|
|
167
|
+
|
|
168
|
+
Use the appropriate template in [references/debrief.md](references/debrief.md) —
|
|
169
|
+
interview vs. general.
|
|
170
|
+
|
|
171
|
+
#### 14. Offer next steps
|
|
172
|
+
|
|
173
|
+
Offer (don't ask) the follow-ups in
|
|
174
|
+
[references/debrief.md](references/debrief.md#next-step-offers-step-14).
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# Coaching Reference
|
|
2
|
+
|
|
3
|
+
Reference for `hyprnote-follow` Phases 2 and 3.
|
|
4
|
+
|
|
5
|
+
## Pre-meeting brief format
|
|
6
|
+
|
|
7
|
+
### For interviews
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
Following: {Title}
|
|
11
|
+
Type: {Interview type}
|
|
12
|
+
Candidate: {Name} — {current role} at {employer}
|
|
13
|
+
Role: {target role} ({level}, {track})
|
|
14
|
+
Screening: {recommendation from screening.md}
|
|
15
|
+
|
|
16
|
+
Key areas to probe:
|
|
17
|
+
- {Focus area 1 from screening/panel brief}
|
|
18
|
+
- {Focus area 2}
|
|
19
|
+
- {Focus area 3}
|
|
20
|
+
|
|
21
|
+
Strengths to confirm:
|
|
22
|
+
- {Strength 1}
|
|
23
|
+
- {Strength 2}
|
|
24
|
+
|
|
25
|
+
Watching for: {specific signals at this interview stage}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### For general meetings
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
Following: {Title}
|
|
32
|
+
Attendees: {names with roles}
|
|
33
|
+
|
|
34
|
+
Open items with {name}:
|
|
35
|
+
- {item 1}
|
|
36
|
+
- {item 2}
|
|
37
|
+
|
|
38
|
+
Suggested topics:
|
|
39
|
+
- {based on recent activity/projects}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Dimensions to track
|
|
43
|
+
|
|
44
|
+
### Interviews
|
|
45
|
+
|
|
46
|
+
| Dimension | What to watch for |
|
|
47
|
+
| ----------------------- | ---------------------------------------------------------------------------------- |
|
|
48
|
+
| **Skills demonstrated** | Candidate shows (not just claims) standard skills |
|
|
49
|
+
| **Behaviour signals** | Own the Outcome, Think in Systems, Communicate with Precision, Polymath, Curiosity |
|
|
50
|
+
| **Level signals** | Autonomy, scope, complexity handling, mentoring |
|
|
51
|
+
| **Coverage gaps** | Focus areas from screening that haven't been touched yet |
|
|
52
|
+
| **Red flags** | Contradictions with CV, vague answers, deflection |
|
|
53
|
+
| **Time awareness** | Are you running out of time with uncovered areas? |
|
|
54
|
+
|
|
55
|
+
### General meetings
|
|
56
|
+
|
|
57
|
+
| Dimension | What to watch for |
|
|
58
|
+
| --------------------- | ---------------------------------------------------- |
|
|
59
|
+
| **Open items** | Were pending items raised and addressed? |
|
|
60
|
+
| **Decisions** | What was decided? Who owns next steps? |
|
|
61
|
+
| **New commitments** | Track who committed to what |
|
|
62
|
+
| **Unasked questions** | Topics the user should raise before the meeting ends |
|
|
63
|
+
| **Tone/dynamics** | Shifts in energy, resistance, enthusiasm |
|
|
64
|
+
|
|
65
|
+
## Coaching output formats
|
|
66
|
+
|
|
67
|
+
Output **only when actionable**. Each nudge: 1–3 lines max.
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
Probe deeper: {Name} mentioned {topic} — ask for a specific example
|
|
71
|
+
Gap: screening flagged {skill} as uncertain. Try: "{question}"
|
|
72
|
+
Confirmed: {Name} demonstrated {skill} at {level} — "{brief quote}"
|
|
73
|
+
Follow up: {Name} committed to {action} — pin this down with a deadline
|
|
74
|
+
Time check: ~{N} minutes in. Still uncovered: {topic 1}, {topic 2}
|
|
75
|
+
Capture: decision made on {topic} — {who} will {what}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Principles
|
|
79
|
+
|
|
80
|
+
### Interviews
|
|
81
|
+
|
|
82
|
+
- **Standard-grounded.** Every nudge ties to standard skills/behaviours. Don't
|
|
83
|
+
coach on vibes.
|
|
84
|
+
- **Evidence over claims.** Flag _claims_ vs. _demonstrations_; push for
|
|
85
|
+
specific examples.
|
|
86
|
+
- **Coverage-aware.** Track which screening focus areas have been explored and
|
|
87
|
+
nudge before time runs out.
|
|
88
|
+
- **Level-calibrated.** Know what the target level expects; flag
|
|
89
|
+
below-/above-level answers.
|
|
90
|
+
- **Don't lead.** Suggest open-ended probes, never loaded or leading questions.
|
|
91
|
+
|
|
92
|
+
### General meetings
|
|
93
|
+
|
|
94
|
+
- **Agenda-aware.** Track coverage of known topics or open items.
|
|
95
|
+
- **Decision-focused.** Flag decisions and capture owners.
|
|
96
|
+
- **Commitment-tracking.** Note who said they'd do what; surface unresolved
|
|
97
|
+
commitments from prior meetings.
|
|
98
|
+
- **Time-conscious.** Nudge when the meeting is running long and key topics
|
|
99
|
+
aren't raised.
|
|
100
|
+
|
|
101
|
+
### Universal
|
|
102
|
+
|
|
103
|
+
- **Be quiet when things are going well.** Speak only when actionable.
|
|
104
|
+
- **Channel awareness.** Channel 0 = user; channel 1+ = guest(s). Reference what
|
|
105
|
+
the _guest_ said — the user already knows what they said.
|
|
106
|
+
- **Never interrupt flow.** Hold nudges for the next natural pause.
|
|
107
|
+
- **Respect the user.** Coach at the margin, don't patronise.
|
|
108
|
+
|
|
109
|
+
## Constraints
|
|
110
|
+
|
|
111
|
+
- **Read-only.** Never modify Hyprnote files, knowledge notes, or state.
|
|
112
|
+
- **No post-processing during follow.** Don't run `extract-entities`,
|
|
113
|
+
`req-assess`, or `hyprnote-process`. Offer them after.
|
|
114
|
+
- **Channel 0 = user.** Always.
|
|
115
|
+
- **Transcription noise.** Live transcripts are messy. Don't coach from a single
|
|
116
|
+
ambiguous word — wait for context.
|
|
117
|
+
- **Privacy.** Coaching may appear on a shared screen — keep nudges generic
|
|
118
|
+
enough that they don't reveal confidential assessment detail.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Debrief Templates
|
|
2
|
+
|
|
3
|
+
Reference for `hyprnote-follow` Phase 4 (Steps 12–13).
|
|
4
|
+
|
|
5
|
+
## Interview debrief
|
|
6
|
+
|
|
7
|
+
```markdown
|
|
8
|
+
## Session Debrief: {Title}
|
|
9
|
+
**Duration:** ~{N} minutes
|
|
10
|
+
|
|
11
|
+
### Coverage
|
|
12
|
+
| Focus Area | Status | Evidence |
|
|
13
|
+
|---|---|---|
|
|
14
|
+
| {area from screening} | Covered / Partial / Missed | {brief note} |
|
|
15
|
+
|
|
16
|
+
### Signals Observed
|
|
17
|
+
**Strengths:**
|
|
18
|
+
- {skill/behaviour}: {what was demonstrated}
|
|
19
|
+
|
|
20
|
+
**Concerns:**
|
|
21
|
+
- {skill/behaviour}: {what was lacking or contradictory}
|
|
22
|
+
|
|
23
|
+
**Level read:** {level assessment based on what was observed}
|
|
24
|
+
|
|
25
|
+
### Suggested Next Steps
|
|
26
|
+
- {e.g. "Schedule decomposition interview to probe {skill}"}
|
|
27
|
+
- {e.g. "Flag {concern} for panel brief"}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## General-meeting debrief
|
|
31
|
+
|
|
32
|
+
```markdown
|
|
33
|
+
## Session Debrief: {Title}
|
|
34
|
+
**Duration:** ~{N} minutes
|
|
35
|
+
|
|
36
|
+
### Decisions Made
|
|
37
|
+
- {decision 1}
|
|
38
|
+
- {decision 2}
|
|
39
|
+
|
|
40
|
+
### Action Items
|
|
41
|
+
| Owner | Action | Deadline |
|
|
42
|
+
|---|---|---|
|
|
43
|
+
| {name} | {what} | {when, if mentioned} |
|
|
44
|
+
|
|
45
|
+
### Open Items (still unresolved)
|
|
46
|
+
- {item that wasn't addressed}
|
|
47
|
+
|
|
48
|
+
### Key Takeaways
|
|
49
|
+
- {1–2 sentence summary of what matters most}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Next-step offers (Step 14)
|
|
53
|
+
|
|
54
|
+
After the debrief, **offer** (don't ask) logical follow-ups:
|
|
55
|
+
|
|
56
|
+
- **Interviews:** "I can run `req-assess` on this transcript when Hyprnote
|
|
57
|
+
finishes processing."
|
|
58
|
+
- **Meetings:** "I can extract entities from this session into the knowledge
|
|
59
|
+
graph when ready."
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Meeting-Type Classification
|
|
2
|
+
|
|
3
|
+
Reference for `hyprnote-follow` Phase 1, Step 3. Classify from the session
|
|
4
|
+
title.
|
|
5
|
+
|
|
6
|
+
| Title pattern | Type | Coaching focus |
|
|
7
|
+
| ------------------------------------------- | --------------------------- | -------------------------------------------------------------- |
|
|
8
|
+
| "Interview with {Name}", "Screening {Name}" | **Screening interview** | Agent-aligned standard skills, behaviour probes, level signals |
|
|
9
|
+
| "Decomposition interview with {Name}" | **Decomposition interview** | Problem-solving approach, system thinking, trade-offs |
|
|
10
|
+
| "Technical assessment of {Name}" | **Technical interview** | Hands-on skill, architecture reasoning, code quality |
|
|
11
|
+
| "Panel with {Name}", "Second interview" | **Panel interview** | Business acumen, cultural fit, leadership signals |
|
|
12
|
+
| "Meeting with {Name}", "{Topic} meeting" | **General meeting** | Agenda coverage, action items, decision capture |
|
|
13
|
+
| "Recruitment call", "Recruitment strategy" | **Recruitment planning** | Pipeline status, role requirements, next steps |
|
|
14
|
+
| Other | **General** | Active listening, follow-up questions, key takeaways |
|