fix(contribute): explain share hints with friction context - #282
Merged
Conversation
hupicake
marked this pull request as ready for review
August 5, 2026 08:44
m0Nst3r873
reviewed
Aug 5, 2026
m0Nst3r873
left a comment
Collaborator
There was a problem hiding this comment.
Reviewed the PR against #228 and it lands the goal: the hint now explains why it fired (friction reasons, only the non-zero ones) and what the session was about (promptSummary), the scoring path (computeSmartScore, CONTRIBUTE_SMART_THRESHOLD, the tool-count gate, applyPhase2Adjustments) is untouched, all four friction signals render, and the bilingual docs are in sync. I also confirmed the redaction ordering is correct — redactWithEnv() runs before the truncation, so a cut can never resurrect a raw secret.
Two non-blocking notes on the truncation in normalizePromptSummary, both on the same line. Neither leaks plaintext and neither affects the #228 outcome.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary / 摘要
The contribute decision is already driven primarily by friction signals, but the user-facing hint still explains it with tool-call volume and tool diversity. This PR carries a validated friction snapshot and a sanitized first-task summary through the existing cache path, so cache hits and cache misses both explain why the hint appeared and which task it refers to without changing scoring or trigger behavior. The hint itself is now English, following the repository's CLI output policy.
贡献提示的判定已经主要由摩擦信号驱动,但用户看到的文案仍使用工具调用量和工具多样性解释。本 PR 将经过校验的 friction 快照和脱敏后的首个任务摘要贯通现有缓存链路,使 cache hit 与 cache miss 都能准确说明提示原因和任务上下文,同时不改变评分与触发行为。提示文案使用英文,以符合仓库的 CLI 输出规范。
Example / 示例:
Type of Change / 变更类型
This fixes the mismatch between the data used to qualify a session and the explanation shown to the user. The persisted-state additions are optional and backward compatible.
本次修改修复了“session 判定依据”与“展示给用户的解释”不一致的问题。新增的持久化状态字段均为可选字段,并保持向后兼容。
Test Plan / 测试计划
Validated on PR head
5899e81f68e2cd8e171ccb67b5d65306ace7b61c, after mergingupstream/mainate9a60891b35822723b3ecdda4a667472ddbba0f4.Environment / 环境:
Results / 结果:
npm ci— exit 0; 391 packages installed, 392 audited. npm reported 11 dependency audit findings (3 moderate, 6 high, 2 critical); this PR does not change dependencies.npx tsc --noEmit— exit 0npx vitest run— exit 0; 145 test files passed, 1,924 tests passednpm run build— exit 0; tsup build succeedednpm run test:e2e— exit 0; 11 test files passed, 1 skipped; 64 tests passed, 23 skippednpx vitest run --coverage— exit 0; 1,924 tests passed.src/contribute-check.ts: 89.97% lines, 92.30% branches, 91.66% functionsgit diff --check upstream/main...HEAD— exit 0Supplemental Windows baseline / 补充 Windows 基线
Before the macOS run,
npx vitest runwas compared with the then-currentupstream/mainin the same Windows environment. Both revisions had the same 59 existing failures in the same 19 test files, caused by POSIX path, Linux process, permission, symlink, and colon-in-filename assumptions. The branch added five passing tests and no new failures.在 macOS 验证前,曾在同一 Windows 环境对比当时的
upstream/main与本分支。两个版本均在相同的 19 个测试文件中出现相同的 59 个既有失败,来源为 POSIX 路径、Linux 进程、权限、符号链接和文件名冒号等平台假设;本分支新增 5 个通过测试,没有新增失败。upstream/main: 1,832 passed, 59 failedThe all-green macOS run above is the current authoritative result. / 以上全绿的 macOS 结果为当前权威验证结果。
Regression coverage includes / 回归覆盖包括:
events.jsonl;不存在events.jsonl时的完整缓存命中;The raw token is absent from both Hook output and persisted contribute state. 原始 Token 不会出现在 Hook 输出或持久化的 contribute state 中。
Related Issues / 关联 Issue
Closes #228.
Notes for Reviewers / 审核说明
Cache compatibility / 缓存兼容
A fresh cache hit requires
smartScore,toolCount, a validfrictionsnapshot, and a freshlastEvaluatedvalue.promptSummaryis intentionally optional so tools without one do not cause permanent cache misses.Legacy state without friction and malformed friction both fail closed and re-scan
events.jsonl.uniqueToolsremains in state for backward compatibility but is no longer required to render the hint.新缓存命中要求存在
smartScore、toolCount、合法的friction快照,以及未过期的lastEvaluated。promptSummary保持可选,避免无法提供摘要的工具永久 cache miss。缺少 friction 的旧状态和畸形 friction 都会 fail closed 并重新扫描
events.jsonl。uniqueTools继续保留以兼容旧状态,但不再是生成提示的必要字段。Prompt safety / 摘要安全
Before persistence or display, the first task summary is scrubbed with
redactWithEnv(), stripped of control characters, flattened to one line, whitespace-normalized, trimmed, and limited to 160 UTF-16 code units. Truncated summaries end with an ellipsis and never retain a dangling high surrogate. The writer normalizes it again as defense in depth.首个任务摘要在持久化或展示前会经过
redactWithEnv()脱敏、控制字符清理、单行化、空白归一、首尾裁剪和 160 个 UTF-16 code unit 限制;发生截断时会附加省略号,并移除边界处孤立的高代理项。状态写入时会再次标准化,作为纵深防御。Intentionally unchanged / 明确保留
computeSmartScore()and all friction weightsCONTRIBUTE_SMART_THRESHOLDand the tool-count hard gatePhase 2 score-adjustment logic in
applyPhase2Adjustments()hint deduplication, re-read-before-write concurrency protection, and Stop-hook JSON protocol
computeSmartScore()与所有摩擦权重CONTRIBUTE_SMART_THRESHOLD与工具调用数 hard gateapplyPhase2Adjustments()中的 Phase 2 分数调整逻辑提示去重、写前重读并发保护和 Stop hook JSON 协议
One pre-existing behavior remains out of scope: Phase 2 score adjustments are re-applied to cached scores on cache hits.
一个不在本 PR 范围内的预存行为是:cache hit 时会对缓存分数再次应用 Phase 2 调整。