-
Notifications
You must be signed in to change notification settings - Fork 177
feat: 仓库健康事实、可安装资产识别与批量导入提取 #369
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
Show all changes
1093 commits
Select commit
Hold shift + click to select a range
ff5242c
fix: preserve skipped vector metadata
d21d496
fix: preserve diagnostic logs on refresh failure
3ee6ca9
Merge pull request #298 from AmintaCCCP/refactor/settings-hooks
AmintaCCCP 557f3b6
refactor: modularize the app store behind one persistence shell
manus 30d580d
fix: guard backend secret session storage access
manus ef62e73
Merge pull request #299 from AmintaCCCP/refactor/modularize-store
AmintaCCCP 38d8912
perf: typed selectors and extract application lifecycle
b4e85f1
fix: keep fork workflow expansion updates pure
3cc8f64
fix: harden async feature lifecycle updates
c8c8599
fix: guard stale discovery and fork async state
a6a6bd2
fix: isolate async work by auth session generation
982b2bb
fix: harden release and fork async workflows
0a2d1af
Merge pull request #300 from AmintaCCCP/perf/selectors-lifecycle
AmintaCCCP b168eb1
chore: enforce frontend boundaries and publish architecture ADR
AmintaCCCP 1423181
docs(adr): soften brittle line-number ref in 0001 layering ADR
AmintaCCCP 4996ad0
fix: close boundary bypasses from CodeRabbit review
AmintaCCCP 4a5f32a
fix: detect side-effect imports in boundary scanner
AmintaCCCP ba05d9c
fix: apply CodeRabbit auto-fixes
coderabbitai[bot] ca4e638
Merge pull request #301 from AmintaCCCP/chore/enforce-boundaries-adr
AmintaCCCP 5ac6e9c
Bump version from 0.7.6 to 0.7.7
AmintaCCCP 1a6b0db
Bump version from 0.7.6 to 0.7.7
AmintaCCCP 613021e
docs: add v0.7.7 release info and changelog
AmintaCCCP bcb7b9b
feat: add repository release download sheet
f9f9e72
fix: harden release sheet downloads
2df597c
fix: preserve release pagination and backend downloads
66e894d
fix: prevent sheet click-through and action overflow
92de1df
fix: isolate release sheet events and collapse actions
7e8b487
fix: protect release fallback outside dismissal
4cd41c8
Merge pull request #302 from AmintaCCCP/feat/repository-release-sheet
AmintaCCCP f64bd18
feat(repository-chat): add pinned source QA sessions
fa213ce
fix(repository-chat): address audit findings
be5294d
fix(repository-chat): harden retry and storage fallback
b2d2617
fix(repository-chat): preserve history across retries
92a33db
fix(repository-chat): verify storage fallback migration
05fc737
fix(repository-chat): reject failed fallback writes
d52fe54
fix(repository-chat): harden evidence agent and sorting
a02f313
feat(repository-chat): add framework evidence timeline
eb9dcc6
fix(repository-chat): prioritize verified outcomes
e84a1f4
feat(repository-chat): present execution as task cards
894d20e
fix(repository-chat): harden evidence-bound outcomes
e9cf054
fix(repository-chat): prioritize bounded markdown evidence
94f9bcb
fix(repository-chat): harden turn lifecycle and evidence loop
461c392
Merge pull request #303 from AmintaCCCP/feat/repository-chat-qa
AmintaCCCP 86eb09e
fix: stabilize repository edit modal
92af782
fix: reset modal scroll state on close
65c7fef
Merge pull request #305 from AmintaCCCP/fix/issue-304-edit-modal
AmintaCCCP e79fe27
feat(chat): add evidence-driven repository agent
9bd2ace
fix(chat): address evidence agent review feedback
cffe875
fix(chat): harden evidence gate and citations
6aa58df
fix(chat): simplify evidence loop and timeline
bab5686
fix(chat): converge evidence checks and ordering
c6afeb6
fix(chat): harden citations and event persistence
51e17be
feat(chat): plan progressive evidence retrieval
38d9d53
feat(chat): expand evidence retrieval controls
013ec21
fix(chat): stop research when questions are answerable
9f56d65
Merge pull request #306 from AmintaCCCP/feat/evidence-driven-reposito…
AmintaCCCP 1f56b70
Update package.json
AmintaCCCP 40a2ad2
Bump version from 0.7.7 to 0.7.8
AmintaCCCP c69ff81
upload screenshot
AmintaCCCP 3dbe405
docs: add v0.7.8 release notes
6b08891
fix(ci): stabilize multi-arch Docker publishing
d013189
Merge pull request #307 from AmintaCCCP/fix/reliable-multiarch-fronte…
AmintaCCCP cc99066
feat(docker): add optional full-stack image
05b55d9
ci: validate full-stack image on pull requests
9ac7938
docs: add Chinese full-stack Docker guide
4cae972
fix(ci): align image releases and harden full-stack deployment
fdaf6ba
fix(release): standardize image roles and version contract
c691056
fix(docs): harden full-stack migration guidance
0c43663
fix(docs): preserve credentials during full-stack migration
8f3f7d4
fix(release): block invalid desktop releases
1cf08e3
Merge pull request #308 from AmintaCCCP/feat/add-optional-fullstack-i…
AmintaCCCP b2e9b45
fix(store): keep active searchResults during background sync (Fixes #…
AmintaCCCP 18a0c2c
Fix CodeRabbit issues in PR #310
coderabbitai[bot] 0faba3f
fix(store): converge repos hash on push to match backend projection (…
AmintaCCCP 74b9323
fix(sync): unify push/pull repo fingerprints on one client-only field…
AmintaCCCP c526aea
fix(store): keep searchResults through addRepository; add pull-loop r…
AmintaCCCP c5b41f2
Merge pull request #310 from AmintaCCCP/fix/304-edit-modal-search-sync
AmintaCCCP c465dba
feat(chat): stream answers, task depth presets, citation badges & col…
AmintaCCCP 711c8c2
fix(ai): add streamed flag to debug-log http details type
AmintaCCCP de00fee
test(repository-chat): replace localStorage with a throwing stub in f…
AmintaCCCP 1df68b0
fix(chat): address CodeRabbit review round 1
AmintaCCCP 8c44a78
fix(chat): address CodeRabbit review round 2 (incl. outside-diff find…
AmintaCCCP d012215
fix(chat): address CodeRabbit review round 3
AmintaCCCP 651fa9e
fix(chat): stop discarding correct answers over citation format; unlo…
AmintaCCCP 5af1618
fix(chat): readable tables, right-aligned message actions, highlighte…
AmintaCCCP 4a6ad9c
fix(chat): citation parsing tolerance, pruning fallback, repair deadline
AmintaCCCP 525433b
fix(chat): canonicalize bare root-file citations; enforce README-firs…
AmintaCCCP cf56dbf
fix(chat): round-6 review — secure endpoints, docs-first intent, prun…
AmintaCCCP 756f59a
fix(chat): round-7 review — preserve cited sub-ranges, sniff headerle…
AmintaCCCP 2e1f0de
fix(ai): accept bare CR as an SSE line separator in headerless sniffing
AmintaCCCP 4183943
fix(ai): accept bare CR line separators in consumeSseStream
AmintaCCCP fcf395d
fix(ai): round-10 review — require a valid SSE frame before sniffing;…
AmintaCCCP dbab8cb
Merge pull request #311 from AmintaCCCP/feat/repository-chat-streamin…
AmintaCCCP bad239a
fix(ui): keep header above search bar; lock root scroller under modal…
AmintaCCCP b242a35
Merge pull request #312 from AmintaCCCP/fix/header-layering-modal-scr…
AmintaCCCP f69a0a2
feat(ui): adopt Simple Icons brand glyphs for platform indicators
AmintaCCCP 373aff0
feat(release): per-asset platform badge and updated time in release a…
AmintaCCCP b90809b
feat(repo): prefer deterministic platform detection over AI-only tags
AmintaCCCP b2dbcae
fix(repo): scope platform signals to the repo; localize asset time to zh
AmintaCCCP d3685c6
fix(ui): keep readable text color on hovered checked release source row
AmintaCCCP 3f1c0da
fix(release): localize the release header relative time to zh
AmintaCCCP 9313ff9
Merge pull request #313 from AmintaCCCP/feat/platform-brand-icons-and…
AmintaCCCP 5d06cdc
feat(chat): add release/issue meta sources and an optional native too…
AmintaCCCP 2fb747a
fix(chat): harden meta sources and tool loop after self-audit
AmintaCCCP b42160f
fix(chat): address CodeRabbit round-1 review findings
AmintaCCCP 73eb5ab
fix(chat): resolve remaining CodeRabbit review threads
AmintaCCCP aee2793
fix(chat): block boolean operators and grouped/negated qualifiers in …
AmintaCCCP bdcf48b
fix(chat): address CodeRabbit round-3 review findings
AmintaCCCP 6cc03bc
Merge pull request #314 from AmintaCCCP/feat/chat-meta-sources-and-to…
AmintaCCCP 591660a
Bump version from 0.7.8 to 0.7.9
AmintaCCCP f78d8f3
docs: add 0.7.9 release info to version-info.xml
AmintaCCCP 9bb7aa8
ci(docker): bump docker actions to Node 24 releases
AmintaCCCP f49a5a3
fix(release): unify asset platform icons between release page and rep…
AmintaCCCP ad11b2b
Merge pull request #315 from AmintaCCCP/fix/docker-node24-and-asset-i…
AmintaCCCP 8a1c374
update readme
AmintaCCCP 26ca2ae
update readme
AmintaCCCP 8f40e94
Update demo video link in README_zh.md
AmintaCCCP cf62d6a
update readme
AmintaCCCP 94de233
Update README_zh.md
AmintaCCCP ef4d6c7
feat(settings): add routeMode for local GitHub egress preference
AmintaCCCP 7100ae0
fix(review): address CodeRabbit feedback on PR #323
AmintaCCCP 74ee170
Merge pull request #323 from AmintaCCCP/feat/route-mode-local-egress
AmintaCCCP a67938e
fix(release): allow RPC retry, backfill empty changelog, align time/a…
AmintaCCCP 0d9b4af
fix(review): address CodeRabbit feedback on PR #324
AmintaCCCP 00a92f7
fix(review): clear stale RPC success state, widen EN action area
AmintaCCCP 23cc9df
fix(review): version-stamp source/body links, cover updatedAt key change
AmintaCCCP 6aaf1e3
Merge pull request #324 from AmintaCCCP/fix/release-assets-rpc-retry-…
AmintaCCCP 1551e52
refactor(frontend-layering): ban update/translate services in View, m…
AmintaCCCP 04098c3
Merge pull request #325 from AmintaCCCP/chore/frontend-layering-updat…
AmintaCCCP 9fb7f41
refactor(gists): GistEditorModal 改从 useGistActions 重导出引类型
AmintaCCCP eaaeb53
feat(gists): useGistActions 扩展 analyzeOne/unstarGist/deleteGist/fetch…
AmintaCCCP 9f8cd72
feat(discovery): 新建 useDiscoveryRepoActions + discoveryRepoPatches + 单测
AmintaCCCP 41fba70
feat(readme): 新建 src/hooks/useReadmeFetch + pickReadmeCandidate + 单测
AmintaCCCP 0218fea
feat(release): 新建 src/hooks/useReleaseArtifactActions + 单测;useReposit…
AmintaCCCP 6f2fbc5
feat(releases): useReleaseTimelineActions 新增 syncWatchedSources + 单测
AmintaCCCP 60e4e1b
feat(settings): 新建 useBackendAvailability
AmintaCCCP 13f34d9
feat(repositories): 新建 useSearchActions + 纯函数 + 单测
AmintaCCCP 930d173
refactor(gists): GistCard 分析/收藏/删除动作切至 useGistActions
AmintaCCCP 04bb74c
refactor(gists): GistDetailModal 大文件按需拉取改经 useGistActions.fetchGistFi…
AmintaCCCP 83663a5
refactor(settings): SettingsPanel 后端可用性改经 useBackendAvailability
AmintaCCCP 78be4f6
refactor(repositories): RepositoryEditModal 复用 useCategorySyncActions
AmintaCCCP dd2a731
refactor(releases): WatchCustomReleaseSyncPanel 同步动作切至 useReleaseTime…
AmintaCCCP f3df459
refactor(discovery): SubscriptionRepoCard star/unstar/分析动作切至 useDisco…
AmintaCCCP 6eb9802
refactor(release): ReleaseCard RPC 发送与 AI 总结切至 useReleaseArtifactActions
AmintaCCCP 056d38d
refactor(readme): ReadmeModal 抓取两级来源切至 useReadmeFetch,变体选择提纯 pickRead…
AmintaCCCP 5cae88d
refactor(repositories): SearchBar AI/向量/关键词搜索与星标同步切至 useSearchActions…
AmintaCCCP 9d748f7
chore(boundaries): 删除组件边界 allowlist 机制(10 项迁移完成,机制整体删除而非置空)
AmintaCCCP c2fc648
fix(review): 审计修复
AmintaCCCP 004130c
fix(review): CodeRabbit 首轮审计修复
AmintaCCCP 8d739e9
fix(review): CodeRabbit 二轮审计修复——useReleaseArtifactActions.reset 先取消进行…
AmintaCCCP fc4ddde
fix(review): CodeRabbit 三轮审计修复——GistView 移除 onDeleted 中的重复 store 删除调用…
AmintaCCCP e84ba8d
fix(review): 外部审计报告修复
AmintaCCCP a4844af
test(review): 补齐外部审计 T1-T4 覆盖缺口
AmintaCCCP e184cd3
fix(review): CodeRabbit 五轮审计修复
AmintaCCCP ed8d70e
Merge pull request #326 from AmintaCCCP/refactor/frontend-layering-al…
AmintaCCCP 2239ee8
fix(security): 升级依赖组件修复 31 项安全扫描漏洞
AmintaCCCP 19689cf
Merge pull request #328 from AmintaCCCP/fix/security-dependency-upgrades
AmintaCCCP 22e4637
fix(ui): ReleaseCard 时间列改 min-w 自适应,资产已更新徽标不再挤压换行
AmintaCCCP 2480a09
Merge pull request #329 from AmintaCCCP/fix/release-card-badge-wrap
AmintaCCCP 44eaeda
feat: add backend login recovery flow
0f582d2
fix(auth): 落实审计与 CodeRabbit 意见,加固后端登录安全与流程健壮性
AmintaCCCP ebbd768
ci(docker): fullstack PR 校验防超时——fork PR 冷构建超时 30 分钟的修复
AmintaCCCP e042361
fix(auth): 修复 CodeRabbit 第二轮意见——loopback 误判与恢复令牌错误分类
AmintaCCCP 06ebcc2
fix(auth): 区分后端代理凭据 401 与 GitHub 401(CodeRabbit 第三轮)
AmintaCCCP d24cfc3
fix(ui): 桌面端后端 URL 不再预填 file://,改留空由占位符引导
AmintaCCCP 5b5b729
fix(auth): 同步成功后再提交认证状态(CodeRabbit 第四轮)
AmintaCCCP c754591
feat(settings): 后台同步面板新增后端地址配置,与登录页共享同一配置
AmintaCCCP 54b2d9f
fix(review): 落实 full review 三项意见——发布分支限制、URL 显式记忆、禁自动重定向
AmintaCCCP 3a9c839
Merge pull request #327 from Swiftlyfisher/feat/issue-322-backend-login
AmintaCCCP da6c37a
docs: specify MCP discovery tools
ke-1t c1da01c
docs: plan MCP discovery implementation
ke-1t 1170888
feat: add MCP discovery tools
ke-1t 6b5ea74
fix: describe all vector tools in MCP status
ke-1t 3db94a3
fix(review): 审计修复——跨端排序/分页语义对齐并补响应级 parity 测试
AmintaCCCP 7fa1e6e
fix(review): 捕获 Worker 查询的网络与解码异常,折叠进声明的 unavailable 结果
AmintaCCCP ecb081f
fix: normalize worker failure reason
ke-1t e440e27
fix(review): 两端统一校验 Worker JSON 响应结构,无效结构返回 worker_query_failed
AmintaCCCP 53b4725
Merge pull request #330 from ke-1t/feat/mcp-discovery-tools
AmintaCCCP 387652d
feat(search): 无向量 AI 搜索改为「查询扩展 → 词法召回 → LLM 精选」三段式降级链
AmintaCCCP 3afe743
fix: auto-rename GitHub Lists on language switch (Mandarin -> English)
amaruki 0171d41
fix: address adversarial review — rename surfacing & replayable
amaruki 2019271
fix(review): 落实 CodeRabbit 三项意见——abort 传播、扩展词词级剔除、推理模型精选预算
AmintaCCCP 5330010
fix(search): AI 精选成功后置位 skipNextTextSearchRef,防过滤 effect 覆盖结果
AmintaCCCP f5d8987
fix(search): AI 失败可见化 + 词法兜底 CJK bigram 召回 + 扩展预算加固
AmintaCCCP a16871a
fix(review): 取消异常在 hook 两层 catch 中传播,不再被静默吞掉
AmintaCCCP 675aee3
fix(review): 幻觉 ID 不再被误判为模型判空,兜底路径行为补测试钉死
AmintaCCCP 0617fcd
fix(search): aiSearch 管理 AbortController,取消信号穿入无向量精选链路
AmintaCCCP d5d28b1
fix(mcp): align status metadata with application version
ke-1t e1b5988
Merge pull request #331 from AmintaCCCP/feat/ai-search-selection-fall…
AmintaCCCP 4d6497a
Merge remote-tracking branch 'upstream/main' into fix/mcp-status-cont…
ke-1t 576fd0c
fix(release): recover interrupted package version sync
ke-1t f740db3
fix(lists): rename 不再误清描述——省略 description 时不发送显式 null
AmintaCCCP 9b57940
test(release): use a confirmed stale lock pid
ke-1t 27c4aac
Merge pull request #332 from amaruki/fix/list-language-migration
AmintaCCCP 110a5dd
fix(release): clear orphaned package-sync backups and unify error mes…
AmintaCCCP a70cd27
fix(release): recover interrupted transactions under the exclusive re…
AmintaCCCP 639d7d3
Merge pull request #333 from ke-1t/fix/mcp-status-contract
AmintaCCCP 0dbd594
fix(ui): resolve a11y/contrast findings and polish visual details
AmintaCCCP a3c5ce3
fix(ui): keyboard activation of drag handle opens the category editor
AmintaCCCP 5f1a115
style(typography): root font smoothing, ellipsis character, text-wrap…
AmintaCCCP 5c61946
style(theme): premium surface layering, Inter default, tactile press
AmintaCCCP c8a2be5
fix(ui): address CodeRabbit minors — pagination reset key, font keywo…
AmintaCCCP e702f7f
Merge pull request #334 from AmintaCCCP/fix/ui-visual-polish
AmintaCCCP f7b6efe
fix(ci): skip prebuild version sync in frontend Docker build
AmintaCCCP c9130c3
Merge pull request #335 from AmintaCCCP/fix/frontend-docker-prebuild
AmintaCCCP 71e3437
Bump version from 0.7.9 to 0.8.0
AmintaCCCP 386948a
docs: unify Docker image tag examples to 0.8.0
AmintaCCCP 5c1a98d
docs: add 0.8.0 release info to version-info.xml
AmintaCCCP dd1c182
fix(theme): normalize preset palettes for WCAG contrast, layering, ra…
AmintaCCCP 5e8eb6d
fix(theme): address coderabbit review on contrast, focus indicators a…
AmintaCCCP c55757f
fix(theme): ensure strictly monotonic shadow elevation tiers across a…
AmintaCCCP d18388d
Merge pull request #336 from AmintaCCCP/fix/theme-preset-polish
AmintaCCCP 14853e2
fix(categories): prevent partial keyword false positives
b5bef87
Merge pull request #337 from Swiftlyfisher/fix-category-keyword-matching
AmintaCCCP 95bff9b
feat(discovery): add grep.app code search channel with realtime filte…
AmintaCCCP 1d712bd
fix(code-search): harden snippet sanitizer, keep pagination under sta…
AmintaCCCP b5ea78a
Merge pull request #341 from AmintaCCCP/feature/code-search-grep-app
AmintaCCCP 2899623
feat(repository-chat): add S4 global history entry next to filters wi…
AmintaCCCP aa3a222
fix(repository-chat): address coderabbit review on global history entry
AmintaCCCP f85b978
fix(repository-chat): notify global history immediately after session…
AmintaCCCP abea39e
Merge pull request #344 from AmintaCCCP/feature/global-chat-history-s4
AmintaCCCP 2c8c6cf
feat(desktop): add auto-launch and minimize-to-tray (#345)
AmintaCCCP fbafd17
fix(desktop): serialize IPC writes with a sync ref lock
AmintaCCCP 1d2cf04
Merge pull request #346 from AmintaCCCP/feature/desktop-autolaunch-tr…
AmintaCCCP 86f0382
fix(repoSearch): 按更新排序优先pushed_at并加固回退
AmintaCCCP 262d9ae
fix(repoSearch): address coderabbit docstring coverage on sort helpers
AmintaCCCP 8f1a2f7
Merge pull request #347 from AmintaCCCP/fix/repo-sort-pushed-at-342-r…
AmintaCCCP 01bf6dc
feat(discovery): 新增阮一峰周刊发现频道,搜索频道改名并去除 grep.app 文案
AmintaCCCP 492c38b
fix(weekly): address coderabbit review round 1
AmintaCCCP 2b2ceab
feat(weekly): 改为按需分页抓取,不再一次性拉全量
AmintaCCCP 6c251ef
fix(weekly): 遍历分页原子落盘,避免游标与数据不一致
AmintaCCCP fc8f4c8
fix(weekly): 页级脏集合落盘 + 深度遍历停止条件与补全集合对齐
AmintaCCCP 7efb1be
fix(weekly): address coderabbit review round 4
AmintaCCCP 25cb4db
Merge pull request #349 from AmintaCCCP/feature/weekly-discovery-channel
AmintaCCCP af1fc28
fix(theme): 选中/搜索高亮改为派生 token,修复选中态不可见 (#348)
AmintaCCCP 97d0818
Merge pull request #350 from AmintaCCCP/fix/issue-348-selection-visib…
AmintaCCCP 1c6927b
fix(desktop): 托盘图标改为单色图,适配菜单栏深浅与尺寸 (#345 后续)
AmintaCCCP c57adc5
docs(desktop): 补充托盘图标函数 docstring
AmintaCCCP dda7305
Merge pull request #351 from AmintaCCCP/fix/tray-template-icon
AmintaCCCP 8e89787
feat: discover local plugin manifests v0.9.0
Khk-NL b08532a
Merge pull request #1 from Khk-NL/plugin-manifest-discovery
Khk-NL 7bc2931
docs(plans): add 2026-09-17 product roadmap proposal
Khk-NL ccc4387
feat: add repository health facts v0.9.0
Khk-NL 8b1bfeb
fix: align repository health mirrors and unknown release frequency
Khk-NL 6c6e4e1
feat: detect installable release assets v0.10.0
Khk-NL f2b577c
docs: version-control the stage development logs
Khk-NL 8fab039
docs: add main vs plugin-system-v0-9 merge analysis
Khk-NL 721eb31
Merge plugin-system-v0-9 into main: adopt the full v0.10.0 feature set
Khk-NL 7821169
docs: add the stage 3 log for the main unification
Khk-NL 7db3f60
feat: add batch repository URL extraction v0.11.0
Khk-NL File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,139 @@ | ||
| # 阶段日志 1:Repository Health Core(v0.9.0) | ||
|
|
||
| - 日期:2026-09-20 | ||
| - 分支:`plugin-system-v0-9`(基线 `b06a347`,已快进到 `upstream/plugin-system-v0-9`) | ||
| - 依据:[`开发守则.md`](../../../开发守则.md) §1 与 [`docs/plans/2026-09-17-product-roadmap.md`](../plans/2026-09-17-product-roadmap.md) §4 | ||
| - 阶段提交:`feat: add repository health facts` | ||
| - 代码量:29 个文件,+2112 / −31 → 按仓库既有节奏(1166–7110 行的功能提交对应 minor 提升)取 minor 版本号 `0.9.0` | ||
|
|
||
| ## 1. 目标与边界 | ||
|
|
||
| 提供**客观**的 Repository Health Facts,不给统一总分: | ||
|
|
||
| - Core 只输出可验证事实与保守观测(`archived` / `disabled` / `no-releases` / `no-recent-activity`)。 | ||
| - 不提供 0–100 健康分数,不做「健康 / 不健康」结论——主观评分属于插件。 | ||
| - 明确拒绝「最近提交少 = 不健康」:`no-recent-activity` 只是中性观测,阈值 12 个月仅用于展示。 | ||
| - 未知事实一律为 `undefined` / `null`,绝不猜测(例如未同步过 Release 时不声称「没有 Release」)。 | ||
|
|
||
| ## 2. 统一模型 | ||
|
|
||
| 新增 [`src/types/health.ts`](../../src/types/health.ts): | ||
|
|
||
| - `RepositoryHealthSnapshot`:roadmap 建议模型 + `fork` / `isTemplate` / `releasesFetched` / | ||
| `releasesPerYear` / `latestStableVersion` / `latestPrereleaseVersion` / `ageDays` / | ||
| `daysSinceLastPush` / `signals`。 | ||
| - `RepositoryHealthFact`:三态取值语义 —— `undefined` = 未知,`null` = 已知为空(如无 license), | ||
| 有值 = 已知;并带 `group` / `kind` / `source`(`repository` / `releases` / `enrichment`)。 | ||
| - `RepositoryHealthGroup`:固定 `activity` → `maintenance` → `community` → `maturity`。 | ||
|
|
||
| 推导集中在 [`src/utils/repositoryHealth.ts`](../../src/utils/repositoryHealth.ts),纯函数、无网络请求: | ||
|
|
||
| | 能力 | 说明 | | ||
| |---|---| | ||
| | `deriveRepositoryHealthSnapshot` | 由 `Repository` + 本地 `Release[]`(+ 可选 enrichment)推导全部事实 | | ||
| | `deriveRepositoryHealthSignals` | 4 种保守观测,顺序固定,`since` 仅在时间型观测上有值 | | ||
| | `groupRepositoryHealthFacts` | 展开为 UI 分组视图,不含任何格式化(留给 UI / 后续 i18n) | | ||
| | `isArchivedRepository` / `hasRecentActivity` / `hasDeclaredLicense` | 列表筛选谓词,与 UI 口径同源 | | ||
|
|
||
| **没有新增持久化 Store slice,也没有 Store migration**:快照是派生投影,不进入 | ||
| `Repository` 实体持久化路径,因此不触碰 Issue #304 的后端同步哈希契约。 | ||
|
|
||
| ## 3. 让事实真正可达:同步层的最小改动 | ||
|
|
||
| `/user/starred` 原始响应本就带 `archived` / `disabled` / `fork` / `is_template` / | ||
| `open_issues_count` / `default_branch`,但 `Repository` 类型没有声明,且后端不存储这些列。 | ||
| 按「先确认安全性再动手」的顺序处理: | ||
|
|
||
| 1. [`src/types/index.ts`](../../src/types/index.ts):把这 6 个字段加入 `Repository`(可选)。 | ||
| 它们是运行时对象里**已经存在**的字段,因此类型补全不改变 `JSON.stringify` 的任何字节。 | ||
| 2. [`src/utils/repositoryMerge.ts`](../../src/utils/repositoryMerge.ts):同名字段**成对**加入 | ||
| `CLIENT_ONLY_REPOSITORY_FIELDS`(不参与后端同步指纹)与 `LOCAL_REPOSITORY_FIELDS` | ||
| (拉取时保留本地值)。只加一边会破坏既有不变式——只加 CLIENT_ONLY 会在每次拉取时被清空, | ||
| 只加 LOCAL 会保留但触发多余的「已变化」判定。 | ||
| 3. [`src/features/repositories/hooks/useSearchActions.ts`](../../src/features/repositories/hooks/useSearchActions.ts): | ||
| 星标同步的既有仓库字段白名单加入这 6 个字段(归档状态会随上游变化), | ||
| 源缺失时回落到本地已知值,避免事实退化成「未知」。 | ||
| 4. [`src/services/githubApi.ts`](../../src/services/githubApi.ts):详情路径(REST + GraphQL) | ||
| 捕获这些字段;GraphQL 片段补上 `isArchived` / `isDisabled` / `isFork` / `isTemplate` / | ||
| `openIssues` / `defaultBranchRef`,否则 GraphQL 路径拿不到值。字段在 | ||
| `GitHubRepoDetailRead` 中保持可选,避免破坏既有测试夹具。 | ||
|
|
||
| 后端 `server/` 与 `cloudflare-worker/` **未改动**:后端不存这些列,因此 MCP 侧对 | ||
| 「未知」与「未归档」保持严格区分(见 §5)。 | ||
|
|
||
| ## 4. 复用面 | ||
|
|
||
| | 复用方 | 落点 | | ||
| |---|---| | ||
| | UI | 新增 [`RepositoryHealthPanel.tsx`](../../src/components/RepositoryHealthPanel.tsx),接入 [`RepositoryReleaseSheet.tsx`](../../src/components/RepositoryReleaseSheet.tsx)(唯一同时持有 repository 与实时 releases 的界面)。分组展示 + 保守观测徽章 + 「以上为客观事实,不含健康总分」脚注 | | ||
| | 筛选 | `SearchFilters` 新增 `healthArchived` / `healthRecentActivity` / `healthHasLicense`;[`SearchBar.tsx`](../../src/components/SearchBar.tsx) 新增「仓库健康事实」筛选区,`clearFilters` / 激活计数同步 | | ||
| | 排序 | 新增 `sortBy: 'created'`(成熟度视角),`getSortValue` 与排序下拉同步 | | ||
| | Discovery / AI | [`aiService.ts`](../../src/services/aiService.ts) 两处 repoInfo 模板(自定义 / 内置提示)插入客观事实摘要,并显式标注「中性,不代表质量结论」 | | ||
| | MCP | [`electron/repoHealth.js`](../../electron/repoHealth.js) + [`server/src/mcp/repoHealth.ts`](../../server/src/mcp/repoHealth.ts) 镜像同一算法;`buildRepoEvidence` 输出 `health` 块,`gsm_search_repos` / `gsm_list_repos_by_category` 暴露 3 个 health 筛选与 `created` 排序 | | ||
| | Plugin API | [`pluginProtocol.js`](../../electron/plugins/pluginProtocol.js) `sanitizeRepository` 追加 6 个状态字段 + `has_fetched_releases`(全部属于既有 `repositories:read` 权限范围,不新增能力) | | ||
|
|
||
| MCP 侧修正了一处**既有的事实性错误**:原本 `evidence.repository.archived` 恒为 `null`, | ||
| 并在 `limitations[0]` 固定声明 `archived is not stored locally`。现在只有在记录里确实 | ||
| 不存在该布尔值时才保持 `null` 并声明限制;一旦有值就照实上报。该限制串因此改为条件输出, | ||
| 既有断言的夹具不含该字段,所以断言语义不变。 | ||
|
|
||
| ### 三份镜像实现是刻意的 | ||
|
|
||
| `src/utils/repositoryHealth.ts`(ESM/TS)、`electron/repoHealth.js`(CommonJS)、 | ||
| `server/src/mcp/repoHealth.ts`(ESM/TS)必须是三份:Electron 侧是 CJS 且 | ||
| `electron-builder.yml` 不打包 `src/`,server 的 `rootDir: "src"` 禁止 import 应用源码树。 | ||
| 这与仓库既有的 `mcpDiscovery.js` / `server/src/mcp/repoSearch.ts` 镜像模式一致。 | ||
| [`server/tests/mcp/parity.test.ts`](../../server/tests/mcp/parity.test.ts) 新增两条用例锁定 | ||
| Electron 与后端两份输出**逐字段相等**,并锁定「未知保持未知」。 | ||
|
|
||
| ## 5. 刻意未做 | ||
|
|
||
| - 不引入需要联网补全的事实(contributors、closed issues、Security Policy、CI、README/文档、 | ||
| 默认分支最近提交):模型已预留字段与 `enrichment` 来源,但在本阶段不联网获取, | ||
| UI 显示为「未知」。这样避免了额外的 GitHub 请求预算与限流风险,且离线可用。 | ||
| - **列表筛选不包含依赖 Release 的事实**(是否有 Release、最新版本):`applyRepoFilters` | ||
| 拿不到 Release 数组,为它接一个全量 `releases` 订阅会造成整个搜索栏频繁重渲染。 | ||
| 这些事实在 Health 面板、MCP 证据与插件快照中可用。 | ||
| - `gsm_vector_search` 不暴露 health 筛选:向量检索有独立的 Worker 契约,且其注释明确 | ||
| 不应假装提供精确的 corpus-wide filtered topK。保留其已批准的输入面。 | ||
| - 不做健康总分、不做插件评分界面(交给插件生态)。 | ||
|
|
||
| ## 6. 验证 | ||
|
|
||
| | 关卡 | 结果 | | ||
| |---|---| | ||
| | `node scripts/check-boundaries.cjs` | 通过(无分层违规) | | ||
| | `npm run typecheck` | 通过 | | ||
| | `npm run lint` | 通过 | | ||
| | `npx vitest run` | 102 文件 / 1012 用例,16 失败 —— 与改动前基线**完全相同**(`RepositoryCard`、`RepositoryCard.lazyReadme`、`ReadmeModal`、`ForkTimeline` 的 jsdom 5s 超时,属环境慢导致,非本次改动) | | ||
| | `npm run test:electron:mcp` | 24/24 通过(含证据与工具输入面断言) | | ||
| | `npm run test:electron:plugins` | 91/91 通过 | | ||
| | `npm run test:update-version` | 10/10 通过 | | ||
| | server 测试 | **未能运行**:`npm ci` 在 `better-sqlite3` 原生编译处失败(本机缺 C++ 构建工具链),属既有环境限制;server 侧改动已逐行复核,并新增 parity 用例待 CI 执行 | | ||
|
|
||
| 新增/更新的测试: | ||
|
|
||
| - `src/utils/repositoryHealth.test.ts`(22 例):推导、三态语义、观测顺序、`presto` 之类 | ||
| 预发布误判防护、筛选谓词。 | ||
| - `src/components/RepositoryHealthPanel.test.tsx`(6 例):分组、无总分声明、未知不猜测、 | ||
| 无 Release 数据时不报「No releases」。 | ||
| - `electron/repoHealth.test.js`(6 例):锁定 Electron 镜像算法。 | ||
| - `server/tests/mcp/parity.test.ts`(+2 例):跨运行时逐字段一致。 | ||
|
|
||
| `RepositoryReleaseSheet.test.tsx` 的 Release 条目查询改为限定在 `release-list` 容器内, | ||
| 因为 Health 面板同样会显示最新稳定版本 tag,全局查询会与之串台。 | ||
|
|
||
| ## 7. 版本号说明 | ||
|
|
||
| 根 `package.json` 此前停留在 `0.8.1`,而 `version-info.xml` 也没有 `0.9.0` 记录—— | ||
| 插件平台(`c53c07b`…`b06a347`)虽然在提交信息里自称 v0.9.0,却从未落版本号与更新日志。 | ||
| 本阶段既然要发布 `0.9.0`,就把 0.8.1 之后实际进入代码的插件平台内容与本次 Health 事实 | ||
| 一并写入该版本的 changelog,避免用户看到「0.9.0 只包含 Health 事实」的失真描述。 | ||
|
|
||
| ## 8. 下一阶段 | ||
|
|
||
| 阶段 2:Installable Asset Detection(roadmap §5 / 开发守则 §2)—— | ||
| 统一识别当前设备可安装的 Release 资产,输出 `InstallableAsset`(platform / architecture / | ||
| packageType / confidence / reason),排除 source code、checksum、signature、symbols、debug、 | ||
| blockmap 等非安装资产,复用既有 `detectAssetPlatform` 与 Smart Release 的平台/架构判断, | ||
| 不确定时展示多个候选且不声称安装包安全。 |
133 changes: 133 additions & 0 deletions
133
docs/logs/2026-09-20-stage-2-installable-asset-detection.md
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,133 @@ | ||
| # 阶段日志 2:Installable Asset Detection(v0.10.0) | ||
|
|
||
| - 日期:2026-09-20 | ||
| - 分支:`plugin-system-v0-9`(基线 `8b1bfeb`) | ||
| - 依据:[`开发守则.md`](../../../开发守则.md) §2 与 [`docs/plans/2026-09-17-product-roadmap.md`](../plans/2026-09-17-product-roadmap.md) §5 | ||
| - 提交:`feat: detect installable release assets` | ||
| - 代码量:+约 1200 行(含测试)→ minor 提升至 `0.10.0` | ||
|
|
||
| ## 1. 目标与边界 | ||
|
|
||
| 统一回答「这个 Release 里哪个资产可以在当前设备上安装」,并把它做成可被 Release 视图、 | ||
| Discovery、My Apps、AI、MCP 与插件复用的一份结果。 | ||
|
|
||
| 明确不做(roadmap §5.3): | ||
|
|
||
| - 不下载后执行、不自动运行安装程序。 | ||
| - 不因为扩展名像安装包就断言软件安全——UI 文案显式说明「未验证安装包安全性」。 | ||
| - 不把 ZIP 一律当作可安装软件(见 §3 的平台判定)。 | ||
| - 不自动选择来源不明的第三方镜像:下载仍走既有 GitHub allowlist 链路。 | ||
|
|
||
| ## 2. 统一模型 | ||
|
|
||
| [`src/types/installableAsset.ts`](../../src/types/installableAsset.ts):`InstallableAsset` | ||
| (assetId / fileName / downloadUrl / size / platform / architecture / packageType / | ||
| confidence / reason)与 `InstallableAssetDetectionResult`(`matches` + `excluded[]`)。 | ||
|
|
||
| 模型里显式保留 `excluded`(资产 id + 文件名 + 原因):这样 UI 能回答「为什么某个资产没被推荐」, | ||
| 而不是让排除静默发生。这直接对应用户「始终可以手动选择其他 Release Asset」的前提—— | ||
| 用户需要知道还有什么、以及为什么没被选中。 | ||
|
|
||
| ## 3. 识别规则 | ||
|
|
||
| [`src/utils/installableAssets.ts`](../../src/utils/installableAssets.ts),纯函数、无网络: | ||
|
|
||
| | 环节 | 做法 | | ||
| |---|---| | ||
| | 平台 | **复用** [`detectAssetPlatform`](../../src/utils/releaseAssets.ts) 与它导出的 `OS_TOKEN_PLATFORM` 词表,不另写平台表 | | ||
| | 包类型 | 新增后缀表(长后缀优先):`.exe .msi .zip .7z .dmg .pkg .deb .rpm .AppImage .tar.gz .apk .aab` | | ||
| | 架构 | 新增词表:`x64`(`x86_64`/`amd64`/`x64`/`win64`)、`arm64`(`aarch64`/`arm64`)、`x86`(`ia32`/`i386…i686`/裸 `x86` 且后面不是 `64`)、`universal`(`universal`/`universal2`/`multiarch`) | | ||
| | 排除 | 源代码归档、校验和、签名、调试符号、Electron blockmap、SBOM | | ||
| | 置信度 | 决定性扩展名 + 已知架构 = `high`;只满足其一 = `medium`;容器格式且架构未知 = `low` | | ||
|
|
||
| 三条刻意的判定规则: | ||
|
|
||
| 1. **`win32` 不是 32 位标记**。Electron 用 `win32` 命名 Windows 构建,把它当 x86 会让 | ||
| `app-win32-x64.zip` 这种常见命名被误判。参考实现(`examples/plugins/smart-release-recommender/worker.js`) | ||
| 的注释也是这么写的,这里保持一致。 | ||
| 2. **文件名声明多个平台直接排除**(`project-win32-linux-x64.zip`),与参考实现一致; | ||
| **扩展名与文件名冲突也排除**(`app-1.2.0-linux.dmg`)——宁可排除并说明,也不要挑一个可能装错的包。 | ||
| 3. **容器格式缺平台标记时不猜平台**(`myapp-1.0.zip`):只在 `content_type` 提供 MIME 证据时 | ||
| 才回落(复用 `detectAssetPlatform` 的最后一层)。其余情形排除并说明原因, | ||
| 资产表里仍可手动下载。 | ||
|
|
||
| 不确定时的处理是「并列候选」:设备架构未知就不做架构过滤(x64 与 arm64 同时列出), | ||
| 文件名同时声明多架构就不猜架构、降级为 `medium` 并注明。 | ||
|
|
||
| ## 4. 当前设备识别 | ||
|
|
||
| [`src/utils/deviceTarget.ts`](../../src/utils/deviceTarget.ts):`detectDevicePlatformSync()` | ||
| (`navigator.userAgentData.platform` → `navigator.platform` → UA 字符串)与 | ||
| `resolveDeviceArchitecture()`(high-entropy hints,带进程内缓存)。 | ||
|
|
||
| 两个刻意的选择: | ||
|
|
||
| - **不新增 Electron IPC**。渲染进程用 `navigator.userAgentData` 就能拿到宿主 OS/CPU 架构, | ||
| 而 Web 版本来就没有 Electron 进程。为读一个平台号新增 IPC 会扩大 Host 接口面, | ||
| 与「不扩大 Electron 权限边界」相悖。插件运行时的 `hostEnvironment {os, arch}` 保持不变,各管一摊。 | ||
| - **架构拿不到就承认拿不到**。high-entropy hints 只能异步取;Firefox/Safari 或 API 被拒时 | ||
| 返回 `undefined`,调用方据此放弃架构过滤,而不是假定 x64。 | ||
|
|
||
| ## 5. UI | ||
|
|
||
| [`InstallableAssetRecommendation.tsx`](../../src/components/InstallableAssetRecommendation.tsx) | ||
| 接入 `RepositoryReleaseSheet` 的资产页签,位于插件推荐块之下、资产表之上(该组件同时持有 | ||
| `release` 与 `onDownload`,无需新数据源): | ||
|
|
||
| - 首选候选 + 「下载此版本」按钮(**必须点击**,绝不自动下载)、置信度徽章、平台/架构/包类型/大小。 | ||
| - 其他候选列表,每个都可单独下载。 | ||
| - 排除说明:列出「源代码 / 校验和 / 签名 / 调试符号 / blockmap / 其他平台或架构」的排除数量。 | ||
| - 无适配资产时整块**不渲染**(不制造噪音)。 | ||
|
|
||
| 下载动作**复用既有链路**:`buildReleaseDownloadLinks` 生成 `ReleaseDownloadLink`, | ||
| 再交给 `RepositoryReleaseSheet` 的 `downloadAsset`(RPC / 认证下载 / 后端代理 / window.open)。 | ||
| 检测结果只提供 `assetId`,按 id 回查 link,因此没有第二套下载逻辑,也没有改动 | ||
| `ReleaseDownloadLink` 的形状(它的测试做整数组 `toEqual`)。 | ||
|
|
||
| 顺带把 `formatFileSize` 从 `RepositoryReleaseSheet` 提到 | ||
| [`src/utils/formatBytes.ts`](../../src/utils/formatBytes.ts),让推荐块与资产表用同一套显示口径。 | ||
|
|
||
| ## 6. 刻意的分歧与未做 | ||
|
|
||
| - **不复用 `PRESET_FILTERS`**:它把 `zip` / `tar.gz` 归入 Source,且用朴素子串匹配 | ||
| (`win` 会命中 `darwin`),与「可安装软件识别」的目标直接冲突。既有资产筛选器保持原样。 | ||
| - **不改参考实现**:`examples/plugins/smart-release-recommender/worker.js` 里的架构/排除/打分 | ||
| 逻辑无法反向依赖 `src/`(沙箱装的是打包后的插件,且插件不应读 Core 内部)。 | ||
| 它是给第三方插件看的参考实现,保留自己的小词表是合理分歧; | ||
| Core 侧的 Host 实现已在模块注释里标明对应关系。 | ||
| - **本阶段不接入 Discovery / My Apps / 插件 / MCP**:开发守则 §2 的验收项只要求模型、识别规则、 | ||
| 候选展示与手动选择,这三项已完成。把结果推给插件的 MCP 快照与插件 release 载荷需要先定下 | ||
| 「服务端运行时的设备是谁」(自托管后端可能跑在容器里,报容器平台会误导用户), | ||
| 这件事值得单独一个小 PR;`hasInstallableAsset()` 已作为仓库级入口导出,供 Discovery | ||
| 与批量导入预览直接复用。 | ||
|
|
||
| ## 7. 验证 | ||
|
|
||
| | 关卡 | 结果 | | ||
| |---|---| | ||
| | `node scripts/check-boundaries.cjs` | 通过 | | ||
| | `npm run typecheck` | 通过 | | ||
| | `npm run lint` | 通过 | | ||
| | `npx vitest run` | 105 文件 / 1062 用例,16 失败 —— 与阶段 1 及改动前基线**同一集合**(4 个重型 jsdom 组件测试的 5s 超时) | | ||
| | `npm run test:electron:mcp` / `test:electron:plugins` / `test:update-version` | 本阶段未触碰 electron / server / 脚本,保持阶段 1 的通过状态 | | ||
|
|
||
| 新增测试: | ||
|
|
||
| - [`installableAssets.test.ts`](../../src/utils/installableAssets.test.ts)(30 例):各平台包类型、 | ||
| 6 类排除、多平台/扩展名冲突、架构冲突与通用包、未知架构并列候选、AAB 只识别、 | ||
| MIME 回落、排序稳定性、空输入、`hasInstallableAsset`。 | ||
| - [`deviceTarget.test.ts`](../../src/utils/deviceTarget.test.ts)(12 例):三级平台回退、 | ||
| high-entropy 架构映射与缓存、API 缺失/被拒/32 位 ARM 时返回 `undefined`。 | ||
| - [`InstallableAssetRecommendation.test.tsx`](../../src/components/InstallableAssetRecommendation.test.tsx)(6 例): | ||
| 点击才下载、复用 link 模型、安全免责声明、无候选不渲染、候选与排除说明、无法识别设备时并列候选。 | ||
|
|
||
| `RepositoryReleaseSheet.test.tsx` 无需改动即通过(推荐块不渲染被排除的资产名, | ||
| 平台徽章断言仍由资产表的 `.asset-platform-badge` 满足)。 | ||
|
|
||
| ## 8. 下一阶段候选 | ||
|
|
||
| 按开发守则的推荐顺序,下一阶段可以是: | ||
|
|
||
| 1. `feat: add batch repository URL extraction`(§6 前半,纯逻辑、可测试、风险低); | ||
| 2. 或把可安装资产结果接入平台感知 Discovery(§8)与统一快照(插件/MCP), | ||
| 但需要先明确服务端运行时的设备归属。 | ||
Oops, something went wrong.
Oops, something went wrong.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
修正
开发守则.md的相对路径。当前文件位于
docs/logs。../../../开发守则.md会越过仓库根目录,因此链接无法解析。建议修改
📝 Committable suggestion
🤖 Prompt for AI Agents