src/autoskillit/skills_extended/audit-review-decisions/SKILL.md
Audit merged PR review threads for agreed-but-deferred suggestions (design decisions, future work, out-of-scope items) that were never implemented. Mines REVIEW-FLAG markers from resolve-review and legacy keyword signals. Produces a structured markdown report with VALID/RESOLVED/STALE classifications and annotates processed threads with [AUDIT] markers to prevent re-identification on future runs.
npx skillsauth add talont-org/autoskillit audit-review-decisionsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Mine merged PR review threads for agreed-but-deferred suggestions that were never implemented. Identify review debt before it compounds.
$1 — Time period (e.g. 14d, 30d, 7d). Default: 14d.$2 — Output path. Default:
${AUTOSKILLIT_TEMP}/audit-review-decisions/review_decisions_audit_$(date +%Y-%m-%d_%H%M%S).mdNEVER:
${AUTOSKILLIT_TEMP}/audit-review-decisions/[AUDIT] markers — check for existing marker before postingrun_in_background: true is prohibited)gh pr list without --limit to avoid pagination truncation\| in Grep patterns — use | for alternation (ERE, not BRE)ALWAYS:
rateLimit { cost remaining resetAt } in every GraphQL query[AUDIT] commentgit remote get-url origin — never hardcode/autoskillit: prefix when invoking any other skillParse $1 for time period. Default 14d. Compute PERIOD_DAYS.
Resolve OWNER and REPO from git remote get-url origin.
Query the most recent [AUDIT] sentinel comment across recently merged PRs:
gh api graphql -f query='
query($owner:String!, $name:String!) {
rateLimit { cost remaining resetAt }
repository(owner:$owner, name:$name) {
pullRequests(first:500, states:MERGED, orderBy:{field:UPDATED_AT,direction:DESC}) {
nodes { number
reviewThreads(first:50) {
nodes { comments(first:10) { nodes { body createdAt } } }
}
}
}
}
}' -f owner="${OWNER}" -f name="${REPO}"
Extract the most recent createdAt from any comment whose body starts with
[AUDIT]. Store as LAST_AUDIT_TS (empty string if none — first run).
Compute SCAN_SINCE:
LAST_AUDIT_TS is set: max(LAST_AUDIT_TS, date -d "now - PERIOD_DAYS days")date -d "now - PERIOD_DAYS days" --iso-8601=secondsLog: Scan window: ${SCAN_SINCE} to now (${PERIOD_DAYS}d configured, last audit: ${LAST_AUDIT_TS:-none})
List merged PRs in the scan window:
SCAN_DATE=$(echo "${SCAN_SINCE}" | cut -c1-10)
PR_NUMS=$(gh pr list --state merged \
--search "merged:>=${SCAN_DATE}" \
--json number --limit 500 | jq -r '.[].number')
Create temp directory:
mkdir -p "${AUTOSKILLIT_TEMP}/audit-review-decisions/raw"
Batch fetch in groups of 20 using GraphQL aliases. For each batch, build a query
with aliased pr${i}: pullRequest(number: ${NUM}) nodes. Each node fetches:
number title mergedAt
reviews(first: 100) {
nodes { author { login } body state submittedAt }
}
reviewThreads(first: 100) {
pageInfo { hasNextPage endCursor }
nodes {
isResolved
comments(first: 100) {
nodes { databaseId author { login } body path line createdAt }
}
}
}
Include rateLimit { cost remaining resetAt } at query root.
After the initial fetch, for each PR where reviewThreads.pageInfo.hasNextPage is
true, issue additional aliased queries with reviewThreads(first:100, after:$endCursor)
until hasNextPage is false. Merge the nodes arrays across pages before filtering.
For each PR in the batch response:
comments list contains any comment with body
starting with [AUDIT] (already watermarked — skip entirely).${AUTOSKILLIT_TEMP}/audit-review-decisions/raw/pr_${number}.jsonList all JSON files in raw/. Split into batches of ~5 files per agent.
Launch parallel Haiku subagents (one per batch, model: "haiku"). Each agent:
<!-- REVIEW-FLAG: tag present"Valid observation — flagged for design decision",
"out of scope for this fix cycle", "requires a dedicated cleanup commit",
"left open for human review", "future improvement", "beyond this PR's scope",
"requires team consensus"isResolved: false AND author acknowledged validity in a replystate: COMMENTED with no corresponding thread (needs_human indicator)PR: {number}
thread_index: {N}
comment_id: {databaseId of first comment in thread}
path: {file path or empty}
line: {line number or empty}
signal: REVIEW-FLAG|KEYWORD|UNRESOLVED|NEEDS_HUMAN
severity: {from REVIEW-FLAG tag, or "unknown"}
dimension: {from REVIEW-FLAG tag, or "unknown"}
quote: {first 200 chars of flagged comment body}
Collect and parse candidate text from all agent responses.
Group candidates into batches of ~10. Launch parallel Sonnet subagents
(model: "sonnet") per batch.
Each Sonnet agent receives its candidate batch and, for each candidate:
path is set: reads the file and surrounding context.quote (judgment-based
pattern, not a literal string match).VALID — issue still present, impactful, ticket-worthyRESOLVED — code changed; concern no longer appliesSTALE — code deleted/refactored; finding irrelevantPR: {number}
comment_id: {databaseId}
classification: VALID|RESOLVED|STALE
path: {file:line or empty}
severity: {critical|warning|info|unknown}
dimension: {arch|bugs|defense|tests|cohesion|slop|unknown}
priority: HIGH|MEDIUM|LOW
impact: {one sentence}
suggested_title: {short GitHub issue title}
reviewer_quote: {verbatim first 300 chars}
HIGH = severity=critical OR dimension in (bugs, arch);
MEDIUM = severity=warning; LOW = severity=info or unknown.Collect and parse validated findings from all agent responses.
$2 if provided.${AUTOSKILLIT_TEMP}/audit-review-decisions/review_decisions_audit_$(date +%Y-%m-%d_%H%M%S).mdmkdir -p "$(dirname "${OUTPUT_PATH}")"${OUTPUT_PATH}. Structure:Generated: {ISO timestamp} Scan window: {SCAN_SINCE} to {now} PRs scanned: {N} | Threads examined: {M} | Threads skipped (already audited): {K}
| Classification | Count | |---|---| | VALID (ticket-worthy) | {N} | | RESOLVED (already fixed) | {N} | | STALE (no longer applicable) | {N} |
For each HIGH VALID finding, write a section:
### {suggested_title}
**PR:** #{number} | **File:** {path}:{line} | **Severity:** {severity} | **Dimension:** {dimension}
> {reviewer_quote}
**Current relevance:** VALID — {impact}
**Suggested issue title:** {suggested_title}
**Affected files:** {path}
{Same structure}
{Same structure}
{List: PR, file, one-line description of what was fixed}
{List: PR, file, one-line description of why no longer applicable}
{Findings from PRs that were open (not merged) at scan time — may still be addressed. Same per-finding structure but labeled as pending.}
Most common deferral phrases (by frequency): {Table: phrase | count | % of all candidates}
Dimensions with highest VALID rate: {Table: dimension | valid | resolved | stale | valid_rate}
Systemic escape hatches detected: {Narrative: which phrases act as systematic blockers to tracking, with counts}
Recommendations: {2–4 concrete process recommendations based on the pattern data}
audit-review-decisions complete
Output: {OUTPUT_PATH}
VALID: {N} | RESOLVED: {N} | STALE: {N}
Top finding: {first HIGH priority suggested_title, or "none"}
For every finding processed in Steps 2–3 (all classifications — VALID, RESOLVED, STALE):
Re-check for existing audit marker (live): fetch the thread's current comments
directly from the GitHub API — do not use the Step 1 JSON cache, which already
filtered out [AUDIT]-marked threads and cannot detect markers posted after Step 1:
gh api "repos/${OWNER}/${REPO}/pulls/${PR_NUMBER}/comments" \
--jq "[.[] | select(.id == ${COMMENT_ID} or .in_reply_to_id == ${COMMENT_ID}) | .body | startswith(\"[AUDIT]\")] | any"
If the result is true: skip this thread (idempotent — no duplicate post).
Determine marker body based on classification and ticket status:
| Classification | Ticket created? | Marker body |
|---|---|---|
| VALID | Yes | [AUDIT] — tracked in #{issue_number} |
| VALID | No | [AUDIT] — acknowledged, no action taken |
| RESOLVED | — | [AUDIT] — verified resolved in current codebase |
| STALE | — | [AUDIT] — no longer applicable |
Post reply comment:
gh api "repos/${OWNER}/${REPO}/pulls/${PR_NUMBER}/comments/${COMMENT_ID}/replies" \
--method POST \
--field body="${MARKER_BODY}"
sleep 1
COMMENT_ID is the databaseId of the first comment in the thread (from Step 1 JSON).
Thread reply constraint: These calls cannot be batched via the reviews API — each requires an individual POST. The 1s delay between calls is mandatory per GitHub API discipline.
Log progress per finding: [AUDIT] Posted marker on PR #{number} thread {comment_id}: {marker_body}
development
Generate YAML recipes for .autoskillit/recipes/. Use when user says "make script skill", "generate script", "script a workflow", "write a script", "create a script", "new recipe", "write a pipeline", or when loaded by other skills for script formatting.
data-ai
Create Uncertainty Representation visualization planning spec showing error bar definitions, distribution-aware alternatives, and multi-seed variance protocols. Statistical lens answering "How is uncertainty honestly represented?"
data-ai
Create Temporal Dynamics visualization planning spec showing axis scaling (linear vs log), smoothing disclosure, epoch/step alignment, run aggregation (mean + variance bands), early-stopping markers, and wall-clock vs step-count x-axis. Temporal lens answering "Are training dynamics shown clearly and honestly?"
data-ai
Create Narrative Story Arc visualization planning spec showing visual consistency across the report (same color = same model everywhere), logical figure progression, redundant figure detection, and narrative dependency between figures. Narrative lens answering "Do the figures tell a coherent story across the report?"