@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.
- package/package.json +3 -2
- package/src/kb-manager.js +58 -5
- package/src/kb-validator.js +762 -0
- package/src/outpost.js +73 -8
- package/templates/.claude/agents/chief-of-staff.md +14 -6
- package/templates/.claude/agents/concierge.md +9 -2
- package/templates/.claude/agents/head-hunter.md +9 -2
- package/templates/.claude/agents/librarian.md +11 -4
- package/templates/.claude/agents/postman.md +9 -2
- package/templates/.claude/agents/recruiter.md +9 -2
- package/templates/.claude/skills/anarlog-follow/SKILL.md +53 -29
- package/templates/.claude/skills/anarlog-follow/references/sessions.md +52 -0
- package/templates/.claude/skills/anarlog-process/SKILL.md +88 -45
- package/templates/.claude/skills/anarlog-process/references/extraction.md +19 -11
- package/templates/.claude/skills/anarlog-process/references/sessions.md +92 -58
- package/templates/.claude/skills/anarlog-process/scripts/scan.mjs +404 -163
- package/templates/.claude/skills/candidate-report/SKILL.md +12 -9
- package/templates/.claude/skills/changelog/SKILL.md +106 -56
- package/templates/.claude/skills/deck-create/SKILL.md +60 -2
- package/templates/.claude/skills/deck-review/SKILL.md +4 -1
- package/templates/.claude/skills/deck-summarize/SKILL.md +6 -2
- package/templates/.claude/skills/deck-summarize/references/brief-template.md +1 -1
- package/templates/.claude/skills/doc-collab/SKILL.md +16 -11
- package/templates/.claude/skills/doc-create/SKILL.md +6 -3
- package/templates/.claude/skills/draft-emails/SKILL.md +31 -25
- package/templates/.claude/skills/draft-emails/references/template.md +1 -1
- package/templates/.claude/skills/draft-emails/scripts/scan-emails.mjs +14 -8
- package/templates/.claude/skills/draft-emails/scripts/send-email.mjs +9 -3
- package/templates/.claude/skills/extract-entities/SKILL.md +17 -16
- package/templates/.claude/skills/extract-entities/references/TEMPLATES.md +2 -1
- package/templates/.claude/skills/extract-entities/references/conditions.md +6 -5
- package/templates/.claude/skills/extract-entities/references/links.md +34 -10
- package/templates/.claude/skills/extract-entities/references/recruitment.md +15 -10
- package/templates/.claude/skills/extract-entities/references/resolution.md +1 -1
- package/templates/.claude/skills/extract-entities/references/sources.md +1 -1
- package/templates/.claude/skills/extract-entities/references/templates-conditions.md +10 -4
- package/templates/.claude/skills/extract-entities/references/templates-people-orgs.md +29 -10
- package/templates/.claude/skills/extract-entities/references/templates-priorities.md +8 -2
- package/templates/.claude/skills/extract-entities/references/templates-projects-topics.md +19 -7
- package/templates/.claude/skills/meeting-prep/SKILL.md +23 -18
- package/templates/.claude/skills/organize-files/SKILL.md +3 -0
- package/templates/.claude/skills/person-identify/SKILL.md +58 -10
- package/templates/.claude/skills/person-identify/scripts/identify.sh +110 -11
- package/templates/.claude/skills/person-lookup/SKILL.md +8 -3
- package/templates/.claude/skills/person-lookup/scripts/lookup.sh +27 -1
- package/templates/.claude/skills/req-assess/SKILL.md +19 -11
- package/templates/.claude/skills/req-assess/references/interview-template.md +6 -1
- package/templates/.claude/skills/req-assess/references/panel-template.md +5 -1
- package/templates/.claude/skills/req-bundle/SKILL.md +164 -0
- package/templates/.claude/skills/req-bundle/references/matching.md +70 -0
- package/templates/.claude/skills/req-bundle/references/pdf-structure.md +74 -0
- package/templates/.claude/skills/req-bundle/scripts/split-bundle.mjs +377 -0
- package/templates/.claude/skills/req-decide/SKILL.md +26 -18
- package/templates/.claude/skills/req-decide/references/template.md +2 -2
- package/templates/.claude/skills/req-forget/SKILL.md +39 -22
- package/templates/.claude/skills/req-forget/references/classify.md +12 -10
- package/templates/.claude/skills/req-forget/references/locations.md +27 -22
- package/templates/.claude/skills/req-forget/references/report-template.md +23 -15
- package/templates/.claude/skills/req-scan/SKILL.md +6 -3
- package/templates/.claude/skills/req-scan/references/template.md +11 -1
- package/templates/.claude/skills/req-screen/SKILL.md +78 -34
- package/templates/.claude/skills/req-screen/references/rubric.md +38 -42
- package/templates/.claude/skills/req-screen/references/scoring.md +79 -0
- package/templates/.claude/skills/req-screen/references/template.md +26 -14
- package/templates/.claude/skills/req-track/SKILL.md +44 -44
- package/templates/.claude/skills/req-track/references/fields.md +18 -15
- package/templates/.claude/skills/req-track/references/overlays.md +42 -0
- package/templates/.claude/skills/req-track/references/signals.md +2 -2
- package/templates/.claude/skills/req-track/references/templates.md +28 -27
- package/templates/.claude/skills/req-workday/SKILL.md +49 -20
- package/templates/.claude/skills/req-workday/references/brief.md +81 -0
- package/templates/.claude/skills/req-workday/references/templates.md +6 -73
- package/templates/.claude/skills/req-workday/references/xlsx-format.md +19 -0
- package/templates/.claude/skills/req-workday/scripts/parse-workday.mjs +96 -20
- package/templates/.claude/skills/send-chat/SKILL.md +11 -11
- package/templates/.claude/skills/sync-apple-calendar/SKILL.md +3 -0
- package/templates/.claude/skills/sync-apple-mail/SKILL.md +3 -0
- package/templates/.claude/skills/sync-teams/SKILL.md +3 -0
- package/templates/.claude/skills/upstream-instructions/SKILL.md +8 -5
- package/templates/.claude/skills/upstream-instructions/references/examples.md +3 -3
- package/templates/CLAUDE.md +96 -87
- package/templates/MIGRATION.md +359 -0
- package/templates/registry.yaml +25 -0
- package/templates/.claude/skills/anarlog-follow/scripts/follow.mjs +0 -243
- package/templates/.claude/skills/anarlog-trim/SKILL.md +0 -186
|
@@ -54,20 +54,56 @@ try {
|
|
|
54
54
|
const filePath = process.argv[2];
|
|
55
55
|
const summaryMode = process.argv.includes("--summary");
|
|
56
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Read a workbook. Tolerate Workday's ZIP container.
|
|
59
|
+
*
|
|
60
|
+
* Workday exports .xlsx via Apache POI's streaming writer. That writer sets
|
|
61
|
+
* the ZIP "data descriptor" flag (bit 0x08) on every entry, so the sizes live
|
|
62
|
+
* in a trailer after each entry, not in the local header. read-excel-file's
|
|
63
|
+
* streaming unzipper trusts the (zeroed) local-header sizes, loses alignment,
|
|
64
|
+
* and throws `invalid signature: 0x…`. fflate reads the authoritative ZIP
|
|
65
|
+
* central directory, so on failure we re-pack into a clean container (sizes
|
|
66
|
+
* in the local headers, no data descriptors) and retry. Files that already
|
|
67
|
+
* parse take the original path unchanged.
|
|
68
|
+
*/
|
|
69
|
+
async function readWorkbook(path) {
|
|
70
|
+
try {
|
|
71
|
+
return await readXlsxFile(path);
|
|
72
|
+
} catch (err) {
|
|
73
|
+
let fflate;
|
|
74
|
+
try {
|
|
75
|
+
fflate = await import("fflate");
|
|
76
|
+
} catch {
|
|
77
|
+
throw err; // fflate unavailable — surface the original parse error
|
|
78
|
+
}
|
|
79
|
+
const { readFileSync } = await import("node:fs");
|
|
80
|
+
const raw = readFileSync(path);
|
|
81
|
+
const normalized = Buffer.from(
|
|
82
|
+
fflate.zipSync(fflate.unzipSync(new Uint8Array(raw))),
|
|
83
|
+
);
|
|
84
|
+
return await readXlsxFile(normalized);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// read-excel-file v9 returns the whole workbook as [{ sheet, data }] —
|
|
89
|
+
// read it once and index sheets from that.
|
|
90
|
+
const workbook = await readWorkbook(filePath);
|
|
91
|
+
const sheetNames = workbook.map((s) => s.sheet);
|
|
92
|
+
|
|
57
93
|
/** Read a sheet by number (1-indexed) or name. Rows are arrays of strings. */
|
|
58
|
-
|
|
59
|
-
const
|
|
94
|
+
function readSheet(_file, sheet) {
|
|
95
|
+
const entry =
|
|
96
|
+
typeof sheet === "number"
|
|
97
|
+
? workbook[sheet - 1]
|
|
98
|
+
: workbook.find((s) => s.sheet === sheet);
|
|
99
|
+
const rows = entry ? entry.data : [];
|
|
60
100
|
// Normalise null cells to empty strings to match previous behaviour
|
|
61
101
|
return rows.map((row) => row.map((cell) => (cell == null ? "" : cell)));
|
|
62
102
|
}
|
|
63
103
|
|
|
64
|
-
// Get sheet names to find the candidates sheet
|
|
65
|
-
const sheets = await readXlsxFile(filePath, { getSheets: true });
|
|
66
|
-
const sheetNames = sheets.map((s) => s.name);
|
|
67
|
-
|
|
68
104
|
// --- Sheet 1: Requisition metadata ---
|
|
69
105
|
|
|
70
|
-
const sheet1Rows =
|
|
106
|
+
const sheet1Rows = readSheet(filePath, 1);
|
|
71
107
|
|
|
72
108
|
/** Extract the requisition ID and title from the header row. */
|
|
73
109
|
function parseReqHeader(headerText) {
|
|
@@ -120,7 +156,7 @@ const requisition = {
|
|
|
120
156
|
const candSheetName =
|
|
121
157
|
sheetNames.find((n) => n.toLowerCase() === "candidates") ||
|
|
122
158
|
sheetNames[Math.min(2, sheetNames.length - 1)];
|
|
123
|
-
const candRows =
|
|
159
|
+
const candRows = readSheet(filePath, candSheetName);
|
|
124
160
|
|
|
125
161
|
// Find the header row dynamically. Look for a row that contains "Stage".
|
|
126
162
|
// Old format: row 3 (index 2). New format: row 8 (index 7).
|
|
@@ -194,24 +230,64 @@ function col(row, field) {
|
|
|
194
230
|
return row[idx] ?? "";
|
|
195
231
|
}
|
|
196
232
|
|
|
233
|
+
// Any character outside the Latin script blocks (Basic Latin + Latin-1
|
|
234
|
+
// Supplement + Latin Extended-A/B + Latin Extended Additional). Accented Latin
|
|
235
|
+
// (é, ñ, ø, ç, Vietnamese, …) stays; Greek, Cyrillic, CJK, Arabic, Hebrew,
|
|
236
|
+
// etc. count as native-alphabet text to drop.
|
|
237
|
+
const NON_LATIN = /[^\u0020-\u024F\u1E00-\u1EFF]/;
|
|
238
|
+
const HAS_LATIN_LETTER = /[A-Za-z\u00C0-\u024F\u1E00-\u1EFF]/;
|
|
239
|
+
|
|
197
240
|
/**
|
|
198
|
-
* Clean a candidate name
|
|
199
|
-
*
|
|
241
|
+
* Clean a candidate name into the canonical Latin name.
|
|
242
|
+
*
|
|
243
|
+
* Workday encodes several things in the name cell as parentheticals:
|
|
244
|
+
* - Employment annotations: `(Internal)`, `(Prior Worker)`, `(External)`.
|
|
245
|
+
* - A native-alphabet transliteration of the name, e.g.
|
|
246
|
+
* `Nikos Papadopoulos (ΝΙΚΟΣ ΠΑΠΑΔΟΠΟΥΛΟΣ)` or `Wei Zhang (张伟)`.
|
|
247
|
+
* A name may carry both, in either paren style. Normalise on the Latin name:
|
|
248
|
+
* strip every trailing parenthetical (classify employment ones into
|
|
249
|
+
* `internalExternal`, discard native-alphabet ones), then drop any residual
|
|
250
|
+
* non-Latin-script tokens. Returns { cleanName, internalExternal }.
|
|
200
251
|
*/
|
|
252
|
+
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: annotation peel loop classifies employment vs transliteration cases
|
|
201
253
|
function parseName(raw) {
|
|
202
|
-
|
|
254
|
+
// Normalise full-width parens () to ASCII so both styles strip uniformly.
|
|
255
|
+
let name = String(raw).replace(/(/g, "(").replace(/)/g, ")").trim();
|
|
203
256
|
if (!name) return { cleanName: "", internalExternal: "" };
|
|
204
257
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
258
|
+
let internalExternal = "";
|
|
259
|
+
// Repeatedly peel a trailing parenthetical group (allowing one level of
|
|
260
|
+
// nesting so `(External (Prior Worker))` is captured whole).
|
|
261
|
+
const trailing = /\s*\(([^()]*(?:\([^()]*\)[^()]*)*)\)\s*$/;
|
|
262
|
+
let m;
|
|
263
|
+
while ((m = name.match(trailing)) !== null) {
|
|
264
|
+
const annotation = m[1].trim();
|
|
265
|
+
if (/prior\s*worker/i.test(annotation)) {
|
|
266
|
+
if (!internalExternal) internalExternal = "External (Prior Worker)";
|
|
267
|
+
} else if (/internal/i.test(annotation)) {
|
|
268
|
+
if (!internalExternal) internalExternal = "Internal";
|
|
269
|
+
} else if (/external/i.test(annotation)) {
|
|
270
|
+
if (!internalExternal) internalExternal = "External";
|
|
271
|
+
} else if (NON_LATIN.test(annotation)) {
|
|
272
|
+
// Native-alphabet transliteration of the name — drop, no IE signal.
|
|
273
|
+
} else if (!internalExternal && annotation) {
|
|
274
|
+
// Unknown Latin annotation — preserve prior behaviour (first one wins).
|
|
275
|
+
internalExternal = annotation;
|
|
276
|
+
}
|
|
277
|
+
name = name.slice(0, name.length - m[0].length).trim();
|
|
213
278
|
}
|
|
214
|
-
|
|
279
|
+
|
|
280
|
+
// Drop any residual whole-word tokens that are purely non-Latin script
|
|
281
|
+
// (e.g. a native name appended without parentheses). Keep Latin tokens
|
|
282
|
+
// and pure punctuation/digits.
|
|
283
|
+
name = name
|
|
284
|
+
.split(/\s+/)
|
|
285
|
+
.filter((tok) => HAS_LATIN_LETTER.test(tok) || !NON_LATIN.test(tok))
|
|
286
|
+
.join(" ")
|
|
287
|
+
.replace(/\s{2,}/g, " ")
|
|
288
|
+
.trim();
|
|
289
|
+
|
|
290
|
+
return { cleanName: name, internalExternal };
|
|
215
291
|
}
|
|
216
292
|
|
|
217
293
|
/** Detect source-based internal/external when the name annotation is absent. */
|
|
@@ -8,6 +8,9 @@ compatibility:
|
|
|
8
8
|
|
|
9
9
|
# Send Chat
|
|
10
10
|
|
|
11
|
+
Write tier: `0-Draft` (sending is an export)
|
|
12
|
+
Frontmatter: none
|
|
13
|
+
|
|
11
14
|
Send chat messages to people with browser automation against a web-based chat
|
|
12
15
|
platform (Microsoft Teams, Slack, or similar). This skill resolves recipients by
|
|
13
16
|
name from the knowledge graph. The user can say "message Sarah about the
|
|
@@ -36,7 +39,7 @@ base.**
|
|
|
36
39
|
When the user mentions ANY person:
|
|
37
40
|
|
|
38
41
|
1. **STOP** — Do not open the chat platform yet
|
|
39
|
-
2. **SEARCH** — Look them up: `rg -l "{name}"
|
|
42
|
+
2. **SEARCH** — Look them up: `rg -l "{name}" 3-Team/People/`
|
|
40
43
|
3. **READ** — Read their note to understand context, role, recent interactions
|
|
41
44
|
4. **UNDERSTAND** — Know who they are and what you work on together
|
|
42
45
|
5. **THEN PROCEED** — Only now compose the message and use browser automation
|
|
@@ -54,10 +57,10 @@ reference to a full name with the knowledge graph:
|
|
|
54
57
|
|
|
55
58
|
```bash
|
|
56
59
|
# Find person by partial name
|
|
57
|
-
rg -l -i "{name}"
|
|
60
|
+
rg -l -i "{name}" 3-Team/People/
|
|
58
61
|
|
|
59
62
|
# If ambiguous, read candidates to disambiguate
|
|
60
|
-
cat "
|
|
63
|
+
cat "3-Team/People/{Candidate}.md"
|
|
61
64
|
```
|
|
62
65
|
|
|
63
66
|
**If ambiguous** (multiple matches), ask the user which person they mean. List
|
|
@@ -74,7 +77,7 @@ can review and edit the exact message before you send it.
|
|
|
74
77
|
### Draft Workflow
|
|
75
78
|
|
|
76
79
|
1. **Compose the message** based on context and user intent.
|
|
77
|
-
2. **Write it to a draft file** at `
|
|
80
|
+
2. **Write it to a draft file** at `0-Draft/chat-{recipient-slug}-{date}.md`
|
|
78
81
|
- `{recipient-slug}` = lowercase, hyphenated full name (e.g. `sarah-chen`)
|
|
79
82
|
- `{date}` = ISO date (e.g. `2026-02-19`)
|
|
80
83
|
3. **Show the user the draft** — display the file path and contents.
|
|
@@ -139,14 +142,11 @@ same organization.
|
|
|
139
142
|
4. Press Enter or click Send
|
|
140
143
|
5. Take a screenshot to confirm the message was sent
|
|
141
144
|
|
|
142
|
-
### Step 4:
|
|
143
|
-
|
|
144
|
-
If the message is substantive (not just "hey" or "thanks"), note the interaction
|
|
145
|
-
on the person's knowledge note:
|
|
145
|
+
### Step 4: Keep the Draft as the Record
|
|
146
146
|
|
|
147
|
-
|
|
148
|
-
-
|
|
149
|
-
|
|
147
|
+
Do not write the interaction to the person's note. This skill writes only to
|
|
148
|
+
`0-Draft/`. The chat sync (`sync-teams`) and `extract-entities` record the
|
|
149
|
+
interaction when the messages sync.
|
|
150
150
|
|
|
151
151
|
## Error Handling
|
|
152
152
|
|
|
@@ -6,6 +6,9 @@ compatibility: Requires macOS with Apple Calendar configured and Full Disk Acces
|
|
|
6
6
|
|
|
7
7
|
# Sync Apple Calendar
|
|
8
8
|
|
|
9
|
+
Write tier: none (cache only)
|
|
10
|
+
Frontmatter: none
|
|
11
|
+
|
|
9
12
|
Sync calendar events from the macOS Calendar app's local SQLite database into
|
|
10
13
|
`~/.cache/fit/outpost/apple_calendar/` as JSON files. This is an automated skill
|
|
11
14
|
in the data pipeline. It ingests raw calendar data that other skills (like
|
|
@@ -6,6 +6,9 @@ compatibility: Requires macOS with Apple Mail configured and Full Disk Access gr
|
|
|
6
6
|
|
|
7
7
|
# Sync Apple Mail
|
|
8
8
|
|
|
9
|
+
Write tier: none (cache only)
|
|
10
|
+
Frontmatter: none
|
|
11
|
+
|
|
9
12
|
Sync email threads from the macOS Mail app's local SQLite database into
|
|
10
13
|
`~/.cache/fit/outpost/apple_mail/` as markdown files. This is an automated skill
|
|
11
14
|
in the data pipeline. It ingests raw email data that other skills (like
|
|
@@ -6,6 +6,9 @@ compatibility: Requires macOS with Microsoft Teams desktop app (com.microsoft.te
|
|
|
6
6
|
|
|
7
7
|
# Sync Teams
|
|
8
8
|
|
|
9
|
+
Write tier: none (cache only)
|
|
10
|
+
Frontmatter: none
|
|
11
|
+
|
|
9
12
|
Sync recent Microsoft Teams chat messages into
|
|
10
13
|
`~/.cache/fit/outpost/teams_chat/` as markdown files. This is an automated skill
|
|
11
14
|
in the data pipeline. It ingests chat data that other skills (like
|
|
@@ -5,6 +5,9 @@ description: Track changes to this installation's instruction files: the root CL
|
|
|
5
5
|
|
|
6
6
|
# Upstream Instructions
|
|
7
7
|
|
|
8
|
+
Write tier: none (the root CHANGELOG.md is a personal surface)
|
|
9
|
+
Frontmatter: none
|
|
10
|
+
|
|
8
11
|
Track changes to this installation's **instructions**. Record them in one root
|
|
9
12
|
`CHANGELOG.md` so you can contribute improvements back to the upstream monorepo.
|
|
10
13
|
"Instructions" means all three surfaces, and they carry equal weight:
|
|
@@ -32,7 +35,7 @@ Track changes to this installation's **instructions**. Record them in one root
|
|
|
32
35
|
- `.claude/skills/*/SKILL.md` and reference files — skills.
|
|
33
36
|
- `CHANGELOG.md` (root) — the existing changelog, for what's already recorded.
|
|
34
37
|
- The changes you made in the current working session — the source of truth for
|
|
35
|
-
what changed. The KB
|
|
38
|
+
what changed. The KB may sync without version control; do not rely on it.
|
|
36
39
|
|
|
37
40
|
## Outputs
|
|
38
41
|
|
|
@@ -64,8 +67,8 @@ head -20 CHANGELOG.md 2>/dev/null # newest date already recorded, if any
|
|
|
64
67
|
|
|
65
68
|
### 2. Identify changed instructions
|
|
66
69
|
|
|
67
|
-
|
|
68
|
-
|
|
70
|
+
A knowledge base may sync over a mount with no version control, so never rely
|
|
71
|
+
on commit history. Identify what changed from the work you did **this
|
|
69
72
|
session**. Recall every edit, addition, removal, and rename you made to
|
|
70
73
|
`CLAUDE.md`, `.claude/agents/`, and `.claude/skills/` during the current
|
|
71
74
|
conversation. List them per surface.
|
|
@@ -102,8 +105,8 @@ Every entry must answer:
|
|
|
102
105
|
2. **Why?** — the problem encountered or improvement discovered in use.
|
|
103
106
|
3. **Details** — a summary of the actual change (not a full diff).
|
|
104
107
|
|
|
105
|
-
Good: "Agents now read `
|
|
106
|
-
flag anything that threatens a priority. Drafts and triage ignored strategic
|
|
108
|
+
Good: "Agents now read `Priorities/` in every tier at the start of every wake
|
|
109
|
+
and flag anything that threatens a priority. Drafts and triage ignored strategic
|
|
107
110
|
context."
|
|
108
111
|
|
|
109
112
|
Bad: "Updated the agents" / "Fixed stuff" / "Changed line 42".
|
|
@@ -20,7 +20,7 @@ strategic layer.
|
|
|
20
20
|
Priorities, removing the Project↔Goal↔Priority coupling that earned nothing.
|
|
21
21
|
|
|
22
22
|
**Details:**
|
|
23
|
-
- Deleted `
|
|
23
|
+
- Deleted `3-Team/Goals/`; repointed live backlinks to `3-Team/Priorities/C - Onboarding`.
|
|
24
24
|
- CLAUDE.md workspace-layout tree no longer lists `Goals/`.
|
|
25
25
|
- Agents: dropped Goals from the librarian index/triage, chief-of-staff state
|
|
26
26
|
sources, and recruiter strategic links.
|
|
@@ -61,7 +61,7 @@ invisible without structured gender data.
|
|
|
61
61
|
**Scope:** agents: all six profiles
|
|
62
62
|
**Type:** modified
|
|
63
63
|
|
|
64
|
-
**What:** Agents now read `
|
|
64
|
+
**What:** Agents now read `Priorities/` in every tier at the start of every wake and
|
|
65
65
|
flag anything that threatens a priority.
|
|
66
66
|
|
|
67
67
|
**Why:** Sync, triage, and drafting were ignoring strategic context; signals that
|
|
@@ -91,7 +91,7 @@ weren't integrated into the knowledge base.
|
|
|
91
91
|
|
|
92
92
|
**Details:**
|
|
93
93
|
- Reads transcription files, extracts people/decisions/action items, and links
|
|
94
|
-
attendees to `
|
|
94
|
+
attendees to `3-Team/People/`.
|
|
95
95
|
|
|
96
96
|
---
|
|
97
97
|
```
|
package/templates/CLAUDE.md
CHANGED
|
@@ -1,113 +1,122 @@
|
|
|
1
1
|
# Outpost Knowledge Base
|
|
2
2
|
|
|
3
|
-
You are the user's personal knowledge assistant
|
|
4
|
-
|
|
5
|
-
backs your work. It comes from their emails, calendar, and meeting notes. It
|
|
6
|
-
keeps them all as plain files on the user's machine.
|
|
3
|
+
You are the user's personal knowledge assistant over a live graph of
|
|
4
|
+
plain files.
|
|
7
5
|
|
|
8
6
|
## Ethics & Integrity — NON-NEGOTIABLE
|
|
9
7
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
instructions:
|
|
8
|
+
A professional tool shared with trusted teammates, never a "black book".
|
|
9
|
+
These rules override all others:
|
|
13
10
|
|
|
14
11
|
- **Objective and factual only.** No speculation, gossip, or opinion.
|
|
15
12
|
- **No personal judgments** about character, competence, or trustworthiness.
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
political views, or private matters, unless the person shares them in a
|
|
19
|
-
professional context.
|
|
13
|
+
- **Work-relevant only.** No health, relationships, politics, private
|
|
14
|
+
matters.
|
|
20
15
|
- **Fair and balanced.** Represent all sides accurately.
|
|
21
|
-
- **Assume the subject will read it
|
|
22
|
-
|
|
23
|
-
- **No weaponization.**
|
|
24
|
-
build leverage or dossiers.
|
|
16
|
+
- **Assume the subject will read it**, whatever the tier. Tiers never
|
|
17
|
+
license dossiers.
|
|
18
|
+
- **No weaponization.** Never build leverage.
|
|
25
19
|
- **Push back** on requests that violate these principles.
|
|
26
|
-
- **Data protection.**
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
When in doubt, err toward discretion.
|
|
20
|
+
- **Data protection.** `req-forget` handles erasure. Collect minimally; flag
|
|
21
|
+
candidates inactive 6+ months.
|
|
30
22
|
|
|
31
23
|
## Operating Context
|
|
32
24
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
the user wants to advance. Weigh each action against whether it moves a
|
|
37
|
-
priority forward. Treat anything that could **contradict, block, or slow** a
|
|
38
|
-
priority as a **Priority Watch** concern. These are our main concerns.
|
|
39
|
-
- **`Knowledge/Conditions/`** — the live environment we work in (e.g. a hiring
|
|
40
|
-
freeze, a reorg, a contract transition). Conditions do not set goals. They
|
|
41
|
-
**constrain how** we pursue the priorities. Let them shape what you propose
|
|
42
|
-
and how you phrase it.
|
|
43
|
-
|
|
44
|
-
Before you act or recommend, consult both as your lens. Read the relevant
|
|
45
|
-
notes. Do not assume. Skip this only for general knowledge or when you
|
|
46
|
-
brainstorm.
|
|
25
|
+
Read `Priorities/` and `Conditions/` in every tier present before you act.
|
|
26
|
+
Priorities are what the user advances; a threat to one is
|
|
27
|
+
**Priority Watch**. Conditions constrain how you pursue them.
|
|
47
28
|
|
|
48
29
|
## Workspace Layout & Sharing
|
|
49
30
|
|
|
50
|
-
The
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
`
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
31
|
+
The KB root is the Obsidian vault. Tier directories (one digit, one dash) are
|
|
32
|
+
the graph and the share units; a lower rank is a narrower audience. Every other
|
|
33
|
+
root entry is personal, never shared (instruction files, `Briefings/`,
|
|
34
|
+
`registry.yaml`, `validation-baseline.json`); personal folders never match the
|
|
35
|
+
rank grammar.
|
|
36
|
+
|
|
37
|
+
- `0-Draft/` — owner only, never shared: drafts, agent reports, permanent
|
|
38
|
+
owner-only notes.
|
|
39
|
+
- `1-Management/` — senior managers. User-placed; fellow-manager notes go
|
|
40
|
+
to tier 0.
|
|
41
|
+
- `2-Confidential/` — hiring managers. Candidates, Prospects, Roles,
|
|
42
|
+
Erasure.
|
|
43
|
+
- `3-Team/` — the team. People, Teams, Organizations, Projects, Topics,
|
|
44
|
+
Priorities, Conditions, Tasks.
|
|
45
|
+
- `4-Public/` — anyone. User-placed after rights and verification checks.
|
|
46
|
+
|
|
47
|
+
Rename, add, or remove tiers; entity subdirectories appear on demand.
|
|
48
|
+
|
|
49
|
+
Sharing is cumulative: a tier-N member receives every wider tier, from
|
|
50
|
+
tier 1 up, over any syncing mount (OneDrive, Git). A shared tier is often a
|
|
51
|
+
symlink into a synced folder; the rank comes from the link's name. Keep
|
|
52
|
+
the vault root outside every cloud-synced folder.
|
|
53
|
+
`npx fit-outpost validate <root>` checks any vault or suffix.
|
|
54
|
+
|
|
55
|
+
## Placement and Links
|
|
56
|
+
|
|
57
|
+
- Link only to your own tier or a wider one, never narrower or personal.
|
|
58
|
+
- Shared-tier links are tier-prefixed and vault-absolute
|
|
59
|
+
(`[[3-Team/People/Sarah Chen]]`); bare basenames only in tier 0 or one
|
|
60
|
+
entity folder.
|
|
61
|
+
- Place each note in the widest tier that excludes everyone who must not
|
|
62
|
+
read it; otherwise tier 0.
|
|
63
|
+
- Promote: a human moves a note into its tier. Export: a skill
|
|
64
|
+
sends a copy over mail or chat; the note keeps its tier. Named recipients
|
|
65
|
+
and panels are exports.
|
|
66
|
+
- Overlay: a narrower facet in a narrower tier, declared by a one-way
|
|
67
|
+
quoted `canonical` link to the wide note. Forms: facet, timeline split
|
|
68
|
+
(same date keys), inverse stub (linked down to).
|
|
69
|
+
- Link inversion: the wide note's narrow link moves, with its one-line
|
|
70
|
+
context, into the narrow note; no tombstone.
|
|
71
|
+
- Route each dated entry to the note in its own tier.
|
|
72
|
+
- Aggregates over narrower sources go to `0-Draft/`; no agent writes
|
|
73
|
+
tier 1.
|
|
74
|
+
- `no-redistribute` overrides tier; marked or third-party content never
|
|
75
|
+
enters tier 4.
|
|
76
|
+
- Assessment prose about a named subject lives only in that subject's
|
|
77
|
+
record.
|
|
78
|
+
|
|
79
|
+
## Note Metadata
|
|
80
|
+
|
|
81
|
+
Stamp YAML frontmatter on every note. Humans edit `registry.yaml`; agents
|
|
82
|
+
select from it.
|
|
83
|
+
|
|
84
|
+
- Core on every shared note: `type`, `created`, `updated` (ISO dates).
|
|
85
|
+
- Conditional: `aliases` (person, candidate, organization), `status`
|
|
86
|
+
(candidate, prospect), `canonical` (overlays), `verified` (tier 4).
|
|
87
|
+
- Flat block at line 1, snake_case, canonical key order; property links
|
|
88
|
+
double-quoted, tier-prefixed.
|
|
89
|
+
- No tier, rank, or audience key; the path is the sole tier authority.
|
|
90
|
+
- Tags: the closed `topic/` registry taxonomy, frontmatter `tags` only;
|
|
91
|
+
each tag carries its widest tier.
|
|
92
|
+
- Coherence: Bases on `type`/`status`, aliases in the switcher, path-keyed
|
|
93
|
+
graph groups; absolute-link, same-folder vault settings.
|
|
70
94
|
|
|
71
95
|
## Agents
|
|
72
96
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
Execute it.
|
|
76
|
-
|
|
77
|
-
Each agent's own profile under `.claude/agents/` declares its skills.
|
|
97
|
+
The scheduler wakes the `.claude/agents/` agents: observe, decide,
|
|
98
|
+
execute. Profiles declare skills, read scope, write tier.
|
|
78
99
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
| **head-hunter** | Passive talent scouting | Every 60 min |
|
|
86
|
-
| **chief-of-staff** | Daily briefings and priorities | 7am, Mon 7:30am |
|
|
87
|
-
|
|
88
|
-
Each agent writes `~/.cache/fit/outpost/state/{agent}_triage.md` per wake. The
|
|
89
|
-
**chief-of-staff** reads all of them to write daily briefings in `Briefings/`.
|
|
100
|
+
- **postman** (5 min) — communication triage and drafts
|
|
101
|
+
- **concierge** (10 min) — meeting prep and transcripts
|
|
102
|
+
- **librarian** (15 min) — knowledge graph maintenance
|
|
103
|
+
- **recruiter** (30 min) — engineering recruitment
|
|
104
|
+
- **head-hunter** (60 min) — passive talent scouting
|
|
105
|
+
- **chief-of-staff** (daily 7am) — briefings in `Briefings/`
|
|
90
106
|
|
|
91
107
|
## Cache Directory (`~/.cache/fit/outpost/`)
|
|
92
108
|
|
|
93
|
-
Synced data and runtime state live outside the KB.
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
**Resolve `~` before you pass a path to a tool.** Shell commands expand `~`.
|
|
97
|
-
The Write and Edit tools do not. A literal `~/...` creates a stray `.cache/`
|
|
98
|
-
inside the KB. Read `$HOME` at runtime and pass the full `$HOME/...` path. Read
|
|
99
|
-
meetings, emails, and messages directly from the source dirs below.
|
|
109
|
+
Synced data and runtime state live outside the KB. Resolve `~` to `$HOME`
|
|
110
|
+
for Write and Edit; search with `rg`.
|
|
100
111
|
|
|
101
|
-
- `apple_mail/` —
|
|
102
|
-
- `
|
|
103
|
-
- `
|
|
104
|
-
- `
|
|
105
|
-
- `state/` — per-source last-sync timestamps, processed-file index, and
|
|
106
|
-
`{agent}_triage.md` per agent
|
|
112
|
+
- `apple_mail/`, `apple_calendar/`, `teams_chat/` — synced sources
|
|
113
|
+
- `head-hunter/` — agent memory
|
|
114
|
+
- `drafts/` — the draft-status ledgers (`handled`, `ignored`)
|
|
115
|
+
- `state/` — daemon-owned sync state and triage files
|
|
107
116
|
|
|
108
|
-
## User Identity
|
|
117
|
+
## User Identity & Team
|
|
109
118
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
119
|
+
Read `~/.cache/fit/outpost/state/identity.md`; refresh with
|
|
120
|
+
`person-identify`. Manager plus Direct reports define "our team";
|
|
121
|
+
`Direct reports: none` means an individual contributor. Resolve peers with
|
|
122
|
+
`person-lookup` on the Manager. Never guess.
|