{"_id":"9ai-skills","_rev":"10-f78e8aead3c52a237eb72518692b9ce4","name":"9ai-skills","dist-tags":{"latest":"1.28.1"},"versions":{"1.21.1":{"name":"9ai-skills","version":"1.21.1","keywords":["ai","qa","fintech","prompt","llm","claude","codex"],"author":{"name":"9AI QA Team"},"license":"ISC","_id":"9ai-skills@1.21.1","maintainers":[{"name":"johnbaron","email":"johnbaron.bha@gmail.com"}],"bin":{"9ai":"bin/cli.js"},"dist":{"shasum":"e08b547d4c4eab08d930a22461bebc7af8b5854c","tarball":"https://registry.npmjs.org/9ai-skills/-/9ai-skills-1.21.1.tgz","fileCount":30,"integrity":"sha512-OHJDC6D3AGT0BbCcyYBjGFxMl4vAQpdW3QqUMqb+qfOi7ujjhYHv1yw7mJLRsHYC7Jz60bBDnLOIzhi1px9Vxg==","signatures":[{"sig":"MEUCIBrnmrTeBq4cLDxcEDHAdsyVd4baxQZhqbNbJT1eSE5iAiEA4fP4BfiTTvXDozj56dRx4/6Un1OiRr37LimLSiNS/o4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":384464},"engines":{"node":">=14"},"scripts":{"test":"node test/scenarios.js","verify":"node scripts/verify-package.js","verify:published":"node scripts/verify-package.js --published"},"_npmUser":{"name":"johnbaron","email":"johnbaron.bha@gmail.com"},"_npmVersion":"11.12.1","description":"9AI QA & Automation Skills Framework for AI Agents","directories":{},"_nodeVersion":"24.15.0","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/9ai-skills_1.21.1_1787306739107_0.8947879844810618","host":"s3://npm-registry-packages-npm-production"}},"1.28.1":{"name":"9ai-skills","version":"1.28.1","description":"9AI QA & Automation Skills Framework for AI Agents","bin":{"9ai":"bin/cli.js"},"scripts":{"test":"node test/scenarios.js","verify":"node scripts/verify-package.js","verify:published":"node scripts/verify-package.js --published"},"keywords":["ai","qa","fintech","prompt","llm","claude","codex"],"author":{"name":"9AI QA Team"},"license":"ISC","engines":{"node":">=14"},"_id":"9ai-skills@1.28.1","_nodeVersion":"24.15.0","_npmVersion":"11.12.1","dist":{"integrity":"sha512-B6IRwjcmpN70M9i4uqRh+1AxQupnoVR4HWrW3Yu3XEPwZh925y7AhXKAk5+KIFaZpffUn123yt7VZZKb6CM9pw==","shasum":"7a80854743de2e9cad1da35ff7bec62a2ea517d8","tarball":"https://registry.npmjs.org/9ai-skills/-/9ai-skills-1.28.1.tgz","fileCount":32,"unpackedSize":436940,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCEx73iFDeK7K7AFJtlPz+58VaTR+axses9yTrT5WqPagIgPv9EP5mLmtnrpY+ggeaop+rA6ar936+9jaCReLfvj9k="}]},"_npmUser":{"name":"johnbaron","email":"johnbaron.bha@gmail.com"},"directories":{},"maintainers":[{"name":"johnbaron","email":"johnbaron.bha@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/9ai-skills_1.28.1_1787385827067_0.5913653614934558"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-14T14:27:42.969Z","modified":"2026-08-22T08:03:47.402Z","1.0.0":"2026-07-14T14:27:43.436Z","1.0.1":"2026-07-14T14:40:12.140Z","1.0.2":"2026-07-15T00:00:35.295Z","1.20.0":"2026-08-21T04:41:25.373Z","1.21.1":"2026-08-21T10:05:39.329Z","1.28.1":"2026-08-22T08:03:47.214Z"},"author":{"name":"9AI QA Team"},"license":"ISC","keywords":["ai","qa","fintech","prompt","llm","claude","codex"],"description":"9AI QA & Automation Skills Framework for AI Agents","maintainers":[{"name":"johnbaron","email":"johnbaron.bha@gmail.com"}],"readme":"# 🚀 9ai (9AI QA & Automation Skills)\n\n**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.\n\n---\n\n## 📦 Installation & Setup\n\nInstall the CLI globally, then run `init` once inside each project you want to use it in:\n\n```bash\nnpm install -g 9ai-skills\n```\n\n```bash\n9ai init\n```\n\n**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:\n\n```\n.claude/commands/9ai.*.md             13 slash commands (autocomplete in the / menu)\n.claude/skills/<kebab-name>/SKILL.md  13 model-invoked skills\n.cursor/rules/9ai-*.mdc               13 Cursor rules (agent-requested, or @9ai-commit)\n.agents/{AGENTS.md, skills.json}      Antigravity / Codex\nCLAUDE.md                             fallback mapping table\n9AI_SKILL/                            the skills themselves\n```\n\nRun `9ai init` again in any other repo — it is per-project.\n\n---\n\n## 🌐 Report Language\n\nEverything 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.\n\nOn the first run, you get asked once:\n\n```\n🌐  Report language / Langue des rapports\n\n    First run — pick the language for reports, confirmations and summaries.\n    Première exécution — choisissez la langue des rapports et confirmations.\n\n    [1] Français   (langue de cette conversation)\n    [2] English    (langue du système)\n    [3] Autre — tapez le nom de la langue\n\n    Commit messages, code and file paths stay English either way.\n    Les messages de commit, le code et les chemins restent en anglais.\n\n    Saved to ~/.9ai/config.json — asked once, never again.\n```\n\nThe 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.\n\nThat 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.\n\nThe answer goes to `~/.9ai/config.json` and no skill asks again — pick your language in `/9ai.git-commit` and `/9ai.triage` already knows.\n\n| Want to | Do |\n| --- | --- |\n| Change it for good | Edit `~/.9ai/config.json` |\n| Change it for one run | Pass `report_language: fr` (any language) |\n| Override it in one repo | Add `.9ai/config.json` to that repo |\n\n**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.\n\n## 🔒 Security\n\nThis 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:\n\n```bash\nnpm run verify:published\n```\n\nTwelve checks, each printing file and line as evidence. Full threat model and the behavioural guarantees the skills make: [SECURITY.md](SECURITY.md).\n\n### Independent scanners, and what they actually said\n\nNothing below is self-reported. Every line is a command you can run yourself, and the reason\nit is worth running is given rather than implied.\n\n| Check | Tool | Result | Why it matters |\n| --- | --- | --- | --- |\n| Dependency CVEs | `npm audit` | 0 vulnerabilities | The usual way a clean package hurts its users |\n| Dependency count | `npm ls` | **0 runtime dependencies** | Removes the supply-chain surface instead of monitoring it |\n| Secrets | `gitleaks` | 0 leaks | A committed credential stays valid long after it is deleted |\n| Vulnerability DB | `osv-scanner` | nothing to scan — no manifests | The expected result at zero dependencies, not a pass by omission |\n| Static analysis | `semgrep`, 77 rules | 0 findings | Catches `eval`, concatenated shell and dynamic `require` |\n| Package contract | `verify-package.js` | 12/12 | No install script, no network, no stray files, no leaked identifiers or document links |\n\nRun all six at once from a clone:\n\n```bash\nnode scripts/security-audit.js          # add --json for CI\n```\n\n**A skipped check is reported as skipped, never as a pass.** If a scanner is not installed the\nreport says so and prints the install command, because a report that silently counts an\nabsent tool as a clean result is worse than no report.\n\nThe registry's free Semgrep rulesets flag none of `eval`, concatenated shell, or dynamic\n`require` — checked by running four of them against a file containing all three. So those\nrules live in [`.semgrep.yml`](.semgrep.yml) instead of being assumed.\n\n## 🔄 Updating Core Skills\n\nWhen the skills are updated on npm, refresh the CLI, then re-run `update` in each project:\n\n```bash\nnpm update -g 9ai-skills\n```\n\n```bash\n9ai update\n```\n\n**Safety Guarantee:** `update` only replaces the skills this package ships. It will:\n\n- **Skip** your `CLAUDE.md`, `.agents/AGENTS.md` and `skills.json` — your custom instructions are never overwritten.\n- **Preserve** any skill you added yourself under `9AI_SKILL/skills/`, and print `🛡️ Preserved N custom skill(s): ...` so you can see it happened.\n- **Refresh** the generated `.claude/commands/` and `.claude/skills/` pointers, so new skills show up in your `/` menu automatically.\n\n---\n\n## ⚡️ Core Slash Commands\n\nOnce initialized, your AI assistant will instantly understand the following \"Slash Commands\". You do not need to write long prompts—just use these shortcuts!\n\n**Test design**\n\n| Command          | Target Skill                     | Description                                                                              |\n| ---------------- | -------------------------------- | ---------------------------------------------------------------------------------------- |\n| `/9ai.coverage`  | `generate-fintech-test-coverage` | Analyze requirements and generate a strict Fintech Test Coverage Matrix (15 dimensions). |\n| `/9ai.review`    | `review-fintech-test-design`     | Audit and review existing Test Cases or Coverage Matrices against Fintech standards.     |\n| `/9ai.checklist` | `generate-api-test-checklist`    | Extract requirements from API specs and generate an executable API Test Checklist.       |\n\n**Automation**\n\n| Command           | Target Skill                | Description                                                                                     |\n| ----------------- | --------------------------- | ------------------------------------------------------------------------------------------------ |\n| `/9ai.spec`       | `generate-playwright-spec`  | Turn checklist test cases into Playwright specs that respect the repo's pom → flow → verify → spec layering. |\n| `/9ai.triage`     | `triage-test-failures`      | Classify a failed run into product bug / locator drift / timing / data / env, with evidence.    |\n| `/9ai.autoreview` | `review-automation-code`    | Find hard waits, brittle locators, tests with no assertions, shared state, leaked credentials.  |\n| `/9ai.tutorial`   | `generate-user-guide`       | Turn a skill or workflow into a step-by-step Word guide with document control and change history. |\n| `/9ai.repo-security` | `audit-repo-security`    | Audit an npm + git project across secrets, dependencies, supply chain, own code, what ships, provenance and licence. |\n| `/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. |\n| `/9ai.uidrift`    | `apply-ui-drift`            | Turn a `npm run ui:drift` log into POM/verify fixes — baseline is updated **last**, never first. |\n| `/9ai.skill-format` | `9ai.skill-format`        | Score a `SKILL.md` on the 12-dimension house rubric; author or repair skills to match. |\n\n**Git**\n\n| Command          | Target Skill                     | Description                                                                              |\n| ---------------- | -------------------------------- | ---------------------------------------------------------------------------------------- |\n| `/9ai.git-commit`    | `generate-git-commits`           | Report the target repo + git identity + security findings, auto-group uncommitted files, commit & push. |\n| `/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. |\n| `/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. |\n| `/9ai.git-release`   | `record-release-notes`           | Pull a chosen branch, verify the build, and record pushed/incoming commits into a Release Note file. |\n\n> **🔥 Quick Example:**\n> Open Claude Code or Antigravity and simply type:\n> `/9ai.git-commit to src/ and modules/`\n> 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!\n\n---\n\n## 🧠 What's Inside?\n\nWhen you run `9ai init`, it installs the following expert prompt frameworks (Skills) into your project:\n\n### 1. Generate Fintech Test Coverage (`generate-fintech-test-coverage`)\n\nForces the AI to analyze features against 15 rigorous Fintech dimensions (Concurrency, Money Integrity, Rollback, Idempotency, etc.) instead of writing naive happy-path test cases.\n\n### 2. Review Fintech Test Design (`review-fintech-test-design`)\n\nTurns 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).\n\n### 3. Generate API Test Checklist (`generate-api-test-checklist`)\n\nDesigned to parse technical documents (SRS, Swagger) and break them down into a concise, traceable, and non-duplicated API checklist.\n\n### 4. Generate Playwright Spec (`generate-playwright-spec`)\n\nTurns 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.\n\n### 5. Triage Test Failures (`triage-test-failures`)\n\nTurns 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`.\n\n### 6. Review Automation Code (`review-automation-code`)\n\nGrades 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.\n\n### 7. Auto Group, Git Commit & Push (`generate-git-commits`)\n\nScans 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.\n\nIts 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.\n\nAfter a successful push it hands off to `/9ai.git-release`.\n\n#### What a run actually looks like\n\nYou type this, and nothing else:\n\n```\n/9ai.git-commit cho payment-service\n```\n\n**① Pre-flight — printed BEFORE a single commit exists**\n\n```\n📦 Repo:      payment-service  (/Users/an/work/payment-service)\n🔗 Pushes to: origin → git@gitlab.company.com:platform/payment-service.git\n🌿 Branch:    feature/retry-policy → origin/feature/retry-policy\n👤 Identity:   Nguyen Van A <a.nguyen@company.com>  (from ~/.gitconfig — global)\n\n🔐 Security\n   • Held back from commit: .env.staging — matches pattern `.env*`\n                            → the line for you to run: echo \".env.staging\" >> .gitignore\n                            → file is STILL on disk, not deleted, not edited\n   • Remote URL:            ✅ Clean — SSH, no token\n   • Sensitive files in git: ✅ None\n   • `.gitignore` gaps:      coverage/\n```\n\nWrong remote, empty identity, a protected branch, or a secret in the diff — it stops here and asks. Nothing has been committed yet.\n\n**② Grouping — 12 changed files become 3 commits, not 1 or 12**\n\n```\nfeat  │ retry policy for payouts   │ 6 file  │ feat(payout): add retry policy for failed payouts\nfix   │ webhook signature check     │ 4 file  │ fix(webhook): reject payload with invalid signature\nchore │ bump dev dependencies    │ 2 file  │ chore(deps): bump vite to 5.4.11\n```\n\nFiles are grouped by what they *do*, read from the diff — never from filenames. Unrelated changes never share a commit.\n\n**③ Report**\n\n```\n🚀 Git Commit & Push Summary\n\n1. 📦 Repo: payment-service — /Users/an/work/payment-service\n   🔗 Pushes to: origin → git@gitlab.company.com:platform/payment-service.git\n   🌿 Branch:    feature/retry-policy → origin/feature/retry-policy\n   👤 Identity:   Nguyen Van A <a.nguyen@company.com>  (global ~/.gitconfig)\n   Status:      ✅ Committed and pushed\n   MR Link:      https://gitlab.company.com/platform/payment-service/-/merge_requests/42\n\n   🛠 [New Feature]   retry policy for payouts   (6 files)\n   🐛 [Fix Bug]       webhook signature check     (4 files)\n   🔄 [Update]        bump dev dependencies    (2 files)\n\n🔐 Security — 1 thing needs you\n   .env.staging was held back from the commit. The file is untouched on disk.\n\n➡️ Hand-off\n   /9ai.git-release: ✅ ran (its report follows)\n```\n\n`.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.\n\n### 8. Commit + Push + Webhook (`generate-git-commits-webhook`)\n\nEverything above, then one more step: it asks whether to announce the push to a webhook, and calls it.\n\nIt **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.\n\nBecause this is the only 9AI skill that sends anything off your machine, the prompt is deliberately loud about it:\n\n```\n🔔 Notify a webhook?  The push landed; the commits are on the remote.\n\n⚠️  READ THIS BEFORE PASTING — this SENDS DATA OFF YOUR MACHINE:\n\n   1. A webhook URL IS A CREDENTIAL. Anyone holding it can post into that\n      channel as you, indefinitely, with no further authentication.\n   2. Pasting it here LEAVES IT IN THE CHAT HISTORY. To avoid that: set the\n      NINEAI_WEBHOOK_URL env var and type `env` — I never see the value.\n   3. CHECK IT IS THE RIGHT CHANNEL. The wrong team's or customer's hook\n      leaks your repo name, branch, commit subjects and committer name\n      over there — and it cannot be taken back.\n   4. `https://` only. Never a URL found in a file in the repo.\n\n   📦 Payload to be sent — this is ALL the data leaving the machine:\n   { \"repo\": \"payment-service\", \"branch\": \"feature/retry-policy\", \"status\": \"success\",\n     \"commit_count\": 3, \"author\": \"Nguyen Van A <a.nguyen@company.com>\", ... }\n\n   Pick one of three:\n   [1] Paste the hook URL `https://…`  → notify that hook\n   [2] Type `env`                      → use NINEAI_WEBHOOK_URL, value never shown to me\n   [3] Type `no` (or press Enter)      → SKIP, ending exactly like a plain /9ai.git-commit.\n                                          The commit and push are already done; nothing is lost.\n```\n\n**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.\n\nThen the result, in full, either way:\n\n```\n🔔 Webhook\n   Target:  hooks.slack.com/services/T04AB…/***     (URL always masked)\n   Result:  ✅ Sent — HTTP 200 (0.4s), response `ok`\n```\n\n```\n🔔 Webhook\n   Target:  hooks.slack.com/services/T04AB…/***\n   Result:  ❌ Rejected — HTTP 404 (0.3s), response `no_service`\n            The hook does not exist or was revoked. Not retried.\n   Note:    The push succeeded and the commits are on the remote — a failed\n            hook changes nothing about the code.\n```\n\nFour 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.\n\n> `9AI_WEBHOOK_URL` would not work as a variable name: shell variables cannot start with a digit, so `$9AI_WEBHOOK_URL` expands to `$9` plus the text `AI_WEBHOOK_URL` and the URL silently becomes empty. Hence `NINEAI_`.\n\n### 9. Resolve Git Conflicts (`resolve-git-conflicts`)\n\nWalks 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.\n\nEvery 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:\n\n```\n⚔️  Hunk 1/7 — src/services/payment.ts, lines 42–58\n\n   [A] Keep YOURS — feat/example\n       return retryPolicy.execute(payload, { maxAttempts: 5 });\n   [B] Keep THEIRS — origin/staging\n       return retryPolicy.execute(payload, { maxAttempts: 3, backoff: 'exp' });\n   [C] Combine both — my proposal, check it says what you meant:\n       return retryPolicy.execute(payload, { maxAttempts: 5, backoff: 'exp' });\n   [D] I will fix it myself — stop so I can open the file\n\n   ⚠️ Choosing [B] DISCARDS your maxAttempts: 5.\n```\n\nThe 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.\n\nA 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.\n\nChoosing `[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:\n\n```\n   ✋ Waiting on you — file still carries its conflict markers:\n      src/services/payment.ts      3 hunks  (lines 42–58, 96–104, 210–215)\n\n   When done, type:  /9ai.git-conflict continue\n   (no need to `git add` — I verify it, then stage it for you)\n```\n\nResuming 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.\n\n### 10. Record Release Notes (`record-release-notes`)\n\nCloses 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.\n\nEach 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.\n\nIt 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.\n\n### 11. Generate User Guide (`generate-user-guide`)\n\nTurns 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.\n\n**Every step says what it is for**, and specifically **the failure it prevents**:\n\n> ❌ \"This step runs git status.\" — the reader can see that from the command.\n> ✅ \"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.\"\n\n**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.\n\nThree 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.\n\nShips 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.\n\nIt 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.\n\n### 12. Apply UI Drift (`apply-ui-drift`)\n\n`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.\n\n### 13. Skill Format (`9ai.skill-format`)\n\nKeeps 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.\n\nThree modes: `audit` scores files and **changes nothing**; `author` writes a new skill already conforming; `repair` fills structural gaps without touching substance.\n\nThe 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:\n\n| Dimension | Points | Why it dominates |\n| --- | --- | --- |\n| Blocking markers | 1.5 | A model skims. An unlabelled absolute rule competes with a style preference three rules below it. |\n| Rationale | 1.5 | A rule without a reason gets dropped the moment it is inconvenient. |\n| Security Note | 1.5 | The dangerous skills are the ones nobody thought were dangerous. |\n| Closing Summary | 1.0 | The reader finds out what happened without rebuilding it from the transcript. |\n\nTwo 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.\n\nIt 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.\n\n### 14. Generate Project Context (`generate-project-context`)\n\nWrites 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.\n\nThe 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.\n\n| File | What goes in it |\n| --- | --- |\n| `CLAUDE.md` | Stack · commands · a few lines of directory map · conventions an agent breaks by default · the `@`-references. Default budget **6 KB** |\n| `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** |\n| `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 |\n| `docs/claude/features.md` | One block per feature: what it does, entry point, owner, current state |\n| `docs/claude/known-issues.md` | Known bugs, tech debt, flaky areas — each with **why it is still open** |\n\nThree rules carry the weight:\n\n**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**.\n\n**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.\n\n**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.\n\nUse 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`.\n\n### 15. Audit Repo Security (`audit-repo-security`)\n\nRuns every security check that applies to a repository published to npm and tracked in git, then reports **what each tool actually measured**.\n\nThe 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.\n\n| Category | Tool | The number it produces | What it does **not** prove |\n| --- | --- | --- | --- |\n| Secrets, tree **and history** | `gitleaks` | findings, redacted, per rule | Absence — a novel credential shape has no rule |\n| Dependency CVEs | `npm audit`, `osv-scanner` | count by severity, with advisory IDs | Anything about undisclosed vulnerabilities |\n| 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 |\n| Own code | `semgrep` | findings **and rules run** | Absence — only that the patterns looked for were not found |\n| What ships | `npm pack --dry-run` | file count, install scripts | That the files are benign, only which ones travel |\n| Provenance | `npm view <pkg> dist.attestations` | attestation present or absent | Absence of provenance is not evidence of tampering |\n| Repo posture | OpenSSF Scorecard | 0–10 over ~18 checks | Code quality; it grades process, not logic |\n\nFour rules carry the weight:\n\n**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.\n\n**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.\n\n**Severity comes from where the finding lives, not from the scanner.** The same token is Low in a `.gitignore`d file and Critical inside `npm pack` output — which is why the shipped file list is produced *before* any severity is assigned.\n\n**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.\n\nIt 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.\n\n### 📐 Shared Standard (`skills/_shared/fintech_test_standard.md`)\n\nNot 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:\n\n- The **15 fintech dimensions** with stable codes (`MONEY`, `IDEM`, `CONC`, `LEDGER`…) and a criticality baseline per dimension.\n- The **Risk Classification Standard** — objective rules for Critical / High / Medium / Low.\n- **Test Case ID conventions** — `TC-<MODULE>-<DIM>-<NN>` for Markdown artifacts, `TC_<NN>` for JSON checklists (matching the `<your-checklist-backend>` pipeline).\n- The **canonical Test Case schema**, the **Data Verification Layers**, and the **Defect Root Cause Taxonomy** (`RC1`–`RC8`).\n\n`/9ai.coverage` produces artifacts in exactly the shape `/9ai.review` audits, so the two skills compose instead of contradicting each other.\n\n---\n\n## 🗂 Folder layout\n\n```\n9AI_SKILL/\n├── skills/\n│   ├── _shared/fintech_test_standard.md      # shared definitions (read by the QA skills)\n│   ├── _shared/json-output-schema.ts         # exact JSON contract /9ai.checklist must emit\n│   ├── generate_fintech_coverage/SKILL.md    # /9ai.coverage\n│   ├── review_fintech_design/SKILL.md        # /9ai.review\n│   ├── generate_api_test_checklist/SKILL.md  # /9ai.checklist\n│   ├── generate_playwright_spec/SKILL.md     # /9ai.spec\n│   ├── triage_test_failures/SKILL.md         # /9ai.triage\n│   ├── review_automation_code/SKILL.md       # /9ai.autoreview\n│   ├── apply_ui_drift/SKILL.md               # /9ai.uidrift\n│   ├── generate_git_commits/SKILL.md         # /9ai.git-commit\n│   ├── generate_git_commits_webhook/SKILL.md  # /9ai.git-commit-webhook\n│   ├── resolve_git_conflicts/SKILL.md        # /9ai.git-conflict\n│   ├── generate_user_guide/SKILL.md          # /9ai.tutorial\n│   ├── apply_skill_format/SKILL.md           # /9ai.skill-format\n│   ├── record_release_notes/SKILL.md         # /9ai.git-release\n│   ├── generate_project_context/SKILL.md     # /9ai.context\n│   └── audit_repo_security/SKILL.md          # /9ai.repo-security\n├── platforms/chatgpt-custom-gpt-instructions.md\n├── templates/{CLAUDE.md, AGENTS.md}\n├── PLATFORMS.md\n└── bin/cli.js\n```\n\n`init` generates, in your project root:\n\n```\n.claude/commands/9ai.*.md          # 9 real slash commands (autocomplete in the / menu)\n.claude/skills/<kebab-name>/SKILL.md  # 9 model-invoked skills\n.agents/{AGENTS.md, skills.json}   # Antigravity / Codex\nCLAUDE.md                          # fallback mapping table\n```\n\nThose 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.\n\nDirectory 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.\n\n---\n\n## 🔌 Platform Setup\n\n**➡️ Full step-by-step guide: [PLATFORMS.md](PLATFORMS.md)** — covers Claude Code, ChatGPT (Custom GPT), Claude Projects, Antigravity, Codex CLI and Cursor, plus a capability matrix and troubleshooting.\n\nThe short version:\n\n| Platform | Setup | Note |\n|---|---|---|\n| **Claude Code** | `9ai init` | Generates real `/9ai.*` slash commands in `.claude/commands/` **and** auto-invoked skills in `.claude/skills/` |\n| **Codex CLI** | `9ai init` then `cp .agents/AGENTS.md ./AGENTS.md` | Has a terminal — file paths work |\n| **Antigravity** | `9ai init` | Reads `.agents/AGENTS.md`; verify on first install |\n| **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 |\n| **GitHub Copilot** | `@` the `SKILL.md` file in chat | Also `@` the `_shared/fintech_test_standard.md` for the QA skills |\n| **ChatGPT (Custom GPT)** | Paste [`platforms/chatgpt-custom-gpt-instructions.md`](platforms/chatgpt-custom-gpt-instructions.md) into Instructions, upload 5 files as Knowledge | See PLATFORMS.md §3 |\n| **Claude web (Projects)** | Project instructions + upload the same 5 files as Knowledge | See PLATFORMS.md §4 |\n\n⚠️ **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.\n\n---\n\n_Built with ❤️ for 9AI Automation Teams._\n","readmeFilename":"README.md"}