Initial publish v0.1.0: standalone workflow core (corpus + examples + guards)

This commit is contained in:
octopus
2026-09-15 08:41:51 +08:00
commit bb35e661b2
114 changed files with 20240 additions and 0 deletions
View File
+36
View File
@@ -0,0 +1,36 @@
# 术语映射表(Core ↔ dogfood 实例)
> 本表是 Core 改写与 dogfood 实例对照的**唯一事实源**v3 §E):Core 侧
> 工件使用下表左列的中立术语,右列是本组织 dogfood 实例(Gitea 后端)的
> 实际表述。任何 Core 工件需要落到本实例时,按本表做机械替换;反向
> 改写(实例 → Core)同样以本表为准。新增映射必须先改本表,再改工件。
| Core 中立术语 | dogfood/Gitea 实例表述 |
| --- | --- |
| 工单后端(ticket backend | Gitea |
| Tier-2 工件库 | Gitea wiki |
| 工单评论 APIticket backend 评论接口) | `gitea_issue_comment__*` |
| wiki 读写 APITier-2 工件库读写接口) | `gitea_wiki__*` |
| 看板移动 API(工单看板列迁移接口) | `gitea_column__move_issue` |
| 项目看板 API(工单面板管理接口) | `gitea_project__*` |
| 路由解析工具(Step 0 路由门依赖) | `route_resolver` |
| 会话工作树路径(并发分支工作区根) | `<worktrees-root>` |
| 测试命令·变更集(本地前置检查) | `bun run test:changed` |
| 测试命令·全量分片(交付前置 / nightly) | `bun run test:parallel` |
| 类型检查命令 | `bun typecheck` |
| 产品代码路径(harness 实现所在包) | `packages/octopus/src/...` |
| 私化工单引用(组织内部工单号) | `#NNNN` 活链接(Core 侧用 `[org-internal #NNNN]` 注记) |
| 实例规则目录(dogfood 消费副本所在) | `.octopus/`(如 `.octopus/rules/` |
| 运行工作区(Tier-1 本地工件) | `.octopus/runs/{slug}/` |
| 实例配置文件(会话/管线配置) | `octopus.jsonc` |
## 备注
- **私化工单引用**:Core 侧不得产出指向具体实例的活链接 `#NNNN`(会被
实例渲染为真实工单);一律写 `[org-internal #NNNN]` 注记格式,落地
实例时按本表还原为 `#NNNN`
- **命令占位**:Core 规则正文中的 `<test-cmd:changed>`
`<test-cmd:parallel>` 等占位符按本表「测试命令」两行绑定到实例命令。
- **裸词 Gitea**:仅当作为 adapter 名称出现时允许(如「Gitea adapter」);
- 表内反引号包裹的实例表述仅供对照,不构成 Core 对实例的引用
(C-1 扫描剥离行内代码后本表零命中)。
+215
View File
@@ -0,0 +1,215 @@
# Gitea Adapter — 写模式(Write Patterns
> Gitea adapter 参考实现(Increment 3,自 dogfood 源
> `_shared/gitea-write-patterns.md` 拆分上提)。本目录承载后端绑定的
> API 形态(MCP 工具名、REST 端点、curl 形态);页名规范与寻址语义
> 是后端中立契约,见 `core/rules/artifact-addressing.md`(本文不重复)。
> 实例基址由实例配置提供(下文 `<gitea-base-url>`),见
> `core/adapters/TERMINOLOGY.md`。
Owner/repo 固定为 `Octopus/octopus`。所有 wiki 页名遵循 Core 契约
`{slug}/{type}-{seq:02d}-{title}`(例外页全枚举见 artifact-addressing.md)。
## Wiki URL 构造 — html_url 规则
**黄金规则:绝不手工拼接 wiki URL。** `gitea_wiki__create_page` /
`gitea_wiki__get_page` / `gitea_wiki__list_pages` 响应中的 `html_url`
字段是唯一权威链接,发布时捕获并原样复用。`page_name``html_url`
的变换不可推导(`/``%2F`、含斜杠页名带 `.-` 尾缀、CJK 百分号编码),
必须读 API。
**两种标识符勿混淆**
| 标识符 | 是什么 | 用途 |
| ----------- | ------------------------------------ | ---------------------------------------- |
| `page_name` | 原始页标识;字面 `/`、无主机、无编码 | wiki MCP 工具的 `page_name`/`title` 参数 |
| `html_url` | 后端生成的完整可点击 URL | markdown 链接、`target_url`、PR 正文 |
**去向**
- **工件索引位置列** — 一个单元格同时存两者:
``[`{page_name}`]({html_url})``。链接文本供读侧调
`gitea_wiki__get_page`href 供人点击(见 Pattern 10)。
- **commit-status `target_url`** — 终报页的 `html_url`(见 Pattern 8)。
- **页内交叉链接** — 用 `html_url`。
无 API 响应可用时(静态源串)用 `<gitea-base-url>`,且仅此一处来源。
## Pattern 1: create-wiki-page
```
gitea_wiki__create_page(owner="Octopus", repo="octopus",
title="{slug}/{type}-{seq:02d}-{title}",
content="{内容}",
message="{可选 commit message}")
```
**发布→验证(强制)**:发布后立刻回读确认存在且内容一致:
```
gitea_wiki__get_page(owner="Octopus", repo="octopus", page_name="{同 title}")
```
404 / 内容不一致 → 修复后重发。页名冲突(409)→ 该页已存在,改用
Pattern 2 update,绝不另发新页。响应的 `html_url` 立即捕获复用。
## Pattern 2: update-wiki-page
```
gitea_wiki__update_page(owner="Octopus", repo="octopus",
page_name="{页名}",
content="{新内容}",
message="{commit message}")
```
更新后再回读验证;409 冲突 → 拉最新内容手工合并后重试。
## Pattern 3: create-issue
```
gitea_issue__create(owner="Octopus", repo="octopus",
title="{标题}", body="{正文}", labels=["{label}"])
```
### 工单交叉链接(强制)
父子工单组必须双向链接:父工单 task list 引用 `#<number>`;子工单正文
带 `## 父级 / Parent` 节引用父 `#<number>`。
### 衍生工单创建
- 技术债(verify Phase 5.5):`TD-NNN` 经分配台账取号后升票,`## Parent`
指回登记册源工单。
- 基线失败(Phase 5.55):label `baseline-failure` + `BF-NNN`(族伞签,
按失败签名去重)。
- 不稳定测试(Phase 5.56):label `flaky-test` + `FT-NNN`(同上)。
## Pattern 4: update-issue
```
gitea_issue__update(owner="Octopus", repo="octopus",
index={issue_number}, body="{正文}", state="{open|closed}", ...)
```
原位更新正文(checklist 勾选、live 状态表维护);关闭工单即触发
归档动作(见 artifact-addressing.md §4.3 + Pattern 10)。
## Pattern 5: add-issue-comment
```
gitea_issue_comment__create(owner="Octopus", repo="octopus",
index={issue_number}, body="{评论正文}")
```
首次评论后捕获返回的 `comment_id`——后续对同一逻辑评论的更新必须走
Pattern 6 原位 edit,绝不再 create。用于:评审综合(Synthesis)、
状态备注、TD 登记、claim 认领。
## Pattern 6: edit-issue-comment
```
gitea_issue_comment__edit(owner="Octopus", repo="octopus",
comment_id={comment_id}, body="{新正文}")
```
单评论聚合不变量(工件索引、当前状态表等)的执行手段。
## Pattern 7: move-issue-to-column
```
gitea_column__move_issue(owner="Octopus", repo="octopus",
project_id={project_id}, column_id={column_id}, index={issue_number})
```
看板列迁移(Todo → In Progress → Review → Done)。
## Pattern 7.5: move-issue-to-pipeline-stage
管线阶段板列(Pipeline Stages board column)承载阶段迁移——阶段转移
落到板列,**不落** `## 当前状态` 行(该表只承载 PR / 评审 / CI 行与
非阶段阻塞项)。列序列按管线阶段定义;移动用 Pattern 7 同款
`gitea_column__move_issue`column 由 `gitea_project__list` /
`gitea_column__list` 发现。
## Pattern 8: post-commit-statusREST 回退)
MCP 工具缺席时用 REST 直发 commit status(评审综合的 Tier-2 落点):
```bash
curl -X POST "<gitea-base-url>/api/v1/repos/Octopus/octopus/statuses/{sha}" \
-H "Authorization: token <token>" \
-H "Content-Type: application/json" \
-d '{
"context": "pipeline/review-{stage}",
"state": "{success|failure|pending|error}",
"target_url": "{html_url}",
"description": "{≤140 chars 摘要}"
}'
```
context 公式:`pipeline/review-{stage}``code` / `review-dag` /
`audit-process`)。token 从实例配置读取(此处 `<token>` 占位)。
merge 前读回验证:`GET /commits/{PR_SHA}/status`。
## Pattern 9: create-iteration-board
```
gitea_project__create(owner="Octopus", repo="octopus",
title="{slug} — Iteration {N}", description="…")
gitea_column__create(owner="Octopus", repo="octopus",
project_id={project_id}, title="Todo")
# … In Progress / Review / Done 同款
```
DAG 聚合 agent 在单门 PASS 后建板;工单正文模板带 `## Node Reference`
(指向 `{epic-slug}/dag`)、`## Acceptance Criteria`、`## Parent`。
## Pattern 10: artifact-index(工单 ↔ 工件索引)
技能发布工件后,在源工单维护 **`## 工件索引` 评论**——单一原位编辑的
索引(反向链接 + compaction 恢复主路径;语义不变量见
`core/rules/artifact-addressing.md` §4):
```
# 1. 找源工单(PR body / commit 的 Closes #N,或 DAG 父映射);无则跳过
# 2. 评论已存在?
gitea_issue_comment__list(owner="Octopus", repo="octopus", index={issue_number})
# → 扫 body 以 "## 工件索引" 开头的评论(遗留前缀 "## Pipeline 工件追踪表"
# 原位升级,不重复发)
# 3a. 不存在 → gitea_issue_comment__create 初始化
# 3b. 存在 → gitea_issue_comment__edit 原位编辑(复用 comment_id
```
**索引表模板**(每工件一行;技能只增改自己的行,绝不删他技的行):
## 工件索引
slug: `{slug}` — source issue #{N}
| 工件 | 类型 | 版本 | 位置 | 重读 |
|------|------|------|------|------|
| DAG | 任务图 | v1 (frozen) | [`{epic-slug}/dag`]({html_url}) | CORE |
**位置列填充规则**:单元格 = markdown 链接 ``[`{page_name}`]({html_url})``
链接文本(page_name,字面 `/`)供读侧 `gitea_wiki__get_page`href
(html_url)供人点击,必须取自 API 响应,严禁拼接。
**重读优先级**`CORE` = compaction 后必读(重读集 = 全部 CORE 行);
`ON-Demand` → `ON-DEMAND` = 按需;`ARCHIVE` = 已归档不读。
**归档动作(archive-at-close**:工单关闭时由关闭方 agent 原位 edit
本评论——表格上方加归档横幅(`> **状态**: ✅ 已归档 — issue #{N} 关闭于
{date}`+ 全部行 重读 置 `ARCHIVE`;不删行、不改位置列、不发第二条
评论。主路径 verify Phase 5.6;跳过 verify 的路由由关闭 agent 补执行。
**各技能行映射**
| 技能 | 工件 ID | 位置 |
| ------------------------- | ---------------------------- | ------------------------------------------------------------ |
| `analyze-dag` | `DAG` | `{epic-slug}/dag` |
| `review-artifact` | `REVIEW-{stage}` | `{slug}/reviews/{stage}/final/report` |
| `review-code` | `REVIEW-code` | `{slug}/reviews/code/final/report` |
| `review-code`DAG task | `REVIEW-code-task-{node-id}` | `{epic-slug}/reviews/code/final/report-task-{node-id}` |
| `verify` | `VERIFY-{N}` | `{slug}/05-verify-iteration-{N}` |
| `verify`milestone | `VERIFY-M-{M-id}` | `{epic-slug}/05-verify-milestone-{M-id}`(重读 `ON-DEMAND` |
| `verify`DAG task | `VERIFY-TASK-{node-id}` | `{epic-slug}/05-verify-task-{node-id}`(重读 `ON-DEMAND` |
+123
View File
@@ -0,0 +1,123 @@
# Gitea Adapter — 读模式(Read Patterns
> Gitea adapter 参考实现(Increment 3,自 dogfood 源
> `_shared/gitea-read-patterns.md` 拆分上提)。页名规范与寻址语义见
> `core/rules/artifact-addressing.md`(后端中立契约,本文不重复)。
> 实例基址 `<gitea-base-url>` 由实例配置提供,见 TERMINOLOGY.md。
Owner/repo 固定 `Octopus/octopus`。compaction 恢复从 Pattern 6
(读工件索引)开始——源工单上的工件索引是上下文恢复的规范入口,
硬编码页名路径仅作回退。
## Pattern 1: read-wiki-page
```
gitea_wiki__get_page(owner="Octopus", repo="octopus", page_name="{slug}/{page_title}")
```
常用页名(全量文法 + 例外枚举见 `core/rules/artifact-addressing.md` §2):
| 工件 | page_name |
| -------------------------- | ------------------------------------------------------------------------------------------------- |
| 验证报告 | `{slug}/05-verify-iteration-{N}` |
| DAG 工件(单门) | `{epic-slug}/dag`AC 子页 `{epic-slug}/dag-nodes/{node-id}`;覆盖子页 `{epic-slug}/dag-coverage` |
| 评审终报(review-dag | `{epic-slug}/reviews/review-dag/final/report` |
| 评审终报(code) | `{slug}/reviews/code/final/report` |
| 评审终报(code, DAG task | `{epic-slug}/reviews/code/final/report-task-{node-id}` |
| 验证(DAG milestone | `{epic-slug}/05-verify-milestone-{M-id}` |
| 验证(DAG task | `{epic-slug}/05-verify-task-{node-id}` |
| DAG 共享契约 | `{epic-slug}/shared/{file}` |
| bugfix 附件 | `{slug}/repro-notes` · `{slug}/test-report` · `{slug}/bugfix-report` · `{slug}/ABORT` |
| 原型/实现笔记 | `{slug}/prototype-debt` · `{slug}/spike-report` · `{slug}/impl-notes` |
| 设计修订 | `{slug}/03-design-amendments` |
| 审计工件 | `audit/{date}/{page}`,如 `audit/{date}/final/report` |
| 移植工件 | `port-{name}/source-analysis/{file}` · `port-{name}/self-check` |
| 回顾报告 | `_retrospectives/{cycle-name}` |
| 回顾归档 | `_archive/{slug}/` |
| 技能评估 | `_evals/{skill-name}/{page}` |
| 浏览器调试证据 | `{slug}/verify/evidence/{name}`(临时截图留在工作区截图目录) |
历史只读页名(旧管线产物仍可读):`{slug}/01-stakeholder-interview`
`{slug}/02-requirements-index``{slug}/02-req-{seq:02d}-{title}`
`{slug}/02-03-req-design``{slug}/03-design-index`
`{slug}/03-design-{seq:02d}-{title}``{slug}/03-adr-{NNNN}-{title}`
`{slug}/04-plan-index``{slug}/04-plan-{seq:02d}-{title}`
`{slug}/roadmap/{page}``{slug}/shared/{file}`
`{slug}/reviews/{roadmap|design-space|plan}/final/report`
**本地回退(wiki MCP 工具不可用)**:读本地 wiki 克隆(实例路径见
TERMINOLOGY.md)。wiki 文件名 URL 编码(`/``%2F``.md` 前可能带
`.-`),用 glob 而非固定路径解析:
```
glob(pattern="*{slug}*{page-title}*.md", path="<local-wiki-clone>/{repo}-wiki/")
```
## Pattern 2: read-issue
```
gitea_issue__get(owner="Octopus", repo="octopus", index={issue_number})
```
读工单详情、正文、元数据(label、assignee、milestone、state)。
## Pattern 3: read-issue-comments
```
gitea_issue_comment__list(owner="Octopus", repo="octopus", index={issue_number})
```
读工单全部评论(评审结果、状态备注、讨论线程)。
## Pattern 4: read-project-column-issues
```
gitea_column__list_issues(owner="Octopus", repo="octopus",
project_id={project_id}, column_id={column_id})
```
看板列工单队列。project/column 发现:`gitea_project__list` +
`gitea_column__list`
## Pattern 5: read-review-statusCLI
```
octopus review status [--stage <stage>] [--sha <sha>] [--json]
```
读评审收敛状态(commit status)。stage 值:`code``review-dag`
`audit-process`;省略 `--stage` 列出该提交全部状态。历史 stage 值
`design-space` 等)仅可查历史。
**stage-id → 评审目录映射**Tier-1 本地 `reviews/{stage}/` 段):
`review-code``code``review-dag``review-dag`
`audit-process``audit-process`。只有 code 评审用短名,不得发明其他。
收敛判定:context `pipeline/review-{stage}` 的 status 存在且
state = `success`= PASS 或 WARN,无未决 BLOCKER)。退出码 0 = 全部
success1 = 有 failure/error。
## Pattern 6: read-artifact-indexcompaction 恢复主路径)
压缩后或新会话从工单种子恢复时,读工件索引评论(写侧 Pattern 10)
而非猜测页名路径:
```
gitea_issue__get(owner="Octopus", repo="octopus", index={issue_number})
gitea_issue_comment__list(owner="Octopus", repo="octopus", index={issue_number})
# 找 body 以 "## 工件索引"(遗留 "## Pipeline 工件追踪表")开头的评论
gitea_wiki__get_page(owner="Octopus", repo="octopus", page_name=page_name)
```
**位置列提取规则**:单元格形如 ``[`{page_name}`]({html_url})`` ——
取**链接文本**(首个 `[` 与 `]` 之间、剥反引号)作为 page_name,不是
href(含 `%2F`/`.-`API 不认)。裸 page_name 单元格(无链接包裹)也
接受:整格即 page_name。形如 `#comment-{id}` 的值改用
`gitea_issue_comment__list` 读,不得喂给 `gitea_wiki__get_page`。
**重读规则**:重读集 = 全部 `CORE` 行;`ON-DEMAND` 行仅当前任务需要
时读;绝不读 `ARCHIVE` 行。索引缺失(历史工单)→ 回退 issue body +
`## 当前状态` + 硬编码页名路径。
**已归档索引**:无 `CORE` 行,恢复时重读集为空,按需直读目标工件
(位置列 URL 仍有效);归档只改重读优先级,不改可访问性。