Summary
Tools/KnowledgeHarvester.ts is hardcoded single-PAI-instance. KNOWLEDGE_DIR = path.join(PAI_DIR, "MEMORY", "KNOWLEDGE") and WORK_DIR = path.join(PAI_DIR, "MEMORY", "WORK") mean it only sees one tree at a time. Real PAI users accumulate session work across many per-project Claude Code memory directories at ~/.claude/projects/<project-slug>/memory/[MEMORY/]WORK/, and that work is invisible to the central knowledge dashboard.
scanAutoMemory (line 113) reads AUTO_MEMORY_DIR = ~/.claude/projects/-Users-${USER}--claude/memory — but that's only the global home-dir claude session, not the dozens of per-project sessions that contain substantive work.
Repro
- Use Claude Code from multiple project directories over months (e.g.,
~/dev/myproject1, ~/dev/myproject2).
- Each project accumulates session content at
~/.claude/projects/-Users-myuser-dev-myproject1/memory/MEMORY/WORK/<session>/PRD.md (or ISA.md post-v4.1.0).
- Run
bun KnowledgeHarvester.ts harvest.
- Result: 0 candidates from your per-project work — only the central
~/.claude/PAI/MEMORY/WORK/ is scanned (and only if it contains ISAs, which NATIVE-mode sessions don't produce).
- Pulse
/knowledge dashboard shows 0/0/0/0 across People/Companies/Ideas/Research despite real work having occurred.
In my case: 40 PRD.md files exist across 7 projects spanning months of substantive work. None are reachable by the harvester.
Workaround (current state)
Per-project run with PAI_DIR override + manual cp bridge:
PROJ=~/.claude/projects/<proj-slug>/memory
# rename PRD → ISA so harvester sees them
/usr/bin/find "$PROJ" -name "PRD.md" -exec bash -c 'mv "$1" "${1%PRD.md}ISA.md"' _ {} \;
# harvest into per-project silo
cd ~/.claude/PAI && PAI_DIR="$PROJ" bun Tools/KnowledgeHarvester.ts harvest
# bridge silo to central
for d in Ideas Companies People Research; do
[ -d "$PROJ/MEMORY/KNOWLEDGE/$d" ] && \
mkdir -p ~/.claude/PAI/MEMORY/KNOWLEDGE/$d && \
/bin/cp "$PROJ/MEMORY/KNOWLEDGE/$d"/*.md ~/.claude/PAI/MEMORY/KNOWLEDGE/$d/ 2>/dev/null
done
Tedious, requires per-project iteration, leaves duplicate KNOWLEDGE silos in each project's memory dir.
Suggested fix
Extend scanWorkISAs (line 145ish) to also discover per-project memory dirs via glob. New behavior:
function scanWorkISAs(state: HarvestState, isBackfill: boolean): HarvestCandidate[] {
const candidates: HarvestCandidate[] = [];
// 1. Existing: scan central PAI WORK
candidates.push(...scanWorkDir(WORK_DIR, state, isBackfill));
// 2. NEW: scan per-project memory dirs
const PROJECTS_DIR = path.join(HOME, ".claude", "projects");
if (fs.existsSync(PROJECTS_DIR)) {
for (const proj of fs.readdirSync(PROJECTS_DIR)) {
// Per-project layout has BOTH memory/WORK and memory/MEMORY/WORK historically
for (const subpath of ["memory/WORK", "memory/MEMORY/WORK"]) {
const projWorkDir = path.join(PROJECTS_DIR, proj, subpath);
if (fs.existsSync(projWorkDir)) {
candidates.push(...scanWorkDir(projWorkDir, state, isBackfill, { sourceProject: proj }));
}
}
}
}
return candidates;
}
Where scanWorkDir is the extracted version of the current per-dir loop, and sourceProject becomes a tag/frontmatter field on the resulting harvest candidate so provenance carries.
File-name compatibility
The companion fix to ISASync.hook.ts (commit history shows v4.1.0 added the ISA.md ?? PRD.md read-fallback) should be mirrored in the harvester:
const isaPath = path.join(WORK_DIR, dir, "ISA.md");
const prdPath = path.join(WORK_DIR, dir, "PRD.md");
const filePath = fs.existsSync(isaPath) ? isaPath : (fs.existsSync(prdPath) ? prdPath : null);
if (!filePath) continue;
This avoids forcing every user to mass-rename historical PRDs (most users have months of pre-v4.1.0 sessions).
Verified locally
Patched the workflow manually with PAI_DIR override + bridge cp. End-to-end works: 10 MemberOS PRDs → renamed to ISAs → harvested → 5 entries surfaced into central KNOWLEDGE/. Pulse /knowledge flipped from 0/0/0/0 to 1/1/3/0. Same recipe applies to remaining 30 PRDs across 6 other projects, but the per-project iteration + cp bridge is friction this issue would eliminate.
Related
- Companion issue:
KnowledgeHarvester.ts writes directly to domain dirs, bypassing the documented _harvest-queue/ curation step (filed separately).
Summary
Tools/KnowledgeHarvester.tsis hardcoded single-PAI-instance.KNOWLEDGE_DIR = path.join(PAI_DIR, "MEMORY", "KNOWLEDGE")andWORK_DIR = path.join(PAI_DIR, "MEMORY", "WORK")mean it only sees one tree at a time. Real PAI users accumulate session work across many per-project Claude Code memory directories at~/.claude/projects/<project-slug>/memory/[MEMORY/]WORK/, and that work is invisible to the central knowledge dashboard.scanAutoMemory(line 113) readsAUTO_MEMORY_DIR = ~/.claude/projects/-Users-${USER}--claude/memory— but that's only the global home-dir claude session, not the dozens of per-project sessions that contain substantive work.Repro
~/dev/myproject1,~/dev/myproject2).~/.claude/projects/-Users-myuser-dev-myproject1/memory/MEMORY/WORK/<session>/PRD.md(or ISA.md post-v4.1.0).bun KnowledgeHarvester.ts harvest.~/.claude/PAI/MEMORY/WORK/is scanned (and only if it contains ISAs, which NATIVE-mode sessions don't produce)./knowledgedashboard shows 0/0/0/0 across People/Companies/Ideas/Research despite real work having occurred.In my case: 40 PRD.md files exist across 7 projects spanning months of substantive work. None are reachable by the harvester.
Workaround (current state)
Per-project run with
PAI_DIRoverride + manual cp bridge:Tedious, requires per-project iteration, leaves duplicate KNOWLEDGE silos in each project's memory dir.
Suggested fix
Extend
scanWorkISAs(line 145ish) to also discover per-project memory dirs via glob. New behavior:Where
scanWorkDiris the extracted version of the current per-dir loop, andsourceProjectbecomes a tag/frontmatter field on the resulting harvest candidate so provenance carries.File-name compatibility
The companion fix to
ISASync.hook.ts(commit history shows v4.1.0 added theISA.md ?? PRD.mdread-fallback) should be mirrored in the harvester:This avoids forcing every user to mass-rename historical PRDs (most users have months of pre-v4.1.0 sessions).
Verified locally
Patched the workflow manually with
PAI_DIRoverride + bridge cp. End-to-end works: 10 MemberOS PRDs → renamed to ISAs → harvested → 5 entries surfaced into centralKNOWLEDGE/. Pulse/knowledgeflipped from 0/0/0/0 to 1/1/3/0. Same recipe applies to remaining 30 PRDs across 6 other projects, but the per-project iteration + cp bridge is friction this issue would eliminate.Related
KnowledgeHarvester.tswrites directly to domain dirs, bypassing the documented_harvest-queue/curation step (filed separately).