Skip to content

feat(recall): rotate one vocabulary pool instead of permanent trigger regexes - #97

Merged
wefio merged 1 commit into
mainfrom
feat/unified-recall-pool-main
Oct 20, 2026
Merged

wefio merged 1 commit into
mainfrom
feat/unified-recall-pool-main

Conversation

@wefio

@wefio wefio commented Oct 20, 2026

Copy link
Copy Markdown
Owner

变更描述

What(改了什么):召回意图触发从"永久正则 + 独立八槽缓存"改为"词表数据 + 单一轮换池"。

Why(为什么改 / 解决什么问题):原来入口有两个寿命不同的 owner——19 条正则永久有效、不占容量、不受任何实际使用影响,加词必须写正则,写错的词永不下线;会话学到的词组另存在 8 个槽位里,与触发词毫无关系。用户要求触发词也进池轮换,"词表里加词就好了"。

Changes(关键改动点,按文件或模块列出):

  • src/core/recall-vocabulary.ts(新增):词表即数据,每条含词组、retrieve|cue、可选意图条件(前后字距、句内、句首、后接名字)。
  • src/core/recall-matcher.ts(新增):执行上述条件与拉丁词边界;排除引用、代码块、翻译与无记忆输入。
  • src/core/recall-pool.ts(新增):分段 LRU,容量 128、保护段 ≤ 64。不同用户回合命中记一次使用,第二个不同回合晋级;保护溢出降级最久未用的保护词,容量压力淘汰最久未用的非保护词;自动召回、注入内容、回答与工具输出都不更新新旧顺序;种子无豁免、不落盘回填。
  • src/core/gate.ts:从词表判定;未启用租约时保持无状态,原有结论不变。
  • src/core/session-recall.ts:会话池取代 8 槽缓存;retrieve 优先,学到的词不能降级明确回忆提问。
  • src/integration/session-task-window.ts:入口决策可由 daemon 提供,none 具有权威性,本地不复活已淘汰词;拆出 rememberAnchor / gateBudget 满足复杂度上限。
  • .pi/extensions/nmg/index.ts、opencode-plugin/index.ts:在既有 beginDisclosureTurn 中传有界归一化匹配输入(模型参数无法伪造)。
  • 文档按 docs: complete bilingual reader rollout and documentation rules #93 的新结构归位:design/design/progressive-retrieval(双语)承载词表与保留策略,hidden-features-registry/feature-register(双语)更新该行,新增双语决策 2026-10-20-unified-recall-vocabulary 及其 terms 伴随文件,并从 2026-10-15-session-recall-cues 交叉链接。

未验证项

Not verified(没验证什么):

  • 未部署、未重启共享 daemon、未改默认开关;运行中宿主是否加载本版本未核实。
  • 128 容量、64 保护段、"两个回合晋级"是工程初值,没有用自然数据标定;未做按回合过期,也未定义跨会话晋级。
  • 没有自然使用下的效果证据(漏召回减少或噪声增加)。
  • advisory 套件 verify:research / verify:chaos 未运行。
  • 一次产品套件失败已如实保留:tests/extensions/nmg/reasoning-workspace.test.ts 清理临时目录报 EPERM,该文件本改动未触碰;单跑 3/3 通过,产品重跑 1876 例(1874 通过、2 跳过、0 失败)。未复现,未标为 flaky,也未修其清理逻辑。
  • 本 PR 的 CI 是第一条真实 Linux 门禁;本分支只在 Windows 上跑过完整门禁。

完成检查项

本地质量检查

  • npm run verify:static 全绿(build / package:check / check / check:tests / check:lock / lint / format:check / docs:check / agent:context:check / complexity:gate / verify:packages / glossary:check / check:policy-words / rtm:check)
  • npm run test:product 通过
  • 完整门禁 --require-clean:runId 6a9f718f-5bb2-4d81-a699-8a4bcccd80b0,16 项阻断 pass,2 项 advisory skipped,head c0dc6961,工作树干净
  • 定向测试 78 项 pass(gate / recall-pool / session-recall / task-window / nmg index / recall-budget)
  • 未改依赖或 lockfile
  • 文档改动跑过 docs:check(729 files,0 errors,0 warnings;文档组 364,0 errors)
  • npm run complexity:gate 通过(SessionTaskWindow.prepare 曾涨到 18,已拆函数降到阈值内)
  • 未提交可再生产物

RCP(Repository Control Plane)

  • in-flight goal 已登记并 resolve:repo-development#1792471730559_000675
  • 证据目录 .nmg/verification/recall-pool-main-20261020/(clean.json、clean.log)
  • CI 全绿尚未观察:本 PR 以 draft 建立,待 nmg-rcp forge-status --pr <PR号> 读取
  • 只提交本改动拥有的文件;未吞并行 Agent 改动

CI 完成确认

  • nmg-rcp forge-status 的 All checks passed 为 SUCCESS
  • CodeFactor 通过
  • Static job 通过(含 Dependency audit)

… regexes

Recall entry had two owners with different lifetimes: nineteen permanent intent
patterns that no use could retire, and a separate eight-slot cache for phrases
learned during a session. Adding a word meant writing a regular expression.

The trigger list is now data (`recall-vocabulary.ts`): each term carries its
phrase, whether it selects retrieve or cue, and optional intent bounds (words
before/after inside a gap, sentence scope, query start, following name), so
adding or retiring a trigger is a list edit. One pool holds seed and learned
terms under the same capacity, with no seed immunity: a match in a distinct user
turn is a use, the second distinct turn promotes the term into the protected
segment, and protected overflow demotes the least recently used entry while
capacity pressure evicts the least recently used unprotected one. Automatic
recall, injected context, answers and tool output never update recency, so a term
cannot be kept alive by the system repeating it. Outside the Lab lease,
classification stays stateless against the seed vocabulary.

Pi and OpenCode pass bounded normalized matching input in the existing turn RPC
so the session pool, not a second copy of the rules, owns the entry decision;
a daemon `none` decision is authoritative and never resurrected locally.

Verification: targeted 78 tests then full `agent:verify` run
fdc02580-bd45-4ff4-8681-9eebc56ee51f, 16 blocking checks exit 0. One earlier
product run failed only in `reasoning-workspace.test.ts` cleanup with EPERM on a
temp directory (file untouched by this change): 3/3 passed standalone and the
product lane passed on rerun (1876 tests, 1874 passed, 2 skipped, 0 failed).
Advisory research/chaos suites did not run; no deployment or default activation.
@wefio
wefio marked this pull request as ready for review October 20, 2026 06:09
@wefio
wefio merged commit 59ca76e into main Oct 20, 2026
7 checks passed
@wefio
wefio deleted the feat/unified-recall-pool-main branch October 20, 2026 06:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant