@aisystemresources/emdee 0.1.0 → 0.1.2

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 CHANGED
@@ -1,85 +1,134 @@
1
- # Silent Mane
1
+ # Emdee
2
2
 
3
- Local-first knowledge graph backed by plain markdown. Humans browse it through a React renderer; agents (Claude, Cursor, Codex) read and write the same files through an MCP server. The vault is the source of truth — anything an LLM says traces back to a file you wrote.
3
+ Local-first knowledge graph backed by plain markdown. Humans browse it through a Next.js renderer; agents (Claude Code, Claude.ai, Cursor, Codex) read and write the same files through an MCP server. The vault is the source of truth — anything an LLM says traces back to a file you wrote.
4
4
 
5
5
  ## Why
6
6
 
7
- LLM agents need a stable, human-readable substrate to read and write their own context over time. Most knowledge-graph tools are either built for humans (Obsidian) or built for agents (vector stores). Silent Mane is a single substrate for both: the markdown a human edits is the exact bytes an agent reads, with no hidden index, no parallel summaries, no schema gymnastics. Build up a working journal that survives across sessions.
7
+ LLM agents need a stable, human-readable substrate to read and write their own context over time. Most knowledge-graph tools are either built for humans (Obsidian) or built for agents (vector stores). Emdee is a single substrate for both: the markdown a human edits is the exact bytes an agent reads, with no hidden index, no parallel summaries, no schema gymnastics. Build up a working journal that survives across sessions.
8
8
 
9
- ## Status
10
-
11
- Published on npm as `@aisystemresources/emdee`. The CLI (`emdee init`, `emdee mcp`, `emdee list`, `emdee drift-batch`) is globally installable; `emdee start` / `emdee serve-next` still require a repo checkout because they run the full Vite / Next viewer.
12
-
13
- ## Install (consumer)
9
+ ## Install
14
10
 
15
11
  ```bash
16
12
  npm install -g @aisystemresources/emdee
17
13
  cd ~/my-vault
18
- emdee init --nickname "Your Name" # writes ./docs/YOUR-NAME.md as the owner node
19
- emdee list # your owner + 5 virtual system nodes
20
- emdee mcp # stdio MCP server — point Claude Code / claude.ai at it
14
+ emdee init --nickname "Your Name" # writes ./docs/YOUR-NAME.md as your owner node
15
+ emdee list # your owner + 5 virtual system nodes
16
+ emdee mcp # stdio MCP server — point Claude Code at it
21
17
  ```
22
18
 
23
- ## Quick start (developer)
19
+ ## The 5-node OS layer
24
20
 
25
- ```bash
26
- git clone https://github.com/elz-ming/silent-mane.git
27
- cd silent-mane
28
- npm install
29
- ./bin/mane.js init # seeds docs/ with the entry doc, conventions, and sample branch
30
- npm run dev # Vite dev server with hot reload at http://localhost:5173
31
- npm run mcp # MCP server over stdio (point Claude.ai / Cursor / Codex at it)
32
- ```
21
+ Every Emdee vault has exactly 5 canonical top-level nodes, plus your owner node:
33
22
 
34
- `mane init` lays down:
23
+ | Node | Purpose |
24
+ |---|---|
25
+ | `EMDEE` | Vault root — the anchor everything hangs off. |
26
+ | `VAULT` | Your private notes, projects, and knowledge. |
27
+ | `SHARED` | Content shared with you by others (cloud only). |
28
+ | `GRAVEYARD` | Archived and retired documents. |
29
+ | `IMAGES` | Images and visual assets. |
30
+ | `<YOUR-NAME>` | Your personal subtree, seeded by `emdee init --nickname`. |
35
31
 
36
- - `docs/MANE.md` vault entry point
37
- - `docs/VAULT.md` — meta-pillar grouping the system docs below
38
- - `docs/INFO.md` — conventions (filenames, relationships, writing format)
39
- - `docs/INSTRUCTIONS.md` — CEO operating protocol for cross-project agents
40
- - `docs/BRAIN.md` — cross-project distilled wisdom (always-loaded prior)
41
- - `docs/WORKFLOWS.md` — concrete procedures the vault runs
42
- - `docs/SAMPLE.md` + `docs/sample/` — pedagogical examples; delete with `rm -rf docs/sample/` once you've read them
32
+ The 5 system nodes are **virtual** — they appear in every read (`emdee list`, `get_doc`, MCP responses) without being written to disk. Edit any of them via MCP and your version wins. Only the owner node (`<YOUR-NAME>.md`) actually lives on disk after `emdee init`.
43
33
 
44
- Set `SILENT_MANE_ENTRY=your-file.md` to override the default entry name.
34
+ ## Quick start (developer / from source)
45
35
 
36
+ ```bash
37
+ git clone https://github.com/AISystemResources/emdee.git
38
+ cd emdee
39
+ npm install
40
+ ./bin/emdee.js init --nickname "You" # seeds ./docs/ with your owner node
41
+ npm run dev # Next.js viewer at http://localhost:3000
42
+ npm run mcp # stdio MCP server
43
+ ```
44
+
45
+ The web viewer (`emdee start`, `emdee serve-next`) is repo-only — it needs the Next.js `app/` tree that isn't in the published tarball. `init`, `list`, `drift-batch`, `mcp` all work from the global install.
46
46
 
47
47
  ## MCP tools
48
48
 
49
- The MCP server (`mane mcp`) exposes:
49
+ The stdio server (`emdee mcp`) exposes 18 tools.
50
50
 
51
- - `list_docs` — every doc as `{path, title, summary}`. Cold-start enumeration.
51
+ **Reads:**
52
+ - `list_docs` — every doc as `{path, title, summary}`. `format: "text"` returns paths only.
53
+ - `get_doc(path)` — full markdown, per-section `content_hash` for version-guarded patches.
52
54
  - `get_summary(path)` — one doc's `{path, title, summary}`. Cheap.
53
- - `get_neighbors(path)` — focal doc + 1-hop neighbors, categorized as `parents / children / associated`. Each neighbor carries the prose note attached to its wiki-link.
54
- - `get_doc(path)` — full markdown plus per-section `content_hash` for safe patches.
55
- - `search(query, limit?)` — substring match over titles, summaries, content.
56
- - `append_section(path, heading, body, create_if_missing?)` — section-scoped append. Safer than `write_doc` for incremental edits.
57
- - `patch_section(path, heading, body, expected_content_hash)` version-guarded section replacement. Mismatched hash returns a structured `version_conflict`.
58
- - `write_doc_preview(path, content)` — diff and list of removed sections before any full-file write.
59
- - `write_doc(path, content)` — full-file replace (destructive; prefer the section-scoped tools).
55
+ - `get_neighbors(path)` — focal doc + 1-hop neighbourhood, categorised as parents / children / associated, each with the prose note attached to its wiki-link.
56
+ - `get_context(path, hops?, budget_tokens?)` — multi-hop neighbourhood within a token budget.
57
+ - `read_doc_section(path, section_id)` — one section without paying for the whole doc.
58
+ - `search(query, limit?)` — case-insensitive substring over titles, summaries, content.
59
+ - `list_summary_drift` paths whose body has drifted since their summary was last authored.
60
+
61
+ **Writes (version-guarded where destructive):**
62
+ - `patch_section(path, section_id, body, expected_content_hash)` — replace one section; mismatched hash returns structured `version_conflict`.
63
+ - `append_section(path, section_id, body)` — safer than write_doc for incremental edits.
64
+ - `append_doc(path, body)` — append to end of doc (chronological notes, LOGS entries).
65
+ - `patch_preamble(path, body, expected_content_hash)` — replace the region between H1 and first H2.
66
+ - `write_doc(path, content)` — full-file replace (destructive; prefer section-scoped tools).
67
+ - `write_doc_preview(path, content)` — diff + list of sections that would be removed. Always call before `write_doc`.
68
+
69
+ **Atomic multi-side writes (keep the graph consistent):**
70
+ - `create_child(parent_path, title, body?, summary?)` — writes new doc with canonical scaffold AND patches parent's `## Parent of`. Collapses the 5-round-trip add-child flow into one call.
71
+ - `add_association(a_path, b_path, label?)` — patches both docs' `## Associated with` in one call. Hard-refuses hierarchy or sibling duplicates.
72
+ - `move_doc(path, new_parent_path)` — atomic reparent, three-side edge update.
73
+ - `rename_doc(old_path, new_title, new_path?)` — rewrites H1, moves the file, updates every `[[old_title]]` across the vault.
74
+ - `materialize_subgroup(source_path, subgroup_heading)` — promote an H3 subgroup inside `## Parent of` into a real intermediate parent doc.
75
+ - `split_doc(source_path, rewrite_source_content, extracts)` — atomically refactor a doc into concept nodes.
76
+
77
+ **Lifecycle:**
78
+ - `trash_doc(path)` / `restore_doc(path)` — sidecar-based soft delete, edges preserved for lossless restore.
79
+ - `delete_doc(path)` — permanent, no undo. Returns inbound edges + title conflicts.
60
80
 
61
81
  ## Design principles
62
82
 
63
83
  1. **Markdown is the only source of truth.** No persisted index, no derived database, no parallel summaries.
64
84
  2. **Same substrate, different lenses.** Renderer and MCP read the same files via the same indexer. Nothing the LLM sees is invisible to the human.
65
- 3. **Convention over schema.** Light structure — H1 + `> blockquote` summary + three relationship sections (`## Parent of`, `## Child of`, `## Associated with`). The LLM parses English natively; rigid schemas only add authoring friction.
85
+ 3. **Convention over schema.** Light structure — H1 + `> blockquote` summary + three relationship sections (`## Parent of`, `## Child of`, `## Associated with`). Rigid schemas add authoring friction; the LLM parses English natively.
66
86
  4. **Single summary per doc.** The blockquote under the H1 is the routing decision for both humans and LLMs.
87
+ 5. **Version-guarded writes.** Every destructive edit takes an `expected_content_hash`. Concurrent edits fail loudly with `version_conflict` instead of silent overwrites.
67
88
 
68
- ## What's in here
89
+ ## What's in the repo
69
90
 
70
- - `bin/mane.js` — the `mane` CLI (`init`, `start`, `mcp`)
91
+ - `bin/emdee.js` — the `emdee` CLI (`init`, `list`, `drift-batch`, `mcp`, `start`, `serve-next`)
71
92
  - `src/core/indexer.ts` — walks `docs/`, parses wiki-links and relationship sections, derives summaries, skips fenced code blocks
72
- - `src/mcp/server.ts` — MCP server with the tool surface above
73
- - `src/web/`React + TypeScript renderer (Toast UI Editor + Cytoscape egocentric graph, category-colored nodes)
74
- - `src/server/dev-plugin.ts`Vite middleware that serves the index in dev
75
- - `api/index.ts` — Vercel serverless function that serves the index in prod
76
- - `templates/` — vault seeds plus typed templates for `PROJECT`, `NOVEL`, `PERSON`, `HACKATHON`, `CONCEPT`. The engineering layer is type-agnostic — types are conventions plus templates, not schema. Adding a new type is one new file.
93
+ - `src/core/syncDocEdges.ts` — incremental edge sync backed by Supabase
94
+ - `src/mcp/server.ts`stdio MCP server
95
+ - `src/lib/mcp/tools/`the 18 tools listed above
96
+ - `src/lib/system-nodes.ts` — canonical content for the 5 virtual system nodes
97
+ - `src/lib/storage/` — `FilesystemStorage` (local mode) + `SupabaseStorage` (cloud mode) behind a single `VaultStorage` interface
98
+ - `app/` — Next.js App Router: renderer, `/api/index`, `/api/mcp`, OAuth pages for the claude.ai connector
99
+ - `supabase/migrations/` — schema (new files only, never edited in place)
100
+ - `templates/types/` — archetype scaffolds (`PROJECT`, `NOVEL`, `PERSON`, `HACKATHON`, `CONCEPT`) for future `emdee new <type>` commands
101
+ - `e2e/` — Playwright suite (MCP tools, auth, share RBAC, upload, CLI init)
102
+
103
+ ## Conventions
77
104
 
78
- ## Conventions for the vault
105
+ Every doc follows the same shape:
79
106
 
80
- The seeded `docs/INFO.md` is the full conventions reference: filename rules, the relationship grammar (first wiki-link on each bullet is the declared edge, inline links are context-only), the LEARNINGS authoring format, attribution lines for provenance. Read it once when you start a vault, refer back when you forget how something works.
107
+ ```md
108
+ # TITLE
109
+
110
+ > One-line blockquote summary — this is what routing sees.
111
+
112
+ ## Child of
113
+
114
+ * [[PARENT]]
115
+
116
+ ## Parent of
117
+
118
+ * [[CHILD1]]
119
+ * [[CHILD2]]
120
+
121
+ ## Associated with
122
+
123
+ * [[CROSS-TREE-NODE]] — optional prose about the link
124
+
125
+ ## Notes
126
+
127
+ Freeform content.
128
+ ```
81
129
 
82
- ## Deploying to Vercel
130
+ Rules the lint enforces: one parent per doc; no self-loops; no associates that duplicate a hierarchy edge or sibling relationship; UPPERCASE filenames; lowercase folder names. `lint_doc(path)` surfaces violations; write tools accept `gate_on_warnings: ["code"]` to hard-block on specific ones.
83
131
 
84
- Vercel auto-detects Vite. Set `SILENT_MANE_DOCS` (or commit a `docs/` for a public vault) and it will serve the SPA plus the `/api/index` endpoint. The default `.gitignore` excludes `docs/` so your vault stays private; remove that line if you want the vault public.
132
+ ## Cloud deployment
85
133
 
134
+ The repo also runs as a full Next.js web viewer at [emdee.tech](https://emdee.tech). Vercel auto-detects Next.js — set the standard Supabase + Clerk env vars, push to `main`, done. The `/api/mcp` endpoint speaks the HTTP MCP transport for claude.ai connectors; `/oauth/authorize` runs the PKCE flow for the "Connect to Claude.ai" panel.
package/bin/emdee.js CHANGED
@@ -2,12 +2,18 @@
2
2
  import { Command } from "commander";
3
3
  import { spawn } from "node:child_process";
4
4
  import { mkdir, writeFile, access } from "node:fs/promises";
5
+ import { createRequire } from "node:module";
5
6
  import readline from "node:readline/promises";
6
7
  import path from "node:path";
7
8
  import { fileURLToPath } from "node:url";
8
9
 
9
10
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
10
11
  const pkgRoot = path.resolve(__dirname, "..");
12
+ // Version comes from package.json — `npm version <bump>` is the one
13
+ // place the string ever needs to change. createRequire works on any
14
+ // Node >= 14 without depending on the newer `import ... with { type: "json" }`
15
+ // attribute syntax (stable only in Node 20.10+).
16
+ const pkg = createRequire(import.meta.url)("../package.json");
11
17
 
12
18
  // SPRINT-090: `start` and `serve-next` shell out to Vite / Next.js against
13
19
  // the full repo. Those files (app/, next.config.*, etc.) aren't in the
@@ -60,7 +66,7 @@ function ownerNodeScaffold(title) {
60
66
  }
61
67
 
62
68
  const program = new Command();
63
- program.name("emdee").description("Emdee — local docs + knowledge graph + MCP").version("0.1.0");
69
+ program.name("emdee").description("Emdee — local docs + knowledge graph + MCP").version(pkg.version);
64
70
 
65
71
  program
66
72
  .command("init")
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@aisystemresources/emdee",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Local-first document management with markdown rendering, knowledge graph, and MCP server.",
5
5
  "type": "module",
6
6
  "bin": {
7
- "emdee": "./bin/emdee.js"
7
+ "emdee": "bin/emdee.js"
8
8
  },
9
9
  "publishConfig": {
10
10
  "access": "public"
package/src/mcp/server.ts CHANGED
@@ -27,6 +27,7 @@ import {
27
27
  restoreDoc,
28
28
  } from "../lib/mcp/tools/index.js";
29
29
  import type { ToolContext } from "../lib/mcp/tools/types.js";
30
+ import pkg from "../../package.json";
30
31
  // SPRINT-021: this stdio entrypoint is hardcoded to local mode (no
31
32
  // clerk_id, no namespace), so mcp_activity logging is intentionally
32
33
  // skipped here. Cloud-mode logging lives in app/api/mcp/route.ts.
@@ -37,7 +38,7 @@ const ctx: ToolContext = { mode: "local", docsDir };
37
38
  const server = new Server(
38
39
  {
39
40
  name: "emdee",
40
- version: "0.0.1",
41
+ version: pkg.version,
41
42
  },
42
43
  {
43
44
  capabilities: { tools: {} },