@webpieces/rules-config 0.4.468 → 0.4.470

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webpieces/rules-config",
3
- "version": "0.4.468",
3
+ "version": "0.4.470",
4
4
  "description": "Shared webpieces.config.json loader. Single source of truth for validation rule configuration consumed by @webpieces/ai-hook-rules, @webpieces/code-rules, and @webpieces/nx-webpieces-rules.",
5
5
  "type": "commonjs",
6
6
  "main": "./src/index.js",
@@ -1,4 +1,5 @@
1
1
  import { MaxMethodLinesConfig, MaxFileLinesConfig, RequireReturnTypeConfig, NoInlineTypeLiteralsConfig, NoAnyUnknownConfig, NoImplicitAnyConfig, PrismaValidateDtosConfig, PrismaConverterConfig, NoDestructureConfig, NoUnmanagedExceptionsConfig, CatchErrorPatternConfig, ThrowCauseRequiredConfig, AngularNoDirectApiInResolverConfig, NoSymbolDiTokensConfig, NoCustomCssConfig, NoProcessExitOutsideMainConfig, NoFunctionOutsideClassConfig, InjectAnnotationNotNeededForConcreteClassConfig, FrameworkTagConfig, RoleTagConfig, BranchCreationGuardConfig, PrCreationOrPushGuardConfig, MergeInProgressGuardConfig, PrMergeGuardConfig, RedirectHowToMergeMainConfig, FeatureBranchGuardConfig, ReadStaleGuardConfig, NoFileImportCyclesConfig, RuntimeArchitectureConfig, DiGraphConfig, MissingDesignAnnotationConfig, NoJsFilesConfig, ValidateTsInSrcConfig } from './rule-configs';
2
+ import { NoClientCreationOutsideServerOrClientConfig } from './no-client-creation-config';
2
3
  export declare class WebpiecesRulesConfig {
3
4
  'max-method-lines'?: MaxMethodLinesConfig;
4
5
  'max-file-lines'?: MaxFileLinesConfig;
@@ -14,6 +15,7 @@ export declare class WebpiecesRulesConfig {
14
15
  'throw-cause-required'?: ThrowCauseRequiredConfig;
15
16
  'angular-no-direct-api-in-resolver'?: AngularNoDirectApiInResolverConfig;
16
17
  'no-symbol-di-tokens'?: NoSymbolDiTokensConfig;
18
+ 'no-client-creation-outside-server-or-client'?: NoClientCreationOutsideServerOrClientConfig;
17
19
  'no-custom-css'?: NoCustomCssConfig;
18
20
  'no-process-exit-outside-main'?: NoProcessExitOutsideMainConfig;
19
21
  'no-function-outside-class'?: NoFunctionOutsideClassConfig;
@@ -16,6 +16,7 @@ class WebpiecesRulesConfig {
16
16
  'throw-cause-required';
17
17
  'angular-no-direct-api-in-resolver';
18
18
  'no-symbol-di-tokens';
19
+ 'no-client-creation-outside-server-or-client';
19
20
  'no-custom-css';
20
21
  'no-process-exit-outside-main';
21
22
  'no-function-outside-class';
@@ -1 +1 @@
1
- {"version":3,"file":"WebpiecesRulesConfig.js","sourceRoot":"","sources":["../../../../../packages/tooling/rules-config/src/WebpiecesRulesConfig.ts"],"names":[],"mappings":";;;AAoCA,MAAa,oBAAoB;IAC7B,kBAAkB,CAAwB;IAC1C,gBAAgB,CAAsB;IACtC,qBAAqB,CAA2B;IAChD,yBAAyB,CAA8B;IACvD,gBAAgB,CAAsB;IACtC,iBAAiB,CAAuB;IACxC,sBAAsB,CAA4B;IAClD,kBAAkB,CAAyB;IAC3C,gBAAgB,CAAuB;IACvC,yBAAyB,CAA+B;IACxD,qBAAqB,CAA2B;IAChD,sBAAsB,CAA4B;IAClD,mCAAmC,CAAsC;IACzE,qBAAqB,CAA0B;IAC/C,eAAe,CAAqB;IACpC,8BAA8B,CAAkC;IAChE,2BAA2B,CAAgC;IAC3D,iDAAiD,CAAmD;IACpG,eAAe,CAAsB;IACrC,UAAU,CAAiB;IAC3B,uBAAuB,CAA6B;IACpD,2BAA2B,CAA+B;IAC1D,yBAAyB,CAA8B;IACvD,gBAAgB,CAAsB;IACtC,4BAA4B,CAAgC;IAC5D,sBAAsB,CAA4B;IAClD,kBAAkB,CAAwB;IAC1C,uBAAuB,CAA4B;IACnD,sBAAsB,CAA6B;IACnD,UAAU,CAAiB;IAC3B,2BAA2B,CAAiC;IAC5D,aAAa,CAAmB;IAChC,oBAAoB,CAAyB;IAC7C,QAAQ,CAAY;CACvB;AAnCD,oDAmCC","sourcesContent":["import {\n MaxMethodLinesConfig,\n MaxFileLinesConfig,\n RequireReturnTypeConfig,\n NoInlineTypeLiteralsConfig,\n NoAnyUnknownConfig,\n NoImplicitAnyConfig,\n PrismaValidateDtosConfig,\n PrismaConverterConfig,\n NoDestructureConfig,\n NoUnmanagedExceptionsConfig,\n CatchErrorPatternConfig,\n ThrowCauseRequiredConfig,\n AngularNoDirectApiInResolverConfig,\n NoSymbolDiTokensConfig,\n NoCustomCssConfig,\n NoProcessExitOutsideMainConfig,\n NoFunctionOutsideClassConfig,\n InjectAnnotationNotNeededForConcreteClassConfig,\n FrameworkTagConfig,\n RoleTagConfig,\n BranchCreationGuardConfig,\n PrCreationOrPushGuardConfig,\n MergeInProgressGuardConfig,\n PrMergeGuardConfig,\n RedirectHowToMergeMainConfig,\n FeatureBranchGuardConfig,\n ReadStaleGuardConfig,\n NoFileImportCyclesConfig,\n RuntimeArchitectureConfig,\n DiGraphConfig,\n MissingDesignAnnotationConfig,\n NoJsFilesConfig,\n ValidateTsInSrcConfig,\n} from './rule-configs';\n\nexport class WebpiecesRulesConfig {\n 'max-method-lines'?: MaxMethodLinesConfig;\n 'max-file-lines'?: MaxFileLinesConfig;\n 'require-return-type'?: RequireReturnTypeConfig;\n 'no-inline-type-literals'?: NoInlineTypeLiteralsConfig;\n 'no-any-unknown'?: NoAnyUnknownConfig;\n 'no-implicit-any'?: NoImplicitAnyConfig;\n 'prisma-validate-dtos'?: PrismaValidateDtosConfig;\n 'prisma-converter'?: PrismaConverterConfig;\n 'no-destructure'?: NoDestructureConfig;\n 'no-unmanaged-exceptions'?: NoUnmanagedExceptionsConfig;\n 'catch-error-pattern'?: CatchErrorPatternConfig;\n 'throw-cause-required'?: ThrowCauseRequiredConfig;\n 'angular-no-direct-api-in-resolver'?: AngularNoDirectApiInResolverConfig;\n 'no-symbol-di-tokens'?: NoSymbolDiTokensConfig;\n 'no-custom-css'?: NoCustomCssConfig;\n 'no-process-exit-outside-main'?: NoProcessExitOutsideMainConfig;\n 'no-function-outside-class'?: NoFunctionOutsideClassConfig;\n 'inject-annotation-not-needed-for-concrete-class'?: InjectAnnotationNotNeededForConcreteClassConfig;\n 'framework-tag'?: FrameworkTagConfig;\n 'role-tag'?: RoleTagConfig;\n 'branch-creation-guard'?: BranchCreationGuardConfig;\n 'pr-creation-or-push-guard'?: PrCreationOrPushGuardConfig;\n 'merge-in-progress-guard'?: MergeInProgressGuardConfig;\n 'pr-merge-guard'?: PrMergeGuardConfig;\n 'redirect-how-to-merge-main'?: RedirectHowToMergeMainConfig;\n 'feature-branch-guard'?: FeatureBranchGuardConfig;\n 'read-stale-guard'?: ReadStaleGuardConfig;\n 'no-file-import-cycles'?: NoFileImportCyclesConfig;\n 'runtime-architecture'?: RuntimeArchitectureConfig;\n 'di-graph'?: DiGraphConfig;\n 'missing-design-annotation'?: MissingDesignAnnotationConfig;\n 'no-js-files'?: NoJsFilesConfig;\n 'validate-ts-in-src'?: ValidateTsInSrcConfig;\n rulesDir?: string[];\n}\n"]}
1
+ {"version":3,"file":"WebpiecesRulesConfig.js","sourceRoot":"","sources":["../../../../../packages/tooling/rules-config/src/WebpiecesRulesConfig.ts"],"names":[],"mappings":";;;AAqCA,MAAa,oBAAoB;IAC7B,kBAAkB,CAAwB;IAC1C,gBAAgB,CAAsB;IACtC,qBAAqB,CAA2B;IAChD,yBAAyB,CAA8B;IACvD,gBAAgB,CAAsB;IACtC,iBAAiB,CAAuB;IACxC,sBAAsB,CAA4B;IAClD,kBAAkB,CAAyB;IAC3C,gBAAgB,CAAuB;IACvC,yBAAyB,CAA+B;IACxD,qBAAqB,CAA2B;IAChD,sBAAsB,CAA4B;IAClD,mCAAmC,CAAsC;IACzE,qBAAqB,CAA0B;IAC/C,6CAA6C,CAA+C;IAC5F,eAAe,CAAqB;IACpC,8BAA8B,CAAkC;IAChE,2BAA2B,CAAgC;IAC3D,iDAAiD,CAAmD;IACpG,eAAe,CAAsB;IACrC,UAAU,CAAiB;IAC3B,uBAAuB,CAA6B;IACpD,2BAA2B,CAA+B;IAC1D,yBAAyB,CAA8B;IACvD,gBAAgB,CAAsB;IACtC,4BAA4B,CAAgC;IAC5D,sBAAsB,CAA4B;IAClD,kBAAkB,CAAwB;IAC1C,uBAAuB,CAA4B;IACnD,sBAAsB,CAA6B;IACnD,UAAU,CAAiB;IAC3B,2BAA2B,CAAiC;IAC5D,aAAa,CAAmB;IAChC,oBAAoB,CAAyB;IAC7C,QAAQ,CAAY;CACvB;AApCD,oDAoCC","sourcesContent":["import {\n MaxMethodLinesConfig,\n MaxFileLinesConfig,\n RequireReturnTypeConfig,\n NoInlineTypeLiteralsConfig,\n NoAnyUnknownConfig,\n NoImplicitAnyConfig,\n PrismaValidateDtosConfig,\n PrismaConverterConfig,\n NoDestructureConfig,\n NoUnmanagedExceptionsConfig,\n CatchErrorPatternConfig,\n ThrowCauseRequiredConfig,\n AngularNoDirectApiInResolverConfig,\n NoSymbolDiTokensConfig,\n NoCustomCssConfig,\n NoProcessExitOutsideMainConfig,\n NoFunctionOutsideClassConfig,\n InjectAnnotationNotNeededForConcreteClassConfig,\n FrameworkTagConfig,\n RoleTagConfig,\n BranchCreationGuardConfig,\n PrCreationOrPushGuardConfig,\n MergeInProgressGuardConfig,\n PrMergeGuardConfig,\n RedirectHowToMergeMainConfig,\n FeatureBranchGuardConfig,\n ReadStaleGuardConfig,\n NoFileImportCyclesConfig,\n RuntimeArchitectureConfig,\n DiGraphConfig,\n MissingDesignAnnotationConfig,\n NoJsFilesConfig,\n ValidateTsInSrcConfig,\n} from './rule-configs';\nimport { NoClientCreationOutsideServerOrClientConfig } from './no-client-creation-config';\n\nexport class WebpiecesRulesConfig {\n 'max-method-lines'?: MaxMethodLinesConfig;\n 'max-file-lines'?: MaxFileLinesConfig;\n 'require-return-type'?: RequireReturnTypeConfig;\n 'no-inline-type-literals'?: NoInlineTypeLiteralsConfig;\n 'no-any-unknown'?: NoAnyUnknownConfig;\n 'no-implicit-any'?: NoImplicitAnyConfig;\n 'prisma-validate-dtos'?: PrismaValidateDtosConfig;\n 'prisma-converter'?: PrismaConverterConfig;\n 'no-destructure'?: NoDestructureConfig;\n 'no-unmanaged-exceptions'?: NoUnmanagedExceptionsConfig;\n 'catch-error-pattern'?: CatchErrorPatternConfig;\n 'throw-cause-required'?: ThrowCauseRequiredConfig;\n 'angular-no-direct-api-in-resolver'?: AngularNoDirectApiInResolverConfig;\n 'no-symbol-di-tokens'?: NoSymbolDiTokensConfig;\n 'no-client-creation-outside-server-or-client'?: NoClientCreationOutsideServerOrClientConfig;\n 'no-custom-css'?: NoCustomCssConfig;\n 'no-process-exit-outside-main'?: NoProcessExitOutsideMainConfig;\n 'no-function-outside-class'?: NoFunctionOutsideClassConfig;\n 'inject-annotation-not-needed-for-concrete-class'?: InjectAnnotationNotNeededForConcreteClassConfig;\n 'framework-tag'?: FrameworkTagConfig;\n 'role-tag'?: RoleTagConfig;\n 'branch-creation-guard'?: BranchCreationGuardConfig;\n 'pr-creation-or-push-guard'?: PrCreationOrPushGuardConfig;\n 'merge-in-progress-guard'?: MergeInProgressGuardConfig;\n 'pr-merge-guard'?: PrMergeGuardConfig;\n 'redirect-how-to-merge-main'?: RedirectHowToMergeMainConfig;\n 'feature-branch-guard'?: FeatureBranchGuardConfig;\n 'read-stale-guard'?: ReadStaleGuardConfig;\n 'no-file-import-cycles'?: NoFileImportCyclesConfig;\n 'runtime-architecture'?: RuntimeArchitectureConfig;\n 'di-graph'?: DiGraphConfig;\n 'missing-design-annotation'?: MissingDesignAnnotationConfig;\n 'no-js-files'?: NoJsFilesConfig;\n 'validate-ts-in-src'?: ValidateTsInSrcConfig;\n rulesDir?: string[];\n}\n"]}
@@ -10,7 +10,8 @@ export declare class ChecklistDefinition {
10
10
  severity: string;
11
11
  blockMessage: string;
12
12
  disabled: boolean;
13
- constructor(id: string, title: string, patterns: string[], contentPatterns: string[], docs: string[], severity: string, blockMessage: string, disabled?: boolean);
13
+ subagent: string;
14
+ constructor(id: string, title: string, patterns: string[], contentPatterns: string[], docs: string[], severity: string, blockMessage: string, disabled?: boolean, subagent?: string);
14
15
  }
15
16
  export interface RawChecklist {
16
17
  id?: string;
@@ -21,5 +22,6 @@ export interface RawChecklist {
21
22
  severity?: string;
22
23
  blockMessage?: string;
23
24
  disabled?: boolean;
25
+ subagent?: string;
24
26
  }
25
27
  export declare function toChecklist(raw: RawChecklist): ChecklistDefinition;
@@ -27,8 +27,18 @@ class ChecklistDefinition {
27
27
  severity; // 'BLOCK' | 'WARN'
28
28
  blockMessage; // consumer-owned wording shown when it blocks
29
29
  disabled; // example/inactive checklist kept in the file (JSON has no comments)
30
+ // Expected agentType (e.g. "morpheus-reviewer") that must have run on this branch for the checklist
31
+ // to be considered independently reviewed. When set, wp-finish-upsert-pr reads the Claude Code
32
+ // harness's own subagent artifacts (agent-*.meta.json agentType + spawnDepth, sibling jsonl
33
+ // isSidechain/gitBranch) to VERIFY such a subagent actually ran — provenance is READ from harness
34
+ // artifacts, never asserted in review.json. '' = no provenance requirement.
35
+ //
36
+ // NOT tamper-proof: a determined agent can hand-write a fake agent-*.meta.json. This raises the bar
37
+ // from "trust the model's word" to "deliberate, auditable forgery"; it is not cryptographic proof.
38
+ // Absent CLAUDE_CODE_SESSION_ID (plain terminal / CI) the check warns + skips rather than failing.
39
+ subagent;
30
40
  // eslint-disable-next-line @typescript-eslint/max-params
31
- constructor(id, title, patterns, contentPatterns, docs, severity, blockMessage, disabled = false) {
41
+ constructor(id, title, patterns, contentPatterns, docs, severity, blockMessage, disabled = false, subagent = '') {
32
42
  this.id = id;
33
43
  this.title = title;
34
44
  this.patterns = patterns;
@@ -37,12 +47,13 @@ class ChecklistDefinition {
37
47
  this.severity = severity;
38
48
  this.blockMessage = blockMessage;
39
49
  this.disabled = disabled;
50
+ this.subagent = subagent;
40
51
  }
41
52
  }
42
53
  exports.ChecklistDefinition = ChecklistDefinition;
43
54
  // Mirror of pr-gate-config's toGate: build a ChecklistDefinition from an omitting-friendly raw entry.
44
55
  // webpieces-disable no-function-outside-class -- pure config transform beside its data class, mirrors toGate
45
56
  function toChecklist(raw) {
46
- return new ChecklistDefinition(raw.id ?? '', raw.title ?? '', raw.patterns ?? [], raw.contentPatterns ?? [], raw.docs ?? [], raw.severity ?? exports.CHECKLIST_WARN, raw.blockMessage ?? '', raw.disabled ?? false);
57
+ return new ChecklistDefinition(raw.id ?? '', raw.title ?? '', raw.patterns ?? [], raw.contentPatterns ?? [], raw.docs ?? [], raw.severity ?? exports.CHECKLIST_WARN, raw.blockMessage ?? '', raw.disabled ?? false, raw.subagent ?? '');
47
58
  }
48
59
  //# sourceMappingURL=checklist-config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"checklist-config.js","sourceRoot":"","sources":["../../../../../packages/tooling/rules-config/src/checklist-config.ts"],"names":[],"mappings":";AAAA,mGAAmG;AACnG,sGAAsG;AACtG,uGAAuG;AACvG,iGAAiG;AACjG,EAAE;AACF,uGAAuG;AACvG,uGAAuG;AACvG,kFAAkF;AAClF,EAAE;AACF,wGAAwG;AACxG,0FAA0F;;;AAsD1F,kCAWC;AA/DY,QAAA,eAAe,GAAG,OAAO,CAAC;AAC1B,QAAA,cAAc,GAAG,MAAM,CAAC;AACrC,oGAAoG;AACpG,6FAA6F;AAChF,QAAA,oBAAoB,GAAG,CAAC,uBAAe,EAAE,sBAAc,CAAC,CAAC;AAEtE,MAAa,mBAAmB;IAC5B,EAAE,CAAS,CAAiB,sEAAsE;IAClG,KAAK,CAAS,CAAc,kBAAkB;IAC9C,QAAQ,CAAW,CAAS,+DAA+D;IAC3F,eAAe,CAAW,CAAE,wEAAwE;IACpG,IAAI,CAAW,CAAa,iEAAiE;IAC7F,QAAQ,CAAS,CAAW,mBAAmB;IAC/C,YAAY,CAAS,CAAO,8CAA8C;IAC1E,QAAQ,CAAU,CAAU,qEAAqE;IAEjG,yDAAyD;IACzD,YACI,EAAU,EACV,KAAa,EACb,QAAkB,EAClB,eAAyB,EACzB,IAAc,EACd,QAAgB,EAChB,YAAoB,EACpB,QAAQ,GAAG,KAAK;QAEhB,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,eAAe,GAAG,eAAe,CAAC;QACvC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;QACjC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC7B,CAAC;CACJ;AA9BD,kDA8BC;AAcD,sGAAsG;AACtG,6GAA6G;AAC7G,SAAgB,WAAW,CAAC,GAAiB;IACzC,OAAO,IAAI,mBAAmB,CAC1B,GAAG,CAAC,EAAE,IAAI,EAAE,EACZ,GAAG,CAAC,KAAK,IAAI,EAAE,EACf,GAAG,CAAC,QAAQ,IAAI,EAAE,EAClB,GAAG,CAAC,eAAe,IAAI,EAAE,EACzB,GAAG,CAAC,IAAI,IAAI,EAAE,EACd,GAAG,CAAC,QAAQ,IAAI,sBAAc,EAC9B,GAAG,CAAC,YAAY,IAAI,EAAE,EACtB,GAAG,CAAC,QAAQ,IAAI,KAAK,CACxB,CAAC;AACN,CAAC","sourcesContent":["// A company review checklist: a diff-triggered extension point that lets a CONSUMER inject its own\n// PR-time review process into the webpieces gated flow WITHOUT forking the tooling. When the branch's\n// diff touches paths/content the consumer cares about, the AI is made to read the named docs before it\n// writes review.json, and a BLOCK checklist refuses to open the PR until the AI acknowledges it.\n//\n// This is deliberately NOT an authorization mechanism (acknowledged: true is written by the AI). It is\n// a SURFACING + AUDIT extension point — the wording, the docs, and the trigger are all consumer-owned;\n// webpieces owns only the mechanism. Data-only (per CLAUDE.md, classes for data).\n//\n// Lives in rules-config (not pr-gate) because both the config layer AND review.json validation need the\n// severity vocabulary, and rules-config is the package every consumer already depends on.\n\nexport const CHECKLIST_BLOCK = 'BLOCK';\nexport const CHECKLIST_WARN = 'WARN';\n// BLOCK — an unacknowledged one throws before the PR is opened (same guarantee buildCommand gives).\n// WARN — never validated; absence just renders a yellow dashboard row (a nudge, not a gate).\nexport const CHECKLIST_SEVERITIES = [CHECKLIST_BLOCK, CHECKLIST_WARN];\n\nexport class ChecklistDefinition {\n id: string; // stable key echoed in review.json + the dashboard, e.g. \"migrations\"\n title: string; // dashboard label\n patterns: string[]; // path globs (isPathExcluded semantics); [] = any changed file\n contentPatterns: string[]; // regexes matched against ADDED diff lines only; [] = path-only trigger\n docs: string[]; // repo-relative docs the AI MUST read before writing review.json\n severity: string; // 'BLOCK' | 'WARN'\n blockMessage: string; // consumer-owned wording shown when it blocks\n disabled: boolean; // example/inactive checklist kept in the file (JSON has no comments)\n\n // eslint-disable-next-line @typescript-eslint/max-params\n constructor(\n id: string,\n title: string,\n patterns: string[],\n contentPatterns: string[],\n docs: string[],\n severity: string,\n blockMessage: string,\n disabled = false,\n ) {\n this.id = id;\n this.title = title;\n this.patterns = patterns;\n this.contentPatterns = contentPatterns;\n this.docs = docs;\n this.severity = severity;\n this.blockMessage = blockMessage;\n this.disabled = disabled;\n }\n}\n\n// One checklist entry straight from consumer JSON, before it is validated + narrowed into a class.\nexport interface RawChecklist {\n id?: string;\n title?: string;\n patterns?: string[];\n contentPatterns?: string[];\n docs?: string[];\n severity?: string;\n blockMessage?: string;\n disabled?: boolean;\n}\n\n// Mirror of pr-gate-config's toGate: build a ChecklistDefinition from an omitting-friendly raw entry.\n// webpieces-disable no-function-outside-class -- pure config transform beside its data class, mirrors toGate\nexport function toChecklist(raw: RawChecklist): ChecklistDefinition {\n return new ChecklistDefinition(\n raw.id ?? '',\n raw.title ?? '',\n raw.patterns ?? [],\n raw.contentPatterns ?? [],\n raw.docs ?? [],\n raw.severity ?? CHECKLIST_WARN,\n raw.blockMessage ?? '',\n raw.disabled ?? false,\n );\n}\n"]}
1
+ {"version":3,"file":"checklist-config.js","sourceRoot":"","sources":["../../../../../packages/tooling/rules-config/src/checklist-config.ts"],"names":[],"mappings":";AAAA,mGAAmG;AACnG,sGAAsG;AACtG,uGAAuG;AACvG,iGAAiG;AACjG,EAAE;AACF,uGAAuG;AACvG,uGAAuG;AACvG,kFAAkF;AAClF,EAAE;AACF,wGAAwG;AACxG,0FAA0F;;;AAmE1F,kCAYC;AA7EY,QAAA,eAAe,GAAG,OAAO,CAAC;AAC1B,QAAA,cAAc,GAAG,MAAM,CAAC;AACrC,oGAAoG;AACpG,6FAA6F;AAChF,QAAA,oBAAoB,GAAG,CAAC,uBAAe,EAAE,sBAAc,CAAC,CAAC;AAEtE,MAAa,mBAAmB;IAC5B,EAAE,CAAS,CAAiB,sEAAsE;IAClG,KAAK,CAAS,CAAc,kBAAkB;IAC9C,QAAQ,CAAW,CAAS,+DAA+D;IAC3F,eAAe,CAAW,CAAE,wEAAwE;IACpG,IAAI,CAAW,CAAa,iEAAiE;IAC7F,QAAQ,CAAS,CAAW,mBAAmB;IAC/C,YAAY,CAAS,CAAO,8CAA8C;IAC1E,QAAQ,CAAU,CAAU,qEAAqE;IACjG,oGAAoG;IACpG,+FAA+F;IAC/F,4FAA4F;IAC5F,kGAAkG;IAClG,4EAA4E;IAC5E,EAAE;IACF,oGAAoG;IACpG,mGAAmG;IACnG,mGAAmG;IACnG,QAAQ,CAAS;IAEjB,yDAAyD;IACzD,YACI,EAAU,EACV,KAAa,EACb,QAAkB,EAClB,eAAyB,EACzB,IAAc,EACd,QAAgB,EAChB,YAAoB,EACpB,QAAQ,GAAG,KAAK,EAChB,QAAQ,GAAG,EAAE;QAEb,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,eAAe,GAAG,eAAe,CAAC;QACvC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;QACjC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC7B,CAAC;CACJ;AA1CD,kDA0CC;AAeD,sGAAsG;AACtG,6GAA6G;AAC7G,SAAgB,WAAW,CAAC,GAAiB;IACzC,OAAO,IAAI,mBAAmB,CAC1B,GAAG,CAAC,EAAE,IAAI,EAAE,EACZ,GAAG,CAAC,KAAK,IAAI,EAAE,EACf,GAAG,CAAC,QAAQ,IAAI,EAAE,EAClB,GAAG,CAAC,eAAe,IAAI,EAAE,EACzB,GAAG,CAAC,IAAI,IAAI,EAAE,EACd,GAAG,CAAC,QAAQ,IAAI,sBAAc,EAC9B,GAAG,CAAC,YAAY,IAAI,EAAE,EACtB,GAAG,CAAC,QAAQ,IAAI,KAAK,EACrB,GAAG,CAAC,QAAQ,IAAI,EAAE,CACrB,CAAC;AACN,CAAC","sourcesContent":["// A company review checklist: a diff-triggered extension point that lets a CONSUMER inject its own\n// PR-time review process into the webpieces gated flow WITHOUT forking the tooling. When the branch's\n// diff touches paths/content the consumer cares about, the AI is made to read the named docs before it\n// writes review.json, and a BLOCK checklist refuses to open the PR until the AI acknowledges it.\n//\n// This is deliberately NOT an authorization mechanism (acknowledged: true is written by the AI). It is\n// a SURFACING + AUDIT extension point — the wording, the docs, and the trigger are all consumer-owned;\n// webpieces owns only the mechanism. Data-only (per CLAUDE.md, classes for data).\n//\n// Lives in rules-config (not pr-gate) because both the config layer AND review.json validation need the\n// severity vocabulary, and rules-config is the package every consumer already depends on.\n\nexport const CHECKLIST_BLOCK = 'BLOCK';\nexport const CHECKLIST_WARN = 'WARN';\n// BLOCK — an unacknowledged one throws before the PR is opened (same guarantee buildCommand gives).\n// WARN — never validated; absence just renders a yellow dashboard row (a nudge, not a gate).\nexport const CHECKLIST_SEVERITIES = [CHECKLIST_BLOCK, CHECKLIST_WARN];\n\nexport class ChecklistDefinition {\n id: string; // stable key echoed in review.json + the dashboard, e.g. \"migrations\"\n title: string; // dashboard label\n patterns: string[]; // path globs (isPathExcluded semantics); [] = any changed file\n contentPatterns: string[]; // regexes matched against ADDED diff lines only; [] = path-only trigger\n docs: string[]; // repo-relative docs the AI MUST read before writing review.json\n severity: string; // 'BLOCK' | 'WARN'\n blockMessage: string; // consumer-owned wording shown when it blocks\n disabled: boolean; // example/inactive checklist kept in the file (JSON has no comments)\n // Expected agentType (e.g. \"morpheus-reviewer\") that must have run on this branch for the checklist\n // to be considered independently reviewed. When set, wp-finish-upsert-pr reads the Claude Code\n // harness's own subagent artifacts (agent-*.meta.json agentType + spawnDepth, sibling jsonl\n // isSidechain/gitBranch) to VERIFY such a subagent actually ran — provenance is READ from harness\n // artifacts, never asserted in review.json. '' = no provenance requirement.\n //\n // NOT tamper-proof: a determined agent can hand-write a fake agent-*.meta.json. This raises the bar\n // from \"trust the model's word\" to \"deliberate, auditable forgery\"; it is not cryptographic proof.\n // Absent CLAUDE_CODE_SESSION_ID (plain terminal / CI) the check warns + skips rather than failing.\n subagent: string;\n\n // eslint-disable-next-line @typescript-eslint/max-params\n constructor(\n id: string,\n title: string,\n patterns: string[],\n contentPatterns: string[],\n docs: string[],\n severity: string,\n blockMessage: string,\n disabled = false,\n subagent = '',\n ) {\n this.id = id;\n this.title = title;\n this.patterns = patterns;\n this.contentPatterns = contentPatterns;\n this.docs = docs;\n this.severity = severity;\n this.blockMessage = blockMessage;\n this.disabled = disabled;\n this.subagent = subagent;\n }\n}\n\n// One checklist entry straight from consumer JSON, before it is validated + narrowed into a class.\nexport interface RawChecklist {\n id?: string;\n title?: string;\n patterns?: string[];\n contentPatterns?: string[];\n docs?: string[];\n severity?: string;\n blockMessage?: string;\n disabled?: boolean;\n subagent?: string;\n}\n\n// Mirror of pr-gate-config's toGate: build a ChecklistDefinition from an omitting-friendly raw entry.\n// webpieces-disable no-function-outside-class -- pure config transform beside its data class, mirrors toGate\nexport function toChecklist(raw: RawChecklist): ChecklistDefinition {\n return new ChecklistDefinition(\n raw.id ?? '',\n raw.title ?? '',\n raw.patterns ?? [],\n raw.contentPatterns ?? [],\n raw.docs ?? [],\n raw.severity ?? CHECKLIST_WARN,\n raw.blockMessage ?? '',\n raw.disabled ?? false,\n raw.subagent ?? '',\n );\n}\n"]}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Validate ONLY the pr-gate `checklists[]` block, in isolation — docs paths exist, contentPatterns
3
+ * compile, ids are unique, blockMessage present on BLOCK entries. This is the same logic
4
+ * loadAndValidate runs (validateChecklists), but callable directly so a missing/typo'd `docs:` path
5
+ * fails as its OWN `validate-checklist-docs` check (with a clear owner) instead of surfacing as an
6
+ * unrelated validator's banner because it rode along inside loadAndValidate. Returns human-readable
7
+ * errors; never throws.
8
+ */
9
+ export declare function validateChecklistDocs(cwd: string): string[];
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validateChecklistDocs = validateChecklistDocs;
4
+ const tslib_1 = require("tslib");
5
+ const fs = tslib_1.__importStar(require("fs"));
6
+ const path = tslib_1.__importStar(require("path"));
7
+ const config_file_1 = require("./config-file");
8
+ const validate_config_1 = require("./validate-config");
9
+ const to_error_1 = require("./to-error");
10
+ /**
11
+ * Validate ONLY the pr-gate `checklists[]` block, in isolation — docs paths exist, contentPatterns
12
+ * compile, ids are unique, blockMessage present on BLOCK entries. This is the same logic
13
+ * loadAndValidate runs (validateChecklists), but callable directly so a missing/typo'd `docs:` path
14
+ * fails as its OWN `validate-checklist-docs` check (with a clear owner) instead of surfacing as an
15
+ * unrelated validator's banner because it rode along inside loadAndValidate. Returns human-readable
16
+ * errors; never throws.
17
+ */
18
+ // webpieces-disable no-function-outside-class -- module-level config validator, matches validate-config.ts
19
+ function validateChecklistDocs(cwd) {
20
+ const configPath = (0, config_file_1.findConfigFile)(cwd);
21
+ if (!configPath)
22
+ return [];
23
+ // webpieces-disable no-any-unknown -- parsed config JSON is opaque until narrowed below
24
+ let raw;
25
+ // webpieces-disable no-unmanaged-exceptions -- chokepoint: a malformed config surfaces as one readable error
26
+ // eslint-disable-next-line @webpieces/no-unmanaged-exceptions
27
+ try {
28
+ // webpieces-disable no-any-unknown -- parsed config JSON is opaque until narrowed below
29
+ raw = JSON.parse(fs.readFileSync(configPath, 'utf8'));
30
+ }
31
+ catch (err) {
32
+ const error = (0, to_error_1.toError)(err);
33
+ return [`[pr-gate] ${path.basename(configPath)} is not valid JSON: ${error.message}`];
34
+ }
35
+ const repoRoot = path.dirname(configPath);
36
+ // Checklists live under commands["pr-gate"].checklists (current) or the legacy top-level pr-gate.
37
+ // webpieces-disable no-any-unknown -- narrowing the opaque command section
38
+ const commands = raw['commands'];
39
+ // webpieces-disable no-any-unknown -- narrowing the opaque pr-gate section
40
+ const prGate = (commands?.['pr-gate'] ?? raw['pr-gate']);
41
+ if (!prGate || !('checklists' in prGate))
42
+ return [];
43
+ return (0, validate_config_1.validateChecklists)(prGate['checklists'], repoRoot);
44
+ }
45
+ //# sourceMappingURL=checklist-docs-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checklist-docs-validator.js","sourceRoot":"","sources":["../../../../../packages/tooling/rules-config/src/checklist-docs-validator.ts"],"names":[],"mappings":";;AAeA,sDAsBC;;AArCD,+CAAyB;AACzB,mDAA6B;AAC7B,+CAA+C;AAC/C,uDAAuD;AACvD,yCAAqC;AAErC;;;;;;;GAOG;AACH,2GAA2G;AAC3G,SAAgB,qBAAqB,CAAC,GAAW;IAC7C,MAAM,UAAU,GAAG,IAAA,4BAAc,EAAC,GAAG,CAAC,CAAC;IACvC,IAAI,CAAC,UAAU;QAAE,OAAO,EAAE,CAAC;IAC3B,wFAAwF;IACxF,IAAI,GAA4B,CAAC;IACjC,6GAA6G;IAC7G,8DAA8D;IAC9D,IAAI,CAAC;QACD,wFAAwF;QACxF,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAA4B,CAAC;IACrF,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACpB,MAAM,KAAK,GAAG,IAAA,kBAAO,EAAC,GAAG,CAAC,CAAC;QAC3B,OAAO,CAAC,aAAa,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,uBAAuB,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IAC1F,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC1C,kGAAkG;IAClG,2EAA2E;IAC3E,MAAM,QAAQ,GAAG,GAAG,CAAC,UAAU,CAAwC,CAAC;IACxE,2EAA2E;IAC3E,MAAM,MAAM,GAAG,CAAC,QAAQ,EAAE,CAAC,SAAS,CAAC,IAAI,GAAG,CAAC,SAAS,CAAC,CAAwC,CAAC;IAChG,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC,YAAY,IAAI,MAAM,CAAC;QAAE,OAAO,EAAE,CAAC;IACpD,OAAO,IAAA,oCAAkB,EAAC,MAAM,CAAC,YAAY,CAAC,EAAE,QAAQ,CAAC,CAAC;AAC9D,CAAC","sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\nimport { findConfigFile } from './config-file';\nimport { validateChecklists } from './validate-config';\nimport { toError } from './to-error';\n\n/**\n * Validate ONLY the pr-gate `checklists[]` block, in isolation — docs paths exist, contentPatterns\n * compile, ids are unique, blockMessage present on BLOCK entries. This is the same logic\n * loadAndValidate runs (validateChecklists), but callable directly so a missing/typo'd `docs:` path\n * fails as its OWN `validate-checklist-docs` check (with a clear owner) instead of surfacing as an\n * unrelated validator's banner because it rode along inside loadAndValidate. Returns human-readable\n * errors; never throws.\n */\n// webpieces-disable no-function-outside-class -- module-level config validator, matches validate-config.ts\nexport function validateChecklistDocs(cwd: string): string[] {\n const configPath = findConfigFile(cwd);\n if (!configPath) return [];\n // webpieces-disable no-any-unknown -- parsed config JSON is opaque until narrowed below\n let raw: Record<string, unknown>;\n // webpieces-disable no-unmanaged-exceptions -- chokepoint: a malformed config surfaces as one readable error\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\n try {\n // webpieces-disable no-any-unknown -- parsed config JSON is opaque until narrowed below\n raw = JSON.parse(fs.readFileSync(configPath, 'utf8')) as Record<string, unknown>;\n } catch (err: unknown) {\n const error = toError(err);\n return [`[pr-gate] ${path.basename(configPath)} is not valid JSON: ${error.message}`];\n }\n const repoRoot = path.dirname(configPath);\n // Checklists live under commands[\"pr-gate\"].checklists (current) or the legacy top-level pr-gate.\n // webpieces-disable no-any-unknown -- narrowing the opaque command section\n const commands = raw['commands'] as Record<string, unknown> | undefined;\n // webpieces-disable no-any-unknown -- narrowing the opaque pr-gate section\n const prGate = (commands?.['pr-gate'] ?? raw['pr-gate']) as Record<string, unknown> | undefined;\n if (!prGate || !('checklists' in prGate)) return [];\n return validateChecklists(prGate['checklists'], repoRoot);\n}\n"]}
@@ -8,6 +8,7 @@ export declare const RULE_NAMES: {
8
8
  readonly THROW_CAUSE_REQUIRED: "throw-cause-required";
9
9
  readonly REQUIRE_RETURN_TYPE: "require-return-type";
10
10
  readonly NO_SYMBOL_DI_TOKENS: "no-symbol-di-tokens";
11
+ readonly NO_CLIENT_CREATION_OUTSIDE_SERVER_OR_CLIENT: "no-client-creation-outside-server-or-client";
11
12
  readonly NO_PROCESS_EXIT_OUTSIDE_MAIN: "no-process-exit-outside-main";
12
13
  readonly NO_FUNCTION_OUTSIDE_CLASS: "no-function-outside-class";
13
14
  readonly INJECT_ANNOTATION_NOT_NEEDED_FOR_CONCRETE_CLASS: "inject-annotation-not-needed-for-concrete-class";
package/src/constants.js CHANGED
@@ -22,6 +22,7 @@ exports.RULE_NAMES = {
22
22
  THROW_CAUSE_REQUIRED: 'throw-cause-required',
23
23
  REQUIRE_RETURN_TYPE: 'require-return-type',
24
24
  NO_SYMBOL_DI_TOKENS: 'no-symbol-di-tokens',
25
+ NO_CLIENT_CREATION_OUTSIDE_SERVER_OR_CLIENT: 'no-client-creation-outside-server-or-client',
25
26
  NO_PROCESS_EXIT_OUTSIDE_MAIN: 'no-process-exit-outside-main',
26
27
  NO_FUNCTION_OUTSIDE_CLASS: 'no-function-outside-class',
27
28
  INJECT_ANNOTATION_NOT_NEEDED_FOR_CONCRETE_CLASS: 'inject-annotation-not-needed-for-concrete-class',
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../../../packages/tooling/rules-config/src/constants.ts"],"names":[],"mappings":";AAAA,iFAAiF;AACjF,sEAAsE;AACtE,EAAE;AACF,yFAAyF;AACzF,qFAAqF;AACrF,kFAAkF;;;AAiElF,gCAEC;AAjEY,QAAA,iBAAiB,GAAG,mBAAmB,CAAC;AAErD,kFAAkF;AAClF,uFAAuF;AACvF,uEAAuE;AACvE,sFAAsF;AACzE,QAAA,UAAU,GAAG;IACtB,cAAc,EAAE,gBAAgB;IAChC,eAAe,EAAE,iBAAiB;IAClC,cAAc,EAAE,gBAAgB;IAChC,uBAAuB,EAAE,yBAAyB;IAClD,mBAAmB,EAAE,qBAAqB;IAC1C,oBAAoB,EAAE,sBAAsB;IAC5C,mBAAmB,EAAE,qBAAqB;IAC1C,mBAAmB,EAAE,qBAAqB;IAC1C,4BAA4B,EAAE,8BAA8B;IAC5D,yBAAyB,EAAE,2BAA2B;IACtD,+CAA+C,EAAE,iDAAiD;IAClG,aAAa,EAAE,eAAe;IAC9B,QAAQ,EAAE,UAAU;IACpB,eAAe,EAAE,iBAAiB;IAClC,sBAAsB,EAAE,wBAAwB;IAChD,aAAa,EAAE,eAAe;IAC9B,gBAAgB,EAAE,kBAAkB;IACpC,qBAAqB,EAAE,uBAAuB;IAC9C,wBAAwB,EAAE,0BAA0B;IACpD,kBAAkB,EAAE,oBAAoB;CAClC,CAAC;AAEX,wFAAwF;AACxF,0FAA0F;AAC1F,sFAAsF;AACtF,0DAA0D;AAC1D,EAAE;AACF,mFAAmF;AACnF,uFAAuF;AACvF,0FAA0F;AAC1F,iGAAiG;AACjG,8FAA8F;AAC9F,yFAAyF;AAC5E,QAAA,iBAAiB,GAAG,YAAY,CAAC;AACjC,QAAA,cAAc,GAAG,YAAY,CAAC;AAC3C,kGAAkG;AAClG,qGAAqG;AACrG,iCAAiC;AACpB,QAAA,aAAa,GAAG,WAAW,CAAC;AAC5B,QAAA,sBAAsB,GAAG,wBAAwB,CAAC;AAE/D,2FAA2F;AAC3F,mFAAmF;AACnF,uFAAuF;AACvF,uGAAuG;AACvG,kGAAkG;AAClG,kGAAkG;AAClG,iDAAiD;AACpC,QAAA,sBAAsB,GAAG,sBAAsB,CAAC;AAE7D;;;;;GAKG;AACH,SAAgB,UAAU,CAAC,IAAY,EAAE,QAAgB;IACrD,OAAO,IAAI,CAAC,QAAQ,CAAC,yBAAiB,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AACvE,CAAC","sourcesContent":["// Single source of truth for the disable-comment token and rule-name identifiers\n// shared across rules-config, ai-hook-rules, code-rules, and pr-gate.\n//\n// There is exactly ONE disable form: `// webpieces-disable <rule>[, <rule2>] -- reason`.\n// The legacy `ai-hook-disable` alias and the `-file`/`-next`/`-all` variants and the\n// `*`/bare (no-rule) wildcard have been removed — every disable MUST name a rule.\n\nexport const WEBPIECES_DISABLE = 'webpieces-disable';\n\n// Rule-name tokens as they appear AFTER `webpieces-disable` in a disable comment.\n// Values must match existing comments exactly — changing a value silently breaks every\n// disable that names that rule. Note MAX_LINES_MODIFIED is a prefix of\n// MAX_LINES_MODIFIED_FILES (a historical substring-match quirk preserved on purpose).\nexport const RULE_NAMES = {\n NO_ANY_UNKNOWN: 'no-any-unknown',\n NO_IMPLICIT_ANY: 'no-implicit-any',\n NO_DESTRUCTURE: 'no-destructure',\n NO_UNMANAGED_EXCEPTIONS: 'no-unmanaged-exceptions',\n CATCH_ERROR_PATTERN: 'catch-error-pattern',\n THROW_CAUSE_REQUIRED: 'throw-cause-required',\n REQUIRE_RETURN_TYPE: 'require-return-type',\n NO_SYMBOL_DI_TOKENS: 'no-symbol-di-tokens',\n NO_PROCESS_EXIT_OUTSIDE_MAIN: 'no-process-exit-outside-main',\n NO_FUNCTION_OUTSIDE_CLASS: 'no-function-outside-class',\n INJECT_ANNOTATION_NOT_NEEDED_FOR_CONCRETE_CLASS: 'inject-annotation-not-needed-for-concrete-class',\n FRAMEWORK_TAG: 'framework-tag',\n ROLE_TAG: 'role-tag',\n NO_INLINE_TYPES: 'no-inline-types',\n NO_DIRECT_API_RESOLVER: 'no-direct-api-resolver',\n NO_CUSTOM_CSS: 'no-custom-css',\n PRISMA_CONVERTER: 'prisma-converter',\n MAX_LINES_NEW_METHODS: 'max-lines-new-methods',\n MAX_LINES_MODIFIED_FILES: 'max-lines-modified-files',\n MAX_LINES_MODIFIED: 'max-lines-modified',\n} as const;\n\n// Merge-state convention shared by the pr-gate scripts (which WRITE the marker during a\n// conflicted 3-point merge) and the ai-hook-rules merge-in-progress-guard (which READS it\n// to block commit/push/PR until the merge is validated). Kept here so neither package\n// depends on the other — they only share this vocabulary.\n//\n// `.webpieces/` is the single working dir for all webpieces tooling: ai-hook-rules\n// bootstrap/cache, the instruct-ai docs, and the workflow state. To keep the top level\n// quiet, per-feature workflow dirs are nested one level down under `merge-info/<feature>`\n// and `pr-review/<feature>` rather than scattered as top-level `merge-<feature>`/`pr-<feature>`.\n// `.webpieces/` is gitignored; only the per-feature subdirs under those two homes are subject\n// to 30-day cleanup (the homes themselves, like hooks/ and instruct-ai/, are permanent).\nexport const WEBPIECES_TMP_DIR = '.webpieces';\nexport const MERGE_INFO_DIR = 'merge-info';\n// The PR working home. Renamed from the legacy `pr-info` to `pr-review` for clarity (it holds the\n// AI's PR review + rendered body). Old `pr-info/` dirs are gitignored local state and self-clear via\n// cleanTmp's legacy `pr-` sweep.\nexport const PR_REVIEW_DIR = 'pr-review';\nexport const MERGE_IN_PROGRESS_FILE = 'merge-in-progress.json';\n\n// Proof-of-work the AI must produce for every conflicted file it resolves during a 3-point\n// merge: a short explanation written NEXT TO that file's 3-point context (the same\n// `updatemain-<safe_path>/` dir that holds A-forkpoint.txt / B-A.diff / C-A.diff). The\n// wp-finish-upsert-pr gate requires a non-empty file of this name per conflicted file before passing —\n// it is the only check on the part of the process the AI actually owns (resolving files). Using a\n// sidecar file (rather than an in-source comment) works for any file type, including comment-less\n// ones like JSON and files resolved by deletion.\nexport const MERGE_EXPLANATION_FILE = 'merge-explanation.md';\n\n/**\n * Fast predicate: does this text carry a webpieces-disable for the given rule?\n * Line-agnostic — the caller decides which line(s) or block of text to feed it.\n * This is the cheap substring form used by code-rules detection and pr-gate's\n * dashboard grep/count. (ai-hook-rules uses a richer line-mapping parser.)\n */\nexport function hasDisable(text: string, ruleName: string): boolean {\n return text.includes(WEBPIECES_DISABLE) && text.includes(ruleName);\n}\n"]}
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../../../packages/tooling/rules-config/src/constants.ts"],"names":[],"mappings":";AAAA,iFAAiF;AACjF,sEAAsE;AACtE,EAAE;AACF,yFAAyF;AACzF,qFAAqF;AACrF,kFAAkF;;;AAkElF,gCAEC;AAlEY,QAAA,iBAAiB,GAAG,mBAAmB,CAAC;AAErD,kFAAkF;AAClF,uFAAuF;AACvF,uEAAuE;AACvE,sFAAsF;AACzE,QAAA,UAAU,GAAG;IACtB,cAAc,EAAE,gBAAgB;IAChC,eAAe,EAAE,iBAAiB;IAClC,cAAc,EAAE,gBAAgB;IAChC,uBAAuB,EAAE,yBAAyB;IAClD,mBAAmB,EAAE,qBAAqB;IAC1C,oBAAoB,EAAE,sBAAsB;IAC5C,mBAAmB,EAAE,qBAAqB;IAC1C,mBAAmB,EAAE,qBAAqB;IAC1C,2CAA2C,EAAE,6CAA6C;IAC1F,4BAA4B,EAAE,8BAA8B;IAC5D,yBAAyB,EAAE,2BAA2B;IACtD,+CAA+C,EAAE,iDAAiD;IAClG,aAAa,EAAE,eAAe;IAC9B,QAAQ,EAAE,UAAU;IACpB,eAAe,EAAE,iBAAiB;IAClC,sBAAsB,EAAE,wBAAwB;IAChD,aAAa,EAAE,eAAe;IAC9B,gBAAgB,EAAE,kBAAkB;IACpC,qBAAqB,EAAE,uBAAuB;IAC9C,wBAAwB,EAAE,0BAA0B;IACpD,kBAAkB,EAAE,oBAAoB;CAClC,CAAC;AAEX,wFAAwF;AACxF,0FAA0F;AAC1F,sFAAsF;AACtF,0DAA0D;AAC1D,EAAE;AACF,mFAAmF;AACnF,uFAAuF;AACvF,0FAA0F;AAC1F,iGAAiG;AACjG,8FAA8F;AAC9F,yFAAyF;AAC5E,QAAA,iBAAiB,GAAG,YAAY,CAAC;AACjC,QAAA,cAAc,GAAG,YAAY,CAAC;AAC3C,kGAAkG;AAClG,qGAAqG;AACrG,iCAAiC;AACpB,QAAA,aAAa,GAAG,WAAW,CAAC;AAC5B,QAAA,sBAAsB,GAAG,wBAAwB,CAAC;AAE/D,2FAA2F;AAC3F,mFAAmF;AACnF,uFAAuF;AACvF,uGAAuG;AACvG,kGAAkG;AAClG,kGAAkG;AAClG,iDAAiD;AACpC,QAAA,sBAAsB,GAAG,sBAAsB,CAAC;AAE7D;;;;;GAKG;AACH,SAAgB,UAAU,CAAC,IAAY,EAAE,QAAgB;IACrD,OAAO,IAAI,CAAC,QAAQ,CAAC,yBAAiB,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AACvE,CAAC","sourcesContent":["// Single source of truth for the disable-comment token and rule-name identifiers\n// shared across rules-config, ai-hook-rules, code-rules, and pr-gate.\n//\n// There is exactly ONE disable form: `// webpieces-disable <rule>[, <rule2>] -- reason`.\n// The legacy `ai-hook-disable` alias and the `-file`/`-next`/`-all` variants and the\n// `*`/bare (no-rule) wildcard have been removed — every disable MUST name a rule.\n\nexport const WEBPIECES_DISABLE = 'webpieces-disable';\n\n// Rule-name tokens as they appear AFTER `webpieces-disable` in a disable comment.\n// Values must match existing comments exactly — changing a value silently breaks every\n// disable that names that rule. Note MAX_LINES_MODIFIED is a prefix of\n// MAX_LINES_MODIFIED_FILES (a historical substring-match quirk preserved on purpose).\nexport const RULE_NAMES = {\n NO_ANY_UNKNOWN: 'no-any-unknown',\n NO_IMPLICIT_ANY: 'no-implicit-any',\n NO_DESTRUCTURE: 'no-destructure',\n NO_UNMANAGED_EXCEPTIONS: 'no-unmanaged-exceptions',\n CATCH_ERROR_PATTERN: 'catch-error-pattern',\n THROW_CAUSE_REQUIRED: 'throw-cause-required',\n REQUIRE_RETURN_TYPE: 'require-return-type',\n NO_SYMBOL_DI_TOKENS: 'no-symbol-di-tokens',\n NO_CLIENT_CREATION_OUTSIDE_SERVER_OR_CLIENT: 'no-client-creation-outside-server-or-client',\n NO_PROCESS_EXIT_OUTSIDE_MAIN: 'no-process-exit-outside-main',\n NO_FUNCTION_OUTSIDE_CLASS: 'no-function-outside-class',\n INJECT_ANNOTATION_NOT_NEEDED_FOR_CONCRETE_CLASS: 'inject-annotation-not-needed-for-concrete-class',\n FRAMEWORK_TAG: 'framework-tag',\n ROLE_TAG: 'role-tag',\n NO_INLINE_TYPES: 'no-inline-types',\n NO_DIRECT_API_RESOLVER: 'no-direct-api-resolver',\n NO_CUSTOM_CSS: 'no-custom-css',\n PRISMA_CONVERTER: 'prisma-converter',\n MAX_LINES_NEW_METHODS: 'max-lines-new-methods',\n MAX_LINES_MODIFIED_FILES: 'max-lines-modified-files',\n MAX_LINES_MODIFIED: 'max-lines-modified',\n} as const;\n\n// Merge-state convention shared by the pr-gate scripts (which WRITE the marker during a\n// conflicted 3-point merge) and the ai-hook-rules merge-in-progress-guard (which READS it\n// to block commit/push/PR until the merge is validated). Kept here so neither package\n// depends on the other — they only share this vocabulary.\n//\n// `.webpieces/` is the single working dir for all webpieces tooling: ai-hook-rules\n// bootstrap/cache, the instruct-ai docs, and the workflow state. To keep the top level\n// quiet, per-feature workflow dirs are nested one level down under `merge-info/<feature>`\n// and `pr-review/<feature>` rather than scattered as top-level `merge-<feature>`/`pr-<feature>`.\n// `.webpieces/` is gitignored; only the per-feature subdirs under those two homes are subject\n// to 30-day cleanup (the homes themselves, like hooks/ and instruct-ai/, are permanent).\nexport const WEBPIECES_TMP_DIR = '.webpieces';\nexport const MERGE_INFO_DIR = 'merge-info';\n// The PR working home. Renamed from the legacy `pr-info` to `pr-review` for clarity (it holds the\n// AI's PR review + rendered body). Old `pr-info/` dirs are gitignored local state and self-clear via\n// cleanTmp's legacy `pr-` sweep.\nexport const PR_REVIEW_DIR = 'pr-review';\nexport const MERGE_IN_PROGRESS_FILE = 'merge-in-progress.json';\n\n// Proof-of-work the AI must produce for every conflicted file it resolves during a 3-point\n// merge: a short explanation written NEXT TO that file's 3-point context (the same\n// `updatemain-<safe_path>/` dir that holds A-forkpoint.txt / B-A.diff / C-A.diff). The\n// wp-finish-upsert-pr gate requires a non-empty file of this name per conflicted file before passing —\n// it is the only check on the part of the process the AI actually owns (resolving files). Using a\n// sidecar file (rather than an in-source comment) works for any file type, including comment-less\n// ones like JSON and files resolved by deletion.\nexport const MERGE_EXPLANATION_FILE = 'merge-explanation.md';\n\n/**\n * Fast predicate: does this text carry a webpieces-disable for the given rule?\n * Line-agnostic — the caller decides which line(s) or block of text to feed it.\n * This is the cheap substring form used by code-rules detection and pr-gate's\n * dashboard grep/count. (ai-hook-rules uses a richer line-mapping parser.)\n */\nexport function hasDisable(text: string, ruleName: string): boolean {\n return text.includes(WEBPIECES_DISABLE) && text.includes(ruleName);\n}\n"]}
@@ -29,6 +29,10 @@ exports.defaultRules = {
29
29
  'prisma-converter': {},
30
30
  'angular-no-direct-api-in-resolver': {},
31
31
  'no-symbol-di-tokens': {},
32
+ // Ships OFF: a repo opts in per webpieces.config.json once it is ready to migrate any
33
+ // client-in-a-lib sites (severity defaults to "warn" so even when enabled it reports without
34
+ // failing until a repo flips it to "error").
35
+ 'no-client-creation-outside-server-or-client': { mode: 'OFF' },
32
36
  'no-custom-css': { allowGlobs: [] },
33
37
  'no-process-exit-outside-main': {},
34
38
  'inject-annotation-not-needed-for-concrete-class': {},
@@ -1 +1 @@
1
- {"version":3,"file":"default-rules.js","sourceRoot":"","sources":["../../../../../packages/tooling/rules-config/src/default-rules.ts"],"names":[],"mappings":"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","sourcesContent":["// Default holistic exclude list for the validate-ts-in-src\n// rules. Bare names match a directory segment at any depth; globs match the\n// workspace-relative path. `**/*.d.ts` (ambient declarations) and\n// `**/jest.config.ts` legitimately live outside src/ and are exempt here.\nconst DEFAULT_EXCLUDE_PATHS: readonly string[] = [\n 'node_modules', 'dist', '.nx', '.git',\n '**/*.d.ts', '**/jest.config.ts',\n];\n\n// On/off is driven by `mode` (\"OFF\" disables; an absent mode leaves a rule\n// on). Code-rules entries omit `mode` so each executor keeps its own default\n// scope; structural rules declare `mode: 'RUN_EVERY_TIME'`, bash guards `mode: 'ON'`.\n// webpieces-disable no-any-unknown -- rule options are opaque at framework level\nexport const defaultRules: Record<string, Record<string, unknown>> = {\n 'no-any-unknown': {},\n 'no-implicit-any': {},\n 'max-file-lines': { limit: 900 },\n 'max-method-lines': { limit: 80 },\n 'require-return-type': {},\n 'no-inline-type-literals': {},\n 'no-destructure': { allowTopLevel: true },\n 'catch-error-pattern': {},\n 'no-unmanaged-exceptions': {},\n 'no-file-import-cycles': { mode: 'RUN_EVERY_TIME' },\n 'runtime-architecture': { mode: 'RUN_EVERY_TIME', allowedCycles: [] },\n 'prisma-validate-dtos': {},\n 'prisma-converter': {},\n 'angular-no-direct-api-in-resolver': {},\n 'no-symbol-di-tokens': {},\n 'no-custom-css': { allowGlobs: [] },\n 'no-process-exit-outside-main': {},\n 'inject-annotation-not-needed-for-concrete-class': {},\n 'framework-tag': { mode: 'MODIFIED_PROJECTS', knownTypes: ['browser', 'react', 'angular', 'node', 'express'] },\n 'role-tag': { mode: 'MODIFIED_PROJECTS', knownTypes: ['server', 'app', 'designed-lib', 'lib', 'client', 'api-lib'] },\n 'nx-wiring': { mode: 'RUN_EVERY_TIME' },\n 'di-graph': { mode: 'RUN_EVERY_TIME' },\n 'missing-design-annotation': { mode: 'RUN_EVERY_TIME' },\n 'validate-ts-in-src': {\n mode: 'NEW_AND_MODIFIED_FILES',\n allowedRootFiles: ['jest.setup.ts'],\n excludePaths: [...DEFAULT_EXCLUDE_PATHS],\n },\n 'no-js-files': { mode: 'OFF' },\n // The five Nx infrastructure validators. They enforced unconditionally before they were wired to\n // config, so RUN_EVERY_TIME is the only default that keeps existing repos behaving identically on\n // upgrade. Set \"mode\": \"OFF\" to disable one; the two graph-baseline rules\n // (validate-architecture-unchanged / validate-no-architecture-cycles) additionally honor\n // ignoreModifiedUntilEpoch — the other three are all-or-nothing (see rule-configs.ts).\n 'validate-architecture-unchanged': { mode: 'RUN_EVERY_TIME' },\n 'validate-no-architecture-cycles': { mode: 'RUN_EVERY_TIME' },\n 'validate-packagejson': { mode: 'RUN_EVERY_TIME' },\n 'validate-versions-locked': { mode: 'RUN_EVERY_TIME' },\n 'validate-eslint-sync': { mode: 'RUN_EVERY_TIME' },\n // autoReapMergedBranches ships FALSE. It is schema-required so every consumer must state a value,\n // and the framework default must be the conservative one: an upgrade should never start deleting\n // a project's branches unattended before a human has opted in. Set it true to let the background\n // refresher reap dead branches on its own; `pnpm wp-cleanup` works either way.\n 'branch-creation-guard': {\n mode: 'ON',\n subBranchNaming: 'feature/<ticket>/<short-description>',\n autoReapMergedBranches: false,\n },\n 'pr-creation-or-push-guard': { mode: 'ON' },\n 'merge-in-progress-guard': { mode: 'ON' },\n 'pr-merge-guard': { mode: 'ON' },\n 'redirect-how-to-merge-main': { mode: 'ON' },\n // Phase 1 ships OFF on purpose. This guard blocks Read, the highest-blast-radius tool there is,\n // so it is opted into per-repo (webpieces.config.json → hookGuards) only AFTER the release\n // carrying it is published and installed. Flipping it ON here would arm it for every consumer\n // on upgrade, before anyone has verified the fail-open paths against their own git layout.\n 'read-stale-guard': { mode: 'OFF' },\n};\n\nexport const defaultRulesDir: readonly string[] = [];\n"]}
1
+ {"version":3,"file":"default-rules.js","sourceRoot":"","sources":["../../../../../packages/tooling/rules-config/src/default-rules.ts"],"names":[],"mappings":"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","sourcesContent":["// Default holistic exclude list for the validate-ts-in-src\n// rules. Bare names match a directory segment at any depth; globs match the\n// workspace-relative path. `**/*.d.ts` (ambient declarations) and\n// `**/jest.config.ts` legitimately live outside src/ and are exempt here.\nconst DEFAULT_EXCLUDE_PATHS: readonly string[] = [\n 'node_modules', 'dist', '.nx', '.git',\n '**/*.d.ts', '**/jest.config.ts',\n];\n\n// On/off is driven by `mode` (\"OFF\" disables; an absent mode leaves a rule\n// on). Code-rules entries omit `mode` so each executor keeps its own default\n// scope; structural rules declare `mode: 'RUN_EVERY_TIME'`, bash guards `mode: 'ON'`.\n// webpieces-disable no-any-unknown -- rule options are opaque at framework level\nexport const defaultRules: Record<string, Record<string, unknown>> = {\n 'no-any-unknown': {},\n 'no-implicit-any': {},\n 'max-file-lines': { limit: 900 },\n 'max-method-lines': { limit: 80 },\n 'require-return-type': {},\n 'no-inline-type-literals': {},\n 'no-destructure': { allowTopLevel: true },\n 'catch-error-pattern': {},\n 'no-unmanaged-exceptions': {},\n 'no-file-import-cycles': { mode: 'RUN_EVERY_TIME' },\n 'runtime-architecture': { mode: 'RUN_EVERY_TIME', allowedCycles: [] },\n 'prisma-validate-dtos': {},\n 'prisma-converter': {},\n 'angular-no-direct-api-in-resolver': {},\n 'no-symbol-di-tokens': {},\n // Ships OFF: a repo opts in per webpieces.config.json once it is ready to migrate any\n // client-in-a-lib sites (severity defaults to \"warn\" so even when enabled it reports without\n // failing until a repo flips it to \"error\").\n 'no-client-creation-outside-server-or-client': { mode: 'OFF' },\n 'no-custom-css': { allowGlobs: [] },\n 'no-process-exit-outside-main': {},\n 'inject-annotation-not-needed-for-concrete-class': {},\n 'framework-tag': { mode: 'MODIFIED_PROJECTS', knownTypes: ['browser', 'react', 'angular', 'node', 'express'] },\n 'role-tag': { mode: 'MODIFIED_PROJECTS', knownTypes: ['server', 'app', 'designed-lib', 'lib', 'client', 'api-lib'] },\n 'nx-wiring': { mode: 'RUN_EVERY_TIME' },\n 'di-graph': { mode: 'RUN_EVERY_TIME' },\n 'missing-design-annotation': { mode: 'RUN_EVERY_TIME' },\n 'validate-ts-in-src': {\n mode: 'NEW_AND_MODIFIED_FILES',\n allowedRootFiles: ['jest.setup.ts'],\n excludePaths: [...DEFAULT_EXCLUDE_PATHS],\n },\n 'no-js-files': { mode: 'OFF' },\n // The five Nx infrastructure validators. They enforced unconditionally before they were wired to\n // config, so RUN_EVERY_TIME is the only default that keeps existing repos behaving identically on\n // upgrade. Set \"mode\": \"OFF\" to disable one; the two graph-baseline rules\n // (validate-architecture-unchanged / validate-no-architecture-cycles) additionally honor\n // ignoreModifiedUntilEpoch — the other three are all-or-nothing (see rule-configs.ts).\n 'validate-architecture-unchanged': { mode: 'RUN_EVERY_TIME' },\n 'validate-no-architecture-cycles': { mode: 'RUN_EVERY_TIME' },\n 'validate-packagejson': { mode: 'RUN_EVERY_TIME' },\n 'validate-versions-locked': { mode: 'RUN_EVERY_TIME' },\n 'validate-eslint-sync': { mode: 'RUN_EVERY_TIME' },\n // autoReapMergedBranches ships FALSE. It is schema-required so every consumer must state a value,\n // and the framework default must be the conservative one: an upgrade should never start deleting\n // a project's branches unattended before a human has opted in. Set it true to let the background\n // refresher reap dead branches on its own; `pnpm wp-cleanup` works either way.\n 'branch-creation-guard': {\n mode: 'ON',\n subBranchNaming: 'feature/<ticket>/<short-description>',\n autoReapMergedBranches: false,\n },\n 'pr-creation-or-push-guard': { mode: 'ON' },\n 'merge-in-progress-guard': { mode: 'ON' },\n 'pr-merge-guard': { mode: 'ON' },\n 'redirect-how-to-merge-main': { mode: 'ON' },\n // Phase 1 ships OFF on purpose. This guard blocks Read, the highest-blast-radius tool there is,\n // so it is opted into per-repo (webpieces.config.json → hookGuards) only AFTER the release\n // carrying it is published and installed. Flipping it ON here would arm it for every consumer\n // on upgrade, before anyone has verified the fail-open paths against their own git layout.\n 'read-stale-guard': { mode: 'OFF' },\n};\n\nexport const defaultRulesDir: readonly string[] = [];\n"]}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Mints + verifies the server-verifiable PR gate token.
3
+ *
4
+ * `token = HMAC-SHA256(gateSalt, HEAD_sha)`. `wp-finish-upsert-pr` writes it into the PR body (and
5
+ * refuses to mint it unless every BLOCK checklist passed), so a valid token IS proof the local gate ran
6
+ * and passed on that exact commit. `wp-check-pr` in CI recomputes `HMAC(gateSalt, pr.head.sha)` from the
7
+ * committed salt and compares — a PR opened outside the gated flow (unhooked teammate, web UI) carries
8
+ * no valid token for its head sha and fails.
9
+ *
10
+ * Bound to the HEAD sha (not the title/diff) so every push needs a fresh mint: hooked devs re-run finish
11
+ * on every push anyway (manual push is locally blocked), an unhooked bypasser's raw push does not.
12
+ *
13
+ * `@injectable(bindingScopeValues.Singleton)` so it is drawn in the DI design and injected by type.
14
+ */
15
+ export declare class GateTokenService {
16
+ computeGateToken(gateSalt: string, headSha: string): string;
17
+ gateTokenMarker(gateSalt: string, headSha: string): string;
18
+ extractGateToken(prBody: string): string;
19
+ verifyGateToken(prBody: string, gateSalt: string, headSha: string): boolean;
20
+ }
21
+ export declare function computeGateToken(gateSalt: string, headSha: string): string;
22
+ export declare function gateTokenMarker(gateSalt: string, headSha: string): string;
23
+ export declare function extractGateToken(prBody: string): string;
24
+ export declare function verifyGateToken(prBody: string, gateSalt: string, headSha: string): boolean;
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GateTokenService = void 0;
4
+ exports.computeGateToken = computeGateToken;
5
+ exports.gateTokenMarker = gateTokenMarker;
6
+ exports.extractGateToken = extractGateToken;
7
+ exports.verifyGateToken = verifyGateToken;
8
+ const tslib_1 = require("tslib");
9
+ const crypto_1 = require("crypto");
10
+ const inversify_1 = require("inversify");
11
+ // The hidden PR-body marker that carries the gate token. An HTML comment so it does NOT render in the
12
+ // PR description a human reads, but survives round-tripping through `gh pr view --json body`. Versioned
13
+ // so the format can evolve without silently validating an old shape.
14
+ const MARKER_RE = /<!--\s*webpieces-pr-gate\s+v1\s+token=([0-9a-f]{64})\s*-->/;
15
+ /**
16
+ * Mints + verifies the server-verifiable PR gate token.
17
+ *
18
+ * `token = HMAC-SHA256(gateSalt, HEAD_sha)`. `wp-finish-upsert-pr` writes it into the PR body (and
19
+ * refuses to mint it unless every BLOCK checklist passed), so a valid token IS proof the local gate ran
20
+ * and passed on that exact commit. `wp-check-pr` in CI recomputes `HMAC(gateSalt, pr.head.sha)` from the
21
+ * committed salt and compares — a PR opened outside the gated flow (unhooked teammate, web UI) carries
22
+ * no valid token for its head sha and fails.
23
+ *
24
+ * Bound to the HEAD sha (not the title/diff) so every push needs a fresh mint: hooked devs re-run finish
25
+ * on every push anyway (manual push is locally blocked), an unhooked bypasser's raw push does not.
26
+ *
27
+ * `@injectable(bindingScopeValues.Singleton)` so it is drawn in the DI design and injected by type.
28
+ */
29
+ let GateTokenService = class GateTokenService {
30
+ // The raw HMAC hex for (salt, sha). Empty salt ⇒ '' (caller treats '' as "no token / disabled").
31
+ computeGateToken(gateSalt, headSha) {
32
+ if (gateSalt.trim() === '' || headSha.trim() === '')
33
+ return '';
34
+ return (0, crypto_1.createHmac)('sha256', gateSalt).update(headSha).digest('hex');
35
+ }
36
+ // The hidden HTML-comment marker to append to a PR body. '' when there is no token to embed, so a
37
+ // repo with no gateSalt gets a byte-identical PR body to before this feature existed.
38
+ gateTokenMarker(gateSalt, headSha) {
39
+ const token = this.computeGateToken(gateSalt, headSha);
40
+ return token === '' ? '' : `<!-- webpieces-pr-gate v1 token=${token} -->`;
41
+ }
42
+ // Pull the token hex out of a PR body (whatever else the body contains), or '' when absent.
43
+ extractGateToken(prBody) {
44
+ const m = MARKER_RE.exec(prBody);
45
+ return m ? m[1] : '';
46
+ }
47
+ // True when `prBody` carries a token that matches HMAC(gateSalt, headSha). Constant-ish comparison is
48
+ // unnecessary here — the salt is committed/obscurity-grade, so timing side channels add no security.
49
+ verifyGateToken(prBody, gateSalt, headSha) {
50
+ const expected = this.computeGateToken(gateSalt, headSha);
51
+ if (expected === '')
52
+ return false;
53
+ return this.extractGateToken(prBody) === expected;
54
+ }
55
+ };
56
+ exports.GateTokenService = GateTokenService;
57
+ exports.GateTokenService = GateTokenService = tslib_1.__decorate([
58
+ (0, inversify_1.injectable)(inversify_1.bindingScopeValues.Singleton)
59
+ ], GateTokenService);
60
+ // Temporary migration delegators to GateTokenService — removed once every consumer injects it.
61
+ const gateTokenSvc = new GateTokenService();
62
+ // webpieces-disable no-function-outside-class -- temporary back-compat delegator to GateTokenService
63
+ function computeGateToken(gateSalt, headSha) {
64
+ return gateTokenSvc.computeGateToken(gateSalt, headSha);
65
+ }
66
+ // webpieces-disable no-function-outside-class -- temporary back-compat delegator to GateTokenService
67
+ function gateTokenMarker(gateSalt, headSha) {
68
+ return gateTokenSvc.gateTokenMarker(gateSalt, headSha);
69
+ }
70
+ // webpieces-disable no-function-outside-class -- temporary back-compat delegator to GateTokenService
71
+ function extractGateToken(prBody) {
72
+ return gateTokenSvc.extractGateToken(prBody);
73
+ }
74
+ // webpieces-disable no-function-outside-class -- temporary back-compat delegator to GateTokenService
75
+ function verifyGateToken(prBody, gateSalt, headSha) {
76
+ return gateTokenSvc.verifyGateToken(prBody, gateSalt, headSha);
77
+ }
78
+ //# sourceMappingURL=gate-token.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gate-token.js","sourceRoot":"","sources":["../../../../../packages/tooling/rules-config/src/gate-token.ts"],"names":[],"mappings":";;;AAwDA,4CAEC;AAGD,0CAEC;AAGD,4CAEC;AAGD,0CAEC;;AAzED,mCAAoC;AACpC,yCAA2D;AAE3D,sGAAsG;AACtG,wGAAwG;AACxG,qEAAqE;AACrE,MAAM,SAAS,GAAG,4DAA4D,CAAC;AAE/E;;;;;;;;;;;;;GAaG;AAEI,IAAM,gBAAgB,GAAtB,MAAM,gBAAgB;IACzB,iGAAiG;IACjG,gBAAgB,CAAC,QAAgB,EAAE,OAAe;QAC9C,IAAI,QAAQ,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE;YAAE,OAAO,EAAE,CAAC;QAC/D,OAAO,IAAA,mBAAU,EAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACxE,CAAC;IAED,kGAAkG;IAClG,sFAAsF;IACtF,eAAe,CAAC,QAAgB,EAAE,OAAe;QAC7C,MAAM,KAAK,GAAG,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACvD,OAAO,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,mCAAmC,KAAK,MAAM,CAAC;IAC9E,CAAC;IAED,4FAA4F;IAC5F,gBAAgB,CAAC,MAAc;QAC3B,MAAM,CAAC,GAAG,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACjC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACzB,CAAC;IAED,sGAAsG;IACtG,qGAAqG;IACrG,eAAe,CAAC,MAAc,EAAE,QAAgB,EAAE,OAAe;QAC7D,MAAM,QAAQ,GAAG,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC1D,IAAI,QAAQ,KAAK,EAAE;YAAE,OAAO,KAAK,CAAC;QAClC,OAAO,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,KAAK,QAAQ,CAAC;IACtD,CAAC;CACJ,CAAA;AA3BY,4CAAgB;2BAAhB,gBAAgB;IAD5B,IAAA,sBAAU,EAAC,8BAAkB,CAAC,SAAS,CAAC;GAC5B,gBAAgB,CA2B5B;AAED,+FAA+F;AAC/F,MAAM,YAAY,GAAG,IAAI,gBAAgB,EAAE,CAAC;AAE5C,qGAAqG;AACrG,SAAgB,gBAAgB,CAAC,QAAgB,EAAE,OAAe;IAC9D,OAAO,YAAY,CAAC,gBAAgB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;AAC5D,CAAC;AAED,qGAAqG;AACrG,SAAgB,eAAe,CAAC,QAAgB,EAAE,OAAe;IAC7D,OAAO,YAAY,CAAC,eAAe,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;AAC3D,CAAC;AAED,qGAAqG;AACrG,SAAgB,gBAAgB,CAAC,MAAc;IAC3C,OAAO,YAAY,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;AACjD,CAAC;AAED,qGAAqG;AACrG,SAAgB,eAAe,CAAC,MAAc,EAAE,QAAgB,EAAE,OAAe;IAC7E,OAAO,YAAY,CAAC,eAAe,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;AACnE,CAAC","sourcesContent":["import { createHmac } from 'crypto';\nimport { injectable, bindingScopeValues } from 'inversify';\n\n// The hidden PR-body marker that carries the gate token. An HTML comment so it does NOT render in the\n// PR description a human reads, but survives round-tripping through `gh pr view --json body`. Versioned\n// so the format can evolve without silently validating an old shape.\nconst MARKER_RE = /<!--\\s*webpieces-pr-gate\\s+v1\\s+token=([0-9a-f]{64})\\s*-->/;\n\n/**\n * Mints + verifies the server-verifiable PR gate token.\n *\n * `token = HMAC-SHA256(gateSalt, HEAD_sha)`. `wp-finish-upsert-pr` writes it into the PR body (and\n * refuses to mint it unless every BLOCK checklist passed), so a valid token IS proof the local gate ran\n * and passed on that exact commit. `wp-check-pr` in CI recomputes `HMAC(gateSalt, pr.head.sha)` from the\n * committed salt and compares — a PR opened outside the gated flow (unhooked teammate, web UI) carries\n * no valid token for its head sha and fails.\n *\n * Bound to the HEAD sha (not the title/diff) so every push needs a fresh mint: hooked devs re-run finish\n * on every push anyway (manual push is locally blocked), an unhooked bypasser's raw push does not.\n *\n * `@injectable(bindingScopeValues.Singleton)` so it is drawn in the DI design and injected by type.\n */\n@injectable(bindingScopeValues.Singleton)\nexport class GateTokenService {\n // The raw HMAC hex for (salt, sha). Empty salt ⇒ '' (caller treats '' as \"no token / disabled\").\n computeGateToken(gateSalt: string, headSha: string): string {\n if (gateSalt.trim() === '' || headSha.trim() === '') return '';\n return createHmac('sha256', gateSalt).update(headSha).digest('hex');\n }\n\n // The hidden HTML-comment marker to append to a PR body. '' when there is no token to embed, so a\n // repo with no gateSalt gets a byte-identical PR body to before this feature existed.\n gateTokenMarker(gateSalt: string, headSha: string): string {\n const token = this.computeGateToken(gateSalt, headSha);\n return token === '' ? '' : `<!-- webpieces-pr-gate v1 token=${token} -->`;\n }\n\n // Pull the token hex out of a PR body (whatever else the body contains), or '' when absent.\n extractGateToken(prBody: string): string {\n const m = MARKER_RE.exec(prBody);\n return m ? m[1] : '';\n }\n\n // True when `prBody` carries a token that matches HMAC(gateSalt, headSha). Constant-ish comparison is\n // unnecessary here — the salt is committed/obscurity-grade, so timing side channels add no security.\n verifyGateToken(prBody: string, gateSalt: string, headSha: string): boolean {\n const expected = this.computeGateToken(gateSalt, headSha);\n if (expected === '') return false;\n return this.extractGateToken(prBody) === expected;\n }\n}\n\n// Temporary migration delegators to GateTokenService — removed once every consumer injects it.\nconst gateTokenSvc = new GateTokenService();\n\n// webpieces-disable no-function-outside-class -- temporary back-compat delegator to GateTokenService\nexport function computeGateToken(gateSalt: string, headSha: string): string {\n return gateTokenSvc.computeGateToken(gateSalt, headSha);\n}\n\n// webpieces-disable no-function-outside-class -- temporary back-compat delegator to GateTokenService\nexport function gateTokenMarker(gateSalt: string, headSha: string): string {\n return gateTokenSvc.gateTokenMarker(gateSalt, headSha);\n}\n\n// webpieces-disable no-function-outside-class -- temporary back-compat delegator to GateTokenService\nexport function extractGateToken(prBody: string): string {\n return gateTokenSvc.extractGateToken(prBody);\n}\n\n// webpieces-disable no-function-outside-class -- temporary back-compat delegator to GateTokenService\nexport function verifyGateToken(prBody: string, gateSalt: string, headSha: string): boolean {\n return gateTokenSvc.verifyGateToken(prBody, gateSalt, headSha);\n}\n"]}
package/src/index.d.ts CHANGED
@@ -14,7 +14,8 @@ export { ExcludePaths } from './exclude-hook-paths';
14
14
  export { isPathExcluded } from './exclude-paths';
15
15
  export { defaultRules, defaultRulesDir } from './default-rules';
16
16
  export { loadTemplate, writeTemplateIfMissing, writeTemplate, TemplateWriter } from './load-template';
17
- export { validateWebpiecesConfig, validatePrGateSection, validateSectionPlacement, validateCommandsSection, validateExcludePaths, validateMatchRulesSection, allRuleNames } from './validate-config';
17
+ export { validateWebpiecesConfig, validatePrGateSection, validateChecklists, validateSectionPlacement, validateCommandsSection, validateExcludePaths, validateMatchRulesSection, allRuleNames } from './validate-config';
18
+ export { validateChecklistDocs } from './checklist-docs-validator';
18
19
  export { MatchRuleConfig, MatchRuleViolation, findMatchRuleViolations, isMatchRuleAllowedPath, compileMatchRulePatterns, renderMatchRuleMessage, DEFAULT_MATCH_RULES, } from './match-rules-config';
19
20
  export type { ConfigSection } from './sections';
20
21
  export { HOOK_GUARD_NAMES, isHookGuard, sectionForRule } from './sections';
@@ -29,11 +30,15 @@ export { WebpiecesRulesConfig } from './WebpiecesRulesConfig';
29
30
  export { SyncFlowGuidance, WP_START_UPDATE, WP_FINISH_UPDATE, WP_START_UPSERT_PR, WP_FINISH_UPSERT_PR, } from './sync-flow-guidance';
30
31
  export { MaxMethodLinesConfig, MaxFileLinesConfig, RequireReturnTypeConfig, NoInlineTypeLiteralsConfig, NoAnyUnknownConfig, NoImplicitAnyConfig, PrismaValidateDtosConfig, PrismaConverterConfig, NoDestructureConfig, NoUnmanagedExceptionsConfig, CatchErrorPatternConfig, ThrowCauseRequiredConfig, AngularNoDirectApiInResolverConfig, NoSymbolDiTokensConfig, NoCustomCssConfig, NoProcessExitOutsideMainConfig, NoFunctionOutsideClassConfig, InjectAnnotationNotNeededForConcreteClassConfig, FrameworkTagConfig, RoleTagConfig, BranchCreationGuardConfig, PrCreationOrPushGuardConfig, MergeInProgressGuardConfig, PrMergeGuardConfig, RedirectHowToMergeMainConfig, FeatureBranchGuardConfig, ReadStaleGuardConfig, MergedBranchBashGuardConfig, NoFileImportCyclesConfig, RuntimeArchitectureConfig, NxWiringConfig, DiGraphConfig, NoJsFilesConfig, ValidateTsInSrcConfig, ValidateArchitectureUnchangedConfig, ValidateNoArchitectureCyclesConfig, ValidatePackageJsonConfig, ValidateVersionsLockedConfig, ValidateEslintSyncConfig, BaseRuleConfig, } from './rule-configs';
31
32
  export { METHOD_LIMIT_MODES, FILE_LIMIT_MODES, RETURN_TYPE_MODES, INLINE_TYPE_MODES, MODIFIED_CODE_MODES, PROJECT_MODES, PRISMA_DTOS_MODES, PRISMA_CONVERTER_MODES, DIRECT_API_RESOLVER_MODES, THROW_CAUSE_MODES, ON_OFF_MODES, STRUCTURAL_MODES, VALIDATE_TS_MODES, } from './rule-configs';
33
+ export { NoClientCreationOutsideServerOrClientConfig, CLIENT_CREATION_SEVERITIES, } from './no-client-creation-config';
34
+ export type { ClientCreationSeverity } from './no-client-creation-config';
32
35
  export type { MethodLimitMode, FileLimitMode, ReturnTypeMode, InlineTypeMode, ModifiedCodeMode, ProjectMode, PrismaValidateDtosMode, PrismaConverterMode, DirectApiResolverMode, ThrowCauseMode, OnOffMode, StructuralMode, ValidateTsMode, } from './rule-configs';
33
36
  export { GateDefinition, PrGateConfig, defaultGates, defaultPrGateConfig, buildPrGateConfig, MERGE_MODE_AUTO, MERGE_MODE_NONE, MERGE_MODES, } from './pr-gate-config';
34
37
  export { ChecklistDefinition, toChecklist, CHECKLIST_BLOCK, CHECKLIST_WARN, CHECKLIST_SEVERITIES, } from './checklist-config';
35
38
  export type { RawChecklist } from './checklist-config';
36
- export { ReviewJson, ChecklistAck, RequiredChecklist, ReviewJsonService, loadReviewJson, prDirFor, reviewJsonPath, reviewJsonSchemaHint, } from './review-json';
39
+ export { GateTokenService, computeGateToken, gateTokenMarker, extractGateToken, verifyGateToken, } from './gate-token';
40
+ export { SubagentProvenanceService, ProvenanceResult, PROVENANCE_OK, PROVENANCE_MISSING, PROVENANCE_SKIPPED, } from './subagent-provenance';
41
+ export { ReviewJson, ChecklistAck, ChecklistResult, ChecklistVerdict, CK_PASS, CK_OVERRIDDEN, CK_FAIL, CK_MISSING, CK_ACKED, RequiredChecklist, ReviewJsonService, loadReviewJson, prDirFor, reviewJsonPath, reviewJsonSchemaHint, } from './review-json';
37
42
  export { MainSyncStatus, MainSyncLock, MainSyncStatusService, DEFAULT_HANG_TIMEOUT_MINUTES, mainSyncStatusPath, mainSyncLockPath, readMainSyncStatus, writeMainSyncStatus, readMainSyncLock, writeMainSyncLock, isLockStale, isRefreshInProgress, inProcessLock, finishedLock, computeMainSyncStatus, stampCleanMainSyncStatus, squashRecoverySteps, } from './main-sync-status';
38
43
  export { MergedBranch, DeletableBranch, DeletableWorktree, MergedBranchesCache, MergedBranchesService, } from './merged-branches';
39
44
  export { Worktree, WorktreeService, } from './worktrees';
package/src/index.js CHANGED
@@ -1,9 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getCurrentBranch = exports.shouldSkipRule = exports.FieldDef = exports.sectionForRule = exports.isHookGuard = exports.HOOK_GUARD_NAMES = exports.DEFAULT_MATCH_RULES = exports.renderMatchRuleMessage = exports.compileMatchRulePatterns = exports.isMatchRuleAllowedPath = exports.findMatchRuleViolations = exports.MatchRuleViolation = exports.MatchRuleConfig = exports.allRuleNames = exports.validateMatchRulesSection = exports.validateExcludePaths = exports.validateCommandsSection = exports.validateSectionPlacement = exports.validatePrGateSection = exports.validateWebpiecesConfig = exports.TemplateWriter = exports.writeTemplate = exports.writeTemplateIfMissing = exports.loadTemplate = exports.defaultRulesDir = exports.defaultRules = exports.isPathExcluded = exports.ExcludePaths = exports.DESIGN_METADATA_KEYS = exports.isDocumentDesign = exports.DocumentDesign = exports.RulesConfigDesign = exports.INSTRUCT_AI_DIR = exports.RepoRootFinder = exports.ConfigFile = exports.CONFIG_FILENAME = exports.findConfigFile = exports.ConfigLoader = exports.LoadedConfig = exports.loadAndValidate = exports.toError = exports.runMain = exports.CliArgs = exports.CliArgsCheck = exports.CliUsage = exports.CliExitError = exports.RuleFailError = exports.InformAiError = exports.ResolvedRuleConfig = exports.ResolvedConfig = void 0;
4
- exports.PrMergeGuardConfig = exports.MergeInProgressGuardConfig = exports.PrCreationOrPushGuardConfig = exports.BranchCreationGuardConfig = exports.RoleTagConfig = exports.FrameworkTagConfig = exports.InjectAnnotationNotNeededForConcreteClassConfig = exports.NoFunctionOutsideClassConfig = exports.NoProcessExitOutsideMainConfig = exports.NoCustomCssConfig = exports.NoSymbolDiTokensConfig = exports.AngularNoDirectApiInResolverConfig = exports.ThrowCauseRequiredConfig = exports.CatchErrorPatternConfig = exports.NoUnmanagedExceptionsConfig = exports.NoDestructureConfig = exports.PrismaConverterConfig = exports.PrismaValidateDtosConfig = exports.NoImplicitAnyConfig = exports.NoAnyUnknownConfig = exports.NoInlineTypeLiteralsConfig = exports.RequireReturnTypeConfig = exports.MaxFileLinesConfig = exports.MaxMethodLinesConfig = exports.WP_FINISH_UPSERT_PR = exports.WP_START_UPSERT_PR = exports.WP_FINISH_UPDATE = exports.WP_START_UPDATE = exports.SyncFlowGuidance = exports.WebpiecesRulesConfig = exports.MERGE_EXPLANATION_FILE = exports.MERGE_IN_PROGRESS_FILE = exports.PR_REVIEW_DIR = exports.MERGE_INFO_DIR = exports.WEBPIECES_TMP_DIR = exports.hasDisable = exports.RULE_NAMES = exports.WEBPIECES_DISABLE = exports.AbstractRule = exports.ChangedFilesOptions = exports.DiffRange = exports.DiffScope = exports.isNewOrModified = exports.hasChangesInRange = exports.findNewMethodSignaturesInDiff = exports.getChangedLineNumbers = exports.getFileDiff = exports.getChangedFiles = exports.resolveBase = exports.detectBase = void 0;
5
- exports.reviewJsonSchemaHint = exports.reviewJsonPath = exports.prDirFor = exports.loadReviewJson = exports.ReviewJsonService = exports.RequiredChecklist = exports.ChecklistAck = exports.ReviewJson = exports.CHECKLIST_SEVERITIES = exports.CHECKLIST_WARN = exports.CHECKLIST_BLOCK = exports.toChecklist = exports.ChecklistDefinition = exports.MERGE_MODES = exports.MERGE_MODE_NONE = exports.MERGE_MODE_AUTO = exports.buildPrGateConfig = exports.defaultPrGateConfig = exports.defaultGates = exports.PrGateConfig = exports.GateDefinition = exports.VALIDATE_TS_MODES = exports.STRUCTURAL_MODES = exports.ON_OFF_MODES = exports.THROW_CAUSE_MODES = exports.DIRECT_API_RESOLVER_MODES = exports.PRISMA_CONVERTER_MODES = exports.PRISMA_DTOS_MODES = exports.PROJECT_MODES = exports.MODIFIED_CODE_MODES = exports.INLINE_TYPE_MODES = exports.RETURN_TYPE_MODES = exports.FILE_LIMIT_MODES = exports.METHOD_LIMIT_MODES = exports.BaseRuleConfig = exports.ValidateEslintSyncConfig = exports.ValidateVersionsLockedConfig = exports.ValidatePackageJsonConfig = exports.ValidateNoArchitectureCyclesConfig = exports.ValidateArchitectureUnchangedConfig = exports.ValidateTsInSrcConfig = exports.NoJsFilesConfig = exports.DiGraphConfig = exports.NxWiringConfig = exports.RuntimeArchitectureConfig = exports.NoFileImportCyclesConfig = exports.MergedBranchBashGuardConfig = exports.ReadStaleGuardConfig = exports.FeatureBranchGuardConfig = exports.RedirectHowToMergeMainConfig = void 0;
6
- exports.DEFAULT_MERGE_COMPLETE_COMMAND = exports.DEFAULT_UPSERT_PR_COMMAND = exports.buildCommandsConfig = exports.CommandsConfig = exports.logBranchMutation = exports.branchMutationLogPath = exports.BranchMutationLog = exports.BranchMutationEvent = exports.BranchReaper = exports.ReapResult = exports.ReapedBranch = exports.WorktreeService = exports.Worktree = exports.MergedBranchesService = exports.MergedBranchesCache = exports.DeletableWorktree = exports.DeletableBranch = exports.MergedBranch = exports.squashRecoverySteps = exports.stampCleanMainSyncStatus = exports.computeMainSyncStatus = exports.finishedLock = exports.inProcessLock = exports.isRefreshInProgress = exports.isLockStale = exports.writeMainSyncLock = exports.readMainSyncLock = exports.writeMainSyncStatus = exports.readMainSyncStatus = exports.mainSyncLockPath = exports.mainSyncStatusPath = exports.DEFAULT_HANG_TIMEOUT_MINUTES = exports.MainSyncStatusService = exports.MainSyncLock = exports.MainSyncStatus = void 0;
3
+ exports.FieldDef = exports.sectionForRule = exports.isHookGuard = exports.HOOK_GUARD_NAMES = exports.DEFAULT_MATCH_RULES = exports.renderMatchRuleMessage = exports.compileMatchRulePatterns = exports.isMatchRuleAllowedPath = exports.findMatchRuleViolations = exports.MatchRuleViolation = exports.MatchRuleConfig = exports.validateChecklistDocs = exports.allRuleNames = exports.validateMatchRulesSection = exports.validateExcludePaths = exports.validateCommandsSection = exports.validateSectionPlacement = exports.validateChecklists = exports.validatePrGateSection = exports.validateWebpiecesConfig = exports.TemplateWriter = exports.writeTemplate = exports.writeTemplateIfMissing = exports.loadTemplate = exports.defaultRulesDir = exports.defaultRules = exports.isPathExcluded = exports.ExcludePaths = exports.DESIGN_METADATA_KEYS = exports.isDocumentDesign = exports.DocumentDesign = exports.RulesConfigDesign = exports.INSTRUCT_AI_DIR = exports.RepoRootFinder = exports.ConfigFile = exports.CONFIG_FILENAME = exports.findConfigFile = exports.ConfigLoader = exports.LoadedConfig = exports.loadAndValidate = exports.toError = exports.runMain = exports.CliArgs = exports.CliArgsCheck = exports.CliUsage = exports.CliExitError = exports.RuleFailError = exports.InformAiError = exports.ResolvedRuleConfig = exports.ResolvedConfig = void 0;
4
+ exports.PrCreationOrPushGuardConfig = exports.BranchCreationGuardConfig = exports.RoleTagConfig = exports.FrameworkTagConfig = exports.InjectAnnotationNotNeededForConcreteClassConfig = exports.NoFunctionOutsideClassConfig = exports.NoProcessExitOutsideMainConfig = exports.NoCustomCssConfig = exports.NoSymbolDiTokensConfig = exports.AngularNoDirectApiInResolverConfig = exports.ThrowCauseRequiredConfig = exports.CatchErrorPatternConfig = exports.NoUnmanagedExceptionsConfig = exports.NoDestructureConfig = exports.PrismaConverterConfig = exports.PrismaValidateDtosConfig = exports.NoImplicitAnyConfig = exports.NoAnyUnknownConfig = exports.NoInlineTypeLiteralsConfig = exports.RequireReturnTypeConfig = exports.MaxFileLinesConfig = exports.MaxMethodLinesConfig = exports.WP_FINISH_UPSERT_PR = exports.WP_START_UPSERT_PR = exports.WP_FINISH_UPDATE = exports.WP_START_UPDATE = exports.SyncFlowGuidance = exports.WebpiecesRulesConfig = exports.MERGE_EXPLANATION_FILE = exports.MERGE_IN_PROGRESS_FILE = exports.PR_REVIEW_DIR = exports.MERGE_INFO_DIR = exports.WEBPIECES_TMP_DIR = exports.hasDisable = exports.RULE_NAMES = exports.WEBPIECES_DISABLE = exports.AbstractRule = exports.ChangedFilesOptions = exports.DiffRange = exports.DiffScope = exports.isNewOrModified = exports.hasChangesInRange = exports.findNewMethodSignaturesInDiff = exports.getChangedLineNumbers = exports.getFileDiff = exports.getChangedFiles = exports.resolveBase = exports.detectBase = exports.getCurrentBranch = exports.shouldSkipRule = void 0;
5
+ exports.extractGateToken = exports.gateTokenMarker = exports.computeGateToken = exports.GateTokenService = exports.CHECKLIST_SEVERITIES = exports.CHECKLIST_WARN = exports.CHECKLIST_BLOCK = exports.toChecklist = exports.ChecklistDefinition = exports.MERGE_MODES = exports.MERGE_MODE_NONE = exports.MERGE_MODE_AUTO = exports.buildPrGateConfig = exports.defaultPrGateConfig = exports.defaultGates = exports.PrGateConfig = exports.GateDefinition = exports.CLIENT_CREATION_SEVERITIES = exports.NoClientCreationOutsideServerOrClientConfig = exports.VALIDATE_TS_MODES = exports.STRUCTURAL_MODES = exports.ON_OFF_MODES = exports.THROW_CAUSE_MODES = exports.DIRECT_API_RESOLVER_MODES = exports.PRISMA_CONVERTER_MODES = exports.PRISMA_DTOS_MODES = exports.PROJECT_MODES = exports.MODIFIED_CODE_MODES = exports.INLINE_TYPE_MODES = exports.RETURN_TYPE_MODES = exports.FILE_LIMIT_MODES = exports.METHOD_LIMIT_MODES = exports.BaseRuleConfig = exports.ValidateEslintSyncConfig = exports.ValidateVersionsLockedConfig = exports.ValidatePackageJsonConfig = exports.ValidateNoArchitectureCyclesConfig = exports.ValidateArchitectureUnchangedConfig = exports.ValidateTsInSrcConfig = exports.NoJsFilesConfig = exports.DiGraphConfig = exports.NxWiringConfig = exports.RuntimeArchitectureConfig = exports.NoFileImportCyclesConfig = exports.MergedBranchBashGuardConfig = exports.ReadStaleGuardConfig = exports.FeatureBranchGuardConfig = exports.RedirectHowToMergeMainConfig = exports.PrMergeGuardConfig = exports.MergeInProgressGuardConfig = void 0;
6
+ exports.BranchMutationLog = exports.BranchMutationEvent = exports.BranchReaper = exports.ReapResult = exports.ReapedBranch = exports.WorktreeService = exports.Worktree = exports.MergedBranchesService = exports.MergedBranchesCache = exports.DeletableWorktree = exports.DeletableBranch = exports.MergedBranch = exports.squashRecoverySteps = exports.stampCleanMainSyncStatus = exports.computeMainSyncStatus = exports.finishedLock = exports.inProcessLock = exports.isRefreshInProgress = exports.isLockStale = exports.writeMainSyncLock = exports.readMainSyncLock = exports.writeMainSyncStatus = exports.readMainSyncStatus = exports.mainSyncLockPath = exports.mainSyncStatusPath = exports.DEFAULT_HANG_TIMEOUT_MINUTES = exports.MainSyncStatusService = exports.MainSyncLock = exports.MainSyncStatus = exports.reviewJsonSchemaHint = exports.reviewJsonPath = exports.prDirFor = exports.loadReviewJson = exports.ReviewJsonService = exports.RequiredChecklist = exports.CK_ACKED = exports.CK_MISSING = exports.CK_FAIL = exports.CK_OVERRIDDEN = exports.CK_PASS = exports.ChecklistVerdict = exports.ChecklistResult = exports.ChecklistAck = exports.ReviewJson = exports.PROVENANCE_SKIPPED = exports.PROVENANCE_MISSING = exports.PROVENANCE_OK = exports.ProvenanceResult = exports.SubagentProvenanceService = exports.verifyGateToken = void 0;
7
+ exports.DEFAULT_MERGE_COMPLETE_COMMAND = exports.DEFAULT_UPSERT_PR_COMMAND = exports.buildCommandsConfig = exports.CommandsConfig = exports.logBranchMutation = exports.branchMutationLogPath = void 0;
7
8
  var types_1 = require("./types");
8
9
  Object.defineProperty(exports, "ResolvedConfig", { enumerable: true, get: function () { return types_1.ResolvedConfig; } });
9
10
  Object.defineProperty(exports, "ResolvedRuleConfig", { enumerable: true, get: function () { return types_1.ResolvedRuleConfig; } });
@@ -53,11 +54,14 @@ Object.defineProperty(exports, "TemplateWriter", { enumerable: true, get: functi
53
54
  var validate_config_1 = require("./validate-config");
54
55
  Object.defineProperty(exports, "validateWebpiecesConfig", { enumerable: true, get: function () { return validate_config_1.validateWebpiecesConfig; } });
55
56
  Object.defineProperty(exports, "validatePrGateSection", { enumerable: true, get: function () { return validate_config_1.validatePrGateSection; } });
57
+ Object.defineProperty(exports, "validateChecklists", { enumerable: true, get: function () { return validate_config_1.validateChecklists; } });
56
58
  Object.defineProperty(exports, "validateSectionPlacement", { enumerable: true, get: function () { return validate_config_1.validateSectionPlacement; } });
57
59
  Object.defineProperty(exports, "validateCommandsSection", { enumerable: true, get: function () { return validate_config_1.validateCommandsSection; } });
58
60
  Object.defineProperty(exports, "validateExcludePaths", { enumerable: true, get: function () { return validate_config_1.validateExcludePaths; } });
59
61
  Object.defineProperty(exports, "validateMatchRulesSection", { enumerable: true, get: function () { return validate_config_1.validateMatchRulesSection; } });
60
62
  Object.defineProperty(exports, "allRuleNames", { enumerable: true, get: function () { return validate_config_1.allRuleNames; } });
63
+ var checklist_docs_validator_1 = require("./checklist-docs-validator");
64
+ Object.defineProperty(exports, "validateChecklistDocs", { enumerable: true, get: function () { return checklist_docs_validator_1.validateChecklistDocs; } });
61
65
  var match_rules_config_1 = require("./match-rules-config");
62
66
  Object.defineProperty(exports, "MatchRuleConfig", { enumerable: true, get: function () { return match_rules_config_1.MatchRuleConfig; } });
63
67
  Object.defineProperty(exports, "MatchRuleViolation", { enumerable: true, get: function () { return match_rules_config_1.MatchRuleViolation; } });
@@ -162,6 +166,9 @@ Object.defineProperty(exports, "THROW_CAUSE_MODES", { enumerable: true, get: fun
162
166
  Object.defineProperty(exports, "ON_OFF_MODES", { enumerable: true, get: function () { return rule_configs_2.ON_OFF_MODES; } });
163
167
  Object.defineProperty(exports, "STRUCTURAL_MODES", { enumerable: true, get: function () { return rule_configs_2.STRUCTURAL_MODES; } });
164
168
  Object.defineProperty(exports, "VALIDATE_TS_MODES", { enumerable: true, get: function () { return rule_configs_2.VALIDATE_TS_MODES; } });
169
+ var no_client_creation_config_1 = require("./no-client-creation-config");
170
+ Object.defineProperty(exports, "NoClientCreationOutsideServerOrClientConfig", { enumerable: true, get: function () { return no_client_creation_config_1.NoClientCreationOutsideServerOrClientConfig; } });
171
+ Object.defineProperty(exports, "CLIENT_CREATION_SEVERITIES", { enumerable: true, get: function () { return no_client_creation_config_1.CLIENT_CREATION_SEVERITIES; } });
165
172
  var pr_gate_config_1 = require("./pr-gate-config");
166
173
  Object.defineProperty(exports, "GateDefinition", { enumerable: true, get: function () { return pr_gate_config_1.GateDefinition; } });
167
174
  Object.defineProperty(exports, "PrGateConfig", { enumerable: true, get: function () { return pr_gate_config_1.PrGateConfig; } });
@@ -177,9 +184,28 @@ Object.defineProperty(exports, "toChecklist", { enumerable: true, get: function
177
184
  Object.defineProperty(exports, "CHECKLIST_BLOCK", { enumerable: true, get: function () { return checklist_config_1.CHECKLIST_BLOCK; } });
178
185
  Object.defineProperty(exports, "CHECKLIST_WARN", { enumerable: true, get: function () { return checklist_config_1.CHECKLIST_WARN; } });
179
186
  Object.defineProperty(exports, "CHECKLIST_SEVERITIES", { enumerable: true, get: function () { return checklist_config_1.CHECKLIST_SEVERITIES; } });
187
+ var gate_token_1 = require("./gate-token");
188
+ Object.defineProperty(exports, "GateTokenService", { enumerable: true, get: function () { return gate_token_1.GateTokenService; } });
189
+ Object.defineProperty(exports, "computeGateToken", { enumerable: true, get: function () { return gate_token_1.computeGateToken; } });
190
+ Object.defineProperty(exports, "gateTokenMarker", { enumerable: true, get: function () { return gate_token_1.gateTokenMarker; } });
191
+ Object.defineProperty(exports, "extractGateToken", { enumerable: true, get: function () { return gate_token_1.extractGateToken; } });
192
+ Object.defineProperty(exports, "verifyGateToken", { enumerable: true, get: function () { return gate_token_1.verifyGateToken; } });
193
+ var subagent_provenance_1 = require("./subagent-provenance");
194
+ Object.defineProperty(exports, "SubagentProvenanceService", { enumerable: true, get: function () { return subagent_provenance_1.SubagentProvenanceService; } });
195
+ Object.defineProperty(exports, "ProvenanceResult", { enumerable: true, get: function () { return subagent_provenance_1.ProvenanceResult; } });
196
+ Object.defineProperty(exports, "PROVENANCE_OK", { enumerable: true, get: function () { return subagent_provenance_1.PROVENANCE_OK; } });
197
+ Object.defineProperty(exports, "PROVENANCE_MISSING", { enumerable: true, get: function () { return subagent_provenance_1.PROVENANCE_MISSING; } });
198
+ Object.defineProperty(exports, "PROVENANCE_SKIPPED", { enumerable: true, get: function () { return subagent_provenance_1.PROVENANCE_SKIPPED; } });
180
199
  var review_json_1 = require("./review-json");
181
200
  Object.defineProperty(exports, "ReviewJson", { enumerable: true, get: function () { return review_json_1.ReviewJson; } });
182
201
  Object.defineProperty(exports, "ChecklistAck", { enumerable: true, get: function () { return review_json_1.ChecklistAck; } });
202
+ Object.defineProperty(exports, "ChecklistResult", { enumerable: true, get: function () { return review_json_1.ChecklistResult; } });
203
+ Object.defineProperty(exports, "ChecklistVerdict", { enumerable: true, get: function () { return review_json_1.ChecklistVerdict; } });
204
+ Object.defineProperty(exports, "CK_PASS", { enumerable: true, get: function () { return review_json_1.CK_PASS; } });
205
+ Object.defineProperty(exports, "CK_OVERRIDDEN", { enumerable: true, get: function () { return review_json_1.CK_OVERRIDDEN; } });
206
+ Object.defineProperty(exports, "CK_FAIL", { enumerable: true, get: function () { return review_json_1.CK_FAIL; } });
207
+ Object.defineProperty(exports, "CK_MISSING", { enumerable: true, get: function () { return review_json_1.CK_MISSING; } });
208
+ Object.defineProperty(exports, "CK_ACKED", { enumerable: true, get: function () { return review_json_1.CK_ACKED; } });
183
209
  Object.defineProperty(exports, "RequiredChecklist", { enumerable: true, get: function () { return review_json_1.RequiredChecklist; } });
184
210
  Object.defineProperty(exports, "ReviewJsonService", { enumerable: true, get: function () { return review_json_1.ReviewJsonService; } });
185
211
  Object.defineProperty(exports, "loadReviewJson", { enumerable: true, get: function () { return review_json_1.loadReviewJson; } });