forked from Octopus/octopus-workflow
496 lines
24 KiB
Markdown
496 lines
24 KiB
Markdown
> Extracted from verify/SKILL.md (phase 5.5 / 5.55 / 5.56 / 5.6) — moved
|
||||
|
|
> verbatim; read on-demand during Phase 5 execution, before PASS. Each phase
|
|||
|
|
> is mandatory-before-PASS in its trigger condition; the main flow stops at
|
|||
|
|
> each boundary until the referenced protocol reports completion.
|
|||
|
|
|
|||
|
|
<!-- section:phase-5.5 -->
|
|||
|
|
### Phase 5.5 — Tech Debt Registry Filing (mandatory before PASS)
|
|||
|
|
|
|||
|
|
Tech debt is filed **registry-first** (`core/rules/ticket-lifecycle.md`,
|
|||
|
|
[TT-3002] G1): new items become ROWS in the source ticket's `## TD 登记` comment;
|
|||
|
|
an independent ticket is created only at **promotion** (claim/schedule). There
|
|||
|
|
is no `tech-debt.md` file and no `{slug}/tech-debt` wiki page — both remain
|
|||
|
|
retired. The registry preserves the three guarantees of the old
|
|||
|
|
one-issue-per-item model: visible (the comment lives on a tracker ticket),
|
|||
|
|
individually closeable (row-level checkbox), de-duplicated across sessions
|
|||
|
|
(the TD index is stronger than title-keyword matching).
|
|||
|
|
|
|||
|
|
**Sprint-mode override ([TT-3002] G5/[TT-3007])**: read `filing.sprint-mode` from
|
|||
|
|
`<instance-root>/workflow-routing.yaml` at the START of this phase (no caching). When
|
|||
|
|
`true`, ALL severities file registry-only — registration rows are written as
|
|||
|
|
normal (severity included, nothing lost) but promotion to standalone tickets
|
|||
|
|
is FROZEN until the switch returns to `false`. Rationale: the 2026-08-12
|
|||
|
|
sprint zeroed fix capacity while filing kept running (the 125-fragment
|
|||
|
|
backlog's direct trigger); an explicit debt-side downshift beats hoping for
|
|||
|
|
discipline. BF/FT phases 5.55/5.56 are NOT covered by this switch — failure
|
|||
|
|
evidence must stay immediately visible. Flipping the switch is a human
|
|||
|
|
decision recorded on the sprint tracker; semantics in
|
|||
|
|
`rules/workflow-routing.md` §立案降档.
|
|||
|
|
|
|||
|
|
**Adjacency quota ([TT-3002] G3/[TT-3005])**: while collecting inputs, also check the
|
|||
|
|
AREAS this iteration touched (packages/modules with commits this iteration).
|
|||
|
|
If the source tickets for those areas carry applicable `## TD 登记` rows, at
|
|||
|
|
least ONE row must be taken along and disposed this iteration (fixed, or
|
|||
|
|
explicitly re-deferred with a reason — silence is not a disposition). Record
|
|||
|
|
`consumed X / applicable Y` (or `0 applicable`) in the TD report section;
|
|||
|
|
verification checklist §8.4 cross-checks it against the run's debt-quota
|
|||
|
|
record (historically the roadmap's per-chunk debt-quota line). This gives debt digestion a steady capacity source tied to
|
|||
|
|
touch, not to cleanup campaigns.
|
|||
|
|
|
|||
|
|
**Promotion quota + pull event ([TT-3061])**: promotion to a standalone ticket
|
|||
|
|
requires (a) a **pull event** — the row's Reactivation Trigger fired (state
|
|||
|
|
the observed event) OR a named claimer/schedule; "it seemed important" is not
|
|||
|
|
a pull event — recorded in the promotion body's `## 拉动事件 / Pull Event`
|
|||
|
|
section; and (b) the origin module's OPEN promoted-TD count is below the
|
|||
|
|
quota (**default 10** — counted **per origin module**: resolve the row's
|
|||
|
|
module from the ticket body's `Origin` field, then count that module's OPEN
|
|||
|
|
`tech-debt` tickets; retro §2.10 reports breaches). At or above quota →
|
|||
|
|
register-only until the count drops; before each Phase 5.5 promotion
|
|||
|
|
re-check the owning module's count, and a row whose module is at or above
|
|||
|
|
quota is NOT promoted — defer it and annotate the registry row with
|
|||
|
|
`quota-held` (re-checked on the next verify run, retro 2026-08-21). A row
|
|||
|
|
marked `[COLD]` by retrospective §2.10
|
|||
|
|
(unclaimed >3 retro cycles) promotes only after the pull event clears the
|
|||
|
|
mark.
|
|||
|
|
|
|||
|
|
**Collect inputs** — every tech-debt item to register this iteration:
|
|||
|
|
|
|||
|
|
1. Every UNVERIFIABLE row in the DoD matrix (Phase 3), with its Reactivation
|
|||
|
|
Trigger.
|
|||
|
|
2. Every ACCEPTED_RISK finding in the code-review final report
|
|||
|
|
(`{slug}/reviews/code/final/report`), with its Recommended Reactivation
|
|||
|
|
Trigger.
|
|||
|
|
3. Every `[OPEN: <short-id>]` marker the Developer left in code this iteration
|
|||
|
|
(per implementation checklist POST-6.2).
|
|||
|
|
|
|||
|
|
If the code-review final report does not exist, warn the user — ACCEPTED_RISK
|
|||
|
|
items cannot be captured. This is itself a process gap that must be flagged.
|
|||
|
|
|
|||
|
|
**Step 1 — De-duplicate against the registry index and promoted issues.**
|
|||
|
|
|
|||
|
|
1. Read the source ticket's `## TD 登记` comment (create the comment if this
|
|||
|
|
is its first row) and match each candidate against existing rows by
|
|||
|
|
`TD-NNN` and reactivation trigger. Same-source re-reporting is the
|
|||
|
|
anti-pattern this step exists to prevent (the visual-cluster incident: 18
|
|||
|
|
fragments from one source under the old keyword matching).
|
|||
|
|
2. Query OPEN promoted tech-debt issues for cross-source duplicates:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
工单 API 检索(见 TERMINOLOGY)
|
|||
|
|
(owner/repo 按实例绑定,labels="tech-debt", state="open")
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Step 2 — Assign `TD-NNN` via the ledger mutex ([TT-3322]).** One script call
|
|||
|
|
per batch: `bash script/td-alloc.sh <count = new items> <source-slug>
|
|||
|
|
[--ticket N]` returns a contiguous range from the TD allocation ledger
|
|||
|
|
(append-only comments, earliest-comment-id wins; the seed comment pins the
|
|||
|
|
historical floor). Split the returned range across the Step 3 rows in order.
|
|||
|
|
**Any allocation — manual included — must land a `**td-alloc**` comment on
|
|||
|
|
the ledger before the registry row is written; hand-computed `max + 1` is
|
|||
|
|
forbidden** (the 2026-08-24 three-way collision). On exit 5 (retry
|
|||
|
|
exhaustion) abort this phase's filing and retry — never hand-assign. The id is **reserved for life**: promotion reuses it, never
|
|||
|
|
renumbers. Run `--check` (reconciliation) here if the last check predates
|
|||
|
|
this batch.
|
|||
|
|
|
|||
|
|
**Step 3 — Append one registry row per new item.** Append to the source
|
|||
|
|
ticket's `## TD 登记` comment (no source ticket → the owning Epic's tracker
|
|||
|
|
ticket; no Epic → the standing `TD 冷存档` tracker):
|
|||
|
|
|
|||
|
|
```markdown
|
|||
|
|
- [ ] TD-{NNN} · {UNVERIFIABLE | ACCEPTED_RISK | DEFERRED} · {HIGH | MEDIUM | LOW}
|
|||
|
|
· {origin chunk-id/iter-N} — {one-line summary}
|
|||
|
|
· trigger: {objectively verifiable reactivation condition — never "when ready";
|
|||
|
|
if no trigger can be defined this is NOT tech debt and the iteration verdict
|
|||
|
|
becomes FAIL}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Step 4 — Cross-link (adapted).** The registry comment already lives on the
|
|||
|
|
source issue — the source → debt navigation the old body-edit provided. When
|
|||
|
|
filing went to an Epic tracker or the 冷存档 (no source ticket), reference the
|
|||
|
|
originating slug in each row so the trail survives.
|
|||
|
|
|
|||
|
|
**Step 5 — Record the mapping in the verification report.** The report's
|
|||
|
|
"Tech Debt" section records `TD-NNN → registry row` (source `#NNNN` +
|
|||
|
|
`## TD 登记` comment); promoted items record `TD-NNN → #NNNN` as before.
|
|||
|
|
|
|||
|
|
**Promotion (认领升票) — when a row is scheduled or picked up.** Create the
|
|||
|
|
independent ticket THEN, carrying the reserved `TD-NNN`:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
POST <gitea-base-url>/api/v1/repos/Octopus/octopus/issues
|
|||
|
|
body: {"title":"[{origin}] Tech debt: {short description} (TD-{NNN})",
|
|||
|
|
"body":<promotion template below>,
|
|||
|
|
"labels":[tech_debt_label_id, severity_label_id]}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
- **Severity → label** (reuse the existing exclusive Priority set):
|
|||
|
|
|
|||
|
|
| Severity | Label |
|
|||
|
|
| -------- | ----------------- |
|
|||
|
|
| HIGH | `Priority/High` |
|
|||
|
|
| MEDIUM | `Priority/Medium` |
|
|||
|
|
| LOW | `Priority/Low` |
|
|||
|
|
|
|||
|
|
- **Promotion body template** (the pre-[TT-3002] issue template, now used only at
|
|||
|
|
promotion):
|
|||
|
|
|
|||
|
|
```markdown
|
|||
|
|
## Parent / 父级
|
|||
|
|
|
|||
|
|
{#source_issue carrying the ## TD 登记 row}
|
|||
|
|
|
|||
|
|
## Summary
|
|||
|
|
|
|||
|
|
{one-paragraph description of the debt}
|
|||
|
|
|
|||
|
|
| Field | Value |
|
|||
|
|
| -------- | ------------------------------------------- |
|
|||
|
|
| TD ID | TD-{NNN} (reserved at registration) |
|
|||
|
|
| Type | {UNVERIFIABLE \| ACCEPTED_RISK \| DEFERRED} |
|
|||
|
|
| Origin | {chunk-id/iter-N/phase or slug} |
|
|||
|
|
| Severity | {HIGH \| MEDIUM \| LOW} |
|
|||
|
|
|
|||
|
|
## Reactivation Trigger
|
|||
|
|
|
|||
|
|
{from the registry row}
|
|||
|
|
|
|||
|
|
## 拉动事件 / Pull Event
|
|||
|
|
|
|||
|
|
{trigger fired: {observed event} | claimed by {who} for {when}}
|
|||
|
|
|
|||
|
|
## Acceptance Criteria (how to close this issue)
|
|||
|
|
|
|||
|
|
- [ ] {specific action that resolves the debt}
|
|||
|
|
|
|||
|
|
## Context
|
|||
|
|
|
|||
|
|
- Verification report: `{slug}/05-verify-iteration-{N}`
|
|||
|
|
- Code review report: `{slug}/reviews/code/final/report` (if ACCEPTED_RISK)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
- After creating the promoted ticket: tick the registry row (`- [x]`) and
|
|||
|
|
append `→ #NNNN` to it.
|
|||
|
|
|
|||
|
|
If no new tech-debt items were found this iteration, the phase is a no-op —
|
|||
|
|
record "0 tech-debt items" in the report and proceed.
|
|||
|
|
|
|||
|
|
<!-- section:phase-5.55 -->
|
|||
|
|
### Phase 5.55 — Baseline-Failure Issue Registration (mandatory before PASS when pre-existing failures exist)
|
|||
|
|
|
|||
|
|
Pre-existing test failures (BF) are tracked as **root-cause family umbrella
|
|||
|
|
tickets** (`core/rules/ticket-lifecycle.md`, [TT-3002] G1; precedents [TT-2585]
|
|||
|
|
umbrella + [TT-2925] cluster) — one `BF-NNN` ticket per failure-signature family,
|
|||
|
|
labeled `baseline-failure`, with each occurrence's evidence attached as
|
|||
|
|
comments. There is no `baseline-failures.md` file and no
|
|||
|
|
`{slug}/baseline-failures` wiki page. A pre-existing failure does not block
|
|||
|
|
the iteration that _discovered_ it (it pre-dates that work), but it MUST be
|
|||
|
|
filed against (or into) a family; an un-filed baseline failure is a process
|
|||
|
|
gap and the iteration is NOT Done.
|
|||
|
|
|
|||
|
|
**Birth triage SLA ([TT-3061])**: a BF umbrella is born with `Kind/Bug` (it IS a
|
|||
|
|
bug — of the baseline) and must be triaged the SAME DAY it is filed:
|
|||
|
|
assigned, scheduled, or explicitly deferred with a reason on the ticket.
|
|||
|
|
Untriaged-next-day BF umbrellas are named individually in retro §2.10
|
|||
|
|
(compliance %), not averaged away.
|
|||
|
|
|
|||
|
|
**Collect inputs** — every pre-existing failure to register this iteration:
|
|||
|
|
|
|||
|
|
1. Every failure classified **pre-existing** in Phase 2.6 (fails on the base
|
|||
|
|
branch / last-green commit too).
|
|||
|
|
2. Any baseline-run failures noted in the brownfield pre-check (Greenfield vs.
|
|||
|
|
Brownfield section).
|
|||
|
|
|
|||
|
|
**Step 1 — De-duplicate by failure SIGNATURE against existing families (open
|
|||
|
|
AND closed), per `core/rules/testing.md`** (de-duplicate BEFORE filing,
|
|||
|
|
retro [TT-2696]). Query `baseline-failure` issues in ALL states:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
GET <gitea-base-url>/api/v1/repos/Octopus/octopus/issues?labels=baseline-failure&state=all&page=N&limit=50
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Match each candidate by **failure signature** — the error/assertion signature
|
|||
|
|
plus the affected surface, not just `file::test-name` (one root-cause family
|
|||
|
|
may span several tests; several tests failing with the same assertion shape
|
|||
|
|
are ONE family). On a signature hit, do NOT create a new ticket: attach the
|
|||
|
|
new run evidence (run, commit, failing output, sibling tests observed) as a
|
|||
|
|
comment on the FAMILY umbrella ticket. Filing a second ticket inside a known
|
|||
|
|
root-cause family is the anti-pattern this phase exists to prevent. If a
|
|||
|
|
tracked family is now FIXED by this iteration's work, close its umbrella with
|
|||
|
|
a comment citing the fixing commit (a bonus, not a requirement). If the query
|
|||
|
|
itself errors (API failure — not "no matches"), retry once; on the second
|
|||
|
|
failure proceed to file with the literal marker `dedup-unverified` in the
|
|||
|
|
umbrella's first evidence comment (query-failure ruling, [TT-3383] — fail-open,
|
|||
|
|
visible; rationale in `core/rules/ticket-lifecycle.md`).
|
|||
|
|
|
|||
|
|
**Step 2 — Assign the next `BF-NNN`** per `core/rules/testing.md`
|
|||
|
|
§ "Pre-existing test failures must be filed, not silently logged" (the L1 rule
|
|||
|
|
owns the repo-wide sequential numbering invariant — `max + 1`, duplicate ids
|
|||
|
|
forbidden incl. closed tickets). `BF-NNN` names the FAMILY; the Gitea issue
|
|||
|
|
number `#NNNN` is the tracker handle.
|
|||
|
|
|
|||
|
|
**Step 3 — Create one umbrella ticket per NEW root-cause family.** Only when
|
|||
|
|
no existing family matches the signature:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
POST <gitea-base-url>/api/v1/repos/Octopus/octopus/issues
|
|||
|
|
body: {"title":"[{origin}] Baseline failure: {test identifier} (BF-{NNN})",
|
|||
|
|
"body":<issue body template below>,
|
|||
|
|
"labels":[baseline_failure_label_id, severity_label_id, kind_bug_label_id]}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
- **Title**: `[{origin}] Baseline failure: {signature summary} (BF-{NNN})`
|
|||
|
|
where `{origin}` is `chunk-{id}/iter-{N}` or the bugfix slug, and
|
|||
|
|
`{signature summary}` is the family's error/assertion shape (not a single
|
|||
|
|
test name — sibling tests observed later join this umbrella as evidence
|
|||
|
|
comments).
|
|||
|
|
- **Severity → label** (reuse the existing exclusive Priority set; a failing
|
|||
|
|
test defaults to at least MEDIUM, HIGH if on a critical path):
|
|||
|
|
|
|||
|
|
| Severity | Label |
|
|||
|
|
| -------- | ----------------- |
|
|||
|
|
| HIGH | `Priority/High` |
|
|||
|
|
| MEDIUM | `Priority/Medium` |
|
|||
|
|
| LOW | `Priority/Low` |
|
|||
|
|
|
|||
|
|
- Also attach `Kind/Bug` so the failure is discoverable in the bug tracker
|
|||
|
|
alongside manually-reported bugs.
|
|||
|
|
- **Issue body template**:
|
|||
|
|
|
|||
|
|
````markdown
|
|||
|
|
## Parent / 父级
|
|||
|
|
|
|||
|
|
{#source_issue, or "no source issue — discovered during iteration baseline"}
|
|||
|
|
|
|||
|
|
## Summary
|
|||
|
|
|
|||
|
|
A test was already failing before this iteration's work began. It does not
|
|||
|
|
block the discovering iteration but must be tracked to closure.
|
|||
|
|
|
|||
|
|
| Field | Value |
|
|||
|
|
| -------------- | ---------------------------------------------- |
|
|||
|
|
| BF ID | BF-{NNN} (family) |
|
|||
|
|
| Signature | {error/assertion shape} |
|
|||
|
|
| Tests affected | `{file::test-name}`, … (initial members) |
|
|||
|
|
| Origin | {chunk-id/iter-N or slug} |
|
|||
|
|
| Severity | {HIGH \| MEDIUM \| LOW} |
|
|||
|
|
| First observed | {base commit / date the failure reproduces on} |
|
|||
|
|
|
|||
|
|
## Reproduction
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
git checkout {base commit}
|
|||
|
|
(cd <harness-package> && bun test --timeout 120000 {test file}) # or project-equivalent
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Failing output:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
{paste the relevant assertion / error}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Acceptance Criteria (how to close this issue)
|
|||
|
|
|
|||
|
|
- [ ] The named test passes on a clean checkout of the target branch.
|
|||
|
|
- [ ] If the test is deleted/renamed, the replacement covers the same
|
|||
|
|
behavior and passes.
|
|||
|
|
|
|||
|
|
## Context
|
|||
|
|
|
|||
|
|
- Verification report: `{slug}/05-verify-iteration-{N}`
|
|||
|
|
````
|
|||
|
|
|
|||
|
|
**Step 4 — Cross-link to the source issue (mandatory).** Per the
|
|||
|
|
issue-cross-linking rule, every baseline-failure issue MUST link back to its
|
|||
|
|
source:
|
|||
|
|
|
|||
|
|
- The issue body already carries `## Parent` (above).
|
|||
|
|
- Update the source/parent issue body to reference each new baseline-failure
|
|||
|
|
issue by `#NNNN` in its task list (e.g.
|
|||
|
|
`- [ ] #NNNN — BF-{NNN} {test identifier}`), so reviewers can navigate from
|
|||
|
|
source → failure.
|
|||
|
|
|
|||
|
|
**Step 5 — Record the mapping in the verification report.** The
|
|||
|
|
`BF-NNN → #NNNN` mapping is written ONLY in the Phase 5 verification report's
|
|||
|
|
"Baseline Failures" section (and in the issue title itself). There is no local
|
|||
|
|
file to update.
|
|||
|
|
|
|||
|
|
If no new baseline failures were found this iteration, the phase is a no-op —
|
|||
|
|
record "0 baseline failures" in the report and proceed.
|
|||
|
|
|
|||
|
|
<!-- section:phase-5.56 -->
|
|||
|
|
### Phase 5.56 — Flaky-Test Issue Registration (mandatory before PASS when flaky tests are unfixed)
|
|||
|
|
|
|||
|
|
Flaky tests (intermittent pass/fail) are tracked as **root-cause family
|
|||
|
|
umbrella tickets** (`core/rules/ticket-lifecycle.md`, [TT-3002] G1) — one
|
|||
|
|
`FT-NNN` ticket per failure-signature family, labeled `flaky-test`, with each
|
|||
|
|
occurrence's evidence (run count, failure rate, commit) attached as comments.
|
|||
|
|
A flaky test that is not fixed within this iteration MUST be filed against
|
|||
|
|
(or into) a family; otherwise it evaporates at iteration end and the
|
|||
|
|
"compare flaky count against baseline" check (TST-2.5) has no persistent
|
|||
|
|
register to compare against. Filing does not block the verdict, but an unfixed
|
|||
|
|
flaky test left un-filed is a process gap and the iteration is NOT Done.
|
|||
|
|
|
|||
|
|
**Expiry SLA ([TT-3061])**: an FT umbrella is born with `Kind/Testing` and a
|
|||
|
|
**fix-or-isolate window** (default 7 days) recorded in its body (isolating =
|
|||
|
|
quarantining/skipping the test with the family id in the skip reason, which
|
|||
|
|
keeps the register comparable). Past the window without fix or isolation, the
|
|||
|
|
umbrella is escalated on the ticket (comment naming the owner); retro §2.10
|
|||
|
|
reports fix-or-isolate compliance per cycle.
|
|||
|
|
|
|||
|
|
**Collect inputs** — every flaky test to register this iteration:
|
|||
|
|
|
|||
|
|
1. Every flaky test surfaced in Phase 2.1 (intermittent pass/fail across
|
|||
|
|
reruns) that was NOT fixed by the Developer this iteration.
|
|||
|
|
2. Any flaky test carried over from a prior iteration's report that is still
|
|||
|
|
intermittently failing.
|
|||
|
|
|
|||
|
|
**Step 1 — De-duplicate by failure SIGNATURE against existing families (open
|
|||
|
|
AND closed), per `core/rules/testing.md`** (de-duplicate BEFORE filing,
|
|||
|
|
retro [TT-2696]). Query `flaky-test` issues in ALL states:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
GET <gitea-base-url>/api/v1/repos/Octopus/octopus/issues?labels=flaky-test&state=all&page=N&limit=50
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Match each candidate by **failure signature** — the flakiness mode (timeout /
|
|||
|
|
race / order-dependence / env-leak) plus the affected surface, not just
|
|||
|
|
`file::test-name` (one root cause may flake several tests). On a signature
|
|||
|
|
hit, do NOT create a new ticket: attach the new run evidence (run count,
|
|||
|
|
failure rate, commit, sibling tests) as a comment on the FAMILY umbrella
|
|||
|
|
ticket. Filing a second ticket inside a known root-cause family is the
|
|||
|
|
anti-pattern this phase exists to prevent. If a tracked family now passes
|
|||
|
|
deterministically, close its umbrella citing the fixing commit. If the query
|
|||
|
|
itself errors (API failure — not "no matches"), retry once; on the second
|
|||
|
|
failure proceed to file with the literal marker `dedup-unverified` in the
|
|||
|
|
umbrella's first evidence comment (query-failure ruling, [TT-3383] — fail-open,
|
|||
|
|
visible; rationale in `core/rules/ticket-lifecycle.md`).
|
|||
|
|
|
|||
|
|
**Step 2 — Assign the next `FT-NNN`** per `core/rules/testing.md`
|
|||
|
|
§ "Flaky tests must be filed, not silently tolerated" (the L1 rule owns the
|
|||
|
|
repo-wide sequential numbering invariant — `max + 1`, duplicate ids forbidden
|
|||
|
|
incl. closed tickets). `FT-NNN` names the FAMILY.
|
|||
|
|
|
|||
|
|
**Step 3 — Create one umbrella ticket per NEW root-cause family.** Only when
|
|||
|
|
no existing family matches the signature:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
POST <gitea-base-url>/api/v1/repos/Octopus/octopus/issues
|
|||
|
|
body: {"title":"[{origin}] Flaky test: {test identifier} (FT-{NNN})",
|
|||
|
|
"body":<issue body template below>,
|
|||
|
|
"labels":[flaky_test_label_id, severity_label_id, kind_testing_label_id]}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
- **Title**: `[{origin}] Flaky test: {signature summary} (FT-{NNN})` — the
|
|||
|
|
family's flakiness mode + surface (sibling tests join later as evidence
|
|||
|
|
comments, not new tickets).
|
|||
|
|
- **Severity** → a flaky test defaults to MEDIUM (HIGH if on a critical path
|
|||
|
|
or blocking CI); reuse the exclusive Priority set.
|
|||
|
|
- Also attach `Kind/Testing` so it is discoverable in the testing tracker.
|
|||
|
|
- **Issue body template**:
|
|||
|
|
|
|||
|
|
````markdown
|
|||
|
|
## Parent / 父级
|
|||
|
|
|
|||
|
|
{#source_issue, or "no source issue — discovered during iteration verification"}
|
|||
|
|
|
|||
|
|
## Summary
|
|||
|
|
|
|||
|
|
A test passes and fails intermittently across runs. It undermines the
|
|||
|
|
reliability of the suite and must be stabilized or quarantined.
|
|||
|
|
|
|||
|
|
| Field | Value |
|
|||
|
|
| ------------ | ------------------------- |
|
|||
|
|
| FT ID | FT-{NNN} (family) |
|
|||
|
|
| Signature | {flakiness mode + surface} |
|
|||
|
|
| Tests affected | `{file::test-name}`, … (initial members) |
|
|||
|
|
| Origin | {chunk-id/iter-N or slug} |
|
|||
|
|
| Severity | {HIGH \| MEDIUM \| LOW} |
|
|||
|
|
| Failure rate | {e.g. 3/10 runs} |
|
|||
|
|
|
|||
|
|
## Reproduction
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
for i in $(seq 1 10); do (cd <harness-package> && bun test --timeout 120000 {test file}) || echo "run $i FAILED"; done
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Acceptance Criteria (how to close this issue)
|
|||
|
|
|
|||
|
|
- [ ] The test passes deterministically across 10 consecutive runs.
|
|||
|
|
- [ ] If it cannot be stabilized, it is quarantined (`test.skip` /
|
|||
|
|
`test.todo` with a comment citing FT-{NNN}) and a stable replacement
|
|||
|
|
is filed as tech-debt (TD-NNN).
|
|||
|
|
|
|||
|
|
## Context
|
|||
|
|
|
|||
|
|
- Verification report: `{slug}/05-verify-iteration-{N}`
|
|||
|
|
````
|
|||
|
|
|
|||
|
|
**Step 4 — Cross-link to the source issue (mandatory).** Every flaky-test
|
|||
|
|
issue links back to its source via `## Parent`, and the source/parent issue
|
|||
|
|
task list references each by `#NNNN`
|
|||
|
|
(`- [ ] #NNNN — FT-{NNN} {test identifier}`).
|
|||
|
|
|
|||
|
|
**Step 5 — Record the mapping in the verification report.** The
|
|||
|
|
`FT-NNN → #NNNN` mapping is written ONLY in the Phase 5 report's "Flaky Tests"
|
|||
|
|
section (and the issue title). No local file.
|
|||
|
|
|
|||
|
|
If no unfixed flaky tests exist this iteration, the phase is a no-op — record
|
|||
|
|
"0 flaky tests" in the report and proceed.
|
|||
|
|
|
|||
|
|
<!-- section:phase-5.6 -->
|
|||
|
|
### Phase 5.6 — Issue Checklist Sync (final sweep, mandatory before PASS)
|
|||
|
|
|
|||
|
|
This is the **final** checklist sync — the last of the progressive sync
|
|||
|
|
points (requirements exit, design exit, plan exit, each iteration commit, PR
|
|||
|
|
creation, review convergence, CI transitions, and here — per the sync-point
|
|||
|
|
table in `core/rules/issue-checklist-sync.md`). Earlier syncs may have
|
|||
|
|
already checked off completed items; this phase catches everything remaining
|
|||
|
|
and ensures no `- [ ]` item is left without an annotation.
|
|||
|
|
|
|||
|
|
1. **Identify the source issue** per `core/rules/issue-checklist-sync.md`
|
|||
|
|
§ "How to sync (each point)" step 1 (find `Closes #N` / `Fixes #N` in the
|
|||
|
|
PR body or commit messages). If no source issue exists (e.g. standalone
|
|||
|
|
bugfix with no tracking issue), skip this phase.
|
|||
|
|
2. **Fetch the issue body** via `工单 API(见 TERMINOLOGY)get` (rule step 2).
|
|||
|
|
3. **Map every remaining `- [ ]` checklist item** to one of three states:
|
|||
|
|
- **Done** (missed by earlier syncs) → mark `- [x]` and append
|
|||
|
|
`_(PR #NNN: <file/component>)_`.
|
|||
|
|
- **Deferred** → keep `- [ ]` and append `_(Deferred: TD-NNN <reason>)_`.
|
|||
|
|
- **Pending** → keep `- [ ]` and append `_(Pending: <blocker>)_`.
|
|||
|
|
4. **Fold the `## 当前状态` live-status section** (if present). Rows that have
|
|||
|
|
a checklist counterpart (review, process-ACs) are already reflected as
|
|||
|
|
checklist annotations at their sync points. Rows with no checklist
|
|||
|
|
counterpart in a non-Epic issue (PR opened/merged) are folded as follow-up
|
|||
|
|
evidence on the issue narrative (e.g. `_(PR #NNN merged: <summary>)_` on the
|
|||
|
|
item it delivered, or in the report). Once every row is accounted for,
|
|||
|
|
remove the section from the issue body.
|
|||
|
|
5. **archive-at-close: mark the `## 工件索引` comment archived** (归档动作 — [TT-1929]). Issue
|
|||
|
|
closing IS the archive-at-close action; it is explicit, not implicit. Edit the index
|
|||
|
|
comment in place per `_shared/gitea-write-patterns.md` Pattern 10 Archive-at-close
|
|||
|
|
(mechanism — banner + every row's 重读 → ARCHIVE + invariants — is defined there,
|
|||
|
|
do not restate; sequence/actor per `rules/issue-checklist-sync.md` § 归档动作).
|
|||
|
|
- Skip if no source issue exists.
|
|||
|
|
- **Tier 1 run archive** ([TT-1988] two-tier artifacts — only if a Tier 1 run
|
|||
|
|
workspace exists): if `<runs-root>/{slug}/` exists (a stage in this run
|
|||
|
|
produced Tier 1 local artifacts, e.g. review-code findings), archive the
|
|||
|
|
run workspace per `core/rules/two-tier-artifacts.md` § Archive-at-close
|
|||
|
|
(the L1 rule is authoritative — do NOT restate its steps here).
|
|||
|
|
The archived bundle must pass
|
|||
|
|
`core/schemas/runs-bundle.schema.json` validation (the generator
|
|||
|
|
validates by default; a red exit blocks close).
|
|||
|
|
Verify deltas only: skip in milestone/task DAG mode (the aggregator agent
|
|||
|
|
performs it at Epic/task-ticket close — see the DAG branch below).
|
|||
|
|
6. **Update the issue body** via `工单 API(见 TERMINOLOGY)update` with the annotated
|
|||
|
|
checklist. Preserve all non-checklist content unchanged.
|
|||
|
|
7. **Verify**: re-read the issue and confirm no `- [ ]` item lacks an
|
|||
|
|
annotation. Every unchecked item MUST have a `(Deferred: ...)` or
|
|||
|
|
`(Pending: ...)` note explaining why it is not done.
|
|||
|
|
8. **Close the issue** (completes the archive-at-close loop): if the flow has
|
|||
|
|
no PR (no `Closes #N` on merge), the Verifier closes the issue after PASS
|
|||
|
|
approval via `工单 API(见 TERMINOLOGY)update(state="closed")` — the banner date is
|
|||
|
|
corrected to the actual close date if it differs from today. If a PR carries
|
|||
|
|
`Closes #N`, the merge closes it; no further action.
|
|||
|
|
|
|||
|
|
If a checklist item cannot be mapped to evidence, deferral, or pending
|
|||
|
|
status, the iteration is NOT Done — the item represents untracked scope.
|