# Governance Workflow

## What You Need to Know

- ADR convention (per ADR-0011): MADR 4.0 with YAML frontmatter and `.proposed.md` / `.accepted.md` / `.superseded.md` filename suffixes. New ADRs start `.proposed.md`; rename via `git mv` to `.accepted.md` only after the Confirmation criteria are observed in production.
  <!-- signal-score: 0 | last-classified: 2026-06-05 | first-written: 2026-05-13 -->

- JTBD personas: project-maintainer (001-099), ci-automation-engineer (100-199), tech-lead (200-299). Each job in `docs/jtbd/<persona>/JTBD-NNN-*.proposed.md`. Index at `docs/jtbd/README.md`.
  <!-- signal-score: -1 | last-classified: 2026-06-05 | first-written: 2026-05-13 -->

- Architect pushback is substantive. When `wr-architect:agent` returns ISSUES FOUND, the findings are usually correct and worth addressing — don't try to argue past them. Common findings: in-place ADR amendments that smuggle decisions (route to a new ADR instead), trust-boundary widening without recording the broadening, confirmation criteria that don't survive the proposed change.
  <!-- signal-score: 1 | last-classified: 2026-06-05 | first-written: 2026-05-13 -->

- Capture-problem skill is the lightweight aside-invocation path. Use `/wr-itil:capture-problem <description>` (or pass `--no-prompt --type=technical` for non-interactive). The heavyweight `/wr-itil:manage-problem` is for full intake with WSJF placement.
  <!-- signal-score: 4 | last-classified: 2026-06-05 | first-written: 2026-05-13 -->

- **ADR-0011 supersession lifecycle is a 4-step dance per ADR-0011 lines 73-77.** Proposed → Accepted: split into two commits (`git mv` + frontmatter status edit) so `git log --follow` preserves rename detection. Accepted → Superseded: same split (`git mv` + frontmatter `superseded-by:` + "Superseded by" body note). New superseding ADR adds `supersedes:` in its own frontmatter and lives at `docs/decisions/<NNN>-<title>.proposed.md`. Five commits total when going `proposed → accepted → superseded` and adding the new ADR (rename-x2, frontmatter-x2, new ADR add). Implementation commit (e.g. `.husky/pre-commit` change) is its own commit (commit 6 in the sequence). Worked example: ADR-0013 → ADR-0016 supersession this session (commits 6a081bc / a2eec5b / 4c50c64 / 7a945b5 / 0c82d50 / ed5c0e4).
  <!-- signal-score: 0 | last-classified: 2026-06-05 | first-written: 2026-05-17 -->

- **Cold-start RFC pattern is 3 commits per artifact** (observed 2026-05-30 RFC-001 + RFC-002 capture-and-accept session): (1) `/wr-itil:capture-rfc` writes the skeleton `.proposed.md` — one commit. (2) `/wr-itil:manage-rfc <ID>` populates Scope + Tasks and `git mv`s to `.accepted.md` — one commit. For ADRs the equivalent pattern is 2 commits per artifact (`/wr-architect:capture-adr` skeleton + `/wr-architect:create-adr` expansion stays at `.proposed.md` until canonical review confirms). When starting cold from no `docs/rfcs/` dir at all, ADD a third capture-adr commit for the framework-adopting ADR (ADR-0019 this session) before the first RFC capture can succeed (architect verdict ISSUES FOUND on the FIRST RFC capture flagged "no existing decision governs `docs/rfcs/` as an artifact class"). Cold-start total: 1 ADR-adopt + N RFCs × 2 commits each.
  <!-- signal-score: -1 | last-classified: 2026-06-05 | first-written: 2026-05-30 -->

- **Verb-first commit subjects per P010 ALSO apply to RFC commits** (observed 2026-05-30, two commitlint subject-case rejections on `docs(rfcs): RFC-001 accepted —` and `docs(rfcs): RFC-002 accepted —` shapes). `@windyroad/itil`'s manage-rfc SKILL.md commit-convention table writes `docs(rfcs): RFC-<NNN> accepted — <summary>` — that shape starts the subject with `RFC` which is pascal-case under `@commitlint/config-conventional`'s `subject-case` rule and rejects. The local-fix workaround is the same as P010's documented manage-problem fix: lowercase verb first — `docs(rfcs): accept RFC-001 — <summary>`. Same fix shape applies to `docs(decisions): capture ADR-NNN <title>` (worked here). P010 (now **parked**, upstream-blocked on [windyroad/agent-plugins#137](https://github.com/windyroad/agent-plugins/issues/137)) covers the manage-problem case upstream; the manage-rfc / capture-adr surfaces inherit the same convention drift and need an upstream amendment to match. Re-hit again 2026-07-11 on `docs(problems): P013 verification pending —` (the manage-problem K→V transition subject documented in the SKILL) — same subject-case rejection, same lowercase-verb-first fix (`docs(problems): move P013 to verification pending —`).
  <!-- signal-score: 4 | last-classified: 2026-07-11 | first-written: 2026-05-30 -->

- **External `@windyroad/*`-root-cause tickets must be labelled `Origin: external` — a mislabelled `internal` gets mis-selected by the AFK orchestrator as locally-actionable.** This repo tracks two kinds of ticket: dry-aged-deps CLI defects (fixable here) and defects in the adopted `@windyroad/*` plugins (fixable ONLY upstream — the plugin lives in `~/.claude/plugins/cache/...`, there is no `packages/` source here). Before working any ticket, check whether the fix targets a file under this repo or only an upstream package. Disposition ladder for upstream-only root cause:
  - **Report already FILED (`## Reported Upstream` present) + no local fix target → Park** (un-park trigger = upstream issue resolves). Worked example: P010 sat at Known-Error WSJF 6.0 for ~2 months (report #137 filed 2026-05-17) until the orchestrator selected it, found no local path, and parked it.
  - **Report PENDING (not yet filed) → Known Error, `Origin: external (`@windyroad/<plugin>`)`, `- **Upstream report pending** --` marker in `## Related`, KEPT in the WSJF ranking** (not parked). Worked examples: P017, P019, and P027 (2026-07-11 — its root cause is upstream wr-itil work-problems SKILL Step 5 P147 halt-contract prose, confirmed still-unconditional in installed 0.57.2; it was mislabelled `internal`, which is exactly why the orchestrator picked it as locally-actionable this iter). The deferred-not-auto-filed marker is the established local convention over the SKILL's newer AFK auto-invoke-report-upstream branch (surface loudly, don't auto-remediate outward-facing filings).
    `/wr-itil:review-problems` does not auto-park or auto-relabel either shape.

  <!-- signal-score: 3 | last-classified: 2026-07-11 | first-written: 2026-07-11 -->

- **Frontmatter `jtbd: []` (empty list) + body "descriptive references, not load-bearing cites" framing is the inverse-P078 guard for RFC acceptance when local JTBDs are unratified.** JTBD agent flags `[Unratified Dependency]` when an RFC body explicitly "cites and builds on" JTBDs that lack `human-oversight: confirmed` frontmatter. Workaround: keep frontmatter trace empty AND in the body Related section frame the cite as "descriptive references (not load-bearing cites; frontmatter `jtbd: []`)". This pattern got both RFC-001 and RFC-002 past the gate in the 2026-05-30 session. Load-bearing cites land in a follow-up manage-rfc update once the cited JTBDs reach `human-oversight: confirmed`.
  <!-- signal-score: -1 | last-classified: 2026-06-05 | first-written: 2026-05-30 -->

- **Architect gate hash-drifts on every commit to `docs/decisions/`**, forcing a fresh architect re-review for the next gated write. Worked example 2026-05-30: 5 consecutive gated writes (ADR-0019 capture / expand / RFC-001 capture / RFC-001 accept / RFC-002 accept) each required a separate `wr-architect:agent` delegation. The "PASS-WITH-NOTES" verdict survives within-session ONLY until the next `docs/decisions/` commit lands — then the cached hash invalidates and re-review fires. Batching gated writes (no intervening commit) into one session-marker window would amortise the cost; current design re-reviews every iteration. Not a bug — drift detection is the gate's purpose — but worth knowing the cost shape ahead of time when planning multi-artifact governance sessions.
  <!-- signal-score: -1 | last-classified: 2026-06-05 | first-written: 2026-05-30 -->

## What Will Surprise You

- Verify-before-assert is a recurring agent failure mode. Three flip-flops on branch-protection behaviour in one session were directly caused by asserting from training data without checking GitHub's actual docs. Default to verification (fetch action source, read docs, test) when the answer is platform-specific. **Re-confirmed by P008's v2.7.2 → v2.7.3 layered fix**: candidate 1 was picked from training-data assumption that bearer auth works for git transport. It does not. Architect / JTBD reviews would not have caught this — both PASS'd candidate 1 because the failure surface is empirical (live runner) and not in any local file the agents can read. The lesson: for auth-scheme decisions involving non-test-runnable surfaces, EITHER write a dry-run probe before shipping OR pick the most-documented option (candidate 3's URL-embedded basic auth is GitHub's own published recommendation; candidate 1 was a workaround for the duplicate-header symptom that ignored the underlying auth scheme). Pattern applied this session (2026-05-30) — verified `gh run view 26668291165` after `push:watch` reported "Pipeline failed" rather than believing the script; the run was actually green and the script's failure-mode was a network-flake false-positive.
  <!-- signal-score: 6 | last-classified: 2026-06-05 | first-written: 2026-05-13 -->

- Memory files (e.g. `feedback_claude_subscription_only.md`) load into context at session start but only help if the agent actually applies them. Loading is not application. Cited this session: `project_ci_publish_check_gate` informed iter 2 immediately (no time wasted re-discovering the gate); `feedback_push_as_often_as_possible` informed the post-iter Step 6.5 drain cadence; `feedback_claude_subscription_only` is implicit in subprocess dispatch (no API key check).
  <!-- signal-score: 0 | last-classified: 2026-06-05 | first-written: 2026-05-13 -->
