@webpieces/rules-config 0.4.490 → 0.4.491

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"rule-configs.js","sourceRoot":"","sources":["../../../../../packages/tooling/rules-config/src/rule-configs.ts"],"names":[],"mappings":"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","sourcesContent":["import { FieldDef, SchemaShape } from './field-def';\n\n// Mode const arrays — TypeScript union types derived from them, and FieldDef enum\n// values reference the same array. Impossible for the type and runtime check to diverge.\n\n// Single source of truth for rule \"mode\" values. Exported so code-rules (and any other\n// consumer) imports these instead of re-declaring the same unions — a rename here ripples\n// everywhere at compile time. The FieldDef SCHEMA below references the same arrays, so the\n// type and the runtime validation can never diverge.\nexport const METHOD_LIMIT_MODES = ['OFF', 'NEW_METHODS', 'NEW_AND_MODIFIED_METHODS', 'NEW_AND_MODIFIED_FILES'] as const;\nexport type MethodLimitMode = typeof METHOD_LIMIT_MODES[number];\n\nexport const FILE_LIMIT_MODES = ['OFF', 'NEW_AND_MODIFIED_FILES'] as const;\nexport type FileLimitMode = typeof FILE_LIMIT_MODES[number];\n\nexport const RETURN_TYPE_MODES = ['OFF', 'NEW_METHODS', 'NEW_AND_MODIFIED_METHODS', 'NEW_AND_MODIFIED_FILES'] as const;\nexport type ReturnTypeMode = typeof RETURN_TYPE_MODES[number];\n\nexport const INLINE_TYPE_MODES = ['OFF', 'NEW_METHODS', 'NEW_AND_MODIFIED_METHODS', 'NEW_AND_MODIFIED_FILES'] as const;\nexport type InlineTypeMode = typeof INLINE_TYPE_MODES[number];\n\nexport const MODIFIED_CODE_MODES = ['OFF', 'NEW_AND_MODIFIED_CODE', 'NEW_AND_MODIFIED_FILES'] as const;\nexport type ModifiedCodeMode = typeof MODIFIED_CODE_MODES[number];\n\n// PROJECT-level rules (e.g. framework-tag): the check is neither line- nor file-scoped — it runs\n// for a whole project when ANY file the project owns is touched. `MODIFIED_PROJECTS` names that\n// honestly (nx `affected` already narrows execution to the changed projects).\nexport const PROJECT_MODES = ['OFF', 'MODIFIED_PROJECTS'] as const;\nexport type ProjectMode = typeof PROJECT_MODES[number];\n\nexport const PRISMA_DTOS_MODES = ['OFF', 'MODIFIED_CLASS', 'NEW_AND_MODIFIED_FILES'] as const;\nexport type PrismaValidateDtosMode = typeof PRISMA_DTOS_MODES[number];\n\nexport const PRISMA_CONVERTER_MODES = ['OFF', 'NEW_AND_MODIFIED_METHODS', 'NEW_AND_MODIFIED_FILES'] as const;\nexport type PrismaConverterMode = typeof PRISMA_CONVERTER_MODES[number];\n\nexport const DIRECT_API_RESOLVER_MODES = ['OFF', 'NEW_AND_MODIFIED_CODE', 'NEW_AND_MODIFIED_METHODS', 'NEW_AND_MODIFIED_FILES'] as const;\nexport type DirectApiResolverMode = typeof DIRECT_API_RESOLVER_MODES[number];\n\nexport const THROW_CAUSE_MODES = ['OFF', 'NEW_AND_MODIFIED_CODE'] as const;\nexport type ThrowCauseMode = typeof THROW_CAUSE_MODES[number];\n\nexport const ON_OFF_MODES = ['ON', 'OFF'] as const;\nexport type OnOffMode = typeof ON_OFF_MODES[number];\n\n// branch-creation-guard modes. ON_NO_SUBBRANCHES is the strict variant: it hard-blocks\n// creating a branch off any non-main branch (no sub-branch affordance), pointing the agent\n// back to `git checkout main && git pull && git checkout -b <branch>`. Temporarily overridable\n// via the universal ignoreModifiedUntilEpoch escape hatch.\nexport const BRANCH_GUARD_MODES = ['ON', 'OFF', 'ON_NO_SUBBRANCHES'] as const;\nexport type BranchGuardMode = typeof BRANCH_GUARD_MODES[number];\n\nexport const VALIDATE_TS_MODES = ['OFF', 'NEW_AND_MODIFIED_FILES'] as const;\nexport type ValidateTsMode = typeof VALIDATE_TS_MODES[number];\n\n// Structural / whole-graph rules (import-cycle, runtime-architecture, nx-wiring). They can't be\n// scoped to changed lines/files — a cycle or wiring break can route through a project that wasn't\n// itself edited — so when active they run the FULL check every time (nx-affected already limits\n// them to affected projects externally). RUN_EVERY_TIME replaces the old, vaguer \"ON\".\nexport const STRUCTURAL_MODES = ['OFF', 'RUN_EVERY_TIME'] as const;\nexport type StructuralMode = typeof STRUCTURAL_MODES[number];\n\n// ---------------------------------------------------------------------------\n// Universal escape hatches — EVERY rule supports temporarily disabling itself\n// either while on a named git branch (turnOffRuleWhileOnBranch) or until an\n// epoch passes (turnOffRuleUntilEpoch). They live on a shared base class so the\n// fields (and their schema entries) are declared once instead of repeated per\n// rule. `mode` stays per-rule because its allowed values vary (ON/OFF vs\n// NEW_AND_MODIFIED_CODE vs NEW_AND_MODIFIED_METHODS, etc).\n//\n// TWO NAMES per hatch, and BOTH are accepted (see normalizeTurnOffAliases):\n// turnOffRuleUntilEpoch — new, self-describing name. Supersedes ignoreModifiedUntilEpoch.\n// turnOffRuleWhileOnBranch — new, self-describing name. Supersedes ignoreRuleWhileOnBranch.\n// The original `ignoreModifiedUntilEpoch` / `ignoreRuleWhileOnBranch` keep working so a config can\n// migrate a rule at a time. When both names are present on one rule, the new name wins.\n//\n// Convention (unchanged): 0 = rule active (epoch is in the past, never skipped); a future unix epoch\n// IN SECONDS = rule temporarily disabled until that moment. All four fields are OPTIONAL — a rule may\n// carry the branch hatch alone (turnOffRuleWhileOnBranch) with no epoch, which is the intended\n// end-state once callers stop writing turnOffRuleUntilEpoch.\n// ---------------------------------------------------------------------------\nexport abstract class BaseRuleConfig {\n // `mode` is declared here (loosely typed) so the shared AbstractRule base can read it for\n // on/off. Each concrete *Config narrows it to its own union (e.g. `mode?: ModifiedCodeMode`),\n // which is an assignable (covariant) override.\n mode?: string;\n // Original names — still accepted. normalizeTurnOffAliases canonicalizes the new names ONTO these,\n // so every reader in both packages keeps reading exactly this pair.\n ignoreModifiedUntilEpoch?: number;\n ignoreRuleWhileOnBranch?: string;\n // New, self-describing names. A config using these is normalized onto the pair above at load time.\n turnOffRuleUntilEpoch?: number;\n turnOffRuleWhileOnBranch?: string;\n}\n\nexport const BASE_RULE_SCHEMA = {\n ignoreModifiedUntilEpoch: FieldDef.optional('number'),\n ignoreRuleWhileOnBranch: FieldDef.optional('string'),\n turnOffRuleUntilEpoch: FieldDef.optional('number'),\n turnOffRuleWhileOnBranch: FieldDef.optional('string'),\n};\n\n// The new names are canonicalized onto the original pair at the load boundary by\n// ConfigLoader.normalizeTurnOffAliases (load-config.ts), sibling to normalizeDeprecatedKeys — so every\n// downstream reader (AbstractRule.shouldRun, RuleGate, the match-rules engine) reads one name and\n// needs no change. new name wins when both are present.\n\nexport class MaxMethodLinesConfig extends BaseRuleConfig {\n declare mode?: MethodLimitMode;\n limit?: number;\n disableAllowed?: boolean;\n\n static readonly SCHEMA: SchemaShape<MaxMethodLinesConfig> = {\n mode: new FieldDef('string', METHOD_LIMIT_MODES),\n limit: FieldDef.optional('number'),\n disableAllowed: FieldDef.optional('boolean'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class MaxFileLinesConfig extends BaseRuleConfig {\n declare mode?: FileLimitMode;\n limit?: number;\n disableAllowed?: boolean;\n\n static readonly SCHEMA: SchemaShape<MaxFileLinesConfig> = {\n mode: new FieldDef('string', FILE_LIMIT_MODES),\n limit: FieldDef.optional('number'),\n disableAllowed: FieldDef.optional('boolean'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class RequireReturnTypeConfig extends BaseRuleConfig {\n declare mode?: ReturnTypeMode;\n disableAllowed?: boolean;\n\n static readonly SCHEMA: SchemaShape<RequireReturnTypeConfig> = {\n mode: new FieldDef('string', RETURN_TYPE_MODES),\n disableAllowed: FieldDef.optional('boolean'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class NoInlineTypeLiteralsConfig extends BaseRuleConfig {\n declare mode?: InlineTypeMode;\n disableAllowed?: boolean;\n\n static readonly SCHEMA: SchemaShape<NoInlineTypeLiteralsConfig> = {\n mode: new FieldDef('string', INLINE_TYPE_MODES),\n disableAllowed: FieldDef.optional('boolean'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class NoAnyUnknownConfig extends BaseRuleConfig {\n declare mode?: ModifiedCodeMode;\n disableAllowed?: boolean;\n\n static readonly SCHEMA: SchemaShape<NoAnyUnknownConfig> = {\n mode: new FieldDef('string', MODIFIED_CODE_MODES),\n disableAllowed: FieldDef.optional('boolean'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class NoImplicitAnyConfig extends BaseRuleConfig {\n declare mode?: ModifiedCodeMode;\n disableAllowed?: boolean;\n\n static readonly SCHEMA: SchemaShape<NoImplicitAnyConfig> = {\n mode: new FieldDef('string', MODIFIED_CODE_MODES),\n disableAllowed: FieldDef.optional('boolean'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class PrismaValidateDtosConfig extends BaseRuleConfig {\n declare mode?: PrismaValidateDtosMode;\n disableAllowed?: boolean;\n prismaSchemaPath?: string;\n dtoSourcePaths?: string[];\n\n static readonly SCHEMA: SchemaShape<PrismaValidateDtosConfig> = {\n mode: new FieldDef('string', PRISMA_DTOS_MODES),\n disableAllowed: FieldDef.optional('boolean'),\n prismaSchemaPath: FieldDef.optional('string'),\n dtoSourcePaths: FieldDef.optional('string[]'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class PrismaConverterConfig extends BaseRuleConfig {\n declare mode?: PrismaConverterMode;\n disableAllowed?: boolean;\n schemaPath?: string;\n convertersPaths?: string[];\n enforcePaths?: string[];\n\n static readonly SCHEMA: SchemaShape<PrismaConverterConfig> = {\n mode: new FieldDef('string', PRISMA_CONVERTER_MODES),\n disableAllowed: FieldDef.optional('boolean'),\n schemaPath: FieldDef.optional('string'),\n convertersPaths: FieldDef.optional('string[]'),\n enforcePaths: FieldDef.optional('string[]'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\n// `allowedPaths` exempts whole file trees whose idioms are destructuring by construction (React /\n// React Native components and hooks — `const [x, setX] = useState()`, destructured props — framework\n// glue), matched with the shared glob/prefix/segment semantics of `isPathExcluded`. It is the ONLY\n// escape when `disableAllowed: false`, since that setting deliberately ignores inline disables.\nexport class NoDestructureConfig extends BaseRuleConfig {\n declare mode?: ModifiedCodeMode;\n allowTopLevel?: boolean;\n disableAllowed?: boolean;\n allowedPaths?: string[];\n\n static readonly SCHEMA: SchemaShape<NoDestructureConfig> = {\n mode: new FieldDef('string', MODIFIED_CODE_MODES),\n allowTopLevel: FieldDef.optional('boolean'),\n disableAllowed: FieldDef.optional('boolean'),\n allowedPaths: FieldDef.optional('string[]'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class NoUnmanagedExceptionsConfig extends BaseRuleConfig {\n declare mode?: ModifiedCodeMode;\n disableAllowed?: boolean;\n\n static readonly SCHEMA: SchemaShape<NoUnmanagedExceptionsConfig> = {\n mode: new FieldDef('string', MODIFIED_CODE_MODES),\n disableAllowed: FieldDef.optional('boolean'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class CatchErrorPatternConfig extends BaseRuleConfig {\n declare mode?: ModifiedCodeMode;\n disableAllowed?: boolean;\n\n static readonly SCHEMA: SchemaShape<CatchErrorPatternConfig> = {\n mode: new FieldDef('string', MODIFIED_CODE_MODES),\n disableAllowed: FieldDef.optional('boolean'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class ThrowCauseRequiredConfig extends BaseRuleConfig {\n declare mode?: ThrowCauseMode;\n disableAllowed?: boolean;\n\n static readonly SCHEMA: SchemaShape<ThrowCauseRequiredConfig> = {\n mode: new FieldDef('string', THROW_CAUSE_MODES),\n disableAllowed: FieldDef.optional('boolean'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class AngularNoDirectApiInResolverConfig extends BaseRuleConfig {\n declare mode?: DirectApiResolverMode;\n disableAllowed?: boolean;\n enforcePaths?: string[];\n\n static readonly SCHEMA: SchemaShape<AngularNoDirectApiInResolverConfig> = {\n mode: new FieldDef('string', DIRECT_API_RESOLVER_MODES),\n disableAllowed: FieldDef.optional('boolean'),\n enforcePaths: FieldDef.optional('string[]'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\n// Bans hand-written CSS in Angular sources (styles:/styleUrls:/styleUrl: in @Component, and inline\n// style=/[style.x]/[ngStyle] in templates) so teams style with Tailwind utility classes. `allowGlobs`\n// exempts paths WITHIN the Angular scope (e.g. a vendored Fuse kit copied verbatim with its own CSS).\nexport class NoCustomCssConfig extends BaseRuleConfig {\n declare mode?: ModifiedCodeMode;\n disableAllowed?: boolean;\n allowGlobs?: string[];\n\n static readonly SCHEMA: SchemaShape<NoCustomCssConfig> = {\n mode: new FieldDef('string', MODIFIED_CODE_MODES),\n disableAllowed: FieldDef.optional('boolean'),\n allowGlobs: FieldDef.optional('string[]'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class NoSymbolDiTokensConfig extends BaseRuleConfig {\n declare mode?: ModifiedCodeMode;\n disableAllowed?: boolean;\n allowedPaths?: string[];\n\n static readonly SCHEMA: SchemaShape<NoSymbolDiTokensConfig> = {\n mode: new FieldDef('string', MODIFIED_CODE_MODES),\n disableAllowed: FieldDef.optional('boolean'),\n allowedPaths: FieldDef.optional('string[]'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\n// Flags `process.exit(...)` outside a main()/runMain wrapper (and `import { main }`) so a deep exit\n// can't silently kill a reused server/command. Gradual-rollout knobs via the standard base: mode\n// (OFF | NEW_AND_MODIFIED_CODE | NEW_AND_MODIFIED_FILES), ignoreModifiedUntilEpoch, branch, and\n// disableAllowed for the inline `// webpieces-disable` escape at genuine terminal boundaries.\nexport class NoProcessExitOutsideMainConfig extends BaseRuleConfig {\n declare mode?: ModifiedCodeMode;\n disableAllowed?: boolean;\n\n static readonly SCHEMA: SchemaShape<NoProcessExitOutsideMainConfig> = {\n mode: new FieldDef('string', MODIFIED_CODE_MODES),\n disableAllowed: FieldDef.optional('boolean'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\n// Flags a function CREATED OUTSIDE A CLASS at module scope: a top-level `function foo()` declaration\n// or a top-level `const foo = () => {}` / `= function(){}`. The point is that webpieces DI +\n// @DocumentDesign only work when behavior lives in injectable classes — a module-scope function is a\n// dead-end the DI graph can't reach. Inline callbacks, nested functions inside methods, and non-function\n// top-level consts (objects, zod schemas, primitives) are NOT flagged. Standard rollout knobs via the\n// base: mode (OFF | NEW_AND_MODIFIED_CODE | NEW_AND_MODIFIED_FILES), ignoreModifiedUntilEpoch, branch,\n// and disableAllowed for the inline `// webpieces-disable` escape. `allowedPaths` exempts whole file\n// trees that legitimately live outside the class-per-behavior model (e.g. React component/hook files,\n// framework glue), matched with the shared glob/prefix/segment semantics of `isPathExcluded`.\nexport class NoFunctionOutsideClassConfig extends BaseRuleConfig {\n declare mode?: ModifiedCodeMode;\n disableAllowed?: boolean;\n allowedPaths?: string[];\n\n static readonly SCHEMA: SchemaShape<NoFunctionOutsideClassConfig> = {\n mode: new FieldDef('string', MODIFIED_CODE_MODES),\n disableAllowed: FieldDef.optional('boolean'),\n allowedPaths: FieldDef.optional('string[]'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\n// inject-annotation-not-needed-for-concrete-class — flags a REDUNDANT `@inject(X)` whose token is\n// textually identical to the parameter's own declared type (`@inject(Foo) private readonly foo: Foo`).\n// In this inversify setup the decorator is pure noise there: reflect-metadata (emitDecoratorMetadata)\n// already resolves a constructor parameter by its class type, so `private readonly foo: Foo` binds on\n// its own (see CLAUDE.md, and the no-symbol-di-tokens rule that pushes the same way). Symbol/interface\n// tokens are NOT flagged because they never equal the type (`@inject(FOO_TOKEN) x: Provider<Foo>`).\n// AI keeps carpet-bombing `@inject`; this fails the build on the redundant form. Standard rollout knobs\n// via the base: mode (OFF | NEW_AND_MODIFIED_CODE | NEW_AND_MODIFIED_FILES), ignoreModifiedUntilEpoch,\n// branch, and disableAllowed for the inline `// webpieces-disable` escape. `allowedPaths` exempts whole\n// file trees, matched with the shared glob/prefix/segment semantics.\nexport class InjectAnnotationNotNeededForConcreteClassConfig extends BaseRuleConfig {\n declare mode?: ModifiedCodeMode;\n disableAllowed?: boolean;\n allowedPaths?: string[];\n\n static readonly SCHEMA: SchemaShape<InjectAnnotationNotNeededForConcreteClassConfig> = {\n mode: new FieldDef('string', MODIFIED_CODE_MODES),\n disableAllowed: FieldDef.optional('boolean'),\n allowedPaths: FieldDef.optional('string[]'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\n// framework-tag — every project that a changed source file belongs to must carry >=1\n// `framework:<browser|react|angular|node|express>` nx tag in its project.json. Those tags are the\n// project's \"libType\" — the SET of runtime environments it runs in — and the source of truth for\n// the dependencies.json `framework` field and the `library-types-match-client` rule. Multiple tags\n// are allowed (the env set) and values are validated against the known set (`framework:all` is a\n// hard error). `knownTypes` customizes that set (defaults to browser, react, angular, node, express).\nexport class FrameworkTagConfig extends BaseRuleConfig {\n declare mode?: ProjectMode;\n knownTypes?: string[];\n\n static readonly SCHEMA: SchemaShape<FrameworkTagConfig> = {\n mode: new FieldDef('string', PROJECT_MODES),\n knownTypes: FieldDef.optional('string[]'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\n// role-tag — every project that a changed source file belongs to must carry a\n// `role:<server|designed-lib|lib|client>` nx tag in its project.json. That tag is the project's\n// ROLE (orthogonal to `framework` libType) — the source of truth for the dependencies.json `role`\n// field, the `role-dependency` edge rule (apps are never depended upon), and DI-design generation\n// (server→@Controller, designed-lib→@ApiImplementation, lib→none, client→angular design).\n// `knownTypes` customizes the list suggested to the author when a tag is missing.\nexport class RoleTagConfig extends BaseRuleConfig {\n declare mode?: ProjectMode;\n knownTypes?: string[];\n\n static readonly SCHEMA: SchemaShape<RoleTagConfig> = {\n mode: new FieldDef('string', PROJECT_MODES),\n knownTypes: FieldDef.optional('string[]'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class BranchCreationGuardConfig extends BaseRuleConfig {\n declare mode?: BranchGuardMode;\n // Naming pattern for stacked SUB-branches only (branches created off another feature branch,\n // which require human approval). Never applied to branches created off main.\n subBranchNaming?: string;\n // Human-sentence instruction telling the AI how to name a NEW branch off main. Surfaced back\n // to the agent in the guard's fix hints. May mirror no-edit-on-main.branchNamingConvention.\n branchFormat?: string;\n // Hard cap on local feature branches (excluding main). Creating one past the cap is BLOCKED until\n // already-merged branches are reaped, which is what keeps the branch list from growing without\n // bound. Branch creation is the gate because it is the only moment cleanup is both cheap and\n // obviously worth it. See merged-branches.ts for how \"already merged\" is determined.\n maxLocalBranches?: number;\n // Hard cap on LINKED worktrees (the primary clone is never counted). A separate budget from\n // maxLocalBranches: every worktree holds a branch, so if worktree-held branches also spent the\n // branch budget, five worktrees would leave room for zero branches. Held branches count here;\n // parked branches count against maxLocalBranches. Enforced at `git worktree add`.\n maxWorktrees?: number;\n // Let the detached background refresher DELETE dead branches on its own, instead of only\n // reporting them. Every candidate is provably dead (merged PR / squash backup / no commits) and\n // recoverable by the SHA logged to branch-mutations.log — but it is still UNATTENDED deletion,\n // so this is schema-REQUIRED like `mode` and `ignoreModifiedUntilEpoch`. \"Every built-in rule\n // must be explicitly configured — no silent defaults\" (validate-config.ts) applies with extra\n // force here: branches disappearing on a preference nobody ever stated is precisely the kind of\n // default that must not exist. Validation makes each consumer answer the question once.\n //\n // TS-optional but schema-required — the same split `mode` uses. Absent at RUNTIME therefore means\n // the config never passed validation, and the only safe reading of \"nobody has answered\" is: do\n // not delete anything.\n autoReapMergedBranches?: boolean;\n\n static readonly SCHEMA: SchemaShape<BranchCreationGuardConfig> = {\n mode: new FieldDef('string', BRANCH_GUARD_MODES),\n subBranchNaming: FieldDef.optional('string'),\n branchFormat: FieldDef.optional('string'),\n maxLocalBranches: FieldDef.optional('number'),\n maxWorktrees: FieldDef.optional('number'),\n autoReapMergedBranches: new FieldDef('boolean'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class PrCreationOrPushGuardConfig extends BaseRuleConfig {\n declare mode?: OnOffMode;\n // The gated command the guard points agents to instead of direct PR creation OR a manual push.\n // Per-project override; defaults to `pnpm wp-start-upsert-pr` at the point of use.\n upsertPrCommand?: string;\n\n static readonly SCHEMA: SchemaShape<PrCreationOrPushGuardConfig> = {\n mode: new FieldDef('string', ON_OFF_MODES),\n upsertPrCommand: FieldDef.optional('string'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class MergeInProgressGuardConfig extends BaseRuleConfig {\n declare mode?: OnOffMode;\n // The gated command the guard points agents to in order to finish a 3-point merge. Per-project\n // override; defaults to `commands.mergeComplete` (pnpm wp-finish-upsert-pr) at load time.\n mergeCompleteCommand?: string;\n\n static readonly SCHEMA: SchemaShape<MergeInProgressGuardConfig> = {\n mode: new FieldDef('string', ON_OFF_MODES),\n mergeCompleteCommand: FieldDef.optional('string'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class PrMergeGuardConfig extends BaseRuleConfig {\n declare mode?: OnOffMode;\n\n static readonly SCHEMA: SchemaShape<PrMergeGuardConfig> = {\n mode: new FieldDef('string', ON_OFF_MODES),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class RedirectHowToMergeMainConfig extends BaseRuleConfig {\n declare mode?: OnOffMode;\n\n static readonly SCHEMA: SchemaShape<RedirectHowToMergeMainConfig> = {\n mode: new FieldDef('string', ON_OFF_MODES),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class NoFileImportCyclesConfig extends BaseRuleConfig {\n declare mode?: StructuralMode;\n ignoreTypeOnly?: boolean;\n excludePackages?: string[];\n // Raw regex escape hatch for a cycle inside the project being checked — generated code, a\n // vendored tree, or a deliberate bidirectional domain model — that `excludePackages` cannot reach\n // (it resolves npm package NAMES, so it only excludes a *sibling* package, never a directory\n // inside this one). Patterns are handed to madge verbatim and matched against ids RELATIVE TO THE\n // PROJECT (e.g. \"^src/generated/\", \"^src/modules/(item|category)/\") — NOT workspace-rooted or\n // absolute, which silently match nothing. The executor warns when a pattern matches zero\n // traversed files, so a mis-anchored pattern is visible rather than a silent no-op.\n excludeRegExp?: string[];\n\n static readonly SCHEMA: SchemaShape<NoFileImportCyclesConfig> = {\n mode: new FieldDef('string', STRUCTURAL_MODES),\n ignoreTypeOnly: FieldDef.optional('boolean'),\n excludePackages: FieldDef.optional('string[]'),\n excludeRegExp: FieldDef.optional('string[]'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class RuntimeArchitectureConfig extends BaseRuleConfig {\n declare mode?: StructuralMode;\n // NOTE: `servicePaths` / `apiProjectPaths` were removed — they were never read. The runtime graph\n // is derived SOLELY from architecture/dependencies.json apiRelations + project roles (see\n // nx-webpieces-rules/src/lib/runtime-graph.ts), so any config still listing them (a hand-maintained\n // enumeration of api libs) now fails the unknown-field check in validateWebpiecesConfig. There is\n // nothing to enumerate — delete the keys.\n allowedCycles?: string[];\n /**\n * Draw a dashed terminal node for every contract a service calls that NOTHING in-repo\n * implements (firestore, gmail, ...) — the vendor systems the runtime graph otherwise stops one\n * hop short of. Defaults to true; set false in a repo whose external surface is noisy. Purely a\n * RENDER switch: levels, cycle detection and runtime-dependencies.json are identical either way.\n */\n showExternalNodes?: boolean;\n /**\n * Project roots whose exported `*Api` types are contracts for systems OUTSIDE this repo\n * (firestore, gmail, gcp-storage, ...), e.g. `[\"libraries/apis/external/**\"]`. Globs, matched\n * against the nx project root.\n *\n * Needed because an external contract does NOT look like an in-repo one: it is a plain\n * `interface` bound to a Symbol token and injected, never an `abstract class` carrying @ApiPath\n * reached through `createRpcClient`. Without this list the scanner has no way to tell a vendor\n * seam from any other library, so every call leaving the repo is invisible to the runtime graph.\n *\n * Defaults to none, which is correct for a repo with no vendor wrapper libraries.\n */\n externalApiPaths?: string[];\n\n static readonly SCHEMA: SchemaShape<RuntimeArchitectureConfig> = {\n mode: new FieldDef('string', STRUCTURAL_MODES),\n allowedCycles: FieldDef.optional('string[]'),\n showExternalNodes: FieldDef.optional('boolean'),\n externalApiPaths: FieldDef.optional('string[]'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class NxWiringConfig extends BaseRuleConfig {\n declare mode?: StructuralMode;\n\n static readonly SCHEMA: SchemaShape<NxWiringConfig> = {\n mode: new FieldDef('string', STRUCTURAL_MODES),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class DiGraphConfig extends BaseRuleConfig {\n // Structural: the DI graph is regenerated whole-project on every build (generate +\n // unchanged gate), so it cannot be scoped to changed lines.\n declare mode?: StructuralMode;\n\n static readonly SCHEMA: SchemaShape<DiGraphConfig> = {\n mode: new FieldDef('string', STRUCTURAL_MODES),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class MissingDesignAnnotationConfig extends BaseRuleConfig {\n // Structural: enforced per-project by the di-graph-generate executor, which\n // roots the whole DI design on @DocumentDesign classes — cannot be line-scoped.\n declare mode?: StructuralMode;\n\n static readonly SCHEMA: SchemaShape<MissingDesignAnnotationConfig> = {\n mode: new FieldDef('string', STRUCTURAL_MODES),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class NoJsFilesConfig extends BaseRuleConfig {\n // File-tier: NEW_AND_MODIFIED_FILES (active) intercepts a .js/.jsx Write — the file being\n // written is inherently a new/modified file, so it's already diff-scoped in practice.\n declare mode?: FileLimitMode;\n allowedPaths?: string[];\n\n static readonly SCHEMA: SchemaShape<NoJsFilesConfig> = {\n mode: new FieldDef('string', FILE_LIMIT_MODES),\n allowedPaths: FieldDef.optional('string[]'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\n// ---------------------------------------------------------------------------\n// The five Nx infrastructure validators (architecture-unchanged, no-architecture-cycles,\n// packagejson, versions-locked, eslint-sync). Each is whole-graph / whole-repo by nature (a cycle, a\n// drifted dependencies.json, an unlocked version can be introduced by a file nobody in this diff\n// touched), so the only honest mode set is STRUCTURAL_MODES: RUN_EVERY_TIME (the default) or OFF.\n//\n// All five now honor the universal escape hatches (turnOffRuleUntilEpoch / turnOffRuleWhileOnBranch,\n// and their ignore* aliases) via shouldSkipRule — the RuleGate is called with honorEpoch:true from\n// every executor. This lets a repo time-box or branch-scope a failing infrastructure check (e.g. hold\n// validate-packagejson off until an upgrade PR lands) with a one-value edit, instead of only the\n// blunt \"mode\": \"OFF\". Originally packagejson/versions-locked/eslint-sync were all-or-nothing on the\n// theory that \"no blessed baseline\" made grandfathering meaningless, but a time-box is a schedule, not\n// a baseline: \"do not enforce this until <epoch>/off <branch>\" is coherent for any rule.\n// ---------------------------------------------------------------------------\n\nexport class ValidateArchitectureUnchangedConfig extends BaseRuleConfig {\n declare mode?: StructuralMode;\n\n static readonly SCHEMA: SchemaShape<ValidateArchitectureUnchangedConfig> = {\n mode: new FieldDef('string', STRUCTURAL_MODES),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class ValidateNoArchitectureCyclesConfig extends BaseRuleConfig {\n declare mode?: StructuralMode;\n\n static readonly SCHEMA: SchemaShape<ValidateNoArchitectureCyclesConfig> = {\n mode: new FieldDef('string', STRUCTURAL_MODES),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class ValidatePackageJsonConfig extends BaseRuleConfig {\n declare mode?: StructuralMode;\n\n static readonly SCHEMA: SchemaShape<ValidatePackageJsonConfig> = {\n mode: new FieldDef('string', STRUCTURAL_MODES),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class ValidateVersionsLockedConfig extends BaseRuleConfig {\n declare mode?: StructuralMode;\n\n static readonly SCHEMA: SchemaShape<ValidateVersionsLockedConfig> = {\n mode: new FieldDef('string', STRUCTURAL_MODES),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class ValidateEslintSyncConfig extends BaseRuleConfig {\n declare mode?: StructuralMode;\n\n static readonly SCHEMA: SchemaShape<ValidateEslintSyncConfig> = {\n mode: new FieldDef('string', STRUCTURAL_MODES),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class ValidateTsInSrcConfig extends BaseRuleConfig {\n declare mode?: ValidateTsMode;\n allowedRootFiles?: string[];\n excludePaths?: string[];\n\n static readonly SCHEMA: SchemaShape<ValidateTsInSrcConfig> = {\n mode: new FieldDef('string', VALIDATE_TS_MODES),\n allowedRootFiles: FieldDef.optional('string[]'),\n excludePaths: FieldDef.optional('string[]'),\n ...BASE_RULE_SCHEMA,\n };\n}\n"]}
1
+ {"version":3,"file":"rule-configs.js","sourceRoot":"","sources":["../../../../../packages/tooling/rules-config/src/rule-configs.ts"],"names":[],"mappings":";;;;AAAA,2CAAoD;AAEpD,kFAAkF;AAClF,yFAAyF;AAEzF,uFAAuF;AACvF,0FAA0F;AAC1F,2FAA2F;AAC3F,qDAAqD;AACxC,QAAA,kBAAkB,GAAG,CAAC,KAAK,EAAE,aAAa,EAAE,0BAA0B,EAAE,wBAAwB,CAAU,CAAC;AAG3G,QAAA,gBAAgB,GAAG,CAAC,KAAK,EAAE,wBAAwB,CAAU,CAAC;AAG9D,QAAA,iBAAiB,GAAG,CAAC,KAAK,EAAE,aAAa,EAAE,0BAA0B,EAAE,wBAAwB,CAAU,CAAC;AAG1G,QAAA,iBAAiB,GAAG,CAAC,KAAK,EAAE,aAAa,EAAE,0BAA0B,EAAE,wBAAwB,CAAU,CAAC;AAG1G,QAAA,mBAAmB,GAAG,CAAC,KAAK,EAAE,uBAAuB,EAAE,wBAAwB,CAAU,CAAC;AAGvG,iGAAiG;AACjG,gGAAgG;AAChG,8EAA8E;AACjE,QAAA,aAAa,GAAG,CAAC,KAAK,EAAE,mBAAmB,CAAU,CAAC;AAGtD,QAAA,iBAAiB,GAAG,CAAC,KAAK,EAAE,gBAAgB,EAAE,wBAAwB,CAAU,CAAC;AAGjF,QAAA,sBAAsB,GAAG,CAAC,KAAK,EAAE,0BAA0B,EAAE,wBAAwB,CAAU,CAAC;AAGhG,QAAA,yBAAyB,GAAG,CAAC,KAAK,EAAE,uBAAuB,EAAE,0BAA0B,EAAE,wBAAwB,CAAU,CAAC;AAG5H,QAAA,iBAAiB,GAAG,CAAC,KAAK,EAAE,uBAAuB,CAAU,CAAC;AAG9D,QAAA,YAAY,GAAG,CAAC,IAAI,EAAE,KAAK,CAAU,CAAC;AAGnD,uFAAuF;AACvF,2FAA2F;AAC3F,+FAA+F;AAC/F,wDAAwD;AAC3C,QAAA,kBAAkB,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,mBAAmB,CAAU,CAAC;AAGjE,QAAA,iBAAiB,GAAG,CAAC,KAAK,EAAE,wBAAwB,CAAU,CAAC;AAG5E,gGAAgG;AAChG,kGAAkG;AAClG,gGAAgG;AAChG,uFAAuF;AAC1E,QAAA,gBAAgB,GAAG,CAAC,KAAK,EAAE,gBAAgB,CAAU,CAAC;AAGnE,8EAA8E;AAC9E,8EAA8E;AAC9E,4EAA4E;AAC5E,gFAAgF;AAChF,8EAA8E;AAC9E,yEAAyE;AACzE,2DAA2D;AAC3D,EAAE;AACF,kGAAkG;AAClG,sGAAsG;AACtG,oCAAoC;AACpC,oGAAoG;AACpG,sEAAsE;AACtE,2GAA2G;AAC3G,uGAAuG;AACvG,mDAAmD;AACnD,yGAAyG;AACzG,iGAAiG;AACjG,8EAA8E;AAC9E,MAAsB,cAAc;IAChC,0FAA0F;IAC1F,8FAA8F;IAC9F,+CAA+C;IAC/C,IAAI,CAAU;IACd,mGAAmG;IACnG,mEAAmE;IACnE,qBAAqB,CAAU;IAC/B,wBAAwB,CAAiB;CAC5C;AATD,wCASC;AAEY,QAAA,gBAAgB,GAAG;IAC5B,qBAAqB,EAAE,IAAI,oBAAQ,CAAC,QAAQ,CAAC;IAC7C,wBAAwB,EAAE,oBAAQ,CAAC,cAAc,EAAE;CACtD,CAAC;AAEF,MAAa,oBAAqB,SAAQ,cAAc;IAEpD,KAAK,CAAU;IACf,cAAc,CAAW;IAEzB,MAAM,CAAU,MAAM,GAAsC;QACxD,IAAI,EAAE,IAAI,oBAAQ,CAAC,QAAQ,EAAE,0BAAkB,CAAC;QAChD,KAAK,EAAE,oBAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAClC,cAAc,EAAE,oBAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC;QAC5C,GAAG,wBAAgB;KACtB,CAAC;;AAVN,oDAWC;AAED,MAAa,kBAAmB,SAAQ,cAAc;IAElD,KAAK,CAAU;IACf,cAAc,CAAW;IAEzB,MAAM,CAAU,MAAM,GAAoC;QACtD,IAAI,EAAE,IAAI,oBAAQ,CAAC,QAAQ,EAAE,wBAAgB,CAAC;QAC9C,KAAK,EAAE,oBAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAClC,cAAc,EAAE,oBAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC;QAC5C,GAAG,wBAAgB;KACtB,CAAC;;AAVN,gDAWC;AAED,MAAa,uBAAwB,SAAQ,cAAc;IAEvD,cAAc,CAAW;IAEzB,MAAM,CAAU,MAAM,GAAyC;QAC3D,IAAI,EAAE,IAAI,oBAAQ,CAAC,QAAQ,EAAE,yBAAiB,CAAC;QAC/C,cAAc,EAAE,oBAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC;QAC5C,GAAG,wBAAgB;KACtB,CAAC;;AARN,0DASC;AAED,MAAa,0BAA2B,SAAQ,cAAc;IAE1D,cAAc,CAAW;IAEzB,MAAM,CAAU,MAAM,GAA4C;QAC9D,IAAI,EAAE,IAAI,oBAAQ,CAAC,QAAQ,EAAE,yBAAiB,CAAC;QAC/C,cAAc,EAAE,oBAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC;QAC5C,GAAG,wBAAgB;KACtB,CAAC;;AARN,gEASC;AAED,MAAa,kBAAmB,SAAQ,cAAc;IAElD,cAAc,CAAW;IAEzB,MAAM,CAAU,MAAM,GAAoC;QACtD,IAAI,EAAE,IAAI,oBAAQ,CAAC,QAAQ,EAAE,2BAAmB,CAAC;QACjD,cAAc,EAAE,oBAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC;QAC5C,GAAG,wBAAgB;KACtB,CAAC;;AARN,gDASC;AAED,MAAa,mBAAoB,SAAQ,cAAc;IAEnD,cAAc,CAAW;IAEzB,MAAM,CAAU,MAAM,GAAqC;QACvD,IAAI,EAAE,IAAI,oBAAQ,CAAC,QAAQ,EAAE,2BAAmB,CAAC;QACjD,cAAc,EAAE,oBAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC;QAC5C,GAAG,wBAAgB;KACtB,CAAC;;AARN,kDASC;AAED,MAAa,wBAAyB,SAAQ,cAAc;IAExD,cAAc,CAAW;IACzB,gBAAgB,CAAU;IAC1B,cAAc,CAAY;IAE1B,MAAM,CAAU,MAAM,GAA0C;QAC5D,IAAI,EAAE,IAAI,oBAAQ,CAAC,QAAQ,EAAE,yBAAiB,CAAC;QAC/C,cAAc,EAAE,oBAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC;QAC5C,gBAAgB,EAAE,oBAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAC7C,cAAc,EAAE,oBAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC;QAC7C,GAAG,wBAAgB;KACtB,CAAC;;AAZN,4DAaC;AAED,MAAa,qBAAsB,SAAQ,cAAc;IAErD,cAAc,CAAW;IACzB,UAAU,CAAU;IACpB,eAAe,CAAY;IAC3B,YAAY,CAAY;IAExB,MAAM,CAAU,MAAM,GAAuC;QACzD,IAAI,EAAE,IAAI,oBAAQ,CAAC,QAAQ,EAAE,8BAAsB,CAAC;QACpD,cAAc,EAAE,oBAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC;QAC5C,UAAU,EAAE,oBAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC;QACvC,eAAe,EAAE,oBAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC;QAC9C,YAAY,EAAE,oBAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC;QAC3C,GAAG,wBAAgB;KACtB,CAAC;;AAdN,sDAeC;AAED,kGAAkG;AAClG,qGAAqG;AACrG,mGAAmG;AACnG,gGAAgG;AAChG,MAAa,mBAAoB,SAAQ,cAAc;IAEnD,aAAa,CAAW;IACxB,cAAc,CAAW;IACzB,YAAY,CAAY;IAExB,MAAM,CAAU,MAAM,GAAqC;QACvD,IAAI,EAAE,IAAI,oBAAQ,CAAC,QAAQ,EAAE,2BAAmB,CAAC;QACjD,aAAa,EAAE,oBAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC;QAC3C,cAAc,EAAE,oBAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC;QAC5C,YAAY,EAAE,oBAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC;QAC3C,GAAG,wBAAgB;KACtB,CAAC;;AAZN,kDAaC;AAED,MAAa,2BAA4B,SAAQ,cAAc;IAE3D,cAAc,CAAW;IAEzB,MAAM,CAAU,MAAM,GAA6C;QAC/D,IAAI,EAAE,IAAI,oBAAQ,CAAC,QAAQ,EAAE,2BAAmB,CAAC;QACjD,cAAc,EAAE,oBAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC;QAC5C,GAAG,wBAAgB;KACtB,CAAC;;AARN,kEASC;AAED,MAAa,uBAAwB,SAAQ,cAAc;IAEvD,cAAc,CAAW;IAEzB,MAAM,CAAU,MAAM,GAAyC;QAC3D,IAAI,EAAE,IAAI,oBAAQ,CAAC,QAAQ,EAAE,2BAAmB,CAAC;QACjD,cAAc,EAAE,oBAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC;QAC5C,GAAG,wBAAgB;KACtB,CAAC;;AARN,0DASC;AAED,MAAa,wBAAyB,SAAQ,cAAc;IAExD,cAAc,CAAW;IAEzB,MAAM,CAAU,MAAM,GAA0C;QAC5D,IAAI,EAAE,IAAI,oBAAQ,CAAC,QAAQ,EAAE,yBAAiB,CAAC;QAC/C,cAAc,EAAE,oBAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC;QAC5C,GAAG,wBAAgB;KACtB,CAAC;;AARN,4DASC;AAED,MAAa,kCAAmC,SAAQ,cAAc;IAElE,cAAc,CAAW;IACzB,YAAY,CAAY;IAExB,MAAM,CAAU,MAAM,GAAoD;QACtE,IAAI,EAAE,IAAI,oBAAQ,CAAC,QAAQ,EAAE,iCAAyB,CAAC;QACvD,cAAc,EAAE,oBAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC;QAC5C,YAAY,EAAE,oBAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC;QAC3C,GAAG,wBAAgB;KACtB,CAAC;;AAVN,gFAWC;AAED,mGAAmG;AACnG,sGAAsG;AACtG,sGAAsG;AACtG,MAAa,iBAAkB,SAAQ,cAAc;IAEjD,cAAc,CAAW;IACzB,UAAU,CAAY;IAEtB,MAAM,CAAU,MAAM,GAAmC;QACrD,IAAI,EAAE,IAAI,oBAAQ,CAAC,QAAQ,EAAE,2BAAmB,CAAC;QACjD,cAAc,EAAE,oBAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC;QAC5C,UAAU,EAAE,oBAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC;QACzC,GAAG,wBAAgB;KACtB,CAAC;;AAVN,8CAWC;AAED,MAAa,sBAAuB,SAAQ,cAAc;IAEtD,cAAc,CAAW;IACzB,YAAY,CAAY;IAExB,MAAM,CAAU,MAAM,GAAwC;QAC1D,IAAI,EAAE,IAAI,oBAAQ,CAAC,QAAQ,EAAE,2BAAmB,CAAC;QACjD,cAAc,EAAE,oBAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC;QAC5C,YAAY,EAAE,oBAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC;QAC3C,GAAG,wBAAgB;KACtB,CAAC;;AAVN,wDAWC;AAED,oGAAoG;AACpG,iGAAiG;AACjG,6FAA6F;AAC7F,8FAA8F;AAC9F,MAAa,8BAA+B,SAAQ,cAAc;IAE9D,cAAc,CAAW;IAEzB,MAAM,CAAU,MAAM,GAAgD;QAClE,IAAI,EAAE,IAAI,oBAAQ,CAAC,QAAQ,EAAE,2BAAmB,CAAC;QACjD,cAAc,EAAE,oBAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC;QAC5C,GAAG,wBAAgB;KACtB,CAAC;;AARN,wEASC;AAED,qGAAqG;AACrG,6FAA6F;AAC7F,qGAAqG;AACrG,yGAAyG;AACzG,sGAAsG;AACtG,oGAAoG;AACpG,qGAAqG;AACrG,sGAAsG;AACtG,8FAA8F;AAC9F,MAAa,4BAA6B,SAAQ,cAAc;IAE5D,cAAc,CAAW;IACzB,YAAY,CAAY;IAExB,MAAM,CAAU,MAAM,GAA8C;QAChE,IAAI,EAAE,IAAI,oBAAQ,CAAC,QAAQ,EAAE,2BAAmB,CAAC;QACjD,cAAc,EAAE,oBAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC;QAC5C,YAAY,EAAE,oBAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC;QAC3C,GAAG,wBAAgB;KACtB,CAAC;;AAVN,oEAWC;AAED,kGAAkG;AAClG,uGAAuG;AACvG,sGAAsG;AACtG,sGAAsG;AACtG,uGAAuG;AACvG,oGAAoG;AACpG,wGAAwG;AACxG,oGAAoG;AACpG,wGAAwG;AACxG,qEAAqE;AACrE,MAAa,+CAAgD,SAAQ,cAAc;IAE/E,cAAc,CAAW;IACzB,YAAY,CAAY;IAExB,MAAM,CAAU,MAAM,GAAiE;QACnF,IAAI,EAAE,IAAI,oBAAQ,CAAC,QAAQ,EAAE,2BAAmB,CAAC;QACjD,cAAc,EAAE,oBAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC;QAC5C,YAAY,EAAE,oBAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC;QAC3C,GAAG,wBAAgB;KACtB,CAAC;;AAVN,0GAWC;AAED,qFAAqF;AACrF,kGAAkG;AAClG,iGAAiG;AACjG,mGAAmG;AACnG,iGAAiG;AACjG,sGAAsG;AACtG,MAAa,kBAAmB,SAAQ,cAAc;IAElD,UAAU,CAAY;IAEtB,MAAM,CAAU,MAAM,GAAoC;QACtD,IAAI,EAAE,IAAI,oBAAQ,CAAC,QAAQ,EAAE,qBAAa,CAAC;QAC3C,UAAU,EAAE,oBAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC;QACzC,GAAG,wBAAgB;KACtB,CAAC;;AARN,gDASC;AAED,8EAA8E;AAC9E,gGAAgG;AAChG,kGAAkG;AAClG,kGAAkG;AAClG,0FAA0F;AAC1F,kFAAkF;AAClF,MAAa,aAAc,SAAQ,cAAc;IAE7C,UAAU,CAAY;IAEtB,MAAM,CAAU,MAAM,GAA+B;QACjD,IAAI,EAAE,IAAI,oBAAQ,CAAC,QAAQ,EAAE,qBAAa,CAAC;QAC3C,UAAU,EAAE,oBAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC;QACzC,GAAG,wBAAgB;KACtB,CAAC;;AARN,sCASC;AAED,MAAa,yBAA0B,SAAQ,cAAc;IAEzD,6FAA6F;IAC7F,6EAA6E;IAC7E,eAAe,CAAU;IACzB,6FAA6F;IAC7F,4FAA4F;IAC5F,YAAY,CAAU;IACtB,kGAAkG;IAClG,+FAA+F;IAC/F,6FAA6F;IAC7F,qFAAqF;IACrF,gBAAgB,CAAU;IAC1B,4FAA4F;IAC5F,+FAA+F;IAC/F,8FAA8F;IAC9F,kFAAkF;IAClF,YAAY,CAAU;IACtB,yFAAyF;IACzF,gGAAgG;IAChG,+FAA+F;IAC/F,2FAA2F;IAC3F,8FAA8F;IAC9F,gGAAgG;IAChG,wFAAwF;IACxF,EAAE;IACF,kGAAkG;IAClG,gGAAgG;IAChG,uBAAuB;IACvB,sBAAsB,CAAW;IAEjC,MAAM,CAAU,MAAM,GAA2C;QAC7D,IAAI,EAAE,IAAI,oBAAQ,CAAC,QAAQ,EAAE,0BAAkB,CAAC;QAChD,eAAe,EAAE,oBAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAC5C,YAAY,EAAE,oBAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC;QACzC,gBAAgB,EAAE,oBAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAC7C,YAAY,EAAE,oBAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC;QACzC,sBAAsB,EAAE,IAAI,oBAAQ,CAAC,SAAS,CAAC;QAC/C,GAAG,wBAAgB;KACtB,CAAC;;AAvCN,8DAwCC;AAED,MAAa,2BAA4B,SAAQ,cAAc;IAE3D,+FAA+F;IAC/F,mFAAmF;IACnF,eAAe,CAAU;IAEzB,MAAM,CAAU,MAAM,GAA6C;QAC/D,IAAI,EAAE,IAAI,oBAAQ,CAAC,QAAQ,EAAE,oBAAY,CAAC;QAC1C,eAAe,EAAE,oBAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAC5C,GAAG,wBAAgB;KACtB,CAAC;;AAVN,kEAWC;AAED,MAAa,0BAA2B,SAAQ,cAAc;IAE1D,+FAA+F;IAC/F,0FAA0F;IAC1F,oBAAoB,CAAU;IAE9B,MAAM,CAAU,MAAM,GAA4C;QAC9D,IAAI,EAAE,IAAI,oBAAQ,CAAC,QAAQ,EAAE,oBAAY,CAAC;QAC1C,oBAAoB,EAAE,oBAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC;QACjD,GAAG,wBAAgB;KACtB,CAAC;;AAVN,gEAWC;AAED,MAAa,kBAAmB,SAAQ,cAAc;IAGlD,MAAM,CAAU,MAAM,GAAoC;QACtD,IAAI,EAAE,IAAI,oBAAQ,CAAC,QAAQ,EAAE,oBAAY,CAAC;QAC1C,GAAG,wBAAgB;KACtB,CAAC;;AANN,gDAOC;AAED,MAAa,4BAA6B,SAAQ,cAAc;IAG5D,MAAM,CAAU,MAAM,GAA8C;QAChE,IAAI,EAAE,IAAI,oBAAQ,CAAC,QAAQ,EAAE,oBAAY,CAAC;QAC1C,GAAG,wBAAgB;KACtB,CAAC;;AANN,oEAOC;AAED,MAAa,wBAAyB,SAAQ,cAAc;IAExD,cAAc,CAAW;IACzB,eAAe,CAAY;IAC3B,0FAA0F;IAC1F,kGAAkG;IAClG,6FAA6F;IAC7F,kGAAkG;IAClG,8FAA8F;IAC9F,yFAAyF;IACzF,oFAAoF;IACpF,aAAa,CAAY;IAEzB,MAAM,CAAU,MAAM,GAA0C;QAC5D,IAAI,EAAE,IAAI,oBAAQ,CAAC,QAAQ,EAAE,wBAAgB,CAAC;QAC9C,cAAc,EAAE,oBAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC;QAC5C,eAAe,EAAE,oBAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC;QAC9C,aAAa,EAAE,oBAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC;QAC5C,GAAG,wBAAgB;KACtB,CAAC;;AAnBN,4DAoBC;AAED,MAAa,yBAA0B,SAAQ,cAAc;IAEzD,kGAAkG;IAClG,0FAA0F;IAC1F,oGAAoG;IACpG,kGAAkG;IAClG,0CAA0C;IAC1C,aAAa,CAAY;IACzB;;;;;OAKG;IACH,iBAAiB,CAAW;IAC5B;;;;;;;;;;;OAWG;IACH,gBAAgB,CAAY;IAE5B,MAAM,CAAU,MAAM,GAA2C;QAC7D,IAAI,EAAE,IAAI,oBAAQ,CAAC,QAAQ,EAAE,wBAAgB,CAAC;QAC9C,aAAa,EAAE,oBAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC;QAC5C,iBAAiB,EAAE,oBAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC;QAC/C,gBAAgB,EAAE,oBAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC;QAC/C,GAAG,wBAAgB;KACtB,CAAC;;AAnCN,8DAoCC;AAED,MAAa,cAAe,SAAQ,cAAc;IAG9C,MAAM,CAAU,MAAM,GAAgC;QAClD,IAAI,EAAE,IAAI,oBAAQ,CAAC,QAAQ,EAAE,wBAAgB,CAAC;QAC9C,GAAG,wBAAgB;KACtB,CAAC;;AANN,wCAOC;AAED,MAAa,aAAc,SAAQ,cAAc;IAK7C,MAAM,CAAU,MAAM,GAA+B;QACjD,IAAI,EAAE,IAAI,oBAAQ,CAAC,QAAQ,EAAE,wBAAgB,CAAC;QAC9C,GAAG,wBAAgB;KACtB,CAAC;;AARN,sCASC;AAED,MAAa,6BAA8B,SAAQ,cAAc;IAK7D,MAAM,CAAU,MAAM,GAA+C;QACjE,IAAI,EAAE,IAAI,oBAAQ,CAAC,QAAQ,EAAE,wBAAgB,CAAC;QAC9C,GAAG,wBAAgB;KACtB,CAAC;;AARN,sEASC;AAED,MAAa,eAAgB,SAAQ,cAAc;IAI/C,YAAY,CAAY;IAExB,MAAM,CAAU,MAAM,GAAiC;QACnD,IAAI,EAAE,IAAI,oBAAQ,CAAC,QAAQ,EAAE,wBAAgB,CAAC;QAC9C,YAAY,EAAE,oBAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC;QAC3C,GAAG,wBAAgB;KACtB,CAAC;;AAVN,0CAWC;AAED,8EAA8E;AAC9E,yFAAyF;AACzF,qGAAqG;AACrG,iGAAiG;AACjG,kGAAkG;AAClG,EAAE;AACF,qGAAqG;AACrG,mGAAmG;AACnG,sGAAsG;AACtG,iGAAiG;AACjG,qGAAqG;AACrG,uGAAuG;AACvG,yFAAyF;AACzF,8EAA8E;AAE9E,MAAa,mCAAoC,SAAQ,cAAc;IAGnE,MAAM,CAAU,MAAM,GAAqD;QACvE,IAAI,EAAE,IAAI,oBAAQ,CAAC,QAAQ,EAAE,wBAAgB,CAAC;QAC9C,GAAG,wBAAgB;KACtB,CAAC;;AANN,kFAOC;AAED,MAAa,kCAAmC,SAAQ,cAAc;IAGlE,MAAM,CAAU,MAAM,GAAoD;QACtE,IAAI,EAAE,IAAI,oBAAQ,CAAC,QAAQ,EAAE,wBAAgB,CAAC;QAC9C,GAAG,wBAAgB;KACtB,CAAC;;AANN,gFAOC;AAED,MAAa,yBAA0B,SAAQ,cAAc;IAGzD,MAAM,CAAU,MAAM,GAA2C;QAC7D,IAAI,EAAE,IAAI,oBAAQ,CAAC,QAAQ,EAAE,wBAAgB,CAAC;QAC9C,GAAG,wBAAgB;KACtB,CAAC;;AANN,8DAOC;AAED,MAAa,4BAA6B,SAAQ,cAAc;IAG5D,MAAM,CAAU,MAAM,GAA8C;QAChE,IAAI,EAAE,IAAI,oBAAQ,CAAC,QAAQ,EAAE,wBAAgB,CAAC;QAC9C,GAAG,wBAAgB;KACtB,CAAC;;AANN,oEAOC;AAED,MAAa,wBAAyB,SAAQ,cAAc;IAGxD,MAAM,CAAU,MAAM,GAA0C;QAC5D,IAAI,EAAE,IAAI,oBAAQ,CAAC,QAAQ,EAAE,wBAAgB,CAAC;QAC9C,GAAG,wBAAgB;KACtB,CAAC;;AANN,4DAOC;AAED,MAAa,qBAAsB,SAAQ,cAAc;IAErD,gBAAgB,CAAY;IAC5B,YAAY,CAAY;IAExB,MAAM,CAAU,MAAM,GAAuC;QACzD,IAAI,EAAE,IAAI,oBAAQ,CAAC,QAAQ,EAAE,yBAAiB,CAAC;QAC/C,gBAAgB,EAAE,oBAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC;QAC/C,YAAY,EAAE,oBAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC;QAC3C,GAAG,wBAAgB;KACtB,CAAC;;AAVN,sDAWC","sourcesContent":["import { FieldDef, SchemaShape } from './field-def';\n\n// Mode const arrays — TypeScript union types derived from them, and FieldDef enum\n// values reference the same array. Impossible for the type and runtime check to diverge.\n\n// Single source of truth for rule \"mode\" values. Exported so code-rules (and any other\n// consumer) imports these instead of re-declaring the same unions — a rename here ripples\n// everywhere at compile time. The FieldDef SCHEMA below references the same arrays, so the\n// type and the runtime validation can never diverge.\nexport const METHOD_LIMIT_MODES = ['OFF', 'NEW_METHODS', 'NEW_AND_MODIFIED_METHODS', 'NEW_AND_MODIFIED_FILES'] as const;\nexport type MethodLimitMode = typeof METHOD_LIMIT_MODES[number];\n\nexport const FILE_LIMIT_MODES = ['OFF', 'NEW_AND_MODIFIED_FILES'] as const;\nexport type FileLimitMode = typeof FILE_LIMIT_MODES[number];\n\nexport const RETURN_TYPE_MODES = ['OFF', 'NEW_METHODS', 'NEW_AND_MODIFIED_METHODS', 'NEW_AND_MODIFIED_FILES'] as const;\nexport type ReturnTypeMode = typeof RETURN_TYPE_MODES[number];\n\nexport const INLINE_TYPE_MODES = ['OFF', 'NEW_METHODS', 'NEW_AND_MODIFIED_METHODS', 'NEW_AND_MODIFIED_FILES'] as const;\nexport type InlineTypeMode = typeof INLINE_TYPE_MODES[number];\n\nexport const MODIFIED_CODE_MODES = ['OFF', 'NEW_AND_MODIFIED_CODE', 'NEW_AND_MODIFIED_FILES'] as const;\nexport type ModifiedCodeMode = typeof MODIFIED_CODE_MODES[number];\n\n// PROJECT-level rules (e.g. framework-tag): the check is neither line- nor file-scoped — it runs\n// for a whole project when ANY file the project owns is touched. `MODIFIED_PROJECTS` names that\n// honestly (nx `affected` already narrows execution to the changed projects).\nexport const PROJECT_MODES = ['OFF', 'MODIFIED_PROJECTS'] as const;\nexport type ProjectMode = typeof PROJECT_MODES[number];\n\nexport const PRISMA_DTOS_MODES = ['OFF', 'MODIFIED_CLASS', 'NEW_AND_MODIFIED_FILES'] as const;\nexport type PrismaValidateDtosMode = typeof PRISMA_DTOS_MODES[number];\n\nexport const PRISMA_CONVERTER_MODES = ['OFF', 'NEW_AND_MODIFIED_METHODS', 'NEW_AND_MODIFIED_FILES'] as const;\nexport type PrismaConverterMode = typeof PRISMA_CONVERTER_MODES[number];\n\nexport const DIRECT_API_RESOLVER_MODES = ['OFF', 'NEW_AND_MODIFIED_CODE', 'NEW_AND_MODIFIED_METHODS', 'NEW_AND_MODIFIED_FILES'] as const;\nexport type DirectApiResolverMode = typeof DIRECT_API_RESOLVER_MODES[number];\n\nexport const THROW_CAUSE_MODES = ['OFF', 'NEW_AND_MODIFIED_CODE'] as const;\nexport type ThrowCauseMode = typeof THROW_CAUSE_MODES[number];\n\nexport const ON_OFF_MODES = ['ON', 'OFF'] as const;\nexport type OnOffMode = typeof ON_OFF_MODES[number];\n\n// branch-creation-guard modes. ON_NO_SUBBRANCHES is the strict variant: it hard-blocks\n// creating a branch off any non-main branch (no sub-branch affordance), pointing the agent\n// back to `git checkout main && git pull && git checkout -b <branch>`. Temporarily overridable\n// via the universal turnOffRuleUntilEpoch escape hatch.\nexport const BRANCH_GUARD_MODES = ['ON', 'OFF', 'ON_NO_SUBBRANCHES'] as const;\nexport type BranchGuardMode = typeof BRANCH_GUARD_MODES[number];\n\nexport const VALIDATE_TS_MODES = ['OFF', 'NEW_AND_MODIFIED_FILES'] as const;\nexport type ValidateTsMode = typeof VALIDATE_TS_MODES[number];\n\n// Structural / whole-graph rules (import-cycle, runtime-architecture, nx-wiring). They can't be\n// scoped to changed lines/files — a cycle or wiring break can route through a project that wasn't\n// itself edited — so when active they run the FULL check every time (nx-affected already limits\n// them to affected projects externally). RUN_EVERY_TIME replaces the old, vaguer \"ON\".\nexport const STRUCTURAL_MODES = ['OFF', 'RUN_EVERY_TIME'] as const;\nexport type StructuralMode = typeof STRUCTURAL_MODES[number];\n\n// ---------------------------------------------------------------------------\n// Universal escape hatches — EVERY rule supports temporarily disabling itself\n// either while on a named git branch (turnOffRuleWhileOnBranch) or until an\n// epoch passes (turnOffRuleUntilEpoch). They live on a shared base class so the\n// fields (and their schema entries) are declared once instead of repeated per\n// rule. `mode` stays per-rule because its allowed values vary (ON/OFF vs\n// NEW_AND_MODIFIED_CODE vs NEW_AND_MODIFIED_METHODS, etc).\n//\n// BOTH fields are REQUIRED on every rule so both hatches are ALWAYS VISIBLE in the config — an AI\n// editing webpieces.config.json sees them on every rule and cannot miss that a rule can be time-boxed\n// or branch-scoped off. Convention:\n// turnOffRuleUntilEpoch: 0 = rule active (epoch in the past); a future unix epoch IN SECONDS =\n// temporarily disabled until that moment.\n// turnOffRuleWhileOnBranch: null = always on; a branch name = disabled while that branch is checked out.\n// Required-but-nullable so its \"unset\" state is present-and-visible (null)\n// rather than omitted.\n// The earlier names `ignoreModifiedUntilEpoch` / `ignoreRuleWhileOnBranch` were RENAMED to these and are\n// no longer accepted — the validator flags them with a \"renamed to X\" hint (validate-config.ts).\n// ---------------------------------------------------------------------------\nexport abstract class BaseRuleConfig {\n // `mode` is declared here (loosely typed) so the shared AbstractRule base can read it for\n // on/off. Each concrete *Config narrows it to its own union (e.g. `mode?: ModifiedCodeMode`),\n // which is an assignable (covariant) override.\n mode?: string;\n // TS-optional, but schema-REQUIRED (see BASE_RULE_SCHEMA) — same split as `mode`. Read directly by\n // AbstractRule.shouldRun, RuleGate, and the code-rules validators.\n turnOffRuleUntilEpoch?: number;\n turnOffRuleWhileOnBranch?: string | null;\n}\n\nexport const BASE_RULE_SCHEMA = {\n turnOffRuleUntilEpoch: new FieldDef('number'),\n turnOffRuleWhileOnBranch: FieldDef.nullableString(),\n};\n\nexport class MaxMethodLinesConfig extends BaseRuleConfig {\n declare mode?: MethodLimitMode;\n limit?: number;\n disableAllowed?: boolean;\n\n static readonly SCHEMA: SchemaShape<MaxMethodLinesConfig> = {\n mode: new FieldDef('string', METHOD_LIMIT_MODES),\n limit: FieldDef.optional('number'),\n disableAllowed: FieldDef.optional('boolean'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class MaxFileLinesConfig extends BaseRuleConfig {\n declare mode?: FileLimitMode;\n limit?: number;\n disableAllowed?: boolean;\n\n static readonly SCHEMA: SchemaShape<MaxFileLinesConfig> = {\n mode: new FieldDef('string', FILE_LIMIT_MODES),\n limit: FieldDef.optional('number'),\n disableAllowed: FieldDef.optional('boolean'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class RequireReturnTypeConfig extends BaseRuleConfig {\n declare mode?: ReturnTypeMode;\n disableAllowed?: boolean;\n\n static readonly SCHEMA: SchemaShape<RequireReturnTypeConfig> = {\n mode: new FieldDef('string', RETURN_TYPE_MODES),\n disableAllowed: FieldDef.optional('boolean'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class NoInlineTypeLiteralsConfig extends BaseRuleConfig {\n declare mode?: InlineTypeMode;\n disableAllowed?: boolean;\n\n static readonly SCHEMA: SchemaShape<NoInlineTypeLiteralsConfig> = {\n mode: new FieldDef('string', INLINE_TYPE_MODES),\n disableAllowed: FieldDef.optional('boolean'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class NoAnyUnknownConfig extends BaseRuleConfig {\n declare mode?: ModifiedCodeMode;\n disableAllowed?: boolean;\n\n static readonly SCHEMA: SchemaShape<NoAnyUnknownConfig> = {\n mode: new FieldDef('string', MODIFIED_CODE_MODES),\n disableAllowed: FieldDef.optional('boolean'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class NoImplicitAnyConfig extends BaseRuleConfig {\n declare mode?: ModifiedCodeMode;\n disableAllowed?: boolean;\n\n static readonly SCHEMA: SchemaShape<NoImplicitAnyConfig> = {\n mode: new FieldDef('string', MODIFIED_CODE_MODES),\n disableAllowed: FieldDef.optional('boolean'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class PrismaValidateDtosConfig extends BaseRuleConfig {\n declare mode?: PrismaValidateDtosMode;\n disableAllowed?: boolean;\n prismaSchemaPath?: string;\n dtoSourcePaths?: string[];\n\n static readonly SCHEMA: SchemaShape<PrismaValidateDtosConfig> = {\n mode: new FieldDef('string', PRISMA_DTOS_MODES),\n disableAllowed: FieldDef.optional('boolean'),\n prismaSchemaPath: FieldDef.optional('string'),\n dtoSourcePaths: FieldDef.optional('string[]'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class PrismaConverterConfig extends BaseRuleConfig {\n declare mode?: PrismaConverterMode;\n disableAllowed?: boolean;\n schemaPath?: string;\n convertersPaths?: string[];\n enforcePaths?: string[];\n\n static readonly SCHEMA: SchemaShape<PrismaConverterConfig> = {\n mode: new FieldDef('string', PRISMA_CONVERTER_MODES),\n disableAllowed: FieldDef.optional('boolean'),\n schemaPath: FieldDef.optional('string'),\n convertersPaths: FieldDef.optional('string[]'),\n enforcePaths: FieldDef.optional('string[]'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\n// `allowedPaths` exempts whole file trees whose idioms are destructuring by construction (React /\n// React Native components and hooks — `const [x, setX] = useState()`, destructured props — framework\n// glue), matched with the shared glob/prefix/segment semantics of `isPathExcluded`. It is the ONLY\n// escape when `disableAllowed: false`, since that setting deliberately ignores inline disables.\nexport class NoDestructureConfig extends BaseRuleConfig {\n declare mode?: ModifiedCodeMode;\n allowTopLevel?: boolean;\n disableAllowed?: boolean;\n allowedPaths?: string[];\n\n static readonly SCHEMA: SchemaShape<NoDestructureConfig> = {\n mode: new FieldDef('string', MODIFIED_CODE_MODES),\n allowTopLevel: FieldDef.optional('boolean'),\n disableAllowed: FieldDef.optional('boolean'),\n allowedPaths: FieldDef.optional('string[]'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class NoUnmanagedExceptionsConfig extends BaseRuleConfig {\n declare mode?: ModifiedCodeMode;\n disableAllowed?: boolean;\n\n static readonly SCHEMA: SchemaShape<NoUnmanagedExceptionsConfig> = {\n mode: new FieldDef('string', MODIFIED_CODE_MODES),\n disableAllowed: FieldDef.optional('boolean'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class CatchErrorPatternConfig extends BaseRuleConfig {\n declare mode?: ModifiedCodeMode;\n disableAllowed?: boolean;\n\n static readonly SCHEMA: SchemaShape<CatchErrorPatternConfig> = {\n mode: new FieldDef('string', MODIFIED_CODE_MODES),\n disableAllowed: FieldDef.optional('boolean'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class ThrowCauseRequiredConfig extends BaseRuleConfig {\n declare mode?: ThrowCauseMode;\n disableAllowed?: boolean;\n\n static readonly SCHEMA: SchemaShape<ThrowCauseRequiredConfig> = {\n mode: new FieldDef('string', THROW_CAUSE_MODES),\n disableAllowed: FieldDef.optional('boolean'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class AngularNoDirectApiInResolverConfig extends BaseRuleConfig {\n declare mode?: DirectApiResolverMode;\n disableAllowed?: boolean;\n enforcePaths?: string[];\n\n static readonly SCHEMA: SchemaShape<AngularNoDirectApiInResolverConfig> = {\n mode: new FieldDef('string', DIRECT_API_RESOLVER_MODES),\n disableAllowed: FieldDef.optional('boolean'),\n enforcePaths: FieldDef.optional('string[]'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\n// Bans hand-written CSS in Angular sources (styles:/styleUrls:/styleUrl: in @Component, and inline\n// style=/[style.x]/[ngStyle] in templates) so teams style with Tailwind utility classes. `allowGlobs`\n// exempts paths WITHIN the Angular scope (e.g. a vendored Fuse kit copied verbatim with its own CSS).\nexport class NoCustomCssConfig extends BaseRuleConfig {\n declare mode?: ModifiedCodeMode;\n disableAllowed?: boolean;\n allowGlobs?: string[];\n\n static readonly SCHEMA: SchemaShape<NoCustomCssConfig> = {\n mode: new FieldDef('string', MODIFIED_CODE_MODES),\n disableAllowed: FieldDef.optional('boolean'),\n allowGlobs: FieldDef.optional('string[]'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class NoSymbolDiTokensConfig extends BaseRuleConfig {\n declare mode?: ModifiedCodeMode;\n disableAllowed?: boolean;\n allowedPaths?: string[];\n\n static readonly SCHEMA: SchemaShape<NoSymbolDiTokensConfig> = {\n mode: new FieldDef('string', MODIFIED_CODE_MODES),\n disableAllowed: FieldDef.optional('boolean'),\n allowedPaths: FieldDef.optional('string[]'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\n// Flags `process.exit(...)` outside a main()/runMain wrapper (and `import { main }`) so a deep exit\n// can't silently kill a reused server/command. Gradual-rollout knobs via the standard base: mode\n// (OFF | NEW_AND_MODIFIED_CODE | NEW_AND_MODIFIED_FILES), turnOffRuleUntilEpoch, branch, and\n// disableAllowed for the inline `// webpieces-disable` escape at genuine terminal boundaries.\nexport class NoProcessExitOutsideMainConfig extends BaseRuleConfig {\n declare mode?: ModifiedCodeMode;\n disableAllowed?: boolean;\n\n static readonly SCHEMA: SchemaShape<NoProcessExitOutsideMainConfig> = {\n mode: new FieldDef('string', MODIFIED_CODE_MODES),\n disableAllowed: FieldDef.optional('boolean'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\n// Flags a function CREATED OUTSIDE A CLASS at module scope: a top-level `function foo()` declaration\n// or a top-level `const foo = () => {}` / `= function(){}`. The point is that webpieces DI +\n// @DocumentDesign only work when behavior lives in injectable classes — a module-scope function is a\n// dead-end the DI graph can't reach. Inline callbacks, nested functions inside methods, and non-function\n// top-level consts (objects, zod schemas, primitives) are NOT flagged. Standard rollout knobs via the\n// base: mode (OFF | NEW_AND_MODIFIED_CODE | NEW_AND_MODIFIED_FILES), turnOffRuleUntilEpoch, branch,\n// and disableAllowed for the inline `// webpieces-disable` escape. `allowedPaths` exempts whole file\n// trees that legitimately live outside the class-per-behavior model (e.g. React component/hook files,\n// framework glue), matched with the shared glob/prefix/segment semantics of `isPathExcluded`.\nexport class NoFunctionOutsideClassConfig extends BaseRuleConfig {\n declare mode?: ModifiedCodeMode;\n disableAllowed?: boolean;\n allowedPaths?: string[];\n\n static readonly SCHEMA: SchemaShape<NoFunctionOutsideClassConfig> = {\n mode: new FieldDef('string', MODIFIED_CODE_MODES),\n disableAllowed: FieldDef.optional('boolean'),\n allowedPaths: FieldDef.optional('string[]'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\n// inject-annotation-not-needed-for-concrete-class — flags a REDUNDANT `@inject(X)` whose token is\n// textually identical to the parameter's own declared type (`@inject(Foo) private readonly foo: Foo`).\n// In this inversify setup the decorator is pure noise there: reflect-metadata (emitDecoratorMetadata)\n// already resolves a constructor parameter by its class type, so `private readonly foo: Foo` binds on\n// its own (see CLAUDE.md, and the no-symbol-di-tokens rule that pushes the same way). Symbol/interface\n// tokens are NOT flagged because they never equal the type (`@inject(FOO_TOKEN) x: Provider<Foo>`).\n// AI keeps carpet-bombing `@inject`; this fails the build on the redundant form. Standard rollout knobs\n// via the base: mode (OFF | NEW_AND_MODIFIED_CODE | NEW_AND_MODIFIED_FILES), turnOffRuleUntilEpoch,\n// branch, and disableAllowed for the inline `// webpieces-disable` escape. `allowedPaths` exempts whole\n// file trees, matched with the shared glob/prefix/segment semantics.\nexport class InjectAnnotationNotNeededForConcreteClassConfig extends BaseRuleConfig {\n declare mode?: ModifiedCodeMode;\n disableAllowed?: boolean;\n allowedPaths?: string[];\n\n static readonly SCHEMA: SchemaShape<InjectAnnotationNotNeededForConcreteClassConfig> = {\n mode: new FieldDef('string', MODIFIED_CODE_MODES),\n disableAllowed: FieldDef.optional('boolean'),\n allowedPaths: FieldDef.optional('string[]'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\n// framework-tag — every project that a changed source file belongs to must carry >=1\n// `framework:<browser|react|angular|node|express>` nx tag in its project.json. Those tags are the\n// project's \"libType\" — the SET of runtime environments it runs in — and the source of truth for\n// the dependencies.json `framework` field and the `library-types-match-client` rule. Multiple tags\n// are allowed (the env set) and values are validated against the known set (`framework:all` is a\n// hard error). `knownTypes` customizes that set (defaults to browser, react, angular, node, express).\nexport class FrameworkTagConfig extends BaseRuleConfig {\n declare mode?: ProjectMode;\n knownTypes?: string[];\n\n static readonly SCHEMA: SchemaShape<FrameworkTagConfig> = {\n mode: new FieldDef('string', PROJECT_MODES),\n knownTypes: FieldDef.optional('string[]'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\n// role-tag — every project that a changed source file belongs to must carry a\n// `role:<server|designed-lib|lib|client>` nx tag in its project.json. That tag is the project's\n// ROLE (orthogonal to `framework` libType) — the source of truth for the dependencies.json `role`\n// field, the `role-dependency` edge rule (apps are never depended upon), and DI-design generation\n// (server→@Controller, designed-lib→@ApiImplementation, lib→none, client→angular design).\n// `knownTypes` customizes the list suggested to the author when a tag is missing.\nexport class RoleTagConfig extends BaseRuleConfig {\n declare mode?: ProjectMode;\n knownTypes?: string[];\n\n static readonly SCHEMA: SchemaShape<RoleTagConfig> = {\n mode: new FieldDef('string', PROJECT_MODES),\n knownTypes: FieldDef.optional('string[]'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class BranchCreationGuardConfig extends BaseRuleConfig {\n declare mode?: BranchGuardMode;\n // Naming pattern for stacked SUB-branches only (branches created off another feature branch,\n // which require human approval). Never applied to branches created off main.\n subBranchNaming?: string;\n // Human-sentence instruction telling the AI how to name a NEW branch off main. Surfaced back\n // to the agent in the guard's fix hints. May mirror no-edit-on-main.branchNamingConvention.\n branchFormat?: string;\n // Hard cap on local feature branches (excluding main). Creating one past the cap is BLOCKED until\n // already-merged branches are reaped, which is what keeps the branch list from growing without\n // bound. Branch creation is the gate because it is the only moment cleanup is both cheap and\n // obviously worth it. See merged-branches.ts for how \"already merged\" is determined.\n maxLocalBranches?: number;\n // Hard cap on LINKED worktrees (the primary clone is never counted). A separate budget from\n // maxLocalBranches: every worktree holds a branch, so if worktree-held branches also spent the\n // branch budget, five worktrees would leave room for zero branches. Held branches count here;\n // parked branches count against maxLocalBranches. Enforced at `git worktree add`.\n maxWorktrees?: number;\n // Let the detached background refresher DELETE dead branches on its own, instead of only\n // reporting them. Every candidate is provably dead (merged PR / squash backup / no commits) and\n // recoverable by the SHA logged to branch-mutations.log — but it is still UNATTENDED deletion,\n // so this is schema-REQUIRED like `mode` and `turnOffRuleUntilEpoch`. \"Every built-in rule\n // must be explicitly configured — no silent defaults\" (validate-config.ts) applies with extra\n // force here: branches disappearing on a preference nobody ever stated is precisely the kind of\n // default that must not exist. Validation makes each consumer answer the question once.\n //\n // TS-optional but schema-required — the same split `mode` uses. Absent at RUNTIME therefore means\n // the config never passed validation, and the only safe reading of \"nobody has answered\" is: do\n // not delete anything.\n autoReapMergedBranches?: boolean;\n\n static readonly SCHEMA: SchemaShape<BranchCreationGuardConfig> = {\n mode: new FieldDef('string', BRANCH_GUARD_MODES),\n subBranchNaming: FieldDef.optional('string'),\n branchFormat: FieldDef.optional('string'),\n maxLocalBranches: FieldDef.optional('number'),\n maxWorktrees: FieldDef.optional('number'),\n autoReapMergedBranches: new FieldDef('boolean'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class PrCreationOrPushGuardConfig extends BaseRuleConfig {\n declare mode?: OnOffMode;\n // The gated command the guard points agents to instead of direct PR creation OR a manual push.\n // Per-project override; defaults to `pnpm wp-start-upsert-pr` at the point of use.\n upsertPrCommand?: string;\n\n static readonly SCHEMA: SchemaShape<PrCreationOrPushGuardConfig> = {\n mode: new FieldDef('string', ON_OFF_MODES),\n upsertPrCommand: FieldDef.optional('string'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class MergeInProgressGuardConfig extends BaseRuleConfig {\n declare mode?: OnOffMode;\n // The gated command the guard points agents to in order to finish a 3-point merge. Per-project\n // override; defaults to `commands.mergeComplete` (pnpm wp-finish-upsert-pr) at load time.\n mergeCompleteCommand?: string;\n\n static readonly SCHEMA: SchemaShape<MergeInProgressGuardConfig> = {\n mode: new FieldDef('string', ON_OFF_MODES),\n mergeCompleteCommand: FieldDef.optional('string'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class PrMergeGuardConfig extends BaseRuleConfig {\n declare mode?: OnOffMode;\n\n static readonly SCHEMA: SchemaShape<PrMergeGuardConfig> = {\n mode: new FieldDef('string', ON_OFF_MODES),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class RedirectHowToMergeMainConfig extends BaseRuleConfig {\n declare mode?: OnOffMode;\n\n static readonly SCHEMA: SchemaShape<RedirectHowToMergeMainConfig> = {\n mode: new FieldDef('string', ON_OFF_MODES),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class NoFileImportCyclesConfig extends BaseRuleConfig {\n declare mode?: StructuralMode;\n ignoreTypeOnly?: boolean;\n excludePackages?: string[];\n // Raw regex escape hatch for a cycle inside the project being checked — generated code, a\n // vendored tree, or a deliberate bidirectional domain model — that `excludePackages` cannot reach\n // (it resolves npm package NAMES, so it only excludes a *sibling* package, never a directory\n // inside this one). Patterns are handed to madge verbatim and matched against ids RELATIVE TO THE\n // PROJECT (e.g. \"^src/generated/\", \"^src/modules/(item|category)/\") — NOT workspace-rooted or\n // absolute, which silently match nothing. The executor warns when a pattern matches zero\n // traversed files, so a mis-anchored pattern is visible rather than a silent no-op.\n excludeRegExp?: string[];\n\n static readonly SCHEMA: SchemaShape<NoFileImportCyclesConfig> = {\n mode: new FieldDef('string', STRUCTURAL_MODES),\n ignoreTypeOnly: FieldDef.optional('boolean'),\n excludePackages: FieldDef.optional('string[]'),\n excludeRegExp: FieldDef.optional('string[]'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class RuntimeArchitectureConfig extends BaseRuleConfig {\n declare mode?: StructuralMode;\n // NOTE: `servicePaths` / `apiProjectPaths` were removed — they were never read. The runtime graph\n // is derived SOLELY from architecture/dependencies.json apiRelations + project roles (see\n // nx-webpieces-rules/src/lib/runtime-graph.ts), so any config still listing them (a hand-maintained\n // enumeration of api libs) now fails the unknown-field check in validateWebpiecesConfig. There is\n // nothing to enumerate — delete the keys.\n allowedCycles?: string[];\n /**\n * Draw a dashed terminal node for every contract a service calls that NOTHING in-repo\n * implements (firestore, gmail, ...) — the vendor systems the runtime graph otherwise stops one\n * hop short of. Defaults to true; set false in a repo whose external surface is noisy. Purely a\n * RENDER switch: levels, cycle detection and runtime-dependencies.json are identical either way.\n */\n showExternalNodes?: boolean;\n /**\n * Project roots whose exported `*Api` types are contracts for systems OUTSIDE this repo\n * (firestore, gmail, gcp-storage, ...), e.g. `[\"libraries/apis/external/**\"]`. Globs, matched\n * against the nx project root.\n *\n * Needed because an external contract does NOT look like an in-repo one: it is a plain\n * `interface` bound to a Symbol token and injected, never an `abstract class` carrying @ApiPath\n * reached through `createRpcClient`. Without this list the scanner has no way to tell a vendor\n * seam from any other library, so every call leaving the repo is invisible to the runtime graph.\n *\n * Defaults to none, which is correct for a repo with no vendor wrapper libraries.\n */\n externalApiPaths?: string[];\n\n static readonly SCHEMA: SchemaShape<RuntimeArchitectureConfig> = {\n mode: new FieldDef('string', STRUCTURAL_MODES),\n allowedCycles: FieldDef.optional('string[]'),\n showExternalNodes: FieldDef.optional('boolean'),\n externalApiPaths: FieldDef.optional('string[]'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class NxWiringConfig extends BaseRuleConfig {\n declare mode?: StructuralMode;\n\n static readonly SCHEMA: SchemaShape<NxWiringConfig> = {\n mode: new FieldDef('string', STRUCTURAL_MODES),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class DiGraphConfig extends BaseRuleConfig {\n // Structural: the DI graph is regenerated whole-project on every build (generate +\n // unchanged gate), so it cannot be scoped to changed lines.\n declare mode?: StructuralMode;\n\n static readonly SCHEMA: SchemaShape<DiGraphConfig> = {\n mode: new FieldDef('string', STRUCTURAL_MODES),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class MissingDesignAnnotationConfig extends BaseRuleConfig {\n // Structural: enforced per-project by the di-graph-generate executor, which\n // roots the whole DI design on @DocumentDesign classes — cannot be line-scoped.\n declare mode?: StructuralMode;\n\n static readonly SCHEMA: SchemaShape<MissingDesignAnnotationConfig> = {\n mode: new FieldDef('string', STRUCTURAL_MODES),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class NoJsFilesConfig extends BaseRuleConfig {\n // File-tier: NEW_AND_MODIFIED_FILES (active) intercepts a .js/.jsx Write — the file being\n // written is inherently a new/modified file, so it's already diff-scoped in practice.\n declare mode?: FileLimitMode;\n allowedPaths?: string[];\n\n static readonly SCHEMA: SchemaShape<NoJsFilesConfig> = {\n mode: new FieldDef('string', FILE_LIMIT_MODES),\n allowedPaths: FieldDef.optional('string[]'),\n ...BASE_RULE_SCHEMA,\n };\n}\n\n// ---------------------------------------------------------------------------\n// The five Nx infrastructure validators (architecture-unchanged, no-architecture-cycles,\n// packagejson, versions-locked, eslint-sync). Each is whole-graph / whole-repo by nature (a cycle, a\n// drifted dependencies.json, an unlocked version can be introduced by a file nobody in this diff\n// touched), so the only honest mode set is STRUCTURAL_MODES: RUN_EVERY_TIME (the default) or OFF.\n//\n// All five now honor the universal escape hatches (turnOffRuleUntilEpoch / turnOffRuleWhileOnBranch,\n// and their ignore* aliases) via shouldSkipRule — the RuleGate is called with honorEpoch:true from\n// every executor. This lets a repo time-box or branch-scope a failing infrastructure check (e.g. hold\n// validate-packagejson off until an upgrade PR lands) with a one-value edit, instead of only the\n// blunt \"mode\": \"OFF\". Originally packagejson/versions-locked/eslint-sync were all-or-nothing on the\n// theory that \"no blessed baseline\" made grandfathering meaningless, but a time-box is a schedule, not\n// a baseline: \"do not enforce this until <epoch>/off <branch>\" is coherent for any rule.\n// ---------------------------------------------------------------------------\n\nexport class ValidateArchitectureUnchangedConfig extends BaseRuleConfig {\n declare mode?: StructuralMode;\n\n static readonly SCHEMA: SchemaShape<ValidateArchitectureUnchangedConfig> = {\n mode: new FieldDef('string', STRUCTURAL_MODES),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class ValidateNoArchitectureCyclesConfig extends BaseRuleConfig {\n declare mode?: StructuralMode;\n\n static readonly SCHEMA: SchemaShape<ValidateNoArchitectureCyclesConfig> = {\n mode: new FieldDef('string', STRUCTURAL_MODES),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class ValidatePackageJsonConfig extends BaseRuleConfig {\n declare mode?: StructuralMode;\n\n static readonly SCHEMA: SchemaShape<ValidatePackageJsonConfig> = {\n mode: new FieldDef('string', STRUCTURAL_MODES),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class ValidateVersionsLockedConfig extends BaseRuleConfig {\n declare mode?: StructuralMode;\n\n static readonly SCHEMA: SchemaShape<ValidateVersionsLockedConfig> = {\n mode: new FieldDef('string', STRUCTURAL_MODES),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class ValidateEslintSyncConfig extends BaseRuleConfig {\n declare mode?: StructuralMode;\n\n static readonly SCHEMA: SchemaShape<ValidateEslintSyncConfig> = {\n mode: new FieldDef('string', STRUCTURAL_MODES),\n ...BASE_RULE_SCHEMA,\n };\n}\n\nexport class ValidateTsInSrcConfig extends BaseRuleConfig {\n declare mode?: ValidateTsMode;\n allowedRootFiles?: string[];\n excludePaths?: string[];\n\n static readonly SCHEMA: SchemaShape<ValidateTsInSrcConfig> = {\n mode: new FieldDef('string', VALIDATE_TS_MODES),\n allowedRootFiles: FieldDef.optional('string[]'),\n excludePaths: FieldDef.optional('string[]'),\n ...BASE_RULE_SCHEMA,\n };\n}\n"]}
@@ -3,4 +3,4 @@ export interface SkipRuleResult {
3
3
  reason?: string;
4
4
  }
5
5
  export declare function getCurrentBranch(): string;
6
- export declare function shouldSkipRule(epoch: number | undefined, branchPattern: string | undefined): SkipRuleResult;
6
+ export declare function shouldSkipRule(epoch: number | undefined, branchPattern: string | undefined | null): SkipRuleResult;
package/src/skip-rule.js CHANGED
@@ -20,7 +20,10 @@ function getCurrentBranch() {
20
20
  throw new inform_ai_error_1.InformAiError(`Failed to determine current git branch: ${error.message}`, { cause: error });
21
21
  }
22
22
  }
23
- function shouldSkipRule(epoch, branchPattern) {
23
+ function shouldSkipRule(epoch,
24
+ // null (the "no branch / always on" value of turnOffRuleWhileOnBranch) is treated exactly like
25
+ // undefined — no branch scoping. Only a non-empty branch name activates the branch hatch.
26
+ branchPattern) {
24
27
  if (branchPattern) {
25
28
  const current = getCurrentBranch();
26
29
  if (current === branchPattern) {
@@ -31,7 +34,7 @@ function shouldSkipRule(epoch, branchPattern) {
31
34
  const nowSeconds = Date.now() / 1000;
32
35
  if (nowSeconds < epoch) {
33
36
  const expiresDate = new Date(epoch * 1000).toISOString().split('T')[0];
34
- return { skip: true, reason: `ignoreModifiedUntilEpoch active, expires: ${expiresDate}` };
37
+ return { skip: true, reason: `turnOffRuleUntilEpoch active, expires: ${expiresDate}` };
35
38
  }
36
39
  }
37
40
  return { skip: false };
@@ -1 +1 @@
1
- {"version":3,"file":"skip-rule.js","sourceRoot":"","sources":["../../../../../packages/tooling/rules-config/src/skip-rule.ts"],"names":[],"mappings":";;AAmBA,4CASC;AAED,wCAkBC;AAhDD,iDAAyC;AAEzC,uDAAkD;AAClD,yCAAqC;AAYrC,+FAA+F;AAC/F,kGAAkG;AAClG,oGAAoG;AACpG,oGAAoG;AACpG,SAAgB,gBAAgB;IAC5B,wHAAwH;IACxH,0IAA0I;IAC1I,IAAI,CAAC;QACD,OAAO,IAAA,wBAAQ,EAAC,iCAAiC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACpF,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACpB,MAAM,KAAK,GAAG,IAAA,kBAAO,EAAC,GAAG,CAAC,CAAC;QAC3B,MAAM,IAAI,+BAAa,CAAC,2CAA2C,KAAK,CAAC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IAC1G,CAAC;AACL,CAAC;AAED,SAAgB,cAAc,CAC1B,KAAyB,EACzB,aAAiC;IAEjC,IAAI,aAAa,EAAE,CAAC;QAChB,MAAM,OAAO,GAAG,gBAAgB,EAAE,CAAC;QACnC,IAAI,OAAO,KAAK,aAAa,EAAE,CAAC;YAC5B,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,aAAa,GAAG,EAAE,CAAC;QAClE,CAAC;IACL,CAAC;IACD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACtB,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;QACrC,IAAI,UAAU,GAAG,KAAK,EAAE,CAAC;YACrB,MAAM,WAAW,GAAG,IAAI,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YACvE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,6CAA6C,WAAW,EAAE,EAAE,CAAC;QAC9F,CAAC;IACL,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;AAC3B,CAAC","sourcesContent":["import { execSync } from 'child_process';\n\nimport { InformAiError } from './inform-ai-error';\nimport { toError } from './to-error';\n\n// Universal \"should this rule be skipped right now?\" logic, shared by code-rules,\n// ai-hook-rules and the Nx executors so every rule honors the same two escape\n// hatches: ignoreRuleWhileOnBranch (skip while on a named branch) and\n// ignoreModifiedUntilEpoch (skip until an epoch passes).\n\nexport interface SkipRuleResult {\n skip: boolean;\n reason?: string;\n}\n\n// The actual checked-out branch. Always uses git directly — env vars (BRANCH_NAME, GIT_BRANCH,\n// GITHUB_*, CI_COMMIT_BRANCH, …) were intentionally REMOVED: a stray GIT_BRANCH=main locally made\n// this return \"main\" on a feature branch, which (a) mislabeled the main-sync cache and (b) silently\n// disabled merged-PR detection (detectMergedPr skips \"main\"). git rev-parse is the source of truth.\nexport function getCurrentBranch(): string {\n // webpieces-disable no-unmanaged-exceptions -- rethrow as InformAiError so global catch surfaces readable message to AI\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- rethrow as InformAiError so global catch surfaces readable message to AI\n try {\n return execSync('git rev-parse --abbrev-ref HEAD', { encoding: 'utf8' }).trim();\n } catch (err: unknown) {\n const error = toError(err);\n throw new InformAiError(`Failed to determine current git branch: ${error.message}`, { cause: error });\n }\n}\n\nexport function shouldSkipRule(\n epoch: number | undefined,\n branchPattern: string | undefined\n): SkipRuleResult {\n if (branchPattern) {\n const current = getCurrentBranch();\n if (current === branchPattern) {\n return { skip: true, reason: `on branch \"${branchPattern}\"` };\n }\n }\n if (epoch !== undefined) {\n const nowSeconds = Date.now() / 1000;\n if (nowSeconds < epoch) {\n const expiresDate = new Date(epoch * 1000).toISOString().split('T')[0];\n return { skip: true, reason: `ignoreModifiedUntilEpoch active, expires: ${expiresDate}` };\n }\n }\n return { skip: false };\n}\n"]}
1
+ {"version":3,"file":"skip-rule.js","sourceRoot":"","sources":["../../../../../packages/tooling/rules-config/src/skip-rule.ts"],"names":[],"mappings":";;AAmBA,4CASC;AAED,wCAoBC;AAlDD,iDAAyC;AAEzC,uDAAkD;AAClD,yCAAqC;AAYrC,+FAA+F;AAC/F,kGAAkG;AAClG,oGAAoG;AACpG,oGAAoG;AACpG,SAAgB,gBAAgB;IAC5B,wHAAwH;IACxH,0IAA0I;IAC1I,IAAI,CAAC;QACD,OAAO,IAAA,wBAAQ,EAAC,iCAAiC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACpF,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACpB,MAAM,KAAK,GAAG,IAAA,kBAAO,EAAC,GAAG,CAAC,CAAC;QAC3B,MAAM,IAAI,+BAAa,CAAC,2CAA2C,KAAK,CAAC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IAC1G,CAAC;AACL,CAAC;AAED,SAAgB,cAAc,CAC1B,KAAyB;AACzB,+FAA+F;AAC/F,0FAA0F;AAC1F,aAAwC;IAExC,IAAI,aAAa,EAAE,CAAC;QAChB,MAAM,OAAO,GAAG,gBAAgB,EAAE,CAAC;QACnC,IAAI,OAAO,KAAK,aAAa,EAAE,CAAC;YAC5B,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,aAAa,GAAG,EAAE,CAAC;QAClE,CAAC;IACL,CAAC;IACD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACtB,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;QACrC,IAAI,UAAU,GAAG,KAAK,EAAE,CAAC;YACrB,MAAM,WAAW,GAAG,IAAI,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YACvE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,0CAA0C,WAAW,EAAE,EAAE,CAAC;QAC3F,CAAC;IACL,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;AAC3B,CAAC","sourcesContent":["import { execSync } from 'child_process';\n\nimport { InformAiError } from './inform-ai-error';\nimport { toError } from './to-error';\n\n// Universal \"should this rule be skipped right now?\" logic, shared by code-rules,\n// ai-hook-rules and the Nx executors so every rule honors the same two escape\n// hatches: turnOffRuleWhileOnBranch (skip while on a named branch) and\n// turnOffRuleUntilEpoch (skip until an epoch passes).\n\nexport interface SkipRuleResult {\n skip: boolean;\n reason?: string;\n}\n\n// The actual checked-out branch. Always uses git directly — env vars (BRANCH_NAME, GIT_BRANCH,\n// GITHUB_*, CI_COMMIT_BRANCH, …) were intentionally REMOVED: a stray GIT_BRANCH=main locally made\n// this return \"main\" on a feature branch, which (a) mislabeled the main-sync cache and (b) silently\n// disabled merged-PR detection (detectMergedPr skips \"main\"). git rev-parse is the source of truth.\nexport function getCurrentBranch(): string {\n // webpieces-disable no-unmanaged-exceptions -- rethrow as InformAiError so global catch surfaces readable message to AI\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- rethrow as InformAiError so global catch surfaces readable message to AI\n try {\n return execSync('git rev-parse --abbrev-ref HEAD', { encoding: 'utf8' }).trim();\n } catch (err: unknown) {\n const error = toError(err);\n throw new InformAiError(`Failed to determine current git branch: ${error.message}`, { cause: error });\n }\n}\n\nexport function shouldSkipRule(\n epoch: number | undefined,\n // null (the \"no branch / always on\" value of turnOffRuleWhileOnBranch) is treated exactly like\n // undefined — no branch scoping. Only a non-empty branch name activates the branch hatch.\n branchPattern: string | undefined | null\n): SkipRuleResult {\n if (branchPattern) {\n const current = getCurrentBranch();\n if (current === branchPattern) {\n return { skip: true, reason: `on branch \"${branchPattern}\"` };\n }\n }\n if (epoch !== undefined) {\n const nowSeconds = Date.now() / 1000;\n if (nowSeconds < epoch) {\n const expiresDate = new Date(epoch * 1000).toISOString().split('T')[0];\n return { skip: true, reason: `turnOffRuleUntilEpoch active, expires: ${expiresDate}` };\n }\n }\n return { skip: false };\n}\n"]}
package/src/types.d.ts CHANGED
@@ -3,7 +3,7 @@ export type RuleOptions = Record<string, unknown>;
3
3
  * One rule entry from webpieces.config.json, merged with built-in defaults.
4
4
  *
5
5
  * `options` contains the raw option bag (mode, limit, disableAllowed,
6
- * ignoreModifiedUntilEpoch, enforcePaths, etc). Consumers extract the
6
+ * turnOffRuleUntilEpoch, enforcePaths, etc). Consumers extract the
7
7
  * fields they understand and ignore the rest.
8
8
  *
9
9
  * On/off is driven entirely by `mode`: a rule is OFF only when explicitly
package/src/types.js CHANGED
@@ -5,7 +5,7 @@ exports.ResolvedConfig = exports.ResolvedRuleConfig = void 0;
5
5
  * One rule entry from webpieces.config.json, merged with built-in defaults.
6
6
  *
7
7
  * `options` contains the raw option bag (mode, limit, disableAllowed,
8
- * ignoreModifiedUntilEpoch, enforcePaths, etc). Consumers extract the
8
+ * turnOffRuleUntilEpoch, enforcePaths, etc). Consumers extract the
9
9
  * fields they understand and ignore the rest.
10
10
  *
11
11
  * On/off is driven entirely by `mode`: a rule is OFF only when explicitly
package/src/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../../packages/tooling/rules-config/src/types.ts"],"names":[],"mappings":";;;AAGA;;;;;;;;;;;;;GAaG;AACH,MAAa,kBAAkB;IAClB,OAAO,CAAc;IAE9B,YAAY,OAAoB;QAC5B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IAC3B,CAAC;IAED,oFAAoF;IACpF,IAAI,IAAI;QACJ,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC/B,OAAO,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACjD,CAAC;IAED,iFAAiF;IACjF,IAAI,KAAK;QACL,OAAO,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC;IAC/B,CAAC;CACJ;AAjBD,gDAiBC;AAED;;;;;;;GAOG;AACH,MAAa,cAAc;IACd,KAAK,CAAkC;IACvC,uBAAuB,CAAsB;IAC7C,QAAQ,CAAoB;IAC5B,UAAU,CAAgB;IAEnC,YACI,KAAsC,EACtC,uBAA4C,EAC5C,QAA2B,EAC3B,UAAyB;QAEzB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,uBAAuB,GAAG,uBAAuB,CAAC;QACvD,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IACjC,CAAC;CACJ;AAjBD,wCAiBC","sourcesContent":["// webpieces-disable no-any-unknown -- rule options are opaque at framework level; each consumer casts internally\nexport type RuleOptions = Record<string, unknown>;\n\n/**\n * One rule entry from webpieces.config.json, merged with built-in defaults.\n *\n * `options` contains the raw option bag (mode, limit, disableAllowed,\n * ignoreModifiedUntilEpoch, enforcePaths, etc). Consumers extract the\n * fields they understand and ignore the rest.\n *\n * On/off is driven entirely by `mode`: a rule is OFF only when explicitly\n * set to `mode: \"OFF\"`. Any other value (or an absent mode) leaves the rule\n * ON. For code-rules, `mode` doubles as the scope selector\n * (e.g. \"NEW_AND_MODIFIED_CODE\", \"NEW_AND_MODIFIED_METHODS\"); for simple on/off\n * rules it is just \"ON\"/\"OFF\". (The legacy `enabled` boolean has been\n * removed in favor of this single, more flexible switch.)\n */\nexport class ResolvedRuleConfig {\n readonly options: RuleOptions;\n\n constructor(options: RuleOptions) {\n this.options = options;\n }\n\n /** Raw mode string from the option bag (\"ON\" | \"OFF\" | scope value), if present. */\n get mode(): string | undefined {\n const m = this.options['mode'];\n return typeof m === 'string' ? m : undefined;\n }\n\n /** A rule is off only when explicitly `mode: \"OFF\"`. An absent mode means on. */\n get isOff(): boolean {\n return this.mode === 'OFF';\n }\n}\n\n/**\n * The fully-resolved workspace configuration: every rule known to the\n * workspace (built-in + consumer overrides) keyed by its canonical\n * kebab-case name.\n *\n * `configPath` is null when no webpieces.config.json was found (loaders\n * should treat that as \"no validation configured\").\n */\nexport class ResolvedConfig {\n readonly rules: Map<string, ResolvedRuleConfig>;\n readonly userConfiguredRuleNames: ReadonlySet<string>;\n readonly rulesDir: readonly string[];\n readonly configPath: string | null;\n\n constructor(\n rules: Map<string, ResolvedRuleConfig>,\n userConfiguredRuleNames: ReadonlySet<string>,\n rulesDir: readonly string[],\n configPath: string | null,\n ) {\n this.rules = rules;\n this.userConfiguredRuleNames = userConfiguredRuleNames;\n this.rulesDir = rulesDir;\n this.configPath = configPath;\n }\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../../packages/tooling/rules-config/src/types.ts"],"names":[],"mappings":";;;AAGA;;;;;;;;;;;;;GAaG;AACH,MAAa,kBAAkB;IAClB,OAAO,CAAc;IAE9B,YAAY,OAAoB;QAC5B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IAC3B,CAAC;IAED,oFAAoF;IACpF,IAAI,IAAI;QACJ,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC/B,OAAO,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACjD,CAAC;IAED,iFAAiF;IACjF,IAAI,KAAK;QACL,OAAO,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC;IAC/B,CAAC;CACJ;AAjBD,gDAiBC;AAED;;;;;;;GAOG;AACH,MAAa,cAAc;IACd,KAAK,CAAkC;IACvC,uBAAuB,CAAsB;IAC7C,QAAQ,CAAoB;IAC5B,UAAU,CAAgB;IAEnC,YACI,KAAsC,EACtC,uBAA4C,EAC5C,QAA2B,EAC3B,UAAyB;QAEzB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,uBAAuB,GAAG,uBAAuB,CAAC;QACvD,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IACjC,CAAC;CACJ;AAjBD,wCAiBC","sourcesContent":["// webpieces-disable no-any-unknown -- rule options are opaque at framework level; each consumer casts internally\nexport type RuleOptions = Record<string, unknown>;\n\n/**\n * One rule entry from webpieces.config.json, merged with built-in defaults.\n *\n * `options` contains the raw option bag (mode, limit, disableAllowed,\n * turnOffRuleUntilEpoch, enforcePaths, etc). Consumers extract the\n * fields they understand and ignore the rest.\n *\n * On/off is driven entirely by `mode`: a rule is OFF only when explicitly\n * set to `mode: \"OFF\"`. Any other value (or an absent mode) leaves the rule\n * ON. For code-rules, `mode` doubles as the scope selector\n * (e.g. \"NEW_AND_MODIFIED_CODE\", \"NEW_AND_MODIFIED_METHODS\"); for simple on/off\n * rules it is just \"ON\"/\"OFF\". (The legacy `enabled` boolean has been\n * removed in favor of this single, more flexible switch.)\n */\nexport class ResolvedRuleConfig {\n readonly options: RuleOptions;\n\n constructor(options: RuleOptions) {\n this.options = options;\n }\n\n /** Raw mode string from the option bag (\"ON\" | \"OFF\" | scope value), if present. */\n get mode(): string | undefined {\n const m = this.options['mode'];\n return typeof m === 'string' ? m : undefined;\n }\n\n /** A rule is off only when explicitly `mode: \"OFF\"`. An absent mode means on. */\n get isOff(): boolean {\n return this.mode === 'OFF';\n }\n}\n\n/**\n * The fully-resolved workspace configuration: every rule known to the\n * workspace (built-in + consumer overrides) keyed by its canonical\n * kebab-case name.\n *\n * `configPath` is null when no webpieces.config.json was found (loaders\n * should treat that as \"no validation configured\").\n */\nexport class ResolvedConfig {\n readonly rules: Map<string, ResolvedRuleConfig>;\n readonly userConfiguredRuleNames: ReadonlySet<string>;\n readonly rulesDir: readonly string[];\n readonly configPath: string | null;\n\n constructor(\n rules: Map<string, ResolvedRuleConfig>,\n userConfiguredRuleNames: ReadonlySet<string>,\n rulesDir: readonly string[],\n configPath: string | null,\n ) {\n this.rules = rules;\n this.userConfiguredRuleNames = userConfiguredRuleNames;\n this.rulesDir = rulesDir;\n this.configPath = configPath;\n }\n}\n"]}
@@ -69,11 +69,12 @@ function allRuleNames() {
69
69
  return Object.keys(RULE_SCHEMAS);
70
70
  }
71
71
  function valueHint(def, key) {
72
- // The time-box hatch (either name): 0 keeps the rule active (epoch in the past), a future unix
73
- // epoch (seconds) temporarily disables it. Spell that out for the AI. turnOffRuleUntilEpoch is the
74
- // preferred, self-describing name; ignoreModifiedUntilEpoch is the still-accepted original.
75
- if (key === 'ignoreModifiedUntilEpoch' || key === 'turnOffRuleUntilEpoch')
72
+ // The two universal escape hatches, REQUIRED on every rule so they're always visible. Spell out the
73
+ // "off" value so a fresh config seeds them in the active/no-op state (0 / null), not a placeholder.
74
+ if (key === 'turnOffRuleUntilEpoch')
76
75
  return '0 (0 = active; future unix-epoch seconds = temporarily off)';
76
+ if (key === 'turnOffRuleWhileOnBranch')
77
+ return 'null (null = always on; a branch name disables the rule while that branch is checked out)';
77
78
  return def.enumValues
78
79
  ? `"${def.enumValues.join(' | ')}"`
79
80
  : def.type === 'string[]' ? '["<string>", ...]'
@@ -104,9 +105,9 @@ function rolloutTip(schema) {
104
105
  `you next touch that project/file/method).${optOut}`);
105
106
  }
106
107
  function missingRuleSnippet(ruleName, schema) {
107
- // Only required fields go in the copy-paste entry. Optional fields (e.g. the
108
- // universal escape hatches ignoreRuleWhileOnBranch / ignoreModifiedUntilEpoch)
109
- // are listed separately so the snippet doesn't over-state what's mandatory.
108
+ // Required fields go in the copy-paste entry. The two universal escape hatches
109
+ // (turnOffRuleUntilEpoch / turnOffRuleWhileOnBranch) are now REQUIRED, so they land in that block —
110
+ // which is the whole point: every seeded rule shows both hatches. Optional fields are listed separately.
110
111
  const fields = Object.keys(schema);
111
112
  const required = fields.filter(f => !schema[f].optional);
112
113
  const optional = fields.filter(f => schema[f].optional);
@@ -150,6 +151,18 @@ const RETIRED_FIELD_HINTS = {
150
151
  'architecture/dependencies.json, so there is NO list of api libs to maintain. Delete it (do not ' +
151
152
  'enumerate api libs and do not replace it with a glob).',
152
153
  };
154
+ // Universal field renames (apply to EVERY rule/guard AND every match-rule, unlike the per-rule
155
+ // RETIRED_FIELD_HINTS). When an entry still uses the old escape-hatch name, the generic unknown-field
156
+ // error is replaced with a precise "renamed to X — rename it" instruction so the fix is mechanical.
157
+ const RENAMED_FIELD_ALIASES = {
158
+ ignoreModifiedUntilEpoch: 'turnOffRuleUntilEpoch',
159
+ ignoreRuleWhileOnBranch: 'turnOffRuleWhileOnBranch',
160
+ };
161
+ // The renamed-field message shared by keyed rules and match-rules.
162
+ // webpieces-disable no-function-outside-class -- module-level config validator, matches the rest of this file
163
+ function renamedFieldError(scope, oldKey, newKey) {
164
+ return `${scope} Unknown field "${oldKey}" — it was renamed to "${newKey}". Rename it (the value carries over unchanged; for the branch hatch, use null when there is no branch).`;
165
+ }
153
166
  // webpieces-disable no-any-unknown -- rawRules values are opaque JSON; each field is validated individually
154
167
  function validateWebpiecesConfig(rawRules, hasCustomRulesDir = false) {
155
168
  const errors = [];
@@ -167,11 +180,19 @@ function validateWebpiecesConfig(rawRules, hasCustomRulesDir = false) {
167
180
  for (const [key, value] of Object.entries(entry)) {
168
181
  const fieldDef = schema[key];
169
182
  if (!fieldDef) {
183
+ const renamedTo = RENAMED_FIELD_ALIASES[key];
184
+ if (renamedTo) {
185
+ errors.push(renamedFieldError(`[${ruleName}]`, key, renamedTo));
186
+ continue;
187
+ }
170
188
  const retiredHint = RETIRED_FIELD_HINTS[`${ruleName}.${key}`];
171
189
  const suffix = retiredHint ? ` ${retiredHint}` : '';
172
190
  errors.push(`[${ruleName}] Unknown field "${key}". Valid fields: [${Object.keys(schema).join(', ')}].${suffix}`);
173
191
  continue;
174
192
  }
193
+ // A nullable field (e.g. turnOffRuleWhileOnBranch) accepts JSON null in addition to its type.
194
+ if (value === null && fieldDef.nullable)
195
+ continue;
175
196
  if (fieldDef.type === 'string[]') {
176
197
  if (!Array.isArray(value) || !value.every(v => typeof v === 'string'))
177
198
  errors.push(`[${ruleName}] "${key}" must be string[], got ${typeof value}.`);
@@ -185,7 +206,7 @@ function validateWebpiecesConfig(rawRules, hasCustomRulesDir = false) {
185
206
  }
186
207
  // Required fields must actually be present. Until now the loop above only checked
187
208
  // fields that WERE present, so an entry like `{}` (or one missing `mode` /
188
- // `ignoreModifiedUntilEpoch`) slipped through. Every non-optional schema field is mandatory.
209
+ // `turnOffRuleUntilEpoch`) slipped through. Every non-optional schema field is mandatory.
189
210
  for (const [key, fieldDef] of Object.entries(schema)) {
190
211
  if (!fieldDef.optional && !(key in entry)) {
191
212
  errors.push(`[${ruleName}] Missing required field "${key}". Add ${key}: ${valueHint(fieldDef, key)}.`);
@@ -398,7 +419,7 @@ function regexError(pattern) {
398
419
  // webpieces-disable no-any-unknown -- one match-rule entry from opaque consumer JSON, validated field-by-field
399
420
  function validateMatchRule(entry, index) {
400
421
  if (typeof entry !== 'object' || entry === null || Array.isArray(entry)) {
401
- return [`[match-rules] entry[${index}] must be an object { name, patterns, mainMessage, mode, ignoreModifiedUntilEpoch, ... }.`];
422
+ return [`[match-rules] entry[${index}] must be an object { name, patterns, mainMessage, mode, turnOffRuleUntilEpoch, turnOffRuleWhileOnBranch, ... }.`];
402
423
  }
403
424
  // webpieces-disable no-any-unknown -- narrowing one opaque match-rule entry from consumer JSON
404
425
  const e = entry;
@@ -420,24 +441,25 @@ function validateMatchRule(entry, index) {
420
441
  errors.push(`[match-rules] ${label}.mainMessage must be a non-empty string.`);
421
442
  if (typeof e['mode'] !== 'string' || !rule_configs_1.MODIFIED_CODE_MODES.includes(e['mode']))
422
443
  errors.push(`[match-rules] ${label}.mode must be one of: ${rule_configs_1.MODIFIED_CODE_MODES.join(', ')}.`);
423
- // Time-box hatch optional, either name; each must be a number when present (0 = active; a future
424
- // unix-epoch in seconds = temporarily off). turnOffRuleUntilEpoch supersedes ignoreModifiedUntilEpoch.
425
- if (e['ignoreModifiedUntilEpoch'] !== undefined && typeof e['ignoreModifiedUntilEpoch'] !== 'number')
426
- errors.push(`[match-rules] ${label}.ignoreModifiedUntilEpoch must be a number (0 = active; future unix-epoch seconds = temporarily off).`);
427
- if (e['turnOffRuleUntilEpoch'] !== undefined && typeof e['turnOffRuleUntilEpoch'] !== 'number')
444
+ // Both escape hatches are REQUIRED on every match-rule too (same as keyed rules), so they are always
445
+ // visible. turnOffRuleUntilEpoch: number (0 = active; a future unix-epoch in seconds = temporarily
446
+ // off). turnOffRuleWhileOnBranch: string | null (null = always on; a branch name disables the rule
447
+ // while that branch is checked out).
448
+ if (typeof e['turnOffRuleUntilEpoch'] !== 'number')
428
449
  errors.push(`[match-rules] ${label}.turnOffRuleUntilEpoch must be a number (0 = active; future unix-epoch seconds = temporarily off).`);
450
+ if (!(e['turnOffRuleWhileOnBranch'] === null || typeof e['turnOffRuleWhileOnBranch'] === 'string'))
451
+ errors.push(`[match-rules] ${label}.turnOffRuleWhileOnBranch must be a string or null (null = no branch / always on).`);
452
+ // The old escape-hatch names were renamed — flag them precisely.
453
+ for (const oldKey of Object.keys(RENAMED_FIELD_ALIASES)) {
454
+ if (oldKey in e)
455
+ errors.push(renamedFieldError(`[match-rules] ${label}`, oldKey, RENAMED_FIELD_ALIASES[oldKey]));
456
+ }
429
457
  if (e['options'] !== undefined && !isStringArray(e['options']))
430
458
  errors.push(`[match-rules] ${label}.options must be a string[] (omit if not needed).`);
431
459
  if (e['allowedPaths'] !== undefined && !isStringArray(e['allowedPaths']))
432
460
  errors.push(`[match-rules] ${label}.allowedPaths must be a string[] of globs (omit if not needed).`);
433
461
  if (e['disableAllowed'] !== undefined && typeof e['disableAllowed'] !== 'boolean')
434
462
  errors.push(`[match-rules] ${label}.disableAllowed must be a boolean.`);
435
- // Branch hatch — optional, either name; each must be a string when present.
436
- // turnOffRuleWhileOnBranch supersedes ignoreRuleWhileOnBranch.
437
- if (e['ignoreRuleWhileOnBranch'] !== undefined && typeof e['ignoreRuleWhileOnBranch'] !== 'string')
438
- errors.push(`[match-rules] ${label}.ignoreRuleWhileOnBranch must be a string.`);
439
- if (e['turnOffRuleWhileOnBranch'] !== undefined && typeof e['turnOffRuleWhileOnBranch'] !== 'string')
440
- errors.push(`[match-rules] ${label}.turnOffRuleWhileOnBranch must be a string.`);
441
463
  return errors;
442
464
  }
443
465
  /**