pi-think-anchor 1.0.28 → 1.0.30
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.en.md +4 -48
- package/README.md +20 -6
- package/index.ts +2 -7
- package/package.json +10 -3
package/README.en.md
CHANGED
|
@@ -1,53 +1,9 @@
|
|
|
1
1
|
# pi-think-anchor
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Thinking-focus monitor with graded nudges, driven by a reproducible ratio test.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
**English documentation:** [open the English section](README.md#english) · **中文文档:** [中文](README.md#zh)
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
pi install npm:pi-think-anchor
|
|
9
|
-
```
|
|
7
|
+
pi install npm:pi-think-anchor
|
|
10
8
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
Config file `~/.pi/think-anchor.json` (optional; defaults apply, invalid JSON falls back):
|
|
14
|
-
|
|
15
|
-
| Key | Default | Description |
|
|
16
|
-
| --- | --- | --- |
|
|
17
|
-
| `enabled` | `true` | Master switch |
|
|
18
|
-
| `score.minHits` | `3` | Fewer hits in a turn: no scoring, no intervention |
|
|
19
|
-
| `score.spec` | `1.2` | Focused threshold |
|
|
20
|
-
| `score.react` | `0.5` | Reactive threshold |
|
|
21
|
-
| `score.alpha` | `1` | Alpha smoothing |
|
|
22
|
-
| `windowSize` | `5` | Window size in messages |
|
|
23
|
-
| `weights.beta` | `0.4` | Neutral-word weight in the numerator |
|
|
24
|
-
| `weights.eps` | `0.5` | Denominator floor |
|
|
25
|
-
| `intervention.l1CooldownMin` | `10` | L1 cooldown (minutes) |
|
|
26
|
-
| `intervention.l2CooldownMin` | `15` | L2 cooldown (minutes) |
|
|
27
|
-
| `intervention.maxL2` | `2` | Max L2 per session |
|
|
28
|
-
| `lexicon.positive/negative/neutral` | built-in Chinese lexicon (28 focus / 18 drift) | Lexicon override |
|
|
29
|
-
| `bands.spec/react` | `1.2 / 0.5` | Legacy keys (used when `score` is absent) |
|
|
30
|
-
|
|
31
|
-
Also: `THINK_ANCHOR=0` hard off; log `~/.pi/think-anchor.jsonl` (1 MiB truncation, tail-preserving).
|
|
32
|
-
|
|
33
|
-
## Commands
|
|
34
|
-
|
|
35
|
-
| Command | Purpose |
|
|
36
|
-
| --- | --- |
|
|
37
|
-
| `/think-anchor` | Current band, hits, drift share, last intervention result |
|
|
38
|
-
| `/think-anchor stats` | Version, band distribution, actions, effectiveness, log size |
|
|
39
|
-
|
|
40
|
-
## What it does (source facts)
|
|
41
|
-
|
|
42
|
-
- `turn_end`: reads assistant thinking -> fingerprint (pos/neg/neu) -> sliding window -> band; when hits < `minHits` it only advances the window.
|
|
43
|
-
- State machine `healthy -> warning -> critical`; L1/L2 nudges are injected as `nextTurn` trailing messages.
|
|
44
|
-
- No escalation: when the previous `eff >= 0`, L2 degrades to L1.
|
|
45
|
-
- `session_start`: resets state, keeping only the last 3 samples and pending (cross-session settlement).
|
|
46
|
-
|
|
47
|
-
## Credits
|
|
48
|
-
|
|
49
|
-
Distilled from the DSH plugin [`dsh-anchored-monitor`](https://dsh-plugin.org/zh/plugins/aik358/dsh-anchored-monitor) 0.3.1: the mechanism is upstream, the code is not (turn-level, no separate process).
|
|
50
|
-
|
|
51
|
-
## License
|
|
52
|
-
|
|
53
|
-
MIT
|
|
9
|
+
Source: https://github.com/op15066212/pi-plugins-publish
|
package/README.md
CHANGED
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
|
|
8
8
|
# pi-think-anchor
|
|
9
9
|
|
|
10
|
+
> 适用 pi ≥ 0.74 · Node ≥ 20 · MIT · 无运行时依赖(仅 peer: @earendil-works/pi-coding-agent)
|
|
11
|
+
|
|
10
12
|
思维链锚定监测:读取 thinking 的词频指纹,判定专注 / 过渡 / 发散,发散时分级提示。
|
|
11
13
|
|
|
12
14
|
## 快速事实
|
|
@@ -14,7 +16,7 @@
|
|
|
14
16
|
| 项 | 说明 |
|
|
15
17
|
| --- | --- |
|
|
16
18
|
| 配置文件 | ~/.pi/think-anchor.json(可省略) |
|
|
17
|
-
| 命令行 | /think-anchor [on
|
|
19
|
+
| 命令行 | /think-anchor [on, off, reset, stats] |
|
|
18
20
|
| 调用方式 | **全自动**:turn_end 评估 + 条件注入。on/off 只改当前会话内存(不写文件),重启后回到配置文件的值 |
|
|
19
21
|
|
|
20
22
|
## 安装
|
|
@@ -42,7 +44,7 @@ pi install npm:pi-think-anchor
|
|
|
42
44
|
| `intervention.maxL2` | `2` | 每会话 L2 上限 |
|
|
43
45
|
| `lexicon.positive/negative/neutral` | 专注 28 词 / 发散 18 词 / 中性 **默认空** | 词表覆盖 |
|
|
44
46
|
|
|
45
|
-
其他:日志 `~/.pi/think-anchor.jsonl`(1 MiB
|
|
47
|
+
其他:日志 `~/.pi/think-anchor.jsonl`(1 MiB 截断,保留尾部整行);日志里的 `ratio` 是**未平滑**的原始比率,而判定用的是 α 平滑后的比率(`(pos + beta·neu + alpha) / (neg + eps + alpha)`)——两者数值不同,别拿日志 ratio 当判定依据。
|
|
46
48
|
**词表覆盖规则(源码事实)**
|
|
47
49
|
|
|
48
50
|
- 三个键独立覆盖:只写想改的那个,其余保留默认(`lexicon` 按子键浅合并)。
|
|
@@ -139,7 +141,13 @@ pi install npm:pi-think-anchor
|
|
|
139
141
|
## 作用(源码事实)
|
|
140
142
|
|
|
141
143
|
- `turn_end`:取 assistant 消息 thinking → 指纹(pos/neg/neu)→ 滑窗聚合 → 判波段;本轮命中 < `minHits` 时只推进窗口。
|
|
142
|
-
- 状态机 `healthy → warning → critical`;L1/L2 干预以 `nextTurn`
|
|
144
|
+
- 状态机 `healthy → warning → critical`;L1/L2 干预以 `nextTurn` 尾部消息回灌(`display: false`),文本里带当前比率、命中量与触发阈值(如「比率 0.48 · 命中 22;react<0.5」)——让模型看到依据,而不是只收到一句指令。
|
|
145
|
+
**注入样例(示意,字段可能随版本增删)**
|
|
146
|
+
|
|
147
|
+
```text
|
|
148
|
+
think-anchor 信号(词频启发式,非判据):连续偏离。动作:停止探索,立即执行一个具体动作。(比率 0.48 · 命中 22;L2 1/2)
|
|
149
|
+
```
|
|
150
|
+
|
|
143
151
|
- 无效不升级:上次 `eff >= 0` 时 L2 降为 L1。
|
|
144
152
|
- `session_start`:重置状态机,仅保留最近 3 条与 pending(跨会话结算)。
|
|
145
153
|
|
|
@@ -194,7 +202,7 @@ Chain-of-thought drift monitor: reads a word-frequency fingerprint from thinking
|
|
|
194
202
|
| Item | Description |
|
|
195
203
|
| --- | --- |
|
|
196
204
|
| Config file | ~/.pi/think-anchor.json (optional) |
|
|
197
|
-
| Commands | /think-anchor [on
|
|
205
|
+
| Commands | /think-anchor [on, off, reset, stats] |
|
|
198
206
|
| Automation | **Fully automatic**: evaluated on turn_end, injects only when needed. on/off changes in-memory state only (not written to disk); a restart falls back to the config file |
|
|
199
207
|
|
|
200
208
|
Full config (all keys and defaults):
|
|
@@ -224,7 +232,7 @@ Config file `~/.pi/think-anchor.json` (optional; defaults apply, invalid JSON fa
|
|
|
224
232
|
| `intervention.maxL2` | `2` | Max L2 per session |
|
|
225
233
|
| `lexicon.positive/negative/neutral` | 28 focus / 18 drift / neutral **empty by default** | Lexicon override |
|
|
226
234
|
|
|
227
|
-
Also: log `~/.pi/think-anchor.jsonl` (1 MiB truncation, tail-preserving).
|
|
235
|
+
Also: log `~/.pi/think-anchor.jsonl` (1 MiB truncation, tail-preserving). The `ratio` in the log is the **unsmoothed** raw ratio; classification uses the `alpha`-smoothed ratio (`(pos + beta·neu + alpha) / (neg + eps + alpha)`). They differ — do not use the logged ratio as the decision value.
|
|
228
236
|
**Lexicon override rules (from source)**
|
|
229
237
|
|
|
230
238
|
- Keys merge independently: write only what you change; the rest keep defaults (`lexicon` merges per sub-key).
|
|
@@ -321,7 +329,13 @@ Full config (copy-paste ready, includes the default lexicon):
|
|
|
321
329
|
## What it does (source facts)
|
|
322
330
|
|
|
323
331
|
- `turn_end`: reads assistant thinking -> fingerprint (pos/neg/neu) -> sliding window -> band; when hits < `minHits` it only advances the window.
|
|
324
|
-
- State machine `healthy -> warning -> critical`; L1/L2 nudges are
|
|
332
|
+
- State machine `healthy -> warning -> critical`; L1/L2 nudges are fed back as `nextTurn` trailing messages (`display: false`), carrying the current ratio, hit count and the triggering threshold (e.g. ratio 0.48, 22 hits, react<0.5) so the model sees the evidence, not just an order.
|
|
333
|
+
**Sample injection (illustrative; fields may change between versions)**
|
|
334
|
+
|
|
335
|
+
```text
|
|
336
|
+
think-anchor signal (heuristic, not a verdict): sustained drift. Action: stop exploring, execute one concrete step. (ratio 0.48 · 22 hits; L2 1/2)
|
|
337
|
+
```
|
|
338
|
+
|
|
325
339
|
- No escalation: when the previous `eff >= 0`, L2 degrades to L1.
|
|
326
340
|
- `session_start`: resets state, keeping only the last 3 samples and pending (cross-session settlement).
|
|
327
341
|
|
package/index.ts
CHANGED
|
@@ -89,17 +89,12 @@ export function fingerprint(text: string, lex: { positive: string[]; negative: s
|
|
|
89
89
|
};
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
+
|
|
92
93
|
/** 加权比率:专注度代理指标 */
|
|
93
94
|
export function ratioOf(pos: number, neg: number, neu: number, w: { beta: number; eps: number } = DEF_CFG.weights): number {
|
|
94
95
|
return (pos + w.beta * neu) / (neg + w.eps);
|
|
95
96
|
}
|
|
96
97
|
|
|
97
|
-
export function bandOf(ratio: number, t: { spec: number; react: number } = DEF_CFG.score): "spec" | "mixed" | "react" {
|
|
98
|
-
if (ratio >= t.spec) return "spec";
|
|
99
|
-
if (ratio >= t.react) return "mixed";
|
|
100
|
-
return "react";
|
|
101
|
-
}
|
|
102
|
-
|
|
103
98
|
/**
|
|
104
99
|
* v2.1 判据:证据门槛 + α 平滑的专注/发散比。
|
|
105
100
|
* 回放 2069 条可评分日志:旧判据 react 占 18.3%(其中 57% 是命中 <3 的长而散);
|
|
@@ -328,7 +323,7 @@ export default function thinkAnchor(pi: ExtensionAPI): void {
|
|
|
328
323
|
} else {
|
|
329
324
|
// 被冷却/上限挡下:记 blocked,避免与「无需动作」混淆(实测 583 次 want=L2 只有 55 次真发)
|
|
330
325
|
st.phase = prevPhase;
|
|
331
|
-
|
|
326
|
+
acted = st.autoMuted ? "muted-" + d.level : "blocked-" + d.level;
|
|
332
327
|
}
|
|
333
328
|
if (band === "spec" && st.phase === "healthy") st.l2Tried = 0; // 恢复后重置 L2 计数
|
|
334
329
|
// v3 效果闭环:干预后第 3 轮结算(pre = 干预前最近 3 轮 ratio 均值)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-think-anchor",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.30",
|
|
4
4
|
"description": "Monitors thinking focus drift and nudges the model back on track.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -8,7 +8,11 @@
|
|
|
8
8
|
"pi",
|
|
9
9
|
"pi-extension",
|
|
10
10
|
"pi-coding-agent",
|
|
11
|
-
"pi-package"
|
|
11
|
+
"pi-package",
|
|
12
|
+
"chain-of-thought",
|
|
13
|
+
"focus",
|
|
14
|
+
"monitoring",
|
|
15
|
+
"drift"
|
|
12
16
|
],
|
|
13
17
|
"pi": {
|
|
14
18
|
"extensions": [
|
|
@@ -25,7 +29,7 @@
|
|
|
25
29
|
"@earendil-works/pi-coding-agent": "*"
|
|
26
30
|
},
|
|
27
31
|
"author": "15066212pp",
|
|
28
|
-
"homepage": "https://github.com/op15066212/pi-plugins-publish/tree/main/pi-think-anchor",
|
|
32
|
+
"homepage": "https://github.com/op15066212/pi-plugins-publish/tree/main/pi-think-anchor#readme",
|
|
29
33
|
"bugs": {
|
|
30
34
|
"url": "https://github.com/op15066212/pi-plugins-publish/issues"
|
|
31
35
|
},
|
|
@@ -36,5 +40,8 @@
|
|
|
36
40
|
},
|
|
37
41
|
"scripts": {
|
|
38
42
|
"prepublishOnly": "node ../publish-check.mjs"
|
|
43
|
+
},
|
|
44
|
+
"engines": {
|
|
45
|
+
"node": ">=20"
|
|
39
46
|
}
|
|
40
47
|
}
|