{
  "markdown": "# falsegreen-skill\n\n[![CI](https://github.com/vinicq/falsegreen-skill/actions/workflows/ci.yml/badge.svg)](https://github.com/vinicq/falsegreen-skill/actions/workflows/ci.yml)\n[![npm version](https://img.shields.io/npm/v/falsegreen-skill.svg)](https://www.npmjs.com/package/falsegreen-skill)\n[![Downloads](https://img.shields.io/npm/dm/falsegreen-skill.svg)](https://www.npmjs.com/package/falsegreen-skill)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](CONTRIBUTING.md)\n[![Docs](https://img.shields.io/badge/docs-online-blue.svg)](https://vinicq.github.io/falsegreen-docs/)\n[![HOL Registry trust score](https://img.shields.io/endpoint?url=https%3A%2F%2Fhol.org%2Fapi%2Fregistry%2Fbadges%2Fplugin%3Fslug%3Dvinicq%252Ffalsegreen-skill%26metric%3Dtrust%26label%3Dtrust)](https://hol.org/registry/plugins/vinicq%2Ffalsegreen-skill)\n\n**LLM-based semantic analysis for false-positive test detection.** Companion\nto [falsegreen](https://github.com/vinicq/falsegreen), the Python static\nscanner.\n\nFor Python, this skill applies the complete falsegreen catalog directly - all\nstructural and semantic patterns - via LLM analysis, without requiring the\nstatic scanner to run first. For TypeScript, JavaScript, and Robot Framework it\nis the primary detection tool. It is a superset of the three static scanners\n(falsegreen, falsegreen-js, robotframework-falsegreen) plus semantic patterns only an LLM\ncan detect.\n\n**The falsegreen family** (install the one for your stack):\n\n| Tool | Stack | Install | Package |\n|---|---|---|---|\n| [falsegreen](https://github.com/vinicq/falsegreen) | Python / pytest | `pip install falsegreen` | [PyPI](https://pypi.org/project/falsegreen/) |\n| [falsegreen-js](https://github.com/vinicq/falsegreen-js) | JS / TS | `npm i -D falsegreen-js` (`npx falsegreen-js`) | [npm](https://www.npmjs.com/package/falsegreen-js) |\n| [robotframework-falsegreen](https://github.com/vinicq/robotframework-falsegreen) | Robot Framework | `pip install robotframework-falsegreen` | [PyPI](https://pypi.org/project/robotframework-falsegreen/) |\n| **falsegreen-skill** | semantic LLM pass | `npx falsegreen-skill analyze <path>` | [npm](https://www.npmjs.com/package/falsegreen-skill) |\n\n---\n\n## New here? Start here\n\nThis is an LLM skill that reads your tests and flags the false-green ones: tests\nthat stay green even when the code they cover is wrong. It catches the semantic\ncases the static scanners cannot, because it reads the test as text and works\nout what the test was meant to prove.\n\nA test like this passes forever, no matter what the code does:\n\n```python\n# before - false-green: asserts the mock back to itself\ndef test_discount(mock_rate):\n    mock_rate.return_value = 0.1\n    result = apply_discount(100, mock_rate)\n    assert result == mock_rate.return_value   # passes for ANY result, even a wrong one\n```\n\nThe fix is an independent expected value, one the code did not produce:\n\n```python\n# after - the test can now fail when apply_discount is wrong\ndef test_discount():\n    result = apply_discount(100, rate=0.1)\n    assert result == 90                       # 10% off 100, computed by hand from the spec\n```\n\nThe skill reads the first version and reports it as a J2 finding (the expected\nvalue is borrowed from the code, not from an independent source) with the line,\nthe reason, and a fix hint. Three steps to try it:\n\n1. **Install or enable it** for your host - see [Installation](#installation) below.\n2. **Point it at a test file** - `npx falsegreen-skill analyze tests/test_discount.py`,\n   or, in an editor host, just ask it to \"analyze this test for false-positive smells\".\n3. **Read the finding** - each one names the catalog code, the failed judgment\n   (J1-J6), why the test cannot fail, and how to fix it. See\n   [Quick example](#quick-example).\n\nFor a step-by-step walkthrough of all three modes with runnable examples and\nflow diagrams, read the [user guide](docs/user-guide.md). The full catalog, the\njudgments, and the per-language reference live in the\n[docs site](https://vinicq.github.io/falsegreen-docs/) and in\n[reference.md](reference.md). For a visual architecture overview, host and\nlanguage routing plus the Mode A/B/C flow diagrams, see\n[docs/architecture.md](docs/architecture.md).\n\n---\n\n## Why this exists\n\nA test suite with 100% green tests is not a proof of correctness. It is a\nproof that no test failed - which is a different thing. Tests can pass\npermanently not because the code is right, but because the test never checks\nanything meaningful.\n\nStatic analysis tools catch some of these cases. Linters like ruff or\nflake8-pytest-style catch syntax-level patterns: a bare `assert True`, a\nmissing `assert` call, an unreachable block. Mutation testing tools like\nmutmut probe whether tests actually fail when the code changes. Both\napproaches have limits: linters cannot reason about test intent, and\nmutation testing requires the code to run.\n\nThis skill fills the gap between linters and mutation testing. It reads the\ntest as text, reconstructs the intent, and asks six structural questions about\nwhether the test can actually fail. The questions are derived from the\ntaxonomy of false-positive test patterns collected in\n[CREDITS.md](CREDITS.md).\n\nThe core insight: a test is useful if and only if there exists some incorrect\nimplementation that would cause it to fail. If no such implementation exists,\nbecause the assertion is unreachable, tautological, or verifies the mock\ninstead of the code, the test is structurally green regardless of whether the\nproduction code is correct.\n\n---\n\n## The methodology\n\nOne rule underlies every judgment: a test is useful only if it can fail when\nthe code breaks.\n\nThe six-judgment framework (J1-J6) makes this rule concrete:\n\n| # | Question | Catches |\n|---|---|---|\n| J1 | Does the assertion run? | Dead assertions, vacuous loops, swallowed failures |\n| J2 | Is the expected value from an independent oracle? | Echo mocks, formula re-implementation, spec contradictions |\n| J3 | Is the real unit under test, not a mock of it? | Mock-the-SUT, self-confirming literals |\n| J4 | Does the assertion verify enough? | Truthiness-only, len > 0, repr coupling, broad raises |\n| J5 | Is the test coupled to implementation internals? | Positional mock args, private method testing |\n| J6 | Does the test pass in isolation, without ordering? | Shared mutable state, test-order dependency |\n\nA test is flagged HIGH only when the first failed judgment has no plausible\nlegitimate interpretation. A test is flagged LOW when the smell is likely but\nhas plausible intent. Everything else is PASS.\n\n**Precision over recall.** One wrong flag on a legitimate test costs more\ngoodwill than a missed smell. Exemptions are explicit:\n\n- Semantic case 18 requires a cited independent oracle (spec, docstring, API\n  contract). Without a citation, do not report case 18.\n- Characterization tests - intentionally freezing current behavior - are not\n  false positives.\n- Boolean predicates (`isinstance`, `.exists()`, `.is_dir()`) are not weak assertions.\n- In HTTP/UI layer tests, a truthiness check on a response object means\n  \"the request succeeded\" and is meaningful.\n\nFull protocol: [SKILL.md](SKILL.md).\n\n---\n\n## What it detects\n\n### Python - structural patterns (complete falsegreen catalog)\n\n**Family A - The test never checks anything**\n\n| Code | Pattern | Example |\n|---|---|---|\n| C1 | Assert inside `if`/`for` that may not run | `if items: assert items[0].valid` when `items` can be `[]` |\n| C2 | No assertion at all | test body contains only setup calls |\n| C2b | Calls SUT but discards result | `result = process(x)`, result never asserted |\n| C3 | Assert inside `try` whose `except` swallows it | `except Exception: pass` catches `AssertionError` |\n| C4 | Test function nested inside another function | pytest does not collect inner defs |\n| C4b | Test class with `__init__` | pytest skips classes that have `__init__` |\n| C20 | Assertion after unconditional `return`/`raise` | dead code, never runs |\n| C21 | Every assert is conditional, none runs unconditionally | all asserts inside `if/else` branches |\n| CC | Commented-out assertion | `# assert result == 42` |\n\n**Family B - The check is weak or always true**\n\n| Code | Pattern | Example |\n|---|---|---|\n| C5 | Always-true check | `assert True`, `assert (a, b)` (non-empty tuple) |\n| C6 | Truthiness / `len > 0` / substring in `str()` | `assert result`, `assert len(x) > 0` |\n| C6b | Positional mock arg via computed index | `call_args.args[expected_args.index(\"target\")]` |\n| C7 | Self-comparison | `assert name == name` |\n| C8 | Exact float equality | `assert ratio == 3.14159` |\n| C9 | `pytest.raises` too broad or no `match=` | `with pytest.raises(Exception)` |\n| C11a | Self-confirming literal | `product.price = 100; assert product.price == 100` |\n| C13 | Mock assertion uncalled or misspelled | `mock.assert_called_once` (no parens) |\n| C13b | `@patch` without `autospec=True` | typos in kwargs pass silently |\n| C14 | Golden file written from actual output | first run records any output as truth |\n| C16 | Depends on wall clock, random, or `sleep` | `datetime.now()` unfrozen, `time.sleep()` |\n| C18 | `str()`/`repr()` comparison | `assert str(user) == \"User(Alice, 30)\"` |\n| C25 | `@pytest.mark.xfail` without `strict=True` | XPASS silently accepted |\n| C34 | Suboptimal assertion form | `== True`, `== None`, `not x in y`, `len == 0` |\n\n**Family C - The test checks its own setup**\n\n| Code | Pattern | Example |\n|---|---|---|\n| C19 | `pytest.raises` wraps multiple calls | setup call inside raises block may be the one that raises |\n| C28 | `pytest.raises` binding variable never read | `as exc:` but `exc` never asserted |\n| C29 | `os.environ` mutated directly | `os.environ[\"KEY\"] = \"x\"` without `monkeypatch` |\n\n**Family D - Green depends on outside factors**\n\n| Code | Pattern | Example |\n|---|---|---|\n| C17 | `pytest.skip()` inside broad `except` | assertion failure silently becomes a skip |\n| C23 | Hard-coded absolute or home-relative path | `/home/user/data.csv` |\n| C24 | Module-level mutable state shared between tests | `_cache = {}` at module scope |\n| C27 | `try/except/pass` instead of `pytest.raises` | both raise and no-raise leave test green |\n| C30 | `responses.add()` without activating interceptor | real HTTP goes through |\n| C31 | `capsys.readouterr()` result discarded | captured output never asserted |\n| C32 | `@pytest.mark.skip` without `reason=` | forgotten skip |\n| C35 | `@pytest.mark.flaky` / retry decorator | masks non-determinism |\n\n**Family E - The test checks the wrong thing**\n\n| Code | Pattern | Example |\n|---|---|---|\n| C33 | sklearn/ML metric computed but not asserted | `accuracy_score(y, y_hat)` result discarded |\n| C36 | `pytest.fail()` without reason | CI shows only `FAILED`, no context |\n| C37 | Duplicate case in `@pytest.mark.parametrize` | same `(a, b, expected)` tuple appears twice |\n\n### Semantic patterns (all three languages)\n\nSemantic patterns require LLM judgment - no static rule can detect them.\n\n| Case | Pattern |\n|---|---|\n| 10 | Patches the unit under test (not a dependency) |\n| 11 | Asserts the value fed to the mock (echo) |\n| 12 | Re-implements the production formula as the expected value |\n| 15 | Passes only when another test has already run |\n| 18 | Expected value contradicts the spec (freezes a bug as correct) |\n\nThe tables above are the most common Python and semantic patterns, not the whole catalog.\nThe full set is **125 codes**: the Python `C*` series (up to C59), the TS/JS `JS*` series\n(up to JS31), the Robot `R*` series (up to R8b), the project-layer `PL*` and diagnostic\n`D*`/`M*` codes, and the semantic `S1`-`S18` and `S21` series. Each carries a bad-pattern example and\na clean look-alike in [reference.md](reference.md), the canonical catalog.\n\n---\n\n## Diagnostic and coupling codes (opt-in)\n\nThese codes do not create false positives, but they reduce observability and\nmake failures harder to diagnose. They are OFF by default and can be enabled\nper code in `.falsegreen.toml`:\n\n```toml\n[tool.falsegreen]\nseverity = { D1 = \"info\", D3 = \"info\", D4 = \"info\", D5 = \"info\", D6 = \"info\", M2 = \"info\" }\n```\n\n| Code | Pattern | Why it matters |\n|---|---|---|\n| D1 | Assertion Roulette: 2+ asserts without messages | CI output says only the line number, hard to triage |\n| D3 | Duplicate Assert: exact same assertion written twice | second assertion adds nothing |\n| D4 | Unnamed Parametrize: 3+ cases, no `ids=` | CI shows `test[0]`, `test[1]`, unreadable failure reports |\n| D5 | Inline Setup Excess: 5+ setup statements before first assert | test should be split or setup moved to a fixture |\n| D6 | Debug Print: `print()` or `pprint()` in test body | suppressed by default, often a forgotten debug statement |\n| M2 | Long Test Method: test body over 50 lines | trying to verify too many concerns at once |\n\n---\n\n## What we don't flag (and why)\n\nMeasured against the [Open Catalog of Test Smells](https://test-smell-catalog.readthedocs.io/) (517 documented smells), only the false-green slice is in scope. The skill is the broadest of the family - it reads intent - but it is still false-green only. These stay out, on purpose:\n\n- **Brittleness / false-red** (a test that breaks without a real bug): sensitive equality, brittle or fragile assertions. The opposite axis.\n- **Hygiene / maintainability**: assertion roulette, magic numbers, long tests. Linter territory (ruff/ESLint/Robocop); a few are surfaced here as opt-in diagnostics.\n- **Slow, design, naming, duplication, runtime/culture**: none are about whether the test protects.\n\nThe skill carries every structural proxy of the scanners (`C16` for uncontrolled time, `C23` for hard-coded paths, `C24`/`C15` for shared state) plus the semantic patterns no parser sees: negative-only security assertions (`S11`), patching the unit under test (`S12`), and order-dependence across files (`S13`). See [CREDITS.md](CREDITS.md) for the full cross-walk against the literature.\n\n---\n\n## How it compares\n\n**vs. ruff / flake8-pytest-style**\n\nRuff and flake8-pytest-style catch syntax-level patterns: `assert True`,\n`pytest.raises` with no type, magic values in assertions. They are fast and\nprecise for the patterns they cover - about 8-10 of the 37+ cases in the\nfalsegreen catalog.\n\nThis skill covers all 37+ structural codes and the 5 semantic cases that\nrequire reading the test as a whole - echo mocks, formula re-implementation,\nspec contradictions. The two tools are complementary: run the linter for\ninstant feedback on simple cases, run the skill for semantic judgment on the\nrest.\n\n**vs. PyNose / pytest-smell**\n\nPyNose and pytest-smell are the closest research counterparts. Both apply the\nclassic Palomba 2018 test-smell taxonomy (Assertion Roulette, Duplicate\nAssert, General Fixture, etc.). The falsegreen taxonomy is narrower: it\nfocuses only on patterns that create false-positive green tests, not on\nmaintainability smells in general.\n\nWhere there is overlap (Assertion Roulette = D1, Duplicate Assert = D3),\nfalsegreen flags them as diagnostic codes - informational, not blocking.\nThe structural codes unique to falsegreen, 56 of them, cover patterns that\nPalomba's taxonomy does not address because they were derived specifically\nfrom studying how green tests hide broken code in CI.\n\n**vs. mutmut / cosmic-ray**\n\nMutation testing answers the question definitively: change the code, does the\ntest fail? That is the ground truth. Mutmut and cosmic-ray are accurate for\nthe programs they can run, but they require an executable environment, a full\ntest suite, and minutes to hours per run.\n\nThis skill is a static pre-flight check. It cannot prove that a test fails\nwhen the code changes - that is mutation testing's job. It can identify, in\nseconds, tests that are structurally unable to fail: assertions that never\nexecute, checks that are always true by construction, mocks that intercept\nthe function being tested. Think of the skill as a fast filter before the\nmutation testing pass.\n\n---\n\n## How to use\n\n## Installation\n\n| Platform | How |\n|---|---|\n| Claude Code | `/plugin marketplace add vinicq/falsegreen-skill` then `/plugin install falsegreen-skill@falsegreen` |\n| Claude.ai / Anthropic API Skills | `npm run build:targets`, then package `dist/claude-agent-skill/` as the standalone skill |\n| OpenAI Codex CLI | No single-command install: clone the repo and run `codex` for the full protocol (scoped to the clone), or copy `AGENTS.md` into your own project / `~/.codex/AGENTS.md` for compact review (see [`contexts/codex.md`](contexts/codex.md)) |\n| Antigravity CLI (`agy`) | Install as a plugin: `agy plugin install https://github.com/vinicq/falsegreen-skill` (subpath `.antigravity-plugin/`), or open the repo and `agy` discovers the workspace skill at `.agents/skills/falsegreen-skill/SKILL.md`. From Gemini CLI: `agy plugin import gemini` |\n| Gemini Agent Skill | workspace skill at `.agents/skills/falsegreen-skill/SKILL.md`, or `npm run build:targets` for `dist/gemini-skill/` |\n| Cursor | Copy contents of `contexts/cursor.md` to `.cursor/rules/falsegreen-skill.mdc` |\n| CLI | `npx falsegreen-skill analyze tests/test_example.py`, see [docs/cli.md](docs/cli.md) |\n| API | Use the defined provider guides in `contexts/claude.md`, `contexts/codex.md`, and `contexts/gemini.md` |\n\n### Skill or static scanner?\n\nUse the static scanner (`falsegreen` for Python, `falsegreen-js`, `robotframework-falsegreen`)\nfor fast, deterministic checks in CI and pre-commit: it proves what a parser can\nsee and never needs an API key. Use this skill for the semantic cases a parser\ncannot reach - a mock standing in for the unit under test, an expected value\ncopied from the code, a value that contradicts the spec. The skill is a superset:\nit carries every structural code of the three scanners plus the AI-only semantic\npatterns. A common setup runs the scanner on every commit and the skill on the\nfiles the scanner cannot fully judge.\n\n### Quick example\n\nGiven this test that echoes the mock back to itself:\n\n```python\n# tests/test_tax.py\ndef test_calculate_tax(mock_calc):\n    mock_calc.return_value = 0.15\n    result = calculate_tax(100, mock_calc)\n    assert result == mock_calc.return_value  # J2: asserting the mock, not behavior\n```\n\n```bash\nexport ANTHROPIC_API_KEY=sk-ant-...\nnpx falsegreen-skill analyze tests/test_tax.py\n```\n\nOutput:\n\n```\nCASE 11 (J2) - HIGH - Python - spec\n\nTest: test_calculate_tax (line 3-6)\nFinding: The assertion checks mock_calc.return_value - the same value the\nmock was configured to return. This passes for any return value, including\nwrong ones.\nEvidence:\n  mock_calc.return_value = 0.15\n  assert result == mock_calc.return_value\nFix hint: Assert against an independently computed expected value, e.g.\nassert result == 15.0 for a 15% tax on 100.\n\nSUMMARY\nTests reviewed: 1\nFindings: 1 (1 high, 0 low)\nClean: 0\n```\n\n### Try it on your test suite\n\nPoint the CLI at any test file or directory:\n\n```bash\n# single file\nnpx falsegreen-skill analyze tests/test_orders.py\n\n# multiple files\nnpx falsegreen-skill analyze tests/test_orders.py tests/test_payments.py\n\n# JSON report for CI, exits 2 if any HIGH finding is present\nnpx falsegreen-skill analyze tests/test_orders.py --json --fail-on-high\n\n# deep analysis with a stronger model\nnpx falsegreen-skill analyze tests/test_orders.py --model claude-opus-4-8\n\n# lower temperature for more deterministic output (default is already 0.2)\nnpx falsegreen-skill analyze tests/test_orders.py --temperature 0.0\n```\n\nThe skill identifies the language from the file extension. TypeScript and JavaScript work the same way - no extra flags needed.\n\nFull flag reference: [docs/cli.md](docs/cli.md).\n\n---\n\n### Propose a fix and prove it (AI-fix mode, V1)\n\n`analyze` finds a false-green; `fix` proposes a stronger test and proves it before you trust it. It is opt-in, Python/pytest only, and propose-only: it prints a test-file patch but never applies it and never edits your production code.\n\n```bash\n# propose a patch for a C2b finding and run the gate against the real SUT\nnpx falsegreen-skill fix tests/test_discount.py --case C2b --line 14 --sut src/discount.py\n\n# parse + preserve only, no mutation gate (no runnable SUT or a quick pass)\nnpx falsegreen-skill fix tests/test_discount.py --case C5 --line 9 --cheap\n\n# machine-readable gate verdict (schema/fix-validation.json)\nnpx falsegreen-skill fix tests/test_discount.py --case C20 --line 22 --sut src/discount.py --json\n```\n\nThe gate runs three checks on a clean replica: the patch parses, it passes `pytest` against the real code, and it **fails** on a line-scoped mutation of the SUT (a built-in operator on the SUT line; full mutmut integration is deferred to a later version). A patch is accepted only when it both passes on correct code and goes red on the mutant, which is what proves the new assertion catches a bug instead of being a fresh tautology. Without `--sut` it degrades to propose-only and says the fix is unvalidated. The honest limit: the gate proves the fix catches the targeted mutant, not every possible bug. JS/TS/Robot and the deep semantic cases are v2.\n\n---\n\n### Author a test from a spec (authoring mode, Mode B)\n\nThe same protocol runs in reverse. Given a spec and the code under test, the skill proposes a\ntest with an **independent** oracle: an expected value derived from the spec, not read back\nfrom the code. Before writing it, an architect/QA gate (**A0**) runs the review judgments and\nthe precision rules over the design, so the generated test is one the review pass would accept\nrather than a fresh false-green.\n\nTwo ways to drive it. In a host (Claude Code, Codex, Gemini, Cursor, plain LLM) ask the skill\nto \"write a test for this function against this spec\" and it elicits the level, language, and\noracle interactively. Or on the CLI, write the answers into a test-spec file\n([`schema/test-spec.json`](schema/test-spec.json)) and render one stack, self-checked:\n\n```bash\n# render the shipped example spec to a Python test, then run Mode A on the result\nfalsegreen-skill generate examples/authoring/apply-discount.spec.yaml --lang python\n# other stacks from the same spec: --lang typescript | javascript | robot\n```\n\nThe CLI does not elicit - a spec with no `oracle` is refused, because a test generated from the\ncode's current output only freezes the bug. See [SKILL.md](SKILL.md), [docs/cli.md](docs/cli.md),\nand [docs/decisions/0004-authoring-mode.md](docs/decisions/0004-authoring-mode.md).\n\n---\n\n### Claude Code (primary path)\n\nAdd the marketplace and install the plugin:\n\n```\n/plugin marketplace add vinicq/falsegreen-skill\n/plugin install falsegreen-skill@falsegreen\n```\n\nThen invoke the skill with `/falsegreen-skill:falsegreen-skill`, or just attach a\ntest file and ask for false-positive analysis - the skill triggers on intent.\nThe skill identifies the language and framework, classifies the test intent,\napplies the six-judgment protocol, and reports findings with case numbers,\nconfidence levels, and fix hints.\n\nFor Python, the skill applies the full pattern catalog directly. Optionally,\nrun the static scanner first to speed up batch analysis:\n\n```bash\npip install falsegreen\nfalsegreen tests/\n```\n\nIf you provide the scanner output, the skill uses it as the structural pass\nand applies semantic judgment on top. Without it, the skill runs everything.\n\n### Defined API providers\n\nThis skill is not tied to Claude. The maintained provider paths are Anthropic,\nOpenAI/Codex, Google Gemini, and the configured CLI providers listed in\n`providers.md`.\n\nSee [providers.md](providers.md) for per-provider invocation code and Cursor setup.\n\n### Cursor\n\nAdd `.cursor/rules/falsegreen-skill.mdc` to your project (template in\n[providers.md](providers.md)). Open a test file, ask Cursor to analyze it for\nfalse-positive smells, and the J1-J6 protocol runs automatically.\n\n---\n\n## Supported languages and frameworks\n\n| Language | Frameworks |\n|---|---|\n| Python | pytest, unittest |\n| TypeScript | Jest, Vitest, Mocha + Chai, React Testing Library, Vue Test Utils, Angular TestBed |\n| JavaScript | Jest, Vitest, Mocha + Chai, Jasmine, React Testing Library |\n| Robot Framework | BuiltIn, Collections, SeleniumLibrary, Browser, RequestsLibrary, RESTinstance, DatabaseLibrary, AppiumLibrary |\n\nGherkin/BDD (Cucumber.js, behave, pytest-bdd) and Tavern are covered as secondary\nsemantic passes in [reference.md](reference.md).\n\nFrontend component tests - React, Vue, Angular, Svelte - use the same J1-J6\nframework as backend tests. The structural failures are identical: a J4 weak\nassertion on a rendered component is the same smell as a J4 on a service\nmethod. See the family-based examples under `examples/typescript/` (for instance\n`family_a_never_checks.ts`, which carries the Testing Library patterns) for annotated cases.\n\n### Test levels (the pyramid)\n\nThe skill detects the test level and reads the oracle in light of it, the step the static\nscanners cannot fully do. The level changes what counts as a valid check:\n\n- **Unit:** a function or component with its boundaries doubled. A real assertion on the\n  return value is the oracle.\n- **Integration (API and database):** API tests (supertest, `httpx`, a framework TestClient,\n  Tavern) and database tests against a real datastore. The response or the row IS the\n  verification at this level, so the skill does not flag it as a weak check.\n- **E2E:** Cypress, Playwright, Selenium, Robot Browser. The presence of a rendered element\n  or a page state is a real check here.\n\nThe level itself is part of the judgment: a real API or database call inside a test that\nclaims to be a unit test is a smell (over-mocking inverted, mystery guest), and the skill\nsays so rather than accepting the level at face value.\n\n### Patterns by test level and scope\n\nThe same false-green shape is classified by the level the test runs at: the level is a\nper-finding axis (J3), read as unit, integration, or E2E. As the superset of the three\nscanners, the skill covers every level and every language, plus the semantic `S1`-`S18` and `S21`\npatterns no parser sees. The clusters at each level:\n\n- **Unit:** always-true and self-compare (`C5`/`C7`/`JS30`), no oracle (`C2`/`C2b`), asserts its own double (`JS8`/`JS27`/`C13b`/`S8`), and the semantic `S1`/`S5` (intent mismatch, tests the framework).\n- **Integration:** request oracle off (`C9b`), captured log never asserted (`C50`), patching the edge wrong (`S12`/`S18`).\n- **E2E:** sleep as synchronization (`C16`), forced green in Robot (`R1`/`R2`/`R4`/`R6`), and the semantic `S1`/`S2` (intent mismatch, irrelevant oracle).\n\nFull matrix on the docs site: [patterns by test level](https://vinicq.github.io/falsegreen-docs/concepts/by-test-level/) and [what we do not flag](https://vinicq.github.io/falsegreen-docs/concepts/what-we-do-not-flag/).\n\n---\n\n## Project layout\n\n```\nfalsegreen-skill/\n  SKILL.md              the skill protocol (language and LLM agnostic)\n  AGENTS.md             Codex + Antigravity CLI rule file (auto-parsed at workspace root)\n  GEMINI.md             Antigravity CLI rule file (auto-parsed) + legacy Gemini CLI contextFileName / import source\n  llm.md                self-contained prompt context used by CLI/API examples\n  reference.md          per-language case catalog and framework cues\n  providers.md          multi-LLM invocation guide (API snippets)\n  CREDITS.md            the research this skill builds on\n  gemini-extension.json legacy Gemini CLI manifest (source for `agy plugin import gemini`)\n  .antigravity-plugin/  Antigravity CLI (`agy`) plugin manifest + skill (`agy plugin install`)\n  .agents/skills/       Antigravity CLI (`agy`) workspace Agent Skill entry point\n  .gemini/              legacy Gemini Agent Skill entry point\n  .claude-plugin/       Claude Code plugin manifest + marketplace catalog\n  .codex-plugin/        Codex CLI plugin manifest\n  .agents/plugins/      Codex CLI marketplace catalog\n  skills/\n    falsegreen-skill/   shared skill entry point (Claude Code + Codex plugins)\n  bin/\n    falsegreen-llm.js   zero-dependency CLI (npx falsegreen-skill)\n  scripts/\n    validate-package.mjs validate manifests, frontmatter, and schema naming\n    build-targets.mjs    generate standalone Claude/Gemini skill packages\n  docs/\n    architecture.md     architecture overview + Mermaid flow diagrams\n    cli.md              CLI usage guide\n    packaging.md        target packaging and release checklist\n  schema/\n    finding.json        JSON Schema for a single finding\n    report.json         JSON Schema for a full report\n  contexts/             ready-to-use context files per platform\n    claude.md           Claude Code CLI, Claude.ai, Anthropic API\n    codex.md            ChatGPT, OpenAI API, structured output, batch\n    gemini.md           Google AI Studio, Gemini API, long context\n    cursor.md           Cursor IDE, full .cursor/rules/ MDC template\n  examples/\n    python/\n      family_a_never_checks.py       C1, C2, C2b, C3, C4, C4b, C20, C21, CC\n      family_b_weak_always_true.py   C5, C6, C6b, C7, C8, C9, C11a, C13, C13b, C14, C16, C18, C25, C34\n      family_c_checks_own_setup.py   C19, C28, C29\n      family_d_external_state.py     C17, C23, C24, C27, C30, C31, C32, C35\n      family_e_wrong_thing.py        C33, C36, C37\n      semantic_cases.py              cases 10, 11, 12, 15, 18 (LLM-only)\n      diagnostic_codes.py            D1, D3, D4, D5, D6, M2 (opt-in)\n    typescript/\n    javascript/\n```\n\n---\n\n---\n\n## Setup and usage reference\n\nEverything above is the tour. This section is the complete reference: every\ninstall mode, every CLI flag, every provider, and every host, with copy-paste\nblocks. Commands and flags here are taken from `bin/falsegreen-llm.js --help`\nand the host manifests, so they match the shipped 0.6.x line.\n\n### 1. Install the CLI\n\nThe CLI is a zero-dependency Node script. It needs **Node 18 or newer** (the\n`engines` floor in `package.json`; it relies on the built-in `fetch`).\n\n```bash\n# run once, no install\nnpx falsegreen-skill analyze tests/test_payment.py\n\n# install globally, then call `falsegreen-skill` anywhere\nnpm install -g falsegreen-skill\nfalsegreen-skill analyze tests/test_payment.py\n\n# pin it as a dev dependency in a repo\nnpm install -D falsegreen-skill\nnpx falsegreen-skill analyze tests/test_payment.py\n```\n\n`falsegreen-skill --version` prints the installed version; `falsegreen-skill --help`\nprints the full command and flag list.\n\n### 2. `analyze` - review test files\n\n```\nfalsegreen-skill analyze <file...> [options]\n```\n\nEach file is sent to the provider in its own request. Plain-text output is\nprinted under a `=== {filename} ===` header per file. With `--json`, each\nresponse is validated against `schema/report.json` and the CLI emits one\naggregate JSON report.\n\n**Full flag reference** (from `--help`):\n\n| Flag | Meaning | Default |\n|---|---|---|\n| `--provider <name>` | `anthropic`, `openai`, `gemini`, or `openai-compatible` | `anthropic` |\n| `--model <model>` | Override the provider default. Required for `openai-compatible` | per provider (below) |\n| `--base-url <url>` | API base URL. Required for `openai-compatible` | none |\n| `--json` | Validate and output JSON conforming to `schema/report.json` | off |\n| `--conventions <file>` | Conventions YAML/text injected per SKILL.md Step 0 | none |\n| `--temperature <n>` | Sampling temperature 0.0-1.0. Omitted automatically for OpenAI o-series | `0.2` |\n| `--max-tokens <n>` | Max output tokens per request | `4096` |\n| `--fail-on-high` | Exit 2 when any HIGH finding is present. Requires `--json` | off |\n\nDefault models per provider: `anthropic` -> `claude-sonnet-5`,\n`openai` -> `gpt-5`, `gemini` -> `gemini-2.5-flash`. The `openai-compatible`\nprovider has no default model, so `--model` and `--base-url` are both required.\n\n**Exit codes:**\n\n| Code | Meaning |\n|---|---|\n| 0 | Analysis completed (findings may still exist; analyze is not a gate by itself) |\n| 1 | Error: missing file, missing API key, bad flag, invalid JSON, schema mismatch, non-2xx API response |\n| 2 | `--fail-on-high` was set and the JSON report contains at least one HIGH finding |\n\n**Environment variables** (one per provider, read from the environment):\n\n| Variable | Used by |\n|---|---|\n| `ANTHROPIC_API_KEY` | `--provider anthropic` |\n| `OPENAI_API_KEY` | `--provider openai`, and fallback for `openai-compatible` |\n| `GEMINI_API_KEY` | `--provider gemini` |\n| `FALSEGREEN_API_KEY` | `--provider openai-compatible` (takes precedence over `OPENAI_API_KEY`) |\n\n#### One example per provider\n\n```bash\n# Anthropic (default provider)\nexport ANTHROPIC_API_KEY=sk-ant-...\nfalsegreen-skill analyze tests/test_payment.py\nfalsegreen-skill analyze tests/test_payment.py --model claude-opus-4-8   # deep case 18\n\n# OpenAI\nexport OPENAI_API_KEY=sk-...\nfalsegreen-skill analyze tests/test_payment.py --provider openai\nfalsegreen-skill analyze tests/test_payment.py --provider openai --model o3   # reasoning, temperature auto-omitted\n\n# Google Gemini\nexport GEMINI_API_KEY=...\nfalsegreen-skill analyze tests/test_payment.py --provider gemini\n```\n\n#### openai-compatible: any provider that speaks the OpenAI Chat API\n\nSet `FALSEGREEN_API_KEY` to the provider key, point `--base-url` at the\n`/v1` root, and pass the provider's model id. The CLI appends\n`/chat/completions` for you.\n\n```bash\n# Groq\nexport FALSEGREEN_API_KEY=gsk_...\nfalsegreen-skill analyze tests/test_payment.py \\\n  --provider openai-compatible \\\n  --base-url https://api.groq.com/openai/v1 \\\n  --model llama-3.3-70b-versatile\n\n# Nvidia NIM (OpenAI-compatible endpoint)\nexport FALSEGREEN_API_KEY=nvapi-...\nfalsegreen-skill analyze tests/test_payment.py --json \\\n  --provider openai-compatible \\\n  --base-url https://integrate.api.nvidia.com/v1 \\\n  --model qwen/qwen3.5-397b-a17b \\\n  --max-tokens 8192\n\n# Fireworks\nexport FALSEGREEN_API_KEY=fw_...\nfalsegreen-skill analyze tests/test_payment.py --json \\\n  --provider openai-compatible \\\n  --base-url https://api.fireworks.ai/inference/v1 \\\n  --model accounts/fireworks/routers/kimi-k2p6-turbo \\\n  --max-tokens 8192\n\n# Ollama (local - no key needed, any placeholder works)\nexport FALSEGREEN_API_KEY=ollama\nfalsegreen-skill analyze tests/test_payment.py \\\n  --provider openai-compatible \\\n  --base-url http://localhost:11434/v1 \\\n  --model qwen2.5-coder:32b\n\n# Alibaba Qwen (DashScope, OpenAI-compatible mode)\nexport FALSEGREEN_API_KEY=sk-...\nfalsegreen-skill analyze tests/test_payment.py \\\n  --provider openai-compatible \\\n  --base-url https://dashscope-intl.aliyuncs.com/compatible-mode/v1 \\\n  --model qwen-plus\n```\n\n> **Prompt size vs. free tiers.** The system prompt carries the full catalog\n> (`llm.md` + `reference.md`), ~33k tokens. Providers with a small per-minute\n> token cap on their free tier (e.g. Groq's 12k TPM) reject the request with\n> HTTP 413/429. Use a provider whose free or paid tier allows a ~35k-token\n> request (Ollama locally, or a large-context model on OpenRouter/NVIDIA/etc.),\n> and raise `--max-tokens` if a reasoning model gets cut off mid-report.\n\nSet `--model` to the id your account actually exposes; the CLI passes the\nstring through unchanged. Reasoning models work with `--json` as of 0.5.2:\nthe CLI requests native JSON output, strips `<think>`/`<reasoning>` blocks,\nand recovers a slashed-key form (`/findings`) some schema-guided decoders\nemit. Verbose reasoners spend their output budget on chain-of-thought and can\nget cut off mid-JSON; if that happens the CLI says so and points at\n`--max-tokens` - raise it (8192 or higher) and retry.\n\n### 3. `fix` - propose a stronger test and prove it (mutation gate)\n\n```\nfalsegreen-skill fix <test-file> --case <code> --line <n> [options]\n```\n\n`analyze` finds a false-green; `fix` proposes a stronger test and runs a local\ngate to prove it before you trust it. It is opt-in, **Python/pytest only**, and\n**propose-only**: it prints a test-file patch but never applies it and never\nedits production code.\n\n**fix flags** (in addition to the provider flags above):\n\n| Flag | Meaning |\n|---|---|\n| `--case <code>` | Catalog code of the finding to fix. V1 fixable set: `C2b`, `C20`, `C21`, `C5`, `C7` |\n| `--line <n>` | Line of the finding in the test file (1-indexed) |\n| `--sut <file>` | Production file the test protects. Required for a validated fix |\n| `--sut-line <n>` | Line in the SUT to mutate. Defaults to `--line` |\n| `--cheap` | Validation tier: parse + preserve only, no mutation gate |\n\n```bash\n# propose a patch for a C2b finding and run the full gate against the real SUT\nfalsegreen-skill fix tests/test_discount.py --case C2b --line 14 \\\n  --sut src/discount.py --sut-line 12\n\n# parse + preserve only, no mutation gate (no runnable SUT, or a quick pass)\nfalsegreen-skill fix tests/test_discount.py --case C5 --line 9 --cheap\n\n# machine-readable gate verdict (schema/fix-validation.json)\nfalsegreen-skill fix tests/test_discount.py --case C20 --line 22 \\\n  --sut src/discount.py --json\n```\n\n**What the gate proves.** On a clean replica it runs three checks: the patch\nparses (`py_compile`), it passes `pytest` against the real code (preserve), and\nit **fails** on a line-scoped mutation of the SUT (a built-in operator flipped\non the SUT line). A patch is **accepted** only when it passes on correct code\nAND goes red on the mutant, which is what shows the new assertion catches a bug\ninstead of being a fresh tautology. The exit code is 0 on accept, 1 on\nreject/unvalidated, so CI can branch on it.\n\n**The honest limit.** Without `--sut` (or with `--cheap`) the gate degrades to\npropose-only and labels the fix unvalidated. Even with the gate, it proves the\nfix catches the targeted mutant, not every possible bug; full mutmut\nintegration and the deep semantic cases (10/11/12/18) and JS/TS/Robot fix\npaths are deferred to a later version.\n\n### 4. `generate` - author a test from a spec (Mode B)\n\n```\nfalsegreen-skill generate <spec-file> [--lang <language>] [options]\n```\n\nRenders a language-neutral test-spec into a real test, then runs `analyze`\n(Mode A) on the result, so a false-green test cannot pass the self-check\nundetected. It catches false-green *shapes*; it does not, and cannot on its own,\ntell a hand-written wrong oracle from a right one (see the honest limit below).\nThe spec is a [`schema/test-spec.json`](schema/test-spec.json) file (YAML or\nJSON); see [`examples/authoring/`](examples/authoring/) for one spec rendered\ninto all four stacks. If `--lang` is omitted, the spec's first declared\n`languages` entry is used, else Python.\n\n**generate flags** (in addition to the provider flags above):\n\n| Flag | Meaning |\n|---|---|\n| `--lang <language>` | Target stack: `python`, `typescript`, `javascript`, `tsx`, `jsx`, `robot`. `tsx`/`jsx` cover the React side of the JS/TS family (same JS* catalog). One language per run |\n\n```bash\n# render the example spec to a Python test and self-check it\nfalsegreen-skill generate examples/authoring/apply-discount.spec.yaml --lang python\n\n# same spec, TypeScript; the spec is the single source, re-run per stack\nfalsegreen-skill generate examples/authoring/apply-discount.spec.yaml --lang typescript\n\n# machine-readable: { language, test, self_check, self_check_passed, self_check_error }\nfalsegreen-skill generate my-spec.yaml --lang python --json\n```\n\n**The oracle is mandatory.** A spec with no `oracle.expected` key is refused\nbefore any API call: a test generated from the code's current output only freezes\nthe bug (a characterization test). The oracle's *value* is not checked; that is\nyour responsibility. What the command proves is narrower: the generated test\ntrips no HIGH false-green finding when Mode A reviews it.\n\n**The self-check is bounded and fails closed.** After generating, the CLI runs\nMode A on the test once, and if it trips a HIGH false-green finding, revises once\nand re-checks. The exit code is the CI contract:\n\n| Exit | Meaning |\n|---|---|\n| 0 | PASSED: the self-check ran and found no HIGH false-green |\n| 1 | FAILED: a surviving false-green was confirmed (also used for a bad spec or an API error) |\n| 3 | UNVERIFIED: the self-check could not run (small model, provider error). The test is still printed, but it is **not** accepted, so a pipeline never treats an unchecked test as clean |\n\nThe self-check is a same-model static review, not an execution: it does not run\nthe test, confirm it compiles or imports, or verify the oracle value. A\ncharacterization test with a code-derived expected can still pass. Review the\noutput against your spec.\n\n### 5. Host setup\n\nEach host enables the same J1-J6 protocol; the wiring differs. Steps below come\nstraight from the manifests (`.claude-plugin/plugin.json`,\n`.codex-plugin/plugin.json`, `gemini-extension.json`) and the `contexts/` guides.\n\n#### Claude Code\n\nAdd the marketplace, then install the plugin:\n\n```\n/plugin marketplace add vinicq/falsegreen-skill\n/plugin install falsegreen-skill@falsegreen\n```\n\nAfter install the skill is the namespaced command\n`/falsegreen-skill:falsegreen-skill`, and it also triggers on natural-language\nintent (\"analyze this test for false-positive smells\"). Claude Code discovers\ntest files with its own Glob/Read tools, so you can point it at a directory.\nFull guide: [`contexts/claude.md`](contexts/claude.md).\n\n#### OpenAI Codex CLI\n\nCodex has no single-command install for this repo. Clone it and start Codex for\nthe full protocol - `AGENTS.md` at the root auto-loads as project context and\nevery relative reference resolves:\n\n```bash\ngit clone https://github.com/vinicq/falsegreen-skill\ncd falsegreen-skill\ncodex\n```\n\nThe protocol is scoped to that directory. To run it in your own project instead,\ncopy `AGENTS.md` into your project (or `~/.codex/AGENTS.md` to load it\neverywhere); that gives the compact routine protocol, and for deep look-alike\nchecks you also bring `reference.md`/`SKILL.md` or work from the clone.\n\nThe plugin manifest is `.codex-plugin/plugin.json`, the marketplace catalog\n`.agents/plugins/marketplace.json`, the shared skill\n`skills/falsegreen-skill/SKILL.md`. Codex has plugin subcommands, but this\nrepo-is-the-plugin catalog uses a repo-root source that Codex's marketplace\nresolver does not accept, so the two paths above are the supported ones (details\nin [`contexts/codex.md`](contexts/codex.md)). Codex has a ~32 KiB context\nbudget; load `AGENTS.md` eagerly (it carries the compact protocol) and pull\n`reference.md` or `SKILL.md` on demand. Full guide:\n[`contexts/codex.md`](contexts/codex.md).\n\n#### Antigravity CLI (`agy`)\n\nAntigravity is Google's successor to the discontinued Gemini CLI. There are\nthree ways to enable it.\n\nInstall it as a plugin (the `.antigravity-plugin/` bundle stages into\n`~/.gemini/antigravity-cli/plugins/`):\n\n```bash\nagy plugin install https://github.com/vinicq/falsegreen-skill\n```\n\nOr run `agy` inside the repo with no install: it discovers the workspace Agent\nSkill at `.agents/skills/falsegreen-skill/SKILL.md` and parses `AGENTS.md` /\n`GEMINI.md` at the root as codebase rule files on startup. Either way the skill\nis the `/falsegreen-skill` slash command; invoke it or ask in natural language,\nfor example \"analyze tests/ for false-positive smells\".\n\nFor a self-contained plugin (no repo checkout), run `npm run build:targets` and\ninstall `dist/antigravity-plugin/`. If you still have the old Gemini CLI\nextension installed, migrate it with `agy plugin import gemini`, which converts\nthe legacy `gemini-extension.json` + `GEMINI.md` plugin. Full guide:\n[`contexts/gemini.md`](contexts/gemini.md).\n\n#### Cursor\n\nCursor has no plugin install; it loads project rules. Copy the full MDC\ntemplate from [`contexts/cursor.md`](contexts/cursor.md) into\n`.cursor/rules/falsegreen-skill.mdc`:\n\n```\n.cursor/\n  rules/\n    falsegreen-skill.mdc\n```\n\nThe frontmatter globs (`**/test_*.py`, `**/*.test.ts`, `**/*.spec.tsx`,\n`**/*.robot`, ...) activate the rule when you open a matching test file. Then\nin Cursor Chat ask \"analyze this file for false-positive test smells using\nfalsegreen-skill\". `@file` mentions and Composer batch runs work the same way.\n\n#### Plain LLM / raw API\n\nNo host needed: paste `SKILL.md` as the system prompt (or first message for\nreasoning models that reject a system role) and the test file as the user\nmessage. The full per-language catalog lives in `reference.md` - append it when\nyou need the JS/Robot codes or the look-alike exemptions, since `SKILL.md`\ninlines only the Python catalog. Per-provider SDK snippets (Anthropic, OpenAI,\nGemini, Groq, Qwen via OpenRouter, Kimi) and the case 18 two-pass finder/refuter\nprocedure are in [`providers.md`](providers.md).\n\n### 5. Configuration\n\n**Conventions file (Step 0).** Declare project-specific context - custom\nassertion helpers, layer overrides, excluded codes - so the skill folds them in\nbefore judging. Pass it with `--conventions <file>`:\n\n```yaml\nconventions:\n  custom_assertion_helpers:\n    - conftest.assert_model_valid()\n  test_layer_overrides:\n    - tests/integration/ is web-layer   # apply the C6 HTTP exemption here\n  excluded_codes:\n    - C8                                 # project uses Decimal, not float\n```\n\nThe block extends the look-alike exemptions only; it cannot disable severity.\nHIGH findings that survive the exemptions stay HIGH.\n\n**Model selection.** The CLI ships its own defaults (above). The canonical\ntier-to-model map for reference and host docs is [`models.yaml`](models.yaml):\nthe `structural` tier (C-codes, small models fine), the `semantic` tier\n(cases 10-15, frontier or 70B+), and the `adversarial` tier (case 18, frontier\nwith extended reasoning). Nothing loads `models.yaml` at runtime - it keeps the\nCLI zero-dependency - so it is documentation, validated against providers before\neach release.\n\n**Output schema (J1-J6).** JSON output is governed by two canonical schemas:\n[`schema/report.json`](schema/report.json) (the report: `findings`, `summary`,\n`language`, `framework`, optional `scan_date`) and\n[`schema/finding.json`](schema/finding.json) (each finding: `case`, `judgment`\none of J1-J6, `confidence` HIGH/LOW, `language`, `level` unit/integration/e2e,\n`intent`, `test`, `finding`, `evidence`, optional `oracle`, `fix_hint`). The\n`oracle` field is required only for semantic case 18. The CLI validates every\n`--json` response against these and exits 1 on a mismatch.\n\n**Where the catalog lives.** [`reference.md`](reference.md) is the per-language\ncase catalog with examples and look-alike exemptions; the structural code list\nthe scanners share is also mirrored there. The CLI's own prompt is built from\n`llm.md` plus `reference.md` at runtime.\n\n### 6. Relationship to the static scanners\n\nThis skill is a **superset** of the three static scanners. Each scanner proves\nwhat a parser can see, fast and deterministic, with no API key:\n[falsegreen](https://github.com/vinicq/falsegreen) (Python),\n[falsegreen-js](https://github.com/vinicq/falsegreen-js) (JS/TS),\n[robotframework-falsegreen](https://github.com/vinicq/robotframework-falsegreen)\n(Robot). The skill carries every structural code those scanners emit **plus**\nthe AI-only semantic cases (mock-the-SUT, echo mocks, formula re-implementation,\nspec contradictions) that no parser reaches. A common setup runs a scanner on\nevery commit and the skill on the files the scanner cannot fully judge; for\nPython you can also paste the scanner output to the skill so it skips the\nstructural pass and goes straight to semantic adjudication.\n\nFull catalog, judgments, and per-language reference:\n[docs site](https://vinicq.github.io/falsegreen-docs/) and\n[reference.md](reference.md).\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md). The main contribution paths are\nlanguage-specific patterns and look-alike examples in `reference.md`.\n\nLicense: **MIT**, see [LICENSE](LICENSE).\n\n## Contributors ✨\n\nThanks to the people who keep false-green tests out of real suites ([emoji key](https://allcontributors.org/docs/en/emoji-key)):\n\n<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->\n[![All Contributors](https://img.shields.io/badge/all_contributors-2-orange.svg?style=flat-square)](#contributors-)\n<!-- ALL-CONTRIBUTORS-BADGE:END -->\n\n<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->\n<!-- prettier-ignore-start -->\n<!-- markdownlint-disable -->\n<table>\n  <tbody>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"14.28%\"><a href=\"https://vinicq.github.io/md-bridge/\"><img src=\"https://avatars.githubusercontent.com/u/78210890?v=4?s=100\" width=\"100px;\" alt=\"Vinicius Queiroz\"/><br /><sub><b>Vinicius Queiroz</b></sub></a><br /><a href=\"https://github.com/vinicq/falsegreen-skill/commits?author=vinicq\" title=\"Code\">💻</a> <a href=\"https://github.com/vinicq/falsegreen-skill/commits?author=vinicq\" title=\"Documentation\">📖</a> <a href=\"#ideas-vinicq\" title=\"Ideas, Planning, & Feedback\">🤔</a> <a href=\"#maintenance-vinicq\" title=\"Maintenance\">🚧</a> <a href=\"#infra-vinicq\" title=\"Infrastructure (Hosting, Build-Tools, etc)\">🚇</a> <a href=\"https://github.com/vinicq/falsegreen-skill/commits?author=vinicq\" title=\"Tests\">⚠️</a> <a href=\"#research-vinicq\" title=\"Research\">🔬</a></td>\n      <td align=\"center\" valign=\"top\" width=\"14.28%\"><a href=\"https://github.com/homesellerq-coder\"><img src=\"https://avatars.githubusercontent.com/u/294912019?v=4?s=100\" width=\"100px;\" alt=\"Home Seller\"/><br /><sub><b>Home Seller</b></sub></a><br /><a href=\"https://github.com/vinicq/falsegreen-skill/commits?author=homesellerq-coder\" title=\"Code\">💻</a> <a href=\"https://github.com/vinicq/falsegreen-skill/commits?author=homesellerq-coder\" title=\"Documentation\">📖</a> <a href=\"https://github.com/vinicq/falsegreen-skill/commits?author=homesellerq-coder\" title=\"Tests\">⚠️</a> <a href=\"#infra-homesellerq-coder\" title=\"Infrastructure (Hosting, Build-Tools, etc)\">🚇</a></td>\n    </tr>\n  </tbody>\n</table>\n\n<!-- markdownlint-restore -->\n<!-- prettier-ignore-end -->\n\n<!-- ALL-CONTRIBUTORS-LIST:END -->\n\nNew contributors are added automatically; the table also recognizes non-code work (docs, ideas, infrastructure, tests, research) via the [all-contributors](https://allcontributors.org) spec.\n",
  "bytes": 50160,
  "sha": "3e90ffd4be5e233bc605abb1d8d15e6d90b82975c5fc51de9f2b3992ba4a0408",
  "repo_slug": "vinicq/falsegreen-skill",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/plg_vinicq_falsegreen_skill_9d0b1bef/readme"
}