@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.
Files changed (120) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +15 -0
  3. package/bin/fit-outpost.js +3 -0
  4. package/config/scheduler.json +34 -0
  5. package/package.json +63 -0
  6. package/src/agent-runner.js +189 -0
  7. package/src/index.js +5 -0
  8. package/src/kb-manager.js +228 -0
  9. package/src/outpost.js +417 -0
  10. package/src/scheduler.js +195 -0
  11. package/src/socket-server.js +336 -0
  12. package/src/state-manager.js +126 -0
  13. package/templates/.claude/agents/chief-of-staff.md +58 -0
  14. package/templates/.claude/agents/concierge.md +46 -0
  15. package/templates/.claude/agents/head-hunter.md +57 -0
  16. package/templates/.claude/agents/librarian.md +60 -0
  17. package/templates/.claude/agents/postman.md +47 -0
  18. package/templates/.claude/agents/recruiter.md +63 -0
  19. package/templates/.claude/settings.json +88 -0
  20. package/templates/.claude/skills/candidate-report/SKILL.md +139 -0
  21. package/templates/.claude/skills/candidate-report/references/report-template.html +203 -0
  22. package/templates/.claude/skills/candidate-report/references/report.css +438 -0
  23. package/templates/.claude/skills/candidate-report/references/rubric.md +76 -0
  24. package/templates/.claude/skills/candidate-report/scripts/render-pdf.mjs +48 -0
  25. package/templates/.claude/skills/deck-create/SKILL.md +75 -0
  26. package/templates/.claude/skills/deck-create/references/slide.css +35 -0
  27. package/templates/.claude/skills/deck-create/scripts/convert-to-pdf.mjs +47 -0
  28. package/templates/.claude/skills/deck-summarize/SKILL.md +139 -0
  29. package/templates/.claude/skills/deck-summarize/references/brief-template.md +85 -0
  30. package/templates/.claude/skills/deck-summarize/scripts/extract-pptx.mjs +210 -0
  31. package/templates/.claude/skills/doc-collab/SKILL.md +112 -0
  32. package/templates/.claude/skills/doc-create/SKILL.md +105 -0
  33. package/templates/.claude/skills/doc-create/scripts/convert-to-pdf.mjs +50 -0
  34. package/templates/.claude/skills/draft-emails/SKILL.md +141 -0
  35. package/templates/.claude/skills/draft-emails/references/template.md +26 -0
  36. package/templates/.claude/skills/draft-emails/scripts/scan-emails.mjs +66 -0
  37. package/templates/.claude/skills/draft-emails/scripts/send-email.mjs +139 -0
  38. package/templates/.claude/skills/extract-entities/SKILL.md +187 -0
  39. package/templates/.claude/skills/extract-entities/references/TEMPLATES.md +14 -0
  40. package/templates/.claude/skills/extract-entities/references/conditions.md +55 -0
  41. package/templates/.claude/skills/extract-entities/references/content.md +104 -0
  42. package/templates/.claude/skills/extract-entities/references/links.md +48 -0
  43. package/templates/.claude/skills/extract-entities/references/recruitment.md +57 -0
  44. package/templates/.claude/skills/extract-entities/references/resolution.md +71 -0
  45. package/templates/.claude/skills/extract-entities/references/sources.md +70 -0
  46. package/templates/.claude/skills/extract-entities/references/templates-conditions.md +36 -0
  47. package/templates/.claude/skills/extract-entities/references/templates-goals-priorities.md +63 -0
  48. package/templates/.claude/skills/extract-entities/references/templates-people-orgs.md +67 -0
  49. package/templates/.claude/skills/extract-entities/references/templates-projects-topics.md +68 -0
  50. package/templates/.claude/skills/extract-entities/scripts/state.mjs +131 -0
  51. package/templates/.claude/skills/hyprnote-follow/SKILL.md +174 -0
  52. package/templates/.claude/skills/hyprnote-follow/references/coaching.md +118 -0
  53. package/templates/.claude/skills/hyprnote-follow/references/debrief.md +59 -0
  54. package/templates/.claude/skills/hyprnote-follow/references/meeting-types.md +14 -0
  55. package/templates/.claude/skills/hyprnote-follow/scripts/follow.mjs +243 -0
  56. package/templates/.claude/skills/hyprnote-process/SKILL.md +147 -0
  57. package/templates/.claude/skills/hyprnote-process/references/extraction.md +84 -0
  58. package/templates/.claude/skills/hyprnote-process/references/sessions.md +81 -0
  59. package/templates/.claude/skills/hyprnote-process/scripts/scan.mjs +246 -0
  60. package/templates/.claude/skills/hyprnote-trim/SKILL.md +177 -0
  61. package/templates/.claude/skills/manage-tasks/SKILL.md +152 -0
  62. package/templates/.claude/skills/manage-tasks/references/format.md +73 -0
  63. package/templates/.claude/skills/meeting-prep/SKILL.md +180 -0
  64. package/templates/.claude/skills/organize-files/SKILL.md +146 -0
  65. package/templates/.claude/skills/organize-files/scripts/organize-by-type.mjs +105 -0
  66. package/templates/.claude/skills/organize-files/scripts/summarize.mjs +91 -0
  67. package/templates/.claude/skills/req-assess/SKILL.md +137 -0
  68. package/templates/.claude/skills/req-assess/references/interview-template.md +62 -0
  69. package/templates/.claude/skills/req-assess/references/panel-template.md +117 -0
  70. package/templates/.claude/skills/req-assess/references/rubric.md +65 -0
  71. package/templates/.claude/skills/req-decide/SKILL.md +163 -0
  72. package/templates/.claude/skills/req-decide/references/rubric.md +63 -0
  73. package/templates/.claude/skills/req-decide/references/template.md +118 -0
  74. package/templates/.claude/skills/req-forget/SKILL.md +154 -0
  75. package/templates/.claude/skills/req-forget/references/classify.md +23 -0
  76. package/templates/.claude/skills/req-forget/references/locations.md +59 -0
  77. package/templates/.claude/skills/req-forget/references/report-template.md +67 -0
  78. package/templates/.claude/skills/req-scan/SKILL.md +145 -0
  79. package/templates/.claude/skills/req-scan/references/fallbacks.md +76 -0
  80. package/templates/.claude/skills/req-scan/references/filters.md +83 -0
  81. package/templates/.claude/skills/req-scan/references/sources.md +76 -0
  82. package/templates/.claude/skills/req-scan/references/state.md +54 -0
  83. package/templates/.claude/skills/req-scan/references/template.md +36 -0
  84. package/templates/.claude/skills/req-scan/scripts/state.mjs +396 -0
  85. package/templates/.claude/skills/req-screen/SKILL.md +151 -0
  86. package/templates/.claude/skills/req-screen/references/rubric.md +94 -0
  87. package/templates/.claude/skills/req-screen/references/template.md +91 -0
  88. package/templates/.claude/skills/req-track/SKILL.md +189 -0
  89. package/templates/.claude/skills/req-track/references/fields.md +114 -0
  90. package/templates/.claude/skills/req-track/references/signals.md +42 -0
  91. package/templates/.claude/skills/req-track/references/statuses.md +32 -0
  92. package/templates/.claude/skills/req-track/references/templates.md +127 -0
  93. package/templates/.claude/skills/req-workday/SKILL.md +162 -0
  94. package/templates/.claude/skills/req-workday/references/field-mapping.md +40 -0
  95. package/templates/.claude/skills/req-workday/references/status-mapping.md +38 -0
  96. package/templates/.claude/skills/req-workday/references/templates.md +126 -0
  97. package/templates/.claude/skills/req-workday/references/xlsx-format.md +56 -0
  98. package/templates/.claude/skills/req-workday/scripts/parse-workday.mjs +313 -0
  99. package/templates/.claude/skills/send-chat/SKILL.md +170 -0
  100. package/templates/.claude/skills/sync-apple-calendar/SKILL.md +145 -0
  101. package/templates/.claude/skills/sync-apple-calendar/references/SCHEMA.md +80 -0
  102. package/templates/.claude/skills/sync-apple-calendar/scripts/query.mjs +307 -0
  103. package/templates/.claude/skills/sync-apple-calendar/scripts/sync.mjs +332 -0
  104. package/templates/.claude/skills/sync-apple-mail/SKILL.md +151 -0
  105. package/templates/.claude/skills/sync-apple-mail/references/SCHEMA.md +115 -0
  106. package/templates/.claude/skills/sync-apple-mail/scripts/parse-emlx.mjs +389 -0
  107. package/templates/.claude/skills/sync-apple-mail/scripts/sync-helpers.mjs +372 -0
  108. package/templates/.claude/skills/sync-apple-mail/scripts/sync.mjs +239 -0
  109. package/templates/.claude/skills/sync-teams/SKILL.md +177 -0
  110. package/templates/.claude/skills/sync-teams/scripts/idb-reader.mjs +147 -0
  111. package/templates/.claude/skills/sync-teams/scripts/leveldb-reader.mjs +288 -0
  112. package/templates/.claude/skills/sync-teams/scripts/sync.mjs +381 -0
  113. package/templates/.claude/skills/upstream-skill/SKILL.md +130 -0
  114. package/templates/.claude/skills/upstream-skill/references/examples.md +80 -0
  115. package/templates/.claude/skills/weekly-update/SKILL.md +141 -0
  116. package/templates/.claude/skills/weekly-update/references/template.md +55 -0
  117. package/templates/CLAUDE.md +134 -0
  118. package/templates/USER.md +3 -0
  119. package/templates/apm.yml +5 -0
  120. package/templates/knowledge/Briefings/.gitkeep +0 -0
@@ -0,0 +1,180 @@
1
+ ---
2
+ name: meeting-prep
3
+ description: Prepare for meetings by gathering context from the knowledge base and calendar. Use when the user asks to prep for a meeting or wants a briefing on upcoming meetings. Creates personalized briefings with attendee history, open items, and suggested talking points.
4
+ ---
5
+
6
+ # Meeting Prep
7
+
8
+ Help the user prepare for meetings by gathering context from the knowledge base
9
+ and calendar. Creates personalized briefing documents with attendee history,
10
+ open items, and suggested talking points.
11
+
12
+ ## Trigger
13
+
14
+ Run when the user asks to prep for a meeting, or wants a briefing on upcoming
15
+ meetings.
16
+
17
+ ## Prerequisites
18
+
19
+ - Calendar data synced in `~/.cache/fit/outpost/apple_calendar/`
20
+ - Knowledge base populated (from `extract-entities` skill)
21
+
22
+ ## Inputs
23
+
24
+ - `~/.cache/fit/outpost/apple_calendar/*.json` — calendar events
25
+ - `knowledge/People/*.md` — attendee context
26
+ - `knowledge/Organizations/*.md` — company context
27
+ - `knowledge/Projects/*.md` — project context
28
+ - `knowledge/Goals/*.md` — active goals relevant to the meeting topic
29
+ - `knowledge/Priorities/*.md` — strategic context for framing
30
+ - `knowledge/Candidates/*/brief.md` — candidate context (for interview meetings)
31
+ - `knowledge/Roles/*.md` — role/requisition context (for interview meetings)
32
+
33
+ ## Outputs
34
+
35
+ - Meeting brief printed to the user (not saved to a file)
36
+
37
+ ---
38
+
39
+ ## Critical: Always Look Up Context First
40
+
41
+ **BEFORE creating any meeting brief, you MUST look up the attendees in the
42
+ knowledge base.**
43
+
44
+ When the user asks to prep for a meeting:
45
+
46
+ 1. **STOP** — Do not create a generic brief
47
+ 2. **SEARCH** — Look up each attendee: `rg -l "Attendee Name" knowledge/`
48
+ 3. **READ** — Read their notes: `cat "knowledge/People/Attendee Name.md"`
49
+ 4. **UNDERSTAND** — Extract role, organization, history, open items
50
+ 5. **THEN BRIEF** — Create the meeting brief using this context
51
+
52
+ ## Key Principles
53
+
54
+ **Ask, don't guess:**
55
+
56
+ - If unclear which meeting, ASK
57
+ - If multiple upcoming meetings, offer choices
58
+ - **WRONG:** "Here's a generic meeting prep template"
59
+ - **RIGHT:** "I see meetings with Sarah (2pm) and John (4pm). Which one?"
60
+
61
+ **Be thorough, not generic:**
62
+
63
+ - Include specific history, open items, and context from knowledge base
64
+ - Reference actual past interactions and commitments
65
+
66
+ ## Processing Flow
67
+
68
+ ### Step 1: Identify the Meeting
69
+
70
+ Use the calendar query script to find upcoming meetings:
71
+
72
+ ```bash
73
+ # Next 2 hours of meetings as JSON
74
+ node .claude/skills/sync-apple-calendar/scripts/query.mjs --upcoming 2h --json
75
+
76
+ # Today's full schedule
77
+ node .claude/skills/sync-apple-calendar/scripts/query.mjs --today
78
+ ```
79
+
80
+ If "prep me for my next meeting":
81
+
82
+ - Query upcoming events with `--upcoming 2h`
83
+ - Find the next meeting with external attendees
84
+ - Confirm with user if unclear
85
+
86
+ ### Step 2: Parse Calendar Event
87
+
88
+ Extract: summary, start/end time, attendees (names and emails), description.
89
+
90
+ ### Step 3: Gather Context from Knowledge Base
91
+
92
+ For each attendee:
93
+
94
+ ```bash
95
+ rg -l "attendee_name" knowledge/People/
96
+ rg -l "attendee_email" knowledge/People/
97
+ cat "knowledge/People/Attendee Name.md"
98
+ cat "knowledge/Organizations/Their Company.md"
99
+ rg -l "attendee_name" knowledge/Projects/
100
+ ```
101
+
102
+ Extract: role/title, company, key facts, previous interactions, open items.
103
+
104
+ Also check `knowledge/Goals/` and `knowledge/Priorities/` for context relevant
105
+ to the meeting topic — e.g. if the meeting is about hiring, surface the relevant
106
+ hiring Goal's status and progress.
107
+
108
+ ### Step 4: Create Meeting Brief
109
+
110
+ Format:
111
+
112
+ ```markdown
113
+ Meeting Brief: {Attendee Name}
114
+ {Time} today / {Company}
115
+
116
+ About {First Name}
117
+ {Role at company}. {Key background — 1-2 sentences}. {What they focus on}.
118
+
119
+ Your History
120
+ - {Date}: {Brief description of interaction/outcome}
121
+ - {Date}: {Brief description}
122
+ - {Date}: {Brief description}
123
+
124
+ Open Items
125
+ - {Action item} (they asked {date})
126
+ - {Action item}
127
+
128
+ Suggested Talking Points
129
+ - {Concrete suggestion based on history}
130
+ - {Reference relevant entities with [[wiki-links]]}
131
+ ```
132
+
133
+ **Guidelines:**
134
+
135
+ - Use `[[Name]]` wiki-link syntax for cross-references
136
+ - Keep "About" section to 2-3 sentences max
137
+ - History: reverse chronological, 3-5 most relevant items
138
+ - Talking points: concrete, not generic
139
+ - If no notes exist for a person, mention that and offer to create one
140
+
141
+ ### Interview Meeting Context
142
+
143
+ When preparing for interview meetings (title contains "Interview", "Screening",
144
+ "Decomposition", "Panel", or a candidate name from `knowledge/Candidates/`):
145
+
146
+ 1. **Read the candidate brief:** `knowledge/Candidates/{Name}/brief.md`
147
+ 2. **Read the Role file:** Look up the `Req` field and read the corresponding
148
+ `knowledge/Roles/*.md` file.
149
+ 3. **Include in the briefing:**
150
+ - Candidate's current status, skills, and screening recommendation
151
+ - Role context: hiring manager, domain lead, remaining positions
152
+ - Other candidates on the same requisition and their statuses (from the Role
153
+ file's Candidates table)
154
+ - Previous interview assessments if this is a second/later stage
155
+ - Panel brief if one exists (`panel.md`)
156
+ 4. **Format as a dedicated section:**
157
+
158
+ ```markdown
159
+ ## Candidate: {Name}
160
+ **Role:** {Title from Role file} | **Req:** {req number}
161
+ **Hiring manager:** {name} | **Domain lead:** {name}
162
+ **Status:** {current pipeline status}
163
+ **Screening:** {Interview / Interview with focus areas / Pass}
164
+
165
+ ### Pipeline for this req
166
+ - {N} candidates total, {N} interviewed, {N} remaining positions
167
+
168
+ ### Key strengths
169
+ - {from screening.md}
170
+
171
+ ### Focus areas for this interview
172
+ - {from screening.md or panel.md}
173
+ ```
174
+
175
+ ## Constraints
176
+
177
+ - Only prep for meetings with external attendees
178
+ - Skip internal calendar blocks (DND, Focus Time, Lunch)
179
+ - For meetings with multiple attendees, create sections for each key person
180
+ - Prioritize recent interactions (last 30 days)
@@ -0,0 +1,146 @@
1
+ ---
2
+ name: organize-files
3
+ description: Organize, tidy up, and find files in ~/Desktop/ and ~/Downloads/. Use when the user asks to find, organize, clean up, or tidy files on their Mac. Always previews changes before acting and never deletes without explicit confirmation. Extracts entities from document files using the extract-entities skill.
4
+ compatibility: Requires macOS filesystem access
5
+ ---
6
+
7
+ # Organize Files
8
+
9
+ Organize, tidy up, and find files in `~/Desktop/` and `~/Downloads/`. Always
10
+ previews changes before acting and never deletes without explicit confirmation.
11
+
12
+ After organizing, extract entities from document files by invoking the
13
+ **`extract-entities`** skill.
14
+
15
+ ## Trigger
16
+
17
+ Run when the user asks to find, organize, clean up, or tidy files on their Mac.
18
+
19
+ ## Prerequisites
20
+
21
+ - macOS filesystem access
22
+
23
+ ## Inputs
24
+
25
+ - User's description of what to organize or find
26
+ - Source directories: `~/Desktop/` and `~/Downloads/`
27
+
28
+ ## Outputs
29
+
30
+ - Organized files moved to logical subdirectories within `~/Desktop/` and
31
+ `~/Downloads/`
32
+ - Entity extraction triggered on document files via the **`extract-entities`**
33
+ skill
34
+ - Summary of actions taken
35
+
36
+ ---
37
+
38
+ ## Core Capabilities
39
+
40
+ 1. **Find files** — Locate files by name, type, or content in `~/Desktop/` and
41
+ `~/Downloads/`
42
+ 2. **Organize files** — Move files into logical subfolders
43
+ 3. **Tidy up** — Clean up cluttered `~/Desktop/` and `~/Downloads/`
44
+ 4. **Create structure** — Set up folder hierarchies
45
+ 5. **Extract entities** — After organizing, invoke the **`extract-entities`**
46
+ skill on document files to populate the knowledge graph
47
+
48
+ ## Key Principles
49
+
50
+ **Always preview before acting:**
51
+
52
+ - Show what files will be affected BEFORE moving/deleting
53
+ - List proposed changes and ask for confirmation
54
+
55
+ **Be conservative with destructive operations:**
56
+
57
+ - Never delete without explicit confirmation
58
+ - Prefer moving to a "to-review" folder over deleting
59
+
60
+ ## Summarizing Contents
61
+
62
+ Get an overview of both directories:
63
+
64
+ node scripts/summarize.mjs
65
+
66
+ ## Finding Files
67
+
68
+ ```bash
69
+ find ~/Downloads -maxdepth 1 -name "*.pdf" -type f
70
+ find ~/Desktop -maxdepth 1 -iname "*AI*" -type f
71
+ find ~/Desktop -maxdepth 1 -type f \( -name "*.png" -o -name "*.jpg" \)
72
+ find ~/Downloads -maxdepth 1 -type f -mtime -7 # last 7 days
73
+ find ~/Downloads -maxdepth 1 -type f -mtime +30 # older than 30 days
74
+ find ~/Desktop -maxdepth 1 \( -name "Screenshot*" -o -name "Screen Shot*" \)
75
+ ```
76
+
77
+ ## Organizing by File Type
78
+
79
+ Organize a directory into type-based subdirectories (Documents, Images,
80
+ Archives, Installers, Screenshots):
81
+
82
+ node scripts/organize-by-type.mjs ~/Downloads
83
+ node scripts/organize-by-type.mjs ~/Desktop
84
+
85
+ The script creates subdirectories and moves matching files. It does NOT delete
86
+ anything.
87
+
88
+ ## Entity Extraction
89
+
90
+ After organizing files, identify document files that may contain entity
91
+ information (people, organizations, projects, topics) and invoke the
92
+ **`extract-entities`** skill to process them.
93
+
94
+ ### Which files to send for extraction
95
+
96
+ **Include:** `.pdf`, `.txt`, `.md`, `.rtf`, `.doc`, `.docx`, `.csv`, `.xlsx`
97
+
98
+ **Exclude:** Images, installers, archives, media, system files
99
+
100
+ ### How to invoke
101
+
102
+ After organizing, collect the paths of document files and invoke the
103
+ **`extract-entities`** skill, passing the file paths as ad-hoc file inputs.
104
+
105
+ ## Output Format
106
+
107
+ **Plan:**
108
+
109
+ ```
110
+ Organization Plan: Desktop & Downloads Cleanup
111
+
112
+ Found 47 files to organize:
113
+ - 23 screenshots → ~/Desktop/Screenshots/
114
+ - 12 PDFs → ~/Downloads/Documents/
115
+ - 8 images → ~/Downloads/Images/
116
+ - 4 DMGs → ~/Downloads/Installers/
117
+
118
+ Document files for entity extraction: 12
119
+ → Will invoke extract-entities skill after organizing
120
+
121
+ Should I proceed?
122
+ ```
123
+
124
+ **Results:**
125
+
126
+ ```
127
+ Organization Complete
128
+
129
+ Moved 47 files:
130
+ - 23 screenshots to ~/Desktop/Screenshots/
131
+ - 12 PDFs to ~/Downloads/Documents/
132
+ - 8 images to ~/Downloads/Images/
133
+ - 4 DMGs to ~/Downloads/Installers/
134
+
135
+ Entity extraction: invoked extract-entities on 12 document files
136
+ ```
137
+
138
+ ## Safety Rules
139
+
140
+ 1. **Never delete without permission** — "cleanup" means organize, not delete
141
+ 2. **Don't touch system folders** — /System, /Library, /Applications
142
+ 3. **Don't touch hidden files** — files starting with `.` unless asked
143
+ 4. **Limit scope** — only operate on `~/Desktop/` and `~/Downloads/`
144
+ 5. **Limit depth** — use `-maxdepth 1` unless user wants recursive
145
+ 6. **Show before doing** — always preview first
146
+ 7. **Quote paths** — handle spaces: `"$HOME/My Documents"`
@@ -0,0 +1,105 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * Organize files in a directory by type into subdirectories.
4
+ *
5
+ * Scans the top level of the given directory and moves files into category
6
+ * subdirectories: Screenshots, Documents, Images, Archives, and Installers.
7
+ * Categories are determined by file extension and name prefix. Files that do
8
+ * not match any category are left in place. Does NOT delete anything.
9
+ */
10
+
11
+ import {
12
+ existsSync,
13
+ mkdirSync,
14
+ readdirSync,
15
+ renameSync,
16
+ statSync,
17
+ } from "node:fs";
18
+ import { extname, join } from "node:path";
19
+
20
+ const HELP = `organize-by-type — sort files into type-based subdirectories
21
+
22
+ Usage: node scripts/organize-by-type.mjs <directory> [-h|--help]
23
+
24
+ Creates subdirectories (Documents, Images, Archives, Installers, Screenshots)
25
+ and moves matching top-level files into them. Does NOT delete any files.`;
26
+
27
+ if (process.argv.includes("-h") || process.argv.includes("--help")) {
28
+ console.log(HELP);
29
+ process.exit(0);
30
+ }
31
+
32
+ const CATEGORIES = [
33
+ {
34
+ name: "Screenshots",
35
+ test: (name) =>
36
+ name.startsWith("Screenshot") || name.startsWith("Screen Shot"),
37
+ },
38
+ {
39
+ name: "Documents",
40
+ test: (_name, ext) =>
41
+ [
42
+ ".pdf",
43
+ ".doc",
44
+ ".docx",
45
+ ".txt",
46
+ ".md",
47
+ ".rtf",
48
+ ".csv",
49
+ ".xlsx",
50
+ ].includes(ext),
51
+ },
52
+ {
53
+ name: "Images",
54
+ test: (_name, ext) =>
55
+ [".png", ".jpg", ".jpeg", ".gif", ".webp"].includes(ext),
56
+ },
57
+ {
58
+ name: "Archives",
59
+ test: (name, ext) =>
60
+ [".zip", ".rar"].includes(ext) || name.endsWith(".tar.gz"),
61
+ },
62
+ {
63
+ name: "Installers",
64
+ test: (_name, ext) => ext === ".dmg",
65
+ },
66
+ ];
67
+
68
+ function main() {
69
+ const dir = process.argv[2];
70
+ if (!dir) {
71
+ console.error("Usage: node scripts/organize-by-type.mjs <directory>");
72
+ process.exit(1);
73
+ }
74
+ if (!existsSync(dir) || !statSync(dir).isDirectory()) {
75
+ console.error(`Error: Directory not found: ${dir}`);
76
+ process.exit(1);
77
+ }
78
+
79
+ // Create subdirectories
80
+ for (const cat of CATEGORIES) {
81
+ mkdirSync(join(dir, cat.name), { recursive: true });
82
+ }
83
+
84
+ let moved = 0;
85
+ for (const name of readdirSync(dir)) {
86
+ const fullPath = join(dir, name);
87
+ const stat = statSync(fullPath, { throwIfNoEntry: false });
88
+ if (!stat || !stat.isFile()) continue;
89
+
90
+ const ext = extname(name).toLowerCase();
91
+ for (const cat of CATEGORIES) {
92
+ if (cat.test(name, ext)) {
93
+ const dest = join(dir, cat.name, name);
94
+ renameSync(fullPath, dest);
95
+ console.log(`${name} -> ${cat.name}/`);
96
+ moved++;
97
+ break;
98
+ }
99
+ }
100
+ }
101
+
102
+ console.log(`\nOrganization complete: ${dir} (${moved} files moved)`);
103
+ }
104
+
105
+ main();
@@ -0,0 +1,91 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * Summarize the contents of ~/Desktop/ and ~/Downloads/.
4
+ *
5
+ * Counts top-level files in both directories by type (Screenshots, PDFs,
6
+ * Images, Documents, Archives, Installers, Other) and prints a human-readable
7
+ * table for each. Used by the organize-files skill to preview directory
8
+ * contents before organizing.
9
+ */
10
+
11
+ import { existsSync, readdirSync, statSync } from "node:fs";
12
+ import { extname, join } from "node:path";
13
+ import { homedir } from "node:os";
14
+
15
+ const HELP = `summarize — count files by type in ~/Desktop/ and ~/Downloads/
16
+
17
+ Usage: node scripts/summarize.mjs [-h|--help]
18
+
19
+ Prints a summary of file types found at the top level of each directory.`;
20
+
21
+ if (process.argv.includes("-h") || process.argv.includes("--help")) {
22
+ console.log(HELP);
23
+ process.exit(0);
24
+ }
25
+
26
+ const HOME = homedir();
27
+
28
+ const IMAGE_EXTS = new Set([".png", ".jpg", ".jpeg", ".gif", ".webp"]);
29
+ const DOC_EXTS = new Set([
30
+ ".doc",
31
+ ".docx",
32
+ ".txt",
33
+ ".md",
34
+ ".rtf",
35
+ ".csv",
36
+ ".xlsx",
37
+ ]);
38
+ const ARCHIVE_EXTS = new Set([".zip", ".rar"]);
39
+
40
+ function classifyFile(name, ext) {
41
+ if (name.startsWith("Screenshot") || name.startsWith("Screen Shot"))
42
+ return "Screenshots";
43
+ if (ext === ".pdf") return "PDFs";
44
+ if (IMAGE_EXTS.has(ext)) return "Images";
45
+ if (DOC_EXTS.has(ext)) return "Documents";
46
+ if (ARCHIVE_EXTS.has(ext) || name.endsWith(".tar.gz")) return "Archives";
47
+ if (ext === ".dmg") return "Installers";
48
+ return "Other";
49
+ }
50
+
51
+ function countFiles(dir) {
52
+ if (!existsSync(dir)) return null;
53
+
54
+ const counts = {
55
+ Screenshots: 0,
56
+ PDFs: 0,
57
+ Images: 0,
58
+ Documents: 0,
59
+ Archives: 0,
60
+ Installers: 0,
61
+ Other: 0,
62
+ };
63
+
64
+ for (const name of readdirSync(dir)) {
65
+ const fullPath = join(dir, name);
66
+ const stat = statSync(fullPath, { throwIfNoEntry: false });
67
+ if (!stat || !stat.isFile()) continue;
68
+ if (name.startsWith(".")) continue;
69
+
70
+ const category = classifyFile(name, extname(name).toLowerCase());
71
+ counts[category]++;
72
+ }
73
+
74
+ return counts;
75
+ }
76
+
77
+ function main() {
78
+ for (const dirName of ["Desktop", "Downloads"]) {
79
+ const dir = join(HOME, dirName);
80
+ const counts = countFiles(dir);
81
+ if (!counts) continue;
82
+
83
+ console.log(`=== ${dirName} ===`);
84
+ for (const [label, count] of Object.entries(counts)) {
85
+ console.log(`${label.padEnd(12)} ${count}`);
86
+ }
87
+ console.log("");
88
+ }
89
+ }
90
+
91
+ main();
@@ -0,0 +1,137 @@
1
+ ---
2
+ name: req-assess
3
+ description: >
4
+ Analyze interview transcripts against the agent-aligned engineering standard,
5
+ updating skill and behaviour ratings with observed evidence. Produces
6
+ per-interview assessments and panel briefs for subsequent interview stages.
7
+ Use when transcript files appear in a candidate's folder.
8
+ ---
9
+
10
+ # Assess Interview
11
+
12
+ Analyze a candidate's interview transcripts. Update their skill and behaviour
13
+ profile with **observed** (not claimed) evidence. Interview evidence is
14
+ higher-fidelity than CV evidence — it confirms or contradicts the screening
15
+ assessment.
16
+
17
+ This is **Stage 2** of the three-stage hiring pipeline:
18
+
19
+ 1. `req-screen` — CV → interview or pass.
20
+ 2. **Assess interview** (this skill) — transcript → updated profile.
21
+ 3. `req-decide` — all stages complete → hire / no hire.
22
+
23
+ ## Trigger
24
+
25
+ - A new `transcript-*.md` file appears in `knowledge/Candidates/{Name}/`.
26
+ - The user asks to analyze an interview or debrief.
27
+ - The user asks to prepare a panel brief.
28
+ - The concierge agent processes a Hyprnote interview recording.
29
+
30
+ ## Prerequisites
31
+
32
+ - `fit-pathway` CLI installed.
33
+ - At least one transcript in `knowledge/Candidates/{Name}/`.
34
+ - `screening.md` should exist; if missing, run `req-screen` first (proceed
35
+ regardless).
36
+
37
+ ## Inputs
38
+
39
+ - `knowledge/Candidates/{Name}/transcript-{date}.md`.
40
+ - `knowledge/Candidates/{Name}/screening.md`.
41
+ - `knowledge/Candidates/{Name}/brief.md` — target role.
42
+
43
+ ## Outputs
44
+
45
+ - `knowledge/Candidates/{Name}/interview-{date}.md`.
46
+ - `knowledge/Candidates/{Name}/panel.md` — only when more interviews are
47
+ planned.
48
+ - Updated `knowledge/Candidates/{Name}/brief.md`.
49
+
50
+ <do_confirm_checklist goal="Verify the assessment is grounded in transcript
51
+ evidence">
52
+
53
+ - [ ] Every skill re-rating cites a specific moment from the transcript.
54
+ - [ ] Behaviour assessments reference observed actions, not claimed traits.
55
+ - [ ] Level assessment uses standard progression criteria, not gut feel.
56
+ - [ ] Interviewer observations are attributed by name.
57
+ - [ ] Confirmed strengths and new concerns are distinguished.
58
+ - [ ] Panel brief (if created) is written for non-technical readers and ties
59
+ suggested questions to remaining gaps.
60
+ - [ ] Brief's Pipeline section, links, and Status are updated.
61
+ - [ ] Gender field is **not** updated from interview observations.
62
+
63
+ </do_confirm_checklist>
64
+
65
+ ## Procedure
66
+
67
+ ### 1. Read the transcript(s)
68
+
69
+ Extract the fields listed in
70
+ [references/rubric.md](references/rubric.md#what-to-extract-from-the-transcript).
71
+
72
+ ### 2. Load the standard reference
73
+
74
+ Use the role recorded in `screening.md` or `brief.md`:
75
+
76
+ ```bash
77
+ bunx fit-pathway job {discipline} {level} --track={track}
78
+ bunx fit-pathway skill {skill_id}
79
+ bunx fit-pathway behaviour --list
80
+ ```
81
+
82
+ If screening recommended a different level than originally targeted (e.g. J100 →
83
+ J090), load **both** for comparison.
84
+
85
+ ### 3. Re-rate skills
86
+
87
+ For each skill where the interview produced evidence, apply the adjustments in
88
+ [references/rubric.md](references/rubric.md#skill-re-rating). Cite a specific
89
+ moment, quote, or observation per change.
90
+
91
+ ### 4. Re-rate behaviours
92
+
93
+ Behaviours are better assessed in interviews than CVs — they describe how
94
+ someone acts, not what they've done. Use the
95
+ [behaviour signals](references/rubric.md#behaviour-signals) and the
96
+ [behaviour maturity scale](references/rubric.md#behaviour-maturity-scale).
97
+
98
+ ### 5. Assess level fit
99
+
100
+ ```bash
101
+ bunx fit-pathway progress {discipline} {level} --track={track}
102
+ ```
103
+
104
+ Apply the [level signals](references/rubric.md#level-signals).
105
+
106
+ ### 6. Write the interview assessment
107
+
108
+ Save to `knowledge/Candidates/{Name}/interview-{date}.md` using
109
+ [references/interview-template.md](references/interview-template.md). Include
110
+ only skills with new evidence — don't repeat the full matrix.
111
+
112
+ ### 7. Generate the panel brief (if applicable)
113
+
114
+ When more interview stages are planned (panel, technical, etc.), pull question
115
+ candidates:
116
+
117
+ ```bash
118
+ bunx fit-pathway interview {discipline} {level} --track={track}
119
+ ```
120
+
121
+ Save `knowledge/Candidates/{Name}/panel.md` using
122
+ [references/panel-template.md](references/panel-template.md). Audience:
123
+ next-stage interviewers, often non-engineers — explain without jargon and tie
124
+ suggested questions to remaining gaps.
125
+
126
+ ### 8. Update the candidate brief
127
+
128
+ Apply targeted Edit operations to `knowledge/Candidates/{Name}/brief.md`:
129
+
130
+ - Append a Pipeline entry with date, type, and outcome.
131
+ - Add `## Interview Notes` if missing, with key observations.
132
+ - Append `- [Interview Assessment](./interview-{date}.md)`.
133
+ - Append `- [Panel Brief](./panel.md)` when one was created.
134
+ - Update `Status` to reflect the current pipeline stage.
135
+
136
+ Never rewrite the file. Never update the Gender field from interview
137
+ observations.