docs(comments): 注释中文化 · internal/runtime/memory(31 文件,纯替换)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled

- 只翻注释/文档字符串:820 增 / 820 删 严格 1:1;剥掉整行注释与行尾注释尾巴后,
  逐文件与 HEAD 比对「代码部分差异 = 0」;裁决/design 编号计数逐项与 HEAD 一致
- 保留可执行 SQL 样例、SQLite 报错原文、pgvector/HNSW/ANN/BLOB 等技术词原文
- 复核:go build 绿 + memory/projectindex/vector 三包测试绿;gofmt 仅剩 2 个既有未格式化文件(改动前即如此,未顺手修)
This commit is contained in:
AskaEth committed 2026-10-04 13:32:54 +08:00
1 parent eb1828ee7a
commit 61cf80d5ee
31 files changed
+820 -820

No files matched your search

+50 -50
View File
@@ -1,23 +1,23 @@
// Package projectindex implements the project-index hierarchy from
// DevDocs/design/03-记忆.md §3 ("项目记忆"作用域): a project is indexed as an
// entry plus description, and its content is split into chapters that can be
// searched line by line. The three-layer depth is 项目索引 → 项目描述 → 章节内容.
// projectindex 包实现 DevDocs/design/03-记忆.md §3(「项目记忆」作用域)中的
// 项目索引层级:一个项目被索引为一条
// 条目加描述,其内容被切成可逐行检索的章节。
// 三层深度为 项目索引 → 项目描述 → 章节内容。
//
// The two tables model that depth: the project row is the index entry (layer 1)
// carrying its description (layer 2), and project_chapter holds the chapter
// content (layer 3). Project memory is readable and writable by every persona
// (design §3 "人人可读可写", "项目索引各角色可查"), so the store carries no
// persona/role column and never filters by identity here.
// 两张表刻画该深度:project 行是指引条目(第 1 层),
// 携带其描述(第 2 层),project_chapter 保存章节
// 内容(第 3 层)。项目记忆每个角色都可读写
// (design §3「人人可读可写」「项目索引各角色可查」),因此存储没有
// persona/role 列,也不在此按身份过滤。
//
// This package is deliberately separate from the vector index
// (internal/runtime/memory/vector): it does text-based hierarchical indexing of
// project entries, descriptions, and chapters. Semantic/vector search belongs to
// the vector package.
// 本包刻意与向量索引
// (internal/runtime/memory/vector)分离:它对项目条目、描述与章节
// 做基于文本的分层索引。语义/向量检索属于
// 向量包。
//
// The store owns its schema: New creates the project and project_chapter tables
// and the chapter index idempotently. All SQL is parameterized (?), column lists
// are explicit (no SELECT *), reads take a context.Cancel, and every error is
// wrapped with %w so callers can use errors.Is against the package sentinels.
// 存储自己拥有 schema:New 幂等地创建 project 与 project_chapter 表
// 及章节索引。所有 SQL 参数化(?),列清单
// 显式列出(无 SELECT *),读取带 context.Cancel,且每个错误都
// 用 %w 包裹,调用方可用 errors.Is 对包哨兵错误判断。
package projectindex
import (
@@ -31,56 +31,56 @@ import (
"git.yeij.top/AskaEth/Cyrene_v2/internal/logger"
)
// Sentinels distinguishing projectindex failures. Each is wrapped with %w at the
// call site so callers can use errors.Is.
// 区分 projectindex 各类失败的哨兵错误。每个都在
// 调用点用 %w 包裹,调用方可用 errors.Is 判断。
var (
// ErrProjectNotFound is returned when a project id is blank or does not exist.
// ErrProjectNotFound 在项目 id 为空或不存在时返回。
ErrProjectNotFound = errors.New("projectindex: project not found")
// ErrChapterNotFound is returned when a required chapter reference is invalid.
// ErrChapterNotFound 在必需的章节引用无效时返回。
ErrChapterNotFound = errors.New("projectindex: chapter not found")
// ErrNilDB is returned when New receives a nil *sql.DB.
// ErrNilDB 在 New 收到 nil *sql.DB 时返回。
ErrNilDB = errors.New("projectindex: nil db")
// ErrMissingProject is returned when a required project id is blank.
// ErrMissingProject 在必需的 project id 为空时返回。
ErrMissingProject = errors.New("projectindex: project_id is required")
// ErrMissingTitle is returned when a project or chapter title is blank.
// ErrMissingTitle 在项目或章节标题为空时返回。
ErrMissingTitle = errors.New("projectindex: title is required")
// ErrMissingContent is returned when a chapter has no content.
// ErrMissingContent 在章节没有内容时返回。
ErrMissingContent = errors.New("projectindex: content is required")
// ErrMissingKeyword is returned when Search receives a blank keyword.
// ErrMissingKeyword 在 Search 收到空关键词时返回。
ErrMissingKeyword = errors.New("projectindex: keyword is required")
)
// Store is a project-index store backed by a *sql.DB.
// Store 是基于 *sql.DB 的项目索引存储。
//
// It owns its schema: New creates the project / project_chapter tables and the
// chapter index idempotently. Concurrency is delegated to *sql.DB, which is safe
// for concurrent use by contract, so Store holds no further lock. Every query is
// parameterized and reads take a context.Cancel.
// 它自己拥有 schema:New 幂等地创建 project / project_chapter 表与
// 章节索引。并发交由 *sql.DB,按约定它可安全
// 并发使用,因此 Store 不再持锁。每个查询都
// 参数化,读取带 context.Cancel。
type Store struct {
db *sql.DB
log *slog.Logger
}
// rowScanner is satisfied by both *sql.Row and *sql.Rows so a single scanProject
// or scanChapter helper serves both the Get and List paths.
// rowScanner 同时被 *sql.Row 与 *sql.Rows 满足,因此单个 scanProject
// 或 scanChapter 辅助函数即可服务 Get 与 List 两条路径。
type rowScanner interface {
Scan(dest ...any) error
}
// New builds a Store on db, ensuring the schema exists.
// New 在 db 上构建 Store,确保 schema 存在。
//
// db must be a live connection (the migration framework is owned by
// internal/db). A nil db returns ErrNilDB. log may be nil, in which case a
// discard logger is used; the active logger is tagged with source
// "memory/projectindex" so every record is traceable. ctx controls schema
// creation and must be honored by the caller. Legacy variable-width timestamps
// are normalized in place (see normalizeTimestamps).
// db 必须是存活的连接(迁移框架由
// internal/db 拥有)。nil db 返回 ErrNilDB。log 可为 nil,此时
// 使用丢弃型 logger;实际使用的 logger 带 source
// "memory/projectindex" 标签,因此每条记录都可追溯。ctx 控制 schema
// 创建,调用方必须遵守。旧的变宽时间戳
// 就地规范化(见 normalizeTimestamps)。
func New(ctx context.Context, db *sql.DB, log *slog.Logger) (*Store, error) {
if db == nil {
return nil, ErrNilDB
@@ -101,7 +101,7 @@ func New(ctx context.Context, db *sql.DB, log *slog.Logger) (*Store, error) {
return &Store{db: db, log: log}, nil
}
// discardLogger returns log if non-nil, otherwise a logger that writes nowhere.
// discardLogger 在 log 非 nil 时返回 log,否则返回一个不写任何地方的 logger。
func discardLogger(log *slog.Logger) *slog.Logger {
if log != nil {
return log
@@ -109,12 +109,12 @@ func discardLogger(log *slog.Logger) *slog.Logger {
return slog.New(slog.NewTextHandler(io.Discard, nil))
}
// ListProjects returns every project index entry in insertion order (created_at
// ASC, rowid ASC) — rowid breaks created_at ties so projects written within the
// same clock tick keep their insertion order. An empty (non-nil) slice is
// returned when there are none, so callers can range over it unconditionally. A
// read error is wrapped with %w so callers can use errors.Is against the package
// sentinels.
// ListProjects 按插入顺序(created_at ASC、rowid ASC)返回每个
// 项目索引条目 —— rowid 打破 created_at 并列,使同一时钟刻内写入的项目
// 保持其插入顺序。没有条目时返回空的
// (非 nil)切片,调用方可以无条件 range。读
// 错误用 %w 包裹,调用方可用 errors.Is 对包
// 哨兵错误判断。
func (s *Store) ListProjects(ctx context.Context) ([]Project, error) {
rows, err := s.db.QueryContext(ctx, `SELECT id, title, desc, created_at, updated_at
FROM project ORDER BY created_at ASC, rowid ASC`)
@@ -137,9 +137,9 @@ func (s *Store) ListProjects(ctx context.Context) ([]Project, error) {
return projects, nil
}
// Schema DDL, applied idempotently by New. The two tables model the three-layer
// hierarchy: the project row is the index entry (layer 1) plus its description
// (layer 2), and project_chapter holds the chapter content (layer 3).
// schema DDL,由 New 幂等施加。两张表刻画三层
// 层级:project 行是指引条目(第 1 层)加其描述
// (第 2 层),project_chapter 保存章节内容(第 3 层)。
const createProjectTable = `
CREATE TABLE IF NOT EXISTS project (
id TEXT PRIMARY KEY,