@noesis-brain/mcp-server 2.0.0 → 2.0.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.
@@ -1,92 +1,92 @@
1
- ---
2
- description: Polish a Noesis note's metadata and structure. Use a scope (today/session/catalog/cascade) or pass a specific note to iterate over multiple notes.
3
- ---
4
-
5
- Refine Noesis notes: fill missing metadata (title, description, keywords, aliases), tighten structure (heading hierarchy, frontmatter completeness), refresh AI-rated quality and importance scores. Works on a single note or a batch discovered by scope.
6
-
7
- ## Arguments
8
-
9
- $ARGUMENTS
10
-
11
- Accepted forms:
12
-
13
- - (no args) — ask the user to pick a scope via `AskUserQuestion`.
14
- - `<path-or-filename>.md` — refine this specific note.
15
- - `<topic-or-query>` — search for matching notes and offer them to the user.
16
- - `today` — discover and refine notes referenced in today's conversation logs.
17
- - `session [id]` — discover and refine notes referenced in a specific session (or the latest).
18
- - `catalog <name>` — refine all notes in a named Noesis catalog.
19
- - `cascade <anchor>` — refine the anchor note plus its semantically-similar neighbors.
20
- - `--limit <N>` — cap how many notes a batch mode processes (default: 15).
21
- - `--dry-run` — show what would change without writing.
22
-
23
- ## Workflow
24
-
25
- ### Step 1 — Parse mode
26
-
27
- From `$ARGUMENTS`, determine `MODE` using the first matching rule:
28
-
29
- | Priority | Pattern | Mode |
30
- |---|---|---|
31
- | 1 | `cascade <anchor>` | CASCADE |
32
- | 2 | `today` (anywhere) | TODAY |
33
- | 3 | `catalog <name>` | CATALOG |
34
- | 4 | `session [<id>]` | SESSION |
35
- | 5 | Ends in `.md` (path or filename) | SINGLE |
36
- | 6 | Non-empty string (treated as search query) | SEARCH |
37
- | 7 | Empty | ASK |
38
-
39
- For `ASK`, prompt the user via `AskUserQuestion` with options for each mode and proceed once they pick.
40
-
41
- ### Step 2 — Discover candidate notes
42
-
43
- Cap the candidate list per mode:
44
-
45
- - **SINGLE**: just the one note. Resolve filename to a path via `mcp__noesis__search_notes` if needed.
46
- - **SEARCH**: call `mcp__noesis__search_notes(query)` with the user's query; show the top 10, ask the user to pick one or more.
47
- - **TODAY**: read `~/.claude/logs/console_*.clog` files dated today, extract note paths and search terms mentioned, deduplicate, cap at `--limit` (default 15).
48
- - **SESSION**: same as TODAY but scoped to the chosen session UUID (or the latest if unspecified).
49
- - **CATALOG**: call `mcp__noesis__list_notes(catalog: <name>)`, cap at `--limit` (default 25).
50
- - **CASCADE**: resolve the anchor note's ID via `mcp__noesis__get_note(path)`, then call `mcp__noesis__find_similar_notes(note_id, limit: --limit ?? 10)`. Include the anchor itself.
51
-
52
- Show the discovered list to the user and ask them to confirm or trim before refining. Sort by ascending `quality_score` (worst first) so the most-needed refinement happens first.
53
-
54
- ### Step 3 — Refine each note sequentially
55
-
56
- For each candidate note:
57
-
58
- 1. **Read current state:** `mcp__noesis__get_note(path|id)` to get the full metadata + content.
59
- 2. **Fill missing metadata:** call `mcp__noesis__enhance_note_metadata(note_id)` with the relevant fields requested (`title`, `description`, `keywords`, `aliases`). The MCP tool uses AI to derive values from the note content. Apply with user approval if the change looks substantial; auto-apply if filling pure gaps (e.g., empty `keywords`).
60
- 3. **Structural suggestions** (light touch — skip if `--dry-run`):
61
- - Frontmatter completeness: title / description / keywords / aliases / date / updated / status / importance_score / quality_score.
62
- - Heading hierarchy: surface any H3+ without parent H2, or duplicate H1s.
63
- - Suggest and apply with `Edit` after user approval per file.
64
- 4. **Refresh scores:** call `mcp__noesis__rate_quality(note_id)` and `mcp__noesis__rate_importance(note_id)` — these run an AI rating pass; track the delta vs the prior values.
65
- 5. **Push:** if anything changed locally, call `mcp__noesis__sync_notes(files: [<absolute path>])` to push.
66
-
67
- ### Step 4 — Report
68
-
69
- Per-note line:
70
-
71
- - `refined <path>: metadata filled (Δ desc / kw / aliases), quality <old> → <new>, importance <old> → <new>`
72
- - `refined <path>: no changes needed`
73
- - `skipped <path> (<reason>)`
74
-
75
- Final tally:
76
-
77
- - `Total: T. Refined: R. Score delta: avg +X quality / +Y importance. Skipped: S. Errors: E.`
78
-
79
- ## Constraints
80
-
81
- - Never overwrite a user-authored description with an AI-generated one without confirmation. The MCP tool returns suggestions; you apply them only after the user OKs substantial replacements.
82
- - Never touch note `content` body text in refinement — only frontmatter and structural markers (headings, list normalization). Body rewrites are out of scope; that's an editing task, not a refinement.
83
- - One note at a time — sequential, not parallel. Each push uses `sync_notes(files:[...])` so conflicts surface per-note.
84
- - If a sync push returns conflict, hand off to `/noesis-sync` (which has the conflict-resolution flow embedded) or stop the batch and report.
85
-
86
- ## Examples
87
-
88
- - `/noesis-refine-note c:/path/to/note.md` — refine a single note.
89
- - `/noesis-refine-note today` — refine notes touched today.
90
- - `/noesis-refine-note catalog Work` — refine the Work catalog.
91
- - `/noesis-refine-note cascade c:/path/to/anchor.md` — refine the anchor and its semantic neighbors.
92
- - `/noesis-refine-note today --dry-run` — preview only.
1
+ ---
2
+ description: Polish a Noesis note's metadata and structure. Use a scope (today/session/catalog/cascade) or pass a specific note to iterate over multiple notes.
3
+ ---
4
+
5
+ Refine Noesis notes: fill missing metadata (title, description, keywords, aliases), tighten structure (heading hierarchy, frontmatter completeness), refresh AI-rated quality and importance scores. Works on a single note or a batch discovered by scope.
6
+
7
+ ## Arguments
8
+
9
+ $ARGUMENTS
10
+
11
+ Accepted forms:
12
+
13
+ - (no args) — ask the user to pick a scope via `AskUserQuestion`.
14
+ - `<path-or-filename>.md` — refine this specific note.
15
+ - `<topic-or-query>` — search for matching notes and offer them to the user.
16
+ - `today` — discover and refine notes referenced in today's conversation logs.
17
+ - `session [id]` — discover and refine notes referenced in a specific session (or the latest).
18
+ - `catalog <name>` — refine all notes in a named Noesis catalog.
19
+ - `cascade <anchor>` — refine the anchor note plus its semantically-similar neighbors.
20
+ - `--limit <N>` — cap how many notes a batch mode processes (default: 15).
21
+ - `--dry-run` — show what would change without writing.
22
+
23
+ ## Workflow
24
+
25
+ ### Step 1 — Parse mode
26
+
27
+ From `$ARGUMENTS`, determine `MODE` using the first matching rule:
28
+
29
+ | Priority | Pattern | Mode |
30
+ |---|---|---|
31
+ | 1 | `cascade <anchor>` | CASCADE |
32
+ | 2 | `today` (anywhere) | TODAY |
33
+ | 3 | `catalog <name>` | CATALOG |
34
+ | 4 | `session [<id>]` | SESSION |
35
+ | 5 | Ends in `.md` (path or filename) | SINGLE |
36
+ | 6 | Non-empty string (treated as search query) | SEARCH |
37
+ | 7 | Empty | ASK |
38
+
39
+ For `ASK`, prompt the user via `AskUserQuestion` with options for each mode and proceed once they pick.
40
+
41
+ ### Step 2 — Discover candidate notes
42
+
43
+ Cap the candidate list per mode:
44
+
45
+ - **SINGLE**: just the one note. Resolve filename to a path via `mcp__noesis__search_notes` if needed.
46
+ - **SEARCH**: call `mcp__noesis__search_notes(query)` with the user's query; show the top 10, ask the user to pick one or more.
47
+ - **TODAY**: read `~/.claude/logs/console_*.clog` files dated today, extract note paths and search terms mentioned, deduplicate, cap at `--limit` (default 15).
48
+ - **SESSION**: same as TODAY but scoped to the chosen session UUID (or the latest if unspecified).
49
+ - **CATALOG**: call `mcp__noesis__list_notes(catalog: <name>)`, cap at `--limit` (default 25).
50
+ - **CASCADE**: resolve the anchor note's ID via `mcp__noesis__get_note(path)`, then call `mcp__noesis__find_similar_notes(note_id, limit: --limit ?? 10)`. Include the anchor itself.
51
+
52
+ Show the discovered list to the user and ask them to confirm or trim before refining. Sort by ascending `quality_score` (worst first) so the most-needed refinement happens first.
53
+
54
+ ### Step 3 — Refine each note sequentially
55
+
56
+ For each candidate note:
57
+
58
+ 1. **Read current state:** `mcp__noesis__get_note(path|id)` to get the full metadata + content.
59
+ 2. **Fill missing metadata:** call `mcp__noesis__enhance_note_metadata(note_id)` with the relevant fields requested (`title`, `description`, `keywords`, `aliases`). The MCP tool uses AI to derive values from the note content. Apply with user approval if the change looks substantial; auto-apply if filling pure gaps (e.g., empty `keywords`).
60
+ 3. **Structural suggestions** (light touch — skip if `--dry-run`):
61
+ - Frontmatter completeness: title / description / keywords / aliases / date / updated / status / importance_score / quality_score.
62
+ - Heading hierarchy: surface any H3+ without parent H2, or duplicate H1s.
63
+ - Suggest and apply with `Edit` after user approval per file.
64
+ 4. **Refresh scores:** call `mcp__noesis__rate_quality(note_id)` and `mcp__noesis__rate_importance(note_id)` — these run an AI rating pass; track the delta vs the prior values.
65
+ 5. **Push:** if anything changed locally, call `mcp__noesis__sync_notes(files: [<absolute path>])` to push.
66
+
67
+ ### Step 4 — Report
68
+
69
+ Per-note line:
70
+
71
+ - `refined <path>: metadata filled (Δ desc / kw / aliases), quality <old> → <new>, importance <old> → <new>`
72
+ - `refined <path>: no changes needed`
73
+ - `skipped <path> (<reason>)`
74
+
75
+ Final tally:
76
+
77
+ - `Total: T. Refined: R. Score delta: avg +X quality / +Y importance. Skipped: S. Errors: E.`
78
+
79
+ ## Constraints
80
+
81
+ - Never overwrite a user-authored description with an AI-generated one without confirmation. The MCP tool returns suggestions; you apply them only after the user OKs substantial replacements.
82
+ - Never touch note `content` body text in refinement — only frontmatter and structural markers (headings, list normalization). Body rewrites are out of scope; that's an editing task, not a refinement.
83
+ - One note at a time — sequential, not parallel. Each push uses `sync_notes(files:[...])` so conflicts surface per-note.
84
+ - If a sync push returns conflict, hand off to `/noesis-sync` (which has the conflict-resolution flow embedded) or stop the batch and report.
85
+
86
+ ## Examples
87
+
88
+ - `/noesis-refine-note c:/path/to/note.md` — refine a single note.
89
+ - `/noesis-refine-note today` — refine notes touched today.
90
+ - `/noesis-refine-note catalog Work` — refine the Work catalog.
91
+ - `/noesis-refine-note cascade c:/path/to/anchor.md` — refine the anchor and its semantic neighbors.
92
+ - `/noesis-refine-note today --dry-run` — preview only.
@@ -1,110 +1,110 @@
1
- ---
2
- description: Sync local Noesis notes with the cloud — pulls web-UI edits, pushes local changes, resolves conflicts inline.
3
- ---
4
-
5
- The one-stop sync command for Noesis notes. Discovers notes edited via the Noesis web UI (Quick Fix), pulls them locally first, pushes your local changes, and resolves any conflicts inline with your input.
6
-
7
- ## Arguments
8
-
9
- $ARGUMENTS
10
-
11
- Accepted forms:
12
- - (no args) — auto-scope: sync files edited in this conversation, else the current project root.
13
- - `--files <absolute-paths>` — push these specific files (still pulls web-UI edits first for the matching root).
14
- - `<root-name>` — bulk sync the named root (full scan).
15
- - `--dry-run` — preview all actions without writing anything.
16
- - `--skip-online-edits` — skip the web-UI-edit pull step (advanced; rarely needed).
17
-
18
- ## Workflow
19
-
20
- CRITICAL: never start backend servers, write temporary scripts, or improvise HTTP calls. The cloud API at noesis-notes.vercel.app is always available through the MCP tool or the bundled script.
21
-
22
- ### Step 1 — Discover web-UI edits (unless `--skip-online-edits`)
23
-
24
- Call `mcp__noesis__list_edited_online_notes` (filter by `root_id` if `$ARGUMENTS` names a root). For each returned note inspect the `localStatus`:
25
-
26
- - `unchanged` — local file matches the last sync baseline; pull is safe and silent.
27
- - `not_on_disk` — file does not exist locally; pull creates it (auto-pull, no conflict possible).
28
- - `also_modified` — local file has diverged from the baseline. Tell the user the conflict cascade will run for those entries and ask `AskUserQuestion` to confirm before proceeding. If they decline, skip Step 2 for the `also_modified` entries and continue to Step 3 for the rest.
29
-
30
- If `list_edited_online_notes` returns an empty list, skip to Step 3.
31
-
32
- ### Step 2 — Pull web-UI edits
33
-
34
- For each pending note from Step 1 (excluding any the user declined), call:
35
-
36
- ```
37
- mcp__noesis__sync_notes(files: ["<absolute path = root_path + '/' + relative_path>"])
38
- ```
39
-
40
- Process one file at a time so per-file conflicts surface immediately. Track each result for the Step 5 summary.
41
-
42
- ### Step 3 — Push local changes
43
-
44
- Apply scoping:
45
-
46
- 1. **Specific files just edited in this conversation** → pass `files: [<paths>]` (do NOT sync everything else).
47
- 2. **User passed `--files <paths>`** → use those paths.
48
- 3. **User passed a root name** → pass `root: "<name>"` (slow full scan).
49
- 4. **No context, no args** → pass `root` matching the current project directory if it maps to a registered root; otherwise fall back to `files` of the files edited in this conversation.
50
-
51
- Choose the tier:
52
-
53
- - **Tier 1 (preferred):** call `mcp__noesis__sync_notes` with the resolved scope (and `dryRun: true` if `--dry-run`).
54
- - **Tier 2 (MCP unavailable):** run `node "{{NOESIS_MCP_SCRIPT_PATH}}" [args]` — the bundled script reads its token from `~/.claude.json` → `mcpServers.noesis.env.NOESIS_API_TOKEN` and talks to the cloud API directly. Pass the same CLI args (`--files`, `--root`, `--dry-run`).
55
- - **Tier 3 (no Node.js):** call the cloud HTTPS endpoints directly via `curl`. Read the token from `~/.claude.json` as above.
56
- ```bash
57
- curl -H "Authorization: Bearer $TOKEN" https://noesis-notes.vercel.app/api/mcp/roots?forSync=true
58
- curl -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
59
- https://noesis-notes.vercel.app/api/mcp/notes/upsert \
60
- -d '{"file":{"path":"...","relativePath":"...","content":"...","hash":"...","rootId":N,"rootName":"...","project":"..."},"metadata":{}}'
61
- ```
62
-
63
- ### Step 4 — Resolve conflicts inline (if any)
64
-
65
- If Step 2 or Step 3 reported `conflicts.length > 0` (Tier C of the bidirectional sync — overlapping hunks that anchor reapply and `node-diff3` could not auto-merge), do this PER conflicting file rather than reporting "run another skill":
66
-
67
- 1. **Gather three sides:**
68
- - **CLOUD** — `mcp__noesis__get_note(id)` (id is in the conflict payload, or resolve via `mcp__noesis__list_notes` filtered to the relative path).
69
- - **LOCAL** — `Read` the local file at the resolved absolute path.
70
- - **BASE** — read `.noesis/baseline/<relative_path>` under the root. If the baseline file is missing (legacy sync state), tell the user and ask whether to treat as a two-way merge or skip the file.
71
-
72
- 2. **Classify each pair of overlapping hunks:**
73
- - **Trivial overlap** (one side adds, other doesn't touch; or one side is a strict superset) → auto-merge silently with the inclusive result.
74
- - **Mixed overlap** → resolve the trivial parts automatically; STOP and ask only about the irreconcilable parts.
75
- - **Semantic overlap** (opposing edits, contradictory rewrites) → present the diff and ask via `AskUserQuestion`: `keep-local` / `keep-cloud` / paste merged text. NEVER silently overwrite.
76
-
77
- 3. **Apply the merge:**
78
- - `Write` the merged content to the local file.
79
- - Call `mcp__noesis__sync_notes(files: [<absolute path>])` to push the resolved version.
80
- - If the push returns 409 (cloud changed since this step started), the cloud was updated concurrently — repeat Step 4 for that file from the top.
81
- - After a clean push, call `POST /api/mcp/notes/:id/clear-conflict` (via `Bash` + `curl` with the API token) to clear the cloud `conflict_marker`.
82
-
83
- Process one file at a time. Do NOT batch a chosen-text response across multiple files.
84
-
85
- ### Step 5 — Report
86
-
87
- Print one line per file processed:
88
-
89
- - `pulled (web-UI edit applied locally)` — Step 2 succeeded with no conflict.
90
- - `pushed (local change applied to cloud)` — Step 3 succeeded with no conflict.
91
- - `merged auto for <path>` — Step 4 resolved trivial overlap without user input.
92
- - `merged by user for <path>` — Step 4 resolved with explicit user choice.
93
- - `skipped <path> (<reason>)` — user declined, baseline missing, or other.
94
-
95
- End with a final tally: `Pulled: N. Pushed: M. Merged: K (auto X / by-user Y). Skipped: Z. Errors: E.`
96
-
97
- ## Constraints
98
-
99
- - Never silently overwrite opposing edits — always present the diff and ask.
100
- - Never modify cloud-side content directly via `PUT /api/notes/:id` — go through `sync_notes` so the optimistic-concurrency 409 catches concurrent changes.
101
- - Never strip frontmatter or H1 from either side during merge — preserve verbatim from whichever side wrote them.
102
- - One file at a time for conflict resolution.
103
-
104
- ## Examples
105
-
106
- - `/noesis-sync` — auto-scope to recent conversation edits or current project root.
107
- - `/noesis-sync --dry-run` — preview the full flow without writing.
108
- - `/noesis-sync --files <absolute-path>` — push a specific file (still pulls web-UI edits first).
109
- - `/noesis-sync <root-name>` — bulk sync a named root.
110
- - `/noesis-sync --skip-online-edits` — push only, skip the web-UI pull step.
1
+ ---
2
+ description: Sync local Noesis notes with the cloud — pulls web-UI edits, pushes local changes, resolves conflicts inline.
3
+ ---
4
+
5
+ The one-stop sync command for Noesis notes. Discovers notes edited via the Noesis web UI (Quick Fix), pulls them locally first, pushes your local changes, and resolves any conflicts inline with your input.
6
+
7
+ ## Arguments
8
+
9
+ $ARGUMENTS
10
+
11
+ Accepted forms:
12
+ - (no args) — auto-scope: sync files edited in this conversation, else the current project root.
13
+ - `--files <absolute-paths>` — push these specific files (still pulls web-UI edits first for the matching root).
14
+ - `<root-name>` — bulk sync the named root (full scan).
15
+ - `--dry-run` — preview all actions without writing anything.
16
+ - `--skip-online-edits` — skip the web-UI-edit pull step (advanced; rarely needed).
17
+
18
+ ## Workflow
19
+
20
+ CRITICAL: never start backend servers, write temporary scripts, or improvise HTTP calls. The cloud API at noesis-notes.vercel.app is always available through the MCP tool or the bundled script.
21
+
22
+ ### Step 1 — Discover web-UI edits (unless `--skip-online-edits`)
23
+
24
+ Call `mcp__noesis__list_edited_online_notes` (filter by `root_id` if `$ARGUMENTS` names a root). For each returned note inspect the `localStatus`:
25
+
26
+ - `unchanged` — local file matches the last sync baseline; pull is safe and silent.
27
+ - `not_on_disk` — file does not exist locally; pull creates it (auto-pull, no conflict possible).
28
+ - `also_modified` — local file has diverged from the baseline. Tell the user the conflict cascade will run for those entries and ask `AskUserQuestion` to confirm before proceeding. If they decline, skip Step 2 for the `also_modified` entries and continue to Step 3 for the rest.
29
+
30
+ If `list_edited_online_notes` returns an empty list, skip to Step 3.
31
+
32
+ ### Step 2 — Pull web-UI edits
33
+
34
+ For each pending note from Step 1 (excluding any the user declined), call:
35
+
36
+ ```
37
+ mcp__noesis__sync_notes(files: ["<absolute path = root_path + '/' + relative_path>"])
38
+ ```
39
+
40
+ Process one file at a time so per-file conflicts surface immediately. Track each result for the Step 5 summary.
41
+
42
+ ### Step 3 — Push local changes
43
+
44
+ Apply scoping:
45
+
46
+ 1. **Specific files just edited in this conversation** → pass `files: [<paths>]` (do NOT sync everything else).
47
+ 2. **User passed `--files <paths>`** → use those paths.
48
+ 3. **User passed a root name** → pass `root: "<name>"` (slow full scan).
49
+ 4. **No context, no args** → pass `root` matching the current project directory if it maps to a registered root; otherwise fall back to `files` of the files edited in this conversation.
50
+
51
+ Choose the tier:
52
+
53
+ - **Tier 1 (preferred):** call `mcp__noesis__sync_notes` with the resolved scope (and `dryRun: true` if `--dry-run`).
54
+ - **Tier 2 (MCP unavailable):** run `node "{{NOESIS_MCP_SCRIPT_PATH}}" [args]` — the bundled script reads its token from `~/.claude.json` → `mcpServers.noesis.env.NOESIS_API_TOKEN` and talks to the cloud API directly. Pass the same CLI args (`--files`, `--root`, `--dry-run`).
55
+ - **Tier 3 (no Node.js):** call the cloud HTTPS endpoints directly via `curl`. Read the token from `~/.claude.json` as above.
56
+ ```bash
57
+ curl -H "Authorization: Bearer $TOKEN" https://noesis-notes.vercel.app/api/mcp/roots?forSync=true
58
+ curl -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
59
+ https://noesis-notes.vercel.app/api/mcp/notes/upsert \
60
+ -d '{"file":{"path":"...","relativePath":"...","content":"...","hash":"...","rootId":N,"rootName":"...","project":"..."},"metadata":{}}'
61
+ ```
62
+
63
+ ### Step 4 — Resolve conflicts inline (if any)
64
+
65
+ If Step 2 or Step 3 reported `conflicts.length > 0` (Tier C of the bidirectional sync — overlapping hunks that anchor reapply and `node-diff3` could not auto-merge), do this PER conflicting file rather than reporting "run another skill":
66
+
67
+ 1. **Gather three sides:**
68
+ - **CLOUD** — `mcp__noesis__get_note(id)` (id is in the conflict payload, or resolve via `mcp__noesis__list_notes` filtered to the relative path).
69
+ - **LOCAL** — `Read` the local file at the resolved absolute path.
70
+ - **BASE** — read `.noesis/baseline/<relative_path>` under the root. If the baseline file is missing (legacy sync state), tell the user and ask whether to treat as a two-way merge or skip the file.
71
+
72
+ 2. **Classify each pair of overlapping hunks:**
73
+ - **Trivial overlap** (one side adds, other doesn't touch; or one side is a strict superset) → auto-merge silently with the inclusive result.
74
+ - **Mixed overlap** → resolve the trivial parts automatically; STOP and ask only about the irreconcilable parts.
75
+ - **Semantic overlap** (opposing edits, contradictory rewrites) → present the diff and ask via `AskUserQuestion`: `keep-local` / `keep-cloud` / paste merged text. NEVER silently overwrite.
76
+
77
+ 3. **Apply the merge:**
78
+ - `Write` the merged content to the local file.
79
+ - Call `mcp__noesis__sync_notes(files: [<absolute path>])` to push the resolved version.
80
+ - If the push returns 409 (cloud changed since this step started), the cloud was updated concurrently — repeat Step 4 for that file from the top.
81
+ - After a clean push, call `POST /api/mcp/notes/:id/clear-conflict` (via `Bash` + `curl` with the API token) to clear the cloud `conflict_marker`.
82
+
83
+ Process one file at a time. Do NOT batch a chosen-text response across multiple files.
84
+
85
+ ### Step 5 — Report
86
+
87
+ Print one line per file processed:
88
+
89
+ - `pulled (web-UI edit applied locally)` — Step 2 succeeded with no conflict.
90
+ - `pushed (local change applied to cloud)` — Step 3 succeeded with no conflict.
91
+ - `merged auto for <path>` — Step 4 resolved trivial overlap without user input.
92
+ - `merged by user for <path>` — Step 4 resolved with explicit user choice.
93
+ - `skipped <path> (<reason>)` — user declined, baseline missing, or other.
94
+
95
+ End with a final tally: `Pulled: N. Pushed: M. Merged: K (auto X / by-user Y). Skipped: Z. Errors: E.`
96
+
97
+ ## Constraints
98
+
99
+ - Never silently overwrite opposing edits — always present the diff and ask.
100
+ - Never modify cloud-side content directly via `PUT /api/notes/:id` — go through `sync_notes` so the optimistic-concurrency 409 catches concurrent changes.
101
+ - Never strip frontmatter or H1 from either side during merge — preserve verbatim from whichever side wrote them.
102
+ - One file at a time for conflict resolution.
103
+
104
+ ## Examples
105
+
106
+ - `/noesis-sync` — auto-scope to recent conversation edits or current project root.
107
+ - `/noesis-sync --dry-run` — preview the full flow without writing.
108
+ - `/noesis-sync --files <absolute-path>` — push a specific file (still pulls web-UI edits first).
109
+ - `/noesis-sync <root-name>` — bulk sync a named root.
110
+ - `/noesis-sync --skip-online-edits` — push only, skip the web-UI pull step.
@@ -1,22 +1,22 @@
1
- ## Noesis MCP — conventions
2
-
3
- ### Writing notes
4
- - Use plain `##` headings for primary sections — Noesis builds its sidebar outline from them. Reserve collapsible `<details>` blocks for appendix-style noise (logs, references, changelogs).
5
-
6
- ### Pushing notes to the cloud
7
- - "Sync to Noesis" means push to the Noesis cloud database, not `cp` to a folder.
8
- - Use `mcp__noesis__sync_notes` with `files: [<absolute paths>]`.
9
- - Files must be within a registered root — check via `mcp__noesis__list_roots`.
10
-
11
- ### Reading and discovering notes
12
- - Note relations and codebase links live in the Noesis **database**, not in `.md` frontmatter — don't grep `.md` files for them.
13
- - Use `mcp__noesis__get_note` (read by ID or path), `mcp__noesis__find_similar_notes` (semantic similarity), `mcp__noesis__search_semantic` / `mcp__noesis__search_notes` (meaning / keyword search), `mcp__noesis__update_relations` (read-only when called without the `relations` param).
14
-
15
- ### Path-as-identifier (cross-machine)
16
- For any path inside a Noesis-watched root (paths containing `/.noesis/`, or any path under a directory listed by `mcp__noesis__list_roots`), the path is a Noesis identifier — the cloud copy is always authoritative, and the local copy on this machine may be **missing** (other machine) or **stale** (the user edited the note via the Noesis web UI's Quick Fix; the web UI surfaces that state with the badge 「在线编辑 · 等待本地同步」). Either way, the local copy is not a trustworthy source of truth — reading it directly silently feeds outdated content into the rest of the turn.
17
-
18
- Trigger: when the user references such a path and you are about to read, edit, or otherwise consume it, sync first — once per path per turn, before the first tool call that touches it. Not before subsequent re-reads of the same path in the same turn.
19
-
20
- - **NORMAL mode (writes allowed):** call `mcp__noesis__sync_notes(files: [<that path>])`. The three-way merge handles every case: in-sync → cheap no-op (`'skip'`); cloud-newer → auto-pulls to local disk; local-newer → pushes to cloud; both diverged → conflict cascade (3-way merge); missing locally → auto-creates from cloud. In all five cases the next `Read`/`Edit`/`Write` sees the right bytes.
21
- - **PLAN mode (writes forbidden):** call `mcp__noesis__get_note(path=<that path>)` for a read-only cloud lookup. Compare its `content_hash` / `updated_at` against the local file's hash / mtime; if drift exists, surface it in the plan and propose `sync_notes` as Step 1 of the implementation.
22
- - In either mode, do NOT fall back to Glob/Grep to hunt for similar filenames; do NOT ask the user to disambiguate the path. The cloud is authoritative for Noesis-watched paths.
1
+ ## Noesis MCP — conventions
2
+
3
+ ### Writing notes
4
+ - Use plain `##` headings for primary sections — Noesis builds its sidebar outline from them. Reserve collapsible `<details>` blocks for appendix-style noise (logs, references, changelogs).
5
+
6
+ ### Pushing notes to the cloud
7
+ - "Sync to Noesis" means push to the Noesis cloud database, not `cp` to a folder.
8
+ - Use `mcp__noesis__sync_notes` with `files: [<absolute paths>]`.
9
+ - Files must be within a registered root — check via `mcp__noesis__list_roots`.
10
+
11
+ ### Reading and discovering notes
12
+ - Note relations and codebase links live in the Noesis **database**, not in `.md` frontmatter — don't grep `.md` files for them.
13
+ - Use `mcp__noesis__get_note` (read by ID or path), `mcp__noesis__find_similar_notes` (semantic similarity), `mcp__noesis__search_semantic` / `mcp__noesis__search_notes` (meaning / keyword search), `mcp__noesis__update_relations` (read-only when called without the `relations` param).
14
+
15
+ ### Path-as-identifier (cross-machine)
16
+ For any path inside a Noesis-watched root (paths containing `/.noesis/`, or any path under a directory listed by `mcp__noesis__list_roots`), the path is a Noesis identifier — the cloud copy is always authoritative, and the local copy on this machine may be **missing** (other machine) or **stale** (the user edited the note via the Noesis web UI's Quick Fix; the web UI surfaces that state with the badge 「在线编辑 · 等待本地同步」). Either way, the local copy is not a trustworthy source of truth — reading it directly silently feeds outdated content into the rest of the turn.
17
+
18
+ Trigger: when the user references such a path and you are about to read, edit, or otherwise consume it, sync first — once per path per turn, before the first tool call that touches it. Not before subsequent re-reads of the same path in the same turn.
19
+
20
+ - **NORMAL mode (writes allowed):** call `mcp__noesis__sync_notes(files: [<that path>])`. The three-way merge handles every case: in-sync → cheap no-op (`'skip'`); cloud-newer → auto-pulls to local disk; local-newer → pushes to cloud; both diverged → conflict cascade (3-way merge); missing locally → auto-creates from cloud. In all five cases the next `Read`/`Edit`/`Write` sees the right bytes.
21
+ - **PLAN mode (writes forbidden):** call `mcp__noesis__get_note(path=<that path>)` for a read-only cloud lookup. Compare its `content_hash` / `updated_at` against the local file's hash / mtime; if drift exists, surface it in the plan and propose `sync_notes` as Step 1 of the implementation.
22
+ - In either mode, do NOT fall back to Glob/Grep to hunt for similar filenames; do NOT ask the user to disambiguate the path. The cloud is authoritative for Noesis-watched paths.