@jayjiang/byoao 0.2.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/dist/cli/cli-program.js +241 -0
- package/dist/cli/cli-program.js.map +1 -0
- package/dist/cli/installer.js +226 -0
- package/dist/cli/installer.js.map +1 -0
- package/dist/cli/ui.js +157 -0
- package/dist/cli/ui.js.map +1 -0
- package/dist/hooks/idle-suggestions.js +14 -0
- package/dist/hooks/idle-suggestions.js.map +1 -0
- package/dist/hooks/system-transform.js +34 -0
- package/dist/hooks/system-transform.js.map +1 -0
- package/dist/index.js +43 -0
- package/dist/index.js.map +1 -0
- package/dist/plugin-config.js +57 -0
- package/dist/plugin-config.js.map +1 -0
- package/dist/tools/add-glossary-term.js +19 -0
- package/dist/tools/add-glossary-term.js.map +1 -0
- package/dist/tools/add-member.js +21 -0
- package/dist/tools/add-member.js.map +1 -0
- package/dist/tools/add-project.js +24 -0
- package/dist/tools/add-project.js.map +1 -0
- package/dist/tools/init-vault.js +82 -0
- package/dist/tools/init-vault.js.map +1 -0
- package/dist/tools/vault-doctor.js +38 -0
- package/dist/tools/vault-doctor.js.map +1 -0
- package/dist/tools/vault-status.js +18 -0
- package/dist/tools/vault-status.js.map +1 -0
- package/dist/vault/create.js +230 -0
- package/dist/vault/create.js.map +1 -0
- package/dist/vault/doctor.js +148 -0
- package/dist/vault/doctor.js.map +1 -0
- package/dist/vault/glossary.js +33 -0
- package/dist/vault/glossary.js.map +1 -0
- package/dist/vault/member.js +67 -0
- package/dist/vault/member.js.map +1 -0
- package/dist/vault/obsidian-check.js +125 -0
- package/dist/vault/obsidian-check.js.map +1 -0
- package/dist/vault/obsidian-cli.js +47 -0
- package/dist/vault/obsidian-cli.js.map +1 -0
- package/dist/vault/opencode-check.js +65 -0
- package/dist/vault/opencode-check.js.map +1 -0
- package/dist/vault/preset.js +48 -0
- package/dist/vault/preset.js.map +1 -0
- package/dist/vault/project.js +68 -0
- package/dist/vault/project.js.map +1 -0
- package/dist/vault/status.js +135 -0
- package/dist/vault/status.js.map +1 -0
- package/dist/vault/template.js +14 -0
- package/dist/vault/template.js.map +1 -0
- package/package.json +58 -0
- package/src/assets/obsidian-skills/defuddle.md +41 -0
- package/src/assets/obsidian-skills/json-canvas.md +244 -0
- package/src/assets/obsidian-skills/obsidian-bases.md +497 -0
- package/src/assets/obsidian-skills/obsidian-cli.md +106 -0
- package/src/assets/obsidian-skills/obsidian-markdown.md +196 -0
- package/src/assets/presets/common/AGENT.md.hbs +29 -0
- package/src/assets/presets/common/Glossary.md.hbs +44 -0
- package/src/assets/presets/common/Start Here.md.hbs +95 -0
- package/src/assets/presets/common/obsidian/core-plugins.json +33 -0
- package/src/assets/presets/common/obsidian/daily-notes.json +5 -0
- package/src/assets/presets/common/obsidian/templates.json +3 -0
- package/src/assets/presets/common/templates/Daily Note.md +19 -0
- package/src/assets/presets/common/templates/Decision Record.md +32 -0
- package/src/assets/presets/common/templates/Investigation.md +34 -0
- package/src/assets/presets/common/templates/Meeting Notes.md +25 -0
- package/src/assets/presets/pm-tpm/agent-section.hbs +15 -0
- package/src/assets/presets/pm-tpm/preset.json +12 -0
- package/src/assets/presets/pm-tpm/templates/Feature Doc.md +45 -0
- package/src/assets/presets/pm-tpm/templates/Sprint Handoff.md +38 -0
- package/src/assets/web-clipper/confluence-page.json +63 -0
- package/src/assets/web-clipper/general-article.json +53 -0
- package/src/assets/web-clipper/jira-issue.json +68 -0
- package/src/assets/web-clipper/meeting-notes.json +53 -0
- package/src/skills/enrich-document.md +52 -0
- package/src/skills/init-knowledge-base.md +85 -0
- package/src/skills/system-explainer.md +58 -0
- package/src/skills/vault-doctor.md +73 -0
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import fs from "fs-extra";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { renderTemplate, today } from "./template.js";
|
|
4
|
+
import { loadPreset, getCommonDir } from "./preset.js";
|
|
5
|
+
// Common directories shared by all presets
|
|
6
|
+
const COMMON_DIRECTORIES = [
|
|
7
|
+
"Inbox",
|
|
8
|
+
"Knowledge",
|
|
9
|
+
"Knowledge/concepts",
|
|
10
|
+
"Knowledge/templates",
|
|
11
|
+
"People",
|
|
12
|
+
"Systems",
|
|
13
|
+
"Archive",
|
|
14
|
+
"Daily",
|
|
15
|
+
];
|
|
16
|
+
export async function createVault(config) {
|
|
17
|
+
const { teamName, vaultPath, members, projects, glossaryEntries, jiraHost, jiraProject, preset } = config;
|
|
18
|
+
const presetName = preset ?? "pm-tpm"; // Fallback if config wasn't parsed through Zod
|
|
19
|
+
const { config: presetConfig, presetsDir } = loadPreset(presetName);
|
|
20
|
+
const commonDir = getCommonDir();
|
|
21
|
+
const presetDir = path.join(presetsDir, presetName);
|
|
22
|
+
let filesCreated = 0;
|
|
23
|
+
let wikilinksCreated = 0;
|
|
24
|
+
// Merge directories: common + preset-specific
|
|
25
|
+
const allDirectories = [...COMMON_DIRECTORIES, ...presetConfig.directories];
|
|
26
|
+
// 1. Create directories
|
|
27
|
+
for (const dir of allDirectories) {
|
|
28
|
+
await fs.ensureDir(path.join(vaultPath, dir));
|
|
29
|
+
}
|
|
30
|
+
// 2. Copy .obsidian config from common
|
|
31
|
+
await fs.ensureDir(path.join(vaultPath, ".obsidian"));
|
|
32
|
+
const obsidianSrc = path.join(commonDir, "obsidian");
|
|
33
|
+
if (await fs.pathExists(obsidianSrc)) {
|
|
34
|
+
await fs.copy(obsidianSrc, path.join(vaultPath, ".obsidian"), { overwrite: false });
|
|
35
|
+
filesCreated += (await fs.readdir(obsidianSrc)).length;
|
|
36
|
+
}
|
|
37
|
+
// 3. Copy note templates: common first, then preset overlay
|
|
38
|
+
const templateDest = path.join(vaultPath, "Knowledge/templates");
|
|
39
|
+
const allTemplateNames = [];
|
|
40
|
+
// Common templates
|
|
41
|
+
const commonTemplatesDir = path.join(commonDir, "templates");
|
|
42
|
+
if (await fs.pathExists(commonTemplatesDir)) {
|
|
43
|
+
const files = await fs.readdir(commonTemplatesDir);
|
|
44
|
+
for (const file of files) {
|
|
45
|
+
await fs.copy(path.join(commonTemplatesDir, file), path.join(templateDest, file), { overwrite: false });
|
|
46
|
+
allTemplateNames.push(file.replace(/\.md$/, ""));
|
|
47
|
+
filesCreated++;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// Preset templates
|
|
51
|
+
const presetTemplatesDir = path.join(presetDir, "templates");
|
|
52
|
+
if (await fs.pathExists(presetTemplatesDir)) {
|
|
53
|
+
const files = await fs.readdir(presetTemplatesDir);
|
|
54
|
+
for (const file of files) {
|
|
55
|
+
await fs.copy(path.join(presetTemplatesDir, file), path.join(templateDest, file), { overwrite: false });
|
|
56
|
+
allTemplateNames.push(file.replace(/\.md$/, ""));
|
|
57
|
+
filesCreated++;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// 4. Generate Glossary.md
|
|
61
|
+
const glossaryTemplate = await fs.readFile(path.join(commonDir, "Glossary.md.hbs"), "utf-8");
|
|
62
|
+
let glossaryRows = "";
|
|
63
|
+
if (glossaryEntries.length > 0) {
|
|
64
|
+
glossaryRows = glossaryEntries
|
|
65
|
+
.map((e) => `| **${e.term}** | ${e.definition} |`)
|
|
66
|
+
.join("\n");
|
|
67
|
+
}
|
|
68
|
+
const glossaryContent = renderTemplate(glossaryTemplate, {
|
|
69
|
+
TEAM_NAME: teamName,
|
|
70
|
+
date: today(),
|
|
71
|
+
GLOSSARY_ENTRIES: glossaryRows,
|
|
72
|
+
});
|
|
73
|
+
await fs.writeFile(path.join(vaultPath, "Knowledge/Glossary.md"), glossaryContent);
|
|
74
|
+
filesCreated++;
|
|
75
|
+
// 5. Generate Start Here.md
|
|
76
|
+
const startHereTemplate = await fs.readFile(path.join(commonDir, "Start Here.md.hbs"), "utf-8");
|
|
77
|
+
const startHereContent = renderTemplate(startHereTemplate, { TEAM_NAME: teamName });
|
|
78
|
+
await fs.writeFile(path.join(vaultPath, "Start Here.md"), startHereContent);
|
|
79
|
+
filesCreated++;
|
|
80
|
+
// 6. Generate AGENT.md (two-layer: common skeleton + preset section)
|
|
81
|
+
const agentSkeletonTemplate = await fs.readFile(path.join(commonDir, "AGENT.md.hbs"), "utf-8");
|
|
82
|
+
// Render preset agent-section
|
|
83
|
+
let roleSection = "";
|
|
84
|
+
const agentSectionPath = path.join(presetDir, "agent-section.hbs");
|
|
85
|
+
if (await fs.pathExists(agentSectionPath)) {
|
|
86
|
+
const agentSectionTemplate = await fs.readFile(agentSectionPath, "utf-8");
|
|
87
|
+
let projectsList;
|
|
88
|
+
if (projects.length > 0) {
|
|
89
|
+
projectsList = projects
|
|
90
|
+
.map((p) => `- [[${p.name}]] — ${p.description}`)
|
|
91
|
+
.join("\n");
|
|
92
|
+
wikilinksCreated += projects.length;
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
projectsList = "(No projects added yet — create notes in Projects/)";
|
|
96
|
+
}
|
|
97
|
+
roleSection = renderTemplate(agentSectionTemplate, {
|
|
98
|
+
PROJECTS: projectsList,
|
|
99
|
+
JIRA_HOST: jiraHost,
|
|
100
|
+
JIRA_PROJECT: jiraProject,
|
|
101
|
+
HAS_JIRA: jiraHost && jiraProject,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
// Build team table
|
|
105
|
+
let teamTable;
|
|
106
|
+
if (members.length > 0) {
|
|
107
|
+
const rows = members.map((m) => `| [[${m.name}]] | ${m.role} |`).join("\n");
|
|
108
|
+
teamTable = `| Name | Role |\n|------|------|\n${rows}`;
|
|
109
|
+
wikilinksCreated += members.length;
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
teamTable = "(No members added yet — create notes in People/)";
|
|
113
|
+
}
|
|
114
|
+
// Build template list string
|
|
115
|
+
const templateList = allTemplateNames.map((t) => `- ${t}`).join("\n");
|
|
116
|
+
const agentContent = renderTemplate(agentSkeletonTemplate, {
|
|
117
|
+
TEAM_NAME: teamName,
|
|
118
|
+
AGENT_DESCRIPTION: presetConfig.agentDescription,
|
|
119
|
+
ROLE_SECTION: roleSection,
|
|
120
|
+
TEAM_TABLE: teamTable,
|
|
121
|
+
TEMPLATE_LIST: templateList,
|
|
122
|
+
});
|
|
123
|
+
await fs.writeFile(path.join(vaultPath, "AGENT.md"), agentContent);
|
|
124
|
+
await fs.writeFile(path.join(vaultPath, "CLAUDE.md"), agentContent);
|
|
125
|
+
filesCreated += 2;
|
|
126
|
+
// 7. Create people notes
|
|
127
|
+
for (const member of members) {
|
|
128
|
+
const content = `---
|
|
129
|
+
title: "${member.name}"
|
|
130
|
+
type: person
|
|
131
|
+
team: "${teamName}"
|
|
132
|
+
role: "${member.role}"
|
|
133
|
+
status: active
|
|
134
|
+
tags: [person]
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
# ${member.name}
|
|
138
|
+
|
|
139
|
+
**Role**: ${member.role}
|
|
140
|
+
**Team**: ${teamName}
|
|
141
|
+
`;
|
|
142
|
+
await fs.writeFile(path.join(vaultPath, `People/${member.name}.md`), content);
|
|
143
|
+
filesCreated++;
|
|
144
|
+
}
|
|
145
|
+
// 8. Create project notes
|
|
146
|
+
for (const project of projects) {
|
|
147
|
+
const content = `---
|
|
148
|
+
title: "${project.name}"
|
|
149
|
+
type: feature
|
|
150
|
+
status: active
|
|
151
|
+
date: ${today()}
|
|
152
|
+
team: "${teamName}"
|
|
153
|
+
jira: ""
|
|
154
|
+
stakeholders: []
|
|
155
|
+
priority: ""
|
|
156
|
+
tags: [project]
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
# ${project.name}
|
|
160
|
+
|
|
161
|
+
${project.description}
|
|
162
|
+
`;
|
|
163
|
+
await fs.writeFile(path.join(vaultPath, `Projects/${project.name}.md`), content);
|
|
164
|
+
filesCreated++;
|
|
165
|
+
}
|
|
166
|
+
// 9. Create team index (always, since Start Here.md links to it)
|
|
167
|
+
{
|
|
168
|
+
let teamIndexContent = `---
|
|
169
|
+
title: "${teamName} Team"
|
|
170
|
+
type: reference
|
|
171
|
+
team: "${teamName}"
|
|
172
|
+
tags: [team]
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
# ${teamName} Team
|
|
176
|
+
|
|
177
|
+
## Members
|
|
178
|
+
|
|
179
|
+
`;
|
|
180
|
+
if (members.length > 0) {
|
|
181
|
+
teamIndexContent += "| Name | Role |\n|------|------|\n";
|
|
182
|
+
teamIndexContent += members.map((m) => `| [[${m.name}]] | ${m.role} |`).join("\n");
|
|
183
|
+
wikilinksCreated += members.length;
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
teamIndexContent += "(No members added yet)";
|
|
187
|
+
}
|
|
188
|
+
teamIndexContent += "\n\n## Active Projects\n\n";
|
|
189
|
+
if (projects.length > 0) {
|
|
190
|
+
teamIndexContent += projects
|
|
191
|
+
.map((p) => `- [[${p.name}]] — ${p.description}`)
|
|
192
|
+
.join("\n");
|
|
193
|
+
wikilinksCreated += projects.length;
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
teamIndexContent += "(No projects added yet)";
|
|
197
|
+
}
|
|
198
|
+
teamIndexContent += "\n";
|
|
199
|
+
await fs.writeFile(path.join(vaultPath, `People/${teamName} Team.md`), teamIndexContent);
|
|
200
|
+
filesCreated++;
|
|
201
|
+
}
|
|
202
|
+
// 10. Create .gitkeep in empty directories
|
|
203
|
+
const dirsNeedingGitkeep = [
|
|
204
|
+
"Inbox",
|
|
205
|
+
"Knowledge/concepts",
|
|
206
|
+
"Systems",
|
|
207
|
+
"Archive",
|
|
208
|
+
"Daily",
|
|
209
|
+
];
|
|
210
|
+
// Add preset-specific dirs if they're empty
|
|
211
|
+
for (const dir of presetConfig.directories) {
|
|
212
|
+
dirsNeedingGitkeep.push(dir);
|
|
213
|
+
}
|
|
214
|
+
for (const dir of dirsNeedingGitkeep) {
|
|
215
|
+
const dirPath = path.join(vaultPath, dir);
|
|
216
|
+
if (await fs.pathExists(dirPath)) {
|
|
217
|
+
const files = await fs.readdir(dirPath);
|
|
218
|
+
if (files.length === 0) {
|
|
219
|
+
await fs.writeFile(path.join(dirPath, ".gitkeep"), "");
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
return {
|
|
224
|
+
vaultPath,
|
|
225
|
+
filesCreated,
|
|
226
|
+
wikilinksCreated,
|
|
227
|
+
directories: allDirectories,
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
//# sourceMappingURL=create.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create.js","sourceRoot":"","sources":["../../src/vault/create.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import fs from "fs-extra";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import matter from "gray-matter";
|
|
4
|
+
/** Recursively collect all .md files (excluding .obsidian) */
|
|
5
|
+
async function collectMarkdownFiles(dir) {
|
|
6
|
+
const results = [];
|
|
7
|
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
8
|
+
for (const entry of entries) {
|
|
9
|
+
const fullPath = path.join(dir, entry.name);
|
|
10
|
+
if (entry.isDirectory()) {
|
|
11
|
+
if (entry.name === ".obsidian" || entry.name === ".git")
|
|
12
|
+
continue;
|
|
13
|
+
results.push(...(await collectMarkdownFiles(fullPath)));
|
|
14
|
+
}
|
|
15
|
+
else if (entry.name.endsWith(".md")) {
|
|
16
|
+
results.push(fullPath);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return results;
|
|
20
|
+
}
|
|
21
|
+
/** Extract wikilink targets from content (skip code blocks) */
|
|
22
|
+
function extractWikilinks(content) {
|
|
23
|
+
const stripped = content
|
|
24
|
+
.replace(/```[\s\S]*?```/g, "")
|
|
25
|
+
.replace(/`[^`]+`/g, "");
|
|
26
|
+
const matches = stripped.match(/\[\[([^\]|]+)(?:\|[^\]]+)?\]\]/g);
|
|
27
|
+
if (!matches)
|
|
28
|
+
return [];
|
|
29
|
+
return matches.map((m) => m.replace(/\[\[([^\]|]+)(?:\|[^\]]+)?\]\]/, "$1"));
|
|
30
|
+
}
|
|
31
|
+
export async function getVaultDiagnosis(vaultPath) {
|
|
32
|
+
const issues = [];
|
|
33
|
+
const allFiles = await collectMarkdownFiles(vaultPath);
|
|
34
|
+
const noteNames = new Set(allFiles.map((f) => path.basename(f, ".md")));
|
|
35
|
+
let healthyNotes = 0;
|
|
36
|
+
// Check 1 & 2: Frontmatter — missing type or tags
|
|
37
|
+
for (const filePath of allFiles) {
|
|
38
|
+
const relativePath = path.relative(vaultPath, filePath);
|
|
39
|
+
// Skip template files
|
|
40
|
+
if (relativePath.startsWith("Knowledge/templates/"))
|
|
41
|
+
continue;
|
|
42
|
+
const content = await fs.readFile(filePath, "utf-8");
|
|
43
|
+
const { data } = matter(content);
|
|
44
|
+
let hasIssue = false;
|
|
45
|
+
if (!data || Object.keys(data).length === 0) {
|
|
46
|
+
issues.push({
|
|
47
|
+
severity: "warning",
|
|
48
|
+
category: "frontmatter",
|
|
49
|
+
file: relativePath,
|
|
50
|
+
message: "Missing frontmatter — no metadata defined",
|
|
51
|
+
});
|
|
52
|
+
hasIssue = true;
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
if (!data.type) {
|
|
56
|
+
issues.push({
|
|
57
|
+
severity: "warning",
|
|
58
|
+
category: "frontmatter",
|
|
59
|
+
file: relativePath,
|
|
60
|
+
message: "Missing `type` in frontmatter",
|
|
61
|
+
});
|
|
62
|
+
hasIssue = true;
|
|
63
|
+
}
|
|
64
|
+
if (!data.tags || (Array.isArray(data.tags) && data.tags.length === 0)) {
|
|
65
|
+
issues.push({
|
|
66
|
+
severity: "info",
|
|
67
|
+
category: "frontmatter",
|
|
68
|
+
file: relativePath,
|
|
69
|
+
message: "Missing `tags` in frontmatter",
|
|
70
|
+
});
|
|
71
|
+
hasIssue = true;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (!hasIssue)
|
|
75
|
+
healthyNotes++;
|
|
76
|
+
}
|
|
77
|
+
// Check 3: AGENT.md drift
|
|
78
|
+
const agentPath = path.join(vaultPath, "AGENT.md");
|
|
79
|
+
if (await fs.pathExists(agentPath)) {
|
|
80
|
+
const agentContent = await fs.readFile(agentPath, "utf-8");
|
|
81
|
+
const agentLinks = extractWikilinks(agentContent);
|
|
82
|
+
for (const linkTarget of agentLinks) {
|
|
83
|
+
if (!noteNames.has(linkTarget)) {
|
|
84
|
+
issues.push({
|
|
85
|
+
severity: "warning",
|
|
86
|
+
category: "agent-drift",
|
|
87
|
+
message: `AGENT.md links to [[${linkTarget}]] but no matching note found`,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// Check 4: Orphan notes (no incoming or outgoing wikilinks)
|
|
93
|
+
const allLinksMap = new Map();
|
|
94
|
+
const incomingLinks = new Set();
|
|
95
|
+
for (const filePath of allFiles) {
|
|
96
|
+
const content = await fs.readFile(filePath, "utf-8");
|
|
97
|
+
const links = extractWikilinks(content);
|
|
98
|
+
const name = path.basename(filePath, ".md");
|
|
99
|
+
allLinksMap.set(name, new Set(links));
|
|
100
|
+
for (const link of links) {
|
|
101
|
+
incomingLinks.add(link);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
for (const filePath of allFiles) {
|
|
105
|
+
const relativePath = path.relative(vaultPath, filePath);
|
|
106
|
+
if (relativePath.startsWith("Knowledge/templates/"))
|
|
107
|
+
continue;
|
|
108
|
+
if (relativePath === "AGENT.md" || relativePath === "CLAUDE.md")
|
|
109
|
+
continue;
|
|
110
|
+
const name = path.basename(filePath, ".md");
|
|
111
|
+
const outgoing = allLinksMap.get(name) || new Set();
|
|
112
|
+
const hasIncoming = incomingLinks.has(name);
|
|
113
|
+
const hasOutgoing = outgoing.size > 0;
|
|
114
|
+
if (!hasIncoming && !hasOutgoing) {
|
|
115
|
+
issues.push({
|
|
116
|
+
severity: "info",
|
|
117
|
+
category: "orphan",
|
|
118
|
+
file: relativePath,
|
|
119
|
+
message: "Orphan note — no incoming or outgoing wikilinks",
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
// Check 5: Broken wikilinks
|
|
124
|
+
for (const filePath of allFiles) {
|
|
125
|
+
const relativePath = path.relative(vaultPath, filePath);
|
|
126
|
+
const content = await fs.readFile(filePath, "utf-8");
|
|
127
|
+
const links = extractWikilinks(content);
|
|
128
|
+
for (const link of links) {
|
|
129
|
+
if (!noteNames.has(link)) {
|
|
130
|
+
issues.push({
|
|
131
|
+
severity: "warning",
|
|
132
|
+
category: "broken-link",
|
|
133
|
+
file: relativePath,
|
|
134
|
+
message: `Broken wikilink: [[${link}]]`,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return {
|
|
140
|
+
summary: {
|
|
141
|
+
totalNotes: allFiles.length,
|
|
142
|
+
healthyNotes,
|
|
143
|
+
issueCount: issues.length,
|
|
144
|
+
},
|
|
145
|
+
issues,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=doctor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/vault/doctor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import fs from "fs-extra";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
export async function addGlossaryTerm(input) {
|
|
4
|
+
const { vaultPath, term, definition } = input;
|
|
5
|
+
const glossaryPath = path.join(vaultPath, "30-Knowledge/Glossary.md");
|
|
6
|
+
if (!(await fs.pathExists(glossaryPath))) {
|
|
7
|
+
throw new Error(`Glossary not found at: ${glossaryPath}`);
|
|
8
|
+
}
|
|
9
|
+
let content = await fs.readFile(glossaryPath, "utf-8");
|
|
10
|
+
// Find the Core Terms table and append a new row
|
|
11
|
+
const newRow = `| **${term}** | ${definition} |`;
|
|
12
|
+
// Find the last row in the Core Terms table (after |------|-----------|)
|
|
13
|
+
const tableMatch = content.match(/(## Core Terms\n\n\| Term \| Definition \|\n\|------|-----------\|\n)([\s\S]*?)(\n\n---|\n\n##|\n*$)/);
|
|
14
|
+
if (tableMatch) {
|
|
15
|
+
const [fullMatch, tableHeader, existingRows, tableEnd] = tableMatch;
|
|
16
|
+
const updatedRows = existingRows.trim()
|
|
17
|
+
? `${existingRows.trim()}\n${newRow}`
|
|
18
|
+
: newRow;
|
|
19
|
+
content = content.replace(fullMatch, `${tableHeader}${updatedRows}\n${tableEnd}`);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
// Fallback: just append before the "How to Add" section
|
|
23
|
+
if (content.includes("## How to Add a New Term")) {
|
|
24
|
+
content = content.replace("## How to Add a New Term", `${newRow}\n\n## How to Add a New Term`);
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
content += `\n${newRow}\n`;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
await fs.writeFile(glossaryPath, content);
|
|
31
|
+
return { glossaryPath, termAdded: term };
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=glossary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glossary.js","sourceRoot":"","sources":["../../src/vault/glossary.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,IAAI,MAAM,WAAW,CAAC;AAQ7B,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,KAA2B;IAE3B,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,KAAK,CAAC;IAE9C,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,0BAA0B,CAAC,CAAC;IACtE,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC;QACzC,MAAM,IAAI,KAAK,CAAC,0BAA0B,YAAY,EAAE,CAAC,CAAC;IAC5D,CAAC;IAED,IAAI,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IAEvD,iDAAiD;IACjD,MAAM,MAAM,GAAG,OAAO,IAAI,QAAQ,UAAU,IAAI,CAAC;IAEjD,yEAAyE;IACzE,MAAM,UAAU,GAAG,OAAO,CAAC,KAAK,CAC9B,sGAAsG,CACvG,CAAC;IAEF,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,CAAC,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,CAAC,GAAG,UAAU,CAAC;QACpE,MAAM,WAAW,GAAG,YAAY,CAAC,IAAI,EAAE;YACrC,CAAC,CAAC,GAAG,YAAY,CAAC,IAAI,EAAE,KAAK,MAAM,EAAE;YACrC,CAAC,CAAC,MAAM,CAAC;QACX,OAAO,GAAG,OAAO,CAAC,OAAO,CACvB,SAAS,EACT,GAAG,WAAW,GAAG,WAAW,KAAK,QAAQ,EAAE,CAC5C,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,wDAAwD;QACxD,IAAI,OAAO,CAAC,QAAQ,CAAC,0BAA0B,CAAC,EAAE,CAAC;YACjD,OAAO,GAAG,OAAO,CAAC,OAAO,CACvB,0BAA0B,EAC1B,GAAG,MAAM,8BAA8B,CACxC,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,OAAO,IAAI,KAAK,MAAM,IAAI,CAAC;QAC7B,CAAC;IACH,CAAC;IAED,MAAM,EAAE,CAAC,SAAS,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IAE1C,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;AAC3C,CAAC"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import fs from "fs-extra";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
export async function addMember(input) {
|
|
4
|
+
const { vaultPath, name, role, team } = input;
|
|
5
|
+
let wikilinksAdded = 0;
|
|
6
|
+
// 1. Create person note
|
|
7
|
+
const personPath = path.join(vaultPath, `40-People/${name}.md`);
|
|
8
|
+
if (await fs.pathExists(personPath)) {
|
|
9
|
+
throw new Error(`Person note already exists: ${personPath}`);
|
|
10
|
+
}
|
|
11
|
+
const content = `---
|
|
12
|
+
title: "${name}"
|
|
13
|
+
type: person
|
|
14
|
+
team: "${team}"
|
|
15
|
+
role: "${role}"
|
|
16
|
+
status: active
|
|
17
|
+
tags: [person]
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
# ${name}
|
|
21
|
+
|
|
22
|
+
**Role**: ${role}
|
|
23
|
+
**Team**: ${team}
|
|
24
|
+
`;
|
|
25
|
+
await fs.writeFile(personPath, content);
|
|
26
|
+
// 2. Update team index if it exists
|
|
27
|
+
const teamFiles = await fs.readdir(path.join(vaultPath, "40-People"));
|
|
28
|
+
const teamIndexFile = teamFiles.find((f) => f.endsWith("Team.md"));
|
|
29
|
+
if (teamIndexFile) {
|
|
30
|
+
const teamIndexPath = path.join(vaultPath, "40-People", teamIndexFile);
|
|
31
|
+
let teamContent = await fs.readFile(teamIndexPath, "utf-8");
|
|
32
|
+
// Add to members table
|
|
33
|
+
const tableRow = `| [[${name}]] | ${role} |`;
|
|
34
|
+
if (teamContent.includes("|------|------|")) {
|
|
35
|
+
// Insert after the table header separator
|
|
36
|
+
teamContent = teamContent.replace(/(^\|------|------\|$)/m, `$1\n${tableRow}`);
|
|
37
|
+
wikilinksAdded++;
|
|
38
|
+
}
|
|
39
|
+
await fs.writeFile(teamIndexPath, teamContent);
|
|
40
|
+
}
|
|
41
|
+
// 3. Update AGENT.md wikilinks
|
|
42
|
+
for (const agentFile of ["AGENT.md", "CLAUDE.md"]) {
|
|
43
|
+
const agentPath = path.join(vaultPath, agentFile);
|
|
44
|
+
if (await fs.pathExists(agentPath)) {
|
|
45
|
+
let agentContent = await fs.readFile(agentPath, "utf-8");
|
|
46
|
+
// Replace placeholder if present
|
|
47
|
+
if (agentContent.includes("(No members added yet")) {
|
|
48
|
+
const table = `| Name | Role |\n|------|------|\n| [[${name}]] | ${role} |`;
|
|
49
|
+
agentContent = agentContent.replace(/\(No members added yet[^)]*\)/, table);
|
|
50
|
+
wikilinksAdded++;
|
|
51
|
+
}
|
|
52
|
+
else if (agentContent.includes("|------|------|")) {
|
|
53
|
+
// Find the team table section and add a row
|
|
54
|
+
const teamSectionMatch = agentContent.match(/## Team[^\n]*\n[\s\S]*?(\|------|------\|[^\n]*(?:\n\|[^\n]*)*)/);
|
|
55
|
+
if (teamSectionMatch) {
|
|
56
|
+
const existingTable = teamSectionMatch[1];
|
|
57
|
+
const newTable = existingTable + `\n| [[${name}]] | ${role} |`;
|
|
58
|
+
agentContent = agentContent.replace(existingTable, newTable);
|
|
59
|
+
wikilinksAdded++;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
await fs.writeFile(agentPath, agentContent);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return { filePath: personPath, wikilinksAdded };
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=member.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"member.js","sourceRoot":"","sources":["../../src/vault/member.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,IAAI,MAAM,WAAW,CAAC;AAU7B,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,KAAqB;IACnD,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC;IAC9C,IAAI,cAAc,GAAG,CAAC,CAAC;IAEvB,wBAAwB;IACxB,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,IAAI,KAAK,CAAC,CAAC;IAChE,IAAI,MAAM,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QACpC,MAAM,IAAI,KAAK,CAAC,+BAA+B,UAAU,EAAE,CAAC,CAAC;IAC/D,CAAC;IAED,MAAM,OAAO,GAAG;UACR,IAAI;;SAEL,IAAI;SACJ,IAAI;;;;;IAKT,IAAI;;YAEI,IAAI;YACJ,IAAI;CACf,CAAC;IACA,MAAM,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IAExC,oCAAoC;IACpC,MAAM,SAAS,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC,CAAC;IACtE,MAAM,aAAa,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;IAEnE,IAAI,aAAa,EAAE,CAAC;QAClB,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,EAAE,aAAa,CAAC,CAAC;QACvE,IAAI,WAAW,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;QAE5D,uBAAuB;QACvB,MAAM,QAAQ,GAAG,OAAO,IAAI,QAAQ,IAAI,IAAI,CAAC;QAC7C,IAAI,WAAW,CAAC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC;YAC5C,0CAA0C;YAC1C,WAAW,GAAG,WAAW,CAAC,OAAO,CAC/B,wBAAwB,EACxB,OAAO,QAAQ,EAAE,CAClB,CAAC;YACF,cAAc,EAAE,CAAC;QACnB,CAAC;QAED,MAAM,EAAE,CAAC,SAAS,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;IACjD,CAAC;IAED,+BAA+B;IAC/B,KAAK,MAAM,SAAS,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,EAAE,CAAC;QAClD,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QAClD,IAAI,MAAM,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YACnC,IAAI,YAAY,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YAEzD,iCAAiC;YACjC,IAAI,YAAY,CAAC,QAAQ,CAAC,uBAAuB,CAAC,EAAE,CAAC;gBACnD,MAAM,KAAK,GAAG,yCAAyC,IAAI,QAAQ,IAAI,IAAI,CAAC;gBAC5E,YAAY,GAAG,YAAY,CAAC,OAAO,CACjC,+BAA+B,EAC/B,KAAK,CACN,CAAC;gBACF,cAAc,EAAE,CAAC;YACnB,CAAC;iBAAM,IAAI,YAAY,CAAC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC;gBACpD,4CAA4C;gBAC5C,MAAM,gBAAgB,GAAG,YAAY,CAAC,KAAK,CACzC,iEAAiE,CAClE,CAAC;gBACF,IAAI,gBAAgB,EAAE,CAAC;oBACrB,MAAM,aAAa,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC;oBAC1C,MAAM,QAAQ,GAAG,aAAa,GAAG,SAAS,IAAI,QAAQ,IAAI,IAAI,CAAC;oBAC/D,YAAY,GAAG,YAAY,CAAC,OAAO,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;oBAC7D,cAAc,EAAE,CAAC;gBACnB,CAAC;YACH,CAAC;YAED,MAAM,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,cAAc,EAAE,CAAC;AAClD,CAAC"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { execSync } from "node:child_process";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { platform } from "node:os";
|
|
4
|
+
const OBSIDIAN_DOWNLOAD_URL = "https://obsidian.md/download";
|
|
5
|
+
function getMacAppPaths() {
|
|
6
|
+
return [
|
|
7
|
+
"/Applications/Obsidian.app",
|
|
8
|
+
`${process.env.HOME}/Applications/Obsidian.app`,
|
|
9
|
+
];
|
|
10
|
+
}
|
|
11
|
+
function getLinuxPaths() {
|
|
12
|
+
return [
|
|
13
|
+
"/usr/bin/obsidian",
|
|
14
|
+
"/usr/local/bin/obsidian",
|
|
15
|
+
"/snap/bin/obsidian",
|
|
16
|
+
`${process.env.HOME}/.local/bin/obsidian`,
|
|
17
|
+
];
|
|
18
|
+
}
|
|
19
|
+
function findInstallPath() {
|
|
20
|
+
const os = platform();
|
|
21
|
+
if (os === "darwin") {
|
|
22
|
+
for (const p of getMacAppPaths()) {
|
|
23
|
+
if (existsSync(p))
|
|
24
|
+
return p;
|
|
25
|
+
}
|
|
26
|
+
// Also check via mdfind (Spotlight)
|
|
27
|
+
try {
|
|
28
|
+
const result = execSync('mdfind "kMDItemCFBundleIdentifier == md.obsidian"', {
|
|
29
|
+
timeout: 5000,
|
|
30
|
+
encoding: "utf-8",
|
|
31
|
+
}).trim();
|
|
32
|
+
if (result)
|
|
33
|
+
return result.split("\n")[0];
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
// Spotlight may not be available
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
else if (os === "linux") {
|
|
40
|
+
for (const p of getLinuxPaths()) {
|
|
41
|
+
if (existsSync(p))
|
|
42
|
+
return p;
|
|
43
|
+
}
|
|
44
|
+
// Check via which
|
|
45
|
+
try {
|
|
46
|
+
const result = execSync("which obsidian", {
|
|
47
|
+
timeout: 3000,
|
|
48
|
+
encoding: "utf-8",
|
|
49
|
+
}).trim();
|
|
50
|
+
if (result)
|
|
51
|
+
return result;
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
// Not found
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
else if (os === "win32") {
|
|
58
|
+
const localAppData = process.env.LOCALAPPDATA || "";
|
|
59
|
+
const winPath = `${localAppData}\\Obsidian\\Obsidian.exe`;
|
|
60
|
+
if (existsSync(winPath))
|
|
61
|
+
return winPath;
|
|
62
|
+
}
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
function isRunning() {
|
|
66
|
+
const os = platform();
|
|
67
|
+
try {
|
|
68
|
+
if (os === "darwin") {
|
|
69
|
+
const result = execSync("pgrep -x Obsidian", {
|
|
70
|
+
timeout: 3000,
|
|
71
|
+
encoding: "utf-8",
|
|
72
|
+
}).trim();
|
|
73
|
+
return result.length > 0;
|
|
74
|
+
}
|
|
75
|
+
else if (os === "linux") {
|
|
76
|
+
const result = execSync("pgrep -x obsidian", {
|
|
77
|
+
timeout: 3000,
|
|
78
|
+
encoding: "utf-8",
|
|
79
|
+
}).trim();
|
|
80
|
+
return result.length > 0;
|
|
81
|
+
}
|
|
82
|
+
else if (os === "win32") {
|
|
83
|
+
const result = execSync("tasklist /FI \"IMAGENAME eq Obsidian.exe\" /NH", {
|
|
84
|
+
timeout: 3000,
|
|
85
|
+
encoding: "utf-8",
|
|
86
|
+
});
|
|
87
|
+
return result.includes("Obsidian.exe");
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
// pgrep returns exit code 1 if no match — that's expected
|
|
92
|
+
}
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
export function checkObsidian() {
|
|
96
|
+
const appPath = findInstallPath();
|
|
97
|
+
return {
|
|
98
|
+
installed: appPath !== null,
|
|
99
|
+
running: isRunning(),
|
|
100
|
+
appPath,
|
|
101
|
+
downloadUrl: OBSIDIAN_DOWNLOAD_URL,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
export function formatObsidianStatus(status) {
|
|
105
|
+
const lines = [];
|
|
106
|
+
if (!status.installed) {
|
|
107
|
+
lines.push("⚠️ Obsidian is NOT installed.");
|
|
108
|
+
lines.push(` Download it from: ${status.downloadUrl}`);
|
|
109
|
+
lines.push(" After installing, open Obsidian and create or open a vault.");
|
|
110
|
+
return lines.join("\n");
|
|
111
|
+
}
|
|
112
|
+
lines.push(`✓ Obsidian is installed at: ${status.appPath}`);
|
|
113
|
+
if (!status.running) {
|
|
114
|
+
lines.push("⚠️ Obsidian is NOT currently running.");
|
|
115
|
+
lines.push(" Please open Obsidian before working with vaults.");
|
|
116
|
+
if (status.appPath && platform() === "darwin") {
|
|
117
|
+
lines.push(` Run: open "${status.appPath}"`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
lines.push("✓ Obsidian is running.");
|
|
122
|
+
}
|
|
123
|
+
return lines.join("\n");
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=obsidian-check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"obsidian-check.js","sourceRoot":"","sources":["../../src/vault/obsidian-check.ts"],"names":[],"mappings":"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"}
|