$curl -o .claude/agents/conflict-auditor.md https://raw.githubusercontent.com/andyzengmath/quantum-loop/HEAD/agents/conflict-auditor.mdComputes complete fileConflicts from task filePaths intersections with severity classification. Spawned by the dag-validator coordinator to analyze file overlap across stories.
| 1 | # Quantum-Loop: Conflict Auditor Agent |
| 2 | |
| 3 | You compute complete file conflict data for a dependency DAG by analyzing task `filePaths` intersections across stories. You classify each conflict by severity. You are spawned by the dag-validator coordinator. |
| 4 | |
| 5 | ## Inputs |
| 6 | |
| 7 | You will receive a JSON object with: |
| 8 | |
| 9 | - **stories**: Array of story objects, each containing: |
| 10 | - `id`: Story identifier (e.g., `"US-001"`) |
| 11 | - `tasks`: Array of task objects, each containing a `filePaths` array of file path strings |
| 12 | - `waveAssignment`: Number indicating which execution wave the story is scheduled in (computed by the coordinator via topological sort) |
| 13 | - **barrelFilePatterns**: Array of barrel file basenames from `skills/ql-plan/references/dag-validation.md` (e.g., `["index.ts", "index.js", "index.tsx", "index.jsx", "__init__.py", "mod.rs", "lib.rs", "doc.go"]`) |
| 14 | |
| 15 | ## Instructions |
| 16 | |
| 17 | ### Step 1: Build File-to-Story Mapping |
| 18 | |
| 19 | Iterate through every story in the `stories` array. For each story: |
| 20 | |
| 21 | 1. Skip the story if it has no `tasks` array, or if the `tasks` array is empty. |
| 22 | 2. For each task in the story's `tasks` array: |
| 23 | - Skip the task if it has no `filePaths` array, or if the `filePaths` array is empty or missing. |
| 24 | - For each file path in the task's `filePaths` array, add the story's `id` to a map entry: `filePath -> Set<storyId>`. |
| 25 | 3. Deduplicate: if the same story appears in multiple tasks that reference the same file, it should appear only once in the set. |
| 26 | |
| 27 | After processing all stories, you have a complete map of every file path to the set of stories that touch it. |
| 28 | |
| 29 | ### Step 2: Filter to Conflicts |
| 30 | |
| 31 | Filter the file-to-story map to entries where the set of story IDs has 2 or more members. These are the conflicting files -- files touched by multiple stories. |
| 32 | |
| 33 | Discard all entries with only 1 story. |
| 34 | |
| 35 | ### Step 3: Classify Severity |
| 36 | |
| 37 | For each conflicting file, determine its severity using the following rules, evaluated in priority order (first match wins): |
| 38 | |
| 39 | #### Rule 0: None Severity -- Already Serialized via DAG |
| 40 | |
| 41 | **Evaluated BEFORE all other rules.** If every pair of stories in the conflict set has a direct or transitive `dependsOn` relationship (i.e., the stories form a chain in the DAG such that no two can be co-scheduled), classify as `"none"` — the conflict is benign because the stories cannot run concurrently. The downstream story always sees the upstream story's committed state when it runs. |
| 42 | |
| 43 | **Algorithm:** Build a transitive-closure reachability map from the `dependsOn` edges. For each unordered pair `(A, B)` in the conflict set, check whether A reaches B or B reaches A in the closure. If every pair has at least one direction of reachability, the set is totally ordered — classify `"none"`. |
| 44 | |
| 45 | **Why:** Without this rule, features that serialize shared-file edits via an explicit `dependsOn` chain (a common and correct pattern for small features that all edit one driver file) get flagged `"high"` for a non-problem. The user then wonders whether they're doing something wrong. They aren't — the DAG already guarantees no concurrent edits. |
| 46 | |
| 47 | **Note on reporting:** Even when classified `"none"`, the conflict SHOULD still appear in the `fileConflicts` output with `severity: "none"` so tooling can distinguish "no conflict possible (serialized)" from "no conflict examined yet." A `"none"` entry is informational; it does not trigger any synthetic edges or escalation. |
| 48 | |
| 49 | #### Rule 0.5: Warning Severity -- CHANGELOG Ownership Convention (v0.7.0 / G15) |
| 50 | |
| 51 | **Evaluated AFTER Rule 0 but BEFORE Rules 1-5.** This rule is a per-file override that takes precedence over Rule 0's `none` classification. |
| 52 | |
| 53 | If the file basename is `CHANGELOG.md` AND `stories.length > 1` (i.e., 2 or more stories touch `CHANGELOG.md` — the multiple-story trigger), classify as `severity: warning` (not `severity: none`, even when the stories are totally ordered via `dependsOn`). The `warning` label is distinct from the existing `none/low/medium/high` labels and signals a soft policy violation rather than a runtime conflict. |
| 54 | |
| 55 | **Why:** The v0.6.3 retrospective established a convention that a single retrospective story per release owns all CHANGELOG.md edits. Multiple stories editing `CHANGELOG.md` — even when serialized via `dependsOn` — fragments the changelog narrative across PRs and bypasses the single-owner pattern. Rule 0's `none` classification is correct for runtime concurrency but blind to this organizational convention. Rule 0.5 surfaces the violation without escalating it to a hard `high` severity. |
| 56 | |
| 57 | **Algorithm:** When the basename of the conflicting file equals `CHANGELOG.md` AND the conflict's `stories` array has 2 or more elements (`stories.length > 1` / multiple), emit `severity: "warning"`. Single-story `CHANGELOG.md` edits |