@webpieces/hook-runtime 0.0.1

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.
Files changed (103) hide show
  1. package/package.json +37 -0
  2. package/src/adapters/agent-adapters.d.ts +13 -0
  3. package/src/adapters/agent-adapters.js +23 -0
  4. package/src/adapters/agent-adapters.js.map +1 -0
  5. package/src/adapters/agent-payload.d.ts +48 -0
  6. package/src/adapters/agent-payload.js +30 -0
  7. package/src/adapters/agent-payload.js.map +1 -0
  8. package/src/adapters/claude-code-adapter.d.ts +26 -0
  9. package/src/adapters/claude-code-adapter.js +69 -0
  10. package/src/adapters/claude-code-adapter.js.map +1 -0
  11. package/src/adapters/codex-adapter.d.ts +19 -0
  12. package/src/adapters/codex-adapter.js +48 -0
  13. package/src/adapters/codex-adapter.js.map +1 -0
  14. package/src/adapters/detect-ai.d.ts +70 -0
  15. package/src/adapters/detect-ai.js +82 -0
  16. package/src/adapters/detect-ai.js.map +1 -0
  17. package/src/core/apply-patch-parse.d.ts +36 -0
  18. package/src/core/apply-patch-parse.js +155 -0
  19. package/src/core/apply-patch-parse.js.map +1 -0
  20. package/src/core/build-context.d.ts +11 -0
  21. package/src/core/build-context.js +69 -0
  22. package/src/core/build-context.js.map +1 -0
  23. package/src/core/command-scan.d.ts +122 -0
  24. package/src/core/command-scan.js +282 -0
  25. package/src/core/command-scan.js.map +1 -0
  26. package/src/core/custom-rule-adapter.d.ts +23 -0
  27. package/src/core/custom-rule-adapter.js +50 -0
  28. package/src/core/custom-rule-adapter.js.map +1 -0
  29. package/src/core/delete-scoped-rules.d.ts +9 -0
  30. package/src/core/delete-scoped-rules.js +31 -0
  31. package/src/core/delete-scoped-rules.js.map +1 -0
  32. package/src/core/disable-directives.d.ts +8 -0
  33. package/src/core/disable-directives.js +86 -0
  34. package/src/core/disable-directives.js.map +1 -0
  35. package/src/core/effective-tree.d.ts +197 -0
  36. package/src/core/effective-tree.js +269 -0
  37. package/src/core/effective-tree.js.map +1 -0
  38. package/src/core/excluded-paths.d.ts +23 -0
  39. package/src/core/excluded-paths.js +54 -0
  40. package/src/core/excluded-paths.js.map +1 -0
  41. package/src/core/file-evaluation.d.ts +11 -0
  42. package/src/core/file-evaluation.js +45 -0
  43. package/src/core/file-evaluation.js.map +1 -0
  44. package/src/core/fix-hint.d.ts +40 -0
  45. package/src/core/fix-hint.js +53 -0
  46. package/src/core/fix-hint.js.map +1 -0
  47. package/src/core/glob.d.ts +1 -0
  48. package/src/core/glob.js +42 -0
  49. package/src/core/glob.js.map +1 -0
  50. package/src/core/report.d.ts +21 -0
  51. package/src/core/report.js +74 -0
  52. package/src/core/report.js.map +1 -0
  53. package/src/core/root-manifest.d.ts +1 -0
  54. package/src/core/root-manifest.js +21 -0
  55. package/src/core/root-manifest.js.map +1 -0
  56. package/src/core/rule-base.d.ts +40 -0
  57. package/src/core/rule-base.js +37 -0
  58. package/src/core/rule-base.js.map +1 -0
  59. package/src/core/rule-evaluation.d.ts +18 -0
  60. package/src/core/rule-evaluation.js +179 -0
  61. package/src/core/rule-evaluation.js.map +1 -0
  62. package/src/core/rules/shell-segment-scan.d.ts +64 -0
  63. package/src/core/rules/shell-segment-scan.js +88 -0
  64. package/src/core/rules/shell-segment-scan.js.map +1 -0
  65. package/src/core/shell-read-parity.d.ts +34 -0
  66. package/src/core/shell-read-parity.js +157 -0
  67. package/src/core/shell-read-parity.js.map +1 -0
  68. package/src/core/strip-ts-noise.d.ts +1 -0
  69. package/src/core/strip-ts-noise.js +191 -0
  70. package/src/core/strip-ts-noise.js.map +1 -0
  71. package/src/core/target-tree.d.ts +84 -0
  72. package/src/core/target-tree.js +148 -0
  73. package/src/core/target-tree.js.map +1 -0
  74. package/src/core/types.d.ts +149 -0
  75. package/src/core/types.js +190 -0
  76. package/src/core/types.js.map +1 -0
  77. package/src/harness-vocabulary.d.ts +2 -0
  78. package/src/harness-vocabulary.js +10 -0
  79. package/src/harness-vocabulary.js.map +1 -0
  80. package/src/hook-app.d.ts +15 -0
  81. package/src/hook-app.js +58 -0
  82. package/src/hook-app.js.map +1 -0
  83. package/src/hook-evaluator.d.ts +5 -0
  84. package/src/hook-evaluator.js +13 -0
  85. package/src/hook-evaluator.js.map +1 -0
  86. package/src/hook-ports.d.ts +9 -0
  87. package/src/hook-ports.js +40 -0
  88. package/src/hook-ports.js.map +1 -0
  89. package/src/index.d.ts +31 -0
  90. package/src/index.js +59 -0
  91. package/src/index.js.map +1 -0
  92. package/src/outcome.d.ts +14 -0
  93. package/src/outcome.js +20 -0
  94. package/src/outcome.js.map +1 -0
  95. package/src/protocol.d.ts +40 -0
  96. package/src/protocol.js +55 -0
  97. package/src/protocol.js.map +1 -0
  98. package/src/response.d.ts +2 -0
  99. package/src/response.js +21 -0
  100. package/src/response.js.map +1 -0
  101. package/src/to-error.d.ts +1 -0
  102. package/src/to-error.js +9 -0
  103. package/src/to-error.js.map +1 -0
@@ -0,0 +1,11 @@
1
+ import { LoadedConfig } from '@webpieces/rules-config';
2
+ import { ToolKind, NormalizedToolInput } from '../protocol';
3
+ import { Rule, BlockedResult } from './types';
4
+ export declare class HookRuleSet {
5
+ readonly rules: readonly Rule[];
6
+ readonly configuredRules: readonly Rule[];
7
+ constructor(rules: readonly Rule[], configuredRules: readonly Rule[]);
8
+ }
9
+ export declare class HookFileEvaluation {
10
+ evaluate(toolKind: ToolKind, input: NormalizedToolInput, loaded: LoadedConfig, contributions: HookRuleSet): BlockedResult | null;
11
+ }
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HookFileEvaluation = exports.HookRuleSet = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const path = tslib_1.__importStar(require("path"));
6
+ const rules_config_1 = require("@webpieces/rules-config");
7
+ const types_1 = require("./types");
8
+ const target_tree_1 = require("./target-tree");
9
+ const delete_scoped_rules_1 = require("./delete-scoped-rules");
10
+ const excluded_paths_1 = require("./excluded-paths");
11
+ const build_context_1 = require("./build-context");
12
+ const rule_evaluation_1 = require("./rule-evaluation");
13
+ const report_1 = require("./report");
14
+ const root_manifest_1 = require("./root-manifest");
15
+ class HookRuleSet {
16
+ rules;
17
+ configuredRules;
18
+ constructor(rules, configuredRules) {
19
+ this.rules = rules;
20
+ this.configuredRules = configuredRules;
21
+ }
22
+ }
23
+ exports.HookRuleSet = HookRuleSet;
24
+ class HookFileEvaluation {
25
+ evaluate(toolKind, input, loaded, contributions) {
26
+ if (loaded.configPath === null)
27
+ return null;
28
+ if (path.resolve(input.filePath) === path.resolve(loaded.configPath)
29
+ || (0, root_manifest_1.isRootManifest)(input.filePath) || new rules_config_1.HomeConfigService().isHomeConfigPath(input.filePath))
30
+ return null;
31
+ const root = path.dirname(loaded.configPath);
32
+ const governed = new target_tree_1.TargetTreeResolver().governedPath(input.filePath, root);
33
+ const rules = new delete_scoped_rules_1.DeleteScopedRules().narrow(toolKind, (0, excluded_paths_1.filterByExcludedPaths)(contributions.rules, governed, loaded.excludePaths));
34
+ if (rules.length === 0)
35
+ return null;
36
+ const sync = (0, rule_evaluation_1.checkConfigSync)(rules.filter((rule) => contributions.configuredRules.includes(rule)), loaded.rulesConfig, loaded.ruleRegistry);
37
+ if (sync)
38
+ return sync;
39
+ const contexts = (0, build_context_1.buildContexts)(toolKind, input, root, governed);
40
+ const groups = [...(0, rule_evaluation_1.runEditRules)(rules, contexts.editContexts), ...(0, rule_evaluation_1.runFileRules)(rules, contexts.fileContext)];
41
+ return groups.length === 0 ? null : new types_1.BlockedResult((0, report_1.formatReport)(governed.relativePath, groups));
42
+ }
43
+ }
44
+ exports.HookFileEvaluation = HookFileEvaluation;
45
+ //# sourceMappingURL=file-evaluation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-evaluation.js","sourceRoot":"","sources":["../../../../../../packages/tooling/hook-runtime/src/core/file-evaluation.ts"],"names":[],"mappings":";;;;AAAA,mDAA6B;AAC7B,0DAA0E;AAE1E,mCAA8C;AAE9C,+CAAmD;AACnD,+DAA0D;AAC1D,qDAAyD;AACzD,mDAAgD;AAChD,uDAAgF;AAChF,qCAAwC;AACxC,mDAAiD;AAEjD,MAAa,WAAW;IACC;IAAiC;IAAtD,YAAqB,KAAsB,EAAW,eAAgC;QAAjE,UAAK,GAAL,KAAK,CAAiB;QAAW,oBAAe,GAAf,eAAe,CAAiB;IAAG,CAAC;CAC7F;AAFD,kCAEC;AAED,MAAa,kBAAkB;IAC3B,QAAQ,CAAC,QAAkB,EAAE,KAA0B,EAAE,MAAoB,EAAE,aAA0B;QACrG,IAAI,MAAM,CAAC,UAAU,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;QAC5C,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC;eAC7D,IAAA,8BAAc,EAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,IAAI,gCAAiB,EAAE,CAAC,gBAAgB,CAAC,KAAK,CAAC,QAAQ,CAAC;YAAE,OAAO,IAAI,CAAC;QAC/G,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QAC7C,MAAM,QAAQ,GAAG,IAAI,gCAAkB,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAC7E,MAAM,KAAK,GAAG,IAAI,uCAAiB,EAAE,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAA,sCAAqB,EAAC,aAAa,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;QAClI,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QACpC,MAAM,IAAI,GAAG,IAAA,iCAAe,EAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAU,EAAW,EAAE,CAAC,aAAa,CAAC,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,YAAY,CAAC,CAAC;QAC3J,IAAI,IAAI;YAAE,OAAO,IAAI,CAAC;QACtB,MAAM,QAAQ,GAAG,IAAA,6BAAa,EAAC,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;QAChE,MAAM,MAAM,GAAG,CAAC,GAAG,IAAA,8BAAY,EAAC,KAAK,EAAE,QAAQ,CAAC,YAAY,CAAC,EAAE,GAAG,IAAA,8BAAY,EAAC,KAAK,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC;QAC7G,OAAO,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,qBAAa,CAAC,IAAA,qBAAY,EAAC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC;IACvG,CAAC;CACJ;AAfD,gDAeC","sourcesContent":["import * as path from 'path';\nimport { LoadedConfig, HomeConfigService } from '@webpieces/rules-config';\nimport { ToolKind, NormalizedToolInput } from '../protocol';\nimport { Rule, BlockedResult } from './types';\n\nimport { TargetTreeResolver } from './target-tree';\nimport { DeleteScopedRules } from './delete-scoped-rules';\nimport { filterByExcludedPaths } from './excluded-paths';\nimport { buildContexts } from './build-context';\nimport { checkConfigSync, runEditRules, runFileRules } from './rule-evaluation';\nimport { formatReport } from './report';\nimport { isRootManifest } from './root-manifest';\n\nexport class HookRuleSet {\n constructor(readonly rules: readonly Rule[], readonly configuredRules: readonly Rule[]) {}\n}\n\nexport class HookFileEvaluation {\n evaluate(toolKind: ToolKind, input: NormalizedToolInput, loaded: LoadedConfig, contributions: HookRuleSet): BlockedResult | null {\n if (loaded.configPath === null) return null;\n if (path.resolve(input.filePath) === path.resolve(loaded.configPath)\n || isRootManifest(input.filePath) || new HomeConfigService().isHomeConfigPath(input.filePath)) return null;\n const root = path.dirname(loaded.configPath);\n const governed = new TargetTreeResolver().governedPath(input.filePath, root);\n const rules = new DeleteScopedRules().narrow(toolKind, filterByExcludedPaths(contributions.rules, governed, loaded.excludePaths));\n if (rules.length === 0) return null;\n const sync = checkConfigSync(rules.filter((rule: Rule): boolean => contributions.configuredRules.includes(rule)), loaded.rulesConfig, loaded.ruleRegistry);\n if (sync) return sync;\n const contexts = buildContexts(toolKind, input, root, governed);\n const groups = [...runEditRules(rules, contexts.editContexts), ...runFileRules(rules, contexts.fileContext)];\n return groups.length === 0 ? null : new BlockedResult(formatReport(governed.relativePath, groups));\n }\n}\n"]}
@@ -0,0 +1,40 @@
1
+ import { Option } from '@webpieces/rules-config';
2
+ /**
3
+ * Framework-owned `// webpieces-disable` escape hatch for a rule, gated by the team's
4
+ * `disableAllowed` config (default true). `comment` is the exact suppress syntax to show
5
+ * (usually `// webpieces-disable <rule> -- <reason>`; max-file-lines uses the eslint form).
6
+ * When `allowed` is false the framework prints a "must be followed" line instead of the escape.
7
+ */
8
+ export declare class DisableEscape {
9
+ readonly allowed: boolean;
10
+ readonly comment: string;
11
+ constructor(allowed: boolean, comment: string);
12
+ }
13
+ /**
14
+ * Structured fix guidance shown under a violation in a blocked-write / blocked-bash report.
15
+ *
16
+ * A rule authors its user-facing text once here: a required `violation` (the "what's wrong"
17
+ * line — the rule-level default for the `→` line; a dynamic per-occurrence `Violation.message`
18
+ * overrides it), a `mainMessage` (fix prose, or a lead-in to the options), an optional list of
19
+ * genuinely distinct `fixOptions`, and — for the disable-able code-style rules — a framework-
20
+ * owned `escape`.
21
+ *
22
+ * The framework (report.ts / `formatFixOptions`) — not the rule author — owns the "Fix Option N:"
23
+ * numbering, the "(preferred)" tag, and the escape/`disableAllowed` rendering. So a multi-line
24
+ * message can never be mis-split into fake options, and authors never hand-write those labels.
25
+ *
26
+ * `Option` is NOT defined here: it lives in `@webpieces/rules-config` (`fix-option.ts`) because
27
+ * `RuleFailError` — thrown by BOTH engines — carries the same class. One cure shape, one definition,
28
+ * one import path. Import it from `@webpieces/rules-config`, never from this module.
29
+ */
30
+ export declare class FixHint {
31
+ /** Required: the "what's wrong" line (rule-level default for the `→` line). */
32
+ readonly violation: string;
33
+ /** Required (may be ''): fix prose, or a lead-in to the options. Multi-line ok. */
34
+ readonly mainMessage: string;
35
+ /** Real fixes only — NEVER the disable escape (that is `escape`). */
36
+ readonly fixOptions: readonly Option[];
37
+ /** Present only for disable-able rules; absent for guards. */
38
+ readonly escape?: DisableEscape;
39
+ constructor(violation: string, mainMessage: string, fixOptions?: readonly Option[], escape?: DisableEscape);
40
+ }
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FixHint = exports.DisableEscape = void 0;
4
+ /**
5
+ * Framework-owned `// webpieces-disable` escape hatch for a rule, gated by the team's
6
+ * `disableAllowed` config (default true). `comment` is the exact suppress syntax to show
7
+ * (usually `// webpieces-disable <rule> -- <reason>`; max-file-lines uses the eslint form).
8
+ * When `allowed` is false the framework prints a "must be followed" line instead of the escape.
9
+ */
10
+ class DisableEscape {
11
+ allowed;
12
+ comment;
13
+ constructor(allowed, comment) {
14
+ this.allowed = allowed;
15
+ this.comment = comment;
16
+ }
17
+ }
18
+ exports.DisableEscape = DisableEscape;
19
+ /**
20
+ * Structured fix guidance shown under a violation in a blocked-write / blocked-bash report.
21
+ *
22
+ * A rule authors its user-facing text once here: a required `violation` (the "what's wrong"
23
+ * line — the rule-level default for the `→` line; a dynamic per-occurrence `Violation.message`
24
+ * overrides it), a `mainMessage` (fix prose, or a lead-in to the options), an optional list of
25
+ * genuinely distinct `fixOptions`, and — for the disable-able code-style rules — a framework-
26
+ * owned `escape`.
27
+ *
28
+ * The framework (report.ts / `formatFixOptions`) — not the rule author — owns the "Fix Option N:"
29
+ * numbering, the "(preferred)" tag, and the escape/`disableAllowed` rendering. So a multi-line
30
+ * message can never be mis-split into fake options, and authors never hand-write those labels.
31
+ *
32
+ * `Option` is NOT defined here: it lives in `@webpieces/rules-config` (`fix-option.ts`) because
33
+ * `RuleFailError` — thrown by BOTH engines — carries the same class. One cure shape, one definition,
34
+ * one import path. Import it from `@webpieces/rules-config`, never from this module.
35
+ */
36
+ class FixHint {
37
+ /** Required: the "what's wrong" line (rule-level default for the `→` line). */
38
+ violation;
39
+ /** Required (may be ''): fix prose, or a lead-in to the options. Multi-line ok. */
40
+ mainMessage;
41
+ /** Real fixes only — NEVER the disable escape (that is `escape`). */
42
+ fixOptions;
43
+ /** Present only for disable-able rules; absent for guards. */
44
+ escape;
45
+ constructor(violation, mainMessage, fixOptions = [], escape) {
46
+ this.violation = violation;
47
+ this.mainMessage = mainMessage;
48
+ this.fixOptions = fixOptions;
49
+ this.escape = escape;
50
+ }
51
+ }
52
+ exports.FixHint = FixHint;
53
+ //# sourceMappingURL=fix-hint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fix-hint.js","sourceRoot":"","sources":["../../../../../../packages/tooling/hook-runtime/src/core/fix-hint.ts"],"names":[],"mappings":";;;AAEA;;;;;GAKG;AACH,MAAa,aAAa;IACb,OAAO,CAAU;IACjB,OAAO,CAAS;IAEzB,YAAY,OAAgB,EAAE,OAAe;QACzC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IAC3B,CAAC;CACJ;AARD,sCAQC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAa,OAAO;IAChB,+EAA+E;IACtE,SAAS,CAAS;IAC3B,mFAAmF;IAC1E,WAAW,CAAS;IAC7B,qEAAqE;IAC5D,UAAU,CAAoB;IACvC,8DAA8D;IACrD,MAAM,CAAiB;IAEhC,YACI,SAAiB,EACjB,WAAmB,EACnB,aAAgC,EAAE,EAClC,MAAsB;QAEtB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/B,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACzB,CAAC;CACJ;AArBD,0BAqBC","sourcesContent":["import { Option } from '@webpieces/rules-config';\n\n/**\n * Framework-owned `// webpieces-disable` escape hatch for a rule, gated by the team's\n * `disableAllowed` config (default true). `comment` is the exact suppress syntax to show\n * (usually `// webpieces-disable <rule> -- <reason>`; max-file-lines uses the eslint form).\n * When `allowed` is false the framework prints a \"must be followed\" line instead of the escape.\n */\nexport class DisableEscape {\n readonly allowed: boolean;\n readonly comment: string;\n\n constructor(allowed: boolean, comment: string) {\n this.allowed = allowed;\n this.comment = comment;\n }\n}\n\n/**\n * Structured fix guidance shown under a violation in a blocked-write / blocked-bash report.\n *\n * A rule authors its user-facing text once here: a required `violation` (the \"what's wrong\"\n * line — the rule-level default for the `→` line; a dynamic per-occurrence `Violation.message`\n * overrides it), a `mainMessage` (fix prose, or a lead-in to the options), an optional list of\n * genuinely distinct `fixOptions`, and — for the disable-able code-style rules — a framework-\n * owned `escape`.\n *\n * The framework (report.ts / `formatFixOptions`) — not the rule author — owns the \"Fix Option N:\"\n * numbering, the \"(preferred)\" tag, and the escape/`disableAllowed` rendering. So a multi-line\n * message can never be mis-split into fake options, and authors never hand-write those labels.\n *\n * `Option` is NOT defined here: it lives in `@webpieces/rules-config` (`fix-option.ts`) because\n * `RuleFailError` — thrown by BOTH engines — carries the same class. One cure shape, one definition,\n * one import path. Import it from `@webpieces/rules-config`, never from this module.\n */\nexport class FixHint {\n /** Required: the \"what's wrong\" line (rule-level default for the `→` line). */\n readonly violation: string;\n /** Required (may be ''): fix prose, or a lead-in to the options. Multi-line ok. */\n readonly mainMessage: string;\n /** Real fixes only — NEVER the disable escape (that is `escape`). */\n readonly fixOptions: readonly Option[];\n /** Present only for disable-able rules; absent for guards. */\n readonly escape?: DisableEscape;\n\n constructor(\n violation: string,\n mainMessage: string,\n fixOptions: readonly Option[] = [],\n escape?: DisableEscape,\n ) {\n this.violation = violation;\n this.mainMessage = mainMessage;\n this.fixOptions = fixOptions;\n this.escape = escape;\n }\n}\n"]}
@@ -0,0 +1 @@
1
+ export declare function globMatches(pattern: string, filePath: string): boolean;
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.globMatches = globMatches;
4
+ // webpieces-disable no-function-outside-class -- existing stateless module helper moved intact with its callers; ownership extraction preserves its functional API
5
+ function globMatches(pattern, filePath) {
6
+ const regex = globToRegex(pattern);
7
+ return regex.test(filePath);
8
+ }
9
+ // webpieces-disable no-function-outside-class -- existing stateless module helper moved intact with its callers; ownership extraction preserves its functional API
10
+ function globToRegex(pattern) {
11
+ let re = '';
12
+ let i = 0;
13
+ while (i < pattern.length) {
14
+ const ch = pattern[i];
15
+ if (ch === '*') {
16
+ if (pattern[i + 1] === '*') {
17
+ re += '.*';
18
+ i += 2;
19
+ if (pattern[i] === '/')
20
+ i += 1;
21
+ continue;
22
+ }
23
+ re += '[^/]*';
24
+ i += 1;
25
+ continue;
26
+ }
27
+ if (ch === '?') {
28
+ re += '[^/]';
29
+ i += 1;
30
+ continue;
31
+ }
32
+ if ('.+^$(){}|[]\\'.includes(ch)) {
33
+ re += '\\' + ch;
34
+ i += 1;
35
+ continue;
36
+ }
37
+ re += ch;
38
+ i += 1;
39
+ }
40
+ return new RegExp('^' + re + '$');
41
+ }
42
+ //# sourceMappingURL=glob.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"glob.js","sourceRoot":"","sources":["../../../../../../packages/tooling/hook-runtime/src/core/glob.ts"],"names":[],"mappings":";;AACA,kCAGC;AAJD,mKAAmK;AACnK,SAAgB,WAAW,CAAC,OAAe,EAAE,QAAgB;IACzD,MAAM,KAAK,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IACnC,OAAO,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AAChC,CAAC;AAED,mKAAmK;AACnK,SAAS,WAAW,CAAC,OAAe;IAChC,IAAI,EAAE,GAAG,EAAE,CAAC;IACZ,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;QACxB,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QACtB,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YACb,IAAI,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;gBACzB,EAAE,IAAI,IAAI,CAAC;gBACX,CAAC,IAAI,CAAC,CAAC;gBACP,IAAI,OAAO,CAAC,CAAC,CAAC,KAAK,GAAG;oBAAE,CAAC,IAAI,CAAC,CAAC;gBAC/B,SAAS;YACb,CAAC;YACD,EAAE,IAAI,OAAO,CAAC;YACd,CAAC,IAAI,CAAC,CAAC;YACP,SAAS;QACb,CAAC;QACD,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YACb,EAAE,IAAI,MAAM,CAAC;YACb,CAAC,IAAI,CAAC,CAAC;YACP,SAAS;QACb,CAAC;QACD,IAAI,eAAe,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;YAC/B,EAAE,IAAI,IAAI,GAAG,EAAE,CAAC;YAChB,CAAC,IAAI,CAAC,CAAC;YACP,SAAS;QACb,CAAC;QACD,EAAE,IAAI,EAAE,CAAC;QACT,CAAC,IAAI,CAAC,CAAC;IACX,CAAC;IACD,OAAO,IAAI,MAAM,CAAC,GAAG,GAAG,EAAE,GAAG,GAAG,CAAC,CAAC;AACtC,CAAC","sourcesContent":["// webpieces-disable no-function-outside-class -- existing stateless module helper moved intact with its callers; ownership extraction preserves its functional API\nexport function globMatches(pattern: string, filePath: string): boolean {\n const regex = globToRegex(pattern);\n return regex.test(filePath);\n}\n\n// webpieces-disable no-function-outside-class -- existing stateless module helper moved intact with its callers; ownership extraction preserves its functional API\nfunction globToRegex(pattern: string): RegExp {\n let re = '';\n let i = 0;\n while (i < pattern.length) {\n const ch = pattern[i];\n if (ch === '*') {\n if (pattern[i + 1] === '*') {\n re += '.*';\n i += 2;\n if (pattern[i] === '/') i += 1;\n continue;\n }\n re += '[^/]*';\n i += 1;\n continue;\n }\n if (ch === '?') {\n re += '[^/]';\n i += 1;\n continue;\n }\n if ('.+^$(){}|[]\\\\'.includes(ch)) {\n re += '\\\\' + ch;\n i += 1;\n continue;\n }\n re += ch;\n i += 1;\n }\n return new RegExp('^' + re + '$');\n}\n"]}
@@ -0,0 +1,21 @@
1
+ import type { RuleGroup } from './types';
2
+ /**
3
+ * How the report names the tool it just blocked. Data-only, so a class (per CLAUDE.md).
4
+ *
5
+ * WHY it is a parameter: the header and footer used to be hard-coded to "write". A blocked READ
6
+ * therefore printed "\u274c webpieces ai-hooks blocked this write:" and closed with "This is a pre-write
7
+ * check. Fix and retry the Write/Edit." \u2014 observed live, and actively misleading, because the agent is
8
+ * told to fix and retry the one tool it did not use. A blocked Bash command printed the same thing
9
+ * against the path `<bash>`.
10
+ */
11
+ export declare class ReportSubject {
12
+ /** Fills "blocked this ___". */
13
+ noun: string;
14
+ /** The closing line: what kind of check this was and which tool to retry. */
15
+ footer: string;
16
+ constructor(noun: string, footer: string);
17
+ }
18
+ export declare const WRITE_SUBJECT: ReportSubject;
19
+ export declare const READ_SUBJECT: ReportSubject;
20
+ export declare const BASH_SUBJECT: ReportSubject;
21
+ export declare function formatReport(relativePath: string, ruleGroups: readonly RuleGroup[], subject?: ReportSubject): string;
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BASH_SUBJECT = exports.READ_SUBJECT = exports.WRITE_SUBJECT = exports.ReportSubject = void 0;
4
+ exports.formatReport = formatReport;
5
+ const rules_config_1 = require("@webpieces/rules-config");
6
+ /**
7
+ * How the report names the tool it just blocked. Data-only, so a class (per CLAUDE.md).
8
+ *
9
+ * WHY it is a parameter: the header and footer used to be hard-coded to "write". A blocked READ
10
+ * therefore printed "\u274c webpieces ai-hooks blocked this write:" and closed with "This is a pre-write
11
+ * check. Fix and retry the Write/Edit." \u2014 observed live, and actively misleading, because the agent is
12
+ * told to fix and retry the one tool it did not use. A blocked Bash command printed the same thing
13
+ * against the path `<bash>`.
14
+ */
15
+ class ReportSubject {
16
+ /** Fills "blocked this ___". */
17
+ noun;
18
+ /** The closing line: what kind of check this was and which tool to retry. */
19
+ footer;
20
+ constructor(noun, footer) {
21
+ this.noun = noun;
22
+ this.footer = footer;
23
+ }
24
+ }
25
+ exports.ReportSubject = ReportSubject;
26
+ exports.WRITE_SUBJECT = new ReportSubject('write', 'This is a pre-write check. Fix and retry the Write/Edit.');
27
+ exports.READ_SUBJECT = new ReportSubject('read', 'This is a pre-read check. Follow the fix above, then retry the Read.');
28
+ exports.BASH_SUBJECT = new ReportSubject('command', 'This is a pre-run check. Follow the fix above, then retry the command.');
29
+ // webpieces-disable no-function-outside-class -- pre-existing shape: this whole module is the report formatter as module-scope functions, and a lone class here would break it
30
+ function formatReport(relativePath, ruleGroups, subject = exports.WRITE_SUBJECT) {
31
+ const lines = [];
32
+ lines.push(`\u274c webpieces ai-hooks blocked this ${subject.noun}: ${relativePath}`);
33
+ lines.push('');
34
+ for (const group of ruleGroups) {
35
+ const count = group.violations.length;
36
+ const label = count === 1 ? '1 violation' : `${count} violations`;
37
+ lines.push(`[${group.ruleName}] (${label})`);
38
+ const fh = group.fixHint;
39
+ for (const v of group.violations) {
40
+ const editPrefix = formatEditPrefix(v);
41
+ lines.push(` ${editPrefix}L${String(v.line)}: ${v.snippet}`);
42
+ // Per-occurrence override (dynamic rules), else the rule-level FixHint.violation.
43
+ lines.push(` \u2192 ${v.message ?? fh.violation}`);
44
+ }
45
+ // mainMessage may be '' (guidance already on the violation line) \u2014 skip when empty.
46
+ if (fh.mainMessage)
47
+ for (const l of fh.mainMessage.split('\n'))
48
+ lines.push(` ${l}`);
49
+ // "Fix Option N:" numbering + "(preferred)" are framework-owned so a multi-line message
50
+ // can never become fake options and authors never hand-write those labels. ONE renderer
51
+ // (`formatFixOptions`, in rules-config) serves this report, the thrown-rule path in
52
+ // runner.ts and the build-time console in code-rules.
53
+ for (const l of (0, rules_config_1.formatFixOptions)(fh.fixOptions))
54
+ lines.push(l);
55
+ // Framework-owned disable escape (only the 9 disable-able code-style rules set this).
56
+ if (fh.escape) {
57
+ lines.push(fh.escape.allowed
58
+ ? ` Escape (if truly needed): ${fh.escape.comment}`
59
+ : ' \u{1F512} The team disabled escaping via webpieces-disable for this rule (disableAllowed:false) — it must be followed.');
60
+ }
61
+ lines.push('');
62
+ }
63
+ lines.push(subject.footer);
64
+ lines.push('');
65
+ return lines.join('\n');
66
+ }
67
+ // webpieces-disable no-function-outside-class -- existing stateless module helper moved intact with its callers; ownership extraction preserves its functional API
68
+ function formatEditPrefix(v) {
69
+ if (v.editIndex !== undefined && v.editCount !== undefined && v.editCount > 1) {
70
+ return `edit ${String(v.editIndex + 1)}/${String(v.editCount)} `;
71
+ }
72
+ return '';
73
+ }
74
+ //# sourceMappingURL=report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../../../../../../packages/tooling/hook-runtime/src/core/report.ts"],"names":[],"mappings":"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","sourcesContent":["import type { RuleGroup, Violation } from './types';\nimport { formatFixOptions } from '@webpieces/rules-config';\n\n/**\n * How the report names the tool it just blocked. Data-only, so a class (per CLAUDE.md).\n *\n * WHY it is a parameter: the header and footer used to be hard-coded to \"write\". A blocked READ\n * therefore printed \"\\u274c webpieces ai-hooks blocked this write:\" and closed with \"This is a pre-write\n * check. Fix and retry the Write/Edit.\" \\u2014 observed live, and actively misleading, because the agent is\n * told to fix and retry the one tool it did not use. A blocked Bash command printed the same thing\n * against the path `<bash>`.\n */\nexport class ReportSubject {\n /** Fills \"blocked this ___\". */\n noun: string;\n /** The closing line: what kind of check this was and which tool to retry. */\n footer: string;\n\n constructor(noun: string, footer: string) {\n this.noun = noun;\n this.footer = footer;\n }\n}\n\nexport const WRITE_SUBJECT = new ReportSubject(\n 'write', 'This is a pre-write check. Fix and retry the Write/Edit.');\nexport const READ_SUBJECT = new ReportSubject(\n 'read', 'This is a pre-read check. Follow the fix above, then retry the Read.');\nexport const BASH_SUBJECT = new ReportSubject(\n 'command', 'This is a pre-run check. Follow the fix above, then retry the command.');\n\n// webpieces-disable no-function-outside-class -- pre-existing shape: this whole module is the report formatter as module-scope functions, and a lone class here would break it\nexport function formatReport(\n relativePath: string,\n ruleGroups: readonly RuleGroup[],\n subject: ReportSubject = WRITE_SUBJECT,\n): string {\n const lines: string[] = [];\n lines.push(`\\u274c webpieces ai-hooks blocked this ${subject.noun}: ${relativePath}`);\n lines.push('');\n\n for (const group of ruleGroups) {\n const count = group.violations.length;\n const label = count === 1 ? '1 violation' : `${count} violations`;\n lines.push(`[${group.ruleName}] (${label})`);\n const fh = group.fixHint;\n for (const v of group.violations) {\n const editPrefix = formatEditPrefix(v);\n lines.push(` ${editPrefix}L${String(v.line)}: ${v.snippet}`);\n // Per-occurrence override (dynamic rules), else the rule-level FixHint.violation.\n lines.push(` \\u2192 ${v.message ?? fh.violation}`);\n }\n // mainMessage may be '' (guidance already on the violation line) \\u2014 skip when empty.\n if (fh.mainMessage) for (const l of fh.mainMessage.split('\\n')) lines.push(` ${l}`);\n // \"Fix Option N:\" numbering + \"(preferred)\" are framework-owned so a multi-line message\n // can never become fake options and authors never hand-write those labels. ONE renderer\n // (`formatFixOptions`, in rules-config) serves this report, the thrown-rule path in\n // runner.ts and the build-time console in code-rules.\n for (const l of formatFixOptions(fh.fixOptions)) lines.push(l);\n // Framework-owned disable escape (only the 9 disable-able code-style rules set this).\n if (fh.escape) {\n lines.push(fh.escape.allowed\n ? ` Escape (if truly needed): ${fh.escape.comment}`\n : ' \\u{1F512} The team disabled escaping via webpieces-disable for this rule (disableAllowed:false) — it must be followed.');\n }\n lines.push('');\n }\n\n lines.push(subject.footer);\n lines.push('');\n return lines.join('\\n');\n}\n\n// webpieces-disable no-function-outside-class -- existing stateless module helper moved intact with its callers; ownership extraction preserves its functional API\nfunction formatEditPrefix(v: Violation): string {\n if (v.editIndex !== undefined && v.editCount !== undefined && v.editCount > 1) {\n return `edit ${String(v.editIndex + 1)}/${String(v.editCount)} `;\n }\n return '';\n}\n"]}
@@ -0,0 +1 @@
1
+ export declare function isRootManifest(filePath: string): boolean;
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isRootManifest = isRootManifest;
4
+ const tslib_1 = require("tslib");
5
+ const fs = tslib_1.__importStar(require("fs"));
6
+ const path = tslib_1.__importStar(require("path"));
7
+ const rules_config_1 = require("@webpieces/rules-config");
8
+ // webpieces-disable no-function-outside-class -- existing stateless filesystem predicate shared by both hook products
9
+ function isRootManifest(filePath) {
10
+ if (!rules_config_1.MANIFEST_FILENAMES.has(path.basename(filePath)))
11
+ return false;
12
+ // eslint-disable-next-line @webpieces/no-unmanaged-exceptions
13
+ try {
14
+ return fs.existsSync(path.join(path.dirname(filePath), rules_config_1.CONFIG_FILENAME));
15
+ }
16
+ catch (err) {
17
+ //const error = toError(err); best-effort on a blocking path: unreadable is NOT a root manifest
18
+ return false;
19
+ }
20
+ }
21
+ //# sourceMappingURL=root-manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"root-manifest.js","sourceRoot":"","sources":["../../../../../../packages/tooling/hook-runtime/src/core/root-manifest.ts"],"names":[],"mappings":";;AAKA,wCASC;;AAdD,+CAAyB;AACzB,mDAA6B;AAC7B,0DAA8E;AAE9E,sHAAsH;AACtH,SAAgB,cAAc,CAAC,QAAgB;IAC3C,IAAI,CAAC,iCAAkB,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACnE,8DAA8D;IAC9D,IAAI,CAAC;QACD,OAAO,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,8BAAe,CAAC,CAAC,CAAC;IAC7E,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACpB,+FAA+F;QAC/F,OAAO,KAAK,CAAC;IACjB,CAAC;AACL,CAAC","sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\nimport { MANIFEST_FILENAMES, CONFIG_FILENAME } from '@webpieces/rules-config';\n\n// webpieces-disable no-function-outside-class -- existing stateless filesystem predicate shared by both hook products\nexport function isRootManifest(filePath: string): boolean {\n if (!MANIFEST_FILENAMES.has(path.basename(filePath))) return false;\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\n try {\n return fs.existsSync(path.join(path.dirname(filePath), CONFIG_FILENAME));\n } catch (err: unknown) {\n //const error = toError(err); best-effort on a blocking path: unreadable is NOT a root manifest\n return false;\n }\n}\n"]}
@@ -0,0 +1,40 @@
1
+ import { BaseRuleConfig } from '@webpieces/rules-sdk';
2
+ import { AbstractRule, RuleOptions } from '@webpieces/rules-config';
3
+ import type { EditContext, BashContext, FileContext, Violation, Rule } from './types';
4
+ import type { FixHint } from './fix-hint';
5
+ /**
6
+ * A concrete, instantiable BaseRuleConfig used as a fallback when a built-in rule has no
7
+ * entry in webpieces.config.json yet. It carries no values, so the rule's `description`,
8
+ * `fixHint`, and `defaultOptions` (which are config-independent) are still readable for the
9
+ * out-of-sync report — the rule never actually runs in that state (the sync check blocks first).
10
+ */
11
+ export declare class EmptyRuleConfig extends BaseRuleConfig {
12
+ }
13
+ /**
14
+ * Scope-specific base for edit rules. Extends the shared AbstractRule (which owns `name`,
15
+ * the typed `config`, and `shouldRun()`), and adds the ai-hook execution surface.
16
+ */
17
+ export declare abstract class EditRuleBase<C extends BaseRuleConfig> extends AbstractRule<C> implements Rule {
18
+ readonly scope: "edit";
19
+ readonly files: readonly string[];
20
+ readonly defaultOptions: RuleOptions;
21
+ abstract readonly description: string;
22
+ abstract readonly fixHint: FixHint;
23
+ abstract check(ctx: EditContext): readonly Violation[];
24
+ }
25
+ export declare abstract class FileRuleBase<C extends BaseRuleConfig> extends AbstractRule<C> implements Rule {
26
+ readonly scope: "file";
27
+ readonly files: readonly string[];
28
+ readonly defaultOptions: RuleOptions;
29
+ abstract readonly description: string;
30
+ abstract readonly fixHint: FixHint;
31
+ abstract check(ctx: FileContext): readonly Violation[];
32
+ }
33
+ export declare abstract class BashRuleBase<C extends BaseRuleConfig> extends AbstractRule<C> implements Rule {
34
+ readonly scope: "bash";
35
+ readonly files: readonly string[];
36
+ readonly defaultOptions: RuleOptions;
37
+ abstract readonly description: string;
38
+ abstract readonly fixHint: FixHint;
39
+ abstract check(ctx: BashContext): readonly Violation[];
40
+ }
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BashRuleBase = exports.FileRuleBase = exports.EditRuleBase = exports.EmptyRuleConfig = void 0;
4
+ const rules_sdk_1 = require("@webpieces/rules-sdk");
5
+ const rules_config_1 = require("@webpieces/rules-config");
6
+ /**
7
+ * A concrete, instantiable BaseRuleConfig used as a fallback when a built-in rule has no
8
+ * entry in webpieces.config.json yet. It carries no values, so the rule's `description`,
9
+ * `fixHint`, and `defaultOptions` (which are config-independent) are still readable for the
10
+ * out-of-sync report — the rule never actually runs in that state (the sync check blocks first).
11
+ */
12
+ class EmptyRuleConfig extends rules_sdk_1.BaseRuleConfig {
13
+ }
14
+ exports.EmptyRuleConfig = EmptyRuleConfig;
15
+ /**
16
+ * Scope-specific base for edit rules. Extends the shared AbstractRule (which owns `name`,
17
+ * the typed `config`, and `shouldRun()`), and adds the ai-hook execution surface.
18
+ */
19
+ class EditRuleBase extends rules_config_1.AbstractRule {
20
+ scope = 'edit';
21
+ files = [];
22
+ defaultOptions = {};
23
+ }
24
+ exports.EditRuleBase = EditRuleBase;
25
+ class FileRuleBase extends rules_config_1.AbstractRule {
26
+ scope = 'file';
27
+ files = [];
28
+ defaultOptions = {};
29
+ }
30
+ exports.FileRuleBase = FileRuleBase;
31
+ class BashRuleBase extends rules_config_1.AbstractRule {
32
+ scope = 'bash';
33
+ files = [];
34
+ defaultOptions = {};
35
+ }
36
+ exports.BashRuleBase = BashRuleBase;
37
+ //# sourceMappingURL=rule-base.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-base.js","sourceRoot":"","sources":["../../../../../../packages/tooling/hook-runtime/src/core/rule-base.ts"],"names":[],"mappings":";;;AAAA,oDAAsD;AACtD,0DAAoE;AAKpE;;;;;GAKG;AACH,MAAa,eAAgB,SAAQ,0BAAc;CAAG;AAAtD,0CAAsD;AAEtD;;;GAGG;AACH,MAAsB,YAAuC,SAAQ,2BAAe;IACvE,KAAK,GAAG,MAAe,CAAC;IACxB,KAAK,GAAsB,EAAE,CAAC;IAC9B,cAAc,GAAgB,EAAE,CAAC;CAK7C;AARD,oCAQC;AAED,MAAsB,YAAuC,SAAQ,2BAAe;IACvE,KAAK,GAAG,MAAe,CAAC;IACxB,KAAK,GAAsB,EAAE,CAAC;IAC9B,cAAc,GAAgB,EAAE,CAAC;CAK7C;AARD,oCAQC;AAED,MAAsB,YAAuC,SAAQ,2BAAe;IACvE,KAAK,GAAG,MAAe,CAAC;IACxB,KAAK,GAAsB,EAAE,CAAC;IAC9B,cAAc,GAAgB,EAAE,CAAC;CAK7C;AARD,oCAQC","sourcesContent":["import { BaseRuleConfig } from '@webpieces/rules-sdk';\nimport { AbstractRule, RuleOptions } from '@webpieces/rules-config';\n\nimport type { EditContext, BashContext, FileContext, Violation, Rule } from './types';\nimport type { FixHint } from './fix-hint';\n\n/**\n * A concrete, instantiable BaseRuleConfig used as a fallback when a built-in rule has no\n * entry in webpieces.config.json yet. It carries no values, so the rule's `description`,\n * `fixHint`, and `defaultOptions` (which are config-independent) are still readable for the\n * out-of-sync report — the rule never actually runs in that state (the sync check blocks first).\n */\nexport class EmptyRuleConfig extends BaseRuleConfig {}\n\n/**\n * Scope-specific base for edit rules. Extends the shared AbstractRule (which owns `name`,\n * the typed `config`, and `shouldRun()`), and adds the ai-hook execution surface.\n */\nexport abstract class EditRuleBase<C extends BaseRuleConfig> extends AbstractRule<C> implements Rule {\n readonly scope = 'edit' as const;\n readonly files: readonly string[] = [];\n readonly defaultOptions: RuleOptions = {};\n abstract readonly description: string;\n abstract readonly fixHint: FixHint;\n\n abstract check(ctx: EditContext): readonly Violation[];\n}\n\nexport abstract class FileRuleBase<C extends BaseRuleConfig> extends AbstractRule<C> implements Rule {\n readonly scope = 'file' as const;\n readonly files: readonly string[] = [];\n readonly defaultOptions: RuleOptions = {};\n abstract readonly description: string;\n abstract readonly fixHint: FixHint;\n\n abstract check(ctx: FileContext): readonly Violation[];\n}\n\nexport abstract class BashRuleBase<C extends BaseRuleConfig> extends AbstractRule<C> implements Rule {\n readonly scope = 'bash' as const;\n readonly files: readonly string[] = [];\n readonly defaultOptions: RuleOptions = {};\n abstract readonly description: string;\n abstract readonly fixHint: FixHint;\n\n abstract check(ctx: BashContext): readonly Violation[];\n}\n"]}
@@ -0,0 +1,18 @@
1
+ import { RulePackRegistry, WebpiecesRulesConfig } from '@webpieces/rules-config';
2
+ import { Rule, EditContext, FileContext, BashContext, Violation, RuleGroup, BlockedResult } from './types';
3
+ /**
4
+ * Fault Y — a loaded rule whose CONFIG KEY has no entry.
5
+ *
6
+ * Compared on `configKey`, not `name`. Eight of the loaded rules are classes behind two policy keys, so
7
+ * comparing names here would demand entries named `feature-branch-guard`, `pr-merge-guard` and six
8
+ * others — keys the validator then REJECTS as retired. That is the two-enforcement-paths deadlock this
9
+ * repo has already hit once (see the narration in guards.spec.ts), and it blocks every Bash/Write/Edit.
10
+ *
11
+ * De-duplicated on the key too, so one missing policy entry reports ONE paste-ready snippet rather than
12
+ * four copies of the same one under four different headings.
13
+ */
14
+ export declare function checkConfigSync(rules: readonly Rule[], config: WebpiecesRulesConfig, registry: RulePackRegistry): BlockedResult | null;
15
+ export declare function runRuleCheck(rule: Rule, ctx: EditContext | FileContext | BashContext): readonly Violation[];
16
+ export declare function runBashRules(rules: readonly Rule[], bashContext: BashContext): readonly RuleGroup[];
17
+ export declare function runEditRules(rules: readonly Rule[], editContexts: readonly EditContext[]): readonly RuleGroup[];
18
+ export declare function runFileRules(rules: readonly Rule[], fileContext: FileContext): readonly RuleGroup[];