commit b450b03638350ba4f8b9590c6ad9f6cb1729eefc Author: weichen Date: Tue Sep 29 15:20:38 2026 +0000 Initialize the repository with pinned submodules, project entry documents, and the design record Details (original message): Initialize the repository with pinned submodules, project entry documents, and the design record. diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml new file mode 100644 index 0000000..f7b20b4 --- /dev/null +++ b/.gitea/workflows/ci.yml @@ -0,0 +1,22 @@ +name: ci +on: + push: + branches: [main] + pull_request: + branches: [main] +jobs: + vet-and-test: + runs-on: nightly + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + - run: go vet ./... && go test -count=1 ./... + docker-checkout-hostgateway: + runs-on: ubuntu-latest + options: --add-host gitea:host-gateway + env: + GITHUB_SERVER_URL: http://gitea:3000 + steps: + - uses: actions/checkout@v4 + - run: test -f go.mod && echo "docker-mode checkout via host-gateway OK" diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..36f0f04 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# CodeGraph local index. A second layer so the database stays untracked even +# if .codegraph/.gitignore is overwritten by codegraph init. +.codegraph/* +!.codegraph/.gitignore diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..032d44a --- /dev/null +++ b/.gitmodules @@ -0,0 +1,9 @@ +[submodule "deps/development-guidelines"] + path = deps/development-guidelines + url = ssh://git@git-ssh.u1680832.nyat.app:31411/weichen/Development-Guidelines.git +[submodule "deps/error-code-system"] + path = deps/error-code-system + url = ssh://git@git-ssh.u1680832.nyat.app:31411/weichen/Error-Code-System.git +[submodule "deps/logging-system"] + path = deps/logging-system + url = ssh://git@git-ssh.u1680832.nyat.app:31411/weichen/Logging-System.git diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..67238a5 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,32 @@ +# 项目工作入口 + +本项目采纳的通用规则:[核心规则](deps/development-guidelines/core/baseline.md)。 +采纳范围、生效状态及项目差异:[采纳记录](policy/guidelines-adoption.md)。 +项目事实、测试和环境入口:[PROJECT.md](PROJECT.md)。 + +- 启动:阅读以上短入口;只加载本次任务触发的专题。 +- 普通交付:[交付流程](deps/development-guidelines/workflows/delivery.md)。 +- 并行开发/正式测试/审核/合入:[共同基线与同步节点](deps/development-guidelines/standards/collaboration.md),必须确认并实际同步最新权威目标。 +- Bug/异常:[系统性排障](deps/development-guidelines/workflows/debugging.md)。 +- 会话结束/换机器/换客户端/换执行者:[会话、执行者与机器交接](deps/development-guidelines/workflows/handoff.md),状态写入任务主记录,不依赖本地会话历史。 +- 测试与验收:[验证标准](deps/development-guidelines/standards/verification.md)。 +- 模块/接口:[模块契约](deps/development-guidelines/standards/module-contracts.md)。 +- 功能设计/跨模块变更:[设计与验证](deps/development-guidelines/workflows/design-verification.md),按增量明确验收、独立测试及故障范围。 +- 错误与过程事件:[可观测性](deps/development-guidelines/standards/observability.md)。 +- 配置来源与生效:[配置规范](deps/development-guidelines/standards/configuration.md),spec/overlay 合并、快照 revision 与诊断工具须遵守。 +- 拆仓与 submodule:[多仓库与固定版本组合](deps/development-guidelines/standards/multi-repo.md)。 +- 其他专题:按 [任务索引](deps/development-guidelines/README.md) 选择。 + +项目补充硬边界: + +- 本仓只做意图识别机制(定义、合并、识别、槽位、诊断),不内置任何业务意图内容;意图词表与正则一律由宿主注册或配置。 +- 依赖方向:仅可选接入 error-code-system 与 logging-system;禁止导入 agent-native、agent-squad、agent-system 或任何宿主类型。LLM 分类器、挂起预期、分句等扩展点只定义接口,实现留在宿主。 +- 配置/spec 校验失败 fail-closed:拒绝生成新快照并保留上一生效快照。「无匹配」(fallback)是正常识别结果,不是错误。 +- 错误码常量与 Error-Code-System 的 `intent.*` / `sys.*` 规范码对齐,`catalogcheck` 防止双权威;未知码不静默当成功。 +- 核心识别路径纯内存、无 I/O、确定性:同输入 + 同快照 → 同结果,不含时间与随机因素。 +- 依赖仓版本以本仓 gitlink 为准,不执行 `submodule update --remote`;除两个生态子模块外零第三方依赖。 + +任务权威:Gitea 仓库 `weichen/Agent-Intent` 的 Issue 与 Pull Request。 +规范性文档目录与过程记录位置:`policy/` 放项目规则;`docs/records/` 为过程记录豁免目录(方案、验证、交接)。项目规范与过程记录不进通用规范库。 +默认集成基线和提交身份:`main`;提交身份沿用本机 git 作者,不在文档中写死密钥或个人 fork URL。 +共享环境/发布入口及授权:无共享运行环境。权威远端 `ssh://git@git-ssh.u1680832.nyat.app:31411/weichen/Agent-Intent.git`。 diff --git a/PROJECT.md b/PROJECT.md new file mode 100644 index 0000000..88f2120 --- /dev/null +++ b/PROJECT.md @@ -0,0 +1,55 @@ +# Agent-Intent 项目事实 + +工作规则见 [AGENTS.md](AGENTS.md)。此文件维护本项目事实,不复制通用规范。 + +## 仓库与操作 + +- 目标/产品边界:通用意图识别基础库。提供意图定义(spec)、注册表与配置合并(registry/loader)、四级漏斗识别器(guard → expectation → rules → adjudicate)、槽位抽取与诊断(conformance/catalogcheck/intentctl)。不做动作执行、不内置 LLM 客户端、不含任何业务意图内容,不依赖 Agent-Native / Agent-Squad / Agent-System。 +- 源码、资产、文档、机器契约位置:Go 源码在仓库根包目录;模块路径 `agent-intent`;人类文档在根 `README.md`、`docs/`、`policy/`;过程记录在 `docs/records/`;机器契约以 `intent` 包公开类型为准。 +- 权威远端、集成基线、受保护分支:`ssh://git@git-ssh.u1680832.nyat.app:31411/weichen/Agent-Intent.git`,集成基线 `main`。 +- 并行共同基线记录位置、合入通知/主动检查方式:任务主记录在 Gitea Issue/PR;合入前在本仓 `main` 上 `git fetch` 并确认 HEAD。 +- 发布线与批准版本/实际制品查询入口:当前无独立制品仓库。可构建性以本仓 `main` 的 `go test` 为准;依赖子模块版本以 gitlink 为准,不把工作区未提交文件当发布组合。 +- 提交/审核/合并/发布身份与权限:仓库所有者 weichen。本机提交不代替远端合并。 +- 任务唯一来源:Gitea `weichen/Agent-Intent` 的 Issue 与 Pull Request。 +- 规范性文档目录:`policy/`。 +- 过程文档仓/目录:`docs/records/`(项目内豁免,理由见 [采纳记录](policy/guidelines-adoption.md))。 +- 交接记录位置:随任务主记录;需要落盘的交接放入 `docs/records/`。 +- 凭证查找入口及所需字段:无凭证。本仓不保存密钥字段的值。 + +## 依赖组合 + +| 逻辑 ID | 路径 | 角色 | +|---|---|---| +| development-guidelines | `deps/development-guidelines` | development-only,规范文本 | +| error-code-system | `deps/error-code-system` | build-required,规范码目录(catalogcheck 对齐 + `intent.*` 常量值) | +| logging-system | `deps/logging-system` | build-required,可选日志器 | + +克隆: + +```bash +git clone --recurse-submodules ssh://git@git-ssh.u1680832.nyat.app:31411/weichen/Agent-Intent.git +# 已克隆时:git submodule update --init --recursive +``` + +构建、审核和发布固定父仓 gitlink,不执行 `submodule update --remote`。 + +消费方(Agent-Squad / Agent-Native)接入本仓时须自带全部 replace:依赖模块内部的 replace 在上层构建中不生效。 + +## 验证命令 + +| 影响 | 工作目录与真实命令/CI | 前提与不覆盖范围 | +|---|---|---| +| 文档 | 人工核对 `AGENTS.md`、`PROJECT.md`、`policy/` 相对链接 | 不证明运行时行为 | +| 模块/接口 | 仓库根:`GOWORK=off go vet ./... && GOWORK=off go test -count=1 ./...` | 需要 Go 1.27 | +| 并发/快照隔离 | 仓库根:`GOWORK=off go test -count=1 -race ./...` | 覆盖 Reload 与识别并发 | +| 依赖纪律 | 仓库根:`GOWORK=off go list -m all` 仅标准库 + 两个生态模块 | 不证明宿主接入正确性 | +| 宿主行为验收 | 消费方仓内跑 `conformance.Run` | 本命令不覆盖真实宿主配置 | + +## 环境与数据 + +| 环境/实例 ID | 只读查询入口 | 授权写入入口 | DB/存储归属 | 恢复入口 | +|---|---|---|---|---| +| 本地开发 | 本机工作区与 `go test` | 本机 git 提交 | 无数据库;配置由宿主注入 | 重新 clone 父仓并 `submodule update --init --recursive` | + +共享项及 ACL:无。部署、迁移、发布的审批依据与负责角色:当前库不独立部署;合并进 `main` 由仓库所有者批准。 +实际制品/配置/schema 的查询方法:阅读当前 `main` 的 `intent` 包与 `go.mod`,不以历史 README 快照代替。 diff --git a/README.md b/README.md new file mode 100644 index 0000000..820bbcc --- /dev/null +++ b/README.md @@ -0,0 +1,59 @@ +# Agent-Intent + +可定义、可配置、可扩展的通用意图识别基础库:把「输入文本 → 意图 + 槽位 + 分支裁决」做成纯内存、确定性的库能力,供宿主在 LLM 之前完成确定性分流——守卫拦截(安全红线、识别即拒绝)、系统功能命令识别、路由提示与多轮澄清入口。 + +本仓库是该模块的源码位置。Go 模块路径为 `agent-intent`。不依赖 Agent-Native、Agent-Squad 或任何第三方模块;错误码与日志和 Error-Code-System / Logging-System 轻接入对齐(常量对齐 + 鸭子接口,核心包不依赖错误码库)。 + +设计目标与边界: + +- **机制与内容分离**:本仓只提供识别流水线与定义框架,不内置任何业务意图;词表、正则、守卫内容一律由宿主以 Go 注册或 JSON 配置提供。 +- **确定性**:同输入 + 同快照 → 同结果;识别路径纯内存、无 I/O、无时间与随机因素,「无匹配」(fallback)是正常结果而非错误。 +- **fail-closed 配置**:spec 校验或配置加载失败时整批原子拒绝,保留上一生效快照并给出可定位到字段与来源的错误。 +- **扩展点只留接口**:LLM 分类器、会话挂起预期、分句等由宿主实现并注入。 + +## 分层 + +| 包 | 职责 | 依赖边界 | +|---|---|---| +| intent | spec 定义与校验、注册表与不可变快照、JSON overlay 加载合并、四级漏斗识别器、槽位抽取、诊断 | 标准库 + 可选 logging-system | +| conformance | 消费方行为验收套件(Recognizer 公开契约正反例) | 只用公开 API | +| catalogcheck | 本仓错误常量与错误码库 `intent` 域的对齐断言 | 仅测试,import error-code-system | +| examples | 最小接入示例(embed 配置端到端) | 只用公开 API | +| cmd/intentctl | 配置 lint / 单条解释 / 评测集跑批的只读诊断 CLI | 组合根之一 | + +## 识别流水线 + +``` +Stage 0 Guard 守卫域规则(宿主声明 GuardDomains;命中 → GuardHit,可表达"识别即拒绝") +Stage 1 Expectation 会话挂起预期(可选注入;命中 → ExpectationHit,支持多轮澄清) +Stage 2 Rules 规则计分:includes_any / includes_all / excludes_any / patterns 对快照内启用 spec 计分 +Stage 3 Adjudicate 置信度裁决:唯一过阈 → Matched;多候选分数贴近 → Ambiguous;全不过 → Fallback +``` + +意图定义(`IntentSpec`)支持 Go 注册与 JSON overlay(新增 / 覆盖 / 禁用),合并产物为带 revision 的不可变快照;保护域(`ProtectedDomains`)内的 spec 不接受 overlay 覆盖或禁用。 + +详细字段说明、接入代码与 `intentctl` 用法在核心实现合入后补全于本 README 与 `docs/`。 + +## 作为 submodule 使用 + +消费方把本库固定为 submodule,推荐路径 `deps/agent-intent`;版本以消费方 gitlink 为准,不执行 `submodule update --remote`: + +```bash +git submodule add ssh://git@git-ssh.u1680832.nyat.app:31411/weichen/Agent-Intent.git deps/agent-intent +``` + +```text +require agent-intent v0.0.0 +replace agent-intent => ./deps/agent-intent +``` + +依赖模块内部的 replace 在上层构建中不生效:消费方须自带 `error-code-system` 与 `logging-system` 的 require + replace,并保持与本仓 gitlink 相同的组合。 + +## 验证 + +```bash +GOWORK=off go vet ./... && GOWORK=off go test -count=1 ./... +GOWORK=off go test -count=1 -race ./... +``` + +需要 Go 1.27。规则入口见 [AGENTS.md](AGENTS.md),项目事实见 [PROJECT.md](PROJECT.md)。 diff --git a/deps/development-guidelines b/deps/development-guidelines new file mode 160000 index 0000000..26b562d --- /dev/null +++ b/deps/development-guidelines @@ -0,0 +1 @@ +Subproject commit 26b562d2e34fbc560711296a309c91c74ffc55b1 diff --git a/deps/error-code-system b/deps/error-code-system new file mode 160000 index 0000000..28fa06e --- /dev/null +++ b/deps/error-code-system @@ -0,0 +1 @@ +Subproject commit 28fa06eaa56a19906732681cc02474a87ac9d408 diff --git a/deps/logging-system b/deps/logging-system new file mode 160000 index 0000000..2c5716f --- /dev/null +++ b/deps/logging-system @@ -0,0 +1 @@ +Subproject commit 2c5716fdcffbc4696fc0371afc70f39c44174201 diff --git a/docs/records/2026-09-29-agent-intent-design.md b/docs/records/2026-09-29-agent-intent-design.md new file mode 100644 index 0000000..a28aceb --- /dev/null +++ b/docs/records/2026-09-29-agent-intent-design.md @@ -0,0 +1,282 @@ +# Agent-Intent 通用意图识别模块设计方案 + +状态:待审;owner:weichen;主任务:本文件(仓库初始化前为唯一任务记录)。 +授权与交付终点:本方案获批后进入实现——初始化仓库、按阶段交付代码与文档、推送到批准远端。 +并行基线:新仓库,无并行基线;生态固定组合见「submodule 与版本固定」。 + +## 问题与证据 + +- Agent-Squad 当前"意图→路由"的唯一决策点是 `BlueprintRegistry.Match`(关键词 contains 计分,`squad/blueprint.go:82`)与 `RoleRegistry.Recommend`(`squad/registry.go:85`);入口层 CLI 一级命令硬编码 switch(`cli/cli.go:32`)。新增一个"自然语言系统功能命令"需要改多处 Go 源码。 +- Agent-Native 定位为纯执行内核(README),仓内无任何意图/路由/命令解析代码;"用户输入→决定做什么"全部留在消费方。 +- Agent-System 有成熟的四级漏斗意图层(`internal/intent/`),但它是 internal 包、33 种 IntentType 与词表全部硬编码在 Go 源文件(`recognizer_matchers_*.go` 共千余行)、与 Agent-System 会话模型强耦合,不可直接复用。 +- 生态既有事实:Agent-Native 与 Agent-Squad 均为 stdlib-only Go 模块(go 1.27),以 `deps/` submodule + gitlink + `require v0.0.0` + `replace` 接线;Error-Code-System 与 Logging-System 已定义库级轻接入范式(Agent-Native 先例:错误码走"常量取规范字符串 + ErrorCode()/ErrorFields() 鸭子方法 + catalogcheck 对齐测试",日志走"可选 `*logsys.Logger` 注入,nil→Nop")。 + +结论:缺的是一个**机制与内容分离、配置驱动、可被两个消费方以既有 submodule 范式接入**的独立意图识别模块。 + +## 目标与边界 + +**目标**(对应用户要求的三属性): + +1. **可定义**:意图以声明式 `IntentSpec`(JSON)或 Go 代码定义,含匹配规则、槽位、置信度参数、风险等级、宿主 handler 键与路由元数据。 +2. **可配置**:内置(Go 注册)为基线,JSON 配置可新增/覆盖/禁用;合并结果为不可变快照,带 revision;启动校验 fail-closed;提供 check/explain 诊断。 +3. **可扩展**:流水线各阶段(守卫、挂起预期、规则、分句、L2 分类)都是接口,宿主可注入实现;模块本身不含任何业务意图内容。 + +**非目标(v1 明确不做)**: + +- 不内置 LLM 客户端(L2 只暴露接口,由宿主用 `agent-native/runtime/llm` 等自行实现)。 +- 不做动作执行器(识别结果交宿主;IntentSpec 只携带 handler 键与元数据)。 +- 不含 Agent-System 的领域内容(docgov/task/kb 词表、33 种 IntentType 一律不迁移;实现全新编写,机制层借鉴其漏斗结构)。 +- 不提供 HTTP 服务、文件监听热更新(Reload 显式 API 即可)。 +- 消费方(Squad/Native)的接入改造不在本仓交付范围,只保证其可行并给出预告。 + +**硬边界(将写入根 AGENTS.md)**: + +1. 只做识别机制,不做领域内容;所有意图内容宿主注册。 +2. 依赖方向唯一:`agent-intent` 可选接入 error-code-system / logging-system(轻接入范式);**禁止**依赖 agent-native、agent-squad、agent-system 及任何宿主类型。 +3. 配置/spec 校验失败 fail-closed:拒绝生成新快照,保留上一个 applied 快照并暴露原因。 +4. "无匹配"不是错误(fallback 是正常识别结果);系统错误(配置损坏等)与识别结果严格分离。 +5. 零第三方依赖(仅标准库 + 两个生态子模块)。 +6. 版本以消费方 gitlink 为权威;禁止 `submodule update --remote`。 + +## 总体设计 + +### 定位与依赖方向 + +``` +Agent-Squad ──┐ ┌──> deps/development-guidelines (dev-only) + ├─ deps/agent-intent ─────┤ +Agent-Native ─┘ (module agent-intent) ├──> deps/error-code-system (build-required, 仅 catalogcheck 对齐 + 规范码字符串) + └──> deps/logging-system (build-required, 可选注入) +``` + +关键约束:**不得依赖 agent-native**。否则 Agent-Native 接入本模块时形成仓级循环(agent-native → deps/agent-intent → deps/agent-native)。因此 LLM 分类器、挂起预期的会话状态等一律以本模块定义的窄接口表达,宿主提供实现(模块契约规范:"进程内调用方可定义更窄的需求接口,通过适配器连接")。 + +### 核心概念与识别流水线 + +识别入口:`Recognizer.Recognize(ctx, input, snap) (Result, error)`。四级漏斗(借鉴 Agent-System 结构,机制化、去内容化): + +``` +Stage 0 Guard 守卫域规则(宿主声明 protected domain,优先级最高;命中→GuardHit,可携带"识别即拒绝"语义) +Stage 1 Expect 会话挂起预期(宿主可选注入 PendingExpectation;命中→ExpectationHit,优先于一般规则) +Stage 2 Rules 规则匹配:编译后的 matcher(关键词/正则/排除词)对快照内全部启用 spec 计分 +Stage 3 Adjudicate 置信度裁决:threshold 之上取最高分→Matched;多候选分数接近且都过阈→Ambiguous;全不过→Fallback +(可选) L2 宿主对 Ambiguous 追加分类器重打分(接口 Classifier,宿主自担延迟与成本,默认不接) +``` + +确定性要求:同一输入 + 同一快照 → 逐字节相同的结果(排序键:置信度降序 → priority 降序 → spec 注册序 → id 字典序)。识别无随机性、无时间依赖,可脱离外部 I/O 完整单测。 + +### IntentSpec(可定义的核心) + +```json +{ + "id": "squad.run.status_query", + "domain": "squad", + "version": 1, + "description": "查询任务运行进度", + "enabled": true, + "priority": 100, + "matcher": { + "includes_any": ["进度", "跑到哪了"], + "includes_all": ["查询", "任务"], + "excludes_any": ["怎么配置"], + "patterns": ["(?:查询|看).{0,6}(?:进度|状态)"], + "case_sensitive": false + }, + "slots": [ + {"key": "run_id", "required": false, "pattern": "(?:run|任务)[:# ]?([A-Za-z0-9-]+)", "group": 1} + ], + "confidence": {"base": 0.8, "pattern_bonus": 0.15, "threshold": 0.6}, + "risk": "low", + "requires_confirm": false, + "handler": "taskrun.query_status", + "metadata": {"channel": "dialogue"} +} +``` + +- `id` 全局唯一,格式 `^[a-z][a-z0-9-]{1,31}\.[a-z][a-z0-9_]{1,63}$`(与错误码同构,域名.记忆名)。 +- `handler`、`metadata` 模块不解释,仅供宿主路由/执行。 +- `risk`(low/medium/high)、`requires_confirm` 透传给宿主做授权判断。 +- 校验规则:id 冲突、正则编译失败、未知字段、空 matcher、槽位 group 越界 → 定位到字段路径的 `intent.invalid_spec` 错误(含来源文件与 spec id)。 +- 安全上限:单 spec 正则数、长度、快照内 spec 总数有默认上限(可由宿主在构建 Registry 时调整),防止配置膨胀拖垮识别。 + +### 注册与配置合并(可配置) + +双源合并,遵循配置规范的"单一解析管道 + 快照": + +1. **内置基线**:宿主(或本模块 examples)用 `RegistryBuilder.Register(spec...)` 注册 Go 定义的 spec。本模块自身不内置任何业务 spec。 +2. **JSON overlay**:`loader.Load(ctx, fs.FS)` 支持 `embed.FS` 与真实目录(config root 由宿主显式给出,不从 cwd 猜测)。overlay 语义:新增(新 id)/ 覆盖(同 id 整体替换,version 必须递增)/ 禁用(同 id `enabled:false`)。 +3. **保护域**:宿主构建时声明 protected domain 列表(典型:guard 域)。overlay 对保护域内 spec 的覆盖与禁用 → `intent.spec_protected` 错误,整批加载原子失败(不产生半套快照)。 +4. **快照**:合并产物编译为不可变 `Snapshot`(含全部编译后 matcher),原子指针发布;携带 `revision` 单调递增与来源摘要(每个 spec 来自哪个源、哪次覆盖)。 +5. **Reload**:显式 `Reload(ctx)`——校验→构建新快照→原子替换;失败保留旧 applied 快照并返回带原因的错误。运行中识别请求绑定取快照时刻的版本,不受并发替换影响。 +6. **诊断**:`Snapshot.Explain(input)` 输出各阶段裁决轨迹(每 spec 得分、命中词、排除原因);`Snapshot.Conflicts()` 输出 includes 词重叠/正则遮蔽报告(诊断信息,不阻断加载;确定性排序依据保证同名冲突不产生歧义)。 + +### 扩展点(可扩展) + +| 接口 | 阶段 | 默认实现 | 宿主典型实现 | +|---|---|---|---| +| `GuardSource` | Stage 0 | 无(宿主注册 guard 域 spec) | Agent-System 式安全红线词表(内容宿主给) | +| `ExpectationProvider` | Stage 1 | 无(不启用该阶段) | 会话系统提供挂起预期(多轮澄清) | +| `Classifier` | 可选 L2 | 无 | 基于 `runtime/llm.Client` 的重打分适配器(在宿主仓实现) | +| `Segmenter` | 前置分句 | 规则分句(分隔符表可配) | LLM 分句(宿主实现) | +| `Recognizer` | 整体 | 漏斗实现 | —(接口本身即消费面) | + +新增机制不改核心:流水线阶段间以中间结果传递,宿主扩展实现接口并在 Options 装配(组合根模式,同 Squad 的 Planner/Backend 注入惯例)。 + +### 结果契约 + +```go +type Result struct { + Input string // 原文(宿主决定是否记录日志,默认不落原始输入) + Branch Branch // GuardHit / ExpectationHit / Matched / Ambiguous / Fallback + Top *Candidate // GuardHit/Matched/ExpectationHit 非空;Ambiguous/Fallback 为 nil + Candidates []Candidate // 排序后的 top-N(含分数与命中原因) + Slots map[string]string + SnapshotRev int64 // 所用快照 revision,用于审计与复现 +} + +type Candidate struct { + ID string + Domain string + Confidence float64 + Risk string + RequiresConfirm bool + Handler string + Metadata map[string]string + Reason string // 命中解释(哪些词/哪个模式) +} +``` + +Query 语义(模块契约四类通信):纯函数式 Query——无副作用、无 I/O、无超时依赖(预算由宿主在调用侧控制);错误仅表示系统级失败(配置损坏等),不表示"没识别出"。 + +### 错误码与日志接入 + +**错误码(Pattern B,同 Agent-Native 先例,不 import errcode 于核心包)**: + +- 核心包定义错误常量,字符串值即规范码;错误类型实现 `ErrorCode() string` + `ErrorFields() map[string]any`(logsys 鸭子识别,自动展开 code 与字段)。 +- `catalogcheck/` 对齐测试断言本仓常量与错误码库 `intent` 域种子码逐个相等(防双权威)。 +- 上游变更(见下节):Error-Code-System 新增 `intent` 种子域,最小集: + - `intent.invalid_spec`(http 400 / error / retry never / side_effects none)— spec 定义或校验失败,字段含 spec id、字段路径、来源。 + - `intent.spec_protected`(http 400 / error / never / none)— 覆盖/禁用保护域。 + - `intent.load_failed`(http 500 / error / never / none)— 配置读取/解析失败,含来源路径与原因。 + 每条按六要素登记(http/severity/retry/side_effects/中文 summary/hint),走上游 PR + `WRITE_CATALOG=1` 重导目录。 + +**日志(可选注入,同 Agent-Native 惯例)**: + +- `Config.Log *logsys.Logger`,nil → `logsys.Nop()`;使用时 `.Module("intent")`。 +- 事件:`intent recognized`(info:branch、top intent id、confidence、snapshot_rev、duration_ms)、`intent snapshot reloaded`(info:新旧 revision、spec 计数)、`intent config rejected`(error:整批拒绝原因)。 +- 原始输入默认不写入日志(槽位值可能敏感);确需排障时宿主自行脱敏后以字段携带。trace 走 `logsys.WithContext(ctx)`,沿用宿主 `trace_id`。 + +### 并发、快照与安全 + +- Registry 持有 `atomic.Pointer[Snapshot]`;识别路径全程无锁读。 +- 编译产物(regexp、分词表)在快照构建期生成;识别期零编译。 +- 正则全部 `RE2` 语义(Go regexp 天然线性时间),另加输入长度上限与单次识别的 spec 评分预算。 +- `-race` 下并发识别 + Reload 的隔离测试为必测项。 + +## 仓库结构与生态接入 + +### 目录布局 + +``` +agent-intent/ +├── go.mod # module agent-intent, go 1.27; require+replace 两个生态库 +├── AGENTS.md # 短入口 + 硬边界 + 指向 deps/development-guidelines/core/baseline.md +├── PROJECT.md # 项目事实:依赖组合表、验证命令(GOWORK=off go vet && go test)、任务权威 +├── README.md # 定位、spec 编写指南、消费方接线(require v0.0.0 + replace) +├── policy/guidelines-adoption.md # 采纳记录(固定 gitlink、登记 docs/records/ 豁免) +├── docs/records/ # 过程记录(本方案为第一篇) +├── deps/ # 三个 submodule(见下) +├── intent/ # 核心包:spec/registry/loader/recognizer/slots/result/errors + testdata/ +├── conformance/ # 消费方行为验收套件(Recognizer 公开契约的正反例场景) +├── catalogcheck/ # 与错误码库 intent 域的对齐断言(仅测试) +├── examples/ # 最小接入示例:embed 配置 + guard 域 + 槽位抽取端到端样例 +├── scripts/submodule-consistency.sh +└── .gitea/workflows/ci.yml # vet + test(-race) + 一致性脚本 +``` + +后期(v0.2)追加 `cmd/intentctl`(lint 配置冲突、跑评测集、explain 单条输入——即配置规范要求的只读 check/explain 诊断)。 + +### submodule 与版本固定 + +- `.gitmodules`:`deps/development-guidelines`(dev-only,不进 go.mod)、`deps/error-code-system`、`deps/logging-system`(build-required)。 +- **pin 与生态当前组合一致**:guidelines `26b562d2`、error-code-system `95a03b75`、logging-system `2c5716f`(实现时以 `git submodule status` 实测为准)。理由:消费方的 `submodule-consistency.sh` 校验嵌套副本 gitlink 与本仓一致,Agent-Intent 作为中间层必须与上下游同组合,否则 Squad/Native 接入时一致性校验失败。 +- go.mod:`require error-code-system v0.0.0` / `require logging-system v0.0.0` + 两条 `replace => ./deps/...`;无 go.sum、测试带 `GOWORK=off`(同 Squad/Native)。 +- 远端:`ssh://git@git-ssh.u1680832.nyat.app:31411/weichen/Agent-Intent.git`;初始化流程按 adoption 工作流第 2 节(远端需先建仓,Gitea API token 在 `~/.secrets/gitea`,实现阶段处理)。 + +### Error-Code-System 上游变更 + +新增 `intent` 种子域(`errcode/codes.go` + `domains/intent.go` + 目录 JSON + docs 映射表)。这是唯一跨仓前置项;不落地则本仓 catalogcheck 无法编写。计划先于 Phase 1 提交该 PR 并固定新 gitlink。 + +### 消费方接入预告(不在本仓交付) + +- **Agent-Squad**:`SquadEngine.planAndExecute`(`squad/engine.go:175`)处以 `Recognizer` 前置/替换 `Blueprints.Match`;CLI `cmdRun` 与 HTTP `handleCreateRun` 入口用 guard 域拦截"系统功能命令"。接线清单:submodule + replace + PROJECT.md 依赖表 + submodule-consistency 扩路径 + 采纳记录补行。 +- **Agent-Native**:可选。典型位置是 `contract.Resolver` 决策前置(intent → 所需 Capability → Backend),须遵守"缺能力即拒绝"边界。 + +## 实施计划 + +| 阶段 | 内容 | 出口(验收证据) | +|---|---|---| +| P0 仓库初始化 | 建远端仓、clone、挂三个 submodule 至既定 pin、AGENTS/PROJECT/policy/CI/一致性脚本、首次提交推送 | 全新 clone `submodule update --init --recursive` 后 CI 绿;PROJECT.md 验证命令通过 | +| P1 错误码上游 | Error-Code-System 加 `intent` 域 PR | 上游合入,目录 JSON 与 docs 更新,本仓 pin 新 gitlink | +| P2 核心 v0.1.0 | intent 包全量(spec/校验/registry/loader/recognizer/slots/guard/expectation 接口/result/errors/logsys 接入)+ 单测 + testdata 评测集 + conformance + examples + catalogcheck | `GOWORK=off go vet ./... && go test -count=1 -race ./...` 全绿;零第三方依赖检查通过 | +| P3 v0.2 增量 | cmd/intentctl(lint/explain/评测)、Segmenter 规则实现、Reload+revision 报告 | intentctl 在 examples 配置上输出冲突报告与 explain 轨迹 | +| P4 消费方(独立仓) | Squad 接入 PR;Native 视需要 | 各自仓 conformance + 记录文档 | + +## 兼容、迁移与恢复 + +- 新仓无历史兼容负担;公开 API 从 v0.1.0 起视为契约,变更走"扩展→兼容→迁移→移除"。 +- spec 定义的兼容:spec `version` 字段递增用于宿主审计;id 一旦被消费方依赖即不改语义(改名=新 id+旧 id 禁用)。 +- 回退:消费方以普通 PR 恢复旧 gitlink 即回退本模块;本仓配置快照失败保留上一个 applied,不需要专门恢复程序。 + +## 验收 + +| 需求/验收条件 | 负责模块/不变量 | 验证方法 | 结果 | +|---|---|---|---| +| 同输入+同快照→同结果(确定性) | intent/recognizer | 表驱动单测(含同分并列场景) | 待执行 | +| guard 保护域不可被 overlay 禁用/覆盖 | intent/loader | 负例单测:整批原子失败、错误码 `intent.spec_protected` | 待执行 | +| 配置错误定位到字段与来源 | intent/spec 校验 | 未知键/坏正则/空 matcher/槽位越界负例 | 待执行 | +| 合并语义(新增/覆盖/禁用/version 递增) | intent/registry+loader | Go+JSON 双源合并表测 | 待执行 | +| 无匹配=Fallback 正常返回,非错误 | intent/result | 单测断言 Branch 与 nil error | 待执行 | +| Reload 失败保留旧快照;并发识别不受影响 | intent/registry | `-race` 并发测试 | 待执行 | +| 硬负例语料(否定写+只读、排除词、近义混淆) | testdata 评测集 | 表测逐条断言期望分支 | 待执行 | +| 错误码与上游 intent 域逐个相等 | catalogcheck | 对齐测试 | 待执行 | +| 零第三方依赖 | go.mod | `go list -m all` 仅标准库+两个生态模块 | 待执行 | +| 消费方可按生态范式接入 | conformance+examples | 示例端到端跑通(embed 配置→识别→槽位) | 待执行 | + +| 用户/系统条件 | 检查层级 | 预期结果 | 必需环境 | +|---|---|---|---| +| 系统功能命令被 guard 拦截(原例) | examples 端到端 | GuardHit + 宿主 handler 键 | 本地 Go 1.27 | +| 普通目标文本走 Fallback(变体) | examples 端到端 | Fallback 分支,不误触 | 同上 | +| 歪曲写法/否定式(边界) | 硬负例语料 | 不误命中高斯 intent | 同上 | +| 正常行为保持(Squad 接入后) | Squad conformance | 原蓝图匹配行为由宿主基线 spec 复现 | P4 | + +## 模块设计卡 + +| 维度 | 内容 | +|---|---| +| owner、目的、非职责 | weichen;通用意图识别机制(定义/合并/识别/槽位/诊断);不做领域内容、动作执行、LLM 客户端、HTTP 服务 | +| 隔离范围与失效行为 | L1 库级逻辑隔离;无 I/O 依赖(配置加载除外);识别路径纯内存,失败影响=单次返回错误,不崩溃宿主 | +| 数据与不变量 | 快照唯一写者=Reload;spec 只在快照构建期编译;revision 单调;同输入同快照同结果 | +| 入口 | Query:Recognize、Explain、Conflicts;Command:Reload、Register(构建期);无 Event/Stream | +| 契约 | 见「结果契约」;错误=系统级失败(intent.* 码),无匹配=正常分支 | +| 依赖 | 公开端口:Classifier/ExpectationProvider/Segmenter(宿主实现);必需:无;可选:logsys、errcode(仅 catalogcheck) | +| 独立测试 | 纯函数识别 + testdata 语料,无外部 I/O;时间不参与裁决;conformance 供消费方复用 | +| 简洁性 | 调用方只需 Recognize(ctx, input, snap);快照/合并/编译复杂性全部隐藏在 Loader+Registry | +| 并发/副作用 | 识别只读;Reload 原子指针替换;识别期零编译零分配热点 | +| 故障控制与定位 | 配置失败 fail-closed 保留旧快照;定位信号=错误码+字段(spec id/来源/字段路径)+Explain 轨迹 | +| 生命周期 | 无常驻资源;Close 仅透传日志 Sync 由宿主管理 | +| 验收 | 见验收表 | + +## 决策与剩余项 + +需负责人确认的选择(均有推荐项): + +- **D1 实现来源**:全新编写(推荐)vs 移植 Agent-System `internal/intent` 代码。推荐全新:原实现与 Agent-System 会话模型/33 IntentType 强耦合,且可避免跨仓来源与授权问题;机制结构(漏斗/分支/元数据)已在本方案吸收。 +- **D2 配置格式**:JSON(推荐,stdlib-only 与生态一致)vs YAML(需引第三方依赖,破坏零依赖边界)。 +- **D3 错误码接入模式**:Pattern B 常量+鸭子+catalogcheck(推荐,同 Agent-Native)vs 直接 import errcode(Squad 式,重一级)。 +- **D4 Error-Code-System 上游 `intent` 域 PR**:需授权修改另一仓(最小 3 码)。若暂不动上游,备选是本仓 catalogcheck 内 `LoadJSON` 自建域(不推荐,形成事实双权威)。 +- **D5 v1 范围**:不含 LLM 分类器实现、不含动作执行器、不含 HTTP 面(推荐;L2/执行留接口给宿主)。 +- **D6 生态 pin 组合**:三个 submodule pin 与 Squad/Native 当前一致(guidelines 26b562d2 / errcode 95a03b75 / logsys 2c5716f;实现时实测复核)。 +- **D7 远端建仓时机**:P0 阶段用 Gitea API 建远端仓并首推 main(token 在 `~/.secrets/gitea`,按惯例不回显)。 + +剩余项:Squad/Native 的具体接入 PR 细节在 P4 前另立方案;Agent-System 未来是否以本模块替换 `internal/intent` 不在本方案范围。 diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..ac7fad7 --- /dev/null +++ b/go.mod @@ -0,0 +1,12 @@ +module agent-intent + +go 1.27 + +require ( + error-code-system v0.0.0 + logging-system v0.0.0 +) + +replace error-code-system => ./deps/error-code-system + +replace logging-system => ./deps/logging-system diff --git a/policy/guidelines-adoption.md b/policy/guidelines-adoption.md new file mode 100644 index 0000000..eccdd9a --- /dev/null +++ b/policy/guidelines-adoption.md @@ -0,0 +1,44 @@ +# 通用规范采纳记录 + +- 项目/负责人:Agent-Intent / 仓库所有者 weichen +- 状态:active +- 规范位置:`deps/development-guidelines` +- 规范性文档目录:`policy/` +- 过程文档位置:`docs/records/`(项目内固定目录豁免。当前为个人维护的基础库,单独过程仓会让每份记录都变成跨仓 gitlink;任务主记录仍在 Gitea Issue/PR。豁免一经登记,过程记录不得再写入 `policy/` 或规范库。) +- 版本权威:父仓 gitlink;可读标签:无(内容版本 `0.1.0-draft.6`,提交 `26b562d2e34fbc560711296a309c91c74ffc55b1`) +- 批准/生效依据:本仓接入提交;草案审阅完成后随该提交生效 +- 替代范围和迁移说明:本仓为新建仓库,无既往规则需要迁移。 + +| 规范/工作流 | 适用条件与范围 | 采纳或不适用理由 | 执行方式/证据 | +|---|---|---|---| +| core/baseline.md | 日常工作 | 所有改动都要守硬边界 | manual | +| workflows/delivery.md、debugging.md、handoff.md | 交付、排障与交接 | 单人维护仍需要可交接的任务记录 | manual | +| standards/collaboration.md | 并行共同起点、节点同步与陈旧候选拒绝 | 本仓会被 Agent-Squad / Agent-Native 以 gitlink 消费 | manual | +| standards/verification.md | 验证与结论 | 仓库根 `go vet` / `go test`(含 `-race`) | manual;命令见 PROJECT.md | +| workflows/design-verification.md、standards/testability.md、standards/failure-containment.md | 识别漏斗、配置合并与快照切换 | 识别必须可脱离外部 I/O 独立验证;配置失败保留上一快照 | manual | +| standards/module-contracts.md | intent/conformance/catalogcheck/examples 边界 | 公开端口按层拆分;扩展点只留接口 | manual | +| standards/observability.md | 错误码、识别事件日志 | 与 Error-Code-System / Logging-System 对齐 | manual | +| standards/configuration.md | spec/overlay 双源合并、快照 revision、生效时机与诊断 | 本仓核心就是配置驱动模块;check/explain 由 `intentctl` 承担 | manual | +| standards/multi-repo.md | submodule 与固定组合 | 规范与基础库以 gitlink 锁定 | manual | +| standards/security.md | 凭证、配置信任边界 | 配置文件属宿主可信输入;本仓不含凭证 | manual | +| standards/documentation.md | 三层文档 | `policy/` 与 `docs/records/` 已分开 | manual | +| standards/data-reliability.md | 本仓自有数据库 | 无数据库;快照替换的原子性由并发测试覆盖 | 不适用 | +| standards/agent-execution.md | Agent 执行契约 | 本仓不做执行,只做 LLM 前的确定性识别 | 不适用 | +| standards/release-operations.md | 独立发布流水线 | 当前无制品仓库与部署入口 | 不适用 | +| workflows/automation.md | 定时与后台任务 | 本仓无 daemon | 不适用 | + +## 项目差异 + +| 原规则/章节 | 项目采用方式 | 原因与风险 | 负责人/复查条件 | +|---|---|---|---| +| documentation.md 过程仓默认独立仓库 | 过程记录放 `docs/records/` | 个人基础库;风险是记录与代码同 PR 时容易把证据写成第二权威。任务状态仍只认 Gitea Issue/PR | 出现第二名维护者或对外发布流程时复查 | + +默认做法差异说明理由;硬边界冲突须有明确有效决策,不能用此表自授权。建议不采用无需登记。 + +## 本次升级或首次接入验证 + +- 入口:根 `AGENTS.md`、`PROJECT.md` 指向 `deps/development-guidelines`。 +- 子模块:`deps/development-guidelines` 固定 `26b562d2e34fbc560711296a309c91c74ffc55b1`;`deps/error-code-system` 固定 `28fa06eaa56a19906732681cc02474a87ac9d408`(含 `intent` 种子域);`deps/logging-system` 固定 `2c5716fdcffbc4696fc0371afc70f39c44174201`。三者与 Agent-Squad / Agent-Native 当前组合一致(error-code-system 为新增 intent 域后的新提交,属追加式变更)。 +- `.gitmodules` 使用批准的上游 SSH URL,不含本机路径或凭证。 +- 执行方式保持 manual:挂载 Markdown 不自动改变 CI。 +- 回退:恢复本提交之前的 gitlink,并删除根入口与 `policy/guidelines-adoption.md` 中对应条款;无已生效的 CI 或权限变更需要另恢复。 diff --git a/scripts/submodule-consistency.sh b/scripts/submodule-consistency.sh new file mode 100755 index 0000000..76d427b --- /dev/null +++ b/scripts/submodule-consistency.sh @@ -0,0 +1,22 @@ +#!/bin/sh +# 核对本仓 gitlink 与已检出子模块 HEAD 是否一致。 +# 嵌套副本是否与消费方自己的 deps 相同,由消费方仓库的同名脚本比较。 +set -eu +cd "$(dirname "$0")/.." +fail=0 +for path in deps/development-guidelines deps/error-code-system deps/logging-system; do + if [ ! -e "$path/.git" ]; then + echo "missing submodule checkout: $path" >&2 + fail=1 + continue + fi + recorded=$(git rev-parse ":$path") + actual=$(git -C "$path" rev-parse HEAD) + if [ "$recorded" != "$actual" ]; then + echo "gitlink mismatch: $path recorded=$recorded HEAD=$actual" >&2 + fail=1 + else + echo "ok $path $recorded" + fi +done +exit "$fail"