Resolve the right adversarial-test tooling, performance-measurement tooling, and QA-{n} rules for a repo's bankai_scenario. Use before a release is cut, deployed, or published — when Phinks runs his adversarial pre-release QA, when Uvogin measures a performance budget, when authoring an E2E/adversarial test, or when either needs the scenario's pinned tooling before writing one.
Install
npx skillscat add zheref/hatsu/surfaces-antigravity-skills-bankai-quality Install via the SkillsCat registry.
Resolving Bankai quality tooling & rules
handbooks/quality-baseline.md (QA-{n}), read live from a checkout of the public canon repositoryzheref/bankai-handbooks at the tag Hatsu's nen/repos.json pins (maintained_tools → pinned,v0.6.0 at this port; the canon home since 2026-09-28, CON-13) — Hatsu ships no handbooks of its own —
is the single canonical source for adversarial-QA method, test tooling, and performance budgets. This
skill is a resolver: it resolves which tooling, budget thresholds, and rules apply to the repo in
front of you, and no more. The judgment layer — which QA-{n} class applies, a finding's severity, theQuality-Gate: verdict itself — is Phinks' and Uvogin's (claude/agents/phinks.md,claude/agents/uvogin.md), not this skill's; read those files for the full protocol this skill's
resolutions feed.
This gate is local, on-demand, and advisory. It runs on the human's own credentials before a tag cut
or a store submission, deploy or publish (QA-20). Its verdict informs the human's G3 (CON-6); it
never blocks (QA-21). Hatsu's roster carries no CI counterpart — docs/ROSTER.md lists no quality gate
among the ratified independents, and there is no scheduled sweep behind Phinks or Uvogin either.
1. Resolve the scenario — nen repo scenario, never a hand-grep
The old mechanic read bankai_scenario out of the target repo's own .github/workflows/bankai.yml by
eye. That is now a verb:
nen repo scenario --repo <path to a checkout carrying nen/repos.json — or schemas/repos.json under the fallback nen keeps until v0.4.0> --target <owner/name>--repo is a path, not a slug — the checkout whose nen/repos.json records the target underconsumers[] with a scenario: zheref/bankai-handbooks' own registry first (at v0.6.0 it records
no consumers — the estate's products are private and a public registry names none), then the
target's own checkout when it records itself; `bankai-handbooks` § 1
carries that order, the verified refusals and the open question it leaves the maintainer. --target is the
product repo's owner/name. --repo is required — omitted, exit 2 by name (nen v0.2.0, #73;
verified live at v0.3.0), never a silent cwd default. The verb reads the scenario live, off the
same CON-14-factual registry pr-state's --repo flag and warmup's stale-pin sweep already read —
never a value remembered from a prior session. Exits 1 with a distinct reason for each of: the
checkout carries no registry at all (the refusal names both nen/repos.json and the legacy path), the
target is not recorded anywhere in it, or it is recorded but carries no scenario field (verified live
at v0.3.0 against nen's bundled registry) — every one a finding about the registry, never a licence to
guess a scenario. Each is the trigger to ask and set up, not the end: a missing argument or
configuration item is asked for and set up inline (missing-argument, missing-configuration;
`WORKFLOW.md` § 4 Ask, set up, continue) — the scenario offered in
the picker and written to the nen/repos.json entry in the registry's own checkout, on its own
declaration PR at that repository's gate, then the resolution re-run.
A machinery repository recorded only under
maintained_toolsis the one class this verb cannot resolve, and that is expected, not a defect.
Only aconsumers[]entry carries ascenario.zheref/bankai-handbooks(a repository cannot be its own
consumer),zheref/hatsuandzheref/nensit undermaintained_toolsin both the public canon registry
and Hatsu's own, sonen repo scenario --repo <either registry> --target <any of the three>refuses at
exit1with the recorded-but-not-a-consumer reason ("only a consumers[] entry carries a 'scenario'
field") — verified live forzheref/hatsuat nen0.15.1, and exactly how the frozen<reference-repo>
refused for itself at the port (docs/ab/bankai-quality.md§ 2.1). That refusal is the expected answer
for a machinery repository, not a configuration defect to repair by writing a registry entry. Their
scenario isbankai-machinery— renamed at handbook set v0.6 from the frozen repository's own name
(handbooks/INDEX.md;MIGRATION.md§ 3 there), theBC-prefix kept — the scenarioINDEX.md
states for the CI plane, the CLI and the local plugin. Read that literal fromINDEX.md, say so, and
never route it through this verb as though a registry had answered. This is the one scenario resolution
this skill still does by direct read, and only because there is structurally no registry entry to
resolve it against.
2. Load the quality canon — always, live, never from memory
handbooks/quality-baseline.md(QA-{n}) — every scenario,bankai-machineryincluded (its § Scope).- The existing testing canon, so a run extends it instead of duplicating it (
QA-9):handbooks/uzf-core.mdUZF-18/UZF-19/UZF-20/UZF-26, plushandbooks/stacks/<scenario>/rules/
—07-testing.md(swiftui) or09-testing.md(compose, react). A missing unit test or a
coverage-floor breach is the architecture reviewer'sUZF-19finding, never aQA-{n}one. handbooks/stacks/<scenario>/architecture.md— only when a finding needs a stack rule cited
(SW-{n}/KT-{n}/RC-{n}/BC-{n}). Never load another scenario's folder.
All three are read from the zheref/bankai-handbooks checkout that `bankai-handbooks`
§ 0 locates or fetches ($canon), at the pinned tag, never at a branch
(git -C "$canon" describe --tags --exact-match → v0.6.0, verified live), and never written to from
this skill — a gap is a finding (§ Rules). The frozen <reference-repo>'s pre-migration handbooks/ copy
is not read at all.
3. Resolve the scenario's tooling — nen quality tooling
nen quality tooling --table <path.json> --scenario <name>--table is the target repository's own manifest — never a table shipped in nen, never one
remembered here. Exits 1 when the scenario has no entry: a finding about the manifest, never a licence to
pick a tool by improvisation.
RETIRED at nen
0.7:--table's and--input's second base. A relative--table(here) or--input(§ 5'snen quality method-check) resolves against--repo's root, not the
process's own directory (zheref/nen#100) — so the manifest this verdict is about is the one in
the repository--reponames, which is the only reading that was ever intended. An absolute path
is still used as-is. Throughv0.6.0the two bases diverged the moment a run happened from a
worktree or a wrapper script, and anENOENTwas the lucky outcome; a same-named manifest in both
trees was the unlucky one.
No repo in the reachable estate ships this JSON file today — verified at the port against the frozen<reference-repo> and re-verified against zheref/bankai-handbooks at v0.6.0: the tooling matrix is
markdown only (handbooks/quality-baseline.md § B Tooling matrix), and Hatsu carries no such file at all. This is genuine residue (docs/ab/bankai-quality.md § 3), not a defect in
the verb — the manifest is deliberately the caller's, per its own --help text. Until a target repo
authors one (conventionally at docs/Quality/tooling.json, keyed by scenario, in the shape nen quality tooling expects — see docs/ab/bankai-quality.md § 2.2 for a worked, clearly-labelled constructed
example transcribed from the live handbook), the values below are the reference content to seed it
with, transcribed from zheref/bankai-handbooks' handbooks/quality-baseline.md § B (current as of v0.6.0) — cite
the handbook when reporting a tooling choice, never invent a value, and prefer running the verb the moment
a manifest exists over reading this table by eye.
| Scenario | E2E / UI automation | Adversarial logic layer | Not used |
|---|---|---|---|
swiftui-tca-uzf-v2 |
XCUITest via xcodebuild test -destination … |
swift-testing; TestStore for race and effect ordering |
Appium, Selenium |
compose-uzf-v2 |
Compose UI Test on a Gradle Managed Device; Espresso/UIAutomator for cross-app and system dialogs | JUnit5 + Turbine | Appium, Selenium |
react-uzf-v1 (web) |
Playwright (page.route for degradation; --repeat-each=3 for QA-4) |
Vitest | Selenium, Cypress |
react-uzf-v1 (Expo) |
Maestro against a dev-client build | Jest (jest-expo) + RNTL |
Detox, Appium |
bankai-machinery |
bats over scripts/*.sh + yq assertions over .github/workflows/*.yml |
pytest | — |
Selenium and Appium are never a default — use one only where a target has no first-party driver (a
legacy browser matrix, a physical-device farm), and say so in the report (QA-7).
4. Performance thresholds — nen quality perf-compare
nen quality perf-compare --metric <name> --baseline <n> --measured <n>QA-13's own thresholds, computed rather than reconstructed by hand: a median regression strictly
greater than 10% is high, strictly greater than 25% is critical — both are regression-relative
to --baseline, and lower is better for every one of the fixed seven metrics, so there is no metric
here where a bigger measured number is good. Exits 1 when severity is high or critical; exits 0 onok, including an improvement (a negative regression). A zero baseline is refused outright rather
than divided by (verified live, docs/ab/bankai-quality.md § 2.3) — record a non-zero baseline or compare
the absolute values by hand.
Verified live, exactly at both boundaries (§ 2.3): 10.0% itself is ok (the rule is strictly
greater than 10%, not "at least"), and 25.0% itself is high, not critical — the same strict->
reading on both edges. Never round a boundary value up to the next severity by hand; relay the verb's own
computed severity.
Independently, these absolutes hold regardless of baseline — perf-compare does not check them, so
they remain this skill's own citation, never a computation to improvise:
- P1 ≤ 2000 ms median on the reference device.
- P7 ≤ 250 ms (Apple hang threshold) / jank frames ≤ 5% (Android) / INP ≤ 200 ms (web).
- P5 web initial transfer ≤ 300 KB compressed.
A number produced by a tool other than the scenario's pinned one (§ 3) is reported as a diagnostic,
never fed into perf-compare as a budget check (QA-12) — cross-tool numbers are not comparable, and
pinning the tool is the only thing that makes this percentage mean anything.
Measurement matrix (reference — read live, same residue as § 3's table)
| Scenario | Harness | Diagnosis |
|---|---|---|
swiftui-tca-uzf-v2 |
XCTMetric in an XCTest perf test — XCTApplicationLaunchMetric, XCTMemoryMetric, XCTClockMetric, XCTOSSignpostMetric over os_signpost intervals; App Thinning size report; URLSession metrics via a test-only URLProtocol recorder (P6 network) |
Instruments (Time Profiler, Allocations, Animation Hitches, Hangs) |
compose-uzf-v2 |
Jetpack Macrobenchmark — StartupTimingMetric, FrameTimingMetric, MemoryUsageMetric, TraceSectionMetric around the HTTP span + OkHttp EventListener, with a BaselineProfile; AAB analyzer for size |
Perfetto |
react-uzf-v1 (web) |
Lighthouse CI on a pinned mobile preset (Moto-G-class, 4× CPU, Slow 4G) + Web Vitals (LCP/INP/CLS/TBT) collected in the Playwright run; a CDP heap sample via Playwright (P4 memory); Playwright page.on('request'|'response') totals (P6 network); next build + @next/bundle-analyzer for bytes |
Lighthouse CI (@lhci/cli), pinned mobile preset |
react-uzf-v1 (Expo) |
Reuse the Apple/Android row for the native build under test (P1/P2); EAS build artifact size (P5); RN network inspector, as web (P6) | — |
bankai-machinery |
wall-clock of make test from a clean checkout + per-guard-script wall clock |
gh run view --json jobs durations |
5. Method-block validation — nen quality method-check
nen quality method-check --input <path.json>QA-15's five fields, validated rather than eyeballed: device/OS stated, Release config with no
debugger, sample size ≥ 5 with the first discarded, median and p90 reported, thermal and network
conditions stated. Exits 1 on any gap and names every missing field (verified live, both a passing and
a failing block, docs/ab/bankai-quality.md § 2.4) — there is no partial credit: a block missing even one
field is reported as a measurement that could not be completed, never as a number.
The verb's input is the exact MethodBlock shape:
{
"device": "<string>", "os": "<string>",
"releaseConfig": true, "debuggerAttached": false,
"sampleSize": 6, "firstDiscarded": true,
"median": 1180, "p90": 1340,
"thermalState": "nominal", "networkCondition": "Wi-Fi, unshaped"
}Report the verb's verdict rather than a hand-reading of the block — a block that looks complete but
fails validation (a stray empty string in networkCondition, a sampleSize of exactly 5 with the first
discarded miscounted) is exactly the class of gap this verb exists to catch instead of missing by eye.
5a. The candidate's own build, test, lint and coverage — nen shu, where the repository declares them
Since nen v0.3.0 the candidate's build, test suite, lint and coverage report are verbs that run what
the target repository declares in its nen/contract.json project block — never a command remembered
from a handbook. Phinks and Uvogin run these against the exact commit proposed for the tag; this resolver
names them so a report can cite which form produced a number:
nen shu tools --repo <path> # the host toolchain the declaration pins; exit 5 = a not-testable-here, tool named
nen shu build --repo <path> [--lane <lane>] # the declared build
nen shu test --repo <path> [--lane <lane>] # the declared suite
nen shu lint --repo <path> [--lane <lane>] # the declared lint and format check
nen shu coverage --repo <path> [--threshold <n>] # runs the declared coverage command and PARSES its report--dry-run on any of them prints the exact argv and spawns nothing. shu coverage reads the first path
under the verb's own artifacts whose format nen knows (Istanbul/Vitest JSON summary, xccov JSON,
Cobertura, JaCoCo, LCOV) into one shape — a total and a row per target — and --threshold only reportsmet, never moving the exit code (a coverage-floor breach stays UZF-19's finding for the architecture
reviewer, QA-9; this verb gives it a number, not a verdict). Exit 4 on any of these is the lane's own
seat — quote its reason, run the repository's documented command, say that you did; exit 3 is a host
the declaration excludes — not-testable-here, host named; a repository with no declaration answers
exit 2 naming the missing nen/contract.json (or its missing project block) — a fact read off these
verbs, not off nen shu detect, whose exit 1 means no marker nen recognises; the two coincide only
outside the seven stacks — and is tested by its own documented commands, the report saying which case it
was; the absent declaration is the trigger to offer the one nen scaffold init detects on its own PR at
that repository's gate (missing-configuration), never a change to the candidate under test (claude/agents/kurapika.md § The shu verbs). nen shu deploy --run is never this resolver's, nor
Phinks' nor Uvogin's: the plan without --run is a read of where the candidate would go; the run is G3.
6. Machinery scenario (bankai-machinery) — QA-16–QA-18
make lintandmake testgreen from a clean checkout where the machinery repository documents
them (the frozen<reference-repo>was bash and markdown, none of nen's seven stacks, and declared noprojectblock, so its ownMakefilewas the documented command, § 5a); a machinery repository that does declare its verbs runsnen shu lintandnen shu teston a treenen shu warmup --repo <path> --branch qa/<slug>(--dry-runfirst,
then bare) has just cut.- Drive changed
scripts/*.shwith the hostile-input corpus — empty, missing, malformed
JSON/YAML, non-UTF-8, oversized, a path with spaces, an extra field — and require fail-closed. - Assert every privileged or wake-bearing workflow
if:conjunct by conjunct withyqin a
bats case;tests/wake_label_iterate.batsis the shape. - Every guard needs at least one negative test; happy-path-only counts as untested.
- Its wall-clock budget flows through the same § 4 mechanics:
make test≤ 120 s, any single guard
≤ 5 s on the recorded machine, both regression-relative viaperf-compareagainst the prior release.
Rules this resolver still carries
- Cite findings by rule id, never invent one. A gap no
QA-{n}covers is a canon question — abankai:handbook-questionagainstzheref/bankai-handbooks, landing as a canon-lane PR the human merges
at G4 (CON-37), never authored by this skill as a side effect of a run, and never against the frozen<reference-repo>(no issue, comment, label, branch, push or PR there, ever). Record the gap and stop at
G5; do not treat it as silently resolved. The rewritten constitution has landed (CONSTITUTION.mdinzheref/bankai-handbooks,CON-51appended at v0.6); where a gap lands is the maintainer's call. - Extend, never duplicate the stack's existing test minimums (
QA-9) — a coverage-floor breach
routes to the architecture reviewer, never here. - One default tool per scenario per layer (
QA-7); a deviation states its reason in the report. - Measurement is tool-pinned per scenario (
QA-12) — a cross-tool number is adiagnostic, never a
budget check, and stays labelled as one. - The verdict marker is
Quality-Gate:, neverVerdict:(QA-21) — that marker is reserved for the
CI review gates (Sasuke, Tenma, Bisky) that still run in the consuming product repos' own CI today, and
a quality report must never collide with it. This resolver produces the tooling choice and the
threshold/method-block computations that feed that line; Phinks emits it, per his own file. - No LLM-improvised fallback for a Nen-owned operation, ever. If
nenis unavailable and the
bootstrap failed, the resolution does not happen — say so; never approximate a scenario, a tooling
choice, a severity, or a method-block verdict by hand in its place.