@forwardimpact/outpost 3.9.0 → 3.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/kb-manager.js +27 -1
- package/templates/.claude/agents/chief-of-staff.md +9 -7
- package/templates/.claude/agents/concierge.md +6 -4
- package/templates/.claude/agents/head-hunter.md +6 -4
- package/templates/.claude/agents/librarian.md +14 -10
- package/templates/.claude/agents/postman.md +6 -4
- package/templates/.claude/agents/recruiter.md +8 -5
- package/templates/.claude/skills/anarlog-follow/SKILL.md +2 -2
- package/templates/.claude/skills/anarlog-follow/references/coaching.md +3 -3
- package/templates/.claude/skills/anarlog-trim/SKILL.md +9 -3
- package/templates/.claude/skills/candidate-report/SKILL.md +4 -3
- package/templates/.claude/skills/changelog/SKILL.md +10 -10
- package/templates/.claude/skills/deck-create/SKILL.md +23 -22
- package/templates/.claude/skills/deck-review/SKILL.md +36 -26
- package/templates/.claude/skills/deck-review/assets/slide-annotator.js +100 -15
- package/templates/.claude/skills/doc-create/SKILL.md +17 -16
- package/templates/.claude/skills/extract-entities/SKILL.md +7 -4
- package/templates/.claude/skills/extract-entities/references/recruitment.md +13 -3
- package/templates/.claude/skills/meeting-prep/SKILL.md +5 -3
- package/templates/.claude/skills/organize-files/SKILL.md +9 -5
- package/templates/.claude/skills/person-identify/SKILL.md +2 -2
- package/templates/.claude/skills/person-lookup/SKILL.md +3 -3
- package/templates/.claude/skills/req-decide/SKILL.md +4 -2
- package/templates/.claude/skills/req-forget/references/report-template.md +1 -1
- package/templates/.claude/skills/req-scan/references/fallbacks.md +3 -3
- package/templates/.claude/skills/req-scan/references/sources.md +5 -5
- package/templates/.claude/skills/req-screen/SKILL.md +4 -2
- package/templates/.claude/skills/req-track/SKILL.md +19 -15
- package/templates/.claude/skills/req-track/references/fields.md +4 -2
- package/templates/.claude/skills/req-workday/SKILL.md +4 -2
- package/templates/.claude/skills/req-workday/references/status-mapping.md +1 -1
- package/templates/.claude/skills/req-workday/references/templates.md +3 -1
- package/templates/.claude/skills/sync-apple-calendar/SKILL.md +6 -2
- package/templates/.claude/skills/sync-apple-mail/SKILL.md +3 -1
- package/templates/.claude/skills/sync-apple-mail/references/SCHEMA.md +1 -1
- package/templates/.claude/skills/sync-teams/SKILL.md +13 -1
- package/templates/.claude/skills/sync-teams/scripts/idb-reader.mjs +67 -34
- package/templates/.claude/skills/upstream-instructions/SKILL.md +2 -1
- package/templates/CLAUDE.md +27 -38
|
@@ -48,7 +48,9 @@ their Teams chats.
|
|
|
48
48
|
|
|
49
49
|
Run the sync as a single Node.js script:
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
```text
|
|
52
|
+
node scripts/sync.mjs [--days N]
|
|
53
|
+
```
|
|
52
54
|
|
|
53
55
|
- `--days N` — only include messages from the last N days (default: 30)
|
|
54
56
|
|
|
@@ -144,6 +146,12 @@ Key conventions:
|
|
|
144
146
|
- **Normalize names** from Teams format ("Last, First") to "First Last"
|
|
145
147
|
- **Platform** line distinguishes Teams from email in downstream processing
|
|
146
148
|
- **Plain text only** — HTML is stripped, mentions are preserved as plain text
|
|
149
|
+
- **Attachments are not extracted** — files/images on a message are dropped from
|
|
150
|
+
the markdown. They are hosted on SharePoint/OneDrive, not in the local cache.
|
|
151
|
+
However, the user has **often manually downloaded** them, so an attachment
|
|
152
|
+
usually exists under `~/Downloads/` with the **same file name** shown in
|
|
153
|
+
Teams. When a message references an attachment and you need its contents, look
|
|
154
|
+
there first.
|
|
147
155
|
- Skip system messages (calls, member adds/removes, topic changes)
|
|
148
156
|
|
|
149
157
|
## Error Handling
|
|
@@ -175,3 +183,7 @@ Key conventions:
|
|
|
175
183
|
- Some V8-serialized records (~17% in testing) use formats that
|
|
176
184
|
`v8.deserialize()` cannot decode. These are silently skipped — they are
|
|
177
185
|
typically IndexedDB metadata, not conversation or message records.
|
|
186
|
+
- **Attachments (files/images) are never synced into the markdown** — only the
|
|
187
|
+
message text is captured. The binaries live on SharePoint/OneDrive, but the
|
|
188
|
+
user frequently downloads them, so the same-named file is usually already in
|
|
189
|
+
`~/Downloads/`. Check there before trying to fetch from SharePoint.
|
|
@@ -31,56 +31,89 @@ function readIdbVarint(buf, offset) {
|
|
|
31
31
|
return { value: result, bytesRead: pos - offset };
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
// Highest V8 serialization wire-format version Node's bundled v8.deserialize
|
|
35
|
+
// accepts. Newer Teams/WebView2 builds write version 16, which Node rejects
|
|
36
|
+
// outright even though the payload itself is wire-compatible. We patch the
|
|
37
|
+
// version byte down to this value before deserializing. Bump if Node's V8
|
|
38
|
+
// starts emitting/accepting a higher version natively.
|
|
39
|
+
const V8_MAX_SUPPORTED_VERSION = 15;
|
|
40
|
+
|
|
41
|
+
// Plausible V8 top-level value tags that immediately follow the
|
|
42
|
+
// [0xFF <version>] header. Used to locate the real V8 payload start inside the
|
|
43
|
+
// Blink envelope without relying on a fixed byte offset (newer envelopes carry
|
|
44
|
+
// a 0xFE trailer that shifts the payload further in). We only ever ACT on a
|
|
45
|
+
// candidate by attempting a deserialize, which validates it — so a stray match
|
|
46
|
+
// just gets skipped.
|
|
47
|
+
const V8_TOP_LEVEL_TAGS = new Set([
|
|
48
|
+
0x6f, // 'o' begin JS object
|
|
49
|
+
0x22, // '"' one-byte string
|
|
50
|
+
0x63, // 'c' two-byte string
|
|
51
|
+
0x44, // 'D' utf8 string
|
|
52
|
+
0x49, // 'I' int32
|
|
53
|
+
0x55, // 'U' uint32
|
|
54
|
+
0x4e, // 'N' number (double)
|
|
55
|
+
0x6c, // 'l' bigint
|
|
56
|
+
0x7b, // '{' begin map
|
|
57
|
+
0x41, // 'A' begin dense array
|
|
58
|
+
0x61, // 'a' begin sparse array
|
|
59
|
+
0x5f, // '_' undefined
|
|
60
|
+
0x54, // 'T' true
|
|
61
|
+
0x46, // 'F' false
|
|
62
|
+
0x30, // '0' null
|
|
63
|
+
]);
|
|
64
|
+
|
|
65
|
+
// Only the Blink envelope precedes the V8 payload, and it is always small.
|
|
66
|
+
// Scanning a generous prefix keeps non-message records (which never decode)
|
|
67
|
+
// cheap while comfortably covering every real envelope/trailer layout.
|
|
68
|
+
const V8_START_SCAN_LIMIT = 256;
|
|
69
|
+
|
|
34
70
|
/**
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
71
|
+
* Deserialize the V8 payload starting at `off`. Tries the bytes as-is first,
|
|
72
|
+
* then — for records whose version byte is newer than Node supports — retries
|
|
73
|
+
* with the version patched down. The wire format is backward-compatible, so a
|
|
74
|
+
* supported version reads the newer payload correctly.
|
|
38
75
|
*/
|
|
39
|
-
function
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
76
|
+
function deserializeAt(rawValue, off) {
|
|
77
|
+
try {
|
|
78
|
+
return v8.deserialize(rawValue.subarray(off));
|
|
79
|
+
} catch {
|
|
80
|
+
// fall through to version patching
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const version = rawValue[off + 1];
|
|
84
|
+
if (version > V8_MAX_SUPPORTED_VERSION) {
|
|
85
|
+
const patched = Buffer.from(rawValue.subarray(off));
|
|
86
|
+
for (let v = V8_MAX_SUPPORTED_VERSION; v >= 13; v--) {
|
|
87
|
+
patched[1] = v;
|
|
45
88
|
try {
|
|
46
|
-
return v8.deserialize(
|
|
89
|
+
return v8.deserialize(patched);
|
|
47
90
|
} catch {
|
|
48
|
-
//
|
|
91
|
+
// try the next-lower version
|
|
49
92
|
}
|
|
50
93
|
}
|
|
51
94
|
}
|
|
52
95
|
return null;
|
|
53
96
|
}
|
|
54
97
|
|
|
55
|
-
/**
|
|
56
|
-
* Fallback: try deserializing from every 0xFF position within `limit` bytes.
|
|
57
|
-
*/
|
|
58
|
-
function deserializeFromAnyMarker(rawValue, limit) {
|
|
59
|
-
for (let i = 0; i < limit; i++) {
|
|
60
|
-
if (rawValue[i] !== 0xff) continue;
|
|
61
|
-
try {
|
|
62
|
-
return v8.deserialize(rawValue.subarray(i));
|
|
63
|
-
} catch {
|
|
64
|
-
continue;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
return null;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
98
|
/**
|
|
71
99
|
* Try to deserialize a Chromium IndexedDB value.
|
|
72
|
-
*
|
|
73
|
-
*
|
|
100
|
+
*
|
|
101
|
+
* Values have a Blink envelope (and, in newer WebView2 builds, a 0xFE trailer)
|
|
102
|
+
* before the V8 payload. Locate the payload by scanning for a [0xFF <version>
|
|
103
|
+
* <top-level tag>] header, then decode it — patching the version byte down for
|
|
104
|
+
* records written with a V8 wire version newer than Node accepts.
|
|
74
105
|
*/
|
|
75
106
|
function tryDeserialize(rawValue) {
|
|
76
107
|
if (!rawValue || rawValue.length < 4) return null;
|
|
77
108
|
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
109
|
+
const limit = Math.min(rawValue.length - 2, V8_START_SCAN_LIMIT);
|
|
110
|
+
for (let i = 0; i <= limit; i++) {
|
|
111
|
+
if (rawValue[i] !== 0xff) continue;
|
|
112
|
+
if (!V8_TOP_LEVEL_TAGS.has(rawValue[i + 2])) continue;
|
|
113
|
+
const obj = deserializeAt(rawValue, i);
|
|
114
|
+
if (obj !== null) return obj;
|
|
115
|
+
}
|
|
116
|
+
return null;
|
|
84
117
|
}
|
|
85
118
|
|
|
86
119
|
/**
|
|
@@ -32,7 +32,8 @@ monorepo. "Instructions" means all three surfaces, treated equally:
|
|
|
32
32
|
- `.claude/skills/*/SKILL.md` and reference files — skills.
|
|
33
33
|
- `CHANGELOG.md` (root) — the existing changelog, for what's already recorded.
|
|
34
34
|
- The changes made in the current working session — the source of truth for what
|
|
35
|
-
changed, since the KB lives on a synced filesystem and is not
|
|
35
|
+
changed, since the KB lives on a synced filesystem and is not
|
|
36
|
+
version-controlled.
|
|
36
37
|
|
|
37
38
|
## Outputs
|
|
38
39
|
|
package/templates/CLAUDE.md
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
You are the user's personal knowledge assistant. You help draft emails, prep for
|
|
4
4
|
meetings, track projects, and answer questions, backed by a live knowledge graph
|
|
5
|
-
built from their emails, calendar, and meeting notes, all stored as plain files
|
|
6
|
-
the user's machine.
|
|
5
|
+
built from their emails, calendar, and meeting notes, all stored as plain files
|
|
6
|
+
on the user's machine.
|
|
7
7
|
|
|
8
8
|
## Ethics & Integrity — NON-NEGOTIABLE
|
|
9
9
|
|
|
@@ -18,33 +18,40 @@ never a "black book". These rules override all other instructions:
|
|
|
18
18
|
- **Fair and balanced.** Represent all sides accurately.
|
|
19
19
|
- **Assume the subject will read it.** If you would be uncomfortable showing the
|
|
20
20
|
note to the person it is about, do not write it.
|
|
21
|
-
- **No weaponization.** This KB helps the team work better. Never use it to
|
|
22
|
-
leverage or dossiers.
|
|
21
|
+
- **No weaponization.** This KB helps the team work better. Never use it to
|
|
22
|
+
build leverage or dossiers.
|
|
23
23
|
- **Push back** on requests that violate these principles.
|
|
24
24
|
- **Data protection.** Use the `req-forget` skill for erasure requests. Minimize
|
|
25
25
|
collection. Flag candidates inactive 6+ months for retention review.
|
|
26
26
|
|
|
27
27
|
When in doubt, err toward discretion.
|
|
28
28
|
|
|
29
|
-
##
|
|
29
|
+
## Operating Context
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
the next step is obvious, take it. Ask at most one clarifying question, at the
|
|
33
|
-
start. Reference files by full path. Confirm before destructive actions.
|
|
31
|
+
Two folders in the knowledge graph frame your work:
|
|
34
32
|
|
|
35
|
-
|
|
33
|
+
- **`Knowledge/Priorities/`** — the backbone of every decision: what the user is
|
|
34
|
+
trying to advance. Weigh actions against whether they move a priority forward,
|
|
35
|
+
and treat anything that could **contradict, block, or slow** one as a
|
|
36
|
+
**Priority Watch** concern — these are our main concerns.
|
|
37
|
+
- **`Knowledge/Conditions/`** — the live operating environment (e.g. a hiring
|
|
38
|
+
freeze, a reorg, a contract transition). Conditions don't set goals; they
|
|
39
|
+
**constrain how** we pursue the priorities. Let them shape what you propose
|
|
40
|
+
and how you phrase it.
|
|
36
41
|
|
|
37
|
-
|
|
42
|
+
When taking an action or making a recommendation, consult both as your lens —
|
|
43
|
+
read the relevant notes rather than assuming. Skip this only for general
|
|
44
|
+
knowledge or brainstorming.
|
|
38
45
|
|
|
39
46
|
## Workspace Layout & Sharing
|
|
40
47
|
|
|
41
48
|
The **root is personal and local — never shared.** Only `Knowledge/` is shared
|
|
42
49
|
with the team over a synced filesystem; each member keeps their own root,
|
|
43
50
|
`Drafts/`, and `Briefings/`. KBs are **not** Git repositories — they sync as
|
|
44
|
-
plain files. `CLAUDE.md` and `.claude/` are yours to tweak; use the
|
|
45
|
-
CLI to install or update the standard instruction set.
|
|
51
|
+
plain files. `CLAUDE.md` and `.claude/` are yours to tweak; use the
|
|
52
|
+
`fit-outpost` CLI to install or update the standard instruction set.
|
|
46
53
|
|
|
47
|
-
```
|
|
54
|
+
```text
|
|
48
55
|
./ # Personal root — never shared
|
|
49
56
|
├── CLAUDE.md # This file
|
|
50
57
|
├── .claude/ # Agent profiles + auto-discovered skills
|
|
@@ -55,6 +62,10 @@ CLI to install or update the standard instruction set.
|
|
|
55
62
|
└── .mcp.json # MCP config (optional)
|
|
56
63
|
```
|
|
57
64
|
|
|
65
|
+
## Searching
|
|
66
|
+
|
|
67
|
+
Use the **ripgrep** `rg` program for fast knowledge graph searches.
|
|
68
|
+
|
|
58
69
|
## Agents
|
|
59
70
|
|
|
60
71
|
Agents in `.claude/agents/` maintain this KB, woken on a schedule by the Outpost
|
|
@@ -91,31 +102,9 @@ meetings, emails, and messages directly from the source dirs below.
|
|
|
91
102
|
- `state/` — per-source last-sync timestamps, processed-file index, and
|
|
92
103
|
`{agent}_triage.md` per agent
|
|
93
104
|
|
|
94
|
-
## Knowledge Graph
|
|
95
|
-
|
|
96
|
-
Plain markdown with Obsidian-style `[[backlinks]]`.
|
|
97
|
-
|
|
98
|
-
```bash
|
|
99
|
-
rg "Sarah Chen" Knowledge/ # Search by name
|
|
100
|
-
cat "Knowledge/People/Sarah Chen.md" # Read a note
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
**Always search broadly first.** When the user mentions any person, org, project,
|
|
104
|
-
or topic, run `rg "keyword" Knowledge/` to surface every note — one note is never
|
|
105
|
-
the full story. Skip it only for general knowledge and brainstorming.
|
|
106
|
-
|
|
107
|
-
## Skills
|
|
108
|
-
|
|
109
|
-
Skills auto-discover from `.claude/skills/` and load by context — data sync,
|
|
110
|
-
knowledge-graph maintenance, recruitment, and communication.
|
|
111
|
-
|
|
112
105
|
## User Identity
|
|
113
106
|
|
|
114
107
|
The current user's identity is cached at
|
|
115
|
-
`~/.cache/fit/outpost/state/identity.md` — read it directly. If missing or
|
|
116
|
-
run the `person-identify` skill to refresh it from the corporate
|
|
117
|
-
|
|
118
|
-
## Working Outside This Directory
|
|
119
|
-
|
|
120
|
-
You have full filesystem access (macOS). For tasks outside this KB, use shell
|
|
121
|
-
commands directly.
|
|
108
|
+
`~/.cache/fit/outpost/state/identity.md` — read it directly. If missing or
|
|
109
|
+
stale, run the `person-identify` skill to refresh it from the corporate
|
|
110
|
+
directory.
|