misakanet 2.43.1 → 2.44.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/.codex-plugin/plugin.json +1 -1
- package/README.ja.md +1 -1
- package/README.md +1 -1
- package/README.zh-CN.md +3 -3
- package/SKILL.md +2 -2
- package/lib/client.js +223 -21
- package/package.json +1 -1
- package/skills/misakanet/SKILL.md +2 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "misakanet",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.44.1",
|
|
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
|
@@ -12,7 +12,7 @@ mcp-name: io.github.Ikalus1988/misakanet
|
|
|
12
12
|
> 誰かがすでに代償を支払ったバグを、セッションごとに一つずつ再発見せずに済みます —— 上部の **Lessons**
|
|
13
13
|
> バッジが現在のコーパス規模です。
|
|
14
14
|
>
|
|
15
|
-
> エージェントネイティブなインターフェース: [MCP サーバー](https://misakanet.org/mcp)(
|
|
15
|
+
> エージェントネイティブなインターフェース: [MCP サーバー](https://misakanet.org/mcp)(8 ツール)、WebMCP(ブラウザの
|
|
16
16
|
> `navigator.modelContext`)、`llms.txt` / `llms-full.txt`、そして `.well-known/agent-card.json` 経由の A2A ディスカバリー。
|
|
17
17
|
|
|
18
18
|
<p align="center">
|
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ mcp-name: io.github.Ikalus1988/misakanet
|
|
|
12
12
|
> the bugs someone already paid for, instead of rediscovering them one session at a time — the **Lessons**
|
|
13
13
|
> badge above is the live corpus size.
|
|
14
14
|
>
|
|
15
|
-
> Agent-native interfaces: [MCP server](https://misakanet.org/mcp) (
|
|
15
|
+
> Agent-native interfaces: [MCP server](https://misakanet.org/mcp) (8 tools), WebMCP (browser
|
|
16
16
|
> `navigator.modelContext`), `llms.txt` / `llms-full.txt`, and A2A discovery through
|
|
17
17
|
> `.well-known/agent-card.json`.
|
|
18
18
|
|
package/README.zh-CN.md
CHANGED
|
@@ -439,7 +439,7 @@ npx @misaka-net/misakanet-setup
|
|
|
439
439
|
|
|
440
440
|
| 层 | 是什么 | 缺了它会怎样 |
|
|
441
441
|
|---|---|---|
|
|
442
|
-
| **① 服务** | `https://misakanet.org/mcp`(Streamable HTTP,
|
|
442
|
+
| **① 服务** | `https://misakanet.org/mcp`(Streamable HTTP,8 个工具,匿名**不限次数**,只有反爬突发保护)或**本地 stdio**(clone 后 `python3 scripts/mcp_server.py`,无限额)| 没有可查的地方 |
|
|
443
443
|
| **② 接入** | `npx @misaka-net/misakanet-setup`:把服务写进每个助手**自己的**配置文件(Claude Code / Codex / Hermes / OpenClaw / codewhale 各一套)| 你得自己知道 5 种配置文件分别怎么写 |
|
|
444
444
|
| **③ 触发** | 规则块(「遇到报错先查经验库」)+ 检查点钩子(约 20 轮提醒沉淀)+ 14 天升级提示 | **端点在,但没有任何人会去调用它** |
|
|
445
445
|
|
|
@@ -452,8 +452,8 @@ setup 保证的是"工具确实在"和"该查的时刻更容易被抓住",不
|
|
|
452
452
|
|
|
453
453
|
### 装完你得到什么(逐条可自检)
|
|
454
454
|
|
|
455
|
-
1. **
|
|
456
|
-
`claude mcp list` / `hermes mcp list`;**证据**:列表里有 `misakanet` 且
|
|
455
|
+
1. **8 个 `misakanet_*` 工具出现在助手里** —— `codex mcp list` / `codewhale mcp tools` /
|
|
456
|
+
`claude mcp list` / `hermes mcp list`;**证据**:列表里有 `misakanet` 且 8 个工具;
|
|
457
457
|
2. **助手被要求「遇错先查」** —— 问一句「switch vision model」「context window exceeded」这类片段,它应该先说查过经验库;
|
|
458
458
|
**证据**:事件流里出现 `misakanet_search`(claude/codewhale 用 `--output-format stream-json`,codex 用 `--json`);
|
|
459
459
|
3. **长会话会提醒沉淀** —— 约 20 轮后提醒把本次「失败 → 根因 → 修复 → 验证」变成一条课程
|
package/SKILL.md
CHANGED
|
@@ -45,8 +45,8 @@ Do NOT use MisakaNet for:
|
|
|
45
45
|
> stdio server adds `misakanet_me_events` as a **proxy** of the hosted tool, so the reuse-evidence
|
|
46
46
|
> steps below work on either install.
|
|
47
47
|
>
|
|
48
|
-
> * **hosted** exposes
|
|
49
|
-
> * a **local stdio** install (`python3 scripts/mcp_server.py`) exposes those same
|
|
48
|
+
> * **hosted** exposes 8 tools, `misakanet_me_events` among them;
|
|
49
|
+
> * a **local stdio** install (`python3 scripts/mcp_server.py`) exposes those same 8 **plus three that
|
|
50
50
|
> only make sense on your machine** — `misakanet_submit_usage`, `misakanet_usage_status` and
|
|
51
51
|
> `misakanet_memory_context`. They read this checkout's own usage meter and `lessons/` corpus, which
|
|
52
52
|
> a hosted endpoint has nothing to answer.
|
package/lib/client.js
CHANGED
|
@@ -178,6 +178,16 @@ window.__ModuleLoader__.load({
|
|
|
178
178
|
"panel.asked.voteNotHelpful": "not helpful",
|
|
179
179
|
"panel.asked.voteNone": "not voted",
|
|
180
180
|
"panel.asked.voteNoLesson": "no lesson",
|
|
181
|
+
"panel.asked.voteHint": "Same action as the verdict beside the assistant message, without scrolling back to it. Sends this lesson's id and one constant label (`dsh-web`); nothing else.",
|
|
182
|
+
"panel.asked.voteFailed": "could not reach misakanet.org — nothing was recorded",
|
|
183
|
+
"panel.asked.voteOne": "1 human confirmation — the reuse event now appears (E3: a reuse signal, not CI verification).",
|
|
184
|
+
"panel.asked.voteTwo": "2 human confirmations — enough for agents to read this as E4.",
|
|
185
|
+
"panel.asked.voteMore": "human confirmations — enough for agents to read this as E4.",
|
|
186
|
+
"panel.asked.noMatchTag": "no match",
|
|
187
|
+
"panel.asked.agentNext": "Hand this line to the agent:",
|
|
188
|
+
"panel.asked.agentNextCopy": "Copy the next step",
|
|
189
|
+
"panel.asked.agentNextText": "Please record this gap with the MisakaNet intake so the next person finds it: misakanet_submit_intake problem: ",
|
|
190
|
+
"panel.asked.agentNextWhy": "This page cannot file it: a report is re-checked by submitting the same text again, the server's dedup window is finite, and a page-triggered submit could open a second issue for one problem.",
|
|
181
191
|
"panel.counters": "this session · counters local to this browser · no account, nothing uploaded but your votes and reports",
|
|
182
192
|
"panel.report.title": "MisakaNet report",
|
|
183
193
|
"panel.report.coveredBy": "covered by ",
|
|
@@ -196,6 +206,9 @@ window.__ModuleLoader__.load({
|
|
|
196
206
|
"panel.trust.human": "human confirmation",
|
|
197
207
|
"panel.trust.noLevel": "no level",
|
|
198
208
|
"panel.trust.used": " · used ",
|
|
209
|
+
"panel.trust.external": "external reuse evidence: ",
|
|
210
|
+
"panel.trust.declared": "declared: ",
|
|
211
|
+
"panel.trust.e4signal": "live signal: E4",
|
|
199
212
|
"panel.trust.footnote": "The level is the lesson's own stored evidence. The count is other people's confirmations, not yours: one makes the reuse event appear, the second is what agents read as E4.",
|
|
200
213
|
"panel.activity.session": "this session: ",
|
|
201
214
|
"panel.activity.browser": "on this browser: ",
|
|
@@ -212,9 +225,11 @@ window.__ModuleLoader__.load({
|
|
|
212
225
|
"main.footnote": "The left column opens this page; the session-scoped counters live in the session's right-sidebar MisakaNet tab. The numbers here are what this browser has contributed.",
|
|
213
226
|
"tool.rawResult": "raw result",
|
|
214
227
|
"tool.readFailed": "result could not be read",
|
|
215
|
-
"tool.helpfulTitle": "Sends this lesson's id to misakanet.org as reuse evidence. Sends nothing else.",
|
|
228
|
+
"tool.helpfulTitle": "Sends this lesson's id and the fixed label `dsh-web` to misakanet.org as reuse evidence. Sends nothing else.",
|
|
216
229
|
"tool.notHelpfulTitle": "Sends this lesson's id and the search text, so the gap gets counted.",
|
|
217
|
-
"tool.helpfulHint": "Helpful sends the lesson id · not-helpful also sends the search text (gap stats)",
|
|
230
|
+
"tool.helpfulHint": "Helpful sends the lesson id and the label `dsh-web` · not-helpful also sends the search text (gap stats)",
|
|
231
|
+
"tool.verdict.helpful": "recorded — this lesson now has {count} human confirmation(s)",
|
|
232
|
+
"tool.verdict.helpfulSelf": "recorded — this lesson now has your human confirmation",
|
|
218
233
|
"tool.helpful": "👍 Helpful",
|
|
219
234
|
"tool.notHelpful": "👎 Not what I needed",
|
|
220
235
|
"tool.untitled": "(untitled)",
|
|
@@ -287,6 +302,16 @@ window.__ModuleLoader__.load({
|
|
|
287
302
|
"panel.asked.voteNotHelpful": "没用",
|
|
288
303
|
"panel.asked.voteNone": "未投票",
|
|
289
304
|
"panel.asked.voteNoLesson": "无课程",
|
|
305
|
+
"panel.asked.voteHint": "与助手消息旁的裁决行是同一个动作,不用再往回滚。只发这篇课程的 id 和一个固定标签(`dsh-web`),不发别的。",
|
|
306
|
+
"panel.asked.voteFailed": "连不上 misakanet.org —— 这次没有记下任何东西",
|
|
307
|
+
"panel.asked.voteOne": "1 个人工确认 —— 复用事件现在出现了(E3:复用信号,不是 CI 验证)。",
|
|
308
|
+
"panel.asked.voteTwo": "2 个人工确认 —— 已经是 agent 读到的 E4 了。",
|
|
309
|
+
"panel.asked.voteMore": "个人工确认 —— 已经是 agent 读到的 E4 了。",
|
|
310
|
+
"panel.asked.noMatchTag": "无命中",
|
|
311
|
+
"panel.asked.agentNext": "把这行交给 agent:",
|
|
312
|
+
"panel.asked.agentNextCopy": "复制下一步",
|
|
313
|
+
"panel.asked.agentNextText": "请用 MisakaNet 报料记下这个缺口,让下一个人能搜到:misakanet_submit_intake problem: ",
|
|
314
|
+
"panel.asked.agentNextWhy": "这个页面不能替你报:报料的复查方式是原样再提交一次,而服务端的去重窗口是有限的 —— 页面触发的提交可能为同一个问题开出第二个 issue。",
|
|
290
315
|
"panel.counters": "本会话 · 计数只存在本浏览器 · 没有账号,除了你的投票与报料,不上传任何东西",
|
|
291
316
|
"panel.report.title": "MisakaNet 报料",
|
|
292
317
|
"panel.report.coveredBy": "已被 ",
|
|
@@ -305,6 +330,9 @@ window.__ModuleLoader__.load({
|
|
|
305
330
|
"panel.trust.human": "人工确认",
|
|
306
331
|
"panel.trust.noLevel": "无等级",
|
|
307
332
|
"panel.trust.used": " · 已复用 ",
|
|
333
|
+
"panel.trust.external": "外部复用证据:",
|
|
334
|
+
"panel.trust.declared": "课程自述:",
|
|
335
|
+
"panel.trust.e4signal": "实时信号:E4",
|
|
308
336
|
"panel.trust.footnote": "等级来自课程自己存的证据;计数是别人的确认,不是你的:前者让复用事件出现,后者才是 agent 读到的 E4。",
|
|
309
337
|
"panel.activity.session": "本会话:",
|
|
310
338
|
"panel.activity.browser": "本浏览器:",
|
|
@@ -321,9 +349,11 @@ window.__ModuleLoader__.load({
|
|
|
321
349
|
"main.footnote": "左栏打开的就是这一页;会话级的计数在右栏的 MisakaNet 标签里。这里的数字是本浏览器贡献的部分。",
|
|
322
350
|
"tool.rawResult": "原始结果",
|
|
323
351
|
"tool.readFailed": "结果读不出来",
|
|
324
|
-
"tool.helpfulTitle": "把这篇课程的 id
|
|
352
|
+
"tool.helpfulTitle": "把这篇课程的 id 和一个固定标签(`dsh-web`)发给 misakanet.org 作为复用证据,不发别的。",
|
|
325
353
|
"tool.notHelpfulTitle": "把课程 id 和检索文本一起发出去,好把缺口统计进去。",
|
|
326
|
-
"tool.helpfulHint": "「有用」只发课程 id ·「没用」还会发检索文本(用于缺口统计)",
|
|
354
|
+
"tool.helpfulHint": "「有用」只发课程 id 与固定标签 `dsh-web` ·「没用」还会发检索文本(用于缺口统计)",
|
|
355
|
+
"tool.verdict.helpful": "已记录 —— 这篇课程现在有 {count} 个人工确认",
|
|
356
|
+
"tool.verdict.helpfulSelf": "已记录 —— 这篇课程现在有你的一次人工确认",
|
|
327
357
|
"tool.helpful": "👍 有用",
|
|
328
358
|
"tool.notHelpful": "👎 不是我需要的",
|
|
329
359
|
"tool.untitled": "(无标题)",
|
|
@@ -590,6 +620,32 @@ var DEFAULT_MCP_URL = "https://misakanet.org/mcp";
|
|
|
590
620
|
var OVERLAY_LIMIT = 5;
|
|
591
621
|
var OVERLAY_TIMEOUT_MS = 8000;
|
|
592
622
|
|
|
623
|
+
/**
|
|
624
|
+
* The label every vote from this browser half carries: what cast it, not who.
|
|
625
|
+
*
|
|
626
|
+
* It is a **constant**, identical for every person and every session. There is no account, no
|
|
627
|
+
* `client_id`, no cookie and no generated value anywhere in this file — the repository's privacy
|
|
628
|
+
* line is "no account, no client_id, nothing uploaded but your votes and reports", and a fixed
|
|
629
|
+
* surface label does not cross it while a generated id would. What it buys is the only thing that
|
|
630
|
+
* was missing: `POST /api/helpful` used to accept `{lesson_id}` alone, so a vote cast from this
|
|
631
|
+
* panel was byte-identical to one cast by `curl` and the panel's own effect was unmeasurable by
|
|
632
|
+
* construction. The worker keeps `count` exactly as it was and writes this label to its own
|
|
633
|
+
* per-source, per-day counter.
|
|
634
|
+
*/
|
|
635
|
+
var HELPFUL_SOURCE = "dsh-web";
|
|
636
|
+
|
|
637
|
+
/**
|
|
638
|
+
* The exact line the panel hands back to the agent for a search that matched nothing.
|
|
639
|
+
*
|
|
640
|
+
* The panel cannot file it: a receipt is pulled only by submitting the same text again, and the
|
|
641
|
+
* server's dedup window is finite, so a page-triggered submit could open a **second** issue for
|
|
642
|
+
* one problem (acceptance item D4). A copyable string has no such power, and it is the one thing
|
|
643
|
+
* this page can honestly offer — the agent in the chat is the only party that may submit.
|
|
644
|
+
*/
|
|
645
|
+
function intakeNextStep(query) {
|
|
646
|
+
return T("panel.asked.agentNextText") + JSON.stringify(String(query || ""));
|
|
647
|
+
}
|
|
648
|
+
|
|
593
649
|
function isJson(text) {
|
|
594
650
|
try { JSON.parse(text); return true; } catch (error) { return false; }
|
|
595
651
|
}
|
|
@@ -942,6 +998,23 @@ var DEFAULT_MCP_URL = "https://misakanet.org/mcp";
|
|
|
942
998
|
});
|
|
943
999
|
}
|
|
944
1000
|
|
|
1001
|
+
/**
|
|
1002
|
+
* The one place a helpful vote is posted, from either surface (the message verdict, the panel row).
|
|
1003
|
+
*
|
|
1004
|
+
* One function, so the two surfaces cannot drift into sending different bodies — and so the body
|
|
1005
|
+
* is stated once: this lesson's id, plus the constant `HELPFUL_SOURCE` label. No query text, no
|
|
1006
|
+
* identity, no timestamp of our own. The guard is a double-submit brake, not an auto-vote: it only
|
|
1007
|
+
* stops a *second* click on a sighting whose vote already landed, and abstaining remains free.
|
|
1008
|
+
*/
|
|
1009
|
+
function sendHelpfulVote(log, entry) {
|
|
1010
|
+
if (!entry || entry.voted) return Promise.resolve(null);
|
|
1011
|
+
return post("/api/helpful", { lesson_id: entry.lessonId, source: HELPFUL_SOURCE })
|
|
1012
|
+
.then(function (answer) {
|
|
1013
|
+
recordVote(log, entry, "helpful", answer);
|
|
1014
|
+
return answer;
|
|
1015
|
+
});
|
|
1016
|
+
}
|
|
1017
|
+
|
|
945
1018
|
/**
|
|
946
1019
|
* The tool-call row for `misakanet_search`: what came back — and nothing else.
|
|
947
1020
|
*
|
|
@@ -974,7 +1047,11 @@ var DEFAULT_MCP_URL = "https://misakanet.org/mcp";
|
|
|
974
1047
|
} else if (payload && payload.no_match) {
|
|
975
1048
|
head.push(h("span", { key: "state" }, " " + T("panel.asked.noMatch")));
|
|
976
1049
|
} else if (results.length) {
|
|
977
|
-
|
|
1050
|
+
// Through the plural helper, like every other count: this line used to spell the plural by
|
|
1051
|
+
// hand (`results.length === 1 ? " lesson" : " lessons"`), which is exactly the shape the
|
|
1052
|
+
// helper exists to prevent — and it was also the one count in this file that could not be
|
|
1053
|
+
// localized.
|
|
1054
|
+
head.push(h("span", { key: "state" }, " " + count(results.length, T("unit.lesson"), T("unit.lessons"))));
|
|
978
1055
|
head.push(h("span", { key: "top", style: DIM }, " · top: "));
|
|
979
1056
|
head.push(h("span", { key: "title" }, top.title || top.id || T("tool.untitled")));
|
|
980
1057
|
// Only fields the DEFAULT payload actually carries. `detail: "compact"` is
|
|
@@ -1031,21 +1108,23 @@ var DEFAULT_MCP_URL = "https://misakanet.org/mcp";
|
|
|
1031
1108
|
if (log.shownFor && log.shownFor !== messageId) return null;
|
|
1032
1109
|
|
|
1033
1110
|
function send(kind) {
|
|
1034
|
-
// 👍 carries the lesson id
|
|
1035
|
-
//
|
|
1111
|
+
// 👍 carries the lesson id plus the fixed `dsh-web` label and nothing else — one call site
|
|
1112
|
+
// (`sendHelpfulVote`), shared with the panel's row so the two surfaces cannot drift. 👎 has
|
|
1113
|
+
// to carry the search text: that is what turns one annoyed person into a counted gap, and
|
|
1114
|
+
// the line below says so before the click.
|
|
1036
1115
|
var call = kind === "helpful"
|
|
1037
|
-
?
|
|
1116
|
+
? sendHelpfulVote(log, pending)
|
|
1038
1117
|
: post("/api/feedback", { query: pending.query, lesson_id: pending.lessonId, feedback: "irrelevant" });
|
|
1039
1118
|
call.then(
|
|
1040
1119
|
function (answer) {
|
|
1041
|
-
recordVote(log, pending, kind, answer);
|
|
1120
|
+
if (kind !== "helpful") recordVote(log, pending, kind, answer);
|
|
1042
1121
|
setVerdict({
|
|
1043
1122
|
kind: kind,
|
|
1044
1123
|
count: answer && typeof answer.count === "number" ? answer.count : null,
|
|
1045
1124
|
});
|
|
1046
1125
|
},
|
|
1047
1126
|
function () {
|
|
1048
|
-
setVerdict({ error: "
|
|
1127
|
+
setVerdict({ error: T("panel.asked.voteFailed") });
|
|
1049
1128
|
}
|
|
1050
1129
|
);
|
|
1051
1130
|
}
|
|
@@ -1056,7 +1135,9 @@ var DEFAULT_MCP_URL = "https://misakanet.org/mcp";
|
|
|
1056
1135
|
|
|
1057
1136
|
if (verdict) {
|
|
1058
1137
|
var done = verdict.kind === "helpful"
|
|
1059
|
-
?
|
|
1138
|
+
? (verdict.count === null
|
|
1139
|
+
? T("tool.verdict.helpfulSelf")
|
|
1140
|
+
: T("tool.verdict.helpful", { count: verdict.count }))
|
|
1060
1141
|
: "recorded as not helpful — it feeds the unsolved-gap map";
|
|
1061
1142
|
return h("span", { style: Object.assign({}, DIM, { fontSize: "12px" }) }, done);
|
|
1062
1143
|
}
|
|
@@ -1151,6 +1232,11 @@ var DEFAULT_MCP_URL = "https://misakanet.org/mcp";
|
|
|
1151
1232
|
var trustState = react.useState({});
|
|
1152
1233
|
var trust = trustState[0];
|
|
1153
1234
|
var setTrust = trustState[1];
|
|
1235
|
+
// What a click just did, per search row: the count the server answered with, or a failure. The
|
|
1236
|
+
// point of change #2 is that the click is *consequential*, so the row has to say what moved.
|
|
1237
|
+
var voteState = react.useState({});
|
|
1238
|
+
var panelVotes = voteState[0];
|
|
1239
|
+
var setPanelVotes = voteState[1];
|
|
1154
1240
|
|
|
1155
1241
|
react.useEffect(function () {
|
|
1156
1242
|
return subscribe(sessionId, function () {
|
|
@@ -1222,18 +1308,106 @@ var DEFAULT_MCP_URL = "https://misakanet.org/mcp";
|
|
|
1222
1308
|
count(intakes.length, "report") + " (" + converted + " became a lesson)"));
|
|
1223
1309
|
|
|
1224
1310
|
// ① what this session asked
|
|
1311
|
+
//
|
|
1312
|
+
// This is the session's own transcript, and each row already knows which searches were *not*
|
|
1313
|
+
// voted — so this is where a vote costs one click instead of a scroll back to the finalized
|
|
1314
|
+
// message the verdict lives beside. The row offers exactly the action the verdict row offers
|
|
1315
|
+
// (`sendHelpfulVote`, one call site), and abstaining stays free: the button is an offer, it is
|
|
1316
|
+
// not pre-selected and nothing posts without a click.
|
|
1317
|
+
//
|
|
1318
|
+
// A no-match row is drawn distinctly and carries the one thing this page may hand over: a
|
|
1319
|
+
// copyable line for the agent. It cannot file the gap itself (see `intakeNextStep`).
|
|
1320
|
+
function voteFromPanel(entry) {
|
|
1321
|
+
var key = "q" + entry.callId + entry.at;
|
|
1322
|
+
sendHelpfulVote(log, entry).then(
|
|
1323
|
+
function (answer) {
|
|
1324
|
+
var total = answer && typeof answer.count === "number" ? answer.count : null;
|
|
1325
|
+
if (total !== null) {
|
|
1326
|
+
// Written into the same per-lesson receipt section ③ renders, so the number the
|
|
1327
|
+
// click produced and the number the section shows can never disagree.
|
|
1328
|
+
asked.current[entry.lessonId] = true;
|
|
1329
|
+
setTrust(function (prev) {
|
|
1330
|
+
var next = Object.assign({}, prev);
|
|
1331
|
+
next[entry.lessonId] = total;
|
|
1332
|
+
return next;
|
|
1333
|
+
});
|
|
1334
|
+
}
|
|
1335
|
+
var said = total === null ? ""
|
|
1336
|
+
: (total === 1 ? T("panel.asked.voteOne")
|
|
1337
|
+
: (total === 2 ? T("panel.asked.voteTwo")
|
|
1338
|
+
: total + " " + T("panel.asked.voteMore")));
|
|
1339
|
+
setPanelVotes(function (prev) {
|
|
1340
|
+
var next = Object.assign({}, prev);
|
|
1341
|
+
next[key] = said || T("panel.asked.voteFailed");
|
|
1342
|
+
return next;
|
|
1343
|
+
});
|
|
1344
|
+
},
|
|
1345
|
+
function () {
|
|
1346
|
+
setPanelVotes(function (prev) {
|
|
1347
|
+
var next = Object.assign({}, prev);
|
|
1348
|
+
next[key] = T("panel.asked.voteFailed");
|
|
1349
|
+
return next;
|
|
1350
|
+
});
|
|
1351
|
+
}
|
|
1352
|
+
);
|
|
1353
|
+
}
|
|
1354
|
+
|
|
1225
1355
|
rows.push(h("div", { key: "s1", style: { marginTop: "12px", fontWeight: 600 } }, T("panel.asked")));
|
|
1226
1356
|
if (!searches.length) {
|
|
1227
1357
|
rows.push(h("div", { key: "s1e", style: DIM }, T("panel.asked.none")));
|
|
1228
1358
|
} else {
|
|
1229
1359
|
var searchRows = searches.slice().reverse().slice(0, 20).map(function (entry) {
|
|
1230
|
-
var
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1360
|
+
var key = "q" + entry.callId + entry.at;
|
|
1361
|
+
var vote = entry.voted
|
|
1362
|
+
? (entry.voteKind === "helpful" ? T("panel.asked.voteHelpful") : T("panel.asked.voteNotHelpful"))
|
|
1363
|
+
: (entry.lessonId ? T("panel.asked.voteNone") : T("panel.asked.voteNoLesson"));
|
|
1364
|
+
var said = panelVotes[key];
|
|
1365
|
+
var missed = Boolean(entry.noMatch) || !entry.lessonId;
|
|
1366
|
+
var controls = [];
|
|
1367
|
+
if (entry.lessonId && !entry.voted) {
|
|
1368
|
+
controls.push(h("button", {
|
|
1369
|
+
key: "v", type: "button", style: BUTTON, title: T("panel.asked.voteHint"),
|
|
1370
|
+
onClick: function () { voteFromPanel(entry); },
|
|
1371
|
+
}, T("tool.helpful")));
|
|
1372
|
+
}
|
|
1373
|
+
if (missed) {
|
|
1374
|
+
// A copy, never a submit. The string is the next step *for the agent*, because the
|
|
1375
|
+
// only way to pull a receipt is to submit the same text again and a page-triggered
|
|
1376
|
+
// re-check could open a second issue for one problem.
|
|
1377
|
+
controls.push(h("button", {
|
|
1378
|
+
key: "c", type: "button", style: BUTTON, title: intakeNextStep(entry.query),
|
|
1379
|
+
onClick: function () {
|
|
1380
|
+
copyText(intakeNextStep(entry.query), function (label) {
|
|
1381
|
+
setPanelVotes(function (prev) {
|
|
1382
|
+
var next = Object.assign({}, prev);
|
|
1383
|
+
next[key] = label;
|
|
1384
|
+
return next;
|
|
1385
|
+
});
|
|
1386
|
+
});
|
|
1387
|
+
},
|
|
1388
|
+
}, T("panel.asked.agentNextCopy")));
|
|
1389
|
+
}
|
|
1390
|
+
var lines = [
|
|
1391
|
+
h("div", { key: "head", style: { borderLeft: "2px solid " + (missed ? "rgba(127,127,127,0.9)" : "transparent"), paddingLeft: missed ? "6px" : "8px" } },
|
|
1392
|
+
h("span", { style: DIM }, clockOf(entry.at) + " "),
|
|
1393
|
+
h("span", {}, entry.query || T("panel.asked.noQuery")),
|
|
1394
|
+
h("span", { style: DIM }, " " + (entry.noMatch ? T("panel.asked.nothingFound") : count(entry.hits, T("unit.lesson")))),
|
|
1395
|
+
missed ? h("span", { style: Object.assign({}, DIM, { border: "1px solid " + MUTED, borderRadius: "4px", padding: "0 4px", marginLeft: "4px", fontSize: "11px" }) },
|
|
1396
|
+
T("panel.asked.noMatchTag")) : null,
|
|
1397
|
+
entry.title ? h("span", { style: DIM }, " · top: " + entry.title + (entry.evidence ? " (" + entry.evidence + ")" : "")) : null,
|
|
1398
|
+
entry.lessonId ? h("span", { style: DIM }, " · " + vote) : null),
|
|
1399
|
+
];
|
|
1400
|
+
if (missed) {
|
|
1401
|
+
lines.push(h("div", { key: "next", style: DIM },
|
|
1402
|
+
T("panel.asked.agentNext") + " ",
|
|
1403
|
+
h("code", { style: { fontSize: "11px" } }, intakeNextStep(entry.query))));
|
|
1404
|
+
lines.push(h("div", { key: "why", style: DIM }, T("panel.asked.agentNextWhy")));
|
|
1405
|
+
}
|
|
1406
|
+
if (controls.length || said) {
|
|
1407
|
+
lines.push(h("div", { key: "do" }, controls,
|
|
1408
|
+
said ? h("span", { style: DIM }, said) : null));
|
|
1409
|
+
}
|
|
1410
|
+
return h("div", { key: key, style: { borderTop: "1px solid " + MUTED, padding: "4px 0" } }, lines);
|
|
1237
1411
|
});
|
|
1238
1412
|
rows.push(h("div", { key: "s1r" }, searchRows));
|
|
1239
1413
|
}
|
|
@@ -1272,6 +1446,24 @@ var DEFAULT_MCP_URL = "https://misakanet.org/mcp";
|
|
|
1272
1446
|
}
|
|
1273
1447
|
|
|
1274
1448
|
// ③ how much these lessons are trusted
|
|
1449
|
+
//
|
|
1450
|
+
// Two different facts, kept apart because they come from two different places and mean two
|
|
1451
|
+
// different things:
|
|
1452
|
+
// * **declared** — the lesson's own stored `evidence_level`, from the compact search payload;
|
|
1453
|
+
// * **external reuse evidence** — the confirmation count `GET /api/helpful?lesson_id=` returns,
|
|
1454
|
+
// i.e. other people's votes, not yours, which is the live signal `misakanet_me_events`
|
|
1455
|
+
// reports.
|
|
1456
|
+
//
|
|
1457
|
+
// What this panel canNOT show, stated here rather than implied: `misakanet_me_events` returns a
|
|
1458
|
+
// richer receipt (per-event types, `count`/`queries`/`sources`, its own `evidence`) but it is an
|
|
1459
|
+
// MCP tool, reachable only through the MCP endpoint with a JSON-RPC `tools/call` — and this
|
|
1460
|
+
// browser half is forbidden from making one (acceptance D4: the same endpoint files issues). The
|
|
1461
|
+
// count therefore carries the helpful-vote signal, and the regression citations and cross-node
|
|
1462
|
+
// confirmations the tool also aggregates are **not** rendered. Nothing here is guessed: no field
|
|
1463
|
+
// this endpoint does not return is displayed.
|
|
1464
|
+
//
|
|
1465
|
+
// The count itself is the same threshold `misakanet_me_events` reports: one helpful vote is a
|
|
1466
|
+
// reuse signal (E3), two or more is E4 — which is also why the rule below is stated once.
|
|
1275
1467
|
rows.push(h("div", { key: "s3", style: { marginTop: "12px", fontWeight: 600 } }, T("panel.trust")));
|
|
1276
1468
|
if (!lessons.length) {
|
|
1277
1469
|
rows.push(h("div", { key: "s3e", style: DIM }, T("panel.trust.none")));
|
|
@@ -1285,10 +1477,15 @@ var DEFAULT_MCP_URL = "https://misakanet.org/mcp";
|
|
|
1285
1477
|
var counted = confirmations === undefined ? T("panel.trust.checking")
|
|
1286
1478
|
: (confirmations === null ? T("panel.trust.unavailable")
|
|
1287
1479
|
: count(confirmations, T("panel.trust.human")) + (confirmations >= 2 ? " → E4" : ""));
|
|
1480
|
+
var declared = lesson.evidence || T("panel.trust.noLevel");
|
|
1481
|
+
var external = h("span", { style: DIM },
|
|
1482
|
+
T("panel.trust.external") + counted + (confirmations >= 2 ? " · " + T("panel.trust.e4signal") : ""));
|
|
1288
1483
|
return h("div", { key: "l" + lesson.lessonId, style: { borderTop: "1px solid " + MUTED, padding: "4px 0" } },
|
|
1289
|
-
h("
|
|
1290
|
-
|
|
1291
|
-
T("panel.trust.
|
|
1484
|
+
h("div", null,
|
|
1485
|
+
h("span", {}, lesson.title || lesson.lessonId),
|
|
1486
|
+
h("span", { style: DIM }, " " + T("panel.trust.declared") + declared +
|
|
1487
|
+
T("panel.trust.used") + lesson.count + "× · " + timeRange(lesson))),
|
|
1488
|
+
h("div", null, external));
|
|
1292
1489
|
})));
|
|
1293
1490
|
}
|
|
1294
1491
|
|
|
@@ -2120,6 +2317,11 @@ var DEFAULT_MCP_URL = "https://misakanet.org/mcp";
|
|
|
2120
2317
|
}
|
|
2121
2318
|
|
|
2122
2319
|
exports.apply = apply;
|
|
2320
|
+
// Test hooks, not surfaces: the headless render (`tests/test_dsh_plugin_panel_render.py`) has to
|
|
2321
|
+
// seed the session log exactly the way the transcript rows do, or the panel it renders is an empty
|
|
2322
|
+
// panel that proves nothing. Same constructor, same recorder, no second shape to drift.
|
|
2323
|
+
exports.__sessionLog = sessionLog;
|
|
2324
|
+
exports.__recordSearch = recordSearch;
|
|
2123
2325
|
exports.inject = inject;
|
|
2124
2326
|
exports.name = "misakanet-client";
|
|
2125
2327
|
return module.exports;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "misakanet",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.44.1",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"description": "MisakaNet failure-memory skill — evidence-rated failure lessons for AI agents. DSH bundle: registers the MCP tools as mcp__misakanet__* (misakanet_search/get_lesson/…), served by the public Streamable HTTP endpoint https://misakanet.org/mcp — live tools from an npm install, in any profile, with no local python. A profile that prefers the repo's own stdio server can override the bundle row.",
|
|
6
6
|
"icon": "icon.svg",
|
|
@@ -45,8 +45,8 @@ Do NOT use MisakaNet for:
|
|
|
45
45
|
> stdio server adds `misakanet_me_events` as a **proxy** of the hosted tool, so the reuse-evidence
|
|
46
46
|
> steps below work on either install.
|
|
47
47
|
>
|
|
48
|
-
> * **hosted** exposes
|
|
49
|
-
> * a **local stdio** install (`python3 scripts/mcp_server.py`) exposes those same
|
|
48
|
+
> * **hosted** exposes 8 tools, `misakanet_me_events` among them;
|
|
49
|
+
> * a **local stdio** install (`python3 scripts/mcp_server.py`) exposes those same 8 **plus three that
|
|
50
50
|
> only make sense on your machine** — `misakanet_submit_usage`, `misakanet_usage_status` and
|
|
51
51
|
> `misakanet_memory_context`. They read this checkout's own usage meter and `lessons/` corpus, which
|
|
52
52
|
> a hosted endpoint has nothing to answer.
|