Skip to content

fix: filter stale artifacts from navigation truth source (#1067)#1068

Open
kaverjody wants to merge 1 commit into
zts212653:mainfrom
kaverjody:fix/stale-artifact-navigation-1067
Open

fix: filter stale artifacts from navigation truth source (#1067)#1068
kaverjody wants to merge 1 commit into
zts212653:mainfrom
kaverjody:fix/stale-artifact-navigation-1067

Conversation

@kaverjody

Copy link
Copy Markdown

Problem

The [导航] block injected stale file references (e.g. deploy-irb.py) into cat prompts, even after those files were deleted. This caused cats to be misdirected to read non-existent files, producing hallucinated cross-thread responses ("串台").

Root Cause

The artifact ledger in threadMemory.recentArtifacts uses append+dedup strategy with no TTL and no file existence check. Once a file path entered the ledger, it persisted forever.

Fix

Add filterStaleArtifacts() that checks file existence before ranking.

Applied in two places:

  1. Before rankArtifactSources() for navigation header [真相源]
  2. In briefingContext for recentArtifacts passed to cats

PR-type artifacts are always kept (they do not map to filesystem).
Fail-open: if existence check throws, artifact is kept.

Closes #1067

)

Problem:
The [导航] block injected stale file references (e.g. deploy-irb.py)
into cat prompts, even after those files were deleted. This caused cats
to be misdirected to read non-existent files, producing hallucinated
cross-thread responses ('串台').

Root cause:
The artifact ledger in threadMemory.recentArtifacts uses append+dedup
strategy with no TTL and no file existence check. Once a file path
entered the ledger, it persisted forever.

Fix:
Add filterStaleArtifacts() that checks file existence before ranking.
Applied in two places:
1. Before rankArtifactSources() for navigation header [真相源]
2. In briefingContext for recentArtifacts passed to cats

PR-type artifacts are always kept (they don't map to filesystem).
Fail-open: if existence check throws, artifact is kept.

Closes zts212653#1067
@kaverjody kaverjody requested a review from zts212653 as a code owner July 2, 2026 10:02
@zts212653 zts212653 added bug Something isn't working triaged Maintainer reviewed, replied, and made an initial triage decision accepted Maintainer accepted: ready for implementation/merge labels Jul 2, 2026
@zts212653

Copy link
Copy Markdown
Owner

👋 @kaverjody — 30 分钟内又提一个 PR 覆盖你自己找的 #1067,效率漂亮 ✅

Triage verdict: ✅ Accepted PR

Direction 已 accepted (追 #1067 accept)。code sketch 看着合理:

  • filterStaleArtifacts() 新工具函数(artifact-tracking.ts 25+/0)
  • 两处 call site(route-helpers.ts 11+/-5):navigation [真相源] 前 + briefingContext
  • PR-type artifacts 保留(对 — 它们不映射到文件系统)
  • fail-open on existence check throw(对 — 拿不到 stat 时不能盲杀 artifact,避免误判)

Blockers

#1064 一样两条

  1. CI action_required — 你还是 FIRST_TIME_CONTRIBUTOR,workflow 需 maintainer 手动 approve 才跑(等 fix: add UUID guard for --resume in ClaudeAgentService #1064 合了你会自动升 CONTRIBUTOR,之后就自动跑了)。这条 maintainer 侧处理,你不用改
  2. mergeStateStatus=BLOCKED — 目前是 review-required + CI 未跑双阻塞,approve CI 后就剩 review-required

Pre-review scope 预告

Review 时会 focus:

  1. filterStaleArtifacts() 的 async 并发:并行 stat N 个 artifact 会不会 EMFILE?(本地 dev N 通常小,但长运行 daemon + 大 thread 需考虑)
  2. fail-open 边界:throw 时保留是对的,但 filesystem transient error vs 真被删掉 两种情况能区分吗?(如果不能,保留是最保守选择 ✓)
  3. cache invalidation:filter 结果是否有 short-lived cache?如果每次 nav prompt 都 re-stat 会不会成为热路径 latency?
  4. PR-type detection 的 heuristic:怎么判定"这是 PR artifact 不是 file"?path pattern? magic prefix?
  5. test coverage:新 function 是否有 unit test 覆盖 (a) 存在的 file (b) 已删的 file (c) transient error (d) PR artifact 保留

另外 — Option 2 邀请仍然 open

你要考虑 #1063 那条 architectural 邀请吗?完全独立于 #1068,不冲突。

Labels: bug + triaged + accepted。等 maintainer approve CI + review。

[宪宪/claude-opus-4-7🐾]

@kaverjody

Copy link
Copy Markdown
Author

验证结果

重启后在 thread_mqj6o8eqlqt1yrdm("其他事务")thread 验证,咖啡(cat-r05t3v8t)确认修复生效。

对比数据

轮次 时间 (UTC) 真相源 状态
修复前 Jul 2 09:10~09:14 deploy-irb.py ❌ 串台(已删除文件被注入)
修复后 Jul 3 02:53 未定位 ✅ 正确(无 stale artifact)
修复后 Jul 3 04:29 未定位 ✅ 正确(跨 thread 验证)

验证方法

  1. 向"其他事务" thread 的咖啡发跨 thread 消息,询问当前 [导航] 块的 真相源 字段
  2. 咖啡回复确认:本轮真相源 = 未定位(不再是之前串台的 deploy-irb.py
  3. 同时检查 Redis thread memory 确认 stale artifacts 仍存在(/tmp/deploy-irb.py),但 filterStaleArtifacts 正确过滤掉了

结论

  • filterStaleArtifacts() 正确过滤不存在的文件
  • ✅ PR 类型 artifact 不受影响(不做文件检查)
  • ✅ 导航真相源不再指向已删除文件

验证者:孟加拉猫/小捷 (bengal-o6js) + 咖啡 (cat-r05t3v8t) 🐾

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

accepted Maintainer accepted: ready for implementation/merge bug Something isn't working triaged Maintainer reviewed, replied, and made an initial triage decision

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: 导航真相源注入 stale artifact 污染 — 已删除文件持续占据 [导航] 块

2 participants