Skip to main content

Script Governance

This page is the canonical governance reference for all scripts in this repository. It defines the three-tier taxonomy, JSDoc header standard, enforcement tiers, and the process for adding a new script. The full script inventory lives in the auto-generated catalog: Scripts Catalog.

Taxonomy — the three-tier model

Every script in operations/scripts/ is placed at a path following this structure:
operations/scripts/<type>/<concern>/<niche>/script-name.js
This hierarchy is enforced — a script placed in the wrong folder will fail classification validation.

Layer 1 — Type

What the script does.
Type folderWhat it does@type valueTypical @mode
audits/Read-only scan, measure, report. Never modifies files. Produces reports and metrics.auditread-only
generators/Produces new files from source-of-truth data. Creates artefacts (JSON, MDX, indexes, registries).generatorwrite, generate
validators/Enforces rules with a pass/fail gate. Exits 0 (pass) or non-zero (fail).validatorread-only
remediators/Bulk-fixes existing files in place. Modifies source content to bring it into compliance.remediatoredit
dispatch/Dispatches work to other scripts or agents. Genuine orchestrators that spawn child processes.dispatchexecute
automations/End-to-end automated workflows — translation, data fetching, transforms.automationwrite, execute
Key distinctions:
  • If the script only readsaudit or validator (validator exits non-zero on failure; audit just reports)
  • If the script only creates new filesgenerator
  • If the script edits existing filesremediator
  • If the script runs other scriptsdispatch
  • A script that does NOT spawn other scripts is NOT a dispatch

Layer 2 — Concern

What domain the script operates on. The same four concerns appear under every type folder.
ConcernWhat it covers
content/Docs pages, copy, SEO, veracity, quality, reference, reconciliation
components/Component library, registry, CSS, naming, documentation
governance/Scripts about scripts, repo structure, agent docs, manifests, catalogs
ai/LLM files, agent packaging, skills sync, Codex operations

Layer 3 — Niche

The specific sub-concern within the domain. Examples: quality, veracity, structure, copy, grammar, catalogs, compliance, pr, codex, repair, style, scaffold, llm. Full niche reference: see script-framework.md section 2.

Classification decision tree

1. Does the script SPAWN other scripts or coordinate a multi-script pipeline?
   YES → dispatch/
   NO  → continue

2. Does the script only READ files and produce reports/metrics (no file modifications)?
   YES → Does it enforce a pass/fail gate (exit 0/1)?
         YES → validators/
         NO  → audits/
   NO  → continue

3. Does the script CREATE new files from source-of-truth data?
   YES → generators/
   NO  → continue

4. Does the script MODIFY existing files in place to fix/repair them?
   YES → remediators/
   NO  → continue

5. Is the script an end-to-end automated workflow (translation, data fetching, transforms)?
   YES → automations/
For concern:
- Operates on docs pages, MDX, copy, SEO, frontmatter? → content/
- Operates on components, registry, CSS, naming?        → components/
- Operates on scripts, repo structure, agent docs?      → governance/
- Operates on LLM files, agent packs, skills, Codex?   → ai/

JSDoc Header Standard

Every script MUST include a JSDoc header block as the first block comment in the file (or hash-comment equivalent for .sh and .py files). The pre-commit hook and CI validate header presence and tag format.

Required tags (enforced by --strict)

#TagRequiredWhat it capturesAllowed values / format
1@scriptYesScript identityFilename without extension. Example: lint-copy
2@typeYesLayer 1 — what the script doesaudit | generator | validator | remediator | dispatch | automation
3@concernYesLayer 2 — domaincontent | components | governance | ai
4@nicheYesLayer 3 — specific sub-concernSee niche reference in section 2 above
5@purposeYesFunctional categoryNamespaced string: qa:content-quality, governance:repo-health, tooling:dev-tools, etc.
6@descriptionYesOne-line human-readable descriptionPlain English. No line breaks.
7@modeYesHow the script affects the systemread-only | write | edit | generate | execute
8@pipelineYesFlow declarationArrow notation: trigger → inputs → outputs
9@scopeYesWhat files/directories it operates onComma-separated paths, patterns, or keywords
10@usageYesCLI invocation exampleFull command with flags
11@policyIf applicableGovernance traceabilityRequirement IDs: E-R1, R-R11
The required minimum validated by --strict is tags 1–10. @policy is expected but not blocked on by default.

@mode values

ValueMeaning
read-onlyInspects and reports only — no file changes. Used by audits and validators.
writeCreates new files. Used by generators and automations.
editModifies existing files in place. Used by remediators.
generateProduces artefacts (JSON, MDX, indexes, registries). Used by generators.
executeRuns external commands, dispatches work to other scripts or agents. Used by dispatch.

@pipeline format

Single-line flow declaration using arrow notation:
@pipeline   trigger → inputs → outputs [→ dependants]
Examples:
@pipeline   pre-commit → staged .mdx files → stdout:report
@pipeline   manual → docs.json, v2 frontmatter → docs-index.json → scripts-catalog
@pipeline   cron:weekly → full v2 tree → governance-repair PR
@pipeline   pr-workflow → changed .mdx files → exit-code, stdout:violations

Example header — JavaScript

/**
 * @script      lint-copy
 * @type        validator
 * @concern     content
 * @niche       copy
 * @purpose     qa:content-quality
 * @description Enforce banned word and phrase rules on MDX content files.
 * @mode        read-only
 * @pipeline    pr-workflow → staged .mdx files → exit-code, stdout:violations
 * @scope       staged, changed, v2-content, single-file
 * @usage       node operations/scripts/validators/content/copy/lint-copy.js [file or glob] [flags]
 * @policy      E-R1, R-R11
 */

Example header — shell / Python (hash-comment style)

# @script            pre-commit
# @type              dispatch
# @concern           governance
# @niche             pipelines
# @purpose           infrastructure:pipeline-orchestration
# @description       Pre-commit hook — hard gates only.
# @mode              execute
# @pipeline          P1 → git index → exit-code
# @scope             .githooks
# @usage             bash .githooks/pre-commit [flags]
# @policy            R-R29

Removed tags — MUST NOT appear

These tags were used in earlier versions and must not appear in new scripts:
Removed tagReplaced by
@ownerRemoved — ownerless governance model
@category@type
@dualmodeNot replaced — scripts should have one purpose
@purpose-statement@description
@needs@policy
@domain@concern

Enforcement Tiers

Scripts are assigned to one of three tiers. Tier assignment belongs in @pipeline.
TierGate typeRuns whereWhat it means
Hard gateBlocks commit or mergePre-commit hook + required GitHub Actions status checkMust pass. Violations block the commit.
Soft gateWarns in PR, does not block mergeGitHub Actions check (non-required)Violations surface in PR UI but do not prevent merge.
Self-healNo gate — auto-fixes on scheduleCron workflow with auto-PRRuns periodically and opens a PR with corrections.

File Structure Standard

Every script MUST follow this section order:
1. Shebang line          #!/usr/bin/env node  (or bash, python3)
2. JSDoc header block    All 11 tags in declared order
3. 'use strict'          JS only — recommended
4. Requires / imports    const fs = require('fs'); etc.
5. Constants / config    REPO_ROOT, paths, thresholds — ALL in first ~30 lines after imports
6. Helper functions      Small, focused utilities
7. Main function         Primary logic
8. Exports / execution   module.exports or main() call

REPO_ROOT pattern

// Correct — repo root from process.cwd()
const REPO_ROOT = process.cwd();

// Wrong — fragile, breaks if script is moved
const REPO_ROOT = path.resolve(__dirname, '../../../../..');
__dirname-relative paths are acceptable only for reaching sibling files or shared libraries within the scripts tree (e.g., require('../../../../lib/docs-index-utils')).

How to Write a New Script

1

Classify it first

Use the decision tree above to determine type, concern, and niche. Place the file at operations/scripts/<type>/<concern>/<niche>/<script-name>.js.
2

Write the JSDoc header

Copy the example header above. Fill all 11 tags. Do not leave placeholder values. Run node operations/scripts/validators/governance/compliance/review-governance-repair-checklist.js --staged to validate.
3

Follow the file structure

Shebang → JSDoc header → 'use strict' → imports → constants/config at top → helpers → main() → export/execute.
4

Use process.cwd() for REPO_ROOT

Never traverse up with __dirname to reach the repo root. Use process.cwd() or a shared getRepoRoot() utility.
5

Support --dry-run if the script writes files

Any script that writes or modifies files SHOULD support --dry-run to show what would change without making changes.
6

Assign an enforcement tier

Set @pipeline to indicate where the script runs. Hard gates go in pre-commit or required CI; soft gates in non-required CI; self-heals in cron.
7

Add to the registry

Run node operations/scripts/generators/governance/catalogs/generate-script-registry.js to update tools/config/registry/script-registry.json. The catalog is regenerated automatically from the registry.

Source of Truth

ResourceWhere
This governance specdocs-guide/policies/script-governance.mdx (you are here)
Full technical specworkspace/plan/active/SCRIPT-GOVERNANCE/script-framework.md
Script registry (derived index)tools/config/registry/script-registry.json
Script catalog (auto-generated)docs-guide/catalog/scripts-catalog
Registry generatoroperations/scripts/generators/governance/catalogs/generate-script-registry.js
Last modified on April 7, 2026