feat(): 完成 skills 领域模型与本地注册表基础能力#269
Conversation
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
|
/code 帮我检查现在代码还有没有你提到的风险,有就修复 |
|
已按你提到的历史风险点完成复查并修复,改动已推送到当前 PR 头分支 本次修复
测试补充
验证结果
未做内容:未扩展到 |
Generated with [codeagent](https://github.com/qbox/codeagent) Co-authored-by: Cai-Tang-www <106404101+Cai-Tang-www@users.noreply.github.com>
|
/review |
| continue | ||
| } | ||
|
|
||
| data, readErr := readFile(skillPath) |
There was a problem hiding this comment.
maxFileBytes is enforced using Lstat().Size() before ReadFile(), but this is a TOCTOU window: the file can be swapped/grown between those two operations, and ReadFile will still load the full contents into memory. In adversarial or concurrent environments this bypasses the intended memory cap and can cause large allocations/DoS. Consider opening the file once and reading via io.LimitedReader (or equivalent bounded read) so the size limit is enforced at read time, not only at pre-check time.
|
/simplify |
|
|
||
| var headingPattern = regexp.MustCompile(`^\s{0,3}#{1,6}\s+(.+?)\s*$`) | ||
|
|
||
| // LocalLoader scans one root directory and loads local skills. |
There was a problem hiding this comment.
Reviewed this change set end-to-end (including tests and edge paths). No actionable issues found.
| } | ||
| name := strings.TrimSpace(meta.Name) | ||
| if name == "" { | ||
| name = firstHeading(body) |
There was a problem hiding this comment.
name 的回退逻辑直接取 firstHeading(body),会把结构化分段标题(例如仅有 ## References)当作技能名。当前测试也固定了该行为,导致无显式 name 且无标题时会生成语义错误的名称(如 references)。建议仅将一级标题(如 # Title)用于名称回退,或在找不到合适标题时直接回退到 id。
|
|
||
| candidates := make([]string, 0, len(entries)+1) | ||
| rootSkillFile := filepath.Join(absRoot, skillFileName) | ||
| if _, err := statPath(rootSkillFile); err == nil { |
There was a problem hiding this comment.
statPath(rootSkillFile) errors other than nil are silently ignored, so a root-level SKILL.md that exists but is unreadable (e.g. permission error / transient IO error) disappears without any LoadIssue. This breaks the "partial success + issue aggregation" contract and makes debugging difficult.
Please handle non-NotExist errors explicitly (append IssueReadFailed for rootSkillFile) instead of treating all errors as "no root skill".
|
|
||
| candidates := make([]string, 0, len(entries)+1) | ||
| rootSkillFile := filepath.Join(absRoot, skillFileName) | ||
| if _, err := statPath(rootSkillFile); err == nil { |
There was a problem hiding this comment.
statPath(rootSkillFile) errors are silently ignored unless nil. That drops permission/IO failures for root SKILL.md and makes loader issues non-observable. Consider handling non-NotExist errors by appending a LoadIssue (IssueReadFailed) instead of skipping root candidate detection entirely.
| continue | ||
| } | ||
|
|
||
| data, readErr := readFile(skillPath) |
There was a problem hiding this comment.
Size is checked via Lstat before ReadFile, but the file can change between those operations (TOCTOU). A replaced/grown file can bypass maxFileBytes and trigger unbounded memory read. Consider opening the file once, validating size from the opened descriptor (or reading through io.LimitReader) before/while reading.
结果已按触发评论完成处理:先检查历史评论并修复可执行问题,再做 simplify,最后提交并推送到当前 PR 头分支。 已完成内容
变更文件
验证
提交与推送
|
- aggregate root SKILL.md stat errors as non-fatal issues - enforce read-time size limit with bounded file reader - restrict name fallback to level-1 heading or id - add regression tests and simplify issue assertions Generated with [codeagent](https://github.com/qbox/codeagent) Co-authored-by: Cai-Tang-www <106404101+Cai-Tang-www@users.noreply.github.com>
背景
本 PR 对应 Skills 子任务落地,目标是在不改动主链路(TUI -> Runtime -> Provider -> Tools)的前提下,先完成
internal/skills领域层的可用骨架:关联父任务:#255
关联子任务:#257
本次改动
1) 新增 skills 领域模型与契约
SourceKind/ActivationScope/Descriptor/Content/Skill等核心类型Snapshot、LoadIssue、LoadIssueCode,用于“部分成功 + 问题聚合”模式Loader/Registry接口,明确后续扩展边界2) 新增本地加载器 LocalLoader
SKILL.md3) 新增内存注册表 MemoryRegistry
Refresh/List/GetIssues()暴露非致命问题,便于上层观测4) 覆盖率与测试补齐
internal/skills/coverage_test.go,补齐 helper/边界/异常分支测试internal/skills覆盖率提升至 100%(statement)验证结果
go test ./...✅go test ./internal/skills -coverprofile skills.out -count=1✅go tool cover -func skills.out显示total: 100.0%风险与说明
LocalLoader新增内部可测性钩子仅用于覆盖异常路径测试,不改变默认运行行为Closes #257