symbiote-cli 0.1.4 → 0.2.1
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/README.md +35 -26
- package/dist/bin/symbiote.js +8 -2
- package/dist/bin/symbiote.js.map +1 -1
- package/dist/src/commands/dna.d.ts.map +1 -1
- package/dist/src/commands/dna.js +292 -78
- package/dist/src/commands/dna.js.map +1 -1
- package/dist/src/commands/hooks.d.ts.map +1 -1
- package/dist/src/commands/hooks.js +54 -45
- package/dist/src/commands/hooks.js.map +1 -1
- package/dist/src/cortex/stage-7-intelligence.d.ts +1 -1
- package/dist/src/cortex/stage-7-intelligence.d.ts.map +1 -1
- package/dist/src/cortex/stage-7-intelligence.js +8 -8
- package/dist/src/cortex/stage-7-intelligence.js.map +1 -1
- package/dist/src/dna/engine.d.ts +26 -11
- package/dist/src/dna/engine.d.ts.map +1 -1
- package/dist/src/dna/engine.js +106 -92
- package/dist/src/dna/engine.js.map +1 -1
- package/dist/src/dna/export.d.ts +12 -0
- package/dist/src/dna/export.d.ts.map +1 -0
- package/dist/src/dna/export.js +39 -0
- package/dist/src/dna/export.js.map +1 -0
- package/dist/src/dna/index.d.ts +7 -4
- package/dist/src/dna/index.d.ts.map +1 -1
- package/dist/src/dna/index.js +5 -3
- package/dist/src/dna/index.js.map +1 -1
- package/dist/src/dna/profile.d.ts +19 -0
- package/dist/src/dna/profile.d.ts.map +1 -0
- package/dist/src/dna/profile.js +183 -0
- package/dist/src/dna/profile.js.map +1 -0
- package/dist/src/dna/schema.d.ts +112 -0
- package/dist/src/dna/schema.d.ts.map +1 -0
- package/dist/src/dna/schema.js +51 -0
- package/dist/src/dna/schema.js.map +1 -0
- package/dist/src/dna/types.d.ts +0 -37
- package/dist/src/dna/types.d.ts.map +1 -1
- package/dist/src/dna/types.js +0 -57
- package/dist/src/dna/types.js.map +1 -1
- package/dist/src/hooks/dna-checker.d.ts +1 -1
- package/dist/src/hooks/dna-checker.d.ts.map +1 -1
- package/dist/src/hooks/dna-checker.js +11 -10
- package/dist/src/hooks/dna-checker.js.map +1 -1
- package/dist/src/hooks/handlers/post-tool-use.d.ts +1 -1
- package/dist/src/hooks/handlers/post-tool-use.d.ts.map +1 -1
- package/dist/src/hooks/handlers/pre-tool-use.js +1 -1
- package/dist/src/hooks/handlers/pre-tool-use.js.map +1 -1
- package/dist/src/hooks/handlers/session-start.d.ts.map +1 -1
- package/dist/src/hooks/handlers/session-start.js +24 -9
- package/dist/src/hooks/handlers/session-start.js.map +1 -1
- package/dist/src/hooks/handlers/stop.js +5 -1
- package/dist/src/hooks/handlers/stop.js.map +1 -1
- package/dist/src/hooks/handlers/subagent-start.js +1 -1
- package/dist/src/hooks/handlers/subagent-start.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcp/context.d.ts +2 -2
- package/dist/src/mcp/context.d.ts.map +1 -1
- package/dist/src/mcp/context.js +4 -5
- package/dist/src/mcp/context.js.map +1 -1
- package/dist/src/mcp/http-api.d.ts.map +1 -1
- package/dist/src/mcp/http-api.js +26 -12
- package/dist/src/mcp/http-api.js.map +1 -1
- package/dist/src/mcp/proxy-handler.d.ts.map +1 -1
- package/dist/src/mcp/proxy-handler.js +8 -4
- package/dist/src/mcp/proxy-handler.js.map +1 -1
- package/dist/src/mcp/resources.d.ts.map +1 -1
- package/dist/src/mcp/resources.js +2 -3
- package/dist/src/mcp/resources.js.map +1 -1
- package/dist/src/mcp/server.d.ts.map +1 -1
- package/dist/src/mcp/server.js +39 -16
- package/dist/src/mcp/server.js.map +1 -1
- package/dist/src/mcp/tools/architecture-tools.d.ts +21 -2
- package/dist/src/mcp/tools/architecture-tools.d.ts.map +1 -1
- package/dist/src/mcp/tools/architecture-tools.js +4 -1
- package/dist/src/mcp/tools/architecture-tools.js.map +1 -1
- package/dist/src/mcp/tools/dna-tools.d.ts +3 -7
- package/dist/src/mcp/tools/dna-tools.d.ts.map +1 -1
- package/dist/src/mcp/tools/dna-tools.js +3 -8
- package/dist/src/mcp/tools/dna-tools.js.map +1 -1
- package/dist/src/utils/config.d.ts +1 -0
- package/dist/src/utils/config.d.ts.map +1 -1
- package/dist/src/utils/config.js +1 -10
- package/dist/src/utils/config.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/skills/symbiote-init/SKILL.md +127 -55
- package/dist/src/dna/storage.d.ts +0 -19
- package/dist/src/dna/storage.d.ts.map +0 -1
- package/dist/src/dna/storage.js +0 -112
- package/dist/src/dna/storage.js.map +0 -1
package/package.json
CHANGED
|
@@ -11,18 +11,35 @@ MCP server is already registered globally by `symbiote install`. This skill only
|
|
|
11
11
|
|
|
12
12
|
## Process
|
|
13
13
|
|
|
14
|
-
1. Scan the codebase
|
|
14
|
+
1. Scan the codebase and start the server
|
|
15
15
|
2. Write project overview
|
|
16
|
-
3.
|
|
17
|
-
4.
|
|
18
|
-
5.
|
|
16
|
+
3. Scan ALL projects for developer identity
|
|
17
|
+
4. Build complete DNA entries, constraints, and decisions
|
|
18
|
+
5. Dispatch subagent with pre-built entries
|
|
19
|
+
6. Print one-line summary
|
|
19
20
|
|
|
20
|
-
## Step 1: Scan
|
|
21
|
+
## Step 1: Scan and Start Server
|
|
22
|
+
|
|
23
|
+
Run these as SEPARATE bash commands:
|
|
21
24
|
|
|
22
25
|
```bash
|
|
23
26
|
npx symbiote-cli scan
|
|
24
27
|
```
|
|
25
28
|
|
|
29
|
+
Then start the server:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npx symbiote-cli serve --no-open > /dev/null 2>&1 &
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Then wait and verify:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
sleep 3 && curl -s http://127.0.0.1:$(cat .brain/port)/internal/health
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
IMPORTANT: Do NOT combine scan and serve into one command. The scan must finish and release the DB lock before the server starts.
|
|
42
|
+
|
|
26
43
|
## Step 2: Write Project Overview
|
|
27
44
|
|
|
28
45
|
Write `.brain/intent/overview.md` — a concise project summary that gives AI tools instant context.
|
|
@@ -45,105 +62,160 @@ Read the codebase context (CLAUDE.md, package.json, top-level structure, scan re
|
|
|
45
62
|
|
|
46
63
|
- `{top-level-dir}/` — {what it contains}
|
|
47
64
|
- `{top-level-dir}/` — {what it contains}
|
|
48
|
-
- `{sub-dir}/` — {what it contains, if important}
|
|
49
65
|
|
|
50
66
|
## Key Patterns
|
|
51
67
|
|
|
52
|
-
- {How data flows
|
|
53
|
-
- {How modules connect
|
|
54
|
-
- {Any non-obvious architectural pattern}
|
|
68
|
+
- {How data flows}
|
|
69
|
+
- {How modules connect}
|
|
55
70
|
|
|
56
71
|
## Entry Points
|
|
57
72
|
|
|
58
|
-
- `{file}` — {what it does}
|
|
59
73
|
- `{file}` — {what it does}
|
|
60
74
|
```
|
|
61
75
|
|
|
62
|
-
Rules:
|
|
76
|
+
Rules: keep it under 40 lines, no frontmatter, be specific to THIS project.
|
|
77
|
+
|
|
78
|
+
## Step 3: Scan ALL Projects for Developer Identity
|
|
79
|
+
|
|
80
|
+
Read the developer's full coding identity across every project:
|
|
81
|
+
|
|
82
|
+
1. `~/.claude/CLAUDE.md` — global instructions
|
|
83
|
+
2. Every CLAUDE.md in `~/.claude/projects/*/` — all project instructions
|
|
84
|
+
3. Every `.md` file in `~/.claude/projects/*/memory/` — all memories
|
|
85
|
+
4. `./CLAUDE.md` — current project
|
|
86
|
+
|
|
87
|
+
Read ALL of these. Do not skip any.
|
|
88
|
+
|
|
89
|
+
**Also extract the developer's identity** from the global CLAUDE.md:
|
|
63
90
|
|
|
64
|
-
-
|
|
65
|
-
-
|
|
66
|
-
-
|
|
67
|
-
-
|
|
68
|
-
- Use the project's actual directory names, tech choices, and patterns
|
|
91
|
+
- Name (look for "Name:", "Author:", or similar)
|
|
92
|
+
- Email
|
|
93
|
+
- GitHub handle
|
|
94
|
+
- Website/URL
|
|
69
95
|
|
|
70
|
-
## Step
|
|
96
|
+
## Step 4: Build Complete DNA Entries
|
|
71
97
|
|
|
72
|
-
|
|
98
|
+
From everything in Step 3, build three COMPLETE lists. Every entry must be fully formed — do NOT leave fields empty.
|
|
73
99
|
|
|
74
|
-
### DNA
|
|
100
|
+
### DNA entries
|
|
75
101
|
|
|
76
|
-
|
|
102
|
+
Build each entry as a COMPLETE JSON object with ALL fields filled:
|
|
77
103
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
104
|
+
```json
|
|
105
|
+
{
|
|
106
|
+
"rule": "Use 4-space indentation everywhere, never tabs",
|
|
107
|
+
"reason": "Consistency across polyglot stack eliminates context-switching friction and keeps diffs uniform",
|
|
108
|
+
"category": "formatting",
|
|
109
|
+
"applies_to": ["typescript", "javascript", "json", "php"],
|
|
110
|
+
"not_for": ["go"],
|
|
111
|
+
"source": "explicit"
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
**EVERY field is required:**
|
|
116
|
+
|
|
117
|
+
- `rule` — one specific sentence, self-contained
|
|
118
|
+
- `reason` — WHY this matters. NEVER leave empty. "Comments rot faster than code; good names eliminate narration" is good. Generic "for consistency" is not acceptable.
|
|
119
|
+
- `category` — use organic categories: `formatting`, `patterns`, `architecture`, `workflow`, `testing`, `tooling`, `ai-collaboration`. Not the old fixed categories.
|
|
120
|
+
- `applies_to` — list of languages/frameworks in lowercase. Empty `[]` means universal.
|
|
121
|
+
- `not_for` — exclusions where a rule doesn't apply (e.g., Go uses tabs not spaces). Omit if no exclusions.
|
|
122
|
+
- `source` — always `"explicit"` for init
|
|
123
|
+
|
|
124
|
+
**Categories to cover** (verify you have entries for each):
|
|
84
125
|
|
|
85
|
-
|
|
126
|
+
- **formatting** — indentation, quotes, semicolons, line length, file naming (kebab-case?)
|
|
127
|
+
- **patterns** — early returns, composition over inheritance, small functions, naming, error handling, type strictness
|
|
128
|
+
- **architecture** — project structure, separation of concerns, where logic lives, module boundaries, monorepo patterns
|
|
129
|
+
- **workflow** — commit style, no co-authored-by, never push without asking, no destructive DB ops, challenge plans
|
|
130
|
+
- **testing** — framework per language (Vitest, Pest), TDD, test structure, isolation
|
|
131
|
+
- **tooling** — framework choices per stack: Laravel+Inertia for PHP, Next.js for TS, Supabase, Stripe, Tailwind, shadcn
|
|
132
|
+
- **ai-collaboration** — concise responses, no trailing summaries, research before changing, no docs unless asked
|
|
86
133
|
|
|
87
|
-
|
|
134
|
+
**Confidence scoring:**
|
|
88
135
|
|
|
89
|
-
-
|
|
90
|
-
-
|
|
91
|
-
-
|
|
136
|
+
- Found in 3+ project CLAUDE.md files → `1.0`
|
|
137
|
+
- Found in 1-2 projects → `0.7`
|
|
138
|
+
- Current project only → `0.5`
|
|
92
139
|
|
|
93
|
-
|
|
140
|
+
**Completeness checklist before proceeding:**
|
|
94
141
|
|
|
95
|
-
|
|
142
|
+
- [ ] Formatting rules (indentation, quotes, line length, file naming)
|
|
143
|
+
- [ ] Code patterns (early returns, composition, function size, type strictness)
|
|
144
|
+
- [ ] Architecture (project structure, separation of concerns, module boundaries)
|
|
145
|
+
- [ ] Workflow (commits, pushing, destructive operations, AI collaboration style)
|
|
146
|
+
- [ ] Testing (framework per language, TDD, test structure)
|
|
147
|
+
- [ ] Tooling (framework choices per language/stack)
|
|
148
|
+
- [ ] AI collaboration (response style, autonomy level)
|
|
149
|
+
- [ ] Language-specific entries with proper `applies_to` scoping
|
|
150
|
+
- [ ] `not_for` exclusions where rules don't apply to certain languages
|
|
151
|
+
- [ ] Every `reason` field is filled with a specific WHY
|
|
96
152
|
|
|
97
|
-
|
|
98
|
-
- "Using DuckDB for graph storage — local-first, no external deps"
|
|
99
|
-
- "Switched to Drizzle for better type safety"
|
|
153
|
+
### Constraints (project rules)
|
|
100
154
|
|
|
101
|
-
|
|
155
|
+
For THIS project only. Use `propose_constraint` MCP tool.
|
|
156
|
+
|
|
157
|
+
### Decisions (architectural choices)
|
|
158
|
+
|
|
159
|
+
For THIS project only. Use `propose_decision` MCP tool.
|
|
160
|
+
|
|
161
|
+
### What to Skip
|
|
102
162
|
|
|
103
163
|
- File paths or directory descriptions
|
|
104
164
|
- Tool/product feature lists
|
|
105
|
-
- Author identity
|
|
165
|
+
- Author identity (captured separately)
|
|
106
166
|
- CLI commands or usage examples
|
|
107
|
-
- Anything describing WHAT the project IS rather than rules/choices/preferences
|
|
108
|
-
|
|
109
|
-
### Formatting Rules (applies to all three)
|
|
110
167
|
|
|
111
|
-
|
|
168
|
+
## Step 5: Dispatch Subagent
|
|
112
169
|
|
|
113
|
-
-
|
|
114
|
-
- Self-contained — understandable without context
|
|
115
|
-
- Specific — not vague or overly broad
|
|
170
|
+
Launch a single Agent to record everything. Pass the COMPLETE pre-built entries — do NOT ask the subagent to figure out fields.
|
|
116
171
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
Launch a single Agent to record everything. Pass it all three lists.
|
|
172
|
+
**Critical: also pass the developer identity** so the subagent can update the profile metadata.
|
|
120
173
|
|
|
121
174
|
**Agent prompt template:**
|
|
122
175
|
|
|
123
176
|
```
|
|
124
177
|
Record the following Symbiote entries using MCP tools. Call tools in parallel where possible.
|
|
125
178
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
179
|
+
## Developer Identity
|
|
180
|
+
|
|
181
|
+
After recording all entries, the profile at ~/.symbiote/profiles/personal.json needs its metadata updated.
|
|
182
|
+
Read the file, update the "profile" block with:
|
|
183
|
+
- name: {developer name}
|
|
184
|
+
- handle: {github handle}
|
|
185
|
+
- bio: {one-liner about their coding identity, synthesized from the DNA entries}
|
|
186
|
+
Then write the file back.
|
|
187
|
+
|
|
188
|
+
## DNA entries
|
|
189
|
+
|
|
190
|
+
Use `record_instruction` for each. Pass the EXACT JSON shown — do not modify or simplify the fields.
|
|
129
191
|
|
|
130
|
-
|
|
192
|
+
1. {"rule": "...", "reason": "...", "category": "...", "applies_to": [...], "not_for": [...], "source": "explicit"}
|
|
193
|
+
2. {"rule": "...", "reason": "...", "category": "...", "applies_to": [...], "source": "explicit"}
|
|
194
|
+
...
|
|
195
|
+
|
|
196
|
+
## Constraints
|
|
197
|
+
|
|
198
|
+
Use `propose_constraint` for each with `scope: "global"` and a slugified `id`:
|
|
131
199
|
1. [constraint]
|
|
132
200
|
2. [constraint]
|
|
133
201
|
|
|
134
|
-
|
|
202
|
+
## Decisions
|
|
203
|
+
|
|
204
|
+
Use `propose_decision` for each with `scope: "global"` and a slugified `id`:
|
|
135
205
|
1. [decision]
|
|
136
206
|
2. [decision]
|
|
137
207
|
|
|
138
208
|
Return counts: { dna: N, constraints: N, decisions: N, failed: N }
|
|
139
209
|
```
|
|
140
210
|
|
|
141
|
-
|
|
211
|
+
**IMPORTANT:** List every DNA entry as a complete JSON object in the subagent prompt. The subagent just passes them through to `record_instruction` — it does NOT need to think about what fields to include.
|
|
212
|
+
|
|
213
|
+
## Step 6: Output
|
|
142
214
|
|
|
143
215
|
One line, nothing more:
|
|
144
216
|
|
|
145
217
|
```
|
|
146
|
-
Symbiote initialized — scanned 350 files, recorded
|
|
218
|
+
Symbiote initialized — scanned 350 files, recorded 48 DNA entries, 5 constraints, 3 decisions.
|
|
147
219
|
```
|
|
148
220
|
|
|
149
221
|
Do NOT render tables, lists, or per-entry details.
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { type DnaCategory, type DnaEntry, type DnaIndex, type DnaStatus } from './types.js';
|
|
2
|
-
export interface ListOptions {
|
|
3
|
-
status?: DnaStatus;
|
|
4
|
-
category?: DnaCategory;
|
|
5
|
-
}
|
|
6
|
-
export declare class DnaStorage {
|
|
7
|
-
private dnaDir;
|
|
8
|
-
private cachedIndex;
|
|
9
|
-
constructor(dnaDir: string);
|
|
10
|
-
ensureDirectories(): void;
|
|
11
|
-
readIndex(): DnaIndex;
|
|
12
|
-
readEntry(id: string): DnaEntry | null;
|
|
13
|
-
writeEntry(entry: DnaEntry): void;
|
|
14
|
-
deleteEntry(id: string): void;
|
|
15
|
-
listEntries(options?: ListOptions): DnaEntry[];
|
|
16
|
-
private writeIndex;
|
|
17
|
-
private idToFileName;
|
|
18
|
-
}
|
|
19
|
-
//# sourceMappingURL=storage.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../../src/dna/storage.ts"],"names":[],"mappings":"AAEA,OAAO,EAIH,KAAK,WAAW,EAChB,KAAK,QAAQ,EACb,KAAK,QAAQ,EAEb,KAAK,SAAS,EACjB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,WAAW;IACxB,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,QAAQ,CAAC,EAAE,WAAW,CAAC;CAC1B;AAED,qBAAa,UAAU;IAGP,OAAO,CAAC,MAAM;IAF1B,OAAO,CAAC,WAAW,CAAyB;gBAExB,MAAM,EAAE,MAAM;IAElC,iBAAiB,IAAI,IAAI;IAazB,SAAS,IAAI,QAAQ;IAQrB,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI;IAgBtC,UAAU,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IA4BjC,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAe7B,WAAW,CAAC,OAAO,CAAC,EAAE,WAAW,GAAG,QAAQ,EAAE;IAwB9C,OAAO,CAAC,UAAU;IAQlB,OAAO,CAAC,YAAY;CAKvB"}
|
package/dist/src/dna/storage.js
DELETED
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import fs from 'node:fs';
|
|
2
|
-
import path from 'node:path';
|
|
3
|
-
import { DNA_CATEGORIES, parseFrontmatter, serializeEntry, } from './types.js';
|
|
4
|
-
export class DnaStorage {
|
|
5
|
-
dnaDir;
|
|
6
|
-
cachedIndex = null;
|
|
7
|
-
constructor(dnaDir) {
|
|
8
|
-
this.dnaDir = dnaDir;
|
|
9
|
-
}
|
|
10
|
-
ensureDirectories() {
|
|
11
|
-
for (const category of DNA_CATEGORIES) {
|
|
12
|
-
fs.mkdirSync(path.join(this.dnaDir, category), {
|
|
13
|
-
recursive: true,
|
|
14
|
-
});
|
|
15
|
-
}
|
|
16
|
-
const indexPath = path.join(this.dnaDir, 'index.json');
|
|
17
|
-
if (!fs.existsSync(indexPath)) {
|
|
18
|
-
this.writeIndex({ version: 1, entries: [] });
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
readIndex() {
|
|
22
|
-
if (this.cachedIndex)
|
|
23
|
-
return this.cachedIndex;
|
|
24
|
-
const indexPath = path.join(this.dnaDir, 'index.json');
|
|
25
|
-
const raw = fs.readFileSync(indexPath, 'utf-8');
|
|
26
|
-
this.cachedIndex = JSON.parse(raw);
|
|
27
|
-
return this.cachedIndex;
|
|
28
|
-
}
|
|
29
|
-
readEntry(id) {
|
|
30
|
-
const index = this.readIndex();
|
|
31
|
-
const indexEntry = index.entries.find((e) => e.id === id);
|
|
32
|
-
if (!indexEntry)
|
|
33
|
-
return null;
|
|
34
|
-
const filePath = path.join(this.dnaDir, indexEntry.category, indexEntry.fileName);
|
|
35
|
-
if (!fs.existsSync(filePath))
|
|
36
|
-
return null;
|
|
37
|
-
const raw = fs.readFileSync(filePath, 'utf-8');
|
|
38
|
-
const parsed = parseFrontmatter(raw);
|
|
39
|
-
if (!parsed)
|
|
40
|
-
return null;
|
|
41
|
-
return { frontmatter: parsed.frontmatter, content: parsed.content };
|
|
42
|
-
}
|
|
43
|
-
writeEntry(entry) {
|
|
44
|
-
const fm = entry.frontmatter;
|
|
45
|
-
const fileName = this.idToFileName(fm.id, fm.category);
|
|
46
|
-
const filePath = path.join(this.dnaDir, fm.category, fileName);
|
|
47
|
-
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
48
|
-
fs.writeFileSync(filePath, serializeEntry(entry));
|
|
49
|
-
const index = this.readIndex();
|
|
50
|
-
const existingIdx = index.entries.findIndex((e) => e.id === fm.id);
|
|
51
|
-
const indexEntry = {
|
|
52
|
-
id: fm.id,
|
|
53
|
-
category: fm.category,
|
|
54
|
-
status: fm.status,
|
|
55
|
-
confidence: fm.confidence,
|
|
56
|
-
fileName,
|
|
57
|
-
};
|
|
58
|
-
if (existingIdx >= 0) {
|
|
59
|
-
index.entries[existingIdx] = indexEntry;
|
|
60
|
-
}
|
|
61
|
-
else {
|
|
62
|
-
index.entries.push(indexEntry);
|
|
63
|
-
}
|
|
64
|
-
this.writeIndex(index);
|
|
65
|
-
}
|
|
66
|
-
deleteEntry(id) {
|
|
67
|
-
const index = this.readIndex();
|
|
68
|
-
const indexEntry = index.entries.find((e) => e.id === id);
|
|
69
|
-
if (!indexEntry)
|
|
70
|
-
return;
|
|
71
|
-
const filePath = path.join(this.dnaDir, indexEntry.category, indexEntry.fileName);
|
|
72
|
-
if (fs.existsSync(filePath)) {
|
|
73
|
-
fs.unlinkSync(filePath);
|
|
74
|
-
}
|
|
75
|
-
index.entries = index.entries.filter((e) => e.id !== id);
|
|
76
|
-
this.writeIndex(index);
|
|
77
|
-
}
|
|
78
|
-
listEntries(options) {
|
|
79
|
-
const index = this.readIndex();
|
|
80
|
-
let filtered = index.entries;
|
|
81
|
-
if (options?.status) {
|
|
82
|
-
filtered = filtered.filter((e) => e.status === options.status);
|
|
83
|
-
}
|
|
84
|
-
if (options?.category) {
|
|
85
|
-
filtered = filtered.filter((e) => e.category === options.category);
|
|
86
|
-
}
|
|
87
|
-
const entries = [];
|
|
88
|
-
for (const indexEntry of filtered) {
|
|
89
|
-
const filePath = path.join(this.dnaDir, indexEntry.category, indexEntry.fileName);
|
|
90
|
-
if (!fs.existsSync(filePath))
|
|
91
|
-
continue;
|
|
92
|
-
const raw = fs.readFileSync(filePath, 'utf-8');
|
|
93
|
-
const parsed = parseFrontmatter(raw);
|
|
94
|
-
if (parsed)
|
|
95
|
-
entries.push({ frontmatter: parsed.frontmatter, content: parsed.content });
|
|
96
|
-
}
|
|
97
|
-
return entries;
|
|
98
|
-
}
|
|
99
|
-
writeIndex(index) {
|
|
100
|
-
const indexPath = path.join(this.dnaDir, 'index.json');
|
|
101
|
-
const tmpPath = indexPath + '.tmp';
|
|
102
|
-
fs.writeFileSync(tmpPath, JSON.stringify(index, null, 4) + '\n');
|
|
103
|
-
fs.renameSync(tmpPath, indexPath);
|
|
104
|
-
this.cachedIndex = index;
|
|
105
|
-
}
|
|
106
|
-
idToFileName(id, category) {
|
|
107
|
-
const prefix = `${category}-`;
|
|
108
|
-
const name = id.startsWith(prefix) ? id.slice(prefix.length) : id;
|
|
109
|
-
return `${name}.md`;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
//# sourceMappingURL=storage.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../../src/dna/storage.ts"],"names":[],"mappings":"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"}
|