Docs & ÉcritureAttention7878/100
PR New (Ansible) — Agents
Prepare and submit a pull request for the APME project. Syncs with upstream, creates a feature branch, runs quality gates (tox -e lint, tox -e unit), updates documentation and ADRs as needed, commits with conventional commits, then creates the PR via gh. Use when the user asks to submit, create, or open a pull request, or says "submit PR", "open PR", "create PR", "new PR".
ou envoie-le directement à ton agent.
Installer dans ton projet
$ curl -fsSL https://arboristhree.xyz/cli/install-skill.mjs -o /tmp/arboris-install-skill.mjs && node /tmp/arboris-install-skill.mjs pr-new__ansible-apme__agents-skills-fe0eb434a77aAnsible
ansible/apme
Contenu à copier
---
name: pr-new
description: >
Prepare and submit a pull request for the APME project. Syncs with upstream,
creates a feature branch, runs quality gates (tox -e lint, tox -e unit),
updates documentation and ADRs as needed, commits with conventional commits,
then creates the PR via gh. Use when the user asks to submit, create, or open
a pull request, or says "submit PR", "open PR", "create PR", "new PR".
argument-hint: "[branch-name] [--title 'PR title']"
user-invocable: true
metadata:
origin: Ansible
author: APME Team
version: 1.6.0
---
# PR New
## Workflow
### Step 1: Sync with upstream and create a feature branch
Always start from the latest upstream main:
```bash
git fetch upstream
git checkout -b <branch-name> upstream/main
```
Use a descriptive branch name (e.g., `feat/add-ruff-prek`, `fix/parser-context-manager`).
If changes already exist on the current branch (e.g., from an in-progress session), cherry-pick or rebase them onto the new branch.
### Step 2: Run quality gates
```bash
tox -e lint
tox -e unit
```
**Both must pass cleanly on the full tree** — not just the files you changed.
If the branch has pre-existing violations (e.g., from an old base), rebase onto `upstream/main` first.
Do **not** run `ruff`, `mypy`, `prek`, or `pytest` directly — always use tox (ADR-047).
See the `/tox` skill for the full environment reference.
### Step 3: Self-review the diff
**This step is mandatory.** Do not skip it. Do not combine it with
Step 2. After quality gates pass, review the **full PR diff** — all commits
since the branch diverged from the base branch, not just the last
commit or unstaged changes:
```bash
git diff upstream/main...HEAD
```
Read every changed line against these questions. For each question,
name at least one specific file and line you verified. If you cannot,
you haven't actually reviewed the diff.
**Context rule.** The diff alone is not sufficient for Q1, Q4, and Q7.
Before evaluating those questions, **read the full function, class, or
module** surrounding each changed hunk — not just the hunk itself:
- **Q1 (statements mean what they say):** Read the function body to
verify that new or modified docstrings/comments accurately describe
what the code actually does. A docstring that says "all validators
receive scoped data" is wrong if one validator receives the full
graph.
- **Q4 (still true after this change):** Search for all prose that
describes the behavior you changed — not just prose you edited.
If you changed how a function is called, grep for every docstring
and comment that references that function.
- **Q7 (internally consistent):** Read sibling files and functions
before writing new code. If you add a `.pyi` field, read the other
`.pyi` files for conventions. If you write a test, read the sibling
tests for mock patterns. If you add an env var check, read how
existing env var checks handle the missing case. If you add a UI
control for an action the product already has (same label, href, or
table-cell pattern), reuse that component rather than a parallel
HTML primitive.
**Artifact-type sweep.** Before answering the questions below, list
every distinct artifact type in the diff (e.g., Python, proto, Rego,
Ansible YAML, shell script, Dockerfile, JSON config, Markdown). For
each question, you must cite at least one file of _each_ artifact
type — not just Python. If a question feels inapplicable to an
artifact type, translate it:
- "caller" in proto means any service or CLI that invokes an RPC
(e.g., Engine calling `Validator.Validate`, CLI calling
`FixSession`)
- "type signature" in Rego means a rule's expected input/output
shape (e.g., `input.hierarchy` must contain certain keys)
- "manifest parity" means every gRPC service in `proto/*.proto` has
a matching servicer in `daemon/` and every RPC method has a handler
- "constructed scenario" for async servers means: what happens when
`run_in_executor()` blocks longer than expected, when a validator
never responds, or when `asyncio.gather()` returns a mix of results
and exceptions?
- "dependencies pinned to intent" for Dockerfiles means: does the
base image tag, `pip install` version spec, or `COPY` path express
exactly what you mean?
1. **Does every statement mean what it says?** Check every type
annotation, return value, error code, version range, log level,
comment, and docstring. If the code declares it, the runtime must
honor it on every path.
For recurring background work, compare steady-state and transition logs:
unchanged successes and repeated failures should not crowd out meaningful
changes; initial failures and recoveries must remain visible.
When classifying free-form diagnostics, require context and token boundaries
for numeric identifiers so unrelated values do not acquire error semantics.
Check real diagnostics from the upstream producer, including every supported
output format, so restrictive matching still recognizes actual failures.
2. **Does this expose more than it should?** Check every log call,
error message, and user-facing string. Does it contain user content,
credentials, or internal state? Could a caller or log reader learn
something they shouldn't? Also check every capability grant:
permission scopes, CORS origins, container capabilities. Does each
grant the minimum necessary?
3. **Would a caller be surprised?** Read every public function from
the caller's perspective. Can it return a value the type doesn't
cover? Does it mutate an argument the caller owns? Does it throw
where the signature implies it won't? Does it have side effects
(logging, I/O, global state) that its name or signature doesn't
advertise? Does it behave differently from sibling functions in
the same module? When a helper opens a channel, socket, or other
closeable resource, does every return path (success and failure)
close it — typically via `finally` — or can a failed RPC leak it?
Trace async entry points through helpers to every filesystem operation,
including discovery, metadata probes, and parsing. Blocking storage must
stay off the event loop, and unchanged hot paths should avoid repeated
content reads and unnecessary shared-lock contention.
4. **Is everything still true after this change?** Diff comments and
docstrings against the code they describe. Did you rename something
but leave the old name in prose? Did you change behavior but leave
an old description? Check ADRs, `CLAUDE.md`, `AGENTS.md`, and
`docs/` for stale references. When implementation adds an
intentional filter or exception (e.g. stamp only compatible
members of a mixed group), update any ADR/doc that still says
"all" / "every" — prose that overclaims is drift even if the
code is correct. When one ADR cites another coupling or inventory
rule (sole import site, core vs optional validators, required
services), confirm the citing ADR does not invent a second path
that contradicts it. When docs name protobuf fields on
`SessionEvent` / `SessionResult` / reporting events, verify the
field exists on that message in the active `.proto` — aggregated
types defined elsewhere do not imply they are streamed.
5. **Are dependencies and versions pinned to intent?** Check every
version range, action tag, and base image. Does each one express
what you actually mean — not tighter, not looser? When updating a tool
used by CI, compare all of its resolution sources: CI requirements,
project lockfiles, developer install commands, and agent setup guides.
Keep the resolved versions aligned or document the intentional split.
For workflow
checkouts: if the job has write scopes (`packages: write`, etc.)
or runs untrusted/repo scripts after checkout, is
`persist-credentials: false` set so `GITHUB_TOKEN` is not left
in local Git config? Match sibling jobs in the same workflow.
6. **Is there dead weight?** Check for unused imports, unreachable
branches, written-but-never-read variables, parameters accepted
but ignored. Also flag **paid-for-but-wasteful work**: parsing
the same JSON twice in one loop body; `list.pop(0)` / repeated
`list.insert(0, …)` when a `deque` (or reverse + `pop()`) would
be O(1); `len(list(seq))` when `len(seq)` works; nested scans
that are O(P×V) when an id→row map would be O(P+V) — reviewers
treat these as dead weight even when functionally correct.
7. **Is this internally and externally consistent?** Within each
module: do all code paths use the same patterns (e.g., registry
lookups vs hardcoded values)? Are exports named consistently?
When a function accepts multiple input shapes (dataclass vs
mapping, ORM vs dict), do both paths normalize and branch the
same way for the same logical fields — or can one path skip a
transform the other applies? When adding an alternate branch
(interactive vs auto-apply, graph vs legacy text), trace both
paths to the same output artifact (file bytes, event payload,
telemetry) and confirm they run the same post-processing and
state-accounting steps — not just reach the same endpoint.
When overlaying fields from a
second source (e.g. outcome ``tier`` onto a pre-grouped
proposal), do dependent fields (``source``/``gate``/``tier``,
status→review mapping) stay aligned for *all* pre-group
sources — not only when the pre-group source was a sentinel
like ``"outcome"``? When adding fields to an existing
Pydantic/schema module, match sibling default patterns
(`Field(default_factory=list)` vs mutable `=[]`)? Across the
repo: do proto RPCs have matching servicer methods in `daemon/`?
Do rule IDs follow ADR-008 conventions (L/M/R/P/SEC)? Does
`_DEFAULT_PORTS` match the services actually started? Are
`event_emitter` calls consistent with the reporting sink
protocol? Cross-artifact mismatches (proto declaration vs Python
implementation) are the easiest to miss and the most embarrassing
to ship.
8. **Would a constructed scenario break this?** For each public
function, construct one realistic failure case: an edge-case
input, a specific field combination after deletion/filtering,
an empty-but-not-falsy value. Trace it through the code path.
If it fails silently, sends a vacuous request, or produces a
return value that violates the declared type, that's a finding.
When tests exercise optional OS or native capabilities, trace both
available and unavailable cases: gate capability-specific assertions
and separately assert the documented fallback.
When a check treats a character as a metacharacter (shell `|`,
glob `*`, YAML `&`), construct an input where that character is
a token in a *different* grammar in the same string — Jinja
filters (`{{ x | quote }}`), URLs, or quoted YAML. Strip or
parse the inner language before applying the outer check.
The strip pattern must allow nested tokens of the inner language
(Jinja dicts ``{{ {'k': 'v'} }}`` — ``[^{}]*`` fails). Leftover
delimiters after the strip (``{{``) are still uninspectable.
Glob character classes (``[ab]``) are shell features like ``*``.
If a transform inspects ``cmd`` and ``argv``, the detector must
inspect those same sources — ``not mo["cmd"]`` is not "safe".
After stripping, also construct the whole-string-is-inner-language
case (`{{ command }}`): empty remainder is uninspectable, not
proven-safe. When the same predicate exists in two languages
(Rego helper vs Python transform), construct whitespace that one
trim would drop and the other would keep (`\t` vs `" "` cutset)
— "empty" must mean the same thing on both sides. After the
emptiness check uses ``trim_space``, tokenize/split on that
string with the same whitespace class, not ``split(trim(x, " "), " ")``.
When a scanner skips escaped characters inside quoted strings,
verify that escaping follows the active quote style. Construct each
supported quote style with a backslash immediately before its closing
delimiter and structural text afterward; the scanner must close the
scalar and continue parsing that structure. YAML single-quoted scalars
treat backslashes literally, while doubled single quotes encode an apostrophe.
Also construct _temporal_ failures: what happens when an async
dependency never responds, times out, or responds after the
consumer has moved on? For React effects that rerun when a provider,
route, or selected entity changes, resolve and reject an older request
after cleanup; verify its success, catch, and finally handlers cannot
overwrite current data, selections, persisted values, or loading state.
What happens when `asyncio.gather()`
returns a mix of results and exceptions — does every caller
handle `return_exceptions=True` correctly?
Trace intentional control-flow exceptions through enclosing broad catches:
retries, cancellations, and source conflicts must retain their caller-visible
meaning. Malformed user configuration must reach the public entry point's
error contract with useful setting context and without exposing raw values.
For persisted identity, enumerate all transitive inputs (including trust
files, directory entries, and symlink targets); rotate their contents at
unchanged paths and verify both invalidation and steady-state reuse.
When the change schedules fire-and-forget tasks (notifications,
broadcasts, cleanup), construct the fixture/lifecycle race: does
teardown dispose shared resources (DB engine, clients) while a
pending task still needs them? Drain or cancel outstanding work
before closing those resources — mid-test awaits alone do not
cover paths that never assert on the side effect.
For persistence and aggregation helpers, also construct:
- **Concurrent writers** — two sessions calling the same
select-then-insert / claim path before either commits (lost
updates, double-counts, `IntegrityError`). Prefer atomic
upsert or compare-and-set claims.
- **Non-unique lookup keys** — dicts keyed by `(file, rule_id)`
or similar when duplicates are realistic; last-write-wins
silently corrupts overlays.
- **Mixed members of a group** — after grouping/bucketing, does
a single decision stamp apply to every member, including ones
of a different class (e.g. Tier 1 fixed + AI-candidate +
MANUAL_REVIEW on the same node path)? Filters must be
allowlists of the intended class, not "everything except X"
— the latter silently includes unrelated classes.
- **Docstring vs deny-by-default** — if prose says "only when
compatible" / "same class", the fallback branch must not return
``True`` unconditionally for unknown/sentinel sources.
9. **Do inherited contracts hold?** When implementing a Protocol
or extending a base class, check that the subclass honors the
full runtime contract — not just the compiler-required members,
but expected behaviors (validators must be read-only per ADR-009,
gRPC servicers must use `grpc.aio` per ADR-007, transforms must
call `submit()` for changes to take effect per ADR-044).
Only proceed to Step 3b after completing this review.
### Step 3b: Rule of Five (cold multi-agent review)
**This step is mandatory.** Step 3 is necessary but insufficient — it
suffers from confirmation bias because the reviewing agent wrote the
code. Spin up **independent read-only subagents** with no conversation
history. Each pass uses a progressively broader lens (in-the-small →
in-the-large). Findings that appear in **≥2 passes** are ship-blockers
until fixed or explicitly demoted with a documented follow-up.
This replaces the former single cold 9-question subagent. The nine
questions are **folded into the five lenses** below so coverage is not
lost.
#### Scale
| PR size | Passes | Which lenses |
|---------|--------|--------------|
| Small / chore / docs-only / single-file fix | **3** | Pass 1, 2, 5 |
| Nontrivial feature, ADR, multi-service, persistence, API | **5** | Pass 1–5 |
When unsure, use **5**.
#### Model selection (capabilities, not slugs)
Do **not** pin vendor model names or slugs in this skill — they rot.
When launching each Task subagent, choose a model by **capability
tier**, mapping to whatever the current agent runtime offers.
| Tier | Attributes to prefer | Use for |
|------|----------------------|---------|
| **fast** | Low latency, lower cost, solid at local reasoning and grep-style consistency checks; does not need deep architectural judgment | Pass **1**, Pass **2** |
| **strong** | Best available reasoning / long-context judgment in the current runtime; willing to challenge product framing and system design | Pass **3**, Pass **4**, Pass **5** |
**Selection rules:**
1. Match the tier’s **attributes**, not a remembered product name.
2. If the runtime only exposes one model, use it for every pass
(correctness over cost).
3. If several models fit a tier, pick the cheapest that still matches
the attributes — do not “upgrade” Pass 1–2 to strong by default.
4. Never downgrade Pass 3–5 to fast to save money; those passes catch
ship-blockers that mechanical review misses.
5. Parent aggregation stays on the parent model (no extra subagent).
#### Shared preamble (every pass)
Every subagent prompt must start with this block (fill in repo path,
branch, and PR number if known):
```text
You are Review Pass <N> of <TOTAL> for an APME pull request.
You have no prior context about why these changes were made — review
every line at face value.
Repository: <absolute path to repo>
Branch: <branch-name>
Base: upstream/main
PR: #<number or "unopened">
Run `git diff upstream/main...HEAD` for the full diff. Then:
1. List every distinct artifact type in the diff (Python, proto, Rego,
Ansible YAML, shell, Dockerfile, JSON/YAML config, Markdown, TS/TSX,
etc.). Your findings must cover each type that appears — translate
the lens if needed (e.g. "caller" in proto = any RPC invoker;
"pin to intent" in Dockerfiles = base image / pip / COPY paths).
2. Read each changed file in full (not just hunks). For new functions,
tests, or stubs, also read sibling files for convention consistency
(mocks, typing style, error handling).
3. Return ONLY actionable findings. No praise. No padding.
Format: **[Pass N / severity] file:line — description**
If truly nothing for your lens: "No findings."
```
Launch all passes in **one message** (parallel Task calls). Set each
subagent’s model according to the tier table above (fast vs strong) —
pass the runtime’s current model id that best matches the tier’s
attributes; omit `model` only when the runtime has a single option.
```text
Launch each Task subagent with:
subagent_type: "generalPurpose"
readonly: true
run_in_background: false
model: <runtime id matching Pass N's tier>
```
#### Pass 1 — classic bugs (narrow / in-the-small)
**Tier: fast.** Covers former cold-review **Q1, Q3, Q8** (bugs and edge paths).
```text
<shared preamble with N=1>
**Lens — classic code review:** Find concrete bugs in the changed code:
logic errors, off-by-ones, incorrect conditionals, race conditions,
wrong types, missing null checks, broken edge cases, return values that
violate declared types, caller-surprising behavior (nullable returns,
hidden mutation/I/O, throws the signature denies).
Also construct at least one realistic failure per public entry point:
empty-but-not-falsy values, post-filter field combinations, async
dependency never responds / asyncio.gather(return_exceptions=True)
mix, concurrent select-then-insert, non-unique dict keys, mixed members
of a group stamped with one decision, unbounded SQL IN clause size
limits (prefer ``col.in_(select(...))`` over materializing large id
lists into bound parameters; chunk at ~900 when a Python list is
unavoidable; when checking membership of a *small* candidate set
against a large table, query the intersection of those candidates —
never load the full table into Python just to filter a handful of ids),
silent ``OSError``/I/O suppress on paths later re-read by the pipeline
(stale content), writes that skip the same path-safety checks as
sibling helpers (``resolve`` + ``is_relative_to`` / reject ``..``),
and short-circuiting ``a() or b()`` / ``a() and b()`` when both calls
have required side effects (e.g. promote ledger status after approving
progression — evaluate both unconditionally).
When adding a new error return after a status-machine transition
(``SUBMITTING_PR``, ``APPLYING``, etc.), construct the failure *after*
that transition — both explicit raises *and* exceptions from helpers
called in that window (DB commit, flush, RPC). Require the same
restore-to-terminal path as sibling error handlers in the same
function; a 404/409/422/500 that skips ``transition(COMPLETED)`` leaves
live operations stuck in the in-flight status. Match existing
SCM/token/provider error paths before introducing a new raise —
including the same transition extras (``error=``) sibling failure
handlers pass, so SSE subscribers see why the in-flight status ended.
When a parser treats ``:`` as host/port, construct the edge cases that
break ``rpartition(":")``: empty host (``:port``), unbracketed IPv6
(``::1``), ``[ipv6]:port``, and malformed ports (``[::1]:``,
``host:abc``). If a caller claims graceful degrade and only catches
``ImportError``, also construct a parse ``ValueError`` through that
caller. Do not treat “contains a colon” as proof of TCP.
For hostname-based socket probes, construct IPv4-only, IPv6-only, and
dual-stack DNS answers in both answer orders. Verify every resolved
address is probed with its matching socket family, and simulate
resolution failures and recovery so an unavailable lookup cannot be
misreported as a free port or retried with a guessed family.
For best-effort local-address discovery, verify candidates with an
ephemeral bind before adding them to wildcard probe targets. Drop
non-loopback candidates rejected as no longer local, but retain the
loopback sentinel when it fails with ``EADDRNOTAVAIL`` and candidates
when the family itself is unsupported. Stale-state checks must treat
these as unverified instead of free.
For durable state that records a hostname, simulate DNS changing between
state creation and recovery. Current resolver answers cannot prove where the
process originally bound; persist the original targets or fail closed when
no address snapshot exists.
When a function degrades to identity (return original / omit from
diffs / skip and continue) on failure, construct the caller path that
reports "already clean", "idempotent", or "success" from an empty
result list — require an explicit per-item diagnostic (error field,
skipped list, WARNING progress/log) so failure is not presented as
success. If that diagnostic is logged inside ``run_in_executor``,
require ``contextvars.copy_context()`` (or an explicit progress event)
so ADR-033 collectors and FixSession clients actually see it.
When a graph builder maps ordered source sections to sibling edges,
compare edge positions with the source language's execution phases, not
only build order. Test a producer in an earlier phase consumed by a later
phase (for Ansible plays: ``pre_tasks → roles → tasks → post_tasks``).
Treat structured health/status bodies as contracts: reject
substring/`"ok" in body` checks when the peer emits JSON with a
``status`` field — require exact equality (``status == "ok"``).
``{"status":"not ok"}`` must not pass a contains-ok test.
When a snippet is embedded in a templated config (tox ``commands =``,
GitHub ``run:``), construct interpolator collisions: unescaped
``{...}`` that tox substitutes before Python runs. For
``next(glob(...))``, construct the empty-match path and require an
explicit error instead of ``StopIteration``.
For any text unescape/decode normalizer, construct inputs with one and
multiple escaping layers, structural boundaries at root and nested
positions, and lookalike escape sequences inside quoted content. Verify
the detector and the rewrite recognize the same boundaries.
Do NOT discuss architecture philosophy. Rank findings
critical/high/medium/low.
```
#### Pass 2 — consistency, drift, and waste
**Tier: fast.** Covers former cold-review **Q4, Q5, Q6, Q7**.
```text
<shared preamble with N=2>
**Lens — consistency & drift:** Assume Pass 1 caught obvious bugs. Hunt for:
- Docstring/ADR/comment vs code drift (especially "all"/"every" claims
vs filtered implementation)
- Rename/migration incompleteness: when an identifier is renamed in the
diff, scan the same affected docs, tests, operator manifests, and state-file
contracts for leftover old names in *current* guidance (historical
notes OK only when explicitly marked). Prefer a compatibility alias
or an explicit breaking-change note for persisted/public keys.
- Dual input shapes that normalize differently (ORM vs dict, dataclass
vs mapping, servicer vs flush path)
- Dual implementations of the same predicate (Rego helper vs Python
transform) that disagree on empty/whitespace (`trim(..., " ")` vs
`str.strip()` / `trim_space`). After one path uses ``trim_space``,
later tokenize/split on the **same string** must use that whitespace
class — ``split(trim(cmd, " "), " ")`` will miss tabs/CRs the
emptiness check already treats as blank. They must also inspect the
**same input shapes** (``cmd`` vs ``argv`` vs ``_raw_params`` vs
missing).
- Overlay fields that drift (tier/source/gate/status→review must stay
aligned for all pre-group sources). When a column documents
"empty means fall back to X" (e.g. ``stamp_rule_ids_json`` →
``rule_ids_json``), every stamp/filter path must honor that
fallback — skipping the filter when empty is a contract break.
- Schema/API mistakes (ADR-060: no breaking changes to /api/v1).
Tightening previously-lenient validation (e.g. turning ignored
unknown ids into hard 400s) is a semantic break even if the
OpenAPI shape is unchanged — prefer log+ignore / intersection
unless an ADR explicitly hardens the contract.
- Cross-artifact parity (proto RPC ↔ daemon servicer; rule IDs ADR-008;
_DEFAULT_PORTS ↔ started services; operator manifests ↔ Podman
``pod.yaml`` for the same in-pod env/volume/probe wiring — if the operator
mounts a shared socket for Gateway health, Podman Gateway must too)
- Sibling-rule parity: when rules enforce the same security condition,
compare their scope enumeration and all-path requirements so a protected
path cannot hide an unprotected path in another rule (for example, L047
and L110 handling shared include contexts).
- Test gaps for behaviors the code/docs claim; verify each regression test
reaches the changed logic and would fail without the fix (use a positive
control or the pre-fix behavior when practical)
- Silent no-ops, dead branches, wrong defaults
- **Dependencies pinned to intent** — version ranges, GitHub Action
tags, base images, pip/uv specs (not tighter, not looser);
checkout `persist-credentials: false` when write-scoped tokens
must not remain in local Git config for later steps.
Tool versions in workflow YAML vs the repo-managed source
(``requires-python``, ``frontend/package.json`` ``engines.node``):
prefer ``node-version-file`` over a hard-coded number. Extra setup
actions need an explicit lean-ci exception next to the job.
- **Dead weight** — unused imports/params; paid-for-but-wasteful work:
double JSON parse, list.pop(0)/insert(0,…) vs deque, len(list(seq)),
O(P×V) nested scans that should be O(P+V)
- Pydantic/schema mutable defaults (`=[]`) vs sibling Field(default_factory=list)
- UI controls that duplicate an existing product action with a
different primitive (raw ``<a>`` vs PatternFly ``Button
variant="link" component="a"`` already used for the same "View PR"
/ table-cell link). Match the sibling component, including
``isInline`` in table cells.
Explain briefly why a Pass-1-style review would miss each finding.
```
#### Pass 3 — Right Thing / product fitness
**Tier: strong.** Covers former cold-review **Q3 (product surprise), Q9 (invariants)**.
```text
<shared preamble with N=3>
**Lens — are we doing the Right Thing?** Read the governing ADR(s),
AGENTS.md architectural invariants, and the implementation. Ask:
- Does this actually solve the stated goal, or is it a half-measure /
framing overclaim?
- Are lifecycle triggers complete, or will users lose state unexpectedly?
- Is the grain/grouping/API shape honest for the UX story?
- Do filters or demotions contradict docs/ADR claims?
- Any invariant violations (validators read-only ADR-009, grpc.aio
ADR-007, engine never queries out ADR-020/029, REST additive-only
ADR-060, transforms submit() ADR-044, tox-only ADR-047, etc.)?
- Do Protocol / base-class implementations honor full runtime contracts,
not just compiler-required members?
Return **[Right Thing / Design Risk]** with recommendation:
fix-now vs follow-up issue. Be skeptical.
```
#### Pass 4 — system architecture (in-the-large)
**Tier: strong.** Covers former cold-review **Q7–Q9** at system scale.
```text
<shared preamble with N=4>
**Lens — system architecture:** Zoom out beyond this PR's files:
- Dependency direction (gateway vs engine; no inverted imports)
- Where state lives and failure modes (concurrency, restart,
multi-instance, partial flush/claim). Client-visible IDs that
authorize or bind requests (gate ids, session tokens, generation
handles) must not reuse values across process lifetimes —
process-local counters reset on restart and can accept stale
client retries against a new operation
- Scaling: algorithmic cost, PostgreSQL parameter limits, fan-out under load
- Whether schemas/analytics support the views claimed in ADR/docs
- Frontend/API contract readiness for the stated UX
- Migration/backfill for existing deployments
- Interaction with surrounding RPC/event timing (e.g. FixSession /
ReportFixCompleted)
Compare ADR/doc claims to what shipped. Label each finding
"fix in this PR" vs "track as issue".
```
#### Pass 5 — adversarial / exposure / simplify
**Tier: strong.** Covers former cold-review **Q2, Q8** plus deliberate simplification.
```text
<shared preamble with N=5>
**Lens — break it / rethink it:** Be creatively adversarial:
- Weird but realistic scenarios that corrupt durable state, double-count
analytics, or bypass filters
- **Overloaded tokens** — a character that is a metacharacter in one
grammar (shell `|`, glob `*`) is an operator in another (Jinja
`|quote`) in the same string. Strip or parse the inner language
before applying the outer check. After stripping, an empty remainder
is uninspectable, not proven-safe — treat it as the conservative
case (keep shell / skip substitution), not as "no features found".
"Empty" must use the same whitespace definition in every
implementation of the check (`trim_space` / `str.strip()`, not a
space-only cutset).
- **Information exposure** — logs, errors, user-facing strings,
persisted diffs/explanations: credentials, secrets, user content,
internal paths? Capability grants, CORS origins, container caps —
minimum necessary?
- Multi-tenant / empty project_id / confused or hostile clients against
additive API fields
- Time travel: clock skew, flush-then-rebuild inconsistency, partial
claim failures; tests that encode absolute calendar timestamps for
"stale" / "within window" checks instead of `now() ± offset`
- If you deleted 50% of this design, what still ships the goal?
Return: (1) adversarial findings that could be real bugs,
(2) simplify/kill recommendations,
(3) short verdict: converged enough to merge, or what must change first?
```
#### Aggregate, act, converge
After all passes return, the parent agent must:
1. **Deduplicate** findings and build a table: finding → which passes →
severity → fix-now vs follow-up.
2. **Ship-blockers** = any finding in **≥2 passes**, plus any single-pass
**critical** or **major** finding (data corruption, security exposure,
ADR-060 break, invariant violation, or a Pass-rated major defect in
one lens). Single-pass **medium/low** may be follow-ups; single-pass
major must be fixed or explicitly demoted with human approval before
Step 4.
3. **Act on ship-blockers.** Fix code (or demote ADR/PR framing and open
a tracked follow-up). Re-run `tox -e lint` and `tox -e unit`.
4. **Re-run Rule of Five** after substantive fixes until:
- no new multi-pass or single-pass major/critical ship-blockers, and
- Pass 5's verdict is merge-ready (or framing is honestly demoted).
5. Document dismissed findings with a clear technical justification.
Do not proceed to Step 4 until convergence (or an explicit user decision
to accept remaining follow-ups).
### Step 4: Update documentation
Check whether your changes affect areas covered by existing docs. Update any that apply:
| Doc | When to update |
|-----|----------------|
| `docs/guides/DEVELOPMENT.md` | New dev workflows, setup changes, new rule patterns |
| `docs/architecture/` | Container topology, gRPC contract changes, new services |
| `docs/architecture/` | Request lifecycle, serialization, payload shape changes |
| `docs/guides/DEPLOYMENT.md` | Podman pod spec, container config, env vars |
| `docs/rules/LINT_RULE_MAPPING.md` | New or renamed rule IDs |
| `docs/design/DESIGN_VALIDATORS.md` | Validator abstraction changes |
| `docs/design/DESIGN_REMEDIATION.md` | Remediation engine changes |
If a new rule was added, regenerate the catalog:
```bash
python tools/generate_rule_catalog.py
```
### Step 4b: ADR and issue traceability (mandatory)
**Do not commit or open a PR until this step passes** (or gaps are explicitly
documented in the PR body with follow-up issues filed).
Follow the **`pr-traceability`** skill (`.agents/skills/pr-traceability/SKILL.md`):
1. Find related **GitHub issues** — link with `Closes #N` / `Refs #N`, or create
an issue / document why none applies.
2. Find related **ADRs** — update status (`Implemented`, `Partially
Implemented`, etc.), revision history, and regenerate the index when the PR
implements or advances an ADR decision.
3. Add **`## Related issues`** and **`## Related ADRs`** sections to the PR body.
If the change is a **new** architectural decision, run **`/adr-new`** (Step 5)
before or in the same PR — do not ship code that contradicts an accepted ADR
without a superseding ADR.
Reviewers use the same checklist via `pr-contributor-review` and
`pr-address-feedback` after follow-up commits.
### Step 5: Update SDLC artifacts (if applicable)
If the change involves an architectural decision (new service, new protocol, new deployment strategy, new tooling adoption), create an ADR in `.sdlc/adrs/` using the `adr-new` skill. The file should follow the naming convention `ADR-NNN-slug.md`.
If open questions or decisions emerged during the session, create a Decision Request using the `dr-new` skill.
If requirements or tasks were affected, update them using the `req-new` or `task-new` skills.
The agent should invoke these skills proactively when context warrants it, informing the user of any artifacts created. All artifacts are reviewed in the PR diff.
### Step 6: Commit with conventional commits
Use the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) format:
```
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
```
Common types for this project:
| Type | When to use |
|------|-------------|
| `feat` | New feature (rule, validator, CLI subcommand, service) |
| `fix` | Bug fix |
| `docs` | Documentation only |
| `style` | Code style/formatting (no logic change) |
| `refactor` | Code restructuring (no feature or fix) |
| `test` | Adding or updating tests |
| `build` | Build system, dependencies, containers |
| `ci` | CI/CD configuration |
| `chore` | Maintenance tasks |
Scopes reflect project areas: `engine`, `native`, `opa`, `ansible`, `gitleaks`, `daemon`, `cli`, `formatter`, `remediation`, `cache`, `proto`.
Examples:
- `feat(native): add L060 jinja2-spacing rule`
- `fix(engine): use context manager for file reads in parser`
- `build: add ruff linter and prek pre-commit hooks`
- `docs: add prek section to DEVELOPMENT.md`
### Step 7: Check branch/artifact alignment
Before pushing, verify the branch name matches the artifact IDs being committed:
```
Checking branch/artifact alignment...
- Branch: docs/req-005-aa-deprecated-reporting
- SDLC artifacts in diff: REQ-011, DR-013
```
**If mismatch detected:**
```
⚠️ Branch name contains 'req-005' but artifacts use REQ-011
Options:
1. Rename branch to match artifacts (recommended)
2. Continue with mismatched names (not recommended)
Choice (1/2):
```
If option 1 selected, use `/branch-align` to rename before pushing.
**Why this matters:** Reviewers and future contributors use branch names to find related work. A branch named `req-005` that contains `REQ-011` creates confusion.
### Step 8: Push and create the pull request
```bash
git push -u origin HEAD
gh pr create --repo upstream-owner/repo --title "conventional commit style title" --body "$(cat <<'EOF'
## Summary
- Concise description of what changed and why
## Changes
- List of notable changes
## Related issues
- Closes #NNN — <why>
- Refs #NNN — <partial / context> (or `None — <why no related issue applies>`)
## Related ADRs
- ADR-NNN — <status change or "reviewed, no change"> (or `None — <why no related ADR applies>`)
## Quality of life
- List any non-functional improvements bundled in this PR: skill updates,
workflow fixes, SDLC artifact changes, rule/template tweaks, documentation
for contributor experience, etc.
- Omit this section entirely if there are none.
## Test plan
- [ ] `tox -e lint` passes
- [ ] `tox -e unit` passes
- [ ] Docs updated (if applicable)
- [ ] ADR added or updated (if applicable)
- [ ] Issues referenced (`Closes` / `Refs`) per pr-traceability
EOF
)"
```
The PR targets upstream's `main` branch from the fork. Return the PR URL to the user.
### Including non-code changes (Quality of life)
PRs often include changes that are not directly part of the feature or fix but
improve the development workflow: skill updates, SDLC template tweaks, rule
improvements, documentation for contributor experience, or process fixes.
These changes belong in the **Quality of life** section of the PR body. Use
this section whenever the PR touches files like `.agents/skills/`, `.sdlc/`,
`CLAUDE.md`, `AGENTS.md`, `SOP.md`, `CONTRIBUTING.md`, or similar workflow
artifacts. This makes it easy for reviewers to separate functional changes
from process improvements.
If a PR contains **only** quality-of-life changes (no production code), use
`chore` or `docs` as the commit type.
### Maintaining the PR
When pushing additional commits to an existing PR, **always update the PR body** to reflect the new changes:
```bash
gh pr edit <pr-number> --body "$(cat <<'EOF'
...updated body...
EOF
)"
```
The Summary, Changes, and Test plan sections must stay current with all commits on the branch, not just the initial one.
### Responding to review feedback
After pushing the PR, reviewers (human, Copilot, or CodeRabbit) may leave
comments. Follow the **`pr-address-feedback`** skill for the full procedure:
checking CI status, replying to comments, resolving threads, and re-checking
for new automated reviews.Colle ce Markdown dans ton agent ou utilise les boutons ci-dessus pour l’écrire dans ton projet.
Ce que fait PR New (Ansible) — Agents
**Q1 (statements mean what they say):** Read the function body to
**Q4 (still true after this change):** Search for all prose that
**Q7 (internally consistent):** Read sibling files and functions
"caller" in proto means any service or CLI that invokes an RPC
Comment utiliser PR New (Ansible) — Agents
1
Copie le prompt
Un clic copie le prompt packagé (ou l'envoie à ton agent).
2
L'agent installe le skill
Il ajoute le SKILL.md et ses ressources à ton projet.
3
Activation automatique
Le skill s'active dès que le contexte correspond.
Déclencheurs pour PR New (Ansible) — Agents
Dis simplement à ton agent quelque chose comme :
Applique le skill pr-new__ansible-apme__agents-skills-fe0eb434a77a à cette tâche
Utilise pr-new__ansible-apme__agents-skills-fe0eb434a77a pour améliorer cette implémentation
Passe en revue ce sujet avec pr-new__ansible-apme__agents-skills-fe0eb434a77a
Skills liés à PR New (Ansible) — Agents
Add Excel (Microsoft)
Adds Excel Online (Business) connector to a Power Apps code app. Use when reading or writing Excel workbook data from OneDrive or SharePoint.IA Usecase Assessment (Microsoft)
Use this skill whenever the user says "assess this use case", "score my AI use case", "prioritise these agent ideas", "generate a use case assessment report", or "update my AI use case report" — or when they attach a use-case document, SDR, or prior `*_AI_UseCase_Assessment_Report_*.html` and ask you to assess, strengthen, score, or refresh it. Invoke BEFORE writing any assessment content and BEFORE generating any report.Aibast Document Checklist 03 (Microsoft)
Use for document readiness questions in the Customer Onboarding Agent synthetic pilot.