Release: Feature Audit

SkillDev tools

Use when a new PuPu feature finishes implementation and needs its consistency audit before its ticket is marked done — \"audit #123\", \"审计这个功能\", \"这个 feature 过一遍检查\" — or when release-close-sprint roll-call finds a new feature that was never audited. Also covers standalone i18n checks (\"漏翻了吗\", \"检查 i18n\"), which used to be the i18n-coverage skill.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Release: Feature Audit skill

What this skill tells your AI

The instructions your AI receives, as published by haoxiang-xu/pupu in .claude/skills/release-feature-audit/SKILL.md and read by ahel’s review.

Five consistency checks against one completed feature. Run before a direct Release sub-issue is marked Done; close-sprint treats an unaudited new feature as not-done-yet. Scope = the feature's diff and its blast radius, not the whole repo — except i18n, which is always a full scan (cheap, script-driven).

Findings are report-first: list violations with file:line, propose the fix, let the project maintainer/implementer decide. Only i18n missing-key auto-fill applies changes directly (rule inherited from the old i18n-coverage skill).

Retired workflow exclusions

Do not read, request, or validate implementation-owner confirmations, Quorum or court records, cases, proposals, rulings, handoffs, HS/RS/AT records, or any other retired authorization artifact. Their presence or absence must never affect PASS/FAIL. For cross-boundary work, use only the current Release issue or direct Plan plus the technical BC/SEQ/AC and immutable artifact evidence below.

Release membership

For a ticket audit, first resolve the ticket's direct Size=Release parent and verify its Project item. The Parent issue and Sub-issues progress Project fields are views; GitHub's issue relationship is authoritative. A ticket without a Release parent may receive a standalone audit report, but it does not change release state. Every ticket labelled new feature needs a fresh audit PASS bound to its delivered candidate digest, or an explicit maintainer waiver, before its parent Release can close.

Plumbing: before reading or changing a Project field, follow .claude/skills/release-open-sprint/board-api.md: run the project-scope preflight, discover the current fields, and verify the child's Project item.

Check 1 — i18n coverage (full scan, scripts in this directory)

en.json is the source of truth; runtime silently falls back to English, so gaps are invisible without this.

  1. node .claude/skills/release-feature-audit/audit.mjs --root <repo-root> > /tmp/i18n-report.json (add --strict only on request — noisy). Report contains per-locale missing/orphan/placeholderMismatch + code.missingInEn/deadKeys/dynamicCount.
  2. Auto-fill missing (the ONLY auto-apply): translate each missing key's en value (preserve {placeholder} tokens verbatim), write flat JSON map, then node .claude/skills/release-feature-audit/apply.mjs --root <repo-root> --locale <name> --translations /tmp/<name>.json. Never overwrites existing values.
  3. Report for confirmation: orphan/dead-key deletions, placeholder-mismatch edits, missingInEn bugs (raw key shows in UI), and the dynamicCount blind spot. Deletions/edits need explicit OK. Never commit.

Check 2 — UI consistency (new UI only)

  • Reuse: every new interactive element must come from src/BUILTIN_COMPONENTs/ when a primitive exists (buttons ALWAYS builtin default form — no bare <button>, no transparent text-link buttons; anchored popovers use the Tooltip engine, never hand-rolled positioning). Flag hand-rolled widgets that duplicate a primitive; the original behavior source is the mini_ui repo if fidelity is in question.
  • Theme: every color must survive a whole-theme switch — isDark from ConfigContext with BOTH branches present (a color defined for one theme only is a violation); shell/background layers use var(--pupu-background|--pupu-sidebar|--pupu-surface), never bare hex (shell_background_guard enforces); no colors invented outside the component's palette pattern. Grep the diff for hex literals and single-branch ternaries.
  • Layering: anything portalled to document.body or position: fixed takes its zIndex from Z in BUILTIN_COMPONENTs/layer/z_layers.js, never a literal (z_layers_guard enforces). Do NOT re-run that scan here — it runs in CI and is stricter than a grep. Audit the two things it structurally cannot see: (a) literals below 1000, which it deliberately ignores because CONTENT_RAISED: 10 and SCROLL_OVERLAY: 500 are legitimately small, and (b) a semantically wrong layerZ.MODAL on a menu passes the guard and is still wrong. Read the chosen constant against the rationale in that file's header, and treat a new overlay that computes its own zIndex dynamically as needing an explicit justification.

Check 3 — model features × agent builder (model-related features only)

A feature touching models/providers/effort/model-selection must be checked against the agent builder surfaces (src/COMPONENTs/agents/ — recipe graph, node detail panel, character model bindings, subagent picker):

  • Does the new capability appear where builder picks models, or is it correctly absent by design?
  • Does an existing recipe/character referencing an old model value still load and run (no schema break)?
  • Run impact upstream on the shared symbols the feature modified; if agent-builder files are in the blast radius, walk each hit. State the verdict explicitly: compatible / conflict found / N/A (not model-related).

Check 4 — ironclad-rules static scan (feature diff only)

Grep the feature's changed files for the rules that have silent failure modes:

<base> = the feature's branch point (git merge-base HEAD dev), or — in a dirty main tree with unrelated changes — the explicit file list from the ticket/PR. Never audit unrelated dirty files.

git diff --name-only <base>  # scope
grep -n "ipcRenderer" <changed src/ files>              # renderer must use window.*API bridges
grep -n "localStorage\." <changed component files>       # only SERVICEs helpers may write
grep -n "react-router-dom\|createContext" <changed>      # mini_router only; no new providers without ConfigContext check

Plus: if electron/tests/** changed, verify the .js/.cjs twin changed too (the repo's only silently-failing test form — a missing twin means the test never runs in one harness).

Check 5 — hollow-shell check (any feature whose value crosses the renderer boundary — consuming OR producing: panels, selectors sent with requests, persisted settings)

A rendered panel is not evidence the pipeline works — PuPu has shipped a panel whose producer emitted zero records ever, with every try/except silent. So: drive the feature once in the real running app via the test-api skill (real LLM, openai:gpt-4.1; delete probe sessions) and verify real data reaches the UI end-to-end — not mocks, not "the component renders". If the feature has a producer side (extension/event/log), grep persisted output for at least one real record produced by your probe. UI renders + producer silent = FAIL, and it's the most important failure this audit can catch.

If the feature changed unchain Python, restart the sidecar before this probe or the test is evidence for old code. If a cross-boundary contract gate applies, verify the required BC, SEQ, AC, and exact delivered-candidate artifact evidence before PASS: the PuPu candidate digest, one reused Unchain wheel SHA-256, and the imported runtime manifest digest.

Feature-audit boundary

This audit proves that the completed feature works in a real app path and that the recorded candidate uses the intended immutable artifacts. It does not require public or internal-user rollout, shadow/canary cohorts, rollout duration, production traffic, or post-rollout reliability metrics. Those belong to Release certification and must not block a feature ticket's audit PASS. A diagnostic, local, unsigned, or not-yet-notarized candidate may be valid audit evidence when the exact candidate digest, wheel digest, runtime manifest digest, package smoke, and applicable real-app behavior are verified. Source-tree dirtiness is provenance, not an automatic failure.

Only audit shadow/canary behavior when the ticket's feature is the rollout mechanism itself. Do not reinterpret wording such as "available before release certification" as a prerequisite for completing the underlying feature ticket.

Output

Give one verdict block per check: PASS, FAIL with violations, or N/A with a reason. For a ticket audit, post a structured comment on the child issue:

<!-- release-feature-audit:v2 -->
## Release feature audit — YYYY-MM-DD
Release: #PARENT
Overall: PASS | FAIL
1. i18n: PASS | FAIL | N/A — reason
2. UI: PASS | FAIL | N/A — reason
3. model × agent builder: PASS | FAIL | N/A — reason
4. static rules: PASS | FAIL | N/A — reason
5. end-to-end: PASS | FAIL | N/A — reason
Candidate digest: sha256:<64 hex>
Unchain wheel SHA-256: sha256:<64 hex> | N/A
Runtime manifest digest: sha256:<64 hex> | N/A
Evidence: links, commands, and sidecar/BC/SEQ/artifact verdict where applicable

Overall PASS requires every applicable check to pass. N/A needs its reason. On PASS, set the child Project Status to In Review; the audit never closes the issue or marks it Done. Normal acceptance may close a PASS child and set Done. On FAIL, keep or return the child to In Progress. A PASS is fresh only if its Candidate digest equals the delivered candidate; any candidate-input change changes that digest and requires a new audit. Git ref, source revision, and working-tree cleanliness may be recorded as provenance but never determine runtime compatibility or audit admission.

An audit waiver must be explicitly approved by the project maintainer and recorded on both the child and Release parent with the marker

approver, and date. No commits. Auto-filled i18n translations remain listed for review.

Common mistakes

  • Auditing the whole repo for checks 2–5 — scope is the feature's diff; repo-wide sweeps drown the signal.
  • Consulting retired owner/court/case records or treating them as an audit gate.
  • Marking check 5 PASS because the UI renders with mock/dev data — only a real-app probe with real output counts.
  • Requiring shadow/canary traffic, real users, rollout duration, signing/notarization, or production metrics for an ordinary feature audit; those are Release-certification gates unless rollout is the feature.
  • Treating check 3 as N/A because "it's just a provider preset" — presets surface in builder pickers; verify, then say N/A.
  • Auto-applying anything beyond i18n missing-key fills.
  • Running i18n scripts from the old .claude/skills/cto/... or .claude/skills/i18n-coverage/... paths — they live HERE now.
  • Treating any audit comment as a PASS, or marking a child Done from this skill.
  • Writing audit state to a sprint document instead of the child and Release issues.

Signals

GitHub stars
36
Forks
6
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
release-feature-audit
Source
github.com/haoxiang-xu/pupu