# Quality Audit Phase (Step 6)

**Precondition:** Backlog cards created (Step 5 complete). Card IDs available from Step 5.

> **YOLO MODE**: All agents spawned via the Task tool MUST use `mode: "bypassPermissions"`. No exceptions.

This phase coordinates parallel audit agents on backlog cards **before development starts** to catch issues early. Each audit agent runs as an independent teammate with its own context window (prevents context saturation).

---

## Step 6.1 — Identify Cards

Use the card IDs produced by Step 5 (prd-card-writer output). No user prompt needed — cards are a mechanical derivation from the approved PRD.

Read each card from `${paths.backlog_dir}/*.yml` to understand scope, requirements, acceptance criteria, and planned changes.

## Step 6.2 — Signal Detection: Security (AUTOMATIC)

Scan each card for security signals to decide whether the `security-reviewer` agent joins the audit.

**Triggered if ANY card meets ONE OR MORE conditions:**

| Signal | Where to look |
|--------|---------------|
| **New or modified API route** | `files_likely_touched` contains `route.ts`, `api/`, or requirements mention new endpoints |
| **Authentication/authorization changes** | Requirements/files mention the project's auth-guard wrapper or permission helper (e.g. a `withAuth*`-style wrapper / `checkPermission`-style guard — resolve from `${paths.high_risk_modules}`), or generic markers: `permissions`, login, session, token, JWT, OAuth |
| **Persistence-layer access rules** | `files_likely_touched` contains rule/policy files matching `stack.database` (e.g. `firestore.rules`, Supabase RLS migration, MongoDB validator) or requirements mention rule changes |
| **External integrations** | Requirements mention webhooks, third-party APIs, payment, SMS, email providers, or external callbacks |
| **File upload or media handling** | Requirements mention upload, image, file, media, or `files_likely_touched` contains upload/media paths |
| **User input processing** | Requirements mention forms, search, filters, or query parameters that flow into DB queries or server logic |
| **Multi-tenant data access** | Requirements mention cross-tenant boundaries (cross-org, cross-workspace, cross-store, cross-account — actual tenant noun from `identity.audience_segments[]`) or data visible to multiple tenants |
| **Sensitive data handling** | Requirements mention PII, credentials, tokens, secrets, or personal data |

**How to assess**: Read each card's `requirements`, `acceptance_criteria`, `files_likely_touched`, `areas`, `existing_patterns`, `anti_patterns`, `validation_commands`, `error_handling`, and `scope_boundaries` fields. This is a **SEMANTIC** check — keyword and path matching on card prose requires interpretation, so it is biased toward RECALL: when a signal is ambiguous, INCLUDE the reviewer rather than skip it. (It is not "deterministic" — a card whose auth change lives in an auth-suggestive `files_likely_touched` path but whose `requirements` omit the trigger keywords can still slip through; prefer the path heuristic over relying on prose keywords alone.)

**Output**: Set internal flag `security_review_needed: true/false`. If ANY card triggers → include `security-reviewer` for ALL cards.

**Transparency**: Inform the user:
- If triggered: "Security review triggered — exposed surfaces detected: [list signals]."
- If not: "Security review not required — no exposed surfaces detected."

## Step 6.3 — Signal Detection: Performance (AUTOMATIC)

Scan each card for performance signals to decide whether the `api-perf-cost-auditor` agent joins.

**Triggered if ANY card meets ONE OR MORE conditions:**

| Signal | Where to look |
|--------|---------------|
| **New or modified API route** | `files_likely_touched` contains `route.ts`, `api/`, or requirements mention new endpoints |
| **Persistence-layer read/write operations** | Requirements mention {entity} read/write, query, transaction, batch, listener/subscription/change-stream (terminology depends on `stack.database`) |
| **List/search/filter endpoints** | Requirements mention listing, searching, filtering, sorting, pagination, or "show all" |
| **Background/batch processing** | Requirements mention cron, batch, import, export, bulk, queue, or scheduled tasks |
| **Real-time/live updates** | Requirements mention real-time, live, auto-update, listener, onSnapshot, subscription |
| **File upload/download** | Requirements mention upload, download, file, media, image processing, or signed URL |
| **Caching decisions** | Requirements mention cache, revalidate, freshness, or card lacks caching strategy for read-heavy endpoints |
| **Cost-sensitive operations** | Requirements mention counters, aggregations, analytics, or denormalization |

**Output**: Set internal flag `perf_review_needed: true/false`. If ANY card triggers → include `api-perf-cost-auditor` for ALL cards.

**Transparency**: Inform the user:
- If triggered: "Performance audit triggered — surfaces with cost/performance impact detected: [list signals]."
- If not: "Performance audit not required — no API/data surfaces detected."

## Step 6.4 — Adjacent Card Retrieval (dependency detection)

[DESIGN-CHOICE: adjacent card context is retrieved to reduce implicit dependency misses — LLMs processing cards in isolation are likely to miss cross-card file conflicts and ordering constraints not captured in explicit `depends_on` fields]

To detect implicit dependencies, gather adjacent context:

1. For each card being audited, check its `depends_on` field for referenced cards → read those cards.
2. Read ALL cards in `${paths.backlog_dir}/` that share the same `epic:` or `parent:` field as the audited cards.
3. Read ALL cards whose `files_likely_touched` overlaps with any audited card's files.
4. **Deduplicate**: merge the results from steps 1-3 into a single set by card ID before building summaries. A card matched by multiple criteria counts once.
5. Build a summary for each unique adjacent card: `{id, title, status, requirements (first 3 lines), files_likely_touched}`. Cap at 10 adjacent cards per audited card `[CALIBRATION-NEEDED: the cap is a context-budget guard, not an empirically tuned value — validate against prompt-size telemetry on large epics]`; if more are present, prefer `depends_on` references, then same-epic, then file-overlap.
6. Include these summaries in each audit agent's task description (Step 6.6) under `## Adjacent Cards`.

This enables agents to detect:
- File conflicts between cards planned for parallel execution
- Missing `depends_on` entries where Card A modifies a file Card B reads
- Duplicated requirements across sibling cards
- Ordering constraints not captured in the dependency graph

## Step 6.5 — Gather Context (lightweight)

Gather **only metadata** to build agent prompts — do NOT read full file contents into your own context:

1. Read the backlog card(s) YAML — store the raw text for each card.
2. If the card has `files_likely_touched` → note the file paths (do NOT read the files yourself).
3. If the card has `links.prd` → note the PRD path (do NOT read it yourself).
4. If the card references parent/child cards → note their paths.

**The audit agents will read files themselves in their own context windows.**

## Step 6.6 — Create Agent Team & Launch Audits

### 6.6a. Create the team

Use `TeamCreate` with name `check-audit` and description based on the cards being reviewed.

### 6.6b. Create tasks

Use `TaskCreate` to create one task per audit agent per card:

- For **N cards × M agent types**, create **N × M tasks** (one task per agent type per card; excluding Codex plan-audit — see 6.6d). In Step 6.6c, ONE teammate agent per type handles all N tasks in its queue — M agents run in parallel, not N×M.
- Each task subject: `[CARD-ID] <agent-type> audit`
- Each task description: full card YAML + adjacent card summaries + file paths + PRD path + instructions.

**Claim-lock (atomicity on the N×M fan-out)**: each task carries a `claimed_by` field, empty at creation. Before a teammate processes a task it MUST atomically set `claimed_by: <its name>` via `TaskUpdate` and re-read; if the field is already non-empty and not its own name, it SKIPS that task (another worker owns it). This prevents two workers — for example a re-spawn after a transient failure, or an overlapping re-audit (Step 6.9) — from both processing the same card+agent pair and producing duplicate findings. The teammate workflow (Step 6.6e) embeds the claim step.

**IMPORTANT**: Embed the full card YAML directly in the task description. For source files and PRDs, only provide paths — agents read those themselves.

### 6.6c. Launch teammate agents in parallel

For each audit agent type (except plan-auditor), spawn ONE teammate using the `Task` tool with `team_name: "check-audit"`.

**Agent type mapping:**

| Audit Role | `subagent_type` | Name | Condition |
|------------|-----------------|------|-----------|
| ~~plan-auditor (plan-logic role)~~ | — | — | **Replaced by Codex adversarial audit (Step 6.6d)** |
| plan-auditor (card grounding) | `plan-auditor` | `plan-auditor` | Always — but SKIP if the Codex fallback to FULL plan-auditor fires (6.6d), to avoid two plan-auditor instances on the same cards |
| doc-reviewer | `doc-reviewer` | `doc-reviewer` | Always |
| api-perf-cost-auditor | `api-perf-cost-auditor` | `perf-auditor` | `perf_review_needed: true` |
| security-reviewer | `security-reviewer` | `security-reviewer` | `security_review_needed: true` |

Launch ALL applicable teammates in a single message (parallel tool calls).

### 6.6d. Codex Adversarial Plan Audit (replaces plan-auditor)

> **Why Codex**: Cross-model validation — a non-Anthropic frontier model reviews artifacts produced by Claude,
> providing genuine diversity of perspective. [DESIGN-CHOICE: adversarial cross-model review catches blind spots that a single model cannot self-detect] Codex reads files directly from the filesystem.

Launch **in parallel** with the teammate agents (6.6c). Use `Bash` with `run_in_background: true` so Claude can launch teammate agents concurrently:

```bash
SESSION_ID="${SESSION_ID:-$(date +%s%N | md5sum | head -c8)}" && \
AUDIT_FILE="/tmp/codex-plan-audit-${CARD_ID_SLUG}-${SESSION_ID}.md" && \
CODEX_SCRIPT="$(ls -d ~/.claude/plugins/marketplaces/openai-codex/plugins/codex/scripts/codex-companion.mjs ~/.claude/plugins/cache/openai-codex/codex/*/scripts/codex-companion.mjs 2>/dev/null | sort -V | tail -1)" && \
[ -z "$CODEX_SCRIPT" ] && echo "CODEX_NOT_FOUND" && exit 1; \
node "$CODEX_SCRIPT" task --wait "
<task>
Perform an adversarial plan audit of the following backlog cards as a pre-development quality gate.
Your job is to find the strongest reasons these cards are NOT ready for implementation.
Default to skepticism. Assume each card can fail in subtle, high-cost ways.
Do not give credit for good intent or likely follow-up work.

Cards to audit (read each file):
${CARD_PATHS}

PRD reference: ${PRD_PATH}
Data model reference: ${paths.references_dir}/data-model.md
API reference: ${paths.api_index}
Adjacent cards context: ${ADJACENT_CARD_PATHS}
</task>

<attack_surface>
INVEST criteria violations:
- Independent: hidden dependencies on in-flight cards not in depends_on
- Negotiable: requirements too rigid or too vague for implementation
- Valuable: card does not deliver user-visible or system-critical value
- Estimable: scope unclear, cannot estimate effort
- Small: card too large for one dev session
- Testable: acceptance criteria not binary pass/fail

Requirements smell detection:
- Ambiguous pronouns without clear antecedent
- Passive voice hiding the actor
- Unbounded scope (all, every, any) without limits
- Missing error/failure paths (happy path only)
- Implicit ordering assumptions
- Conflicting constraints
- Missing units or thresholds
- Compound requirements covering multiple behaviors
- Dependency shadows: implicit deps not in depends_on

Database-specific (apply the subset matching `stack.database`):
- Universal: unbounded reads without limit, offset-based pagination instead of cursor/keyset, N+1 read in loops, transaction/concurrency hotspot risks
- firestore: missing composite index declarations, sequential-ID hotspots, listener attach cost not budgeted
- postgres/supabase: sequential scan on >100k rows, RLS policy missing on new table, JSONB without GIN index
- mongodb: missing compound index for hot aggregation, embedded array unbounded growth
- dynamodb: missing GSI for non-PK access pattern, hot-partition risk

Card structure:
- files_likely_touched missing entries or conflicting across cards
- areas field incomplete
- git_strategy set to TBD
- acceptance_criteria not binary testable
- definition_of_done missing items
- existing_patterns with stale line_range or missing anchor_text
- validation_commands missing for cards with testable outputs
- anti_patterns empty for cards modifying shared state
- scope_boundaries missing for multi-card epics
- error_handling missing for cards with network calls or user input
- reuse_analysis missing for cards creating new components
</attack_surface>

<grounding_rules>
Every finding MUST quote the exact YAML field or PRD text it references.
Do not invent issues without evidence from the card files.
If a conclusion depends on inference, state that explicitly and keep confidence honest.
Prefer one strong finding over several weak ones. Do not dilute with filler.
</grounding_rules>

<structured_output_contract>
For each card return:

### [CARD-ID] — Adversarial Plan Findings

- [ ] **Finding title** — Description. (Severity: HIGH/MEDIUM/LOW) [Target: <field>]
  > **Evidence:** exact quote from card YAML or PRD
  > **Source:** file path or field name
  > **Recommendation:** concrete fix

Target tags: requirements, acceptance_criteria, definition_of_done, files_likely_touched, depends_on, areas, git_strategy, unknowns, notes.

Severity rules:
- HIGH: data loss, security bypass, breaking change, or unbounded read
- MEDIUM: missing dep, vague AC, incomplete files_likely_touched
- LOW: informational only

End with a one-line ship/no-ship assessment per card.
Suppress findings where the strongest false-positive argument is convincing.
</structured_output_contract>
" 2>&1 | tee "$AUDIT_FILE"
```

**Variable interpolation** (build the command string before execution; read all values from the session tracker written at Phase 0 — never guess):
- `${CARD_PATHS}`: newline-separated list of `- ${paths.backlog_dir}/FEAT-XXXX-*.yml` paths from Step 5
- `${PRD_PATH}`: the PRD file path from the session state
- `${ADJACENT_CARD_PATHS}`: newline-separated list from Step 6.4
- `${CARD_ID_SLUG}`: hyphen-separated list of card IDs being audited (e.g. `FEAT-0042-FEAT-0043`) — written to session tracker at Phase 0
- `${SESSION_ID}`: unique run identifier written to the session tracker at Phase 0; the bash fallback `$(date +%s%N | md5sum | head -c8)` is a last resort only

**Timeout**: Set `timeout: 300000` (5 minutes) on the Bash call.

**Output handling**: The `tee` in the command persists output to `$AUDIT_FILE` (`/tmp/codex-plan-audit-<CARD-ID-SLUG>-<SESSION-ID>.md`) as it streams. This ensures findings survive regardless of foreground/background execution or stdout truncation.
1. Read findings from the path stored in `$AUDIT_FILE` (always available — written by `tee`).
2. If the file is empty or its content is `CODEX_NOT_FOUND`, fall back to `plan-auditor` subagent.
3. Merge into the consolidated report at Step 6.7 under `### Codex Plan Audit Findings`.

**Fallback**: If Codex is unavailable (not installed, not authenticated, or timeout), fall back to a **FULL-mode** `plan-auditor` subagent with `subagent_type: "plan-auditor"`. Log the fallback reason in the audit report. **When this fallback fires, do NOT also run the card-grounding plan-auditor teammate from 6.6c** — the FULL fallback subsumes its coverage; running two plan-auditor instances on the same cards is the exact double-fan-out the dedup guard below exists to prevent.

**Dedup guard on the fallback spawn (avoid double fan-out).** plan-auditor internally auto-spawns `codebase-architect` (always) and `security-reviewer` (when the cards carry auth/session signals). This audit session may have ALREADY produced those artifacts — `security-reviewer` runs as a first-class teammate whenever `security_review_needed: true` (Step 6.6c). To prevent a redundant second pass, the fallback `plan-auditor` invocation MUST be passed a context note instructing it to REUSE this session's artifacts rather than re-spawn:
- If `codebase-architect` was already spawned earlier this session (its summary is in the session tracker artifact registry), pass that summary in the prompt and instruct plan-auditor NOT to re-invoke `codebase-architect`.
- If `security_review_needed: true` (security-reviewer already ran as a teammate), instruct plan-auditor NOT to spawn `security-reviewer`; its security findings are already in the task store and will be merged at Step 6.7. plan-auditor should rely on those rather than running an independent, un-merged second review.

### 6.6e. Teammate prompt template

Each teammate receives this prompt:

```
## Identity

You are a SKEPTICAL auditor for a pre-development audit team ("check-audit").
Your default stance is that the card is NOT ready for implementation.
Do not rationalize away issues. Do not give benefit of the doubt.
If something COULD be a problem, flag it. The challenge pass (later) will filter false positives.
Your job is RECALL, not precision — catch everything, filter later.

## Your Workflow

1. Call `TaskList` to see your assigned tasks.
2. For each task (in ID order):
   a. Call `TaskGet` to read the full task description (card YAML + adjacent cards + file paths).
   a2. **Claim the task**: if `claimed_by` is already set to a name other than yours, SKIP this task (another worker owns it). Otherwise set `claimed_by: <your name>` via `TaskUpdate`, then re-read via `TaskGet` to confirm your claim held; if a different name won the race, SKIP.
   b. Mark task as `in_progress` via `TaskUpdate`.
   c. Read any source files or PRDs referenced in the task (use Read tool).
   d. Perform your audit (see instructions below).
   e. Run the Challenge Pass on your findings (see below).
   f. Run Severity Calibration on surviving findings (see below).
   g. **Write findings into the task description** via `TaskUpdate` — append a `## FINDINGS` section.
   h. Send a brief notification to orchestrator via `SendMessage` (task ID + one-line summary only).
   i. Mark task as `completed` via `TaskUpdate`.
3. After all tasks: send "all tasks complete" to orchestrator.

**IMPORTANT**: Always write findings to task description (step g) before notification (step h). Task description is durable; message is just a ping.

## Audit Instructions

{AGENT_SPECIFIC_INSTRUCTIONS}

## Output Format (mandatory evidence quotes)

For each card, return findings as:

### [CARD-ID] — {Agent Role} Findings

- [ ] **Finding title** — Description of the issue, risk, or gap. (Severity: HIGH/MEDIUM/LOW) [Target: <field>]
  > **Evidence:** "<exact quote from the card YAML, PRD, or source file>"
  > **Source:** `<file path or field name>`

**MANDATORY**: Every finding MUST include an evidence quote — a direct excerpt that grounds it. Findings without quotable evidence MUST be discarded. State: "Considered but discarded — no quotable evidence found."

If no findings: "No issues found for [CARD-ID]."

### `[Target: <field>]` tag reference (mandatory on every finding)

| Target tag | When to use |
|---|---|
| `[Target: requirements]` | Missing or wrong requirement text |
| `[Target: acceptance_criteria]` | Missing AC, vague AC needing rewrite |
| `[Target: definition_of_done]` | Missing DoD checkbox |
| `[Target: files_likely_touched]` | Missing file path |
| `[Target: depends_on]` | Missing dependency card ID |
| `[Target: areas]` | Missing area entry (api, docs, data, ui) |
| `[Target: git_strategy]` | `git_strategy: TBD` or wrong value |
| `[Target: unknowns]` | Unresolved unknown to surface |
| `[Target: existing_patterns]` | Missing or stale pattern reference |
| `[Target: validation_commands]` | Missing verification command |
| `[Target: anti_patterns]` | Missing DO NOT constraint |
| `[Target: scope_boundaries]` | Missing scope boundary item |
| `[Target: input_output_examples]` | Missing or incorrect I/O example |
| `[Target: error_handling]` | Missing failure mode spec |
| `[Target: reuse_analysis]` | Missing reuse opportunity or wrong path |
| `[Target: notes]` | LOW severity only — informational |

## Challenge Pass (mandatory before reporting)

After generating initial findings, challenge EACH one:

"What is the strongest argument that this is a false positive?"

Consider:
- Is this already handled elsewhere in the codebase?
- Is this a convention in this project I'm unfamiliar with?
- Is the card intentionally deferring this to a later card?
- Am I applying a generic best practice that doesn't fit this context?

**Suppress the finding if the FP argument is convincing.** Record suppressed findings:

<details>
<summary>Suppressed findings (N items — challenge pass)</summary>
- **Finding title** — FP argument: <why suppressed>
</details>

## Severity Calibration (after challenge pass)

After challenge pass, rank ALL surviving findings relative to each other by impact:

1. List all surviving findings in order of impact (most impactful first).
2. Assign severity based on position:
   - Top 20% → HIGH (must apply)
   - Middle 40% → MEDIUM (should apply)
   - Bottom 40% → LOW (notes only)
3. Exception: data loss, security bypass, or breaking change = automatically HIGH regardless of position.

### Severity Calibration Examples

**HIGH** (must fix before implementation):
- "acceptance_criteria says 'user can see <list>' but doesn't specify pagination → unbounded persistence-layer read"
  > Evidence: "AC-2: <persona from identity.audience_segments[]> views <entity>" — no limit/pagination mentioned

**MEDIUM** (should fix, skip if ambiguous):
- "files_likely_touched missing the API route doc update"
  > Evidence: files_likely_touched lists "src/app/api/v1/<domain>/route.ts" but not "${paths.references_dir}/api/<domain>.md"

**LOW** (note only):
- "Card title could be more descriptive"
  > Evidence: title is "Booking API" — functional but generic
```

### Agent-specific instructions

**plan-auditor**: **Handled by Codex adversarial audit (Step 6.6d).** Not included in the teammate agent team. If Codex is unavailable, the fallback plan-auditor uses INVEST criteria, DoR checks, and requirements smell detection — see Step 6.6d attack_surface for the full checklist.

**plan-auditor (card grounding)**: This is the Claude-side, codebase-grounded counterpart to the cross-model Codex plan audit (6.6d) — it brings what Codex lacks: project memory (`.claude/agent-memory/plan-auditor/MEMORY.md`) and the card-native `[Target: <field>]` tagging this audit consumes. Apply the **full BACKLOG CARD ATTACK SURFACE** (INVEST, requirements-smell detection, persistence-specific checks per `stack.database`, card-structure checks) against each card's `.yml`, reading the existing files in `files_likely_touched` to ground claims about conflicts with existing patterns, missing reuse opportunities, and convention alignment (per `identity.design_philosophy`, project lint/type-check rules, `identity.language`). Check `## Adjacent Cards` for parallel file modifications and missing `depends_on` edges.

> **Mode (team-aware — read first)**: you are running inside the coordinating `check-audit` team, so you MUST behave as in QUICK mode for *spawning* while keeping FULL card-attack-surface *coverage*:
> - **Do NOT spawn `codebase-architect`** for grounding — `/prd` already primed codebase context at kickoff (context-primer) and you read `files_likely_touched` directly. A re-spawn here is wasteful and forbidden.
> - **Do NOT auto-spawn specialists** (`security-reviewer` / `api-perf-cost-auditor` / `ui-expert`) — they run as first-class teammates in this same team whenever their signal fires (6.6c). Consume their findings at merge time; never double-spawn.
> - **Output-format override** (symmetric with the security-reviewer / api-perf-cost-auditor overrides above): produce findings in the teammate contract format (`### [CARD-ID] — Plan Audit Findings` with `[Target: <field>]` tags written to a `## FINDINGS` section via `TaskUpdate`) — NOT plan-auditor's native 10-section OUTPUT FORMAT (Hardened Plan, Pre-Mortem, Risk Register, YAML schema dump). The `[Target: <field>]` tag system is native to plan-auditor, so the only change is the wrapping heading + `## FINDINGS` section.
> - Never suppress a `git_strategy: TBD`, missing-auth, `claimed_path_collision`, `adr_required_missing`, or prompt-injection finding (plan-auditor's never-suppress list still binds here).

**doc-reviewer**: Check documentation links, PRD references are valid and aligned, planned changes requiring doc updates not mentioned. Verify `files_likely_touched` includes doc files. Check `areas` completeness. Flag `git_strategy: TBD`. Include Obsidian trigger assessment (section H) in findings — evaluate whether the planned docs will require KB sync. If `.claude/skills/doc-reviewer-support/references/obsidian-integration.md` is present, use its criteria; otherwise apply a minimal check: does the card introduce new or significantly modified public documentation that should appear in the knowledge base? Proceed with a notice if the file is absent.

**api-perf-cost-auditor** (only when `perf_review_needed: true`): Apply the 5-gate protocol from `api-perf-gate.md` (see `framework/.claude/skills/prd/references/api-perf-gate.md`). Read referenced source files. Universal checks: unbounded reads, N+1 queries, fan-out writes, missing pagination, offset pagination, listener vs polling costs, payload size limits per `stack.deployment`, transaction hotspots. Stack-specific addenda apply per `stack.database` + `stack.framework` (see `framework/.claude/skills/prd/references/api-perf-gate.md`). **Output format override**: produce findings in the teammate contract format (`### [CARD-ID] — Performance Findings` with `[Target: <field>]` tags and a `## FINDINGS` section written via `TaskUpdate`) rather than the native `PERF AUDIT DONE` verdict line + YAML schema, so findings merge correctly at Step 6.7 (symmetric with the `security-reviewer` override below).

**security-reviewer** (only when `security_review_needed: true`): Apply the full security-reviewer methodology. Focus on: auth gaps, input validation, multi-tenant isolation, persistence-layer access rules alignment (Firestore rules / Supabase RLS / Mongo validator / DynamoDB IAM — per `stack.database`), sensitive data exposure, webhook validation, rate limiting, IDOR risks. **Output format override**: produce findings in the teammate contract format (`### [CARD-ID] — Security Findings` with `[Target: <field>]` tags and `## FINDINGS` section written via `TaskUpdate`) rather than the native `# Security Review Summary` format, so findings merge correctly at Step 6.7.

## Step 6.7 — Collect & Merge Findings

**Fan-in barrier (explicit completion gate — do not read findings before it clears).** The consolidation below MUST NOT begin until BOTH the teammate pool AND the Codex background job have reached a terminal state. Resolve each independently:

- **Teammates**: poll `TaskList` until every task is `completed`. Bound the wait with a window of `[CALIBRATION-NEEDED: per-agent budget; align with the 5-min Codex timeout once teammate-duration telemetry exists]` — as a working default, 10 minutes wall-clock from team launch. On expiry, classify any task still `in_progress`/`pending` as **TIMED_OUT**: proceed fail-open with findings from completed tasks, and record `audit_status: partial` plus the timed-out task IDs in the consolidated report so the omission is visible (never wait indefinitely; never silently drop the gap). Do NOT substitute a generic agent for a hung teammate (AGENTS.md anti-fallback rule).
- **Codex**: the background Bash job (Step 6.6d) is terminal once `$AUDIT_FILE` is non-empty OR its own `timeout: 300000` elapses. Do not block teammate consolidation on Codex beyond its 5-minute cap.

Once the barrier clears:
1. **Read teammate findings from the task store** (not `SendMessage`). Use `TaskGet` on each `completed` task to read the `## FINDINGS` section.
2. **Read Codex plan audit findings** from the path stored as `$AUDIT_FILE` in the session tracker (persisted by `tee` in Step 6.6d; pattern: `/tmp/codex-plan-audit-<CARD-ID-SLUG>-<SESSION-ID>.md`). If the file is absent, empty, or its content is `CODEX_NOT_FOUND`, note "Codex audit unavailable — fallback to plan-auditor" and invoke the `plan-auditor` subagent **with the dedup guard from Step 6.6d** (reuse this session's `codebase-architect` summary and already-merged `security-reviewer` findings instead of re-spawning).

Consolidate into a single report:

```
# Pre-Dev Audit Report — YYYY-MM-DD

## [CARD-ID-1] — Card Title

### Codex Plan Audit Findings (cross-model)
- [ ] Finding 1...

### Plan Audit Findings (card grounding — Claude-side)
- [ ] Finding 1...

### Doc Review Findings
- [ ] Finding 1...

### Performance Findings (if applicable)
- [ ] Finding 1...

### Security Findings (if applicable)
- [ ] Finding 1...

## [CARD-ID-2] — Card Title
...

## Audit Engine Summary
- Plan audit (cross-model adversarial): Codex | Fallback: Claude plan-auditor (FULL)
- Plan audit (card grounding, Claude-side): Claude plan-auditor (team-aware, no double-spawn) — suppressed when the Codex FULL fallback fires
- Doc review: Claude doc-reviewer
- Performance: Claude api-perf-cost-auditor (if triggered)
- Security: Claude security-reviewer (if triggered)
```

**CRITICAL — Persist report to file before proceeding.** Write to `/tmp/check-audit-report-<CARD-ID-SLUG>-<SESSION-ID>.md` (using `$CARD_ID_SLUG` and `$SESSION_ID` from the session tracker) using the Write tool. Store the path in the session tracker. This ensures findings survive context compaction.

Present the consolidated report to the user.

## Step 6.8 — Cleanup Team

Use `SendMessage` with `type: "shutdown_request"` to shut down all teammates, then `TeamDelete`.

## Step 6.9 — Apply Findings to Cards

**Goal**: Transform each card from "audited" to "implementation-ready" by editing YAML fields directly.

**Read findings from the persisted report file** (path stored in the session tracker as `$REPORT_FILE`; pattern: `/tmp/check-audit-report-<CARD-ID-SLUG>-<SESSION-ID>.md`).

### Field mapping rules

| Target tag | Card field | Action |
|---|---|---|
| `[Target: requirements]` | `requirements` | Append missing requirement or rewrite existing one |
| `[Target: acceptance_criteria]` | `acceptance_criteria` | Append new `"[ ] [AC-N] ..."` item or rewrite vague AC |
| `[Target: definition_of_done]` | `definition_of_done` | Append new `"[ ] ..."` item |
| `[Target: files_likely_touched]` | `files_likely_touched` | Append missing path (no duplicates) |
| `[Target: depends_on]` | `depends_on` | Append missing card ID |
| `[Target: areas]` | `areas` | Add missing area key/value |
| `[Target: git_strategy]` | `git_strategy` | Replace `TBD` with `feat/<CARD-ID>-<slug> from ${git.trunk_branch}` |
| `[Target: unknowns]` | `unknowns` | Append new `[U-N] UNKNOWN: ...` entry |
| `[Target: existing_patterns]` | `existing_patterns` | Append missing pattern reference or fix stale line_range/anchor_text |
| `[Target: validation_commands]` | `validation_commands` | Append missing verification command |
| `[Target: anti_patterns]` | `anti_patterns` | Append missing DO NOT constraint |
| `[Target: scope_boundaries]` | `scope_boundaries` | Add missing in_scope or out_of_scope item |
| `[Target: input_output_examples]` | `input_output_examples` | Append missing scenario or fix incorrect example |
| `[Target: error_handling]` | `error_handling` | Append missing failure mode or fix incorrect action |
| `[Target: reuse_analysis]` | `reuse_analysis` | Add missing reuse opportunity or correct file path |
| `[Target: notes]` | `notes` | Audit trail only (Step 6.9c) |

### Severity policy

- **HIGH**: MUST apply. Card cannot be safely implemented without these.
- **MEDIUM**: SHOULD apply. Skip only if human judgment needed (mark `[MANUAL]`).
- **LOW**: Do NOT edit structured fields. Audit trail note only.

### Audit trail in `notes`

After applying all edits, append to `notes`:

```yaml
## Applied by quality audit — YYYY-MM-DD
Applied N findings to structured fields (H high, M medium).
Manual review needed: [list [MANUAL] items, or "none"].
```

### Holistic-audit provenance stamp (since v4.3.0) — consumed by `/new` Step 3d

This audit (the 4-agent team + Codex adversarial pass of Step 6.6) IS the holistic cross-card review: Step 6.6d's Codex prompt already covers `files_likely_touched … conflicting across cards`, dependency shadows, implicit ordering, and shared-state mutation across the whole `${CARD_PATHS}` set. To let `/new` AVOID re-running its own pre-flight cross-card Codex check (Step 3d) when nothing has changed since this audit, stamp each audited card with a machine-readable provenance block.

**Capture three run-level values ONCE** (same for every card in this audit run):

```bash
HOLISTIC_AUDITED_AT="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
# Grounding baseline = the trunk commit the cards were authored against.
# The PRD docs worktree was forked from trunk, so the fork point is that baseline.
HOLISTIC_AUDITED_COMMIT="$(git merge-base HEAD "${git.trunk_branch}" 2>/dev/null || git rev-parse "${git.trunk_branch}" 2>/dev/null || echo "")"
# audited_set = sorted card IDs reviewed JOINTLY in this run (the Step 6.6d ${CARD_PATHS} set).
```

`audited_set` is the **same list for every card** — it records which cards were considered together, so `/new` can verify its batch is a subset of one coherent jointly-audited set (not a mix of cards audited in separate PRD runs).

Write under `metadata.holistic_audit` on each card (additive — never overwrite other `metadata` keys):

```yaml
metadata:
  holistic_audit:
    audited_at: "<HOLISTIC_AUDITED_AT>"
    audited_commit: "<HOLISTIC_AUDITED_COMMIT>"   # "" if git unavailable → /new treats as drift (runs Step 3d)
    audited_set: ["FEAT-XXXX-01", "FEAT-XXXX-02", ...]   # sorted; the joint cross-card scope
```

> **Fail-safe contract**: this block is an OPTIMIZATION hint, never a gate. If it is absent, partial, or has an empty `audited_commit`, `/new` Step 3d simply RUNS as before — there is no correctness risk, only a redundant Codex pass. Do NOT block the PRD if the stamp can't be written.

### Per-card workflow

For each card:
1. Read persisted report → collect all findings for this card ID.
2. Read current card YAML.
3. Apply HIGH findings first, then MEDIUM, then write audit trail.
4. Write the `metadata.holistic_audit` provenance block (see "Holistic-audit provenance stamp" above) using the run-level values captured once.
5. Write updated card YAML.
6. Re-read to verify edits landed correctly.

**Note**: No separate commit here — the validation-phase.md Step 7 handles committing all PRD artifacts together.

---

## Maintenance Note

[DESIGN-CHOICE: each audit component encodes a capability boundary; periodic stress-testing prevents dead scaffolding as model capabilities evolve]

Every component in this audit encodes an assumption about what the model can't do alone. Periodically (every 2-3 months `[CALIBRATION-NEEDED: cadence is a team convention, not validated against model-release frequency]` or on major model upgrade), stress-test each component:

- Remove one component at a time, measure audit quality delta.
- If delta < 5% `[CALIBRATION-NEEDED: removal threshold is a heuristic; validate against a labelled audit-quality benchmark before treating it as a hard cutoff]`, remove permanently.
- **Current load-bearing assumptions**: challenge pass, adjacent card retrieval, evidence quotes, adversarial evaluator tuning.
- **Assumptions to re-test**: agent team separation (could single-agent handle N cards?), relative severity ranking (does absolute assignment work with better models?).
