# https://github.com/BrettNye/stoa 项目说明书

生成时间：2026-05-13 16:44:51 UTC

## 目录

- [项目概述](#overview)
- [核心概念](#concepts)
- [系统架构](#architecture)
- [传输层实现](#transport)
- [事件总线系统](#eventbus)
- [召回与检索系统](#recall-system)
- [Wiki管理](#wiki-management)
- [任务协作系统](#task-coordination)
- [Claims与Evolution系统](#claims-evolution)
- [CLI命令参考](#cli-commands)

<a id='overview'></a>

## 项目概述

### 相关页面

相关主题：[系统架构](#architecture), [核心概念](#concepts)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/core/index.ts](https://github.com/BrettNye/stoa/blob/main/src/core/index.ts)
- [src/core/pages.ts](https://github.com/BrettNye/stoa/blob/main/src/core/pages.ts)
- [src/core/wikilinks.ts](https://github.com/BrettNye/stoa/blob/main/src/core/wikilinks.ts)
- [src/core/synthesize.ts](https://github.com/BrettNye/stoa/blob/main/src/core/synthesize.ts)
- [src/core/syntheses.ts](https://github.com/BrettNye/stoa/blob/main/src/core/syntheses.ts)
- [src/core/family.ts](https://github.com/BrettNye/stoa/blob/main/src/core/family.ts)
- [src/core/frontmatter.ts](https://github.com/BrettNye/stoa/blob/main/src/core/frontmatter.ts)
- [src/transport/stdio.ts](https://github.com/BrettNye/stoa/blob/main/src/transport/stdio.ts)
- [src/core/skills-platform.ts](https://github.com/BrettNye/stoa/blob/main/src/core/skills-platform.ts)
- [src/core/lint-checks/synthesis-debt.ts](https://github.com/BrettNye/stoa/blob/main/src/core/lint-checks/synthesis-debt.ts)
</details>

# 项目概述

## 项目简介

**stoa** 是一个基于 Markdown 文件系统的知识库管理系统（Knowledge Vault System），通过结构化的组织方式管理包含前端matter 的 markdown 文件。该系统提供了页面索引、维基链接解析、合成页面生成、语法检查、CLI 命令工具以及 MCP（Model Context Protocol）服务等核心功能。

系统的核心设计理念是将知识以标准化的页面形式存储在文件系统中，通过索引和工具层实现高级的知识管理操作，如跨页面引用、批量合成、部署漂移检测等。

## 核心架构

### 系统层次结构

stoa 采用分层架构设计，主要包含以下层次：

```mermaid
graph TD
    A[CLI 层] --> B[工具层]
    B --> C[核心业务层]
    C --> D[传输层]
    D --> E[文件系统]
    
    F[lint-checks] --> C
    G[index] --> C
    H[pages] --> C
    I[synthesize] --> C
```

### 目录结构

项目源码按功能模块组织：

| 目录 | 职责 |
|------|------|
| `src/core/` | 核心业务逻辑，包含索引、页面操作、合成、链接解析等 |
| `src/tools/` | MCP 工具实现，如 profile-register 等 |
| `src/cli/` | 命令行接口实现 |
| `src/transport/` | 传输层实现，如 stdio 服务器 |
| `src/core/lint-checks/` | 各种语法检查规则实现 |

## 核心模块

### 页面管理（pages）

页面是 stoa 的基本存储单元，每个页面对应一个 markdown 文件。

```mermaid
graph LR
    A[page id] --> B[pathForPage]
    B --> C[文件系统路径]
    D[readPage] --> E[返回页面对象]
    F[writePage] --> G[持久化到磁盘]
```

页面对象包含以下字段：

| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | string | 页面唯一标识符 |
| `path` | string | 文件系统路径 |
| `frontmatter` | Record | YAML 前端配置 |
| `body` | string | markdown 正文内容 |
| `updated` | string | ISO 日期格式的更新时间 |

资料来源：[src/core/pages.ts:1-50]()

页面读取时会解析文件的前端matter，提取元数据并规范化更新时间为 ISO 格式：

```typescript
const raw = readFileSync(path, "utf8");
const { frontmatter, body } = parseFrontmatter(raw);
return {
  id, path, frontmatter, body,
  updated: toIsoDate(frontmatter.updated ?? frontmatter.created)
};
```

资料来源：[src/core/pages.ts:20-27]()

### 索引系统（index）

索引系统是 stoa 的核心组件，负责维护页面元数据的索引以支持高效查询。

```mermaid
graph TD
    A[VaultIndex] --> B[pages]
    A --> C[wikis]
    A --> D[links]
    A --> E[profiles]
    A --> F[tokens]
```

索引数据结构 `VaultIndex` 包含以下子索引：

| 索引 | 用途 |
|------|------|
| `pages` | 所有页面的元数据数组 |
| `wikis` | wiki 列表及其配置 |
| `links` | 页面间链接关系 |
| `profiles` | profile 相关数据 |
| `tokens` | 全文搜索令牌索引 |

查询支持多维度过滤：

```typescript
if (f.wiki && wikiSet && !wikiSet.has(p.wiki)) return false;
if (f.type && p.type !== f.type) return false;
if (f.channel && p.channel !== f.channel) return false;
if (f.layer && f.layer !== "all") {
  const set = f.layer === "knowledge" ? KNOWLEDGE_TYPES : EXECUTION_TYPES;
  if (!set.includes(p.type)) return false;
}
```

资料来源：[src/core/index.ts:1-50]()

### 维基链接解析（wikilinks）

维基链接是 stoa 实现页面间关联的核心机制，支持 `[[wikis/<wiki>/<type>/<id>(|alias)]]` 格式的链接。

```mermaid
graph TD
    A[markdown 内容] --> B[wikilinkExtractor]
    B --> C{代码块检查}
    C -->|顶层代码块| D[跳过]
    C -->|普通内容| E[正则匹配]
    E --> F[WikilinkRef]
    
    F --> G[body]
    F --> H[frontmatter]
```

解析结果 `WikilinkRef` 接口定义：

| 字段 | 类型 | 说明 | 来源 |
|------|------|------|------|
| `raw` | string | 原始链接文本 | body 或 frontmatter |
| `wiki` | string | wiki 名称 | 路径解析 |
| `type` | string | 页面类型 | 路径解析 |
| `id` | string | 页面 ID | 路径解析 |
| `alias` | string? | 可选别名 | 管道后文本 |
| `source` | "body" \| "frontmatter" | 链接来源位置 | 提取位置 |

资料来源：[src/core/wikilinks.ts:1-40]()

代码块感知：顶层代码块（行首的 ``` ）内的链接会被跳过，但嵌套在列表项中的缩进代码块不会被剥离。

### 合成系统（synthesize）

合成功能用于将多个相关页面聚合成一篇综合性的 synthesis 页面。

```mermaid
graph TD
    A[输入: topic/by_agent] --> B[查询候选页面]
    B --> C[按类型过滤]
    C --> D[构建 synthesis 元数据]
    D --> E[生成 summary]
    E --> F[写入 synthesis 页面]
```

合成的页面元数据包含：

| 字段 | 示例值 |
|------|--------|
| `type` | synthesis |
| `wiki` | 目标 wiki |
| `status` | draft |
| `tags` | 根据作用域确定 |
| `sources` | 来源页面的 wikilink 数组 |
| `last_compiled` | ISO 日期 |
| `scope` | "memory"（可选） |

资料来源：[src/core/synthesize.ts:1-80]()

### 合成陈旧度追踪（syntheses）

系统追踪合成页面的陈旧程度，基于 `last_compiled` 时间戳计算滞后期。

```mermaid
graph TD
    A[所有 synthesis 页面] --> B[读取 last_compiled]
    B --> C{时间戳存在?}
    C -->|是| D[计算 lag_days]
    D --> E{超过 min_lag_days?}
    E -->|是| F[加入结果集]
    C -->|否| G[标记为从未编译]
    E -->|否| H[过滤掉]
```

陈旧度数据结构 `SynthesisStaleness` 包含：

- `pageId`: 页面标识
- `wiki`: 所属 wiki
- `lastCompiled`: ISO 日期或 null
- `lagDays`: 自上次编译以来的天数或 null

资料来源：[src/core/syntheses.ts:1-60]()

### Family 解析（family）

Family 是 wiki 的上层组织单元，支持多 wiki 的批量操作。

```mermaid
graph TD
    A[FamilyResolveCtx] --> B{解析优先级}
    B --> C[1. 显式 familyArg]
    B --> D[2. ctx.defaultFamily]
    B --> E[3. .active-family 文件]
    B --> F[4. 返回 null]
    
    C --> G{类型检查}
    G -->|wikiArg 存在| H[FamilyMismatchError]
    G -->|仅 familyArg| I[返回 familyArg]
```

解析上下文 `FamilyResolveCtx`：

```typescript
interface FamilyResolveCtx {
  vaultPath: string;
  defaultFamily?: string;
}
```

资料来源：[src/core/family.ts:1-50]()

### 语法检查系统（lint-checks）

lint 系统提供多维度的页面质量检查。

#### 主要检查规则

| 检查规则 | 严重程度 | 说明 |
|----------|----------|------|
| SYNTHESIS_DEBT | warn | 标记缺乏对应 synthesis 的硬知识聚类 |
| CLAIM_WITH_NO_SCOPE | warn | 标记无作用域的 claim 页面 |
| ACTIVE_WIKI_DIVERGENCE | info | 提示 defaultWiki 与 .active-wiki 不一致 |

#### SYNTHESIS_DEBT 详解

该检查识别满足以下条件的硬知识聚类：

1. 至少 N 个（默认 3）页面共享同一 tag
2. 这些页面都属于"硬知识"类型（concept、decision、spec）
3. 该 wiki 下没有任何 synthesis 页面使用该 tag

```typescript
const HARD_KNOWLEDGE_TYPES = new Set(["concept", "decision", "spec"]);
const DEFAULT_MIN_CLUSTER_SIZE = 3;
```

资料来源：[src/core/lint-checks/synthesis-debt.ts:1-50]()

### 前端matter 模式（frontmatter）

系统定义了严格的前端matter 验证模式。

#### 页面类型（NoteType）

```typescript
export const NoteType = z.enum([
  "concept", "guide", "decision", "source",
  "idea", "question", "journal", "move",
  "claim", "map", "synthesis"
]);
```

#### 页面状态（PageStatus）

```typescript
export const PageStatus = z.enum([
  "draft", "active", "accepted", "superseded", "archived"
]);
```

#### 置信度（Confidence）

```typescript
export const Confidence = z.enum(["high", "medium", "low"]);
```

#### 编排优先级（CurationPriority）

用于标记需要人工关注的草案页面：

```typescript
export const CurationPriority = z.enum(["high", "medium", "low"]);
```

资料来源：[src/core/frontmatter.ts:1-50]()

### 技能平台（skills-platform）

技能平台管理技能的部署和漂移检测。

```mermaid
graph TD
    A[DriftDeployment] --> B[detectDriftAt]
    B --> C{文件状态}
    C -->|canonical 缺失| D[抛出错误]
    C -->|deployed 缺失| E[kind: missing]
    C -->|哈希不匹配| F[kind: hash-mismatch]
    C -->|哈希匹配| G[无报告]
```

检测规则：

| 情况 | 处理方式 |
|------|----------|
| canonical 缺失 | 抛出异常（vault 完整性问题） |
| deployed 缺失 | 报告 `kind: "missing"` |
| 哈希不匹配 | 报告 `kind: "hash-mismatch"` |
| 哈希匹配 | 不报告 |

技能文件路径约定：

- **canonical**: `<vaultPath>/wikis/_agents/moves/<moveId>/SKILL.md`
- **deployed**: `<deployment.skills_dir>/<moveId>/SKILL.md`

资料来源：[src/core/skills-platform.ts:1-60]()

### MCP 服务（transport/stdio）

MCP 服务通过 stdio 传输层提供工具接口。

```mermaid
graph TD
    A[stdio 输入] --> B[JSON-RPC 解析]
    B --> C[工具路由]
    C --> D[profile-register]
    C --> E[其他工具]
    D --> F[StadiumClient]
    F --> G[平台 API]
    D --> H[更新 frontmatter]
    C --> I[返回 JSON-RPC 响应]
```

服务启动时通过 `walkInitablePaths` 预热状态缓存：

```typescript
function walkInitablePaths(vaultPath: string): string[] {
  // 递归遍历 wikis/ 目录
  // 返回所有 .md 文件路径
  // 用于构建初始状态
}
```

资料来源：[src/transport/stdio.ts:1-60]()

### 状态缓存（eventbus/state-cache）

状态缓存为事件处理提供内存状态存储。

```typescript
class StateCache {
  private states = new Map<string, unknown>();
  
  private key(source: string, wiki: string, id: string): string {
    return `${source}:${wiki}:${id}`;
  }
}
```

缓存键格式：`source:wiki:id`，支持按源、wiki、ID 三维定位状态。

资料来源：[src/core/eventbus/state-cache.ts:1-30]()

### 工具注册（tools/profile-register）

profile-register 工具将 profile 页面注册到 Stadium 平台。

流程：

1. 读取 `wikis/<wiki>/profiles/<profile_id>.md`
2. 提取 `pokemon` 或 `species_name` 字段
3. POST 到 `/profiles/register`
4. 更新文件的 `platform_profile_id` 和 `platform_stats`

资料来源：[src/tools/profile-register.ts:1-50]()

## CLI 命令

系统通过 commander 提供命令行接口：

| 命令 | 功能 |
|------|------|
| `new-wiki <name>` | 创建新 wiki，需指定 `--mode` 和 `--scope` |

创建 wiki 时的模式选项：

- `idea-map`
- `project-doc`
- `learning`
- `mixed`

资料来源：[src/cli/commands/new-wiki.ts:1-30]()

## 页面类型对应文件命名

| 类型 | 文件命名规则 |
|------|-------------|
| concept, guide, source, idea, question, claim, synthesis | `<type>-<slug>.md` |
| decision | `decision-YYYY-MM-DD-<slug>.md` |
| journal | `journal-YYYY-MM-DD-HHMM-<slug>.md` |
| move | `<move>/SKILL.md`（目录） |
| map | `map.md`（固定名称） |

资料来源：[src/core/ids.ts:1-30]()

## 总结

stoa 是一个功能完备的知识库管理系统，其核心价值在于：

1. **文件系统优先**：所有数据以标准 markdown 文件存储，便于版本控制和人工编辑
2. **结构化索引**：通过前端matter 和索引提供高效的元数据查询
3. **链接驱动**：通过 wikilink 实现页面间的语义关联
4. **质量保障**：多层 lint 检查确保知识库的一致性
5. **工具扩展**：MCP 架构支持与其他系统的集成

系统的设计遵循单一职责原则，各模块边界清晰，便于维护和扩展。

---

<a id='concepts'></a>

## 核心概念

### 相关页面

相关主题：[项目概述](#overview), [Wiki管理](#wiki-management)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/core/index.ts](https://github.com/BrettNye/stoa/blob/main/src/core/index.ts)
- [src/core/pages.ts](https://github.com/BrettNye/stoa/blob/main/src/core/pages.ts)
- [src/core/frontmatter.ts](https://github.com/BrettNye/stoa/blob/main/src/core/frontmatter.ts)
- [src/core/wikilinks.ts](https://github.com/BrettNye/stoa/blob/main/src/core/wikilinks.ts)
- [src/core/channel.ts](https://github.com/BrettNye/stoa/blob/main/src/core/channel.ts)
- [src/core/family.ts](https://github.com/BrettNye/stoa/blob/main/src/core/family.ts)
- [src/core/synthesize.ts](https://github.com/BrettNye/stoa/blob/main/src/core/synthesize.ts)
- [src/core/syntheses.ts](https://github.com/BrettNye/stoa/blob/main/src/core/syntheses.ts)
</details>

# 核心概念

Stoa 是一个知识管理 MCP (Model Context Protocol) 服务器，旨在对笔记库 (vault) 进行索引、检索和一致性检查。以下文档详细介绍其核心概念与架构。

## 页面类型系统

Stoa 采用结构化的页面类型体系，每种类型具有特定语义和存储约定。

### 页面类型定义

根据 `src/core/frontmatter.ts` 的定义，核心页面类型包括：

| 类型 | 语义 | 文件命名规则 |
|------|------|-------------|
| `concept` | 概念性知识 | `concept-<slug>.md` |
| `decision` | 决策记录 | `decision-YYYY-MM-DD-<slug>.md` |
| `journal` | 日志条目 | `journal-YYYY-MM-DD-HHMM-<slug>.md` |
| `guide` | 操作指南 | `guide-<slug>.md` |
| `source` | 外部引用 | `source-<slug>.md` |
| `idea` | 想法 | `idea-<slug>.md` |
| `question` | 问题 | `question-<slug>.md` |
| `spec` | 规格说明 | `spec-<slug>.md` |
| `synthesis` | 综合页面 | `synthesis-<slug>.md` |
| `move` | 技能移动 | `move-<slug>/SKILL.md` (目录结构) |
| `map` | 维基地图 | `map.md` (固定文件名) |

资料来源：[src/core/frontmatter.ts:1-30]()

### 页面状态

页面状态使用枚举定义：

```typescript
export const PageStatus = z.enum([
  "draft", "active", "accepted", "superseded", "archived"
]);
```

- **draft**: 草稿状态
- **active**: 活跃状态
- **accepted**: 已接受
- **superseded**: 已替代
- **archived**: 已归档

资料来源：[src/core/frontmatter.ts:35-37]()

### 置信度等级

```typescript
export const Confidence = z.enum(["high", "medium", "low"]);
```

资料来源：[src/core/frontmatter.ts:39-40]()

### 整理优先级

用于标记草稿页面的整理优先级，帮助人类注意力分配：

```typescript
export const CurationPriority = z.enum(["high", "medium", "low"]);
```

资料来源：[src/core/frontmatter.ts:48-49]()

## 维基与家族体系

### Wiki 结构

Stoa 使用多 Wiki 架构，每个 Wiki 存储在 `vaultPath/wikis/<wiki>/` 目录下。

### 家族解析顺序

`src/core/family.ts` 定义了家族 (family) 解析的优先级：

1. 显式 `familyArg` 参数
2. MCP CLI 参数 `--default-family`
3. `vaultPath/.active-family` 文件
4. `null` → 回退到单 Wiki 解析

```typescript
export function resolveFamily(
  ctx: FamilyResolveCtx,
  familyArg?: string,
  wikiArg?: string,
  knownWikis?: Record<string, { family?: string | null }>
): string | null
```

资料来源：[src/core/family.ts:38-58]()

### Wiki 与家族校验

当同时提供 `familyArg` 和 `wikiArg` 时，系统会校验 Wiki 所属家族是否匹配：

```typescript
if (wikiFamily !== familyArg) {
  throw new FamilyMismatchError(
    `wiki '${wikiArg}' has family '${wikiFamily ?? "(none)"}' which does not match requested family '${familyArg}'`
  );
}
```

资料来源：[src/core/family.ts:47-51]()

## Wiki 链接系统

### Wikilink 格式

Wiki 链接采用标准化格式：

```
[[wikis/<wiki>/<type>/<id>(|alias)?]]
```

例如：`[[wikis/_meta/concepts/concept-trust-gradient-axes]]`

### Wikilink 提取器

`src/core/wikilinks.ts` 提供了结构化的链接引用接口：

```typescript
export interface WikilinkRef {
  raw: string;
  wiki: string;
  type: string;
  id: string;
  alias?: string;
  source: "body" | "frontmatter";
}
```

资料来源：[src/core/wikilinks.ts:22-29]()

### 代码块感知

Wikilink 提取器具有代码块感知能力：

- 顶层 fenced 代码块 (` ``` `) 内的链接会被跳过
- 缩进代码块（如列表项内的 4 空格缩进）**不会**被剥离
- 内联单反引号代码 span **不会**被剥离

资料来源：[src/core/wikilinks.ts:24-34]()

### Wikilink 职责分离

- **提取职责** (`wikilinks.ts`)：仅提取结构化链接引用
- **完整性检查** (`lint-checks/cross-wiki-link-broken.ts`)：检查目标页面是否存在

资料来源：[src/core/wikilinks.ts:14-16]()

## 页面索引与查询

### VaultIndex 结构

索引文件 `_index/pages.json` 存储所有页面的元数据：

```typescript
interface VaultIndex {
  pages: IndexedPage[];
  wikis: IndexedWiki[];
}
```

资料来源：[src/core/index.ts:1-50]()

### 页面查询

使用 `queryPages` 函数进行多条件过滤：

```typescript
export function queryPages(
  idx: VaultIndex,
  f: PageFilter
): IndexedPage[]
```

支持的过滤条件：

| 过滤器字段 | 说明 |
|-----------|------|
| `wiki` | Wiki 名称精确匹配 |
| `wikis` | Wiki 名称集合 |
| `type` | 页面类型精确匹配 |
| `channel` | 频道名称精确匹配 |
| `status` | 页面状态精确匹配 |
| `layer` | `"knowledge"` 或 `"execution"` 或 `"all"` |

资料来源：[src/core/index.ts:80-95]()

### 全文搜索

`upsertTokenize` 函数使用 Porter Stemmer 进行词干提取和停用词过滤：

```typescript
const UPSERT_STOP_WORDS = new Set([
  "the","and","of","a","an","in","to","is","for","on",
  "with","as","at","by","or","be","this","that","it",
  "from","are","was","were","not","but","if"
]);
```

资料来源：[src/core/index.ts:65-67]()

## 页面读写操作

### 读取页面

`readPage` 函数根据 ID 解析页面路径：

```typescript
export function readPage(
  vaultPath: string,
  wiki: string,
  id: string
): ReadPageResult
```

路径解析顺序：
1. `wikis/<wiki>/<type>/<id>.md` (按类型遍历)
2. `map-<wiki>.md` 或 `map.md`

资料来源：[src/core/pages.ts:40-80]()

### 写入页面

```typescript
export interface WritePageInput {
  id: string;
  type: NoteType;
  wiki: string;
  frontmatter: Record<string, any>;
  body: string;
  expectedUpdated?: string;  // 乐观锁
}

export function writePage(
  vaultPath: string,
  input: WritePageInput
): WritePageResult
```

**乐观锁机制**：若提供 `expectedUpdated`，系统会验证现有文件的 updated 时间戳，防止并发覆盖。

资料来源：[src/core/pages.ts:82-100]()

## 频道系统

### 频道日志

频道 (channel) 用于聚合 `journal` 类型页面的活动摘要：

```typescript
interface ChannelSummary {
  name: string;
  wiki: string;
  lastEntry: ChannelEntry | null;
  count24h: number;
}
```

资料来源：[src/core/channel.ts:20-24]()

### 频道条目

```typescript
interface ChannelEntry {
  id: string;
  channel: string;
  wiki: string;
  author: string;
  ts: string;
  excerpt: string;  // 前 240 字符
  pageId: string;
}
```

资料来源：[src/core/channel.ts:26-33]()

## 综合页面 (Synthesis)

### Synthesis 创建

`synthesize` 命令生成综合页面：

```typescript
const fm: Record<string, any> = {
  id,
  title: `${input.topic} — synthesis`,
  type: "synthesis",
  wiki,
  status: "draft",
  created: today,
  updated: today,
  summary: `Synthesis of ${inputIds.length} pages on "${input.topic}".`,
  tags: [],
  last_compiled: today,
  sources: inputIds.map(i => `[[wikis/${wiki}/${typeFolderForId(i)}/${i}]]`)
};
```

资料来源：[src/core/synthesize.ts:60-75]()

### Synthesis 陈旧度检测

`detectSynthesisStaleness` 函数计算页面"过时"程度：

```typescript
if (lastCompiled) {
  const compiledMs = new Date(lastCompiled).getTime();
  lagDays = Math.floor((now - compiledMs) / MS_PER_DAY);
}
```

资料来源：[src/core/syntheses.ts:55-58]()

### Synthesis 债务检测

当同标签的硬知识页面聚类缺少对应的综合页面时，触发警告：

```typescript
export const DEFAULT_MIN_CLUSTER_SIZE = 3;

const HARD_KNOWLEDGE_TYPES = new Set([
  "concept", "decision", "spec"
]);
```

资料来源：[src/core/synthesize.ts:30-40]()

## 标记渲染系统

### 托管区域契约

Marker 系统用于在文档中维护"托管区域"：

- **起始标记**: `<!-- markerName:start (rendered: YYYY-MM-DD, half-life: Nd) -->`
- **结束标记**: `<!-- markerName:end -->`
- **幂等性**: 相同输入产生字节级相同的输出

```typescript
export interface MarkerOptions {
  renderedDate?: string;   // ISO 日期
  halfLifeDays?: number;   // 半衰期（天）
}
```

资料来源：[src/core/marker-render.ts:20-24]()

### 使用场景

- **Claims 汇总** (`synthesize`)
- **技能/代理文档补丁** (`sync-skills`, `bootstrap-repo`)

资料来源：[src/core/marker-render.ts:6-10]()

## 状态缓存

`StateCache` 提供简单的内存状态缓存：

```typescript
export class StateCache {
  private states = new Map<string, unknown>();

  private key(source: string, wiki: string, id: string): string {
    return `${source}:${wiki}:${id}`;
  }

  get<T>(source: string, wiki: string, id: string): T | undefined;
  set<T>(source: string, wiki: string, id: string, state: T): void;
  has(source: string, wiki: string, id: string): boolean;
  size(): number;
}
```

资料来源：[src/core/eventbus/state-cache.ts:1-25]()

### MCP 预热机制

`walkInitablePaths` 函数在接收变更事件前预热状态缓存：

```typescript
function walkInitablePaths(vaultPath: string): string[] {
  // 遍历 wikis/ 目录，收集所有 .md 文件路径
}
```

资料来源：[src/core/stdio.ts:50-75]()

## 命名规范

### ID 格式

| 类型 | ID 格式要求 |
|------|-------------|
| 普通页面 | 小写字母、数字、连字符 `^[a-z0-9-]+$` |
| Channel | 小写 kebab-case `^[a-z0-9]+(-[a-z0-9]+)*$` |
| 日期 | ISO 格式 `^\d{4}-\d{2}-\d{2}$` |

资料来源：[src/core/frontmatter.ts:41-44]()

## 架构总览

```mermaid
graph TD
    subgraph "MCP 接口层"
        STDIO[STDIO 传输]
        MCP[MCP 服务器]
    end

    subgraph "核心处理层"
        IDX[索引系统]
        QUERY[查询引擎]
        LINT[Lint 检查]
        SYNC[同步引擎]
    end

    subgraph "存储层"
        PAGES[Pages 读写]
        FRONT[Frontmatter 解析]
        WIKI[Wikilinks]
        CHAN[Channel]
    end

    subgraph "文件系统"
        VAULT[Vault 目录]
        WIKIS[wikis/ 目录]
        INDEX[_index/ 目录]
    end

    STDIO --> MCP
    MCP --> IDX
    IDX --> QUERY
    IDX --> LINT
    SYNC --> PAGES
    PAGES --> FRONT
    PAGES --> WIKI
    IDX --> CHAN
    QUERY --> INDEX
    IDX --> VAULT
    VAULT --> WIKIS
    IDX --> INDEX
```

## 术语表

| 术语 | 定义 |
|------|------|
| **Vault** | 根目录下的笔记库，包含 wikis/ 和 _index/ |
| **Wiki** | 某个主题领域的页面集合，位于 `wikis/<wiki>/` |
| **Family** | Wiki 的分组，用于批量操作 |
| **Synthesis** | 综合页面，聚合多个同标签页面的内容 |
| **Hard Knowledge** | 核心知识类型 (concept, decision, spec) |
| **Soft Knowledge** | 非核心类型 (guide, source, idea, question) |
| **Marker** | 托管区域的边界标记 |
| **Channel** | 聚合日志条目的频道 |

---

<a id='architecture'></a>

## 系统架构

### 相关页面

相关主题：[传输层实现](#transport), [事件总线系统](#eventbus), [项目概述](#overview)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/core/index.ts](https://github.com/BrettNye/stoa/blob/main/src/core/index.ts)
- [src/core/start.ts](https://github.com/BrettNye/stoa/blob/main/src/core/start.ts)
- [src/core/pages.ts](https://github.com/BrettNye/stoa/blob/main/src/core/pages.ts)
- [src/core/synthesize.ts](https://github.com/BrettNye/stoa/blob/main/src/core/synthesize.ts)
- [src/core/family.ts](https://github.com/BrettNye/stoa/blob/main/src/core/family.ts)
- [src/core/lint.ts](https://github.com/BrettNye/stoa/blob/main/src/core/lint.ts)
- [src/core/frontmatter.ts](https://github.com/BrettNye/stoa/blob/main/src/core/frontmatter.ts)
- [src/transport/stdio.ts](https://github.com/BrettNye/stoa/blob/main/src/transport/stdio.ts)
- [src/core/skills-platform.ts](https://github.com/BrettNye/stoa/blob/main/src/core/skills-platform.ts)
- [src/core/rewrite-links.ts](https://github.com/BrettNye/stoa/blob/main/src/core/rewrite-links.ts)
</details>

# 系统架构

## 概述

Stoa 是一个基于 Model Context Protocol (MCP) 的知识库管理系统，通过 STDIO 传输层与 LLM 代理进行通信。其核心功能围绕**页面索引**、**合成（Synthesis）管理**、**代码检查（Lint）** 和**技能平台**四大模块展开。系统采用 vault 结构的 Markdown 文件存储，页面之间通过 wikilink 互相引用，形成一个自包含的知识图谱。资料来源：[src/transport/stdio.ts:30-35]()

## 核心设计理念

Stoa 采用单职责原则设计，各模块职责明确划分：

| 模块 | 职责 | 核心文件 |
|------|------|----------|
| 索引系统 | 页面元数据提取、全文搜索、token 管理 | `src/core/index.ts` |
| 页面操作 | 页面读写、路径解析、版本控制 | `src/core/pages.ts` |
| 合成引擎 | 多页面聚合、摘要生成、来源追踪 | `src/core/synthesize.ts` |
| Lint 系统 | 规则检查、诊断报告、错误修复 | `src/core/lint.ts` |
| 技能平台 | 技能部署、漂移检测、版本管理 | `src/core/skills-platform.ts` |
| 家族解析 | 多 wiki 聚合、家族范围查询 | `src/core/family.ts` |

资料来源：[src/core/index.ts:1-50]()

## 系统层次架构

```mermaid
graph TD
    subgraph 传输层["传输层 (Transport)"]
        STDIO[STDIO Server Transport]
    end
    
    subgraph 服务层["服务层 (Service)"]
        MCP[MCP Server]
        Tools[Tools Layer]
    end
    
    subgraph 核心业务["核心业务 (Core)"]
        Index[索引系统]
        Pages[页面管理]
        Synthesize[合成引擎]
        Lint[代码检查]
        Skills[技能平台]
        Family[家族解析]
    end
    
    subgraph 数据层["数据层 (Data)"]
        Vault[Vault 存储]
        IndexFiles[_index 索引文件]
        Frontmatter[Frontmatter 元数据]
    end
    
    STDIO --> MCP
    MCP --> Tools
    Tools --> Index
    Tools --> Pages
    Tools --> Synthesize
    Tools --> Lint
    Tools --> Skills
    Tools --> Family
    
    Index --> IndexFiles
    Pages --> Vault
    Synthesize --> Index
    Lint --> Index
```

## 索引系统

### 索引数据结构

系统维护多个索引文件用于快速查询：

```mermaid
graph LR
    subgraph _index["_index/ 目录"]
        PagesIdx[_index/pages.json]
        TokensIdx[_index/tokens.json]
        LinksIdx[_index/links.json]
        WikisIdx[_index/wikis.json]
        ProfilesIdx[_index/profiles.json]
    end
    
    subgraph 源数据["Vault 源文件"]
        Markdown[*.md 文件]
        Frontmatter[Frontmatter]
    end
    
    Markdown -->|解析| Frontmatter
    Frontmatter -->|提取| PagesIdx
    Frontmatter -->|分词| TokensIdx
    Frontmatter -->|链接提取| LinksIdx
    WikisIdx -->|Wiki 配置| ProfilesIdx
```

索引系统通过 `VaultIndex` 接口提供统一的数据访问：

```typescript
export interface VaultIndex {
  pages: IndexedPage[];
  wikis: IndexedWiki[];
  profiles: IndexedProfile[];
  links: IndexedLink[];
  tokens: Record<string, string[]>;
}
```

资料来源：[src/core/index.ts:1-30]()

### 页面类型体系

Stoa 定义了严格的页面类型系统：

| 类型 | 说明 | 文件命名规范 |
|------|------|-------------|
| `concept` | 概念页面 | `concept-<slug>.md` |
| `decision` | 决策记录 | `decision-YYYY-MM-DD-<slug>.md` |
| `guide` | 操作指南 | `guide-<slug>.md` |
| `source` | 外部引用 | `source-<slug>.md` |
| `idea` | 想法记录 | `idea-<slug>.md` |
| `question` | 问题记录 | `question-<slug>.md` |
| `journal` | 日志条目 | `journal-YYYY-MM-DD-HHMM-<slug>.md` |
| `move` | 技能移动 | `move-<slug>/SKILL.md` |
| `map` | 地图页面 | `map.md` (固定命名) |
| `synthesis` | 合成页面 | 自动生成 |

资料来源：[src/core/ids.ts:1-25]()

### 搜索与查询

系统支持多维度查询过滤：

```typescript
export interface PageFilter {
  wiki?: string;
  type?: NoteType;
  channel?: string;
  status?: PageStatus;
  layer?: "knowledge" | "execution" | "all";
}
```

全文搜索使用 Porter Stemmer 算法进行词干提取，支持停用词过滤：

```typescript
function upsertTokenize(text: string): string[] {
  return text.toLowerCase()
    .replace(/[^a-z0-9\s]/g, " ")
    .split(/\s+/)
    .filter(t => t.length > 1 && !UPSERT_STOP_WORDS.has(t))
    .map(t => upsertStemmer.stem(t));
}
```

资料来源：[src/core/index.ts:35-50]()

## 页面管理系统

### 页面读写流程

```mermaid
graph TD
    A[请求读写页面] --> B{页面是否存在}
    B -->|不存在| C[新建页面]
    B -->|存在| D{是否有 expectedUpdated}
    D -->|有| E[乐观锁检查]
    E -->|版本匹配| F[写入文件]
    E -->|版本不匹配| G[抛出错误]
    D -->|无| F
    C --> H[生成路径]
    F --> I[更新索引]
    H --> I
```

### 页面路径解析

路径生成遵循以下规则：

| 页面类型 | 路径模板 |
|----------|----------|
| 普通页面 | `wikis/{wiki}/{type}/{id}.md` |
| 地图页面 | `wikis/{wiki}/map.md` |
| 技能移动 | `wikis/_agents/moves/{id}/SKILL.md` |
| 技能档案 | `wikis/_agents/profiles/{id}.md` |

资料来源：[src/core/pages.ts:1-60]()

## Frontmatter 验证

### 验证模式

系统使用 Zod 进行运行时验证：

```typescript
const draftSchema = z.object({
  id: z.string().regex(/^[a-z0-9-]+$/),
  title: z.string().min(1),
  type: NoteType,
  created: z.string().regex(ISO_DATE),
  channel: z.string().regex(KEBAB).optional(),
});

export const PageStatus = z.enum([
  "draft", "active", "accepted", "superseded", "archived"
]);

export const Confidence = z.enum(["high", "medium", "low"]);

export const CurationPriority = z.enum(["high", "medium", "low"]);
```

资料来源：[src/core/frontmatter.ts:1-50]()

### 状态流转

| 状态 | 说明 | 允许的转换 |
|------|------|------------|
| `draft` | 草稿状态 | `active` |
| `active` | 活跃状态 | `accepted`, `archived` |
| `accepted` | 已接受 | `superseded`, `archived` |
| `superseded` | 已废弃 | 无 |
| `archived` | 归档 | 无 |

## 合成引擎

### 合成类型

系统支持两种合成模式：

| 模式 | 说明 | 生成条件 |
|------|------|----------|
| `topic` | 主题合成 | 按标签聚合相关页面 |
| `memory` | 记忆合成 | 按代理聚合其 authored 页面 |

### 合成数据结构

```mermaid
graph TD
    subgraph 合成输入["合成输入"]
        Topic[Topic 标签]
        Tags[多个 Tag]
        Pages[源页面列表]
    end
    
    subgraph 合成过程["合成过程"]
        Extract[提取引用]
        Generate[生成摘要]
        Render[渲染标记区域]
    end
    
    subgraph 合成输出["合成输出"]
        Synthesis[Synthesis 页面]
        Sources[Sources 列表]
        Markers[标记区域]
    end
    
    Topic --> Extract
    Tags --> Extract
    Pages --> Extract
    Extract --> Generate
    Generate --> Render
    Render --> Synthesis
```

合成页面的 frontmatter 结构：

```yaml
id: <auto-generated>
title: "{topic} — synthesis"
type: synthesis
wiki: <target-wiki>
status: draft
created: <today>
updated: <today>
summary: "Synthesis of {count} pages on \"{topic}\"."
tags: [<tags>]
last_compiled: <today>
sources: [wikilinks to source pages]
```

资料来源：[src/core/synthesize.ts:1-80]()

### 合成陈旧度检测

系统可检测长时间未重新编译的合成页面：

```typescript
export interface SynthesisStaleness {
  id: string;
  wiki: string;
  lag_days: number | null;
  last_compiled: string | null;
}
```

陈旧度计算基于 `last_compiled` 字段与当前时间的差值：

```typescript
if (lastCompiled) {
  const compiledMs = new Date(lastCompiled).getTime();
  lagDays = Math.floor((now - compiledMs) / MS_PER_DAY);
}
```

资料来源：[src/core/syntheses.ts:1-60]()

## Lint 检查系统

### 检查规则体系

```mermaid
graph LR
    subgraph 规则类型["规则分类"]
        Error[Error 级规则]
        Warning[Warning 级规则]
        Info[Info 级规则]
    end
    
    subgraph 检查范围["检查范围"]
        Frontmatter[Frontmatter 检查]
        Content[内容检查]
        Filename[文件名检查]
        Links[链接检查]
        CrossWiki[跨 Wiki 检查]
    end
    
    Frontmatter -->|验证| Error
    Content -->|验证| Warning
    Filename -->|验证| Warning
    Links -->|验证| Info
```

### 核心检查规则

| 规则代码 | 严重级别 | 说明 |
|----------|----------|------|
| `FILENAME_ID_MISMATCH` | warning | 文件名与 ID 不匹配 |
| `BAD_CHANNEL_FORMAT` | warning | Channel 格式非法（需 kebab-case） |
| `CLAIM_WITH_NO_SCOPE` | warn | Claim 无作用域定义 |
| `SYNTHESIS_DEBT` | info | 存在未合成的知识集群 |
| `SNIPPET_NO_IMPLEMENTATION` | warning | 代码片段缺少实现引用 |
| `CROSS_WIKI_LINK_BROKEN` | error | 跨 Wiki 链接目标不存在 |
| `MISSING_CURATION_PRIORITY` | info | Agent 创作的草稿缺少整理优先级 |

资料来源：[src/core/lint.ts:1-100]()

### 特定 Wiki 检查

针对 `_agents` wiki 有专门的检查逻辑：

- **Profile 检查**：验证 profile 页面存在且格式正确
- **Move 检查**：验证 move 目录结构符合规范（需包含 `SKILL.md`）
- **别名漂移检查**（ALIAS_DRIFT）：检测 agent 别名与实际页面的不一致

## 技能平台

### 技能部署架构

```mermaid
graph TD
    subgraph 源端["Vault 源端"]
        Canonical[Canonical SKILL.md]
        MoveDir[move-{id} 目录]
    end
    
    subgraph 部署端["Deployment 端"]
        DeployDir[部署目录]
        Deployed[Deployed SKILL.md]
    end
    
    subgraph 检测机制["漂移检测"]
        Hash1[源文件哈希]
        Hash2[部署文件哈希]
        Compare[比较结果]
    end
    
    Canonical --> Hash1
    Deployed --> Hash2
    Hash1 --> Compare
    Hash2 --> Compare
    Compare -->|匹配| OK[无需更新]
    Compare -->|不匹配| Drift[报告漂移]
    Compare -->|缺失| Missing[报告缺失]
```

### 漂移报告类型

| 类型 | 说明 | 触发条件 |
|------|------|----------|
| `missing` | 部署端缺失 | 部署目录中无对应 SKILL.md |
| `hash-mismatch` | 哈希不匹配 | 源文件与部署文件内容不一致 |

```typescript
export interface DriftReport {
  move_id: string;
  kind: "missing" | "hash-mismatch";
  actual_hash: string | undefined;
}
```

资料来源：[src/core/skills-platform.ts:1-60]()

## 家族解析系统

### 家族解析优先级

系统按以下顺序解析家族范围：

```mermaid
graph TD
    A{是否有显式 family 参数?} -->|是| B[使用显式参数]
    A -->|否| C{是否有 defaultFamily?}
    C -->|是| D[使用 defaultFamily]
    C -->|否| E{是否有 .active-family 文件?}
    E -->|是| F[使用文件内容]
    E -->|否| G[返回 null, 单 Wiki 解析]
```

### 家族不匹配检测

当同时提供 `family` 和 `wiki` 参数时，系统会验证一致性：

```typescript
if (wikiFamily !== familyArg) {
  throw new FamilyMismatchError(
    `wiki '${wikiArg}' has family '${wikiFamily}' which does not match requested family '${familyArg}'`
  );
}
```

资料来源：[src/core/family.ts:1-50]()

## Wikilink 处理

### 链接格式规范

系统支持 vault-root 绝对路径格式的 wikilink：

```
[[wikis/{wiki}/{type}/{id}(|alias)?]]
```

### 链接提取规则

| 场景 | 是否提取 |
|------|----------|
| 顶层代码块内链接 | ❌ 跳过 |
| 嵌套代码块内链接 | ✅ 提取（v1.6 Phase 1 限制） |
| 单反引号行内代码 | ✅ 提取 |
| Frontmatter related 数组 | ✅ 提取 |

```typescript
export interface WikilinkRef {
  raw: string;
  wiki: string;
  type: string;
  id: string;
  alias?: string;
  source: "body" | "frontmatter";
}
```

资料来源：[src/core/wikilinks.ts:1-30]()

### 链接重写

支持批量前缀重写，保持语义一致性：

```typescript
export interface RewriteScope {
  body: boolean;
  frontmatter: boolean;
}

export interface PageRewrite {
  page_id: string;
  links_rewritten: number;
  new_body: string;
  new_related: string[] | undefined;
}
```

资料来源：[src/core/rewrite-links.ts:1-40]()

## 传输层

### STDIO 服务器

系统通过 STDIO 与 MCP 客户端通信：

```mermaid
graph LR
    subgraph MCP客户端["MCP Client (LLM Agent)"]
        JSONRPC[JSON-RPC Requests]
    end
    
    subgraph STDIO传输["STDIO Transport"]
        Stdin[stdin]
        Stdout[stdout]
        Stderr[stderr (日志)]
    end
    
    JSONRPC -->|输入| Stdin
    Stdout -->|输出| JSONRPC
    Stderr -->|诊断| Console
```

服务器初始化输出：

```
vault-mcp stdio server ready (vault={path}, default-wiki={wiki}, default-family={family})
```

资料来源：[src/transport/stdio.ts:1-60]()

## 配置与扩展

### 运行时配置

| 配置项 | 说明 | 来源 |
|--------|------|------|
| `vaultPath` | Vault 根目录路径 | 必需参数 |
| `defaultWiki` | 默认 Wiki 名称 | CLI 参数 |
| `defaultFamily` | 默认家族名称 | CLI 参数 |

### 扩展机制

- **Marker 渲染**：支持在文件中维护可编辑区域，工具与人类共同编辑
- **Zod 验证**：所有输入通过 schema 验证，确保类型安全
- **模块化检查**：Lint 规则以插件形式注册

## 关键技术栈

| 技术 | 用途 |
|------|------|
| TypeScript | 核心开发语言 |
| Zod | 运行时 schema 验证 |
| Node.js fs 模块 | 文件系统操作 |
| MCP SDK | 模型上下文协议实现 |
| Porter Stemmer | 全文搜索分词 |

## 总结

Stoa 的系统架构体现了以下设计原则：

1. **单一职责**：每个模块只负责一个明确的领域
2. **数据与逻辑分离**：索引系统与业务逻辑解耦
3. **可验证性**：通过 Zod schema 确保数据完整性
4. **幂等性**：所有写操作均可安全重试
5. **可观测性**：Lint 系统提供诊断能力

整个系统以 vault 目录为数据源，通过 MCP STDIO 传输层对外提供服务，形成了完整的知识管理闭环。

---

<a id='transport'></a>

## 传输层实现

### 相关页面

相关主题：[系统架构](#architecture)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/transport/stdio.ts](https://github.com/BrettNye/stoa/blob/main/src/transport/stdio.ts)
- [src/core/eventbus/state-cache.ts](https://github.com/BrettNye/stoa/blob/main/src/core/eventbus/state-cache.ts)
- [src/core/index.ts](https://github.com/BrettNye/stoa/blob/main/src/core/index.ts)
- [src/core/pages.ts](https://github.com/BrettNye/stoa/blob/main/src/core/pages.ts)
</details>

# 传输层实现

## 概述

Stoa 的传输层是 MCP（Model Context Protocol）服务器与外部客户端之间的通信桥梁，负责处理请求的接收、路由和响应返回。该层采用插件化架构，支持多种传输协议，当前实现包括 STDIO 标准输入输出传输和 HTTP 传输两种模式。

传输层的核心职责：

- 初始化并管理 MCP 服务器连接
- 预热状态缓存以支持增量事件处理
- 处理文件系统变化事件并维护索引一致性
- 提供可插拔的传输适配器接口

资料来源：[src/transport/stdio.ts:1-20]()

## 架构设计

### 传输类型概览

| 传输类型 | 用途 | 特点 |
|---------|------|------|
| STDIO | 本地 CLI 集成 | 进程间通信，低延迟，适合桌面工具 |
| HTTP | 远程服务 | 支持网络访问，适合服务器部署 |
| UI Routes | Web 界面 | 提供读写路由的 HTTP 端点 |

### 状态缓存机制

传输层依赖 `StateCache` 类实现内存状态缓存，用于在处理文件系统变更事件时提供基准状态对比。

```mermaid
graph TD
    A[文件系统变更] --> B{StateCache.has?}
    B -->|是| C[获取历史状态]
    B -->|否| D[返回 undefined]
    C --> E[计算差异]
    E --> F[触发增量更新]
    D --> G[处理初始事件]
```

**StateCache 关键方法：**

| 方法 | 签名 | 说明 |
|------|------|------|
| get | `<T>(source, wiki, id) => T \| undefined` | 按复合键获取缓存状态 |
| set | `<T>(source, wiki, id, state) => void` | 存储状态到缓存 |
| has | `(source, wiki, id) => boolean` | 检查键是否存在 |
| size | `() => number` | 返回缓存条目总数 |

复合键格式：`${source}:${wiki}:${id}`，确保不同来源、维基和页面的状态隔离。

资料来源：[src/core/eventbus/state-cache.ts:1-30]()

## STDIO 传输实现

### 工作流程

STDIO 传输是 Stoa 的主要本地通信方式，通过标准输入/输出流与 MCP 客户端交互。

```mermaid
sequenceDiagram
    participant Client as MCP 客户端
    participant Server as StdioServerTransport
    participant Cache as StateCache
    participant Vault as 文件系统

    Client->>Server: 连接建立
    Server->>Vault: walkInitablePaths()
    Server->>Cache: 预热缓存
    Note over Cache: 加载历史状态
    Client->>Server: 请求消息
    Server->>Cache: 查询/更新状态
    Server->>Client: 响应消息
```

### 缓存预热机制

在接收实时事件前，传输层会遍历 `wikis/` 目录结构，将现有文件路径加载到状态缓存中，确保第一次变更事件有有效的基准状态可供对比。

```typescript
function walkInitablePaths(vaultPath: string): string[] {
  const root = join(vaultPath, "wikis");
  if (!existsSync(root)) return [];
  
  let entries: Array<{
    isFile(): boolean;
    name: string;
    parentPath?: string;
    path?: string;
  }>;
  
  entries = readdirSync(root, { recursive: true, withFileTypes: true });
  
  const paths: string[] = [];
  for (const e of entries) {
    if (!e.isFile()) continue;
    if (!e.name.endsWith(".md")) continue;
    // ... 收集有效路径
  }
  return paths;
}
```

**预热流程说明：**

1. 定位 `wikis/` 根目录
2. 递归遍历目录结构获取所有条目
3. 过滤仅保留 `.md` 扩展名文件
4. 将有效路径存入缓存

资料来源：[src/transport/stdio.ts:25-55]()

### 类型兼容性处理

代码对 Node.js v22 的类型定义进行了显式处理：

```typescript
// @types/node 22 声明 Dirent<NonSharedBuffer> 作为默认值
// 'name' 在运行时是字符串，但类型表现为 buffer-like
let entries: Array<{
  isFile(): boolean;
  name: string;
  parentPath?: string;
  path?: string;
}>;

entries = readdirSync(root, { recursive: true, withFileTypes: true }) 
         as unknown as typeof entries;
```

此处的类型断言确保了运行时字符串类型与 TypeScript 类型定义的一致性。

资料来源：[src/transport/stdio.ts:40-45]()

## HTTP 传输

HTTP 传输层通过 Web 服务器方式暴露 MCP 服务，支持远程客户端连接。该传输方式适用于将 Stoa 作为独立服务部署的场景。

**HTTP 传输的核心能力：**

- 接受外部 HTTP 请求
- 路由到对应的工具处理器
- 返回 JSON 格式响应

> 注：详细 HTTP 传输实现请参考 `src/transport/http.ts`。

## UI 路由层

UI 路由层提供基于 HTTP 的读写接口，供 Web 前端或其他 HTTP 客户端使用。

| 路由文件 | 职责 |
|---------|------|
| `routes-read.ts` | 页面读取操作 |
| `routes-write.ts` | 页面写入操作 |
| `index.ts` | 路由聚合与中间件 |

> 注：详细路由实现请参考 `src/transport/ui/` 目录。

## 页面路径解析

传输层与核心页面模块协作，将页面 ID 解析为实际文件系统路径：

```typescript
export function pathForPage(
  vaultPath: string, 
  id: string, 
  type: NoteType, 
  wiki: string
): string {
  // 特殊页面类型处理
  if (id === `map-${wiki}` || id === "map") {
    return join(vaultPath, "wikis", wiki, "map.md");
  }
  // 标准页面路径
  return join(vaultPath, "wikis", wiki, typeFolderForId(id), `${id}.md`);
}
```

资料来源：[src/core/pages.ts:40-55]()

## 索引与缓存协同

传输层的事件处理依赖底层的写穿式索引更新机制：

```mermaid
graph LR
    A[变更事件] --> B[upsertPage]
    B --> C[解析 frontmatter]
    C --> D[更新 pages.json]
    D --> E[更新 tokens.json]
    E --> F[StateCache 同步]
```

索引更新是原子操作，保证了在并发访问下的数据一致性。

资料来源：[src/core/index.ts:80-100]()

## 配置参数

| 参数 | 来源 | 说明 |
|------|------|------|
| `vaultPath` | CLI `--vault=` 或 `STOA_VAULT_PATH` | 保险库根目录 |
| `defaultWiki` | CLI `--default-wiki=` | 默认维基名称 |
| `defaultFamily` | CLI `--default-family=` | 默认家族名称 |

服务器启动时会输出配置确认信息到 stderr：

```
vault-mcp stdio server ready (vault=/path/to/vault, default-wiki=<unset>, default-family=<unset>)
```

资料来源：[src/transport/stdio.ts:20-25]()

## 错误处理

传输层的错误处理策略：

| 场景 | 处理方式 |
|------|---------|
| 目录不存在 | 返回空数组 |
| 读取失败 | 吞没异常并返回空结果 |
| 文件损坏 | 交由调用方处理 |
| 状态缓存未命中 | 返回 undefined |

这种防御性编程确保了传输层在异常情况下的健壮性，不会因单个文件问题导致整个服务中断。

## 扩展传输类型

Stoa 的传输层设计支持添加新的传输适配器。实现新传输类型的步骤：

1. 实现传输类，实现 `connect` 方法
2. 注册传输处理器到 MCP 服务器
3. 在入口文件选择合适的传输类型
4. 添加对应的启动日志输出

当前支持的传输类型已覆盖本地集成（STDIO）和远程访问（HTTP）两种主要场景。

---

<a id='eventbus'></a>

## 事件总线系统

### 相关页面

相关主题：[系统架构](#architecture), [召回与检索系统](#recall-system)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/core/eventbus/bus.ts](https://github.com/BrettNye/stoa/blob/main/src/core/eventbus/bus.ts)
- [src/core/eventbus/match.ts](https://github.com/BrettNye/stoa/blob/main/src/core/eventbus/match.ts)
- [src/core/eventbus/registry.ts](https://github.com/BrettNye/stoa/blob/main/src/core/eventbus/registry.ts)
- [src/core/eventbus/event-deriver.ts](https://github.com/BrettNye/stoa/blob/main/src/core/eventbus/event-deriver.ts)
- [src/core/eventbus/handle-wait.ts](https://github.com/BrettNye/stoa/blob/main/src/core/eventbus/handle-wait.ts)
- [src/core/eventbus/types.ts](https://github.com/BrettNye/stoa/blob/main/src/core/eventbus/types.ts)
- [src/core/eventbus/matchers/task.ts](https://github.com/BrettNye/stoa/blob/main/src/core/eventbus/matchers/task.ts)
</details>

# 事件总线系统

## 概述

事件总线系统是 stoa 项目的核心基础设施之一，提供基于文件系统观察的发布-订阅事件处理机制。该系统使 MCP 工具能够以**阻塞等待**（push 原语）而非轮询的方式响应 vault 中的文件变更，实现了实时事件驱动的工具调用模式。

事件总线在以下场景中发挥关键作用：

- 任务状态变更检测（status/owner 变化）
- wiki 内容变更监听
- 通道（channel）消息通知
- 跨实例协调通信

资料来源：[src/core/eventbus/types.ts]()

## 核心架构

### 模块结构

事件总线系统由以下子模块组成：

| 模块 | 文件 | 职责 |
|------|------|------|
| 类型定义 | `types.ts` | 定义 `VaultEvent`、`VaultEventFilter`、事件派生器接口 |
| 事件总线 | `bus.ts` | 核心事件发布-订阅引擎，文件系统监视器集成 |
| 匹配器 | `match.ts` | 过滤器匹配逻辑，实现事件筛选条件 |
| 注册表 | `registry.ts` | 管理事件监听器订阅和取消订阅 |
| 事件派生器 | `event-deriver.ts` | 从原始文件事件派生语义化 vault 事件 |
| 等待处理 | `handle-wait.ts` | 实现 `wait-for` 系列阻塞原语 |
| 内置匹配器 | `matchers/task.ts` | 任务状态变更检测匹配器 |

```mermaid
graph TD
    subgraph "文件系统层"
        FS[文件系统观察者]
    end
    
    subgraph "事件总线核心"
        EB[EventBus]
        REG[Registry]
        DER[EventDeriver]
        MATCH[Matcher]
    end
    
    subgraph "等待原语"
        WF[wait-for]
        WFA[wait-for-any]
        WFL[wait-for-all]
        WFM[wait-for-many]
    end
    
    FS -->|原始文件变更| EB
    EB --> REG
    EB --> DER
    DER --> MATCH
    MATCH -->|过滤后事件| WF
    MATCH -->|过滤后事件| WFA
    MATCH -->|过滤后事件| WFL
    MATCH -->|过滤后事件| WFM
    
    REG -->|订阅管理| EB
```

资料
Error with Openai API: output new_sensitive (1027)

Please check that you have set the OPENAI_API_KEY environment variable with a valid API key.

---

<a id='recall-system'></a>

## 召回与检索系统

### 相关页面

相关主题：[Wiki管理](#wiki-management), [事件总线系统](#eventbus)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/core/index.ts](https://github.com/BrettNye/stoa/blob/main/src/core/index.ts) - 页面索引与查询核心逻辑
- [src/core/claim-render.ts](https://github.com/BrettNye/stoa/blob/main/src/core/claim-render.ts) - Claims 渲染与排序
- [src/core/synthesize.ts](https://github.com/BrettNye/stoa/blob/main/src/core/synthesize.ts) - 综合页面合成
- [src/core/syntheses.ts](https://github.com/BrettNye/stoa/blob/main/src/core/syntheses.ts) - 综合页面状态管理
- [src/core/channel.ts](https://github.com/BrettNye/stoa/blob/main/src/core/channel.ts) - 频道摘要与查询

> ⚠️ 以下文件在请求上下文中不可用，无法纳入本文档：
> - `src/core/recall.ts`
> - `src/core/claims-index.ts`
> - `src/core/recall-filter.ts`
> - `src/tools/recall.ts`
> - `src/tools/read.ts`
</details>

# 召回与检索系统

## 概述

召回与检索系统是 stoa 知识库系统的核心基础设施，负责从结构化索引中高效定位符合查询条件的页面、Claims 和综合文档。该系统采用**写穿透（Write-Through）索引更新**策略，确保索引数据与文件系统保持同步，同时将完整性检查（目标页面是否存在、Wiki 是否存在）的职责委托给上层消费者。

核心设计原则：

- **单一职责**：召回模块仅负责提取结构化链接引用，不进行完整性验证 资料来源：[src/core/wikilinks.ts:11-12](https://github.com/BrettNye/stoa/blob/main/src/core/wikilinks.ts#L11-L12)
- **幂等性**：重新渲染相同输入产生字节级相同的输出 资料来源：[src/core/marker-render.ts:19-21](https://github.com/BrettNye/stoa/blob/main/src/core/marker-render.ts#L19-L21)
- **分层架构**：索引管理层与工具层分离，索引层负责数据持久化，工具层负责业务逻辑编排

## 核心数据模型

### 索引页面结构（IndexedPage）

```typescript
interface IndexedPage {
  id: string;
  wiki: string;
  type: string;
  path?: string;
  channel?: string;
  status?: string;
  title?: string;
  tags?: string[];
  created?: string;    // ISO日期 YYYY-MM-DD
  updated?: string;     // ISO日期 YYYY-MM-DD
  last_validated?: string;
  confidence?: Confidence;
  authored_by?: string;
}
```

### VaultIndex 主索引结构

```typescript
interface VaultIndex {
  pages: IndexedPage[];
  wikis: IndexedWiki[];
  profiles: IndexedProfile[];
  links: LinkEdge[];
  tokens: TokenIndex;
}
```

## 页面查询系统

### queryPages 函数

`queryPages` 是页面查询的核心入口，支持多维度过滤 资料来源：[src/core/index.ts:40-52](https://github.com/BrettNye/stoa/blob/main/src/core/index.ts#L40-L52)：

```typescript
export function queryPages(idx: VaultIndex, f: PageFilter): IndexedPage[] {
  return idx.pages.filter(p => {
    if (f.wiki && wikiSet && !wikiSet.has(p.wiki)) return false;
    if (f.type && p.type !== f.type) return false;
    if (f.channel && p.channel !== f.channel) return false;
    if (f.status && p.status !== f.status) return false;
    if (f.layer && f.layer !== "all") {
      const set = f.layer === "knowledge" ? KNOWLEDGE_TYPES : EXECUTION_TYPES;
      if (!set.includes(p.type)) return false;
    }
    return true;
  });
}
```

### 查询过滤器参数

| 参数 | 类型 | 说明 |
|------|------|------|
| `wiki` | `string \| undefined` | 按 Wiki 名称过滤 |
| `type` | `string \| undefined` | 按页面类型过滤 |
| `channel` | `string \| undefined` | 按协调频道过滤 |
| `status` | `string \| undefined` | 按状态过滤（draft/active/accepted 等） |
| `layer` | `"knowledge" \| "execution" \| "all" \| undefined` | 按知识层过滤 |
| `id` | `string \| undefined` | 按页面 ID 精确匹配 |

### 页面类型分层

系统将页面类型划分为两个知识层：

| 知识层 | 包含类型 | 说明 |
|--------|----------|------|
| `KNOWLEDGE_TYPES` | concept, decision, spec, process, capability, domain, support | 持久化、可蒸馏的知识 |
| `EXECUTION_TYPES` | guide, source, idea, question | 执行层面的文档 |

> 注意：`guide`、`source`、`idea`、`question` 被排除在知识层之外，因为它们是程序性或外部引用性质，不符合"持久化、可蒸馏"知识的标准 资料来源：[src/core/lint-checks/synthesis-debt.ts:26-34](https://github.com/BrettNye/stoa/blob/main/src/core/lint-checks/synthesis-debt.ts#L26-L34)

## 索引更新机制

### 写穿透索引（Write-Through Index）

`upsertPage` 函数负责单页面的索引更新：

```typescript
export function upsertPage(pagePath: string): void {
  // 读取文件 → 解析 frontmatter → 更新 pages.json 和 tokens.json
  // 注意：不重新生成 links.json, wikis.json, profiles.json
}
```

该函数执行以下操作：

1. 读取页面文件内容
2. 解析 frontmatter 元数据
3. 向 `_index/pages.json` 添加/替换条目
4. 向 `_index/tokens.json` 添加分词数据
5. **不重新生成** `_index/{links,wikis,profiles}.json`（这些是聚合文件）

> 聚合索引文件的重新生成由 `vault.reindex` 工具单独处理 资料来源：[src/core/index.ts:78-82](https://github.com/BrettNye/stoa/blob/main/src/core/index.ts#L78-L82)

### 分词与停用词过滤

```typescript
const UPSERT_STOP_WORDS = new Set([
  "the","and","of","a","an","in","to","is","for","on","with","as","at","by","or","be",
  "this","that","it","from","are","was","were","not","but","if"
]);

function upsertTokenize(text: string): string[] {
  return text.toLowerCase()
    .replace(/[^a-z0-9\s]/g, " ")
    .split(/\s+/)
    .filter(t => t.length > 1 && !UPSERT_STOP_WORDS.has(t))
    .map(t => upsertStemmer.stem(t)); // 使用 Porter Stemmer
}
```

| 处理步骤 | 说明 |
|----------|------|
| 转小写 | 统一大小写 |
| 去除非字母数字字符 | 保留单词边界 |
| 停用词过滤 | 移除高频无意义词 |
| Porter 词干提取 | 词形归一化 |

## Claims 检索与排序

### 有效置信度计算

Claims 采用**半衰期衰减模型**计算有效置信度 资料来源：[src/core/claim-render.ts:52-62](https://github.com/BrettNye/stoa/blob/main/src/core/claim-render.ts#L52-L62)：

```typescript
function effectiveConfidence(
  claim: { confidence: Confidence; last_validated?: string; status?: string },
  today: Date,
  config: ClaimsConfig,
): number {
  const base = BASE_CONFIDENCE[claim.confidence ?? "medium"];
  const ageMs = today.getTime() - new Date(claim.last_validated ?? today).getTime();
  const halfLives = ageMs / MS_PER_DAY / config.half_life_days;
  const decayed = base * Math.pow(0.5, halfLives);
  const eff = Math.max(decayed, config.effective_floor);
  
  // 被撤回的 Claims 有效置信度归零
  if (claim.status === "retracted") return 0;
  
  return eff;
}
```

### 置信度基础值

| 置信度级别 | 基础值 | 半衰期衰减后最小值 |
|------------|--------|-------------------|
| `high` | 0.9 | 由 `effective_floor` 决定 |
| `medium` | 0.6 | 由 `effective_floor` 决定 |
| `low` | 0.3 | 由 `effective_floor` 决定 |

### Claims 排序策略

排序得分公式：

```
score(claim) = effective_confidence + (profile_match ? 0.1 : 0)
```

| 排序因素 | 说明 |
|----------|------|
| 有效置信度 | 半衰期衰减后的当前置信度 |
| Profile 加成 | 当部署 Profile ID 在 claim 的 profile 数组中时加 0.1 |

## 综合文档检索

### 综合文档查询

`syntheses.ts` 提供综合文档的查询与陈旧度分析 资料来源：[src/core/syntheses.ts:40-75](https://github.com/BrettNye/stoa/blob/main/src/core/syntheses.ts#L40-L75)：

```typescript
// 过滤出 synthesis 类型的页面
const syntheses = allPages.filter(p => {
  if (p.type !== "synthesis") return false;
  if (opts.wiki && p.wiki !== opts.wiki) return false;
  return true;
});

// 从文件 frontmatter 读取 last_compiled
if (synthPath && existsSync(synthPath)) {
  const raw = readFileSync(synthPath, "utf8");
  const { frontmatter } = parseFrontmatter(raw);
  const rawLc = frontmatter.last_compiled;
  // 计算距今天数
  lagDays = Math.floor((now - compiledMs) / MS_PER_DAY);
}
```

### 综合文档陈旧度指标

| 指标 | 说明 |
|------|------|
| `last_compiled` | 上次编译日期，来自 frontmatter |
| `lag_days` | 距今天数 |
| `staleness` | 可配置的陈旧度阈值（默认 30 天） |

## 频道摘要检索

`channel.ts` 提供协调频道的实时摘要 资料来源：[src/core/channel.ts:24-45](https://github.com/BrettNye/stoa/blob/main/src/core/channel.ts#L24-L45)：

```typescript
export function channelTail(vaultPath: string, opts: ChannelTailOptions): ChannelSummary[] {
  // 查询所有 journal 类型页面
  const pages = queryPages(idx, { type: "journal", wiki: opts.wiki });
  
  // 按 wiki::channel 聚合
  const byKey = new Map<string, ChannelSummary>();
  for (const p of pages) {
    const key = `${p.wiki}::${p.channel}`;
    // 统计 24 小时内的条目数
    if (p.created >= sinceIso) summary.count24h++;
    // 记录最新条目
    if (!summary.lastEntry || p.created > summary.lastEntry.ts) {
      // 读取文件获取摘要和作者
      excerpt = body.trim().slice(0, 240);
      author = String(fm.author ?? "unknown");
    }
  }
}
```

### 频道摘要数据结构

| 字段 | 类型 | 说明 |
|------|------|------|
| `name` | `string` | 频道名称 |
| `wiki` | `string` | 所属 Wiki |
| `count24h` | `number` | 24 小时内条目数 |
| `lastEntry` | `ChannelEntry \| null` | 最新条目详情 |

## 检索流程图

```mermaid
graph TD
    A[用户查询请求] --> B{查询类型}
    B -->|页面查询| C[queryPages]
    B -->|Claims 查询| D[查询 + 置信度计算]
    B -->|综合文档| E[过滤 synthesis 类型]
    B -->|频道摘要| F[channelTail 聚合]
    
    C --> G[应用过滤器]
    D --> H[计算 effective_confidence]
    E --> I[读取 last_compiled]
    F --> J[统计 count24h]
    
    G --> K[返回 IndexedPage[]]
    H --> L[按 score 排序]
    I --> M[计算 lag_days]
    J --> N[返回 ChannelSummary[]]
    
    L --> O[返回排序后 Claims]
    M --> P[返回 SynthesisStaleness[]]
```

## 架构设计要点

### 索引与文件系统同步

| 操作 | 索引更新范围 |
|------|--------------|
| `upsertPage` | `pages.json` + `tokens.json` |
| `vault.reindex` | 全部索引文件 |
| 文件删除 | 需手动触发重建 |

### Wiki 解析器

```typescript
export function queryWikis(idx: VaultIndex): IndexedWiki[] {
  return idx.wikis;
}
```

### 过滤器组合

页面过滤器支持**多维度组合过滤**，各维度之间为 AND 关系：

```mermaid
graph LR
    A[Wiki 过滤] -->|AND| Z[最终结果]
    B[Type 过滤] -->|AND| Z
    C[Channel 过滤] -->|AND| Z
    D[Status 过滤] -->|AND| Z
    E[Layer 过滤] -->|AND| Z
```

## 配置参数

### Claims 渲染配置

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `half_life_days` | `number` | 30 | 置信度半衰期（天） |
| `effective_floor` | `number` | 0.1 | 有效置信度下限 |

### 综合文档配置

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `min_lag_days` | `number \| null` | null | 最小陈旧天数阈值 |
| `stale_after_days` | `number` | 30 | 标记为陈旧的天数 |

## 相关工具

| 工具名称 | 功能 |
|----------|------|
| `vault.reindex` | 重新生成全部索引文件 |
| `vault.synthesize` | 编译或刷新综合页面 |
| `vault.channel-tail` | 拉取协调频道的最新条目 |
| `vault.recall` | 根据条件召回相关页面 |

---

*本文档基于 stoa 仓库的可用源码生成。部分检索系统核心文件（`recall.ts`、`claims-index.ts` 等）在当前上下文不可用，完整功能描述需待源码补充后更新。*

---

<a id='wiki-management'></a>

## Wiki管理

### 相关页面

相关主题：[召回与检索系统](#recall-system), [核心概念](#concepts)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/core/wikis.ts](https://github.com/BrettNye/stoa/blob/main/src/core/wikis.ts)
- [src/core/frontmatter.ts](https://github.com/BrettNye/stoa/blob/main/src/core/frontmatter.ts)
- [src/core/wikilinks.ts](https://github.com/BrettNye/stoa/blob/main/src/core/wikilinks.ts)
- [src/core/synthesize.ts](https://github.com/BrettNye/stoa/blob/main/src/core/synthesize.ts)
- [src/tools/new-wiki.ts](https://github.com/BrettNye/stoa/blob/main/src/tools/new-wiki.ts)
- [src/tools/set-active.ts](https://github.com/BrettNye/stoa/blob/main/src/tools/set-active.ts)
- [src/tools/synthesize.ts](https://github.com/BrettNye/stoa/blob/main/src/tools/synthesize.ts)
</details>

# Wiki管理

## 概述

Wiki管理是Stoa系统的核心功能之一，负责管理知识库中的wiki空间、页面组织、链接解析以及内容综合。Stoa采用vault-root结构，所有wiki内容位于`wikis/`目录下，每个wiki是独立的内容空间，支持多wiki架构和跨wiki引用。

Wiki管理的核心职责包括：

- 创建和配置新的wiki
- 管理wiki的活动状态和默认上下文
- 解析和验证wiki间的链接关系
- 驱动内容综合（synthesis）机制
- 维护wiki索引和元数据

资料来源：[README.md]()

---

## Wiki核心概念

### 架构分层

Stoa的知识库采用分层架构：

```mermaid
graph TD
    A["vault root"] --> B["wikis/"]
    B --> C["<wiki-name>/"]
    C --> D["concept/"]
    C --> E["decision/"]
    C --> E2["source/"]
    C --> E3["guide/"]
    C --> E4["journal/"]
    C --> E5["claim/"]
    C --> E6["synthesis/"]
    C --> E7["move/"]
    C --> F["map.md"]
    C --> G["index.md"]
    C --> H["_meta/"]
```

每个wiki包含多种页面类型，每种类型对应不同的知识处理模式。

### 页面类型体系

| 类型 | 说明 | 文件命名规则 |
|------|------|-------------|
| `concept` | 概念页面 | `concept-<slug>.md` |
| `decision` | 决策记录 | `decision-YYYY-MM-DD-<slug>.md` |
| `source` | 外部引用 | `source-<slug>.md` |
| `guide` | 操作指南 | `guide-<slug>.md` |
| `journal` | 日志条目 | `journal-YYYY-MM-DD-HHMM-<slug>.md` |
| `claim` | 断言声明 | `claim-<slug>.md` |
| `synthesis` | 综合页面 | `synthesis-<slug>.md` |
| `move` | 技能移动 | `move-<slug>/SKILL.md` |
| `map` | 地图页面 | `map.md` |

资料来源：[src/core/ids.ts]()

---

## Wiki创建与初始化

### newWiki函数

`newWiki`函数负责在vault中创建新的wiki空间，包含完整的目录结构和初始配置文件。

```typescript
function newWiki(
  vaultPath: string,
  opts: NewWikiOptions
): NewWikiResult
```

**参数说明：**

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `vaultPath` | `string` | 是 | vault根目录路径 |
| `opts.name` | `string` | 是 | wiki名称 |
| `opts.mode` | `WikiMode` | 是 | wiki模式：idea-map、project-doc、learning、mixed |
| `opts.scope` | `string` | 是 | wiki作用域描述 |

**返回值：**

```typescript
interface NewWikiResult {
  name: string;
  path: string;
  files_created: string[];
}
```

创建过程中会生成以下基础文件：

- `wikis/<name>/map.md` — wiki导航地图
- `wikis/<name>/index.md` — wiki首页
- `wikis/<name>/CLAUDE.md` — wiki级别的AI上下文配置
- `wikis/<name>/_meta/` — 元数据目录

资料来源：[src/tools/new-wiki.ts]()

### Wiki模式

Wiki支持四种创建模式，每种模式预设不同的内容结构和初始标签：

| 模式 | 用途 | 典型内容 |
|------|------|---------|
| `idea-map` | 头脑风暴和概念映射 | 大量concept页面 |
| `project-doc` | 项目文档管理 | guide、decision为主 |
| `learning` | 学习和知识积累 | source、concept交替 |
| `mixed` | 混合用途 | 均衡各类内容 |

资料来源：[src/core/wikis.ts]()

---

## 活动Wiki管理

### setActiveWiki机制

系统维护一个"活动wiki"的概念，作为命令执行的默认上下文。活动wiki的解析遵循优先级链：

```mermaid
graph LR
    A["explicit wikiArg"] --> B{"已知wiki?"}
    B -->|是| C["返回wikiArg"]
    B -->|否| D["抛出错误"]
    E["无explicit参数"] --> F{".active-family文件?"}
    F -->|存在| G["读取文件内容"]
    F -->|不存在| H["CLI --default-family"]
    H --> I{".active-family文件?"}
    I -->|存在| J["读取文件内容"]
    I -->|不存在| K["返回null - 单wiki解析"]
```

**解析优先级（高到低）：**

1. 显式传入的`wikiArg`参数
2. `ctx.defaultFamily` — CLI的`--default-family`参数
3. `<vaultPath>/.active-family`文件内容
4. `null` — 回退到单wiki解析模式

资料来源：[src/core/family.ts]()

### FamilyMismatchError

当显式传入的`family`和`wiki`参数不匹配时，系统抛出结构化错误：

```typescript
throw new FamilyMismatchError(
  `wiki '${wikiArg}' has family '${wikiFamily ?? "(none)"}' which does not match requested family '${familyArg}'`
);
```

这确保了多family场景下参数的一致性，防止静默的错误路由。

资料来源：[src/core/family.ts]()

---

## Wikilink链接系统

### 链接格式规范

Stoa使用`[[wikilink]]`语法进行wiki内和跨wiki引用。链接格式支持以下变体：

```
[[wikis/<wiki>/<type>/<id>]]
[[wikis/<wiki>/<type>/<id>|alias]]
```

**绝对形式（vault-root）：**
```
[[wikis/brett/concept/my-page]]
[[wikis/brett/concept/my-page|显示别名]]
```

资料来源：[src/core/wikilinks.ts]()

### WikilinkRef数据结构

```typescript
export interface WikilinkRef {
  raw: string;        // 原始链接文本
  wiki: string;       // 目标wiki名称
  type: string;       // 页面类型
  id: string;         // 页面ID
  alias?: string;     // 可选的显示别名
  source: "body" | "frontmatter";  // 链接来源位置
}
```

资料来源：[src/core/wikilinks.ts]()

### 链接提取规则

Wikilink提取器`extractWikilinks`具有以下行为特征：

| 特性 | 说明 |
|------|------|
| 代码块感知 | 顶层\`\`\`代码块内的链接被跳过 |
| 行首要求 | 代码块标记必须在一行的开头 |
| 内联代码 | 单反引号\`包裹的文本中的链接**不**被过滤 |
| 嵌套代码块 | 缩进内的代码块（如列表项内4空格缩进）**不**被处理 |

```typescript
// 示例：以下内容中
```
[[wikis/brett/concept/inside-code]]
```
这里 [[wikis/brett/concept/outside-code]] 会提取

// 提取结果：只包含 outside-code
```

资料来源：[src/core/wikilinks.ts]()

---

## 内容综合（Synthesis）

### Synthesis机制概述

Synthesis是Stoa的核心知识整合功能，用于将多个相关页面综合成一篇聚合文档。综合页面维护一个managed region，由marker边界限定。

```mermaid
graph TD
    A["输入：话题或agent"] --> B["查询匹配页面"]
    B --> C{"by_agent?"}
    C -->|是| D["过滤到特定agent"]
    C -->|否| E["按话题检索"]
    D --> F["生成Synthesis页面"]
    E --> F
    F --> G["写入marker区域"]
    G --> H["更新_index/syntheses.json"]
```

### Marker区域管理

Marker区域由HTML注释界定，支持幂等渲染：

```html
<!-- synthesis:start (rendered: 2025-01-15, half-life: 7d) -->
## 来源

- [[wikis/brett/concept/page-a]]
- [[wikis/brett/concept/page-b]]
<!-- synthesis:end -->
```

**Marker选项：**

| 选项 | 说明 |
|------|------|
| `renderedDate` | ISO日期YYYY-MM-DD，渲染时间戳 |
| `halfLifeDays` | 半衰期天数，用于缓存策略 |

重新渲染相同输入产生字节级一致输出，不同markerName的区域互不干扰。

资料来源：[src/core/marker-render.ts]()

### SynthesisFrontmatter

综合页面生成的frontmatter结构：

```typescript
const fm = {
  id,                    // 唯一标识符
  title,                 // 标题
  type: "synthesis",     // 固定类型
  wiki,                  // 所属wiki
  status: "draft",       // 初始状态
  created: today,
  updated: today,
  summary,               // 综合说明
  tags,                  // 标签数组
  last_compiled: today,  // 最后编译时间
  sources: [...]         // 来源页面wikilinks数组
};
```

对于agent memory类型的综合，还会包含`by_agent`和`scope: "memory"`字段。

资料来源：[src/core/synthesize.ts]()

---

## 索引与查询

### VaultIndex结构

Vault维护统一的索引结构支持高效查询：

```typescript
export interface VaultIndex {
  pages: IndexedPage[];
  wikis: IndexedWiki[];
  profiles: IndexedProfile[];
  tokens: Record<string, string[]>;
  links: Record<string, string[]>;
}
```

### Wiki查询

```typescript
export function queryWikis(idx: VaultIndex): IndexedWiki[]
```

返回所有已索引的wiki列表，每个IndexedWiki包含名称、路径、family归属等信息。

资料来源：[src/core/index.ts]()

---

## 工具命令参考

### vault.new-wiki

```bash
vault new-wiki <name> --mode <mode> --scope <scope>
```

**参数：**

| 参数 | 说明 |
|------|------|
| `name` | wiki名称 |
| `--mode` | 必须：idea-map\|project-doc\|learning\|mixed |
| `--scope` | 必须：作用域描述 |

**输出示例：**
```
created wiki: mywiki at wikis/mywiki (7 files)
```

资料来源：[src/cli/commands/new-wiki.ts]()

### vault.synthesize

创建或刷新综合页面：

```bash
vault synthesize --topic <topic> --wiki <wiki> [--by_agent <agent>]
```

**参数：**

| 参数 | 类型 | 说明 |
|------|------|------|
| `--topic` | string | 综合主题 |
| `--wiki` | string | 目标wiki |
| `--by_agent` | string | 可选：按agent过滤 |
| `--limit` | number | 候选页面数量限制（默认25） |

资料来源：[src/tools/synthesize.ts]()

### vault.set-active

设置当前活动的wiki上下文：

```bash
vault set-active <wiki>
```

该命令更新`.active-family`文件，后续命令默认使用该wiki作为上下文。

资料来源：[src/tools/set-active.ts]()

---

## 跨Wiki协作

### Family机制

Family是一组相关wiki的逻辑分组，支持跨wiki内容发现：

```typescript
export interface FamilyRollup {
  members: string[];      // wiki成员列表（已排序）
  total_pages: number;    // 总页面数
  modes_used: string[];   // 使用的模式类型（去重+排序）
}
```

### 频道系统

Wiki支持通过频道进行协调通信：

```typescript
interface ChannelSummary {
  name: string;
  wiki: string;
  lastEntry: ChannelEntry | null;
  count24h: number;  // 24小时内的条目数
}
```

`vault.channel-tail`命令可拉取最近频道条目，`vault.channel-post`用于发布到频道。

资料来源：[src/core/channel.ts]()

---

## 最佳实践

### Wiki创建建议

1. **选择合适的模式** — 根据内容性质选择`idea-map`、`project-doc`等模式
2. **设置清晰的scope** — scope描述帮助系统理解wiki的职责边界
3. **配置CLAUDE.md** — 在wiki根目录配置AI上下文，指导知识管理行为

### 链接使用规范

1. **优先使用绝对形式** — `[[wikis/wiki/type/id]]`形式跨上下文可移植
2. **避免代码块内链接** — 顶层代码块中的wikilink不会被解析
3. **使用alias增强可读性** — `[[target|描述文本]]`提供语义化展示

### Synthesis维护

1. **定期刷新** — 综合页面会记录`last_compiled`，建议周期性刷新以纳入新内容
2. **利用半衰期** — 设置合理的`halfLifeDays`平衡新鲜度和稳定性
3. **保护marker区域** — 手动编辑时避免修改marker注释边界

---

## 相关文档

- [页面管理](./页面管理.md)
- [链接系统](./链接系统.md)
- [Family机制](./Family机制.md)
- [Synthesis系统](./Synthesis系统.md)

---

<a id='task-coordination'></a>

## 任务协作系统

### 相关页面

相关主题：[事件总线系统](#eventbus)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/core/channel.ts](https://github.com/BrettNye/stoa/blob/main/src/core/channel.ts)
- [src/core/frontmatter.ts](https://github.com/BrettNye/stoa/blob/main/src/core/frontmatter.ts)
- [src/core/lint-checks/synthesis-debt.ts](https://github.com/BrettNye/stoa/blob/main/src/core/lint-checks/synthesis-debt.ts)
- [src/core/index.ts](https://github.com/BrettNye/stoa/blob/main/src/core/index.ts)
- [src/core/pages.ts](https://github.com/BrettNye/stoa/blob/main/src/core/pages.ts)

> **注意**：以下源码文件在查询范围内但未出现在当前上下文片段中：
> - `src/core/tasks.ts`
> - `src/core/inbox.ts`
> - `src/core/sync-enumerate.ts`
> - `src/tools/task-claim.ts`
> - `src/tools/channel-post.ts`
> - `src/tools/process-inbox.ts`
>
> 本页基于现有上下文片段构建，部分系统细节可能需要补充。

</details>

# 任务协作系统

## 概述

任务协作系统是 Stoa 知识管理平台的核心子系统之一，负责管理任务（task）类型页面的生命周期、任务分发与认领、以及通过 Channel 机制实现跨智能体（agent）的任务协调。

系统的设计目标包括：

1. **结构化任务管理**：通过标准化的 frontmatter schema 定义任务元数据，确保任务状态、优先级和归属的完整性
2. **智能体协调**：支持通过 Channel 进行任务公告和认领，实现多智能体环境下的工作分配
3. **状态追踪**：提供任务状态流转的完整生命周期管理，从草稿（draft）到归档（archived）
4. **索引与查询**：基于 VaultIndex 的全文检索能力，支持按类型、wiki、状态等维度查询任务

资料来源：[src/core/frontmatter.ts:1-50]()

## 核心数据模型

### 页面类型体系

Stoa 采用统一的页面类型系统，任务（task）是其中一种核心类型。系统定义了以下类型常量用于过滤和分类：

```typescript
// 知识类型（硬知识，可合成）
const KNOWLEDGE_TYPES = ["concept", "decision", "spec", "source"];

// 执行类型（过程性知识）
const EXECUTION_TYPES = ["guide", "idea", "question", "task", "move"];
```

资料来源：[src/core/index.ts:1-30]()

### 页面状态枚举

任务页面使用统一的 PageStatus 枚举定义状态：

| 状态值 | 含义 | 使用场景 |
|--------|------|----------|
| `draft` | 草稿 | 任务刚创建，尚未激活 |
| `active` | 活跃 | 任务正在执行中 |
| `accepted` | 已接受 | 任务已被认领并确认 |
| `superseded` | 已替代 | 任务已被新任务替代 |
| `archived` | 已归档 | 任务完成或放弃后归档 |

资料来源：[src/core/frontmatter.ts:15-17]()

### Inbox 项结构

Inbox（收件箱）是任务分发的基础机制。系统通过解析 frontmatter 中的特定字段将页面路由到相应的 Inbox：

```typescript
export interface InboxEntry {
  id: string;
  wiki: string;
  path: string;
  title: string;
  type: NoteType;
  updated: string;
  created: string;
}
```

资料来源：[src/core/pages.ts:1-50]()

## Channel 协作机制

Channel 是 Stoa 中实现任务公告和实时协作的核心组件。它本质上是一个命名频道，用于：

1. **任务公告**：将新任务发布到特定频道
2. **认领机制**：智能体通过 Channel 认领分配给它的任务
3. **活动聚合**：按频道聚合 24 小时内的活动摘要

### Channel 摘要结构

```typescript
export interface ChannelSummary {
  name: string;           // 频道名称（kebab-case）
  wiki: string;           // 所属 wiki
  lastEntry: EntryInfo | null;  // 最新条目
  count24h: number;       // 24小时内条目数
}
```

资料来源：[src/core/channel.ts:1-30]()

### Channel 聚合逻辑

系统通过以下流程聚合 Channel 摘要：

```mermaid
graph TD
    A[查询所有 journal 类型页面] --> B[按 channel 分组]
    B --> C{是否超过 24 小时?}
    C -->|是| D[跳过计数]
    C -->|否| E[count24h++]
    E --> F[更新 lastEntry]
    D --> G[返回排序后的 ChannelSummary 列表]
    E --> G
```

处理逻辑的核心代码：

```typescript
for (const p of pages) {
  const channel = p.channel;
  if (typeof channel !== "string" || !channel) continue;
  const key = `${p.wiki}::${channel}`;
  if (p.created >= sinceIso) summary.count24h++;
  if (!summary.lastEntry || p.created > summary.lastEntry.ts) {
    // 读取文件获取 author 和 body excerpt
    summary.lastEntry = {
      id: p.id,
      channel,
      wiki: p.wiki,
      author: String(fm.author ?? "unknown"),
      ts: p.created,
      excerpt,
      pageId: p.id,
    };
  }
}
```

资料来源：[src/core/channel.ts:30-60]()

## 任务生命周期管理

### 任务创建

任务通过 `writePage` 函数创建，系统自动处理：

1. 生成规范的文件路径：`tasks/<slug>.md`
2. 解析并验证 frontmatter
3. 写入文件系统并更新索引

```typescript
export interface WritePageInput {
  id: string;
  type: NoteType;
  wiki: string;
  frontmatter: Record<string, any>;
  body: string;
  expectedUpdated?: string;
}
```

资料来源：[src/core/pages.ts:60-80]()

### 任务路径映射

系统使用 `pathForPage` 函数将页面 ID 映射到文件系统路径：

```typescript
// 任务类型路径格式
path = join(vaultPath, "wikis", wiki, "tasks", `${id}.md`);
```

资料来源：[src/core/pages.ts:20-40]()

## 智能体协作工作流

### 任务分发流程

```mermaid
graph LR
    A[任务创建] --> B[写入 tasks 目录]
    B --> C[更新 VaultIndex]
    C --> D[Channel 公告]
    D --> E[智能体感知]
    E --> F[任务认领]
    F --> G[状态更新为 accepted]
```

### 硬知识类型判定

在协作系统中，系统需要区分"硬知识"（可合成的知识资产）和"执行型"知识。任务属于 `EXECUTION_TYPES`：

```typescript
const HARD_KNOWLEDGE_TYPES = new Set(["concept", "decision", "spec", "source"]);

// 任务不属于硬知识，不参与合成债务检测
const type = String(page.type);
if (HARD_KNOWLEDGE_TYPES.has(type)) {
  // 参与合成债务检测
}
```

资料来源：[src/core/lint-checks/synthesis-debt.ts:40-60]()

## Channel 名称规范

Channel 名称必须符合 kebab-case 格式，lint 检查会验证格式：

| 规则 | 正则表达式 | 示例 |
|------|------------|------|
| 有效格式 | `^[a-z0-9]+(-[a-z0-9]+)*$` | `feature-x`, `bug-fix` |
| 无效格式 | 包含大写或特殊字符 | `myChannel`, `feature_x` |

```typescript
// Lint 检查代码
if (p.channel && !/^[a-z0-9]+(-[a-z0-9]+)*$/.test(p.channel)) {
  diagnostics.push({
    severity: "warning",
    code: "BAD_CHANNEL_FORMAT",
    message: `channel "${p.channel}" must be lowercase kebab-case`
  });
}
```

资料来源：[src/core/lint.ts:1-30]()

## 配置与验证

### Frontmatter Schema 验证

系统使用 Zod 进行运行时验证，确保任务元数据的完整性：

```typescript
const draftSchema = z.object({
  id: z.string().regex(/^[a-z0-9-]+$/),
  title: z.string().min(1),
  type: NoteType,
  created: z.string().regex(ISO_DATE),
  channel: z.string().regex(KEBAB).optional(),
});
```

验证规则：
- `id`：仅允许小写字母、数字和连字符
- `created`：必须是 ISO 日期格式 `YYYY-MM-DD`
- `channel`：必须是 kebab-case 格式

资料来源：[src/core/frontmatter.ts:50-70]()

### 索引查询能力

VaultIndex 提供强大的查询能力，支持按多个维度过滤任务：

```typescript
export function queryPages(
  idx: VaultIndex,
  filters: {
    wiki?: string;
    type?: string;
    status?: string;
    layer?: "knowledge" | "execution" | "all";
  }
): IndexedPage[]
```

支持的过滤维度：
- `wiki`：限定 wiki 范围
- `type`：匹配页面类型
- `status`：匹配页面状态
- `layer`：按知识层过滤（knowledge 或 execution）

资料来源：[src/core/index.ts:1-40]()

## 系统集成

### 与 Lint 系统集成

任务协作系统与全局 lint 检查集成，确保数据质量：

| 检查项 | 严重级别 | 说明 |
|--------|----------|------|
| `BAD_CHANNEL_FORMAT` | warning | Channel 名称格式不符合 kebab-case |
| `FILENAME_ID_MISMATCH` | warning | 文件名与 ID 不匹配 |
| `SNIPPET_NO_IMPLEMENTATION` | warning | 带有 snippet 标签的页面缺少 implementation 字段 |

```typescript
// 示例：遍历所有页面检查 channel 格式
for (const p of idx.pages) {
  if (input.wiki && p.wiki !== input.wiki) continue;
  if (p.channel && !/^[a-z0-9]+(-[a-z0-9]+)*$/.test(p.channel)) {
    diagnostics.push({ /* ... */ });
  }
}
```

资料来源：[src/core/lint.ts:20-45]()

### 与 Synthesis 系统集成

虽然任务本身不参与合成债务检测，但任务可以引用合成的知识资产：

```typescript
// 合成页面可以引用任务
sources: inputIds.map(i => `[[wikis/${wiki}/${typeFolderForId(i)}/${i}]]`)
```

资料来源：[src/core/synthesize.ts:40-50]()

## 总结

任务协作系统是 Stoa 平台中连接知识管理与智能体执行的关键桥梁。它通过：

1. **标准化数据模型**：基于 Zod schema 的类型安全定义
2. **Channel 机制**：实现跨智能体的任务公告和认领
3. **状态流转管理**：完整的任务生命周期支持
4. **索引与查询**：高效的 VaultIndex 查询能力
5. **质量保障**：集成 lint 检查确保数据完整性

该系统设计遵循单一职责原则，将任务提取、状态管理、Channel 协作等功能模块化，便于维护和扩展。

---

<a id='claims-evolution'></a>

## Claims与Evolution系统

### 相关页面

相关主题：[核心概念](#concepts), [Wiki管理](#wiki-management)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/core/claims.ts](https://github.com/BrettNye/stoa/blob/main/src/core/claims.ts)
- [src/core/claim-render.ts](https://github.com/BrettNye/stoa/blob/main/src/core/claim-render.ts)
- [src/core/claim-clustering.ts](https://github.com/BrettNye/stoa/blob/main/src/core/claim-clustering.ts)
- [src/core/evolution.ts](https://github.com/BrettNye/stoa/blob/main/src/core/evolution.ts)
- [src/core/evolution-claims.ts](https://github.com/BrettNye/stoa/blob/main/src/core/evolution-claims.ts)
- [src/tools/claim.ts](https://github.com/BrettNye/stoa/blob/main/src/tools/claim.ts)
- [src/tools/evolve-profile.ts](https://github.com/BrettNye/stoa/blob/main/src/tools/evolve-profile.ts)
</details>

# Claims与Evolution系统

## 系统概述

Claims与Evolution系统是stoa项目的核心智能体能力框架，负责管理知识主张的验证、置信度计算以及智能体画像的动态演进。该系统通过半衰期衰减机制、证据链追踪和多维度评分算法，实现了知识可信度评估与能力成长的闭环管理。

Claims（知识主张）作为系统的基本单元，承载了智能体对特定知识点的断言及其元数据。Evolution（进化）系统则利用Claims集合，通过聚类分析和移动推荐算法，驱动智能体画像的能力升级与专业化发展。

**核心设计目标：**

- 为知识断言提供可量化的置信度评估
- 通过时间衰减机制保持知识库的新鲜度
- 基于证据质量自动调整主张可信度
- 支持多智能体协作场景下的知识共享与验证

资料来源：[src/core/evolution.ts:1-30]()

---

## Claims数据模型

### Claim基础结构

Claims是知识主张的持久化表示，每个Claim包含以下核心字段：

| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | string | 全局唯一标识符，格式为`claim-<slug>` |
| `authored_by` | string | 主张创建者的智能体ID |
| `confidence` | number | 原始置信度，范围0.0-1.0 |
| `status` | enum | 主张状态：active/retracted/superseded |
| `evidence` | string[] | 支持该主张的页面引用数组 |
| `summary` | string | 主张的简要描述 |
| `body` | string | 主张的完整内容 |
| `last_validated` | string | ISO格式的最后验证时间 |
| `validated_by` | string[] | 验证该主张的智能体ID列表 |
| `tags` | string[] | 主题标签，用于分类和聚类 |
| `profile` | string[] | 关联的画像ID列表 |

资料来源：[src/tools/claim.ts:1-50]()

### Claim状态机

```mermaid
stateDiagram-v2
    [*] --> active: 创建新主张
    active --> retracted: 作者主动撤回
    active --> superseded: 被更高置信度主张替代
    retracted --> [*]: 永久归档
    superseded --> [*]: 保留历史参考
```

**状态转换规则：**

- **active → retracted**：仅原创建者可执行撤回操作
- **active → superseded**：当新主张具有更高有效置信度时可触发
- **retracted**：不可逆状态，记录撤回原因和时间戳

资料来源：[src/tools/claim.ts:30-60]()

---

## 有效置信度计算

### 半衰期衰减机制

系统采用指数衰减模型计算主张的有效置信度，这是保持知识库时效性的核心机制：

```
effective_confidence = base_confidence × 0.5^(days_since_validation / half_life_days)
```

**衰减参数配置：**

| 参数 | 默认值 | 说明 |
|------|--------|------|
| `half_life_days` | 90 | 置信度减半所需天数 |
| `effective_floor` | 0.05 | 有效置信度下限 |

### 有效置信度计算函数

```typescript
function effectiveConfidence(
  claim: { confidence: number; last_validated: string; status: string },
  today: Date,
  config: { half_life_days: number; effective_floor: number }
): number {
  // 已撤回或被替代的主张直接返回下限
  if (claim.status !== "active") return config.effective_floor;
  
  const days = daysSince(claim.last_validated, today);
  const decay = Math.pow(0.5, days / config.half_life_days);
  const effective = claim.confidence * decay;
  
  return Math.max(effective, config.effective_floor);
}
```

资料来源：[src/core/claim-render.ts:1-40]()

### 部署画像加成

当主张关联的画像与当前部署的智能体匹配时，额外获得0.1的置信度加成：

```
final_score = effective_confidence + (profile匹配 ? 0.1 : 0)
```

此机制确保智能体在评估与其能力相关的知识时具有优先权。

资料来源：[src/core/claim-render.ts:10-20]()

---

## Claims工具集

### 核心操作

| 操作 | 说明 | 权限限制 |
|------|------|----------|
| `vault.claim-submit` | 提交新主张 | 无限制 |
| `vault.claim-retract` | 撤回本人主张 | 仅原作者 |
| `vault.claim-supersede` | 用新主张替代旧主张 | 高置信度优先 |
| `vault.claim-read` | 读取主张详情 | 无限制 |

### 提交新主张

提交新主张时，系统执行以下校验：

1. **唯一性检查**：相同证据+相同标签组合不允许重复提交
2. **置信度门槛**：新主张置信度必须**严格高于**现有主张
3. **证据完整性**：建议提供至少一个证据页面引用

若校验失败，返回`rejected`状态并附带拒绝原因和现有主张信息：

```json
{
  "claim_id": "existing_claim_id",
  "action": "rejected",
  "rejection": {
    "reason": "existing claim has effective confidence 0.756; submission's 0.700 is not strictly higher",
    "existing_id": "claim-xxx",
    "existing_effective_confidence": 0.756,
    "your_confidence": 0.700
  }
}
```

资料来源：[src/tools/claim.ts:40-80]()

---

## Evolution进化系统

### 进化决策流程

```mermaid
graph TD
    A[输入: 画像ID] --> B[查询关联Claims]
    B --> C{Claims数量 ≥ 阈值?}
    C -->|否| D[返回不满足条件]
    C -->|是| E[聚类分析Claims]
    E --> F[识别Top Clusters]
    F --> G[计算专业领域建议]
    G --> H[生成移动推荐]
    H --> I[渲染进化理由]
    I --> J[输出: 进化结果]
```

Evolution系统通过以下步骤为智能体生成能力进化建议：

1. **Claims收集**：获取关联画像的所有活动主张
2. **聚类分析**：基于标签和证据将主张分组
3. **专业领域识别**：找出Claims最集中的领域
4. **移动推荐**：基于聚类结果推荐可学习的技能
5. **理由生成**：构建人类可读的进化建议文本

资料来源：[src/core/evolution.ts:1-50]()

### 进化输出结构

```typescript
interface EvolutionResult {
  eligible: boolean;
  reason: string;
  current: ProfileSnapshot;
  proposed: {
    specialties: string[];
    moveset_suggestions: MoveSuggestion[];
  };
  rationale: string;
  eligibility: EligibilityDetails;
  evidence_summary: EvidenceSummary;
}
```

### 专业领域（Specialties）

系统从Claim聚类中提取排名前3的专业领域：

- 按标签频率排序
- 仅考虑有效置信度>0.2的Claims
- 每个领域至少包含2个Claims

### 移动建议（Move Suggestions）

基于聚类分析结果，系统推荐适合当前能力阶段的学习移动：

```typescript
interface MoveSuggestion {
  move_id: string;
  move_hint: string;
  evidence_claim_ids: string[];
}
```

资料来源：[src/core/evolution.ts:50-100]()

---

## Claims聚类机制

### 聚类算法

Claims聚类基于多维度相似度计算：

```mermaid
graph LR
    A[Claim A] -->|标签交集| E[相似度计算]
    B[Claim B] -->|标签交集| E
    A -->|证据重叠| E
    B -->|证据重叠| E
    E --> F[聚类分组]
```

**聚类维度：**

| 维度 | 权重 | 说明 |
|------|------|------|
| 标签重叠 | 0.5 | 共同标签越多，关联越强 |
| 证据重叠 | 0.3 | 引用的页面重叠度高 |
| 时间邻近 | 0.2 | 相近时间创建的Claims更可能相关 |

### 聚类用途

1. **Evolution进化**：识别能力集中的主题领域
2. **合成建议**：检测可合成的新知识主题
3. **冲突检测**：发现相互矛盾的Claims组

资料来源：[src/core/claim-clustering.ts:1-30]()

---

## 配置参数

### Claims配置

在`wikis/<wiki>/CLAUDE.md`中配置：

```yaml
claims:
  half_life_days: 90      # 置信度衰减半衰期
  effective_floor: 0.05   # 最低有效置信度
  min_evidence: 1         # 最少证据数量
```

### Evolution配置

```yaml
evolution:
  min_claims_for_evolution: 10  # 触发进化的最少Claims数
  max_specialties: 3             # 最大专业领域数
  cluster_min_size: 2            # 聚类最小规模
```

### 渲染配置

```typescript
interface ClaimsConfig {
  half_life_days: number;
  effective_floor: number;
  render_min_confidence: number;  // 仅渲染高于此值的主张
  include_unvalidated: boolean;  // 是否包含未验证主张
}
```

资料来源：[src/core/claim-render.ts:1-60]()

---

## 工具注册与集成

### 工具清单

| 工具名称 | 功能 | 源码位置 |
|----------|------|----------|
| `vault.claim-submit` | 提交新主张 | src/tools/claim.ts |
| `vault.claim-retract` | 撤回主张 | src/tools/claim.ts |
| `vault.claim-read` | 读取主张详情 | src/tools/claim.ts |
| `vault.evolve-profile` | 触发画像进化 | src/tools/evolve-profile.ts |
| `vault.lint` | Claims相关检查 | src/tools/lint.ts |

### Lint检查集成

Claims系统与lint检查模块集成，提供以下质量保障规则：

- **claim-key-collision**：检测重复主张
- **claim-effective-below-floor**：标记有效置信度过低的主张
- **claim-without-evidence**：检测缺少证据的主张
- **claim-tag-repo-prefix-malformed**：标签格式校验

资料来源：[src/tools/lint.ts:1-30]()

---

## 与其他系统模块的交互

### 与索引系统的集成

Claims的增删改查通过ClaimsStore与索引系统同步：

```mermaid
sequenceDiagram
    参与者 Agent->>ClaimsStore: submit(claim)
    ClaimsStore->>Index: upsertPage(frontmatter)
    Index->>ClaimsStore: 返回索引结果
    ClaimsStore->>参与者 Agent: 返回claim_id
```

### 与Profile系统的集成

Evolution结果直接作用于Profile：

1. Evolution输出的`specialties`更新到Profile的`specialties`字段
2. `moveset_suggestions`提供可选的技能扩展路径
3. Profile的`evolution_stage`根据Claims累积量自动推进

### 与合成系统的集成

Claims聚类结果为`synthesize`工具提供素材：

- 聚类标签直接作为合成主题建议
- 高置信度Claims作为合成内容的证据来源
- 有效置信度作为Claims在合成中的权重因子

资料来源：[src/core/evolution.ts:80-120]()

---

## 最佳实践

### 提高主张置信度

1. **提供充分证据**：引用多个相关页面
2. **主动验证**：定期重新验证旧主张
3. **多人验证**：让多个智能体验证同一主张

### 避免主张被拒绝

1. 新主张置信度必须严格高于现有主张
2. 确保证据页面真实存在且可访问
3. 使用规范化的标签命名

### 有效利用进化系统

1. 保持Claims数量在触发阈值以上
2. 关注高置信度Claims集中的领域
3. 根据进化建议选择可学习的移动

---

<a id='cli-commands'></a>

## CLI命令参考

### 相关页面

相关主题：[任务协作系统](#task-coordination)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/cli/commands/recall.ts](https://github.com/BrettNye/stoa/blob/main/src/cli/commands/recall.ts)
- [src/cli/commands/inbox.ts](https://github.com/BrettNye/stoa/blob/main/src/cli/commands/inbox.ts)
- [src/cli/commands/synthesize.ts](https://github.com/BrettNye/stoa/blob/main/src/cli/commands/synthesize.ts)
- [src/cli/commands/channel-post.ts](https://github.com/BrettNye/stoa/blob/main/src/cli/commands/channel-post.ts)
- [src/cli/commands/task-create.ts](https://github.com/BrettNye/stoa/blob/main/src/cli/commands/task-create.ts)
- [src/cli/commands/bootstrap-repo.ts](https://github.com/BrettNye/stoa/blob/main/src/cli/commands/bootstrap-repo.ts)
- [src/cli/commands/new-wiki.ts](https://github.com/BrettNye/stoa/blob/main/src/cli/commands/new-wiki.ts)
</details>

# CLI命令参考

本文档全面介绍 stoa CLI 的命令结构、用法模式及核心命令详解。stoa 是一个基于 MCP（Model Context Protocol）的知识库管理系统，通过命令行接口提供笔记检索、内容捕获、任务协作等功能。

## 概述

stoa CLI 是 vault-mcp 服务器的命令行封装，提供与 MCP 工具等效的操作能力。所有命令均支持通过 `--vault` 参数指定 vault 路径，或通过环境变量 `STOA_VAULT_PATH` 设置默认路径。资料来源：[README.md:1-50]()

```bash
stoa --vault=/path/to/vault recall <topic>
stoa --vault=/path/to/vault inbox "thought to capture"
stoa --vault=/path/to/vault list-wikis
```

环境变量 `STOA_VAULT_PATH` 可替代每次调用时的 `--vault=` 参数，提升使用效率。资料来源：[README.md:45-50]()

## 命令架构

stoa CLI 采用Commander框架进行命令解析，支持多层级子命令结构。命令注册遵循统一模式，每个命令模块负责注册自身的参数解析和行为逻辑。资料来源：[src/cli/commands/new-wiki.ts:1-15]()

```mermaid
graph TD
    A[stoa CLI] --> B[--vault 路径选项]
    A --> C[命令主体]
    C --> D[recall]
    C --> E[inbox]
    C --> F[synthesize]
    C --> G[channel-post]
    C --> H[task-create]
    C --> I[bootstrap-repo]
    C --> J[new-wiki]
    C --> K[list-wikis]
```

## 核心命令详解

### recall — 主题检索

`recall` 命令根据关键词检索 vault 中的相关页面，返回匹配的页面列表及相关性评分。

```bash
stoa --vault=/path/to/vault recall <topic>
```

**功能说明：** 该命令通过全文索引和分词机制匹配包含指定主题的笔记内容，返回最多25条相关结果。资料来源：[src/core/index.ts:1-30]()

检索结果包含页面ID、标题、wiki归属及更新时间等元数据，支持通过 `--limit` 参数调整返回数量。

### inbox — 快速捕获

`inbox` 命令用于即时捕获思绪或临时笔记，将其写入当前激活 wiki 的 inbox 目录。

```bash
stoa --vault=/path/to/vault inbox "thought to capture"
```

**功能说明：** 捕获的内容会自动添加时间戳并生成唯一ID，适合记录快速闪现的想法而不打乱现有工作流。资料来源：[src/cli/commands/inbox.ts:1-20]()

### synthesize — 合成页面生成

`synthesize` 命令从多个源页面编译生成综合报告，适用于知识整合与摘要生成场景。

```bash
stoa --vault=/path/to/vault synthesize --topic "主题名称"
```

**功能说明：** 系统根据主题相关性从 vault 中选取相关页面，自动生成包含引用来源的综合文档。生成结果保存为 `synthesis-*.md` 格式的草稿页面。资料来源：[src/core/synthesize.ts:1-50]()

### channel-post — 频道消息发布

`channel-post` 用于向协调频道发布消息，支持跨实例通信与任务协调。

```bash
stoa --vault=/path/to/vault channel-post --channel <channel-name> --message <content>
```

**功能说明：** 频道消息遵循 YAML 格式规范，支持结构化数据传递。消息发布后可供其他 MCP 客户端或订阅者消费。资料来源：[src/cli/commands/channel-post.ts:1-25]()

### task-create — 任务创建

`task-create` 命令用于在 vault 中创建新任务，支持原子性任务声明与竞态处理。

```bash
stoa --vault=/path/to/vault task-create --title <title> --description <desc>
```

**功能说明：** 任务创建采用乐观锁机制防止并发冲突，后到的声明请求会收到 `AlreadyClaimedError` 错误。资料来源：[README.md:30-35]()

### bootstrap-repo — 仓库引导

`bootstrap-repo` 命令为消费仓库初始化 MCP 配置和 CLAUDE.md 片段，建立与 vault 的连接。

```bash
stoa --vault=/path/to/vault bootstrap-repo --target <repo-path>
```

**功能说明：** 该命令在目标仓库中写入 `.mcp.json` 配置文件和 `CLAUDE.md` 引导文件，完成自动化集成设置。资料来源：[src/cli/commands/bootstrap-repo.ts:1-20]()

### new-wiki — 新建 Wiki

`new-wiki` 命令脚手架化一个新的 wiki 空间，包括必要的文件夹结构和初始化文件。

```bash
stoa new-wiki <name> --mode <mode> --scope <scope>
```

**参数说明：**

| 参数 | 必填 | 说明 |
|------|------|------|
| `<name>` | 是 | Wiki 名称 |
| `--mode` | 是 | 创建模式：idea-map、project-doc、learning、mixed |
| `--scope` | 是 | Wiki 作用域定义 |

**功能说明：** 新建的 wiki 包含 `map.md`、`index.md`、wiki 本地的 `CLAUDE.md` 等标准文件。资料来源：[src/cli/commands/new-wiki.ts:1-18]()

## 环境变量

| 变量名 | 说明 | 优先级 |
|--------|------|--------|
| `STOA_VAULT_PATH` | 设置默认 vault 路径 | 高于 `.active-wiki` 文件 |
| `STOA_DEFAULT_WIKI` | 设置默认 wiki 名称 | 高于配置文件 |
| `STOA_DEFAULT_FAMILY` | 设置默认家族名称 | 高于配置文件 |

环境变量设置后可省略 `--vault` 参数，直接使用命令主体。资料来源：[README.md:45-50]()

## Wiki 参数解析顺序

当命令涉及 wiki 作用域时，系统按以下优先级解析 wiki 标识：

1. 显式 `wiki:` 参数
2. `--default-wiki=<name>` 服务器启动参数
3. vault 根目录的 `.active-wiki` 文件
4. 无匹配时抛出错误

资料来源：[README.md:40-45]()

## 命令执行流程

```mermaid
sequenceDiagram
    participant CLI as 命令行
    participant CMD as 命令处理器
    participant CORE as 核心模块
    participant FS as 文件系统
    
    CLI->>CMD: 解析参数与选项
    CMD->>CMD: 加载上下文配置
    CMD->>CORE: 调用核心业务逻辑
    CORE->>FS: 读写 vault 数据
    FS-->>CORE: 返回操作结果
    CORE-->>CMD: 格式化输出
    CMD-->>CLI: 显示结果
```

## 输出格式

CLI 命令的输出遵循统一格式，包含操作状态和结果数据：

- **成功操作：** 返回 JSON 格式的结构化结果
- **错误情况：** 返回错误码和描述信息
- **列表查询：** 返回数组格式的多项结果

## 相关命令索引

| 分类 | 命令 | 功能 |
|------|------|------|
| 读取 | recall | 主题检索 |
| 写入 | inbox | 快速捕获 |
| 写入 | synthesize | 合成页面 |
| 协作 | channel-post | 频道消息 |
| 协作 | task-create | 任务创建 |
| 系统 | bootstrap-repo | 仓库引导 |
| 系统 | new-wiki | 新建 wiki |

---

---

## Doramagic 踩坑日志

项目：BrettNye/stoa

摘要：发现 7 个潜在踩坑项，其中 0 个为 high/blocking；最高优先级：配置坑 - 可能修改宿主 AI 配置。

## 1. 配置坑 · 可能修改宿主 AI 配置

- 严重度：medium
- 证据强度：source_linked
- 发现：项目面向 Claude/Cursor/Codex/Gemini/OpenCode 等宿主，或安装命令涉及用户配置目录。
- 对用户的影响：安装可能改变本机 AI 工具行为，用户需要知道写入位置和回滚方法。
- 建议检查：列出会写入的配置文件、目录和卸载/回滚步骤。
- 防护动作：涉及宿主配置目录时必须给回滚路径，不能只给安装命令。
- 证据：capability.host_targets | github_repo:1229401738 | https://github.com/BrettNye/stoa | host_targets=mcp_host, claude, claude_code

## 2. 能力坑 · 能力判断依赖假设

- 严重度：medium
- 证据强度：source_linked
- 发现：README/documentation is current enough for a first validation pass.
- 对用户的影响：假设不成立时，用户拿不到承诺的能力。
- 建议检查：将假设转成下游验证清单。
- 防护动作：假设必须转成验证项；没有验证结果前不能写成事实。
- 证据：capability.assumptions | github_repo:1229401738 | https://github.com/BrettNye/stoa | README/documentation is current enough for a first validation pass.

## 3. 维护坑 · 维护活跃度未知

- 严重度：medium
- 证据强度：source_linked
- 发现：未记录 last_activity_observed。
- 对用户的影响：新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。
- 建议检查：补 GitHub 最近 commit、release、issue/PR 响应信号。
- 防护动作：维护活跃度未知时，推荐强度不能标为高信任。
- 证据：evidence.maintainer_signals | github_repo:1229401738 | https://github.com/BrettNye/stoa | last_activity_observed missing

## 4. 安全/权限坑 · 下游验证发现风险项

- 严重度：medium
- 证据强度：source_linked
- 发现：no_demo
- 对用户的影响：下游已经要求复核，不能在页面中弱化。
- 建议检查：进入安全/权限治理复核队列。
- 防护动作：下游风险存在时必须保持 review/recommendation 降级。
- 证据：downstream_validation.risk_items | github_repo:1229401738 | https://github.com/BrettNye/stoa | no_demo; severity=medium

## 5. 安全/权限坑 · 存在评分风险

- 严重度：medium
- 证据强度：source_linked
- 发现：no_demo
- 对用户的影响：风险会影响是否适合普通用户安装。
- 建议检查：把风险写入边界卡，并确认是否需要人工复核。
- 防护动作：评分风险必须进入边界卡，不能只作为内部分数。
- 证据：risks.scoring_risks | github_repo:1229401738 | https://github.com/BrettNye/stoa | no_demo; severity=medium

## 6. 维护坑 · issue/PR 响应质量未知

- 严重度：low
- 证据强度：source_linked
- 发现：issue_or_pr_quality=unknown。
- 对用户的影响：用户无法判断遇到问题后是否有人维护。
- 建议检查：抽样最近 issue/PR，判断是否长期无人处理。
- 防护动作：issue/PR 响应未知时，必须提示维护风险。
- 证据：evidence.maintainer_signals | github_repo:1229401738 | https://github.com/BrettNye/stoa | issue_or_pr_quality=unknown

## 7. 维护坑 · 发布节奏不明确

- 严重度：low
- 证据强度：source_linked
- 发现：release_recency=unknown。
- 对用户的影响：安装命令和文档可能落后于代码，用户踩坑概率升高。
- 建议检查：确认最近 release/tag 和 README 安装命令是否一致。
- 防护动作：发布节奏未知或过期时，安装说明必须标注可能漂移。
- 证据：evidence.maintainer_signals | github_repo:1229401738 | https://github.com/BrettNye/stoa | release_recency=unknown

<!-- canonical_name: BrettNye/stoa; human_manual_source: deepwiki_human_wiki -->
