# _manifest.json

> 88 lines of code and 0 definitions.

Tree: Governance tree
Language: json
Canonical: https://banes-lab.com/anatomy/governance#file-governance-manifest-json
Source text: https://banes-lab.com/source/governance/_manifest.json.txt

Listed in [Governance tree](https://banes-lab.com/api/source/governance.md), after [types](https://banes-lab.com/api/source/governance/types.md) and before [govlab.config.ts](https://banes-lab.com/source/governance/govlab.config.ts.md).

## Source

```json
{
    "label": "Govlab Extension Host",
    "summary": "The consumer-side extension host govlab loads by convention: the local lint rules and the workspace plugins that gate this repo's architecture, the checker-driven codemods that apply the fixes a linter cannot apply safely, and the doc-verb registry govlab.docs reads. Govlab discovers it by directory shape instead of a registration list, so dropping a file in is the whole wiring.",
    "maturity": "stable",
    "domains": [
        {"meta": "developer-tooling",
            "sub": "linting-quality"},
        {"meta": "developer-tooling",
            "sub": "code-generation"}
    ],
    "capabilities": [
        "local-rule-hosting",
        "workspace-plugin-hosting",
        "rule-index-generation",
        "project-scope-guarding",
        "checker-driven-codemods",
        "syntax-verified-rewriting",
        "doc-verb-extension"
    ],
    "overlaps": [],
    "incompatibleWith": [],
    "supersedes": [],
    "governedBy": [
        "type-safety",
        "separation-of-concerns",
        "duplicate-code"
    ],
    "visibility": {"private": true,
        "hidden": false},
    "ecosystem": "typescript",
    "deliverAs": "source",
    "entries": [
        "rules/plugins/*.plugin.ts",
        "rules/entrypoints/*.entrypoint.ts",
        "shared/manifests/*.manifest.ts",
        "codemods/entrypoints/*.entrypoint.ts",
        "codemods/validators/*.validator.ts"
    ],
    "docs": {
        "overview": "Govlab reads every consumer's `.govlab/` by convention, so this directory is wiring-free: a file's location is its registration. `rules/eslint/` holds the local rules. `rules/entrypoints/index.entrypoint.ts` walks it and writes the generated rule index, the exclusion markers and the file budget under `shared/generated/`. `rules/plugins/rule.plugin.ts` wraps each rule once with the `isGovernedFile` guard, which reaches every governed root the taxonomy declares. `rules/entrypoints/writing.entrypoint.ts` renders the writing canon from `shared/manifests/writing.*.manifest.ts` into `.claude/rules/register.md` and checks the canon's records, `CLAUDE.md` and every `_manifest.json` against it. A rule whose meta declares `workspaceWide` sits outside that guard, as does any wrapper file in `rules/eslint/` that default-exports `{ tool, plugins }`. `codemods/` holds the TypeScript-program-driven rewriters: each is an analyzer under `codemods/analyzers/` producing findings with a `reason` plus an entrypoint under `codemods/entrypoints/` that applies only what the checker proves safe. `codemods/validators/` holds the whole-program checks the gate runs, such as field reach and closed values. `shared/` holds the seams the rules compose: selectors over the syntax tree, the listener factory, the anchor resolver, the manifests, the allowlists and the exclusions. `types/` is the host's flat type bucket.",
        "whenToUse": [
            "Adding a rule that governs the governed roots. The rule is a file in `rules/eslint/`, and the index is regenerated after it lands.",
            "Adding a rule that governs the whole workspace. The rule is a file in `rules/eslint/` exporting `{ tool, plugins }`, named explicitly in the quality config.",
            "Replacing a linter's unsafe auto-fixer. The replacement is an analyzer plus an entrypoint under `codemods/`, which verifies its own output before writing.",
            "Changing how a string is written. The rules are records in `shared/manifests/writing.*.manifest.ts`, and the writing entry point renders them again."
        ],
        "whenNotToUse": [
            "Rules that belong to the framework instead of this consumer. Those live in `@govlab/quality`'s own plugins and reach every consumer through the catalog.",
            "Mechanical rewrites a linter already applies safely. A codemod is for the cases where a fixer would produce unverified output.",
            "Anything needing a published entry point. The host exposes no API for other members to import."
        ],
        "quickStart": [
            {
                "intent": "Add a member-scoped lint rule and activate it",
                "code": "# drop the rule in, then regenerate the index govlab.config reads\nnode .govlab/rules/entrypoints/index.entrypoint.ts"
            },
            {
                "intent": "Run a codemod, which applies fixes by default",
                "code": "node .govlab/codemods/entrypoints/increment.entrypoint.ts"
            },
            {
                "intent": "Inspect what a codemod would touch, without writing",
                "code": "node .govlab/codemods/entrypoints/code-point.entrypoint.ts --map"
            },
            {
                "intent": "Replace an exact string across data files, listing the matches first",
                "code": "npm run codemod:literal -- --from '\"old_id\"' --to '\"new_id\"' --root govlab.root/govlab.context/configuration --ext .json --map"
            },
            {
                "intent": "Narrow a codemod to the programs one member owns",
                "code": "node .govlab/codemods/entrypoints/increment.entrypoint.ts --tsconfig banes-lab.root/banes-lab.web/tsconfig.json"
            }
        ],
        "configuration": "No config file of its own. Roots resolve through `@ssot/paths`. `shared/resolvers/anchor.resolver.ts` is the single anchor: it names the application member, exports the roots every local rule shares and resolves a file to the container of its own governed root. `types/rule.types.ts` carries the typed ESLint surface: `LocalRule`, `RuleContext` and `RuleListener`. Discovery skips `_`-prefixed and `.generated.ts` files. Codemods read the tsconfig list in `codemods/selectors/program.selector.ts`, which defaults to one program per workspace member and narrows to whatever `--tsconfig <comma list>` names.",
        "disposal": [
            "Deleting a rule file and regenerating the index removes the rule from the gate, with no registration list to clean up.",
            "Deleting a workspace plugin file also requires dropping its entries from `eslint.rules` in the root `.govlab/govlab.config.ts`, which names them explicitly.",
            "Deleting a codemod also removes its step from the pipeline's auto-fix stage, where the stage planner lists each one."
        ],
        "aiContext": [
            "Location is registration. The plugin's guard scopes a rule in `rules/eslint/` to the governed roots. A rule declaring `workspaceWide`, or a wrapper exporting `{ tool, plugins }`, bypasses the guard. The declaration chooses the blast radius.",
            "Codemods verify their own output: `applyEdits` re-parses the rewritten file and refuses to write when the rewrite introduces a syntax error.",
            "A codemod splits findings into convertible and blocked, and a blocked finding carries a `reason`. `gateOnBlocked` decides whether a blocked finding fails the run.",
            "A codemod's coverage is its tsconfig list. A member absent from that list is never scanned and the run still reports success. Adding a member means adding its tsconfig here as well as to the workspaces glob.",
            "Never rely on `node.parent` or `node.getSourceFile()` in an analyzer: parent pointers are populated only once the binder runs, which happens when a checker is requested. Thread `sourceFile` and `parent` through the walk instead."
        ]
    }
}
```
