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
+116
View File
@@ -0,0 +1,116 @@
# 工件寻址契约(Core,后端中立)
> Core 原生契约(Increment 3,无 dogfood 对应源文件)。术语对照见
> `core/adapters/TERMINOLOGY.md`;本文所有实例路径以占位符表述
> `<runs-root>` = 实例运行目录根),落地实例时按术语表绑定。
## 1. ref 语法
所有 Tier-2 工件的规范引用格式:
```
{backend}:{kind}/{owner}/{repo}/{id}#{anchor}
```
- `{backend}` — 工单后端标识(如 `gitea`);由 adapter 层注册。
- `{kind}` — 工件类别,枚举见下表;新类别扩展时须同步各 adapter 的
resolve 实现并在本表登记。
- `{owner}/{repo}` — 仓库坐标。
- `{id}` — 工件标识:issue/PR 用数字,wiki 页用页名(可含 `/`),
评论用 `{issue-number}c{comment-id}`commit-status 用 `{sha}@{context}`
- `#{anchor}` — 可选锚点(页内段落、行号等),解析时透传不解释。
| kind | 含义 | id 形态 |
| --------------- | --------------- | ---------------------- |
| `issue` | 工单 | 数字 |
| `issue-comment` | 工单评论 | `{issue}c{comment-id}` |
| `wiki-page` | Tier-2 工件库页 | 页名(含 `/` |
| `commit-status` | 提交状态 | `{sha}@{context}` |
| `pr` | 合并请求 | 数字 |
## 2. 页名文法(Core 契约)
Tier-2 工件库的**常规页名**
```
{slug}/{type}-{seq:02d}-{title}
```
- `{slug}``[a-z0-9-]``{seq}` 两位零填充;`{title}`
`[a-z0-9-]`CJK 标题按 adapter 层编码规则处理)。
### 2.1 例外页(全枚举)
以下页名不受常规文法约束(勘自实例的全部真实约定):
| 例外页 | 形态 | 说明 |
| -------------------- | ---------------------------------------------------------------------------------- | --------------------------------------------------- |
| 评审轮次页 | `{slug}/reviews/{stage}/round{N}/{page}` | `page``task-{ROLE}``revision-summary` |
| 评审终报 | `{slug}/reviews/{stage}/final/report` | 含 DAG task 变体 `…/final/report-task-{node-id}` |
| 验证报告 | `{slug}/05-verify-iteration-{N}` | 常规前缀 + 无 title 段的变体 |
| 验证报告(里程碑) | `{epic-slug}/05-verify-milestone-{M-id}` | 同上 |
| 验证报告(任务节点) | `{epic-slug}/05-verify-task-{node-id}` | 同上 |
| DAG 工件 | `{epic-slug}/dag``{epic-slug}/dag-nodes/{node-id}``{epic-slug}/dag-coverage` | 单门 DAG 管线工件 |
| 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` | 常规前缀 + 固定名 |
| 浏览器证据 | `{slug}/verify/evidence/{name}` | 验证证据页 |
| 审计轮次页 | `audit/{date}/round{N}/{page}` | 日期 slug 例外;`page``synthesis``task-{ROLE}` |
| 审计终报 | `audit/{date}/final/report` | 日期 slug 例外 |
| 回顾报告 | `_retrospectives/{cycle-name}` | 跨 slug 命名空间例外 |
| 技能评估 | `_evals/{skill-name}/{page}` | 评估命名空间例外 |
| 移植工件 | `port-{name}/source-analysis/{file}``port-{name}/self-check` | 移植命名空间例外 |
| 回顾归档 | `_archive/{slug}/…` | 归档命名空间例外 |
> 历史只读页名(旧管线产物,仍可读取):`{slug}/01-stakeholder-interview`、
> `{slug}/02-requirements-index`、`{slug}/02-req-{seq:02d}-{title}`、
> `{slug}/02-03-req-design`、`{slug}/03-design-{seq:02d}-{title}`、
> `{slug}/03-adr-{NNNN}-{title}`、`{slug}/04-plan-index`、
> `{slug}/04-plan-{seq:02d}-{title}`、`{slug}/roadmap/{page}`。
### 2.2 kind ↔ type 映射
| 工件类别(kind 语境) | 页名 `{type}` 段 |
| --------------------- | ---------------------------------------------------------------- |
| 验证报告 | `05-verify-iteration` / `05-verify-milestone` / `05-verify-task` |
| 设计文档 | `03-design` / `03-adr` / `03-design-amendments` |
| 计划文档 | `04-plan` |
| 需求文档 | `02-req` / `02-requirements-index` |
| 评审工件 | `reviews`(目录段,非前缀) |
| DAG 工件 | `dag` / `dag-nodes` / `dag-coverage` |
| 审计工件 | `audit`(日期前缀命名空间) |
## 3. Tier-1 ↔ Tier-2 映射
wiki 页 `{slug}/…` 与实例运行目录 `<runs-root>/{slug}/…`Tier-1 本地
结构化工件,见 Two-Tier 规则)按 slug 一一对应:
-`{slug}/reviews/{stage}/round{N}/findings-{DIM}.json` ↔ 本地
`<runs-root>/{slug}/reviews/{stage}/round{N}/findings-{DIM}.json`
- 页面正文承载 Tier-2 决策记录;原始发现、工作草稿留在 Tier-1 本地。
**文件名 URL 编码规则**:页名映射为本地文件名时 `/``%2F`
(逆向解码同理);`.-` 尾缀是实例后端生成的 slug 产物,解码时剥除。
## 4. 双向链接不变量
1. **工件 ↔ 工单引用成对**:工件发布到工件库后,源工单侧必须有反向
索引(工件索引评论);工单侧索引的每一行必须指向真实存在的工件。
2. **单评论聚合**:一个源工单有且仅有一条工件索引评论,各技能只
原位增改自己的行,绝不发第二条。
3. **归档补全**:工单关闭时,关闭方 agent 原位编辑索引评论——加归档
横幅、全部行重读优先级置 `ARCHIVE`;不删行、不改位置列。
## 5. adapter 义务
每个工单后端 adapter 必须实现三个操作:
- **parse** — 解析 ref 字符串为 `{backend, kind, owner, repo, id, anchor}`
- **resolve** — 把解析结果解析为该后端可调用的 API 形态(端点、工具名、
参数),API 调用形态归 adapter 层,Core 不约束;
- **validate** — 校验页名符合第 2 节文法(含例外枚举)。
页名规范是**后端中立契约**;仓里的共用解析器
`script/resolve-artifact-ref.ts` 提供 parse 与页名/文件名编解码、
Tier-1 路径预测的中立实现,adapter 可复用。
+38
View File
@@ -0,0 +1,38 @@
> Core 中立版(Increment 4 改写)。术语对照见 core/adapters/TERMINOLOGY.md;本组织实例表述见 dogfood 对应文件。
## Artifact-Index Guards (mandatory)
> Check-mechanized (injection-budget batch-3, [org-internal #3699]): guards
> 1-3's checkable invariants run in the repo's artifact-index-check script
> (`<artifact-index-check-cmd> <ticket>`, see the term mapping; exit 4 =
> violation, `--json` summary; tolerant of wild archive-marker dialects).
> This file is the normative definition, NOT in any `agents_md` injection
> whitelist since 2026-08-29 — do not re-add; the checks run at write/close
> time regardless. Full spec: Pattern 10 in the shared write-patterns doc —
> this rule is its on-demand distill.
### 1. Legacy-prefix scan (never create a duplicate)
Before creating a `## 工件索引` comment, scan the issue's existing comments
for the legacy prefix `## Pipeline 工件追踪表`. If found, UPGRADE it
in place (edit, not create) and rename. NEVER create a second index comment
(DEFECT-1 / [org-internal #1924]). Mechanized: reports the comment_id to edit.
### 2. Never-duplicate invariant (single-comment)
Exactly ONE index comment per source issue, maintained by in-place
comment-edit via the ticket-backend comment API (reuse the same
`comment_id`). Each skill adds/updates ONLY its own rows, never deletes
another skill's rows. Mechanized: >1 prefixed comment (either prefix) →
exit 4.
### 3. Archive-at-close (issue close → archive, by ANY closing agent)
When a source issue is CLOSED — by ANY agent, verify ran or not — the closing
agent edits the index comment in place: (a) add the canonical archive banner
(Pattern 10) ABOVE the table with the actual close date; (b) set EVERY row's
重读 column to `ARCHIVE`. Do NOT delete rows or change 位置-column URLs;
reversible in-place edit. Mechanized: closed-ticket marker + 重读
completeness → exit 4. Sequence/actor notes: the issue-checklist-sync rule
§ 归档动作; primary path `verify` Phase 5.6 (Verifier); verify-skipping routes
(audit-only, documentation, standalone/bugfix) — the closing agent does it.
+109
View File
@@ -0,0 +1,109 @@
> Core 中立版(Increment 2 改写)。术语对照见 core/adapters/TERMINOLOGY.md;本组织实例表述见 dogfood 对应文件。
## Auto-approve stages
The `auto_approve` block in the instance config controls which pipeline gates
the agent passes without asking the user. Stage identifiers are matched
against the stage registry (harness 内建的阶段注册模块). Unknown or retired
identifiers fall back to manual confirmation (fail-closed) with a one-time
`auto_approve.unknown_stage` warning — copy ids verbatim from the table
below.
## Scope boundary: `auto_approve` vs `permission`
Two **independent mechanisms** — confusing them is the most common
"auto-approve isn't working" report:
- **`auto_approve`** gates **only the `question` tool** (pipeline decision
questions; the harness 内建的自动批准判定模块); no effect on tool
execution.
- **`permission`** gates **tool / file-system operations** (`bash`, `read`,
`write`, `external_directory`, …) and **never consults `auto_approve`**.
`external_directory` defaults to ask, so outside-project prompts are
expected even with every stage enabled.
**`auto_approve` does NOT suppress permission prompts — intentionally so.**
To stop a permission prompt, change the matching `permission` rule or use the
UI's "auto-accept permissions" toggle (browser-local, not the project
`auto_approve` config).
| Stage | Gate | Risk |
| --------------- | ---------------------------- | -------------------------------------------- |
| `review-dag` | DAG single-gate review | Medium — sets direction |
| `review-code` | Code review | Medium — gates what reaches main |
| `verify` | Iteration verification | Medium — runs tests / DoD matrix |
| `audit-process` | Process infrastructure audit | Medium — read-only but gates process changes |
| `merge-pr` | Create PR + merge to main | High — irreversible landing |
> Risk values mirror the stage registry's `BUILTIN_STAGES[].risk` — the
> registry is the runtime authority; if this table and the registry disagree,
> fix this table. `merge-pr` is excluded from default/preset `stages` arrays
> (not structurally blocked; explicitly adding it is not recommended).
> Legacy stage retirement (12 → 5): the phase-3 retirement ruling doc
> (Tier-2 reference, reachable via the ticket backend).
Config shape: `"auto_approve": { "stages": ["review-code", "verify"], "stageless": false }``stages` empty (`[]`) = all manual; `stageless: true` also auto-approves questions called without a stage. Absent block defaults to `{ stages: ["review-code", "verify", "audit-process"], stageless: false }`; the removed `enabled` field migrates on load (mapping: Tier-2 reference page `rules/auto-approve-detail`). Presets (`safe`/`full`/`off`/`show`): same reference page — `full` never includes `merge-pr`.
### Stage matching behavior
- Question has a stage → auto-approved iff that stage is in `stages`.
- Stageless question → auto-approved iff `stageless: true`; otherwise prompts.
- `destructive: true` → ALWAYS prompts, regardless of config — the safety net
for irreversible actions; business-decision questions are never covered by
a stage whitelist (§"Mandatory destructive list").
Check logic: the harness 内建的问询与自动批准判定模块
(resolveAutoApproveDecision).
### Live-gate degradation chain ([org-internal #3531])
An auto-approved question is NOT consumed instantly: L1 — a live human
watching the session (SSE declaration / fresh presence ping) answers within
`question_live_gate.timeout_sec` (default 600) and overrides the default;
L2 — blocking questions with a `#<ticket>` title and a ticket-backend token
fall back to a ticket comment answered as `**answer <question-id>** <label>`
(default 3600s); L3 — auto default (first option, annotated
`live-gate … → auto default`). `timeout_sec: 0` disables the whole gate
(legacy instant default); `l2_timeout_sec: 0` disables only L2.
`nonblocking: true` questions never reach L2/L3 — no live human → parked in
the pending-answer queue, answered later from the console. Every final
decision publishes a `question.degradation.routed` event.
**`destructive: true` is untouched by the chain**: `decide()` rejects it
before the gate runs (iron law).
### Mandatory destructive list (业务决策类问询强制清单)
Origin: [org-internal #3223] — a stage whitelist auto-answered two
irreversible production data changes because nothing marked them
`destructive`. A stage whitelist grants "execution gates may proceed
uninterrupted"; it must NEVER grant "business decisions may be
self-answered". `stage` names the pipeline phase, `destructive` names the
business risk.
**Iron Law: a question whose recommended/executed action falls in ANY category
below MUST be called with `destructive: true`. The auto-approve stage whitelist
is never a substitute for human confirmation of these categories.**
1. **Merge / release landing** — merging a PR to main, cutting a tag or
release, deploying/promoting to production (server-side auto-merge is a
human-configured policy robot, never agent self-answer latitude; kill
switch: the auto-merge-low-risk runbook, Tier-2 reference via the ticket
backend).
2. **Production database writes** — upsert/update/delete against production
data stores, production data migrations, live-data backfills.
3. **Billing / plan changes** — plan or tier migration, pricing/concurrency
changes, anything touching billing state.
4. **Org / tenant structure changes** — org or workspace migration, tenant
topology changes, moving resources between orgs.
5. **Deletion of durable resources** — deleting data, branches, worktrees,
deployments, or any resource outside `/tmp` and session-scratch space.
6. **Persistent config writes** — config changes that outlive the session
(writing to the instance config file, the instance process-config area,
deploy/systemd units, or other on-disk configuration consumed by other
sessions/services).
This list is the floor, not the ceiling: any other irreversible
business-visible decision also carries `destructive`. When in doubt, mark it —
a redundant prompt costs one round-trip; an auto-approved production write can
cost the data. Mirrored in the question tool's self-description for paths
without L1 injection.
+56
View File
@@ -0,0 +1,56 @@
## Claim Discipline (mandatory)
Every status assertion about work — "tests pass", "build succeeds", "bug fixed",
"work complete", "no regressions", "fully resolves" — is a CLAIM that requires
FRESH evidence produced this turn. Confidence is not evidence; a prior run is
not evidence; the change "looking right" is not evidence. Baseline testing
showed agents asserting "tests pass, no regressions introduced" for changes
whose tests were never run — this rule exists to stop that.
**Iron Law: NO COMPLETION CLAIMS WITHOUT FRESH VERIFICATION EVIDENCE.**
Before asserting any status, run the gate:
1. **IDENTIFY** — what exact command/output proves this claim?
2. **RUN** — execute it fresh, this turn (do not recall a prior result).
3. **READ** — the full output and exit code, not just the tail.
4. **VERIFY** — does the output actually confirm the claim?
5. **ONLY THEN** make the claim, and cite the evidence (`file:line`, test name,
exit code, the command run).
**Red-flag language** — reword or remove unless you attach evidence: "should
work", "probably", "seems to", "I'm confident", "fully tested", "comprehensive",
"no regressions", "fully resolves", "works in all cases", "regardless of why",
"exactly", and any expression of satisfaction ("Done!", "Great!", "Perfect!")
uttered before verification has run.
**If you cannot run the proving command** (hypothetical/analysis task with no
codebase, blocked environment): say so — "not verified; would require running X"
— and downgrade the claim from assertion to hypothesis. An honest "unverified"
beats a confident unevidenced claim.
This applies everywhere: commit messages, PR bodies, status reports, review
conclusions, handoff summaries, and verbal confirmations to the user.
## Tool-failure honesty (never fabricate results)
The Iron Law above governs claims about work; this section governs the
**source** of those claims. When a tool you need is unavailable, returns an
error, returns empty, or you cannot otherwise access a required resource, you
MUST report the failure honestly. NEVER fabricate, invent, or hallucinate a
plausible-looking result to fill the gap.
- An honest "I could not call `gitea_wiki__get_page`, so I cannot review
dimension Y" is always correct. An honest failure beats a confident fiction.
- Producing a complete, specific-looking structured result — review JSON with
findings, severity levels, and file references, all invented — without a
successful tool call that supplies the evidence is a **critical defect**,
more dangerous than aborting: the output looks credible but is entirely
fictional and silently poisons every downstream decision.
- This covers every tool-gated output: review findings, test results, file
contents, API responses, search hits, metrics. If the tool did not return
it, you do not know it — say so.
Origin: [org-internal #2115] root cause 5 / [org-internal #2118] — deepseek-v4-flash reviewers fabricated
full review JSON when the `gitea_wiki__*` tools were unavailable to subagents.
+47
View File
@@ -0,0 +1,47 @@
## Code Graph First (mandatory)
Before any cross-file understanding or change, query the code graph first. Do
NOT grep + read whole files to reconstruct relationships.
- **Session start**: run `codegraph_status` to confirm the graph is built; if
empty, run `codegraph init -i` from the project root once. The graph persists
and is reused for the whole session.
- **Trust but verify stats**: `codegraph_status` can return a stale or partial
snapshot. If counts look low, run `codegraph_status` again — codegraph
auto-syncs on file changes (2s debounce via native OS file watcher).
Do not run structural queries against a graph you suspect is incomplete.
- **Structural questions** ("who calls / what depends on / where defined / what
breaks if I change this") MUST use `codegraph_explore` (primary, for flows and
surveys), `codegraph_search` (locate symbols), `codegraph_callers` (every call
site).
Do not piece relationships together from grep + read output.
- **Reading an implementation**: use `read(filePath, symbol: "<name>")` to fetch
only the target symbol's line range. Do not read an entire large file to see
one function.
- **grep is the fallback, not the default**: use grep only for fuzzy text the
graph cannot answer (comments, string literals, config text). Use
`codegraph_node` with `symbolsOnly: true` for a cheap structural overview instead of Glob.
- **Delegate exploration**: prefer running graph + read inside an Explorer
subagent and returning only `file:line` results and conclusions, to keep the
main context lean.
## Per-worktree indexes (mandatory for worktree sessions)
The main checkout's `.codegraph/` indexes ONLY that tree. A git worktree lives
outside the repo path, so nearest-`.codegraph/` resolution finds nothing under
it — graph queries in a workflow worktree silently degrade to grep+read
(the [org-internal #2561] / TD-006 gap).
- `script/session-worktree.sh create` and `script/scratch-worktree.sh create`
build a per-worktree index automatically: `codegraph init -i <path>` runs in
the background (best-effort — missing CLI, existing index, or init failure
never blocks worktree creation). Set `CODEGRAPH_SKIP=1` to disable
(selftests / CI).
- Worktrees created BEFORE this hook landed have no index: run
`codegraph init -i` once from inside them.
- First query after creating a worktree may hit a still-building index; if
results look empty, check `codegraph status` inside the worktree, then retry.
- Kickoff readiness (`checkCodegraph`) checks `<root>/.codegraph/codegraph.db`
per root, and `codegraph serve --mcp` resolves from the session's cwd — both
pick the worktree's own index once it exists.
+112
View File
@@ -0,0 +1,112 @@
> Core 中立版(Increment 2 改写)。术语对照见 core/adapters/TERMINOLOGY.md;本组织实例表述见 dogfood 对应文件。
## Compaction Discipline (mandatory)
Context compaction keeps long pipelines inside the model's context window.
Two mechanisms exist:
1. **Stage-boundary compaction** (main session / orchestrator) —
capacity-driven [org-internal #2601]: compact at a clean stage boundary
ONLY when a capacity trigger holds (below), not merely because the
boundary was reached.
2. **Round-boundary compaction** (multi-round reviews) — compact at every
review round ≥ 2, after the round's state is persisted.
### Stage-boundary compaction (capacity-driven, [org-internal #2601])
The main session orchestrates the whole pipeline while delegating stages to
subagents, but still accumulates their result summaries, planning reasoning,
and todo state — over a full pipeline this can exhaust the context window.
**Rule — compact at clean boundaries only when capacity demands it.** Every
stage persists its complete output to durable artifacts (Tier-2 artifact
pages under `{slug}/…`, Tier-1 run workspace files) on completion. At each
CLEAN boundary (artifacts written, next stage not yet dispatched), evaluate
the triggers:
1. **Capacity trigger** — the harness's compaction recommendation has fired,
context is near the threshold, or the agent observes context-pressure
symptoms (truncation, degraded recall of earlier stage outputs).
2. **Projection trigger** — the stages REMAINING on this route (skip list in
the routing table) will not fit alongside the context already
accumulated, based on per-stage growth observed so far.
A trigger holding → compact at the NEAREST clean boundary. No trigger → KEEP
the context: preserved working context is worth more than the tokens it costs.
**Mixed capacity threshold — min(water_level, absolute cap)
[org-internal #3321] / TD-434]**: the capacity threshold is
`min(context × water_level, compaction.max_context_tokens)` — whichever is
LOWER (`max_context_tokens` default 100_000; `0` restores pure water_level
semantics [org-internal #3342]). On large windows the 100k cap binds first.
Measurement basis: the provider's REAL reported usage (input tokens), not
local estimates; the rendered guidance and the Trigger A/B overflow paths
resolve the same normalized values (harness 内建的压缩引导模块, see the
instance term mapping).
**Sub-session posture [org-internal #3321]**: Explorers compact by returning
promptly, persisting only what their skill protocol REQUIRES (review findings
JSON to the run workspace reviews directory). Workers persist outputs to
Tier 1 BEFORE finishing. The parent context is where the mixed threshold
applies. Tier 1 boundary: two-tier-artifacts rule.
**Short runs target zero intra-run compaction** — an implement →
review-code → verify run fits one window; clean boundaries do not compact
without a trigger. (Rationale + retired legacy stages: Tier-2 reference page
`rules/compact-detail`, reachable via the ticket backend.)
Clean boundaries where triggers are evaluated (live skills):
- After `analyze-dag` completes (before the `review-dag` single gate)
- After each `review-*` converges (before the next production stage)
- After `implement` / `verify` completes (before its review or the next stage)
**Never compact mid-stage** — not mid tool-call cycle, not mid subagent
dispatch. Compact only at clean boundaries where artifacts are already
persisted.
**Re-orient after compacting** (recovery contract): compaction discards the
in-conversation record of the current slug and stage. Before resuming,
re-read the persisted recovery set — the Tier 1 compact-recovery entry
`index.json` in the run workspace, the issue's `## 工件索引` CORE rows, the
frozen DAG copy (`{epic-slug}/dag`, `{epic-slug}/dag-nodes/{node-id}`) for
DAG-routed runs, the latest review pages, or the DoD matrix
(`{slug}/05-verify-*`) — to recover the current slug, stage, and outstanding
items. Do not rely on the compacted summary alone.
**Identity verification precedes re-orientation [org-internal #2459].**
Every compacted summary opens with a harness-injected `### Session Identity`
card (agent, role/mode/ticket, CORE artifact rows, role re-read set),
rendered from role-yaml `compact.preserve` lists and issue CORE rows by the
harness 内建的压缩引导模块 (renderIdentityInjection; preserve lines keyed
through identityPreserveLines). Role yaml preserve lists are
harness-enforced — recovery is always via the persisted artifact, never
conversation memory. Verify the card against the durable record
(title/purpose, issue assignee + claim, orchestrator id); on mismatch stand
by and report, never act on the summary's identity claims.
### Round-boundary compaction
Multi-round review skills (`review-artifact`, `review-code`) compact at every
round boundary ≥ 2. Canonical text: shared compaction-round-boundary doc
(injected by both review skills); read it for the exact orchestrator
procedure — do not restate.
### The `min_turns_since_compaction` guard applies everywhere
The `compact` tool rejects calls made too soon after the previous one
(`compaction.agent.min_turns_since_compaction`, default **3** assistant
turns); no boundary type is exempt. Beyond `insufficient_turns` the tool has
more guard outcomes (`min_interval`, `no_model`, `circuit_breaker_open`,
`disabled` — rejected; `compaction_in_progress`, `deduplicated` — deferred;
full table: Tier-2 reference page `rules/compact-detail`, reachable via the
ticket backend). All are accept-and-continue: never retry past a guard,
never work around the dedup/breaker state. A boundary whose compaction was
rejected or deferred simply keeps its context; the persisted artifacts still
bound what accumulates.
### Role-level re-read set
Role YAML `compact.preserve` lists are harness-enforced: after any compaction
the session agent's preserve lines are injected at the summary head; recovery
is always via the persisted artifact, never conversation memory.
+159
View File
@@ -0,0 +1,159 @@
> Core 中立版(Increment 4 改写)。术语对照见 core/adapters/TERMINOLOGY.md;本组织实例表述见 dogfood 对应文件。
## Issue Checklist Sync (mandatory, progressive)
The source issue's checklist is the **stakeholder-facing progress tracker**.
It MUST be kept in sync with actual work state at every pipeline milestone —
not just at close time. Stakeholders should be able to open the issue at any
point and see exactly what is done, in progress, and deferred.
### Sync points (progressive)
| When | Who | What |
|------|-----|------|
| After the DAG artifact is frozen (`review-dag` PASS + freeze confirmation per `analyze-dag/SKILL.md` §Output & Lifecycle step 2, [org-internal #3379]) | Aggregator agent | Convert the source Epic's draft acceptance criteria into a formal checklist; annotate requirement-covered items `_(DAG frozen: {epic-slug}/dag v1)_` |
| After each iteration commit (`implement` Phase 4.5) | Developer | Check off items delivered by this iteration |
| After a PR is created | Developer | Append a `## 当前状态` live-status section (or update it) with PR number + mergeable; in an Epic task list, append the PR reference to the corresponding row |
| After code review converges (`review-code` PASS, Phase E) | Orchestrator | Check off review-related items; annotate `_(reviewed: round N PASS)_`; update the `## 当前状态` review row; label the PR `ready-to-merge` — keep-mergeable automation takes over (hand-written keep-mergeable commits are retired) |
| On CI key state transitions (first green / failure / cumulative goal reached) | Verifier or Developer | Update the process-type AC (e.g. "N consecutive green runs") progress note in the issue; record the run number |
| At `verify` Phase 5.6 (final sweep before PASS) / issue close | Closing agent (Verifier on the primary path; otherwise the last role that closes the issue) | Final sweep — every remaining item gets annotated; **archive-at-close**: fold `## 当前状态`, then mark the `## 工件索引` comment archived per the artifact-index-guards rule guard #3 (see「归档动作」below) |
> Historical ([org-internal #3072] phase 3): the requirements/design/plan exit sync points
> were archived with their skills (detail: Tier-2 reference page
> `rules/issue-checklist-sync-detail`, reachable via the ticket backend).
Between sync points the checklist stays as-is. **PR / review / CI
transitions** MUST also be visible via the live status note below — the
checklist is not the only carrier.
### Live status note (`## 当前状态`)
For flows with externally visible transitions between skill exits —
standalone bugfix, incident response, long-running reviews — maintain a short
live status table near the top of the issue body, updated in place via the
ticket-backend issue-update API at the transition moment (closes the
stale-issue gap [org-internal #1668]/[org-internal #1689]]).
All roles use the literal heading `## 当前状态` (no suffix). If an issue carries
a legacy variant (e.g. `## 当前状态 (live)` from [org-internal #1668]), normalize it to
`## 当前状态` at the first transition touched. Example table + legacy-variant
list: Tier-2 reference page `rules/issue-checklist-sync-detail`, reachable
via the ticket backend.
Rules:
- One row per externally visible transition. Skill-exit sync points are
surfaced by checklist annotations alone — do NOT add live-status rows for
them. PR / review / CI transitions carry BOTH a checklist annotation AND
a live-status row.
- **Stage rows live on the board, not here**: pipeline stage transitions are
represented by the Pipeline Stages board column (shared write-patterns
Pattern 7.5), NOT by `## 当前状态` rows. Keep only the
status-sync-automated rows (PR / 代码评审 / CI) and non-stage
blockers/deferrals.
- Update in place (same section heading `## 当前状态`), never append a second copy.
- Optional for quiet pipeline flows; **MANDATORY for incident-response and
standalone-bugfix flows** (long windows without skill exits).
- At verify PASS / issue close, fold the table's content into checklist
annotations and remove the section (see the「归档动作」section below).
### Automated sync ([org-internal #1833], timer-polled since [org-internal #2813])
PR / review / CI status-row transitions are automated by the `status-sync`
poller (deployed as a host timer, every 5 min; event sources + latency table
on the Tier-2 reference page `rules/issue-checklist-sync-detail`, reachable
via the ticket backend). Roles do NOT hand-write those three row types. A PR
body may carry several close refs (batch PRs, [org-internal #3731]
`land-batch`): rows fan out to EVERY referenced issue
(`parseClosesFixesWide` — [org-internal #3867], merged 2026-08-31) — Chinese 关闭/修复 refs
drive rows too, even though the ticket backend never auto-closes those
keywords. The remaining sync points (checklist annotations at skill exits,
`## 当前状态` creation, deferral/pending marking, section fold-at-close) are
still manual (content judgment, not event detection). Fallback for poller
outages / manual replay: the `status-sync` manual dispatch
(`issue`/`row`/`value`) — the row-write engine is a no-op when the section
or row is absent, never creates or corrupts them; poller failures file a
deduplicated `[status-sync-cron]` issue.
### Standalone bugfix / incident flows
Pipeline mode has natural sync points at skill exits; standalone bugfix and
incident flows do NOT — the only boundaries are commit → PR → review → CI →
merge, and EACH is a sync point with the same annotations as the progressive
table above (full table: Tier-2 reference page
`rules/issue-checklist-sync-detail`, reachable via the ticket backend): fix
commit → tick fix-delivered ACs `_(commit {sha}: file)_`; PR → open/update
`## 当前状态`; review convergence → tick review ACs + review row; CI
transitions → process-AC progress with run number; verify PASS / close →
final sweep, fold `## 当前状态`, archive per「归档动作」.
### DAG-routed tickets — node checklist variant
For tickets routed through the DAG pipeline (see workflow-routing rule
§"DAG 路由 (v2)"), the task-node checklist has a fixed shape (spec-08
§1/§2/§3):
- **Task tickets (nodes) use a fixed 5-row checklist** + an optional 6th row:
验收标准 / 依赖就绪 / PR / 评审(review-code) / CI — **fixed 5 rows, fixed
order, no free additions**. The `verify里程碑` row exists ONLY when the node
fans into a milestone.
- **Row 6 close-time semantics**: if at ticket close the milestone is not yet
green, keep `- [ ]` + `_(Pending: M-01 未 green)_` — mapped to **Pending**, not
STALE, so it satisfies the Iron Law (no stale items at close). After milestone
verify PASS the aggregator agent flips it to `- [x]` in place.
- **Epic aggregator `## DAG 状态` vs `## 当前状态`**: `## DAG 状态` is the
node-status aggregator table (one row per DAG node — never carries ARCHIVE);
`## 当前状态` carries only PR / 评审 / CI rows (no stage rows).
- **Archive rule unchanged**: the archive marker stays ONLY on the `## 工件索引`
comment (single-comment invariant). The body aggregator table is kept as a
historical snapshot at close and does NOT carry ARCHIVE.
### Kind/MVP tickets — exemption ([org-internal #3061])
`Kind/MVP` tickets run the interactive no-pipeline mode: no stage exits →
**nothing to sync**, no `## 当前状态` section (no PR/review/CI rows until
graduation). The body itself is the living document: `## 决策日志` is
append-only (superseded decisions struck through, never edited); `## Debt
Register` rows update in place. On graduation (relabel `Kind/Feature`) normal
sync rules resume from the DAG route; the decision log stays as backfill input.
### Annotation format
- **Done** → `- [x]` + parenthetical evidence: `_(PR #NNN: file/component)_`
or `_(commit {sha}: file)_` if no PR yet.
- **Deferred** → keep `- [ ]` + `_(Deferred: TD-XXX <reason>)_`.
- **Pending** → keep `- [ ]` + `_(Pending: <blocker>)_`.
### How to sync (each point)
Find the source issue (`Closes #N` / `Fixes #N` in the PR body or commit
messages, `## 父级 / Parent` / roadmap chunk mapping, or the issue the user
referenced; none exists → skip). Fetch the body, map each `- [ ]` item
**relevant to this sync point** to evidence (`- [x]` + `_(PR #NNN: …)_` /
`_(commit {sha}: file)_`), deferral, or pending — leave out-of-scope items
untouched for a later point — and update in place, preserving all
non-checklist content. PR / review / CI transitions ALSO go into the
`## 当前状态` live-status section.
### 归档动作(issue 关闭 = 归档)
**生命周期 = 工单生命周期**[org-internal #1929]):文档生命周期与源 issue 绑定 —— verify PASS → issue 关闭 = 归档。Tier-2 工件库无独立生命周期。
归档是 **显式动作**,由关闭 issue 的 agent 执行:主路径为 Verifier 在 `verify` Phase 5.6;路径跳过 verify 时(audit-only、文档类、standalone/bugfix)由关闭 issue 的 role 代为执行。无论哪个 actor,均遵循 artifact-index-guards 规则 guard #3(机制以共享 write-patterns Pattern 10 为准)。动作序列:
1. **Checklist 终扫**Phase 5.6 既有步骤 / closing agent 补执行):每个 `- [ ]` 项都被注解(done / deferred / pending)。
2. **Fold `## 当前状态`**Phase 5.6 既有步骤 / closing agent 补执行):表格内容折入 checklist 注解后移除该节。
3. **标记 `## 工件索引` 归档**:按共享 write-patterns Pattern 10 Archive-at-close 原位 edit(机制以 Pattern 10 为准)。横幅日期以实际关闭日为准。
4. **关闭 issue**PR body 的 `Closes #N` 在 merge 时自动关闭;无 PR 的流程由 **关闭 issue 的 agent** 执行工单后端的 issue-close API 完成闭环。
约束([org-internal #1928] 设计约束;机制细节以共享 write-patterns Pattern 10 Archive-at-close 为准,此处不重复):
- **L 级大件(>~300 行)留 Tier-2 工件库不删除** —— 页面与位置列 URL 保持不动(稳定 URL 供历史与共享契约引用)。
- **索引/状态/归档判定全部收敛到 issue** —— Tier-2 工件库无独立生命周期;归档标记只落在 `## 工件索引` 评论。
- 归档标记可逆(原位 edit):PR 被拒 / issue 重开时恢复行级 重读 即可。
### Iron Law
NO ISSUE MAY BE CLOSED WITH STALE CHECKLIST ITEMS. If a checklist item
cannot be mapped to evidence or deferral at verify time, the iteration is
NOT done.
+72
View File
@@ -0,0 +1,72 @@
> Core 中立版(Increment 4 改写)。术语对照见 core/adapters/TERMINOLOGY.md;本组织实例表述见 dogfood 对应文件。
## Issue Cross-Linking (mandatory)
Traceability flows in two directions. Both MUST be maintained so a
reviewer can start at any node — an issue or a Tier-2 artifact-library page —
and navigate to every related artifact without asking.
### Issue ↔ issue (parent/child groups)
When creating a **group** of related issues — an Epic with phase/P-level
sub-tasks, a roadmap decomposed into chunk tickets, a bug with a
regression-test follow-up, or any parent/child breakdown — the issues MUST be
cross-linked:
- **Parent issue**: after creating all children, update the parent body so its
task list references each child by `#<number>` (e.g. `- [ ] [org-internal #1556] — [P0] ...`).
The ticket backend renders these as clickable links and auto-generates a
back-reference on each child's timeline.
- **Child issue**: its body MUST contain a `## 父级 / Parent` section referencing
the parent by `#<number>`.
- Never create a group of issues that is only one-way linked or not linked at
all. The parent task list is the single navigation hub.
### Issue ↔ Tier-2 artifact (pipeline traceability)
When a production skill (`analyze-dag`, publishing the `{epic-slug}/dag`
artifact; historically the pre-[org-internal #3072] producer skills) publishes
an artifact to the Tier-2 artifact library, the link to the source issue is
only **half-built** — the library's index page links forward to the issue,
but the issue has no link back to the library. A stakeholder opening the
issue sees no path to the pipeline artifacts — the traceability chain is
broken.
After publishing, the skill MUST complete the reverse link on the source issue:
- **Post / update the "## 工件索引" comment** (工件索引协议, per the shared
write-patterns doc Pattern 10): a single in-place-edited comment (via the
ticket-backend comment-create, then comment-edit API; NEVER post a
duplicate; legacy prefix "## Pipeline 工件追踪表" is upgraded in place). One
row per artifact: `{工件 | 类型 | 版本 | 位置 | 重读}` where **重读**
{`CORE`, `ON-DEMAND`, `ARCHIVE`}.
- **The CORE rows ARE the compaction re-read set** — after `compact`, recovery
reads the 工件索引 comment and fetches every CORE row's 位置 (shared
read-patterns doc Pattern 6), instead of hard-coded library paths. Skills'
re-read instructions therefore point at the index.
- **Archive-at-close(归档动作, [org-internal #1929]/[org-internal #1928]** — issue 关闭即归档;Tier-2 工件库无独立
生命周期。`ARCHIVE` is not just a per-row re-read priority: at issue close the
whole index is marked archived by the closing agent (Verifier at `verify`
Phase 5.6 on the primary path; otherwise the Orchestrator / last-role that
closes the issue) via in-place edit. The mechanism (banner + every row's
重读 → ARCHIVE, single-comment invariant, rows/位置 URLs never deleted,
L-level library artifacts keep stable URLs) is defined once in the shared
write-patterns doc Pattern 10 Archive-at-close — reference it, do not
restate. Sequence and actor: the issue-checklist-sync rule § 归档动作.
- **Sync the issue's checklist** per the issue-checklist-sync rule for the
matching exit point (live: the DAG-freeze sync point after `review-dag`
PASS; the legacy requirements-exit / design-exit / plan-exit points were
retired with their skills, [org-internal #3072] phase 3).
- Skip if no source issue exists (no `Closes #N` / `Fixes #N` / roadmap chunk
mapping ties this slug to an issue).
**Size/S & Size/M exception ([org-internal #1832]) — RETIRED (2026-08-21, [org-internal #3072]
phase 3)**: retired with the legacy producer skills and the `sizing:` block.
Historical indexes pointing at in-issue artifacts (`位置 = #comment-{id}`)
remain valid, readable locations; new artifacts publish where their live
skill/route puts them (DAG: library page `{epic-slug}/dag` etc.; MVP: ticket
body).
Authoritative implementation patterns: shared write-patterns doc Pattern 3
(issue↔issue) and Pattern 10 (issue↔artifact index) under the skills'
shared-artifacts directory.
+115
View File
@@ -0,0 +1,115 @@
> Core 中立版(Increment 4 改写)。术语对照见 core/adapters/TERMINOLOGY.md;本组织实例表述见 dogfood 对应文件。
## Session Scope Guard (mandatory)
> Enforcement layer: precheck-mechanized (injection-budget batch-2,
> [org-internal #3667]) — pre-flight sources 1-3 below live in the repo's
> session-conflicts script, source 4 in the claim script's compare-and-swap.
> This file is the normative definition, NOT part of any `agents_md`
> injection whitelist since 2026-08-29 — do not re-add; the checks run at
> claim time regardless.
Standalone and ticket-seeded sessions run without a pipeline around them —
no plan, no reviewer keeping them inside their work item. When such a
session hits a test failure NOT caused by its own change ([org-internal
[org-internal #1803]], via [org-internal #1753]/[[org-internal #1744]]), it tends to fix the foreign
failure in place (drifting off-task), and sessions seeded for the same issue
collide on the same shared flaky test.
**Iron Law: if a test fails and it was NOT caused by your change, you MUST
classify → file → continue. Do NOT fix it in place — unless that test IS your
task.**
### The classify → file → continue protocol
1. **Classify** — rerun the failing test on the base commit / last-green:
fails there too → **baseline failure (BF)**; intermittent across runs →
**flaky test (FT)**; fails only with your change → **your regression**
fix it now.
2. **File** — register every BF/FT as an issue in the ticket backend labeled
`baseline-failure` or `flaky-test` with a `BF-NNN` / `FT-NNN` id, per the
testing rule. Deduplicate against an existing BF/FT issue (comment your
run evidence instead of filing a twin).
3. **Continue** — return to your assigned task; cite the BF/FT issue number
in your report / PR body so the next session sees it is owned.
A foreign failure does not block your task, but the task is NOT done until
the failure is filed — an un-filed BF/FT is a process gap. Filing is the
whole job: **the fix belongs to whoever owns that test**, not to you.
### One task, one owner — check before you start
Before starting work on an issue or code area, you MUST verify no other
session already owns it. The pre-flight check spans four sources — (1) live
sessions referencing `#N`, (2) a workflow branch already covering #N
(worktrees, local branches, remote `workflow/*` refs), (3) an open PR
referencing `#N`, (4) assignee + claim comment naming another owner. A hit
on ANY source → the ticket is already owned: ABORT (or, for a DEAD claim,
take over via the mechanized channel below; otherwise coordinate on the
issue), never silently start a second owner.
**Mechanized ([org-internal #3667])**: the repo's session-conflicts script
(`<session-conflicts-cmd> <ticket>`) scans sources 1-3 in one read-only pass
(exit 4 = conflict, matching the claim script; source 1 fail-opens visibly
when the app API is down — the backend hard guard [org-internal #1989]
backstops); source 4 IS the claim script's compare-and-swap. Dead-claim
takeover is mechanized in the claim script (see below); manual recipes:
the headless-session-ops skill's ticket-recipe reference §0.
**Dead-claim takeover ([org-internal #3668]).** A claim whose session is
gone (404 on the app API) and whose branch was never pushed is a DEAD claim
— the [org-internal #3419] shape. Do NOT hand-edit the dead claim comment
(the retired admin workaround — unauditable); run the claim script's
takeover subcommand (`<claim-takeover-cmd> <ticket> <branch> --session-id
<id>`) instead. Evidence rule (the claim script's header is normative): a
competing claim is dead iff its named branch is ABSENT on the remote AND
(its session 404s OR the comment is at least `CLAIM_TAKEOVER_STALE_DAYS`
old — age >= the threshold, default 3d). Evidence holds → one atomic
takeover: assignee re-set + a `**claim**` comment carrying
`supersedes-claim #<id>` markers and the inline evidence (auditable chain,
nothing edited) + branch push, with post-posting race re-verification.
Evidence fails (session alive, branch pushed = completed claim, or fresh
claim with unknown liveness) → exit 10, zero mutation — coordinate on the
issue or salvage the worktree instead. A valid claim is never superseded.
**Claim-first (atomic 3-step claim).** The FIRST action when starting
ticket-driven work is to claim the ticket — one atomic action of THREE
steps, valid ONLY when all complete: (1) set the issue assignee to the
working account, (2) post a claim comment naming the workflow branch and
session id, (3) push the workflow branch to remote (even an empty commit —
a purely local branch is invisible to other sessions, [org-internal
[org-internal #2280]/[org-internal #2282]]). Use the repo's claim wrappers (staged-transaction claim
script; exit codes and CAS semantics in its header; non-zero = NOT claimed)
and the provision wrapper (adds the worktree + Tier-1 runs scaffold). The
manual 3-step is the fallback where the scripts are unavailable, same
re-verification.
**Merge-time equivalence check.** Before merging, scan the remote main
branch's recent commits for `#<ticket>` — surfacing an equivalent
implementation already on main *before* the merge rejection.
**Merge-time review gate ([org-internal #2345]).** `pipeline/review-code` is
a required status: merge needs it green OR the route-based exemption
(Kind/* close routes skip review-code — posted by the repo's
review-gate-exemption script). Read the commit-status endpoint for the PR
SHA: `success` + `review not required (route:` description → route
exemption, proceed; `success` otherwise → proceed; missing / `error` /
`pending` / other → BLOCK — a missing status never approves.
**Epic ownership table.** Multi-chunk parallel Epics keep a chunk →
session/account ownership table on the parent issue — consult it and claim
your chunk before starting.
Two sessions owning the same issue or code area is never faster — it is the
exact collision this rule prevents. If a collision HAS happened, follow the
failure-path playbook at the ownership-collision runbook (Tier-2 reference
page, reachable via the ticket backend).
### Scope
Applies semantically to **every session** — pipeline subagents (Producer /
Verifier / Reviewer / Tool) and standalone/ticket-seeded sessions alike;
for subagents, "your task" is the delegated prompt's scope, and classify →
file → continue applies unchanged. Filing rides the testing rule;
launch-time owner checks live in the headless-session-ops skill (which
points here). This file stays the normative definition — read on demand.
+113
View File
@@ -0,0 +1,113 @@
## Stash Discipline (mandatory)
> Enforcement layer: **L0 tool-enforced** (bash guard + husky hooks) — this
> file is reference/documentation, NOT part of any `agents_md` per-turn
> injection whitelist since the 2026-08-27 injection-budget batch-1. Do not
> re-add it to a whitelist; the guard enforces regardless.
In the octopus worktree model, multiple parallel sessions share a single git
repository. The git **stash stack is repository-global** (`stash@{0}`,
`stash@{1}`, …) and is NOT isolated per worktree. When two sessions in
different worktrees run `git stash` / `git stash pop`, they silently index
each other's entries and one session's `pop` returns the other session's
content — or `drop`/`clear` wipes uncommitted work belonging to a session in
a different worktree.
This failure mode has already destroyed completed work in production ([org-internal #1655] /
[org-internal #1629] — a finished 25-test implementation overwritten on the shared stack).
**Iron Law: NEVER use `git stash` (or `git stash pop` / `push` / `drop` /
`clear` / `apply`) inside an octopus worktree.**
The bash tool enforces this at L0 via a safety-floor pattern that blocks
`git stash` invocations. Use one of the following instead — they are
worktree-local and cannot be clobbered by a parallel session:
### Approved alternatives
1. **WIP commit on the current workflow branch** (preferred for
mid-iteration checkpoints):
```bash
git add -A
git commit -m "wip: <slug> — <one-line state>"
# … later, before the real commit:
git reset --soft HEAD~1 # un-commit but keep the work staged
```
The per-iteration commit model already expects these to be cleaned up by
amend / interactive rebase before merge, so a `wip:` commit is never a
long-term smell.
2. **Throwaway side branch** (preferred when you must switch branches and
cannot commit yet):
```bash
git switch -c wip/<slug>-<topic>
git add -A && git commit -m "wip: <slug> — <one-line state>"
git switch - # back to the workflow branch
# … later:
git cherry-pick wip/<slug>-<topic> # or merge / reset as needed
git branch -D wip/<slug>-<topic>
```
3. **`git diff > /tmp/octopus/<slug>.patch`** (last resort, when even a WIP
commit is impossible — e.g. the index is in a conflicted state you do not
want to disturb):
```bash
git diff --binary > /tmp/octopus/<slug>.patch
git apply /tmp/octopus/<slug>.patch # restore later
```
Keep the patch under `/tmp/octopus/` so it survives the session but is
never accidentally committed (see wiki page `rules/temp-files`, L2
on-demand).
### What about switching away from a dirty tree?
If you must `git checkout <base>` to reproduce a failure but the worktree is
dirty, do **not** reach for stash. Instead:
- WIP-commit first (option 1), or
- Use the lifecycle-managed scratch-worktree script ([org-internal #2790]) to materialise
the base commit in a *separate* worktree and run the failing test there:
```bash
bash script/scratch-worktree.sh create <slug>-base <base>
bash script/scratch-worktree.sh remove <slug>-base
```
This is the pattern the `verify` skill uses for the regression-vs-baseline
classification check. The script registers the worktree, symlinks
`node_modules` from the source checkout when `bun.lock` matches, and the
`sweep` backstop reclaims worktrees abandoned by dying sessions — bare
`git worktree add /tmp/octopus/...` has no such recovery ([org-internal #2790]).
### Exceptions
- Running `git stash list` / `git stash show` to *inspect* the stack (no
mutation) is allowed — it cannot lose work. The safety-floor pattern only
blocks mutating subcommands (`push`, `pop`, `apply`, `drop`, `clear`,
`create`, `store`, `branch`, and bare `git stash`).
- The TUI's **prompt stash** (`prompt.stash` keybind, `usePromptStash`) is
unrelated — it stashes *input text* in memory, not git refs, and is not
affected by this rule.
### Enforcement
- **L0 (tool-enforced)**: `packages/octopus/src/tool/bash.ts` adds
`/\bgit\s+stash\b(?:\s+(?:push|pop|apply|drop|clear|create|store|branch)|\s*$)/`
to `SAFETY_FLOOR_PATTERNS`. Safety-floor items cannot be unblocked via
configuration; bypass requires `--no-security-config`.
- **L1 (this file)**: reference documentation only — removed from every
`agents_md` injection whitelist (2026-08-27, see header); the L0 guard
enforces regardless.
- **L2 (skills)**: any skill that suggests `git stash` is a defect — file it
under Kind/Enhancement with the `retrospective` label (`verify` SKILL.md
already uses `script/scratch-worktree.sh` instead).
If a parallel-session stash collision happens again despite this rule, treat
it as a Sev-2 process incident: stop work, recover via
`git fsck --unreachable` / `git log -g --walk-reflogs stash`, open a follow-up
referencing [org-internal #1655].
+145
View File
@@ -0,0 +1,145 @@
> Core 中立版(Increment 2 改写)。术语对照见 core/adapters/TERMINOLOGY.md;本组织实例表述见 dogfood 对应文件。
## Testing
- Avoid mocks as much as possible
- Test actual implementation, do not duplicate logic into tests
- Tests cannot run from repo root (guard: `do-not-run-tests-from-root`); run from package dirs.
- **Local pre-check: run `<test-cmd:changed>`** from the owning package after editing source. It selects only tests affected by your uncommitted + branch changes (path-mapping CodeGraph direct dependents) and runs them in a single process — seconds, machine stays responsive. Use `--print` to see the selection without running, `--all` to scan beyond the home package.
- **Before a delivery push: `<test-cmd:changed>` green + `<typecheck-cmd>` clean** — same selector as CI's PR side (local parity, [org-internal #4425]). The full suite (`<test-cmd:parallel>`) stays with nightly / `run-full-tests` / manual pre-merge runs. 实例命令绑定见 core/adapters/TERMINOLOGY.md。
- Never use the bare single-process test runner for the full suite; `<test-cmd:parallel>` shards it and process-isolates known-corrupting files. Parallelism is controlled by `TEST_SHARDS` (default 3; raise it on beefy CI runners, e.g. `TEST_SHARDS=7`).
### Pre-existing test failures must be filed, not silently logged
When the full suite surfaces a failure that is **NOT caused by the current
change** (it reproduces on the base branch / last-green commit too), it is a
**pre-existing / baseline failure**. Do NOT silently drop it as "someone else's
problem" and do NOT bury it in a report body.
- Classify it: run the failing test on the base commit (see `verify` Phase 2.6).
Fails there too → pre-existing (BF); passes there → regression you must fix.
- De-duplicate BEFORE filing (retro [org-internal #2696]): search existing
`baseline-failure` tickets — open AND closed — by test/file name to surface
candidates, then match by **failure signature** (error signature + affected
surface — one root-cause family may span several tests; see the
ticket-lifecycle rule §"BF / FT family umbrellas"). On a signature hit,
attach run evidence to the family umbrella; do NOT create a new ticket.
- File it: the Verifier registers every un-tracked pre-existing failure as a
ticket-backend issue labeled `baseline-failure` with a `BF-NNN` id (`verify`
Phase 5.55). The number is repo-wide sequential: highest existing NNN across
ALL `baseline-failure` tickets (open AND closed) + 1 — duplicate ids
forbidden, including against closed tickets.
- A pre-existing failure does not block the iteration that *discovered* it, but
the iteration is NOT Done until it is filed — an un-filed baseline failure is
a process gap.
### Flaky tests must be filed, not silently tolerated
When a test passes and fails intermittently across runs (non-deterministic),
it is a **flaky test**. Do NOT silently re-run until it passes and move on.
- Detect: re-run the suite (or use the project's flaky detector). Record every
test that shows intermittent behavior — name, failure rate, and run count.
- De-duplicate BEFORE filing (retro [org-internal #2696]): same
signature-based procedure as baseline failures above, against existing
`flaky-test` tickets.
- File it: the Verifier registers every un-tracked flaky test as a
ticket-backend issue labeled `flaky-test` with an `FT-NNN` id (`verify`
Phase 5.56). `FT-NNN` allocation follows the same repo-wide sequential rule
as `BF-NNN`, across ALL `flaky-test` tickets (open AND closed).
- A flaky test does not block the iteration verdict, but the iteration is NOT
Done until every unfixed flaky test is filed — an un-filed flaky test is a
process gap.
**Filing is the whole job.** If the failure was NOT caused by your change, do
NOT fix it in place — classify, file, and return to your task per the
session-scope-guard rule. A repository-wide flaky test is a shared magnet —
fixing it in place drifts off-task and collides with its owner
([org-internal #1803]).
### Testing Kobalte components with happydom
Kobalte's portal/context-based components (Collapsible, DropdownMenu, ContextMenu,
FormControlContext) do not work reliably under happydom's DOM environment. For
these components, use **source-verification tests** — assert that the correct
JSX elements, props, and Kobalte primitives are present in the component's
source rather than attempting full DOM rendering.
When implementing a component that uses these Kobalte primitives, prefer
source-verification over render tests. The same applies to SolidJS SVG
`<filter>`/`<mask>`/`<linearGradient>` elements, which happydom also cannot
render reliably.
### Test file naming convention (one file per component)
A single component MUST NOT carry both a `.test.ts` and a `.test.tsx` test
file — the two-file split duplicated ~3300 lines of overlapping assertions
across one UI package [org-internal #1712]. Use exactly one file per
component, chosen by test style:
| Test style | Extension | When to use |
| -------------------------------- | -------------- | -------------------------------------------------------------- |
| Source-verification | `.test.ts` | Kobalte portal/context components, SVG `<filter>`/`<mask>`/`<linearGradient>` components, and any component happydom cannot render reliably. Asserts against the component source. |
| DOM render / interaction | `.test.tsx` | Pure Solid components that render cleanly under happydom. Uses a testing-library harness. |
Rules:
- One file per component. If a component needs both source-verification and
DOM-render assertions, keep them in a single file matching the dominant
style; do not split into a `.test.ts`/`.test.tsx` pair.
- When merging an existing dual pair, carry over any assertion unique to the
deleted file into the surviving file before deletion.
- The app package's `.sv.test.*` suffix is a separate convention for
storybook/storyshots source-verification and is unaffected.
### Source-verification assertion boundaries
Source-verification tests (per the Kobalte/happydom carve-out above) must assert
**structural contracts**, not implementation literals.
- **Assert**: props wiring, event handler attachment, i18n key presence, ARIA
role/attributes present in JSX, namespace correctness, export shape.
- **Do NOT assert**: exact source-string literals (`event.preventDefault()`,
`'block: "nearest"'`, `event.movementX === 0`), branch operators counted via
regex, or any expression that changes when a constant is renamed.
- **Do NOT write tautologies** — `source.includes("false") || source.includes("!")`
is true for nearly all TSX.
- **One source-verification file per component** (see naming convention above).
When two test files read the same source, merge into one.
- **Prefer behavioral tests** — when source-verification and a behavioral/
interaction test cover the same contract, prefer the behavioral test;
collapse the SV duplicate.
### Namespace gate and test assertions
The namespace gate (pre-commit hook + the check-namespace script) scans ALL
string literals in `.ts`/`.tsx`/`.json` files under the product packages for a
reserved vendor namespace. Do NOT write test assertions containing that
namespace literal — the gate cannot distinguish a test's namespace-absence
check from an actual namespace violation, and will fail the commit.
Instead, use patterns that avoid the literal:
```ts
const NAMESPACE = "vendor-prefix"
expect(source).not.toContain(`@${NAMESPACE}`)
```
### Single test root (per package)
Each package MUST have exactly ONE test root — no parallel tracks
(`src/**/__tests__/`, a `tests/` dir alongside colocated `src/`, or a `test/`
alongside `tests/`); a second root drifts and breaks test discovery
([org-internal #1711], extended to all packages by [org-internal #1821]).
Rules:
- New tests: create them at the package's single root from the start.
- Do NOT create `src/**/__tests__/` directories in any package — parallel
tracks drift (residuals eliminated by [org-internal #1821]).
- For `test/`-root packages: mirror the `src/` path (`test/<src-relative>.test.ts`);
type-level tests live alongside the behavioral suites in the config area.
- For colocated-root packages: keep tests next to the source file; one test
file per component [org-internal #1712].
Per-package root tables live in the instance layer (they name concrete
package paths); the invariant itself — ONE root per package — is universal.
+98
View File
@@ -0,0 +1,98 @@
> Core 中立版(Increment 2 改写)。术语对照见 core/adapters/TERMINOLOGY.md;本组织实例表述见 dogfood 对应文件。
## Ticket Lifecycle — registry-first filing, claim-to-promote ([org-internal #3002] G1)
Bugs worth fixing start life as a **registry row**, not an independent ticket.
This extends the two-tier-artifacts philosophy to the ticket queue: a
"discovery" (no consumer yet, lifecycle undetermined) is Tier-1-shaped — a
cheap row in a ledger — and is **promoted** to a Tier-2 independent ticket
only when someone schedules or picks it up. (Filing one ticket per discovery
is how the 2026-08 backlog formed.)
### The registry (登记册)
- **Where**: a `## TD 登记` comment on the **source ticket** (the ticket whose
verify/review produced the candidates; a ticket-backend issue comment).
No source ticket (standalone iteration) → the owning Epic's tracker
ticket; no Epic either → the standing TD 冷存档 tracker ticket (G2's
fallback archive target).
- **Row format** (one line per item, checkbox-closeable):
```markdown
- [ ] TD-{NNN} · {type: UNVERIFIABLE|ACCEPTED_RISK|DEFERRED|INFO} ·
{severity: HIGH|MEDIUM|LOW} · {origin chunk-id/iter-N} — {one-line summary}
· trigger: {objectively verifiable reactivation condition}
```
- **TD-NNN** is allocated at REGISTRATION via the ledger mutex
[org-internal #3322]: the 配额账本脚本 (`td-alloc` 形态, `bash <alloc-script>
<count> <source-slug> [--ticket N]`) takes a contiguous range from the TD
allocation ledger (a standing tracker issue) — append-only `**td-alloc**`
comments, earliest-comment-id wins on collision. **ANY allocation — manual
included — must land a td-alloc comment on the ledger BEFORE the registry
row is written** (script, tool API, or web UI). Hand-computed `max + 1`
without a ledger comment is FORBIDDEN (parallel-session races,
[org-internal #3322]). The id is **reserved for life**: promotion reuses
it, never renumbers. Run the alloc script's `--check` (reconciliation)
when the last check predates this batch, and in retrospectives.
- **De-duplication** queries the TD index (same-source rows) plus open
promoted issues (cross-source); index matching replaces title-keyword
matching (keyword dedup once produced 18 fragments from one source).
- **Query-failure ruling ([org-internal #3383]: fail-open, visible)**: if the
dedup query itself errors (backend API failure — NOT "queried and found no
match"), retry once; on second failure file anyway, marking the comment
`dedup-unverified` for retro/reconciliation sweep. Fail-closed rejected:
known dedup failures are match failures it cannot prevent, and a backend
hiccup would block a verify PASS gate.
### Promotion (认领升票)
A row is promoted to an independent ticket when **scheduled or picked up**
(assigned, pulled into a wave/sprint, or chosen):
1. Create the ticket (ticket backend 立案) with the row's reserved `TD-NNN`
(full body per the verify skill's promotion template).
2. Tick the registry row (`- [x]`) and append `#NNNN` to it.
3. The new ticket's `## Parent` points back at the registry's source ticket.
Unpromoted rows are not second-class: the registry comment IS a visible
ticket-backend comment, rows close individually, and the TD index dedups
across sessions — the old per-item model's three guarantees at ~1 ticket per
source.
### PR 准入(pr-admissionTD-678
会话交付物 = 分支 + 报告;开 PR 属编排职权,按容量串行一次一张、双绿并入
再开下一张([org-internal #3864] 管合并出口、本节管 PR 入口)。交付推送前置
本地验证(`<test-cmd:changed>` + `<typecheck-cmd>` 绿;实例命令绑定见
core/adapters/TERMINOLOGY.md)。编排不可达可自开,PR 正文标
`uncoordinated`。细则与门控项:pipeline-gate 清单 PR 准入节。
### BF / FT family umbrellas
Baseline failures and flaky tests file **per root-cause family**, not per
occurrence: evidence (run, commit, failing output, failure rate) attaches as
comments on the family's **umbrella ticket** (ticket-backend issue), keyed by
failure signature (error signature + affected surface, not just
`file::test-name` — one root-cause family may span several tests; precedents
[org-internal #2585], [org-internal #2925]). Filing a new ticket when the
signature already matches an existing family (open or closed) is forbidden —
attach evidence instead. A family umbrella is closed when its signature no
longer reproduces.
### TTL semantics (feeds G2's issue-reaper)
- An **unpromoted registry row** stale for 30 days (no promotion, no
evidence comment) is reaper-eligible: 7-day notice, then archived into the
tracker's archive section.
- A **promoted ticket** follows the normal issue lifecycle (its own priority,
assignee, milestone).
### Compatibility (Iron Law preserved)
- `_(Deferred: TD-XXX <reason>)_` annotations keep their exact format; the
`TD-XXX` now resolves to a registry row (or promoted ticket) instead of an
issue number.
- Archive-at-close, `## 工件索引` guards, and issue-checklist-sync are
untouched: the registry comment is an ordinary ticket-backend comment, not
a Tier-2 artifact page.
+122
View File
@@ -0,0 +1,122 @@
> Core 中立版(Increment 2 改写)。术语对照见 core/adapters/TERMINOLOGY.md;本组织实例表述见 dogfood 对应文件。
## Two-Tier Artifact Storage (mandatory)
Agent-internal handoff (subagents sharing one worktree) and human-visible
traceability have different consumers, lifecycles, and costs. The harness
separates them into two tiers so internal handoff stops paying the Tier-2
tax (HTTP latency, write conflicts, auth, backend health) while
human-visible decisions stay in the system of record.
**Iron Law: an artifact's tier is decided by its CONSUMER and LIFECYCLE, not by
its format.** Format (json / md / artifact page / comment) follows the tier
decision, never drives it.
### Tier 1 — local structured (transient, intra-workflow)
- **Consumer**: subagents within one worktree (Producer / Reviewer /
Synthesizer / Verifier) — never a human gate, never cross-worktree.
- **Lifecycle**: bounded to one run; one worktree; archived-at-close.
- **Visibility**: agent-internal; not human-gated.
- **Storage**: the run workspace `runs/{slug}/` — schema-validated local
files; active runs gitignored, archive bundle committed at close.
- **Examples**: design detail dumps, plan item lists, raw review dimension
findings, synthesis prompts, intermediate analysis.
### Tier 2 — ticket backend / git (stable, cross-worktree, human-visible)
- **Consumer**: humans (gate decisions), cross-worktree sessions, traceability.
- **Lifecycle**: outlives a run; cross-worktree stable; the system of
record.
- **Visibility**: human-visible; authoritative.
- **Storage**: the ticket backend (issues, PRs, artifact pages, commit
status) + git-committed artifacts.
- **Examples**: frozen inter-chunk contracts, issue status + checklist, PRs,
review verdict + synthesis (the human gate), `## 工件索引` comment, commit
status, the workflow branch.
### Decision rule (the 判据)
An artifact belongs to **Tier 1** if and only if ALL of:
1. consumed only within one worktree / one run, AND
2. not a human gate decision (no human reads it to approve/reject), AND
3. not referenced cross-worktree (e.g. a later chunk's frozen contract), AND
4. regenerable-or-archivable at close without losing a decision record.
If ANY condition fails → **Tier 2**. When in doubt, Tier 2: **the Tier-2
default载体 is decided by the ticket backend adapter** (参考实现见
core/adapters/ 的 adapter 层;本组织实例为 Gitea adapter, 术语对照见
core/adapters/TERMINOLOGY.md) — Tier 2 is the default system of record;
Tier 1 is an optimization an artifact opts INTO, not out of.
### Common classifications
Per-artifact table (review findings, prompt files, working drafts, draft/frozen
contracts, issue checklist, 工件索引, `index.json` …): Tier-2 reference page
`rules/two-tier-artifacts-detail` (reachable via the ticket backend); the
decision rule above classifies anything unlisted.
### Two indexes, parallel not replacement
- **Tier 1 `index.json`** (`runs/{slug}/index.json`) — the agent's
compact-recovery entry; Tier 1 artifacts only.
- **Tier 2 `## 工件索引` comment** — the human-visible traceability hub:
artifact-page/issue locations + 重读 priority.
Both are kept by the producing role but serve different consumers. Migrating a
skill's output to Tier 1 does NOT remove its Tier 2 row — it repoints 位置 at
the distillation.
### Archive-at-close
Closed by the **Verifier** at verify PASS (or the Orchestrator when no
verify). The archive step is the ONLY point active-run Tier 1 content enters
git history:
1. Generate the bundle [org-internal #3604]:
the run-bundle generator script with `--slug {slug} [--ticket N] [--pr N]`
— flips meta to "archived", hashes the workspace into the `sha256_16`
manifest, writes `archive/{ticket}-{slug}.json`, validates.
2. Commit the bundle on the workflow branch (rides into main via `--no-ff`).
Direct pushes to main stay blocked by branch protection [org-internal
[org-internal #3604]]; do not bypass.
3. **归档前置校验** [org-internal #2727]: the generator validates by default
(`--no-validate` must not reach a merge); red exit = fix before close.
The L0 merge gate rejects non-compliant bundles at merge anyway.
merge-gate 另做 **presence(存在性)检查**PR body/commit 引用 `Closes #N`
而 merge 树归档目录无 `meta.ticket.number=N` 的 bundle 时拦截(区别于
schema 包的结构合规检查)。预期无 run 的关闭(文档/audit-only/MVP 晋级
前/revert/ad-hoc/legacy reopen)贴 `gate-exempt/archive-presence`
label——label 事件自动重跑 gate。归档前 PR 呈红是设计行为(fail-closed
until archived)。**禁止以豁免 label 替代确实存在过的 run 的 bundle
归档**。归档目录的 `.gitkeep` 是该检查的目录存在性不变式,不得删除。
4. Remove the `{active-slug}/` workspace. Direct `rm -rf` is L0-blocked —
sanctioned exit: the post-merge worktree sync script with `--prune-runs`
(syncs to the merge commit, prunes the run dir, clears stale-ahead false
positives), then the session-worktree removal script.
5. Mark the Tier 2 `## 工件索引` archived per the issue-checklist-sync rule
§ 归档动作.
Tier 2 remains the decision record; the Tier 1 git archive is the
reproducibility trace — enough to reconstruct what a run produced.
### Compact interaction
`compact` never deletes local files: `index.json` survives compaction and is
the designated re-read entry — after `compact`, read `runs/{slug}/index.json`,
not conversation memory.
### Gate furlough[org-internal #3607]
强制门的唯一退出通道是 gate 台账(furlough ledger)的 furlough 条目
(测量证据 + reopen 条件);无台账条目的减门/跳过改动一律拒绝,台账
本身是 Tier 2 决策工件。
### Scope
This rule + the runs layout template + schemas are the foundation; the two
tiers coexist — unmigrated artifacts keep writing to the ticket backend per
their existing body.
+11
View File
@@ -0,0 +1,11 @@
> Core 中立版(Increment 4 改写)。术语对照见 core/adapters/TERMINOLOGY.md;本组织实例表述见 dogfood 对应文件。
## Type Checking
- Always run `<typecheck-cmd>` from package directories, never invoke the
underlying compiler driver directly.
- Monorepo-wide typecheck from the repo root (all packages in one pass — used
by CI and the review-code mechanical-green gate's precondition check): the
repo-root turbo-pipeline invocation (see the term mapping). This is the
repo-root equivalent of the per-package `<typecheck-cmd>`, not a divergence
from it.
+137
View File
@@ -0,0 +1,137 @@
> Core 中立版(Increment 2 改写)。术语对照见 core/adapters/TERMINOLOGY.md;本组织实例表述见 dogfood 对应文件。
## Workflow Routing — type-driven process selection (mandatory)
A ticket's `Kind/*` label determines its process route. The main-session
Process Assessment Gate MUST resolve the route BEFORE matching a skill, so a
labeled ticket never re-derives its path from scratch. Routing is **additive**:
it can only skip stages a ticket doesn't need — it can never weaken a
mandatory gate or skip review/verify.
**Authoritative table**: the workflow-routing table in the instance config
area (`label → { entry, skip, keep_gates }`). The table is the single source
of truth; this rule only says _when and how_ to consult it.
### When to route (Step 0 — runs before the gate's "Articulate intent")
On every substantive request that is tied to a ticket, run Step 0:
1. **Identify the working ticket**. Priority order: explicit `Closes #N` /
`Fixes #N` / `Resolves #N` in the PR or commit → `## 父级 / Parent` link
or chunk mapping → the issue the user pasted or referenced by number.
None of these → no ticket, skip to degradation.
2. **Resolve the route with the 路由解析工具 FIRST** — pass the full
`Kind/*` label when known; omit `kind` when not yet read (the tool returns
the default route plus a read-ticket-then-re-invoke instruction). Agents
with the route-gate option enabled enforce this mechanically
[org-internal #3328]: other tool calls are dispatch-rejected until the
路由解析工具 runs. Do not hand-read the routing table when the tool is
available.
3. **Read the ticket's `Kind/*` label** from the issue body or via the issue
tools (unblocked once the route gate is satisfied). Pick the FIRST
`Kind/*` label if several exist; on a non-default route, re-invoke the
路由解析工具 with the full label.
4. **Apply the route**:
- `entry.skill` non-null → invoke that skill (with `entry.mode` if given)
instead of natural-language matching. This satisfies gate Step 3.
- `entry.skill` null → normal natural-language match, still honoring
`skip` / `keep_gates` downstream. Never drop a gate the route lists in
`keep_gates`; never add back a stage the route lists in `skip`.
### Degradation — label missing, unknown, or wrong ([org-internal #1828] AC)
- **No ticket / no `Kind/*` label / label not in the table** → `default`
route (natural-language matching). State this in one line ("no Kind/\*
label → default route") so the choice is auditable; never block or ask
the user just because a label is absent.
- **Label looks wrong for the work** → do NOT silently override the label.
Apply the labeled route, flag the mismatch in your first response, and
recommend the correct label — the creator owns label correctness; routing
acts only on what is written.
- **Routing table file missing/unreadable** → fall back to natural-language
matching session-wide and note it once — a broken table never blocks work.
### Interaction with the rest of the pipeline
- Routing chooses the **entry** and the **skip set** only. L0/L1 enforcement
(worktree/branch discipline, commit-msg format, stash ban,
claim-discipline, issue-checklist-sync, issue-cross-linking) applies on
every route; a `Kind/Documentation` ticket still needs a worktree and a
PR.
- `keep_gates` from the route and the skill's own mandatory gates intersect:
a gate is mandatory if EITHER source requires it. Skipping is valid only
when BOTH the route and the skill agree it's skippable for this ticket type.
### Runtime growth signals (post-sizing)
Two live growth mechanisms (narrative: Tier-2 reference page
`rules/workflow-routing-detail`, reachable via the ticket backend; retired
Size/* history: the instance rules-history archive). Canonical key:
`dag.size_derivation.oversize_signals` (TD/DUP-F009).
- **DAG-routed tickets** (DAG Epic, DAG-routed `Kind/Feature`, their
`Kind/Task` children — no `Size/*` tier): runtime growth fires the
oversize signals → response is **re-derivation + review-dag re-run**.
- **Bug tickets (big-bug relabel rule, [org-internal #3061])**: a `Kind/Bug`
hitting a design-level trigger (design-decision root cause, shared-contract /
public-API change, data migration) has outgrown the bug type — mandatory
action is **relabel `Kind/Feature`** (Step 0 reroutes into the DAG
pipeline; repro + root-cause notes carry over as node input). Scale-only
triggers stay in bugfix with batched iterations.
Both follow "act on what's written, surface the doubt": when reality
disagrees with the label, pause, reclassify, and make the change visible —
never quietly override.
### DAG 路由 (v2) — default (转正)
The DAG ticket pipeline (`analyze-dag` → task DAG → single gate `review-dag`)
is the **default** route for `Kind/Epic` and `Kind/Feature`
([org-internal #3061] Phase 2 / TD-388). Both resolve via the routes table
directly — **no trigger/marker check** (route rollback = revert PR).
Authoritative definition: the `dag:` block in the workflow-routing table;
narrative + history: Tier-2 reference page `rules/workflow-routing-detail`.
1. **`Kind/Epic` or `Kind/Feature``dag.route`**: entry `analyze-dag`,
single gate `review-dag` (replaces review-design-space +
review-iteration-plan), `keep_gates` `[review-dag, verify]`.
2. **`Kind/Task` under a DAG parent → `dag.task_route`** (entry `implement`,
`implement → review-code → verify`), NOT `dag.route`. All three skills
carry a DAG branch; `pipeline/review-dag` success replaces the
design-space + iteration-plan convergence preconditions at review-code
and verify.
**Routing stickiness**: once an Epic is routed to DAG (draft DAG artifact
exists or `## DAG 状态` table created), all subsequent Step 0 for that Epic
stays on the DAG route — stickiness starts at first routing, NOT at
single-gate PASS. Symmetrically, an Epic already decomposed via legacy
roadmap stays legacy through close (no new legacy decomposition).
**Ticket creation after single-gate PASS** (switch values authoritative in
the routing table `dag.ticket_creation`; analyze-dag itself does NOT create
tickets): on `review-dag` PASS the **aggregator agent** creates one
`Kind/Task` ticket per `type: task` node (body: node `acceptance_criteria`
or dag subpage link + `test_id` suite; `## 父级 / Parent` → DAG parent so
Step 0 resolves `dag.task_route`); `type: milestone` nodes get NO ticket
(DoD carried by `dag.verify_milestone`); the parent body aggregates
`## DAG 状态` + `## 当前状态` (single writer: the aggregator). Each task
ticket then flows implement → review-code (`mode: "dag-task"`) → verify
(task mode).
### Retired sections (index)
Retired mechanisms (Sizing, JIT decomposition, marker disambiguation,
legacy-route sunset, publish-target-by-tier, gate-trim) live in the instance
rules archive; rulings in the phase-3 retirement ruling doc (Tier-2
reference, reachable via the ticket backend). Nothing trims gates —
`never_trim` is structural.
### 立案降档 — filing/sprint-mode[org-internal #3002] G5 / [org-internal #3007]
Sprint 期间债务侧显式降档,不靠纪律。开关:routing table `filing.sprint-mode`
(默认 `false`)。`true`(冲刺期)时 verify Phase 5.5 registry-only 不分严重度
(登记行照写、零丢失;独立工单创建冻结至开关回 `false`,已登记行按
ticket-lifecycle 规则正常认领升票;期间 HIGH/MEDIUM 行不被 reaper 触碰,
[org-internal #3004])。BF/FT5.55/5.56)不受影响。谁翻转:冲刺负责人(人),
在冲刺跟踪单记一行;开关值即 routing table 当前值,verify 每次运行时读取。
动机与细节:Tier-2 参考页(经 ticket backend`rules/workflow-routing-detail`