Observed since 20 Oct, 21:35 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
9AI QA & Automation Skills Framework for AI Agents
9ai is an advanced, spec-driven development framework designed to empower AI Agents (such as Claude Code, Codex, Antigravity, and Cursor) with Enterprise-grade QA and Automation capabilities. It injects rigorous Fintech testing standards directly into your AI workflows.
Install the CLI globally, then run init once inside each project you want to use it in:
npm install -g 9ai-skills
9ai init
Both steps are required. npm install -g only puts the 9ai CLI on your PATH — it writes nothing into your project. The AI agents look for CLAUDE.md, .claude/ and .agents/ at your project root, not inside node_modules, so init is what actually wires them up. After it runs you get:
.claude/commands/9ai.*.md 13 slash commands (autocomplete in the / menu)
.claude/skills/<kebab-name>/SKILL.md 13 model-invoked skills
.cursor/rules/9ai-*.mdc 13 Cursor rules (agent-requested, or @9ai-commit)
.agents/{AGENTS.md, skills.json} Antigravity / Codex
CLAUDE.md fallback mapping table
9AI_SKILL/ the skills themselves
Run 9ai init again in any other repo — it is per-project.
Everything a skill says to you — confirmations, warnings, findings, the closing Summary — follows a language you pick once. Everything it writes for a machine — commit messages, code, file paths, branch names, git commands, JSON keys — is always English. A translated command is a command that does not run.
On the first run, you get asked once:
🌐 Report language / Langue des rapports
First run — pick the language for reports, confirmations and summaries.
Première exécution — choisissez la langue des rapports et confirmations.
[1] Français (langue de cette conversation)
[2] English (langue du système)
[3] Autre — tapez le nom de la langue
Commit messages, code and file paths stay English either way.
Les messages de commit, le code et les chemins restent en anglais.
Saved to ~/.9ai/config.json — asked once, never again.
The menu is built for you, not hard-coded. Candidates, in order: the language of the current conversation, the OS locale language if it differs, English if not already listed, and always an "other — type it" escape. Each option says why it is being offered, so you can tell an informed suggestion from a guess.
That matters for the common case where the two disagree: an English machine used by someone who works in French gets offered French first, English second — not a fixed pair that includes neither.
The answer goes to ~/.9ai/config.json and no skill asks again — pick your language in /9ai.git-commit and /9ai.triage already knows.
| Want to | Do |
|---|---|
| Change it for good | Edit ~/.9ai/config.json |
| Change it for one run | Pass report_language: fr (any language) |
| Override it in one repo | Add .9ai/config.json to that repo |
The locale shapes the menu; it never decides the outcome. An English machine tells you what language the operating system is in — not which language the person wants their reports in. Plenty of engineers run an English OS, an English IDE and an English terminal while working and reviewing in another language entirely, so deciding from locale gets exactly that person wrong, and silently. Reading it to build a better question is right; reading it to skip the question is not.
This package ships markdown instructions plus one small CLI that copies them. No postinstall, no runtime dependencies, no network calls, no exec. Do not take that on trust — check it:
npm run verify:published
Twelve checks, each printing file and line as evidence. Full threat model and the behavioural guarantees the skills make: SECURITY.md.
Nothing below is self-reported. Every line is a command you can run yourself, and the reason it is worth running is given rather than implied.
| Check | Tool | Result | Why it matters |
|---|---|---|---|
| Dependency CVEs | npm audit | 0 vulnerabilities | The usual way a clean package hurts its users |
| Dependency count | npm ls | 0 runtime dependencies | Removes the supply-chain surface instead of monitoring it |
| Secrets | gitleaks | 0 leaks | A committed credential stays valid long after it is deleted |
| Vulnerability DB | osv-scanner | nothing to scan — no manifests | The expected result at zero dependencies, not a pass by omission |
| Static analysis | semgrep, 77 rules | 0 findings | Catches eval, concatenated shell and dynamic require |
| Package contract | verify-package.js | 12/12 | No install script, no network, no stray files, no leaked identifiers or document links |
Run all six at once from a clone:
node scripts/security-audit.js # add --json for CI
A skipped check is reported as skipped, never as a pass. If a scanner is not installed the report says so and prints the install command, because a report that silently counts an absent tool as a clean result is worse than no report.
The registry's free Semgrep rulesets flag none of eval, concatenated shell, or dynamic
require — checked by running four of them against a file containing all three. So those
rules live in .semgrep.yml instead of being assumed.
When the skills are updated on npm, refresh the CLI, then re-run update in each project:
npm update -g 9ai-skills
9ai update
Safety Guarantee: update only replaces the skills this package ships. It will:
CLAUDE.md, .agents/AGENTS.md and skills.json — your custom instructions are never overwritten.9AI_SKILL/skills/, and print 🛡️ Preserved N custom skill(s): ... so you can see it happened..claude/commands/ and .claude/skills/ pointers, so new skills show up in your / menu automatically.Once initialized, your AI assistant will instantly understand the following "Slash Commands". You do not need to write long prompts—just use these shortcuts!
Test design
| Command | Target Skill | Description |
|---|---|---|
/9ai.coverage | generate-fintech-test-coverage | Analyze requirements and generate a strict Fintech Test Coverage Matrix (15 dimensions). |
/9ai.review | review-fintech-test-design | Audit and review existing Test Cases or Coverage Matrices against Fintech standards. |
/9ai.checklist | generate-api-test-checklist | Extract requirements from API specs and generate an executable API Test Checklist. |
Automation
| Command | Target Skill | Description |
|---|---|---|
/9ai.spec | generate-playwright-spec | Turn checklist test cases into Playwright specs that respect the repo's pom → flow → verify → spec layering. |
/9ai.triage | triage-test-failures | Classify a failed run into product bug / locator drift / timing / data / env, with evidence. |
/9ai.autoreview | review-automation-code | Find hard waits, brittle locators, tests with no assertions, shared state, leaked credentials. |
/9ai.tutorial | generate-user-guide | Turn a skill or workflow into a step-by-step Word guide with document control and change history. |
/9ai.repo-security | audit-repo-security | Audit an npm + git project across secrets, dependencies, supply chain, own code, what ships, provenance and licence. |
/9ai.context | generate-project-context | Build the CLAUDE.md and docs/claude/ files an agent reads, keeping the always-loaded part inside a size budget. |
/9ai.uidrift | apply-ui-drift | Turn a npm run ui:drift log into POM/verify fixes — baseline is updated last, never first. |
/9ai.skill-format | 9ai.skill-format | Score a SKILL.md on the 12-dimension house rubric; author or repair skills to match. |
Git
| Command | Target Skill | Description |
|---|---|---|
/9ai.git-commit | generate-git-commits | Report the target repo + git identity + security findings, auto-group uncommitted files, commit & push. |
/9ai.git-commit-webhook | generate-git-commits-webhook | Everything /9ai.git-commit does, then ask for a webhook URL and notify it — skippable, and it reports the exact HTTP result. |
/9ai.git-conflict | resolve-git-conflicts | Walk a conflict hunk by hunk and confirm which side to keep. Called by /9ai.git-commit only when a conflict exists. |
/9ai.git-release | record-release-notes | Pull a chosen branch, verify the build, and record pushed/incoming commits into a Release Note file. |
🔥 Quick Example: Open Claude Code or Antigravity and simply type:
/9ai.git-commit to src/ and modules/The AI will automatically scan your files, categorize the changes, commit them with English descriptions, push to the server, and return the Merge Request link!
When you run 9ai init, it installs the following expert prompt frameworks (Skills) into your project:
generate-fintech-test-coverage)Forces the AI to analyze features against 15 rigorous Fintech dimensions (Concurrency, Money Integrity, Rollback, Idempotency, etc.) instead of writing naive happy-path test cases.
review-fintech-test-design)Turns the AI into a strict QA Lead. It audits your Test Cases, Coverage Matrices, or Defect Leakage reports to find missing risk scenarios (e.g., Race Conditions, Timeouts).
generate-api-test-checklist)Designed to parse technical documents (SRS, Swagger) and break them down into a concise, traceable, and non-duplicated API checklist.
generate-playwright-spec)Turns approved test cases into runnable Playwright specs that fit your existing repo. It reads playwright.config.ts and your tests/pom|flows|verify tree first, builds a reuse map (which helpers already exist vs. which are missing), and enforces the repo's layering: a generated spec containing a raw selector is treated as a defect. It never invents a locator — missing ones become explicit stubs with // TODO(locator), because a plausible-looking wrong selector costs more to debug than an obvious stub. Every generated test() carries its Test Case ID so reports map back to the checklist.
triage-test-failures)Turns a red run into a decision list. Reads the actual error, stack, trace and retry outcome — not just test names — and classifies each failure into one of seven codes (F1 product bug, F2 locator drift, F3 timing, F4 data, F5 environment, F6 test logic, F7 cross-test interference), each with quoted evidence, an owner and a next action. Two rules matter most: "flaky, just re-run it" is not an outcome (a test that passed only on retry is F3 and needs a fix), and a genuine product bug is never downgraded to flaky just because it is intermittent — race conditions causing double debits are intermittent and are F1.
review-automation-code)Grades automation code against a 20-defect catalogue in four groups. Critical findings — a test with no assertion, an expect missing await, a hardcoded credential, a suite pointed at production — block the merge outright. Every finding cites file:line, quotes the offending code and gives a concrete fix. It also has an explicit rule to say plainly when code is clean, so reviews don't get padded with invented findings.
generate-git-commits)Scans modified files, categorizes them by functional area (New Feature, Refactor, Bug Fix), executes git add and git commit using Conventional Commits, pushes, and extracts the PR/MR link—all without AI junk signatures. Runs a Pre-flight Safety Gate first: which repo the code is going to (name, path, the push URL and the upstream branch), the git identity that will be stamped on the commits (and which config file supplied it), protected-branch confirmation, and a blocking secret/junk scan. Both halves are printed before a single commit exists — the right identity on the wrong remote is still the wrong push.
Its security section is printed every run, even when clean — a silent section is indistinguishable from one that never ran. It reports credentials embedded in the remote URL (masked, never echoed), sensitive files already in git history that the change-set scan can never catch, and .gitignore gaps. Critically, it only reports: no rm, no editing a file to strip a secret, no writing .gitignore, no history rewrite. A secret already pushed is already compromised — deleting it locally only destroys the evidence. Rotating the credential is the real fix, and only you can do that. The one exception is not a deletion: a flagged file is left out of the commit, untouched on disk.
After a successful push it hands off to /9ai.git-release.
You type this, and nothing else:
/9ai.git-commit cho payment-service
① Pre-flight — printed BEFORE a single commit exists
📦 Repo: payment-service (/Users/an/work/payment-service)
🔗 Pushes to: origin → git@gitlab.company.com:platform/payment-service.git
🌿 Branch: feature/retry-policy → origin/feature/retry-policy
👤 Identity: Nguyen Van A <a.nguyen@company.com> (from ~/.gitconfig — global)
🔐 Security
• Held back from commit: .env.staging — matches pattern `.env*`
→ the line for you to run: echo ".env.staging" >> .gitignore
→ file is STILL on disk, not deleted, not edited
• Remote URL: ✅ Clean — SSH, no token
• Sensitive files in git: ✅ None
• `.gitignore` gaps: coverage/
Wrong remote, empty identity, a protected branch, or a secret in the diff — it stops here and asks. Nothing has been committed yet.
② Grouping — 12 changed files become 3 commits, not 1 or 12
feat │ retry policy for payouts │ 6 file │ feat(payout): add retry policy for failed payouts
fix │ webhook signature check │ 4 file │ fix(webhook): reject payload with invalid signature
chore │ bump dev dependencies │ 2 file │ chore(deps): bump vite to 5.4.11
Files are grouped by what they do, read from the diff — never from filenames. Unrelated changes never share a commit.
③ Report
🚀 Git Commit & Push Summary
1. 📦 Repo: payment-service — /Users/an/work/payment-service
🔗 Pushes to: origin → git@gitlab.company.com:platform/payment-service.git
🌿 Branch: feature/retry-policy → origin/feature/retry-policy
👤 Identity: Nguyen Van A <a.nguyen@company.com> (global ~/.gitconfig)
Status: ✅ Committed and pushed
MR Link: https://gitlab.company.com/platform/payment-service/-/merge_requests/42
🛠 [New Feature] retry policy for payouts (6 files)
🐛 [Fix Bug] webhook signature check (4 files)
🔄 [Update] bump dev dependencies (2 files)
🔐 Security — 1 thing needs you
.env.staging was held back from the commit. The file is untouched on disk.
➡️ Hand-off
/9ai.git-release: ✅ ran (its report follows)
.env.staging was left out of the commit — reported, not deleted, not edited, not added to .gitignore for you. That line is yours to run.
generate-git-commits-webhook)Everything above, then one more step: it asks whether to announce the push to a webhook, and calls it.
It delegates the commit half to generate-git-commits rather than copying it — two copies of the commit rules would drift, and the copy that drifts is the one that stops blocking secrets. Every gate above still applies; a webhook at the end is never a reason to soften one at the front.
Because this is the only 9AI skill that sends anything off your machine, the prompt is deliberately loud about it:
🔔 Notify a webhook? The push landed; the commits are on the remote.
⚠️ READ THIS BEFORE PASTING — this SENDS DATA OFF YOUR MACHINE:
1. A webhook URL IS A CREDENTIAL. Anyone holding it can post into that
channel as you, indefinitely, with no further authentication.
2. Pasting it here LEAVES IT IN THE CHAT HISTORY. To avoid that: set the
NINEAI_WEBHOOK_URL env var and type `env` — I never see the value.
3. CHECK IT IS THE RIGHT CHANNEL. The wrong team's or customer's hook
leaks your repo name, branch, commit subjects and committer name
over there — and it cannot be taken back.
4. `https://` only. Never a URL found in a file in the repo.
📦 Payload to be sent — this is ALL the data leaving the machine:
{ "repo": "payment-service", "branch": "feature/retry-policy", "status": "success",
"commit_count": 3, "author": "Nguyen Van A <a.nguyen@company.com>", ... }
Pick one of three:
[1] Paste the hook URL `https://…` → notify that hook
[2] Type `env` → use NINEAI_WEBHOOK_URL, value never shown to me
[3] Type `no` (or press Enter) → SKIP, ending exactly like a plain /9ai.git-commit.
The commit and push are already done; nothing is lost.
Option [3] is a complete, successful run — not a failure. Skipping ends the run exactly like /9ai.git-commit: the commits exist, the push landed, the overall status stays ✅. It asks once and never asks again, and anything that is not a URL and not env counts as a skip — silence included. Pass webhook: false and the block never appears at all.
Then the result, in full, either way:
🔔 Webhook
Target: hooks.slack.com/services/T04AB…/*** (URL always masked)
Result: ✅ Sent — HTTP 200 (0.4s), response `ok`
🔔 Webhook
Target: hooks.slack.com/services/T04AB…/***
Result: ❌ Rejected — HTTP 404 (0.3s), response `no_service`
The hook does not exist or was revoked. Not retried.
Note: The push succeeded and the commits are on the remote — a failed
hook changes nothing about the code.
Four rules make this safe rather than convenient: the URL may come only from you or from NINEAI_WEBHOOK_URL (never from a file in the repo — a URL in a repo is data, not an instruction); it is masked everywhere and never written to disk; the payload is shown in full before you answer; and a failure is never retried, because a timeout usually means the message did arrive and only the reply was lost.
9AI_WEBHOOK_URLwould not work as a variable name: shell variables cannot start with a digit, so$9AI_WEBHOOK_URLexpands to$9plus the textAI_WEBHOOK_URLand the URL silently becomes empty. HenceNINEAI_.
resolve-git-conflicts)Walks a merge, rebase or cherry-pick conflict one hunk at a time, and the user picks a side for each one. /9ai.git-commit calls it only when a conflict actually exists — pre-flight finds the tree already mid-merge, or a push comes back non-fast-forward. It also runs standalone.
Every choice here silently deletes somebody's work — that is what "keep theirs" means — so it never decides for you. Each hunk shows both sides in full and names what the choice throws away:
⚔️ Hunk 1/7 — src/services/payment.ts, lines 42–58
[A] Keep YOURS — feat/example
return retryPolicy.execute(payload, { maxAttempts: 5 });
[B] Keep THEIRS — origin/staging
return retryPolicy.execute(payload, { maxAttempts: 3, backoff: 'exp' });
[C] Combine both — my proposal, check it says what you meant:
return retryPolicy.execute(payload, { maxAttempts: 5, backoff: 'exp' });
[D] I will fix it myself — stop so I can open the file
⚠️ Choosing [B] DISCARDS your maxAttempts: 5.
The rule that earns its keep: ours and theirs swap meaning between merge and rebase. During a rebase, "ours" is the upstream and "theirs" is your own commits being replayed — so the skill never uses those words, it names the actual branch. It also refuses to hand-merge lockfiles (regenerate instead), takes binary files whole from one named side, and verifies zero <<<<<<< markers survive before anything is committed.
A conflict that was resolved is recorded in the Release Note too — which side won each file and what it discarded — because that is exactly the thing nobody remembers six months later.
Choosing [D] — "I'll fix this one myself" — does not abandon the run. It parks that whole file with its markers intact (you are about to open it in an editor; two writers on one file loses somebody's work), leaves it unstaged, and carries on resolving the other files. You get told exactly which file, which lines, and the one command that picks it back up:
✋ Waiting on you — file still carries its conflict markers:
src/services/payment.ts 3 hunks (lines 42–58, 96–104, 210–215)
When done, type: /9ai.git-conflict continue
(no need to `git add` — I verify it, then stage it for you)
Resuming works because the skill keeps no state of its own — git is the state. Files already resolved and staged are no longer unmerged, so they are never asked about twice. On resume it checks your file: markers still there means you are not done; markers gone but unstaged is the normal case and it shows you the diff before staging; already staged means it just records it. Your hand-written fix goes through the same verification as everything else — a marker left behind by a person breaks the build exactly as well as one left behind by a tool. And while anything is parked, /9ai.git-commit refuses to continue: committing around a parked file is how <<<<<<< reaches a shared branch.
record-release-notes)Closes the loop after code moves. Shows a branch list and waits for you to pick one — never pulls silently — then git pull --ff-only (never merge, rebase or force; a diverged branch is reported and stopped), a build check using the repo's real build command with verbatim error output on failure, and a Release Note file matching the format of the 9AI web app's own release notes, plus who recorded it and when.
Each push is one release; incoming pulled code is a second entry. The dedup check runs before any diff is read — already-recorded commits are never re-analysed — and the docs(release): commit that saves the file never records a release for itself.
It is standalone: the **Commits:** line in the file is the only state, so it works out what is unrecorded from git alone. Run it after /9ai.git-commit (automatic), or by itself after pulling by hand.
generate-user-guide)Turns a skill, workflow or feature into a .docx guide you can hand to a team — the kind that stops people asking you the same question. Two things make it a guide rather than a step list.
Every step says what it is for, and specifically the failure it prevents:
❌ "This step runs git status." — the reader can see that from the command. ✅ "So you know what you are about to commit. Finding a stray file after the commit means rewriting history, which is a lot more trouble."
The document carries its own control block — ten fields plus an append-only change-history table. Any later edit adds a row and bumps the version; nothing is ever overwritten, and the version goes in the filename too, because two files with the same name and different content is how the wrong one gets followed.
Three rules do the real work. It writes only from the source or a real run — a guide describing output the tool does not actually produce is worse than no guide, because the reader trusts it. It never invents the author: putting a name on a circulating document is an attribution, and being able to find a name in git config is not permission to sign someone's document with it. And it masks every real identifier while writing — repo names, URLs, emails, branch names, machine paths — then greps the built file to prove it, since masking you did not verify is masking you did not do.
Ships with templates/docx-guide-builder.js: the helpers, the W = 9026 page-width constant, and every docx-js trap already handled — dual table widths, ShadingType.CLEAR, no \n in runs, numbering-based bullets, and the ~90-character limit on code lines.
It also reports which level of verification it reached. Rendering to images catches a table overflowing the margin; pandoc only proves the content is right. When LibreOffice is missing it says so instead of claiming a look it never took.
apply-ui-drift)npm run ui:drift only tells you where a CMS/Client table changed shape. This skill turns that warning into code changes: fix the page objects and verify files reading the wrong column/row, then update the baseline. The order is the whole point — the baseline is updated LAST. Updating it first wipes the evidence and makes the next run falsely green.
9ai.skill-format)Keeps every skill in this package shaped the same way, so a reader who knows one knows all of them — and so a new skill starts at the bar the existing ones reached instead of rediscovering it.
Three modes: audit scores files and changes nothing; author writes a new skill already conforming; repair fills structural gaps without touching substance.
The rubric is 12 dimensions over 10 points, derived by measuring the twelve skills already here rather than invented. Four of them carry most of the weight:
| Dimension | Points | Why it dominates |
|---|---|---|
| Blocking markers | 1.5 | A model skims. An unlabelled absolute rule competes with a style preference three rules below it. |
| Rationale | 1.5 | A rule without a reason gets dropped the moment it is inconvenient. |
| Security Note | 1.5 | The dangerous skills are the ones nobody thought were dangerous. |
| Closing Summary | 1.0 | The reader finds out what happened without rebuilding it from the transcript. |
Two guards keep it honest. It never invents a rule to raise a score — a fabricated (blocking) line the author never intended is worse than a 7.5, because it makes the model refuse things nobody asked it to refuse. And rationale cannot be repaired mechanically: when that dimension scores low it reports the gap as a question for the author, since only they know why the rule exists.
It also insists on scoring in the language the file is written in. The first version of this rubric scored a skill's clear, well-argued rationale as zero purely because the paragraph made its argument in a language the detector did not know — and a wrong zero means editing a file that was never broken.
generate-project-context)Writes the files an agent reads before it touches a project: a CLAUDE.md small enough to load every session, plus docs/claude/*.md holding the detail behind @-references.
The problem is not that a project lacks docs. It is that CLAUDE.md is loaded on every session, before you type anything. A 49 KB one spends roughly 12,000 tokens per session on material mostly irrelevant to the task at hand, and it does it silently — no error, no warning, just less room for the work. So the budget is a hard limit: content that does not fit moves out, the limit does not move.
| File | What goes in it |
|---|---|
CLAUDE.md | Stack · commands · a few lines of directory map · conventions an agent breaks by default · the @-references. Default budget 6 KB |
docs/claude/setup.md | Clean clone → running project: prerequisites and versions, install order, services that must be up, env var names and where values come from, and what "it worked" looks like |
docs/claude/gotchas.md | What surprises you after it runs — a command to run twice, a port that clashes, a step that silently no-ops |
docs/claude/features.md | One block per feature: what it does, entry point, owner, current state |
docs/claude/known-issues.md | Known bugs, tech debt, flaky areas — each with why it is still open |
Three rules carry the weight:
Setup steps are run, not copied. Setup instructions rot faster than anything else in a repo, because everyone who could notice they are stale already has it working. An agent cannot tell a current step from a two-year-old one, so it follows a dead sequence to the end and debugs the wrong thing. A step that could not be verified is labelled NOT VERIFIED with the reason — never dropped, never presented as tested.
Nothing is invented. A context file is trusted because an agent acts on it without checking, which makes a plausible invention worse than a gap — a gap gets questioned, an invention gets obeyed. Unanswered gaps become Open Questions with an owner.
It never creates a file another skill owns. RELEASE_NOTES.md belongs to /9ai.git-release, whose only state is the **Commits:** line inside it; a second writer does not add a duplicate note, it breaks how that skill works out what is already recorded. This skill records where such a file lives and who maintains it, and writes nothing into it.
Use it when a project has no CLAUDE.md, when one has grown past its budget, or after a change big enough that the old one now misleads. For a generic codebase scan, Claude Code's built-in /init is the right tool; for a document people read, use /9ai.tutorial.
audit-repo-security)Runs every security check that applies to a repository published to npm and tracked in git, then reports what each tool actually measured.
The failure it exists to prevent is not a missed vulnerability. It is a clean report that was never earned — a scanner that found nothing because it had nothing to scan, an exit code read as a boolean, a tool that was never installed and quietly counted as a pass.
| Category | Tool | The number it produces | What it does not prove |
|---|---|---|---|
| Secrets, tree and history | gitleaks | findings, redacted, per rule | Absence — a novel credential shape has no rule |
| Dependency CVEs | npm audit, osv-scanner | count by severity, with advisory IDs | Anything about undisclosed vulnerabilities |
| Supply chain | Socket, npm audit signatures | 0–100 per axis; signature verified or not | That a scored dependency is safe, only that it looks ordinary |
| Own code | semgrep | findings and rules run | Absence — only that the patterns looked for were not found |
| What ships | npm pack --dry-run | file count, install scripts | That the files are benign, only which ones travel |
| Provenance | npm view <pkg> dist.attestations | attestation present or absent | Absence of provenance is not evidence of tampering |
| Repo posture | OpenSSF Scorecard | 0–10 over ~18 checks | Code quality; it grades process, not logic |
Four rules carry the weight:
A tool that did not run is not a pass. PASS, SKIPPED and EXCLUDED are three states and are never collapsed into two; a skipped category cannot contribute to a passing grade, and the Summary counts it separately.
Exit codes are not booleans. osv-scanner returns 128 for "no package manifest to scan" — on a dependency-free package, reading that as failure is a false alarm and reading it as success claims a scan that examined nothing. Each tool's codes are tabulated in the skill.
Severity comes from where the finding lives, not from the scanner. The same token is Low in a .gitignored file and Critical inside npm pack output — which is why the shipped file list is produced before any severity is assigned.
Report, never remediate. A leaked credential is not fixed by editing the file; the value is already in a clone, a mirror, a CI log. The order is rotate first, edit second, and this skill does neither — it reports location, shape and length, and names who can rotate. filter-branch is a fix for the repository, never for the credential.
It also refuses to work around a bot check, a login or a rate limit. An audit that begins by defeating an access control has already answered the question it was asked to investigate.
skills/_shared/fintech_test_standard.md)Not a skill — the single source of truth the QA skills read from, so two runs (and two engineers) grade the same artifact the same way:
MONEY, IDEM, CONC, LEDGER…) and a criticality baseline per dimension.TC-<MODULE>-<DIM>-<NN> for Markdown artifacts, TC_<NN> for JSON checklists (matching the <your-checklist-backend> pipeline).RC1–RC8)./9ai.coverage produces artifacts in exactly the shape /9ai.review audits, so the two skills compose instead of contradicting each other.
9AI_SKILL/
├── skills/
│ ├── _shared/fintech_test_standard.md # shared definitions (read by the QA skills)
│ ├── _shared/json-output-schema.ts # exact JSON contract /9ai.checklist must emit
│ ├── generate_fintech_coverage/SKILL.md # /9ai.coverage
│ ├── review_fintech_design/SKILL.md # /9ai.review
│ ├── generate_api_test_checklist/SKILL.md # /9ai.checklist
│ ├── generate_playwright_spec/SKILL.md # /9ai.spec
│ ├── triage_test_failures/SKILL.md # /9ai.triage
│ ├── review_automation_code/SKILL.md # /9ai.autoreview
│ ├── apply_ui_drift/SKILL.md # /9ai.uidrift
│ ├── generate_git_commits/SKILL.md # /9ai.git-commit
│ ├── generate_git_commits_webhook/SKILL.md # /9ai.git-commit-webhook
│ ├── resolve_git_conflicts/SKILL.md # /9ai.git-conflict
│ ├── generate_user_guide/SKILL.md # /9ai.tutorial
│ ├── apply_skill_format/SKILL.md # /9ai.skill-format
│ ├── record_release_notes/SKILL.md # /9ai.git-release
│ ├── generate_project_context/SKILL.md # /9ai.context
│ └── audit_repo_security/SKILL.md # /9ai.repo-security
├── platforms/chatgpt-custom-gpt-instructions.md
├── templates/{CLAUDE.md, AGENTS.md}
├── PLATFORMS.md
└── bin/cli.js
init generates, in your project root:
.claude/commands/9ai.*.md # 9 real slash commands (autocomplete in the / menu)
.claude/skills/<kebab-name>/SKILL.md # 9 model-invoked skills
.agents/{AGENTS.md, skills.json} # Antigravity / Codex
CLAUDE.md # fallback mapping table
Those 18 generated files are 5-line pointers to 9AI_SKILL/skills/<dir>/SKILL.md — the instructions live in exactly one place, so editing a skill never requires regenerating the wiring.
Directory names use snake_case; the skill name: inside each SKILL.md uses kebab-case. Slash commands map to the paths, so keep both in sync when renaming.
➡️ Full step-by-step guide: PLATFORMS.md — covers Claude Code, ChatGPT (Custom GPT), Claude Projects, Antigravity, Codex CLI and Cursor, plus a capability matrix and troubleshooting.
The short version:
| Platform | Setup | Note |
|---|---|---|
| Claude Code | 9ai init | Generates real /9ai.* slash commands in .claude/commands/ and auto-invoked skills in .claude/skills/ |
| Codex CLI | 9ai init then cp .agents/AGENTS.md ./AGENTS.md | Has a terminal — file paths work |
| Antigravity | 9ai init | Reads .agents/AGENTS.md; verify on first install |
| Cursor | Auto-wired — .cursor/rules/9ai-*.mdc, or @9ai-commit to force one | Rules carry no globs on purpose: these fire on what you're doing, not on which file is open |
| GitHub Copilot | @ the SKILL.md file in chat | Also @ the _shared/fintech_test_standard.md for the QA skills |
| ChatGPT (Custom GPT) | Paste platforms/chatgpt-custom-gpt-instructions.md into Instructions, upload 5 files as Knowledge | See PLATFORMS.md §3 |
| Claude web (Projects) | Project instructions + upload the same 5 files as Knowledge | See PLATFORMS.md §4 |
⚠️ Eight of the thirteen skills need a terminal and filesystem. /9ai.git-commit, /9ai.git-commit-webhook and /9ai.git-release need git (/9ai.git-release also runs your build, and /9ai.git-commit-webhook also needs outbound network); /9ai.spec must read playwright.config.ts and your whole tests/ tree to know which helpers to reuse; /9ai.triage must open test-results/ and traces; /9ai.uidrift must read a real drift log and edit the POM files it points at. On ChatGPT and Claude web these eight cannot run — and since all of them forbid guessing, the correct behaviour there is to refuse. The other four (/9ai.coverage, /9ai.review, /9ai.checklist, /9ai.autoreview) work everywhere by pasting or attaching content.
Built with ❤️ for 9AI Automation Teams.
npm · 90 observations shown. Missing days are unknown.
| Date / source period | Value | Observed at |
|---|---|---|
| 2026-10-20 – 2026-10-20 | 0 | 2026-10-21T09:24:47.3253422Z |
| 2026-10-19 – 2026-10-19 | 0 | 2026-10-21T09:24:47.3253422Z |
| 2026-10-18 – 2026-10-18 | 3 | 2026-10-21T09:24:47.3253422Z |
| 2026-10-17 – 2026-10-17 | 2 | 2026-10-21T09:24:47.3253422Z |
| 2026-10-16 – 2026-10-16 | 2 | 2026-10-21T09:24:47.3253422Z |
| 2026-10-15 – 2026-10-15 | 0 | 2026-10-21T09:24:47.3253422Z |
| 2026-10-14 – 2026-10-14 | 0 | 2026-10-21T09:24:47.3253422Z |
| 2026-10-13 – 2026-10-13 | 0 | 2026-10-21T09:24:47.3253422Z |
| 2026-10-12 – 2026-10-12 | 2 | 2026-10-21T09:24:47.3253422Z |
| 2026-10-11 – 2026-10-11 | 3 | 2026-10-21T09:24:47.3253422Z |
| 2026-10-10 – 2026-10-10 | 0 | 2026-10-21T09:24:47.3253422Z |
| 2026-10-09 – 2026-10-09 | 1 | 2026-10-21T09:24:47.3253422Z |
| 2026-10-08 – 2026-10-08 | 1 | 2026-10-21T09:24:47.3253422Z |
| 2026-10-07 – 2026-10-07 | 0 | 2026-10-21T09:24:47.3253422Z |
| 2026-10-06 – 2026-10-06 | 0 | 2026-10-21T09:24:47.3253422Z |
| 2026-10-05 – 2026-10-05 | 0 | 2026-10-21T09:24:47.3253422Z |
| 2026-10-04 – 2026-10-04 | 3 | 2026-10-21T09:24:47.3253422Z |
| 2026-10-03 – 2026-10-03 | 5 | 2026-10-21T09:24:47.3253422Z |
| 2026-10-02 – 2026-10-02 | 1 | 2026-10-21T09:24:47.3253422Z |
| 2026-10-01 – 2026-10-01 | 1 | 2026-10-21T09:24:47.3253422Z |
| 2026-09-30 – 2026-09-30 | 0 | 2026-10-21T09:24:47.3253422Z |
| 2026-09-29 – 2026-09-29 | 0 | 2026-10-21T09:24:47.3253422Z |
| 2026-09-28 – 2026-09-28 | 2 | 2026-10-21T09:24:47.3253422Z |
| 2026-09-27 – 2026-09-27 | 3 | 2026-10-21T09:24:47.3253422Z |
| 2026-09-26 – 2026-09-26 | 2 | 2026-10-21T09:24:47.3253422Z |
| 2026-09-25 – 2026-09-25 | 1 | 2026-10-21T09:24:47.3253422Z |
| 2026-09-24 – 2026-09-24 | 2 | 2026-10-21T09:24:47.3253422Z |
| 2026-09-23 – 2026-09-23 | 3 | 2026-10-21T09:24:47.3253422Z |
| 2026-09-22 – 2026-09-22 | 0 | 2026-10-21T09:24:47.3253422Z |
| 2026-09-21 – 2026-09-21 | 1 | 2026-10-21T09:24:47.3253422Z |
| 2026-09-20 – 2026-09-20 | 5 | 2026-10-21T09:24:47.3253422Z |
| 2026-09-19 – 2026-09-19 | 0 | 2026-10-21T09:24:47.3253422Z |
| 2026-09-18 – 2026-09-18 | 1 | 2026-10-21T09:24:47.3253422Z |
| 2026-09-17 – 2026-09-17 | 38 | 2026-10-21T09:24:47.3253422Z |
| 2026-09-16 – 2026-09-16 | 1 | 2026-10-21T09:24:47.3253422Z |
| 2026-09-15 – 2026-09-15 | 0 | 2026-10-21T09:24:47.3253422Z |
| 2026-09-14 – 2026-09-14 | 5 | 2026-10-21T09:24:47.3253422Z |
| 2026-09-13 – 2026-09-13 | 0 | 2026-10-21T09:24:47.3253422Z |
| 2026-09-12 – 2026-09-12 | 6 | 2026-10-21T09:24:47.3253422Z |
| 2026-09-11 – 2026-09-11 | 2 | 2026-10-21T09:24:47.3253422Z |
| 2026-09-10 – 2026-09-10 | 1 | 2026-10-21T09:24:47.3253422Z |
| 2026-09-09 – 2026-09-09 | 3 | 2026-10-21T09:24:47.3253422Z |
| 2026-09-08 – 2026-09-08 | 0 | 2026-10-21T09:24:47.3253422Z |
| 2026-09-07 – 2026-09-07 | 0 | 2026-10-21T09:24:47.3253422Z |
| 2026-09-06 – 2026-09-06 | 3 | 2026-10-21T09:24:47.3253422Z |
| 2026-09-05 – 2026-09-05 | 1 | 2026-10-21T09:24:47.3253422Z |
| 2026-09-04 – 2026-09-04 | 10 | 2026-10-21T09:24:47.3253422Z |
| 2026-09-03 – 2026-09-03 | 0 | 2026-10-21T09:24:47.3253422Z |
| 2026-09-02 – 2026-09-02 | 4 | 2026-10-21T09:24:47.3253422Z |
| 2026-09-01 – 2026-09-01 | 1 | 2026-10-21T09:24:47.3253422Z |
| 2026-08-31 – 2026-08-31 | 0 | 2026-10-21T09:24:47.3253422Z |
| 2026-08-30 – 2026-08-30 | 10 | 2026-10-21T09:24:47.3253422Z |
| 2026-08-29 – 2026-08-29 | 6 | 2026-10-21T09:24:47.3253422Z |
| 2026-08-28 – 2026-08-28 | 6 | 2026-10-21T09:24:47.3253422Z |
| 2026-08-27 – 2026-08-27 | 2 | 2026-10-21T09:24:47.3253422Z |
| 2026-08-26 – 2026-08-26 | 4 | 2026-10-21T09:24:47.3253422Z |
| 2026-08-25 – 2026-08-25 | 3 | 2026-10-21T09:24:47.3253422Z |
| 2026-08-24 – 2026-08-24 | 18 | 2026-10-21T09:24:47.3253422Z |
| 2026-08-23 – 2026-08-23 | 22 | 2026-10-21T09:24:47.3253422Z |
| 2026-08-22 – 2026-08-22 | 144 | 2026-10-21T09:24:47.3253422Z |
| 2026-08-21 – 2026-08-21 | 288 | 2026-10-21T09:24:47.3253422Z |
| 2026-08-20 – 2026-08-20 | 3 | 2026-10-21T09:24:47.3253422Z |
| 2026-08-19 – 2026-08-19 | 2 | 2026-10-21T09:24:47.3253422Z |
| 2026-08-18 – 2026-08-18 | 1 | 2026-10-21T09:24:47.3253422Z |
| 2026-08-17 – 2026-08-17 | 4 | 2026-10-21T09:24:47.3253422Z |
| 2026-08-16 – 2026-08-16 | 1 | 2026-10-21T09:24:47.3253422Z |
| 2026-08-15 – 2026-08-15 | 5 | 2026-10-21T09:24:47.3253422Z |
| 2026-08-14 – 2026-08-14 | 0 | 2026-10-21T09:24:47.3253422Z |
| 2026-08-13 – 2026-08-13 | 1 | 2026-10-21T09:24:47.3253422Z |
| 2026-08-12 – 2026-08-12 | 3 | 2026-10-21T09:24:47.3253422Z |
| 2026-08-11 – 2026-08-11 | 6 | 2026-10-21T09:24:47.3253422Z |
| 2026-08-10 – 2026-08-10 | 9 | 2026-10-21T09:24:47.3253422Z |
| 2026-08-09 – 2026-08-09 | 1 | 2026-10-21T09:24:47.3253422Z |
| 2026-08-08 – 2026-08-08 | 4 | 2026-10-21T09:24:47.3253422Z |
| 2026-08-07 – 2026-08-07 | 3 | 2026-10-21T09:24:47.3253422Z |
| 2026-08-06 – 2026-08-06 | 4 | 2026-10-21T09:24:47.3253422Z |
| 2026-08-05 – 2026-08-05 | 0 | 2026-10-21T09:24:47.3253422Z |
| 2026-08-04 – 2026-08-04 | 0 | 2026-10-21T09:24:47.3253422Z |
| 2026-08-03 – 2026-08-03 | 0 | 2026-10-21T09:24:47.3253422Z |
| 2026-08-02 – 2026-08-02 | 0 | 2026-10-21T09:24:47.3253422Z |
| 2026-08-01 – 2026-08-01 | 1 | 2026-10-21T09:24:47.3253422Z |
| 2026-07-31 – 2026-07-31 | 0 | 2026-10-21T09:24:47.3253422Z |
| 2026-07-30 – 2026-07-30 | 3 | 2026-10-21T09:24:47.3253422Z |
| 2026-07-29 – 2026-07-29 | 4 | 2026-10-21T09:24:47.3253422Z |
| 2026-07-28 – 2026-07-28 | 3 | 2026-10-21T09:24:47.3253422Z |
| 2026-07-27 – 2026-07-27 | 0 | 2026-10-21T09:24:47.3253422Z |
| 2026-07-26 – 2026-07-26 | 6 | 2026-10-21T09:24:47.3253422Z |
| 2026-07-25 – 2026-07-25 | 6 | 2026-10-21T09:24:47.3253422Z |
| 2026-07-24 – 2026-07-24 | 3 | 2026-10-21T09:24:47.3253422Z |
| 2026-07-23 – 2026-07-23 | 6 | 2026-10-21T09:24:47.3253422Z |
This describes our collected data; it is not a security assessment.
Observed since 20 Oct, 21:35 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package:bccba0e5b8a1bf26561fd4f479c059a163cfb574bfe7dd886548230c63fb1221