misakanet 2.40.0 → 2.41.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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "misakanet",
3
- "version": "2.40.0",
3
+ "version": "2.41.0",
4
4
  "description": "Failure-memory network for AI coding agents: search evidence-rated failure lessons, submit new failures, and turn crashes into reusable knowledge.",
5
5
  "author": {
6
6
  "name": "Ikalus1988",
package/README.ja.md CHANGED
@@ -111,6 +111,14 @@ jobs:
111
111
  > **MisakaNetは1つのこと専用に構築されています:** エージェントが既知の障害を繰り返すのを防ぐこと。
112
112
  > これは汎用メモリレイヤーでもランタイムでもベクトルデータベースでもありません。
113
113
 
114
+ ### 答えてくれること、答えてくれないこと
115
+
116
+ ![4コマ漫画:マスコットは「すべてのAIエラーを防げる」と約束するが、猫がピザと石油缶を尋ねるとしょげてしまい、別の猫が npm ERESOLVE を見せると目を輝かせる。MisakaNet が知っているのは収録済みの障害であり、一般知識ではない。](promotional/misakanet-scope-comic.webp)
117
+
118
+ 答えてくれるのは**収録済みの障害**であり、一般知識ではありません。見つからない場合は `no_match` と、
119
+ そのまま呼び出せる `intake` の案内が返ります —— 未ヒットはギャップが記録される経路そのものなので、
120
+ これもまた答えです。
121
+
114
122
  ### v2.16.0の新機能
115
123
 
116
124
  | 機能 | 説明 |
package/README.md CHANGED
@@ -86,6 +86,47 @@ No account, no token, no Python needed for the plugin path: the npm bundle mount
86
86
  Declared hosts and what was measured: [compatibility](docs/compatibility.md). Every channel, the
87
87
  prerequisites, and the two-package trap that costs people an install: [How to use it](#how-to-use-it).
88
88
 
89
+ ## What the DeepSeek Harness plugin adds
90
+
91
+ Version 2.40.0 ships the browser half, and 2.41.0 adds the rest of it: the surfaces below did not all land in
92
+ the same release, so this section lists them by the version that carries them. It is not a dialog: it puts
93
+ MisakaNet where the session already is.
94
+
95
+ **In 2.40.0 — published.** These six seats are what `npm view misakanet version` gives you today.
96
+
97
+ | Where | What you get |
98
+ | --- | --- |
99
+ | **Left column** | A permanent `MisakaNet` entry directly under `Plugins`. It is a shortcut, not the panel: clicking it opens a full page in the main column. Root scope — it does not come and go with a session. |
100
+ | **Conversation tab** | A `MisakaNet` tab beside Chat and Trajectory: what this session asked, what came back, and what you filed, rebuilt from the conversation's own rows. |
101
+ | **Right column** | The same panel as a pane, so it can sit next to the file tree, a terminal, or a document. |
102
+ | **Tool call rows** | Every `misakanet_search` and `misakanet_submit_intake` call gets its own row on the tool card: the query as it was sent, whether a lesson came back, and which lesson is on top, with the raw result one disclosure away. The row reports and never posts — the vote belongs on the answer's action row below. |
103
+ | **Assistant action row** | 👍 / 👎 on the answer that used a lesson. Those two are the only things the page ever sends — counters live in the browser, not on a server. |
104
+ | **Voice** | An off-by-default switch that explains both mechanisms: the cue the server names on the next search, and the local hook a page cannot read. |
105
+
106
+ <p align="center">
107
+ <img src="docs/assets/dsh-client-left-column.png" width="820" alt="DeepSeek Harness: a permanent MisakaNet entry in the left column under Plugins, and the full page it opens"/>
108
+ </p>
109
+
110
+ <p align="center">
111
+ <img src="docs/assets/dsh-client-right-panel.png" width="820" alt="The MisakaNet pane in the right column of a DeepSeek Harness session"/>
112
+ </p>
113
+
114
+ **With 2.41.0 — [release PR #2591](https://github.com/Ikalus1988/MisakaNet/pull/2591).** These six surfaces
115
+ are in `main` and ship in 2.41.0; a 2.40.0 install does not have them yet.
116
+
117
+ | Where | What you get |
118
+ | --- | --- |
119
+ | **`/misakanet` in the composer** | Type `/misakanet pip install timeout` and press Enter: the lessons come back in a card inside the composer, with no agent in the loop. The query is the only thing it sends. |
120
+ | **Frame-wide toast** | After a `/misakanet` search comes back with lessons, a card appears over every column with the top hit; dismiss it or click through to the lesson. |
121
+ | **Sidebar foot** | One action beside Settings: copy this session's MisakaNet activity as a summary for an issue or a PR body. |
122
+ | **中文 / English** | Every MisakaNet surface follows the host language: the panel, the `/misakanet` card, the settings row, and the plugin page's own title and description. |
123
+ | **Settings → General** | A MisakaNet preference row: play voice cues in this browser, and how much the surfaces show (compact / full). Both stay in the browser. |
124
+ | **Plugin page** | The MCP row's effective configuration — endpoint, transport, timeout — shown read-only, next to where it is edited (the profile's `cordis.patch.yml`). |
125
+
126
+ Which seats the half occupies and why they are `root` or `session` scope, with the host's own contract text
127
+ quoted: [compatibility](docs/compatibility.md). Running a host of your own and want a check that cannot
128
+ touch your profile: `python3 scripts/install_smoke.py dsh-client --serve`.
129
+
89
130
  ## What is MisakaNet?
90
131
 
91
132
  **Git-backed failure memory for AI coding agents.** An error shows up → the agent searches the lessons →
@@ -113,6 +154,13 @@ how much a lesson has been proven.
113
154
  | ❌ A cloud service requiring signup | ✅ `git clone` → search locally |
114
155
  | ❌ A skill marketplace | ✅ Debugging knowledge from real sessions |
115
156
 
157
+ ### What it can and cannot answer
158
+
159
+ ![Four-panel comic: the mascot promises to prevent every AI error; the cats ask about pizza and an oil barrel and it deflates — then a cat shows npm ERESOLVE and it lights up. MisakaNet knows the failures that have been indexed, not general knowledge.](promotional/misakanet-scope-comic.webp)
160
+
161
+ It answers for **the failures it has indexed**, not general knowledge. A query that finds nothing returns
162
+ `no_match` plus a ready-to-call intake — a miss is how a gap gets recorded, so a miss is an answer too.
163
+
116
164
  ### Lesson vs Skill
117
165
 
118
166
  A **skill** teaches an agent *how to do something*. A **lesson** records *what went wrong before, and how
@@ -121,21 +169,53 @@ a general memory layer, not a vector database. → [FAQ](FAQ.md)
121
169
 
122
170
  ## Benchmark: how much of a lesson does a model reproduce when handed one?
123
171
 
124
- Weekly benchmark (Cloudflare Workers AI, 2026-08-30). **Read the metric before the numbers** — measured
125
- 2026-09-25, the scenario in this benchmark is each lesson's own title, the "matching lesson" injected into the
126
- `with_lesson` arm is *that same lesson*, and the score is `lesson_hit_rate`: **the share of the injected lesson's commands reproduced in the answer**.
172
+ Weekly benchmark (Cloudflare Workers AI). **Read the metric before the numbers** — the scenario in this benchmark is each lesson's own title, the "matching lesson" injected into the `with_lesson` arm is *that same lesson*, and the
173
+ score is `lesson_hit_rate`: **the share of the injected lesson's commands reproduced in the answer**.
127
174
  No retrieval is called and correctness is not checked, so this is the **recitation** half of RAG, not
128
- evidence that search works:
175
+ evidence that search works.
176
+
177
+ Latest aggregated data: [`docs/benchmarks/latest.json`](docs/benchmarks/latest.json) (2026-09-22, two
178
+ independent runs of ≈500 scenarios each):
179
+
180
+ | Condition | Run 1 hit rate | Run 2 hit rate | Avg | n (per run) | Actionable |
181
+ |---|---|---|---|---|---|
182
+ | plain (no lesson) | 0.239 | 0.233 | **23.3%** | ≈510 | 82–83% |
183
+ | with_lesson (pasted) | 0.464 | 0.461 | **46.1%** | ≈512 | 76–77% |
129
184
 
130
- | Model | Lesson pasted in prompt: not pasted | Lesson pasted in prompt: pasted | Difference |
185
+ **Reproducibility.** Two runs with identical config produce hit rates within 0.3% of each other
186
+ (0.464 vs 0.461 for `with_lesson`; 0.239 vs 0.233 for `plain`), confirming the metric is stable.
187
+
188
+ **Aggregation.** Each run evaluates every lesson in the corpus as a scenario. The `with_lesson` arm pastes the matching lesson
189
+ into the prompt; `plain` uses no lesson. `actionable` is a boolean per scenario indicating whether the
190
+ model produced a usable answer. Actionable rates are stable across runs (76–77% with lesson, 82–83% plain).
191
+
192
+ **Trend** (weekly snapshots):
193
+
194
+ | Date | with_lesson hit rate | plain hit rate | n |
131
195
  |---|---|---|---|
132
- | llama-3.2-3b (light) | 21% of the lesson's commands reproduced | **43%** | **2×** |
133
- | llama-3.3-70b (strong) | 42% | **73%** | **+31%** |
196
+ | 2026-08-30 | 46.4% | 23.9% | 358 |
197
+ | 2026-08-31 | 49.1% | 25.1% | 398 |
198
+ | 2026-09-06 | 48.3% | 24.1% | 455 |
199
+ | 2026-09-14 | 46.6% | 23.4% | 494 |
200
+ | 2026-09-21 | 46.1% | 23.3% | 512 |
201
+
202
+ ```
203
+ with_lesson hit rate (weekly)
204
+ 49.1% │ ▄
205
+ 48.3% │ █ ▄
206
+ 46.6% │ █ █ ▄
207
+ 46.4% │ ▄ █ █ █ ▄
208
+ 46.1% │ █ █ █ █ █
209
+ └──────────────────
210
+ 08 08 09 09 09
211
+ 30 31 06 14 21
212
+ ```
134
213
 
135
214
  A model repeats more of a document it was handed, and the weaker the model the bigger the relative
136
215
  difference. That is *necessary* for the product to help and it is not sufficient — the claim "search finds the
137
216
  right lesson for a failure you described" is measured nowhere yet. Details:
138
- [benchmark-2026-08-30](docs/benchmarks/benchmark-2026-08-30.json) · metric definition: `METRIC_DEFINITION` in
217
+ [`docs/benchmarks/latest.json`](docs/benchmarks/latest.json) · per-run files in
218
+ [`docs/benchmarks/`](docs/benchmarks/) · metric definition: `METRIC_DEFINITION` in
139
219
  [`scripts/benchmark_workers_ai.py`](scripts/benchmark_workers_ai.py)
140
220
 
141
221
  → [Full changelog](CHANGELOG.md) · [Release notes](https://github.com/Ikalus1988/MisakaNet/releases)
@@ -147,6 +227,7 @@ and where this design loses:
147
227
  |---|---|---|
148
228
  | Hit rate | share of the **injected** lesson's commands reproduced in the answer — a recitation check; the scenario is that lesson's own title and no retrieval happens | it is the ceiling on usefulness, not the measure of it: a corpus can be recitable and still unfindable |
149
229
  | Gain (with − without) | how much more of that lesson appears when it is pasted in | separates "the model can use a lesson" from "the model guessed the same words" — it says nothing about finding the lesson |
230
+ | Actionable | whether the model produced a usable answer at all (boolean per scenario) | a high hit rate on an answer that is not actionable is noise; this tracks whether the model engages with the problem |
150
231
  | Cost / latency | tokens and wall-clock per answer | the whole premise is cheaper than re-debugging, so it has to stay cheap |
151
232
 
152
233
  **Where it loses on purpose:** BM25 matches words, not meaning. A failure described in vocabulary the
package/README.zh-CN.md CHANGED
@@ -102,9 +102,9 @@ python3 search_knowledge.py "GitHub token 401"
102
102
 
103
103
  ```bash
104
104
  # npm 安装(推荐)
105
- dsh plugin add misakanet
105
+ dsh plugin --profile web add misakanet
106
106
  # 或直接从 git 安装(同一 bundle)
107
- # dsh plugin add git+https://github.com/Ikalus1988/MisakaNet.git
107
+ # dsh plugin --profile web add git+https://github.com/Ikalus1988/MisakaNet.git
108
108
 
109
109
  # 让 failure-memory SKILL 可被发现(DSH 扫描 ~/.dsh/skills 与项目 .dsh/skills)
110
110
  mkdir -p ~/.dsh/skills
@@ -164,6 +164,13 @@ MisakaNet 对不同用户的用途不同:
164
164
 
165
165
  > 👉 第一次来?[看 MisakaNet Journey →](https://misakanet.org/journey/)
166
166
 
167
+ ### 它能回答什么,不能回答什么
168
+
169
+ ![四格漫画:吉祥物承诺能避免所有 AI 错误;猫问起披萨和油桶,它就瘪了 —— 然后一只猫亮出 npm ERESOLVE,它立刻发光。MisakaNet 只认识已经收录的失败,不是通用知识。](promotional/misakanet-scope-comic.webp)
170
+
171
+ 它只回答**已经收录过的失败**,不是通用知识。查不到时会返回 `no_match` 和一条可直接调用的 `intake`
172
+ 指引 —— 未命中正是一条缺口被记下来的方式,所以它同样是一个答案。
173
+
167
174
  ### Lesson 和 Skill 有什么区别?
168
175
 
169
176
  MisakaNet 的 lesson **不是** skill。
package/index.js CHANGED
@@ -120,3 +120,73 @@ export async function apply(ctx, config = {}) {
120
120
  ctx?.logger?.warn?.(`misakanet: MCP client not mounted: ${error?.message ?? error}`);
121
121
  }
122
122
  }
123
+
124
+ /**
125
+ * The row's `Config`: what the Loader validates the bundle patch's `config:` against, and what the plugin
126
+ * page turns into a form — the host's own words for it are "the cordis `Config` validator and the
127
+ * Config-form generation's served schema" (`dsh-context`'s `index.d.ts` says the same thing about its own).
128
+ *
129
+ * Built with a **top-level `await` inside a `try`**, not a static import. `@deepseek-ai/schemastery` is a
130
+ * host dependency, but this package is also installed by skill-only consumers that never load this module,
131
+ * and a module-level import failure would take the whole row down rather than only its form. Without it the
132
+ * row keeps working from the patch and only the GUI form is lost — the same "absence is not failure" rule
133
+ * `apply()` follows for the MCP client.
134
+ */
135
+ /**
136
+ * Import schemastery from wherever this install can actually reach it.
137
+ *
138
+ * A profile that **installed** this package resolves the bare specifier on its own: Node walks up from
139
+ * `…/profiles/web/node_modules/misakanet/` and finds the profile's copy. A profile that **linked** a working
140
+ * tree does not — Node resolves the link to its real path, so the walk starts in the repository and never
141
+ * sees the profile. That is the shape this repository's own contributor profiles (and the owner's live one)
142
+ * use, so the second attempt resolves from the `dsh` entry point that started the host, where schemastery is
143
+ * a dependency of DSH itself.
144
+ */
145
+ async function loadSchemastery() {
146
+ const attempts = ['@deepseek-ai/schemastery'];
147
+ try {
148
+ const { createRequire } = await import('node:module');
149
+ const { realpathSync } = await import('node:fs');
150
+ const { pathToFileURL } = await import('node:url');
151
+ const hostEntry = process.argv[1];
152
+ // Both spellings matter: the bin is usually a **symlink**, and the package's own node_modules sits
153
+ // beside its real path — resolving from the link's directory finds the global root instead.
154
+ const from = [];
155
+ if (hostEntry) from.push(hostEntry);
156
+ try { from.push(realpathSync(hostEntry)); } catch (error) { /* no real path to add */ }
157
+ for (const entry of from) {
158
+ try {
159
+ const resolved = createRequire(entry).resolve('@deepseek-ai/schemastery');
160
+ // `require.resolve` hands back a filesystem path, and a Windows one is not a valid ESM specifier
161
+ // (`C:` parses as a scheme). The bare specifier above is left alone; only paths are wrapped.
162
+ const url = pathToFileURL(resolved).href;
163
+ if (!attempts.includes(url)) attempts.push(url);
164
+ } catch (error) { /* this entry cannot see it */ }
165
+ }
166
+ } catch (error) { /* keep the bare specifier as the only attempt */ }
167
+ for (const specifier of attempts) {
168
+ try {
169
+ const loaded = await import(specifier);
170
+ return loaded.default ?? loaded;
171
+ } catch (error) { /* try the next location */ }
172
+ }
173
+ return undefined;
174
+ }
175
+
176
+ let Config;
177
+ try {
178
+ const z = await loadSchemastery();
179
+ if (z === undefined) throw new Error('schemastery is not resolvable from this install');
180
+ Config = z.object({
181
+ transport: z.string().default(DEFAULT_MCP_CONFIG.transport),
182
+ serverName: z.string().default(DEFAULT_MCP_CONFIG.serverName),
183
+ url: z.string().default(DEFAULT_MCP_CONFIG.url),
184
+ headers: z.dict(z.string()).default({ ...DEFAULT_MCP_CONFIG.headers }),
185
+ toolCallTimeoutMs: z.number().default(DEFAULT_MCP_CONFIG.toolCallTimeoutMs),
186
+ failOnStartupError: z.boolean().default(DEFAULT_MCP_CONFIG.failOnStartupError),
187
+ });
188
+ } catch (error) {
189
+ Config = undefined;
190
+ }
191
+
192
+ export { Config };