manifest.json
Stack globs, profiles, vendor toggles and the standards version.
What this is
The single config file everything else is generated from — stack globs, which stacks compose each profile, vendor on/off switches, and the standards version every rendered file names.
How to onboard it
Nothing to onboard: it arrives with the CLI. redline init reads it to detect which stacks your profile includes and which vendors to render for. You never install or copy this file into a product repository — it stays in the source repo and ships inside the published package.
How to use it
core— the source file every profile always includes.stacks— one entry per stack: title, source markdown,globs(plain, never negated or brace-expanded — Copilot'sapplyTocan't express either), and an optionalextendslist.profiles— named lists of stack ids; see Standards for the full table.profileAliases— legacy profile names accepted for backwards compatibility.vendors— which of the four renderers are enabled by default (Cursor ships off).
Expected output
The manifest produces no findings of its own. What it decides is which rule files get composed into each rendered artifact and under which applyTo globs — so an error here shows up as a stack that never loads, or one that loads on the wrong files, rather than as a bad review comment.
scripts/validate.mjs is what catches that: it fails the build on a stack whose source is missing, a profile naming an unknown stack, an alias shadowing a real profile, and on globs Copilot's applyTo cannot express — negated (!), brace expansions, or a glob containing the separator comma.
How to edit it
It is part of standards/, so the same discipline applies as to the rule files themselves — including the version bump, which lives in this very file.
- Edit the markdownstandards/ is the only place a human edits a rule. Everything under AGENTS.md, .github/copilot-instructions.md and .github/instructions/ is rendered from it and is overwritten by the next render.
- node scripts/assign-rule-ids.mjsAssigns a permanent <stack>/<slug> id to any new rule bullet and rewrites the file in place. Do not invent an id by hand. CI runs the same script with --check and fails if a rule is missing one.
- node scripts/render-self.mjsRe-renders this repository's own artifacts from the edited source. CI runs it with --check, so stale checked-in output fails the build.
- Bump standards/manifest.json → versionRequired in the same pull request as the rule change. Sync pull requests quote the version, so a repository's rendered artifacts always name where they came from.
- Add a CHANGELOG.md entryAlso in the same pull request. A standards change with no measurement is an opinion — record the seed score alongside it.
- node scripts/validate.mjsThe bundle self-check CI runs: manifest integrity, well-formed rule ids, the severity output contract surviving your edit, glob portability.
The full file
{
"$comment": "Single source of truth for Redline. scripts/render.mjs turns this into vendor-specific artifacts. Never hand-edit generated output.",
"version": "0.1.0",
"core": {
"title": "Redline Core Engineering Standards",
"source": "standards/core.md"
},
"stacks": {
"javascript": {
"title": "JavaScript",
"source": "standards/stacks/javascript.md",
"globs": [
"**/*.js",
"**/*.jsx",
"**/*.mjs",
"**/*.cjs",
"**/*.vue",
"**/*.svelte"
]
},
"react": {
"title": "React (web)",
"source": "standards/stacks/react.md",
"globs": [
"**/*.tsx",
"**/*.jsx",
"src/**/*.ts",
"app/**/*.ts",
"packages/**/src/**/*.ts",
"apps/**/src/**/*.ts"
]
},
"angular": {
"title": "Angular",
"source": "standards/stacks/angular.md",
"globs": [
"**/*.component.ts",
"**/*.component.html",
"**/*.service.ts",
"**/*.directive.ts",
"**/*.pipe.ts",
"**/*.guard.ts",
"**/*.interceptor.ts",
"src/app/**",
"apps/**/src/app/**",
"packages/**/src/app/**"
]
},
"vue": {
"title": "Vue",
"source": "standards/stacks/vue.md",
"globs": [
"**/*.vue",
"composables/**",
"pages/**",
"server/**/*.ts",
"src/**/*.ts",
"app/**/*.ts",
"apps/**/src/**/*.ts",
"packages/**/src/**/*.ts"
]
},
"svelte": {
"title": "Svelte / SvelteKit",
"source": "standards/stacks/svelte.md",
"globs": [
"**/*.svelte",
"**/*.svelte.ts",
"**/*.svelte.js",
"src/routes/**",
"src/lib/**",
"apps/**/src/routes/**",
"apps/**/src/lib/**",
"packages/**/src/lib/**"
]
},
"dom": {
"title": "Browser / DOM",
"source": "standards/stacks/dom.md",
"globs": [
"**/*.js",
"**/*.mjs",
"**/*.ts",
"**/*.html"
]
},
"react-native": {
"title": "React Native",
"source": "standards/stacks/react-native.md",
"extends": [
"react"
],
"globs": [
"**/*.tsx",
"**/*.native.ts",
"app/**/*.ts",
"src/screens/**",
"src/components/**",
"packages/**/src/**/*.tsx",
"apps/**/src/**/*.tsx"
]
},
"nextjs": {
"title": "Next.js (App Router)",
"source": "standards/stacks/nextjs.md",
"extends": [
"react"
],
"globs": [
"app/**",
"src/app/**",
"pages/**",
"src/pages/**",
"middleware.ts",
"src/middleware.ts",
"next.config.ts",
"next.config.js",
"next.config.mjs",
"apps/**/app/**",
"apps/**/src/app/**"
]
},
"nodejs": {
"title": "Node.js (NestJS)",
"source": "standards/stacks/nodejs.md",
"globs": [
"src/**/*.ts",
"apps/**/src/**/*.ts",
"libs/**/src/**/*.ts",
"packages/**/src/**/*.ts"
]
},
"express": {
"title": "Express",
"source": "standards/stacks/express.md",
"globs": [
"routes/**",
"src/routes/**",
"middleware/**",
"src/middleware/**",
"controllers/**",
"src/controllers/**",
"app.js",
"app.ts",
"server.js",
"server.ts",
"src/app.ts",
"src/server.ts"
]
},
"microservices": {
"title": "Microservice cross-cutting",
"source": "standards/stacks/microservices.md",
"globs": [
"**/*.java",
"**/*.go",
"**/*.py",
"**/*.cs",
"src/**/*.ts",
"cmd/**",
"internal/**",
"services/**"
]
},
"java": {
"title": "Java (Spring Boot)",
"source": "standards/stacks/java.md",
"globs": [
"**/*.java"
]
},
"go": {
"title": "Go",
"source": "standards/stacks/go.md",
"globs": [
"**/*.go"
]
},
"python": {
"title": "Python",
"source": "standards/stacks/python.md",
"globs": [
"**/*.py"
]
},
"csharp": {
"title": "C# (.NET)",
"source": "standards/stacks/csharp.md",
"globs": [
"**/*.cs"
]
},
"kotlin": {
"title": "Kotlin",
"source": "standards/stacks/kotlin.md",
"globs": [
"**/*.kt",
"**/*.kts"
]
},
"swift": {
"title": "Swift (iOS)",
"source": "standards/stacks/swift.md",
"globs": [
"**/*.swift"
]
},
"terraform": {
"title": "Terraform / HCL",
"source": "standards/stacks/terraform.md",
"globs": [
"**/*.tf",
"**/*.tfvars",
"**/*.hcl"
]
}
},
"$profileComment": "A repo installs exactly one profile. Profiles are the disambiguation mechanism: glob negation is not portable across vendors, so we never install two rule sets that would contradict each other in the same repo.",
"profiles": {
"tooling": [
"javascript"
],
"web-react": [
"javascript",
"react"
],
"web-next": [
"javascript",
"react",
"nextjs"
],
"web-angular": [
"javascript",
"angular"
],
"web-vue": [
"javascript",
"vue"
],
"web-svelte": [
"javascript",
"svelte"
],
"web-vanilla": [
"javascript",
"dom"
],
"mobile-rn": [
"javascript",
"react",
"react-native"
],
"mobile-android": [
"kotlin"
],
"mobile-ios": [
"swift"
],
"service-java": [
"microservices",
"java"
],
"service-go": [
"microservices",
"go"
],
"service-node": [
"javascript",
"microservices",
"nodejs"
],
"service-express": [
"javascript",
"microservices",
"express"
],
"service-python": [
"microservices",
"python"
],
"service-dotnet": [
"microservices",
"csharp"
],
"infra": [
"terraform"
],
"fullstack-node": [
"javascript",
"react",
"microservices",
"nodejs"
]
},
"$aliasComment": "Legacy profile names accepted by sync-targets.txt for backwards compatibility.",
"profileAliases": {
"web": "web-react",
"mobile": "mobile-rn",
"java": "service-java",
"go": "service-go",
"node": "service-node",
"python": "service-python",
"dotnet": "service-dotnet"
},
"vendors": {
"copilot": {
"title": "GitHub Copilot code review",
"enabled": true
},
"agents": {
"title": "AGENTS.md (OpenAI Codex, Copilot coding agent, Jules, Cursor agent, Devin)",
"enabled": true
},
"codex": {
"$comment": "Renders AGENTS.md, the same file the \"agents\" vendor writes — that is the file OpenAI Codex reads, and inventing a second Codex-specific path would render rules nothing looks for. Listed separately because an operator looking for Codex should find it by name; selecting either produces the same artifact, and selecting both writes it once.",
"title": "OpenAI Codex (AGENTS.md)",
"enabled": true
},
"claude": {
"title": "Claude Code / Claude in GitHub",
"enabled": true
},
"cursor": {
"title": "Cursor rules",
"enabled": true
}
},
"$deterministicComment": "Rules a checker decides without a model. The classification lives HERE and not in the markdown deliberately: standards/*.md is what a reviewer reads, and removing a rule from it because a checker also covers it would narrow what the model considers. Every rule is classified by construction — listed here means deterministic, absent means judgement. Ids are permanent and are never rewritten by this list. scripts/validate.mjs fails the build if an id here has no implementation in cli/policy/checks.ts, which is the failure mode where a rule is silently enforced by nobody.",
"deterministic": [
"core/untracked-todo",
"core/type-checker-suppression",
"javascript/var-in-new-code",
"javascript/unsafe-numeric-coercion"
]
}