Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 66 additions & 5 deletions .claude/skills/validate-architecture/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,22 @@ architecture.md:L<N> — Process Engine marked "OUT OF SCOPE" but routers/proces
Suggested edit: either remove the OUT OF SCOPE tag (if the module is in fact live), or remove the routers (if it is truly dormant).
```

### Step 2c: Filter Stale Citations

Before generating the report, validate every `file:line` citation produced in Steps 2a and 2b against the current working tree. The skill is sometimes run on a snapshot taken just before a large deletion PR lands; without this filter, the report (and any auto-created issue) cites paths that no longer exist.

For each cited path (always quote `"$path"` — citations may contain spaces or shell metacharacters):

```bash
git ls-files --error-unmatch "$path" >/dev/null 2>&1 && echo exists || echo dropped
```

- **If `dropped`**: remove the citation from the violation. Do not retain "ghost" line numbers from a previous tree.
- **After filtering**, if an invariant's violation list is empty, downgrade its status from `FAIL` to `PASS (after stale-citation filter)` and record the dropped citation count in the report so the reader can see what was removed.
- **If the only violations cited paths that no longer exist**, do not propagate this invariant to Step 4's issue-creation trigger.

This step exists because of issue #479: a 2026-04-24 run cited 11 paths that were deleted by commit e901108 (#430) the same day. None of those P1-critical citations were real on `main`, but the unfiltered report produced a `priority-p1` issue against `main`.

### Step 3: Generate Report

Output two sections:
Expand Down Expand Up @@ -162,9 +178,9 @@ Output two sections:
- architecture.md:L<N> — "<section>" marked out-of-scope but <evidence of activity>. Suggested edit: <resolution>.
```

### Step 4: Create Issue if Critical
### Step 4: Create or Update Issue if Critical

Create a GitHub issue when any of these fire:
Create or update a GitHub issue when any of these fire (after the Step 2c stale-citation filter has run):

**P0-P1 invariants** (critical — break runtime or security):
- #1 Three-Layer Backend (layer violations cause maintenance debt)
Expand All @@ -176,7 +192,41 @@ Create a GitHub issue when any of these fire:
- D1 count mismatches with >25% divergence
- D2 any scope contradiction (dormant-but-live modules)

If any fire, create issue:
**Dedupe guard — required before any `gh issue create`:**

Compute a fingerprint over the post-filter findings, then check for an existing open issue with the same fingerprint. The fingerprint is wrapped in an HTML comment marker (`<!-- validate-architecture::fingerprint=... -->`) inside the issue body so the dedupe key is self-evidently programmatic and won't collide with prose mentions of "fingerprint" in unrelated issues.

```bash
COMMIT_SHA=$(git rev-parse --short HEAD)
# Sorted, comma-separated list of invariant numbers that fired post-filter,
# e.g. "1,3" or "8,14"
FINGERPRINT=$(printf '%s\n' "${FIRED_INVARIANTS[@]}" | sort -n | paste -sd, -)
FINGERPRINT_MARKER="validate-architecture::fingerprint=$FINGERPRINT"

# Find any open automated arch-validation issue with the exact marker
EXISTING=$(gh issue list --repo abilityai/trinity \
--label "automated,priority-p1" --state open \
--search "in:body \"$FINGERPRINT_MARKER\"" \
--json number,title --jq '.[0].number')
```

**Branch on `$EXISTING`. The two paths are mutually exclusive — execute exactly one.**

**Path A — `$EXISTING` is non-empty (matching open issue found): COMMENT, then STOP.**

```bash
gh issue comment "$EXISTING" --repo abilityai/trinity --body "Re-run on \`$COMMIT_SHA\` ($(date -u +%Y-%m-%d)): same invariants still failing (\`$FINGERPRINT\`). See attached fresh report.

[fresh report body]

<!-- $FINGERPRINT_MARKER -->"
```

After commenting, **DO NOT** execute Path B. The skill workflow ends here for this run.

**Path B — `$EXISTING` is empty (no matching open issue): CREATE a new issue.**

Only run this block when Path A did not run.

```bash
gh issue create \
Expand All @@ -185,10 +235,11 @@ gh issue create \
--body "## Automated Architecture Validation Report

**Date**: $(date -u +%Y-%m-%d)
**Commit**: $COMMIT_SHA

### Critical Invariant Violations (P0-P1)

[List each P0-P1 violation with invariant number, file:line, description]
[List each P0-P1 violation with invariant number, file:line, description — Step 2c-filtered, no stale paths]

### Doc Drift — Suggested architecture.md Edits

Expand All @@ -198,12 +249,22 @@ gh issue create \

1. [Prioritized fix for each finding]

### Dedupe Notes

- This issue is keyed by \`$FINGERPRINT_MARKER\` (sorted invariant numbers).
- Future skill runs with the same fingerprint will comment on this issue rather than open a new one.
- Close this issue once the cited invariants pass on \`main\`.

<!-- $FINGERPRINT_MARKER -->

---
*Generated by scheduled /validate-architecture run*" \
--label "type-bug,priority-p1,automated"
```

If nothing critical fires, skip issue creation — report only logged to execution history.
**Concurrency caveat**: this dedupe is best-effort, not atomic. Two runners executing simultaneously could both see `$EXISTING` empty and both create issues. GitHub provides no atomic compare-and-create primitive. The next run with the same fingerprint will detect both open issues and comment on the first; the duplicate can be closed manually with `Closes #<duplicate>`. In practice this is rare because the skill is scheduler-driven (single runner).

If nothing critical fires after Step 2c's filter, skip issue creation — report only logged to execution history. **Do not create an issue solely on pre-filter results.**

## Outputs

Expand Down
Loading