@webpieces/ai-hook-rules 0.3.202 → 0.3.203
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 +2 -2
- package/src/core/load-rules.js +2 -4
- package/src/core/load-rules.js.map +1 -1
- package/src/core/rules/index.js +1 -2
- package/src/core/rules/index.js.map +1 -1
- package/src/core/rules/{no-direct-main-update.d.ts → redirect-how-to-merge-main.d.ts} +3 -3
- package/src/core/rules/{no-direct-main-update.js → redirect-how-to-merge-main.js} +5 -5
- package/src/core/rules/redirect-how-to-merge-main.js.map +1 -0
- package/src/index.d.ts +1 -2
- package/src/index.js +3 -5
- package/src/index.js.map +1 -1
- package/src/core/rules/no-direct-main-update.js.map +0 -1
- package/src/core/rules/no-shell-substitution.d.ts +0 -9
- package/src/core/rules/no-shell-substitution.js +0 -51
- package/src/core/rules/no-shell-substitution.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webpieces/ai-hook-rules",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.203",
|
|
4
4
|
"description": "Pluggable write-time validation framework for AI coding agents (@webpieces/ai-hook-rules). Claude Code PreToolUse + openclaw before_tool_call adapters share one rule engine.",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "./src/index.js",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"directory": "packages/tooling/ai-hook-rules"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@webpieces/rules-config": "0.3.
|
|
38
|
+
"@webpieces/rules-config": "0.3.203"
|
|
39
39
|
},
|
|
40
40
|
"publishConfig": {
|
|
41
41
|
"access": "public"
|
package/src/core/load-rules.js
CHANGED
|
@@ -19,13 +19,12 @@ const require_return_type_1 = require("./rules/require-return-type");
|
|
|
19
19
|
const no_unmanaged_exceptions_1 = require("./rules/no-unmanaged-exceptions");
|
|
20
20
|
const catch_error_pattern_1 = require("./rules/catch-error-pattern");
|
|
21
21
|
const throw_cause_required_1 = require("./rules/throw-cause-required");
|
|
22
|
-
const no_shell_substitution_1 = require("./rules/no-shell-substitution");
|
|
23
22
|
const no_symbol_di_tokens_1 = require("./rules/no-symbol-di-tokens");
|
|
24
23
|
const branch_creation_guard_1 = require("./rules/branch-creation-guard");
|
|
25
24
|
const pr_creation_guard_1 = require("./rules/pr-creation-guard");
|
|
26
25
|
const merge_in_progress_guard_1 = require("./rules/merge-in-progress-guard");
|
|
27
26
|
const pr_merge_cleanup_1 = require("./rules/pr-merge-cleanup");
|
|
28
|
-
const
|
|
27
|
+
const redirect_how_to_merge_main_1 = require("./rules/redirect-how-to-merge-main");
|
|
29
28
|
const no_js_files_1 = require("./rules/no-js-files");
|
|
30
29
|
const feature_branch_guard_1 = require("./rules/feature-branch-guard");
|
|
31
30
|
const REQUIRED_FIELDS = ['name', 'description', 'scope', 'files', 'check'];
|
|
@@ -40,13 +39,12 @@ const BUILT_IN_RULE_MAP = {
|
|
|
40
39
|
'no-unmanaged-exceptions': (c) => new no_unmanaged_exceptions_1.NoUnmanagedExceptionsRule(c),
|
|
41
40
|
'catch-error-pattern': (c) => new catch_error_pattern_1.CatchErrorPatternRule(c),
|
|
42
41
|
'throw-cause-required': (c) => new throw_cause_required_1.ThrowCauseRequiredRule(c),
|
|
43
|
-
'no-shell-substitution': (c) => new no_shell_substitution_1.NoShellSubstitutionRule(c),
|
|
44
42
|
'no-symbol-di-tokens': (c) => new no_symbol_di_tokens_1.NoSymbolDiTokensRule(c),
|
|
45
43
|
'branch-creation-guard': (c) => new branch_creation_guard_1.BranchCreationGuardRule(c),
|
|
46
44
|
'pr-creation-guard': (c) => new pr_creation_guard_1.PrCreationGuardRule(c),
|
|
47
45
|
'merge-in-progress-guard': (c) => new merge_in_progress_guard_1.MergeInProgressGuardRule(c),
|
|
48
46
|
'pr-merge-cleanup': (c) => new pr_merge_cleanup_1.PrMergeCleanupRule(c),
|
|
49
|
-
'
|
|
47
|
+
'redirect-how-to-merge-main': (c) => new redirect_how_to_merge_main_1.RedirectHowToMergeMainRule(c),
|
|
50
48
|
'no-js-files': (c) => new no_js_files_1.NoJsFilesRule(c),
|
|
51
49
|
'feature-branch-guard': (c) => new feature_branch_guard_1.FeatureBranchGuardRule(c),
|
|
52
50
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"load-rules.js","sourceRoot":"","sources":["../../../../../../packages/tooling/ai-hook-rules/src/core/load-rules.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\n\nimport {\n BaseRuleConfig, RuleOptions, WebpiecesRulesConfig,\n NoAnyUnknownConfig, NoImplicitAnyConfig, MaxFileLinesConfig, ValidateTsInSrcConfig,\n NoDestructureConfig, RequireReturnTypeConfig, NoUnmanagedExceptionsConfig,\n CatchErrorPatternConfig, ThrowCauseRequiredConfig, NoShellSubstitutionConfig,\n NoSymbolDiTokensConfig, BranchCreationGuardConfig, PrCreationGuardConfig,\n MergeInProgressGuardConfig, PrMergeCleanupConfig, NoDirectMainUpdateConfig,\n NoJsFilesConfig, FeatureBranchGuardConfig,\n} from '@webpieces/rules-config';\n\nimport type { Rule, PlainRule } from './types';\nimport { InformAiError } from './types';\nimport { toError } from './to-error';\nimport { EmptyRuleConfig } from './rule-base';\nimport { CustomRuleAdapter } from './custom-rule-adapter';\nimport { builtInRuleNames } from './rules/index';\nimport { NoAnyUnknownRule } from './rules/no-any-unknown';\nimport { NoImplicitAnyRule } from './rules/no-implicit-any';\nimport { MaxFileLinesRule } from './rules/max-file-lines';\nimport { ValidateTsInSrcRule } from './rules/validate-ts-in-src';\nimport { NoDestructureRule } from './rules/no-destructure';\nimport { RequireReturnTypeRule } from './rules/require-return-type';\nimport { NoUnmanagedExceptionsRule } from './rules/no-unmanaged-exceptions';\nimport { CatchErrorPatternRule } from './rules/catch-error-pattern';\nimport { ThrowCauseRequiredRule } from './rules/throw-cause-required';\nimport { NoShellSubstitutionRule } from './rules/no-shell-substitution';\nimport { NoSymbolDiTokensRule } from './rules/no-symbol-di-tokens';\nimport { BranchCreationGuardRule } from './rules/branch-creation-guard';\nimport { PrCreationGuardRule } from './rules/pr-creation-guard';\nimport { MergeInProgressGuardRule } from './rules/merge-in-progress-guard';\nimport { PrMergeCleanupRule } from './rules/pr-merge-cleanup';\nimport { NoDirectMainUpdateRule } from './rules/no-direct-main-update';\nimport { NoJsFilesRule } from './rules/no-js-files';\nimport { FeatureBranchGuardRule } from './rules/feature-branch-guard';\n\nconst REQUIRED_FIELDS: readonly string[] = ['name', 'description', 'scope', 'files', 'check'];\nconst VALID_SCOPES = new Set(['edit', 'file', 'bash']);\n\n// Each built-in rule is constructed from its typed *Config (the entry in webpieces.config.json).\n// The config arrives as a plain object structurally typed as the *Config class, so the `as`\n// narrows the shared BaseRuleConfig param back to the concrete config the rule consumes.\ntype RuleFactory = (config: BaseRuleConfig) => Rule;\n\nconst BUILT_IN_RULE_MAP: Record<string, RuleFactory> = {\n 'no-any-unknown': (c: BaseRuleConfig) => new NoAnyUnknownRule(c as NoAnyUnknownConfig),\n 'no-implicit-any': (c: BaseRuleConfig) => new NoImplicitAnyRule(c as NoImplicitAnyConfig),\n 'max-file-lines': (c: BaseRuleConfig) => new MaxFileLinesRule(c as MaxFileLinesConfig),\n 'validate-ts-in-src': (c: BaseRuleConfig) => new ValidateTsInSrcRule(c as ValidateTsInSrcConfig),\n 'no-destructure': (c: BaseRuleConfig) => new NoDestructureRule(c as NoDestructureConfig),\n 'require-return-type': (c: BaseRuleConfig) => new RequireReturnTypeRule(c as RequireReturnTypeConfig),\n 'no-unmanaged-exceptions': (c: BaseRuleConfig) => new NoUnmanagedExceptionsRule(c as NoUnmanagedExceptionsConfig),\n 'catch-error-pattern': (c: BaseRuleConfig) => new CatchErrorPatternRule(c as CatchErrorPatternConfig),\n 'throw-cause-required': (c: BaseRuleConfig) => new ThrowCauseRequiredRule(c as ThrowCauseRequiredConfig),\n 'no-shell-substitution': (c: BaseRuleConfig) => new NoShellSubstitutionRule(c as NoShellSubstitutionConfig),\n 'no-symbol-di-tokens': (c: BaseRuleConfig) => new NoSymbolDiTokensRule(c as NoSymbolDiTokensConfig),\n 'branch-creation-guard': (c: BaseRuleConfig) => new BranchCreationGuardRule(c as BranchCreationGuardConfig),\n 'pr-creation-guard': (c: BaseRuleConfig) => new PrCreationGuardRule(c as PrCreationGuardConfig),\n 'merge-in-progress-guard': (c: BaseRuleConfig) => new MergeInProgressGuardRule(c as MergeInProgressGuardConfig),\n 'pr-merge-cleanup': (c: BaseRuleConfig) => new PrMergeCleanupRule(c as PrMergeCleanupConfig),\n 'no-direct-main-update': (c: BaseRuleConfig) => new NoDirectMainUpdateRule(c as NoDirectMainUpdateConfig),\n 'no-js-files': (c: BaseRuleConfig) => new NoJsFilesRule(c as NoJsFilesConfig),\n 'feature-branch-guard': (c: BaseRuleConfig) => new FeatureBranchGuardRule(c as FeatureBranchGuardConfig),\n};\n\n// Index the typed config by rule name. Each value is the rule's *Config (a plain object from\n// JSON), or undefined when the rule has no entry yet (the sync check reports those).\nfunction asConfigMap(config: WebpiecesRulesConfig): Record<string, BaseRuleConfig | undefined> {\n // webpieces-disable no-any-unknown -- index the typed config by dynamic rule name\n return config as unknown as Record<string, BaseRuleConfig | undefined>;\n}\n\nexport function loadRules(config: WebpiecesRulesConfig, workspaceRoot: string): readonly Rule[] {\n const builtIns = loadBuiltInRules(config);\n const custom = loadCustomRules(config, workspaceRoot);\n return [...builtIns, ...custom];\n}\n\nfunction loadBuiltInRules(config: WebpiecesRulesConfig): Rule[] {\n const map = asConfigMap(config);\n const rules: Rule[] = [];\n for (const name of builtInRuleNames) {\n const factory = BUILT_IN_RULE_MAP[name];\n if (!factory) {\n process.stderr.write(`[ai-hooks] unknown built-in rule: ${name}\\n`);\n continue;\n }\n const ruleConfig = map[name] ?? new EmptyRuleConfig();\n rules.push(factory(ruleConfig));\n }\n return rules;\n}\n\nfunction loadCustomRules(config: WebpiecesRulesConfig, workspaceRoot: string): Rule[] {\n const dirs = config.rulesDir ?? [];\n // webpieces-disable no-any-unknown -- index the typed config by dynamic custom-rule name\n const map = config as unknown as Record<string, RuleOptions | undefined>;\n const rules: Rule[] = [];\n for (const plain of loadCustomPlainRules(dirs, workspaceRoot)) {\n const rawConfig = map[plain.name] ?? {};\n rules.push(new CustomRuleAdapter(plain, rawConfig));\n }\n return rules;\n}\n\nfunction loadCustomPlainRules(rulesDirs: readonly string[], workspaceRoot: string): PlainRule[] {\n const modules: PlainRule[] = [];\n for (const dir of rulesDirs) {\n const absDir = path.isAbsolute(dir) ? dir : path.join(workspaceRoot, dir);\n if (!fs.existsSync(absDir)) {\n process.stderr.write(`[ai-hooks] rulesDir not found: ${absDir}\\n`);\n continue;\n }\n let entries: string[];\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\n try {\n entries = fs.readdirSync(absDir).filter((e: string) => e.endsWith('.js'));\n } catch (err: unknown) {\n const error = toError(err);\n throw new InformAiError(`Cannot read custom rules directory '${absDir}'`, { cause: error });\n }\n for (const entry of entries) {\n const full = path.join(absDir, entry);\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\n try {\n const mod = require(full);\n const candidate = mod.default || mod;\n if (validateRule(candidate)) modules.push(candidate);\n } catch (err: unknown) {\n const error = toError(err);\n throw new InformAiError(`Cannot load custom rule '${full}'`, { cause: error });\n }\n }\n }\n return modules;\n}\n\n// webpieces-disable no-any-unknown -- validates untrusted require() output at system boundary\nfunction validateRule(rule: unknown): rule is PlainRule {\n if (!rule || typeof rule !== 'object') {\n process.stderr.write('[ai-hooks] rule is not an object, skipping\\n');\n return false;\n }\n // webpieces-disable no-any-unknown -- narrowing from unknown at system boundary\n const obj = rule as Record<string, unknown>;\n for (const field of REQUIRED_FIELDS) {\n if (obj[field] === undefined) {\n const name = typeof obj['name'] === 'string' ? obj['name'] : '<unnamed>';\n process.stderr.write(`[ai-hooks] rule \"${name}\" missing required field: ${field}\\n`);\n return false;\n }\n }\n if (!VALID_SCOPES.has(obj['scope'] as string)) {\n process.stderr.write(`[ai-hooks] rule \"${obj['name']}\" has invalid scope: ${String(obj['scope'])}\\n`);\n return false;\n }\n if (!Array.isArray(obj['files'])) {\n process.stderr.write(`[ai-hooks] rule \"${obj['name']}\" files must be an array\\n`);\n return false;\n }\n if (typeof obj['check'] !== 'function') {\n process.stderr.write(`[ai-hooks] rule \"${obj['name']}\" check must be a function\\n`);\n return false;\n }\n return true;\n}\n\nexport function globMatches(pattern: string, filePath: string): boolean {\n const regex = globToRegex(pattern);\n return regex.test(filePath);\n}\n\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"]}
|
|
1
|
+
{"version":3,"file":"load-rules.js","sourceRoot":"","sources":["../../../../../../packages/tooling/ai-hook-rules/src/core/load-rules.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\n\nimport {\n BaseRuleConfig, RuleOptions, WebpiecesRulesConfig,\n NoAnyUnknownConfig, NoImplicitAnyConfig, MaxFileLinesConfig, ValidateTsInSrcConfig,\n NoDestructureConfig, RequireReturnTypeConfig, NoUnmanagedExceptionsConfig,\n CatchErrorPatternConfig, ThrowCauseRequiredConfig,\n NoSymbolDiTokensConfig, BranchCreationGuardConfig, PrCreationGuardConfig,\n MergeInProgressGuardConfig, PrMergeCleanupConfig, RedirectHowToMergeMainConfig,\n NoJsFilesConfig, FeatureBranchGuardConfig,\n} from '@webpieces/rules-config';\n\nimport type { Rule, PlainRule } from './types';\nimport { InformAiError } from './types';\nimport { toError } from './to-error';\nimport { EmptyRuleConfig } from './rule-base';\nimport { CustomRuleAdapter } from './custom-rule-adapter';\nimport { builtInRuleNames } from './rules/index';\nimport { NoAnyUnknownRule } from './rules/no-any-unknown';\nimport { NoImplicitAnyRule } from './rules/no-implicit-any';\nimport { MaxFileLinesRule } from './rules/max-file-lines';\nimport { ValidateTsInSrcRule } from './rules/validate-ts-in-src';\nimport { NoDestructureRule } from './rules/no-destructure';\nimport { RequireReturnTypeRule } from './rules/require-return-type';\nimport { NoUnmanagedExceptionsRule } from './rules/no-unmanaged-exceptions';\nimport { CatchErrorPatternRule } from './rules/catch-error-pattern';\nimport { ThrowCauseRequiredRule } from './rules/throw-cause-required';\nimport { NoSymbolDiTokensRule } from './rules/no-symbol-di-tokens';\nimport { BranchCreationGuardRule } from './rules/branch-creation-guard';\nimport { PrCreationGuardRule } from './rules/pr-creation-guard';\nimport { MergeInProgressGuardRule } from './rules/merge-in-progress-guard';\nimport { PrMergeCleanupRule } from './rules/pr-merge-cleanup';\nimport { RedirectHowToMergeMainRule } from './rules/redirect-how-to-merge-main';\nimport { NoJsFilesRule } from './rules/no-js-files';\nimport { FeatureBranchGuardRule } from './rules/feature-branch-guard';\n\nconst REQUIRED_FIELDS: readonly string[] = ['name', 'description', 'scope', 'files', 'check'];\nconst VALID_SCOPES = new Set(['edit', 'file', 'bash']);\n\n// Each built-in rule is constructed from its typed *Config (the entry in webpieces.config.json).\n// The config arrives as a plain object structurally typed as the *Config class, so the `as`\n// narrows the shared BaseRuleConfig param back to the concrete config the rule consumes.\ntype RuleFactory = (config: BaseRuleConfig) => Rule;\n\nconst BUILT_IN_RULE_MAP: Record<string, RuleFactory> = {\n 'no-any-unknown': (c: BaseRuleConfig) => new NoAnyUnknownRule(c as NoAnyUnknownConfig),\n 'no-implicit-any': (c: BaseRuleConfig) => new NoImplicitAnyRule(c as NoImplicitAnyConfig),\n 'max-file-lines': (c: BaseRuleConfig) => new MaxFileLinesRule(c as MaxFileLinesConfig),\n 'validate-ts-in-src': (c: BaseRuleConfig) => new ValidateTsInSrcRule(c as ValidateTsInSrcConfig),\n 'no-destructure': (c: BaseRuleConfig) => new NoDestructureRule(c as NoDestructureConfig),\n 'require-return-type': (c: BaseRuleConfig) => new RequireReturnTypeRule(c as RequireReturnTypeConfig),\n 'no-unmanaged-exceptions': (c: BaseRuleConfig) => new NoUnmanagedExceptionsRule(c as NoUnmanagedExceptionsConfig),\n 'catch-error-pattern': (c: BaseRuleConfig) => new CatchErrorPatternRule(c as CatchErrorPatternConfig),\n 'throw-cause-required': (c: BaseRuleConfig) => new ThrowCauseRequiredRule(c as ThrowCauseRequiredConfig),\n 'no-symbol-di-tokens': (c: BaseRuleConfig) => new NoSymbolDiTokensRule(c as NoSymbolDiTokensConfig),\n 'branch-creation-guard': (c: BaseRuleConfig) => new BranchCreationGuardRule(c as BranchCreationGuardConfig),\n 'pr-creation-guard': (c: BaseRuleConfig) => new PrCreationGuardRule(c as PrCreationGuardConfig),\n 'merge-in-progress-guard': (c: BaseRuleConfig) => new MergeInProgressGuardRule(c as MergeInProgressGuardConfig),\n 'pr-merge-cleanup': (c: BaseRuleConfig) => new PrMergeCleanupRule(c as PrMergeCleanupConfig),\n 'redirect-how-to-merge-main': (c: BaseRuleConfig) => new RedirectHowToMergeMainRule(c as RedirectHowToMergeMainConfig),\n 'no-js-files': (c: BaseRuleConfig) => new NoJsFilesRule(c as NoJsFilesConfig),\n 'feature-branch-guard': (c: BaseRuleConfig) => new FeatureBranchGuardRule(c as FeatureBranchGuardConfig),\n};\n\n// Index the typed config by rule name. Each value is the rule's *Config (a plain object from\n// JSON), or undefined when the rule has no entry yet (the sync check reports those).\nfunction asConfigMap(config: WebpiecesRulesConfig): Record<string, BaseRuleConfig | undefined> {\n // webpieces-disable no-any-unknown -- index the typed config by dynamic rule name\n return config as unknown as Record<string, BaseRuleConfig | undefined>;\n}\n\nexport function loadRules(config: WebpiecesRulesConfig, workspaceRoot: string): readonly Rule[] {\n const builtIns = loadBuiltInRules(config);\n const custom = loadCustomRules(config, workspaceRoot);\n return [...builtIns, ...custom];\n}\n\nfunction loadBuiltInRules(config: WebpiecesRulesConfig): Rule[] {\n const map = asConfigMap(config);\n const rules: Rule[] = [];\n for (const name of builtInRuleNames) {\n const factory = BUILT_IN_RULE_MAP[name];\n if (!factory) {\n process.stderr.write(`[ai-hooks] unknown built-in rule: ${name}\\n`);\n continue;\n }\n const ruleConfig = map[name] ?? new EmptyRuleConfig();\n rules.push(factory(ruleConfig));\n }\n return rules;\n}\n\nfunction loadCustomRules(config: WebpiecesRulesConfig, workspaceRoot: string): Rule[] {\n const dirs = config.rulesDir ?? [];\n // webpieces-disable no-any-unknown -- index the typed config by dynamic custom-rule name\n const map = config as unknown as Record<string, RuleOptions | undefined>;\n const rules: Rule[] = [];\n for (const plain of loadCustomPlainRules(dirs, workspaceRoot)) {\n const rawConfig = map[plain.name] ?? {};\n rules.push(new CustomRuleAdapter(plain, rawConfig));\n }\n return rules;\n}\n\nfunction loadCustomPlainRules(rulesDirs: readonly string[], workspaceRoot: string): PlainRule[] {\n const modules: PlainRule[] = [];\n for (const dir of rulesDirs) {\n const absDir = path.isAbsolute(dir) ? dir : path.join(workspaceRoot, dir);\n if (!fs.existsSync(absDir)) {\n process.stderr.write(`[ai-hooks] rulesDir not found: ${absDir}\\n`);\n continue;\n }\n let entries: string[];\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\n try {\n entries = fs.readdirSync(absDir).filter((e: string) => e.endsWith('.js'));\n } catch (err: unknown) {\n const error = toError(err);\n throw new InformAiError(`Cannot read custom rules directory '${absDir}'`, { cause: error });\n }\n for (const entry of entries) {\n const full = path.join(absDir, entry);\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\n try {\n const mod = require(full);\n const candidate = mod.default || mod;\n if (validateRule(candidate)) modules.push(candidate);\n } catch (err: unknown) {\n const error = toError(err);\n throw new InformAiError(`Cannot load custom rule '${full}'`, { cause: error });\n }\n }\n }\n return modules;\n}\n\n// webpieces-disable no-any-unknown -- validates untrusted require() output at system boundary\nfunction validateRule(rule: unknown): rule is PlainRule {\n if (!rule || typeof rule !== 'object') {\n process.stderr.write('[ai-hooks] rule is not an object, skipping\\n');\n return false;\n }\n // webpieces-disable no-any-unknown -- narrowing from unknown at system boundary\n const obj = rule as Record<string, unknown>;\n for (const field of REQUIRED_FIELDS) {\n if (obj[field] === undefined) {\n const name = typeof obj['name'] === 'string' ? obj['name'] : '<unnamed>';\n process.stderr.write(`[ai-hooks] rule \"${name}\" missing required field: ${field}\\n`);\n return false;\n }\n }\n if (!VALID_SCOPES.has(obj['scope'] as string)) {\n process.stderr.write(`[ai-hooks] rule \"${obj['name']}\" has invalid scope: ${String(obj['scope'])}\\n`);\n return false;\n }\n if (!Array.isArray(obj['files'])) {\n process.stderr.write(`[ai-hooks] rule \"${obj['name']}\" files must be an array\\n`);\n return false;\n }\n if (typeof obj['check'] !== 'function') {\n process.stderr.write(`[ai-hooks] rule \"${obj['name']}\" check must be a function\\n`);\n return false;\n }\n return true;\n}\n\nexport function globMatches(pattern: string, filePath: string): boolean {\n const regex = globToRegex(pattern);\n return regex.test(filePath);\n}\n\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"]}
|
package/src/core/rules/index.js
CHANGED
|
@@ -12,13 +12,12 @@ exports.builtInRuleNames = [
|
|
|
12
12
|
'no-unmanaged-exceptions',
|
|
13
13
|
'catch-error-pattern',
|
|
14
14
|
'throw-cause-required',
|
|
15
|
-
'no-shell-substitution',
|
|
16
15
|
'no-symbol-di-tokens',
|
|
17
16
|
'branch-creation-guard',
|
|
18
17
|
'pr-creation-guard',
|
|
19
18
|
'merge-in-progress-guard',
|
|
20
19
|
'pr-merge-cleanup',
|
|
21
|
-
'
|
|
20
|
+
'redirect-how-to-merge-main',
|
|
22
21
|
'feature-branch-guard',
|
|
23
22
|
];
|
|
24
23
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/ai-hook-rules/src/core/rules/index.ts"],"names":[],"mappings":";;;AAAa,QAAA,gBAAgB,GAAsB;IAC/C,gBAAgB;IAChB,iBAAiB;IACjB,gBAAgB;IAChB,oBAAoB;IACpB,aAAa;IACb,gBAAgB;IAChB,qBAAqB;IACrB,yBAAyB;IACzB,qBAAqB;IACrB,sBAAsB;IACtB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/ai-hook-rules/src/core/rules/index.ts"],"names":[],"mappings":";;;AAAa,QAAA,gBAAgB,GAAsB;IAC/C,gBAAgB;IAChB,iBAAiB;IACjB,gBAAgB;IAChB,oBAAoB;IACpB,aAAa;IACb,gBAAgB;IAChB,qBAAqB;IACrB,yBAAyB;IACzB,qBAAqB;IACrB,sBAAsB;IACtB,qBAAqB;IACrB,uBAAuB;IACvB,mBAAmB;IACnB,yBAAyB;IACzB,kBAAkB;IAClB,4BAA4B;IAC5B,sBAAsB;CACzB,CAAC","sourcesContent":["export const builtInRuleNames: readonly string[] = [\n 'no-any-unknown',\n 'no-implicit-any',\n 'max-file-lines',\n 'validate-ts-in-src',\n 'no-js-files',\n 'no-destructure',\n 'require-return-type',\n 'no-unmanaged-exceptions',\n 'catch-error-pattern',\n 'throw-cause-required',\n 'no-symbol-di-tokens',\n 'branch-creation-guard',\n 'pr-creation-guard',\n 'merge-in-progress-guard',\n 'pr-merge-cleanup',\n 'redirect-how-to-merge-main',\n 'feature-branch-guard',\n];\n"]}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { RedirectHowToMergeMainConfig } from '@webpieces/rules-config';
|
|
2
2
|
import type { BashContext, Violation } from '../types';
|
|
3
3
|
import { BashRuleBase } from '../rule-base';
|
|
4
|
-
export declare class
|
|
5
|
-
constructor(config:
|
|
4
|
+
export declare class RedirectHowToMergeMainRule extends BashRuleBase<RedirectHowToMergeMainConfig> {
|
|
5
|
+
constructor(config: RedirectHowToMergeMainConfig);
|
|
6
6
|
readonly description = "Block direct git merge/rebase/pull from main on feature branches. Use the squash-update process instead.";
|
|
7
7
|
readonly fixHint: readonly string[];
|
|
8
8
|
check(ctx: BashContext): readonly Violation[];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.RedirectHowToMergeMainRule = void 0;
|
|
4
4
|
const child_process_1 = require("child_process");
|
|
5
5
|
const types_1 = require("../types");
|
|
6
6
|
const rule_base_1 = require("../rule-base");
|
|
@@ -16,8 +16,8 @@ function truncate(s) {
|
|
|
16
16
|
const MAX = 120;
|
|
17
17
|
return s.length <= MAX ? s : s.slice(0, MAX) + '…';
|
|
18
18
|
}
|
|
19
|
-
class
|
|
20
|
-
constructor(config) { super(config, '
|
|
19
|
+
class RedirectHowToMergeMainRule extends rule_base_1.BashRuleBase {
|
|
20
|
+
constructor(config) { super(config, 'redirect-how-to-merge-main'); }
|
|
21
21
|
description = 'Block direct git merge/rebase/pull from main on feature branches. Use the squash-update process instead.';
|
|
22
22
|
fixHint = FIX_HINT;
|
|
23
23
|
check(ctx) {
|
|
@@ -44,5 +44,5 @@ class NoDirectMainUpdateRule extends rule_base_1.BashRuleBase {
|
|
|
44
44
|
].join('\n'))];
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
|
-
exports.
|
|
48
|
-
//# sourceMappingURL=
|
|
47
|
+
exports.RedirectHowToMergeMainRule = RedirectHowToMergeMainRule;
|
|
48
|
+
//# sourceMappingURL=redirect-how-to-merge-main.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redirect-how-to-merge-main.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/ai-hook-rules/src/core/rules/redirect-how-to-merge-main.ts"],"names":[],"mappings":";;;AAAA,iDAAyC;AAKzC,oCAA0C;AAC1C,4CAA4C;AAE5C,MAAM,QAAQ,GAAsB;IAChC,gNAAgN;CACnN,CAAC;AAEF,MAAM,qBAAqB,GAAa;IACpC,qCAAqC;IACrC,sCAAsC;IACtC,8BAA8B;CACjC,CAAC;AAEF,SAAS,QAAQ,CAAC,CAAS;IACvB,MAAM,GAAG,GAAG,GAAG,CAAC;IAChB,OAAO,CAAC,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,GAAG,CAAC;AACvD,CAAC;AAED,MAAa,0BAA2B,SAAQ,wBAA0C;IACtF,YAAY,MAAoC,IAAI,KAAK,CAAC,MAAM,EAAE,4BAA4B,CAAC,CAAC,CAAC,CAAC;IAEzF,WAAW,GAAG,0GAA0G,CAAC;IACzH,OAAO,GAAG,QAAQ,CAAC;IAE5B,KAAK,CAAC,GAAgB;QAClB,MAAM,OAAO,GAAG,qBAAqB,CAAC,IAAI,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;QAC/E,IAAI,CAAC,OAAO;YAAE,OAAO,EAAE,CAAC;QAExB,0GAA0G;QAC1G,IAAI,oCAAoC,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;YACzD,OAAO,EAAE,CAAC;QACd,CAAC;QAED,MAAM,aAAa,GAAG,IAAA,wBAAQ,EAAC,iCAAiC,EAAE;YAC9D,GAAG,EAAE,GAAG,CAAC,aAAa;YACtB,QAAQ,EAAE,MAAM;SACnB,CAAC,CAAC,IAAI,EAAE,CAAC;QAEV,IAAI,aAAa,KAAK,MAAM,EAAE,CAAC;YAC3B,OAAO,EAAE,CAAC;QACd,CAAC;QAED,OAAO,CAAC,IAAI,iBAAC,CACT,CAAC,EACD,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EACrB;gBACI,4CAA4C,aAAa,eAAe;gBACxE,4CAA4C;gBAC5C,wCAAwC;gBACxC,sBAAsB;gBACtB,uCAAuC;aAC1C,CAAC,IAAI,CAAC,IAAI,CAAC,CACf,CAAC,CAAC;IACP,CAAC;CACJ;AApCD,gEAoCC","sourcesContent":["import { execSync } from 'child_process';\n\nimport { RedirectHowToMergeMainConfig } from '@webpieces/rules-config';\n\nimport type { BashContext, Violation } from '../types';\nimport { Violation as V } from '../types';\nimport { BashRuleBase } from '../rule-base';\n\nconst FIX_HINT: readonly string[] = [\n \"Run 'pnpm wp-git-update' to squash-update from main. This preserves the 3-point fork-point system (fork-point=A, feature-HEAD=B, main-HEAD=C) needed for clean PR diffs. See docs/git-workflow.md for details.\",\n];\n\nconst WRONG_UPDATE_PATTERNS: RegExp[] = [\n /git\\s+merge\\s+(origin\\/main|main)\\b/,\n /git\\s+rebase\\s+(origin\\/main|main)\\b/,\n /git\\s+pull\\s+origin\\s+main\\b/,\n];\n\nfunction truncate(s: string): string {\n const MAX = 120;\n return s.length <= MAX ? s : s.slice(0, MAX) + '…';\n}\n\nexport class RedirectHowToMergeMainRule extends BashRuleBase<RedirectHowToMergeMainConfig> {\n constructor(config: RedirectHowToMergeMainConfig) { super(config, 'redirect-how-to-merge-main'); }\n\n readonly description = 'Block direct git merge/rebase/pull from main on feature branches. Use the squash-update process instead.';\n readonly fixHint = FIX_HINT;\n\n check(ctx: BashContext): readonly Violation[] {\n const matched = WRONG_UPDATE_PATTERNS.some((p: RegExp) => p.test(ctx.command));\n if (!matched) return [];\n\n // Allow 'git checkout main && git pull origin main' — switching to main first is the recommended workflow\n if (/git\\s+(?:checkout|switch)\\s+main\\b/.test(ctx.command)) {\n return [];\n }\n\n const currentBranch = execSync('git rev-parse --abbrev-ref HEAD', {\n cwd: ctx.workspaceRoot,\n encoding: 'utf8',\n }).trim();\n\n if (currentBranch === 'main') {\n return [];\n }\n\n return [new V(\n 1,\n truncate(ctx.command),\n [\n `Direct merge/rebase from main on branch '${currentBranch}' is blocked.`,\n 'This breaks the 3-point fork-point system.',\n 'Use the squash-update process instead:',\n ' pnpm wp-git-update',\n 'See docs/git-workflow.md for details.',\n ].join('\\n'),\n )];\n }\n}\n"]}
|
package/src/index.d.ts
CHANGED
|
@@ -10,13 +10,12 @@ export { RequireReturnTypeRule } from './core/rules/require-return-type';
|
|
|
10
10
|
export { NoUnmanagedExceptionsRule } from './core/rules/no-unmanaged-exceptions';
|
|
11
11
|
export { CatchErrorPatternRule } from './core/rules/catch-error-pattern';
|
|
12
12
|
export { ThrowCauseRequiredRule } from './core/rules/throw-cause-required';
|
|
13
|
-
export { NoShellSubstitutionRule } from './core/rules/no-shell-substitution';
|
|
14
13
|
export { NoSymbolDiTokensRule } from './core/rules/no-symbol-di-tokens';
|
|
15
14
|
export { BranchCreationGuardRule } from './core/rules/branch-creation-guard';
|
|
16
15
|
export { PrCreationGuardRule } from './core/rules/pr-creation-guard';
|
|
17
16
|
export { MergeInProgressGuardRule } from './core/rules/merge-in-progress-guard';
|
|
18
17
|
export { PrMergeCleanupRule } from './core/rules/pr-merge-cleanup';
|
|
19
|
-
export {
|
|
18
|
+
export { RedirectHowToMergeMainRule } from './core/rules/redirect-how-to-merge-main';
|
|
20
19
|
export { NoJsFilesRule } from './core/rules/no-js-files';
|
|
21
20
|
export { FeatureBranchGuardRule } from './core/rules/feature-branch-guard';
|
|
22
21
|
export { run } from './core/runner';
|
package/src/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.formatReport = exports.createIsLineDisabled = exports.DirectiveIndex = exports.parseDirectives = exports.stripTsNoise = exports.run = exports.FeatureBranchGuardRule = exports.NoJsFilesRule = exports.
|
|
3
|
+
exports.formatReport = exports.createIsLineDisabled = exports.DirectiveIndex = exports.parseDirectives = exports.stripTsNoise = exports.run = exports.FeatureBranchGuardRule = exports.NoJsFilesRule = exports.RedirectHowToMergeMainRule = exports.PrMergeCleanupRule = exports.MergeInProgressGuardRule = exports.PrCreationGuardRule = exports.BranchCreationGuardRule = exports.NoSymbolDiTokensRule = exports.ThrowCauseRequiredRule = exports.CatchErrorPatternRule = exports.NoUnmanagedExceptionsRule = exports.RequireReturnTypeRule = exports.NoDestructureRule = exports.ValidateTsInSrcRule = exports.MaxFileLinesRule = exports.NoImplicitAnyRule = exports.NoAnyUnknownRule = exports.CustomRuleAdapter = exports.EmptyRuleConfig = exports.BashRuleBase = exports.FileRuleBase = exports.EditRuleBase = exports.ResolvedRuleConfig = exports.ResolvedConfig = exports.BlockedResult = exports.RuleGroup = exports.BashContext = exports.FileContext = exports.EditContext = exports.NormalizedToolInput = exports.NormalizedEdit = exports.Violation = void 0;
|
|
4
4
|
// Pluggable write-time validation framework for AI coding agents
|
|
5
5
|
var types_1 = require("./core/types");
|
|
6
6
|
Object.defineProperty(exports, "Violation", { enumerable: true, get: function () { return types_1.Violation; } });
|
|
@@ -40,8 +40,6 @@ var catch_error_pattern_1 = require("./core/rules/catch-error-pattern");
|
|
|
40
40
|
Object.defineProperty(exports, "CatchErrorPatternRule", { enumerable: true, get: function () { return catch_error_pattern_1.CatchErrorPatternRule; } });
|
|
41
41
|
var throw_cause_required_1 = require("./core/rules/throw-cause-required");
|
|
42
42
|
Object.defineProperty(exports, "ThrowCauseRequiredRule", { enumerable: true, get: function () { return throw_cause_required_1.ThrowCauseRequiredRule; } });
|
|
43
|
-
var no_shell_substitution_1 = require("./core/rules/no-shell-substitution");
|
|
44
|
-
Object.defineProperty(exports, "NoShellSubstitutionRule", { enumerable: true, get: function () { return no_shell_substitution_1.NoShellSubstitutionRule; } });
|
|
45
43
|
var no_symbol_di_tokens_1 = require("./core/rules/no-symbol-di-tokens");
|
|
46
44
|
Object.defineProperty(exports, "NoSymbolDiTokensRule", { enumerable: true, get: function () { return no_symbol_di_tokens_1.NoSymbolDiTokensRule; } });
|
|
47
45
|
var branch_creation_guard_1 = require("./core/rules/branch-creation-guard");
|
|
@@ -52,8 +50,8 @@ var merge_in_progress_guard_1 = require("./core/rules/merge-in-progress-guard");
|
|
|
52
50
|
Object.defineProperty(exports, "MergeInProgressGuardRule", { enumerable: true, get: function () { return merge_in_progress_guard_1.MergeInProgressGuardRule; } });
|
|
53
51
|
var pr_merge_cleanup_1 = require("./core/rules/pr-merge-cleanup");
|
|
54
52
|
Object.defineProperty(exports, "PrMergeCleanupRule", { enumerable: true, get: function () { return pr_merge_cleanup_1.PrMergeCleanupRule; } });
|
|
55
|
-
var
|
|
56
|
-
Object.defineProperty(exports, "
|
|
53
|
+
var redirect_how_to_merge_main_1 = require("./core/rules/redirect-how-to-merge-main");
|
|
54
|
+
Object.defineProperty(exports, "RedirectHowToMergeMainRule", { enumerable: true, get: function () { return redirect_how_to_merge_main_1.RedirectHowToMergeMainRule; } });
|
|
57
55
|
var no_js_files_1 = require("./core/rules/no-js-files");
|
|
58
56
|
Object.defineProperty(exports, "NoJsFilesRule", { enumerable: true, get: function () { return no_js_files_1.NoJsFilesRule; } });
|
|
59
57
|
var feature_branch_guard_1 = require("./core/rules/feature-branch-guard");
|
package/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../packages/tooling/ai-hook-rules/src/index.ts"],"names":[],"mappings":";;;AAAA,iEAAiE;AACjE,sCAOsB;AALlB,kGAAA,SAAS,OAAA;AAAE,uGAAA,cAAc,OAAA;AAAE,4GAAA,mBAAmB,OAAA;AAC9C,oGAAA,WAAW,OAAA;AAAE,oGAAA,WAAW,OAAA;AAAE,oGAAA,WAAW,OAAA;AAErC,kGAAA,SAAS,OAAA;AAAE,sGAAA,aAAa,OAAA;AACxB,uGAAA,cAAc,OAAA;AAAE,2GAAA,kBAAkB,OAAA;AAGtC,gGAAgG;AAChG,8CAA6F;AAApF,yGAAA,YAAY,OAAA;AAAE,yGAAA,YAAY,OAAA;AAAE,yGAAA,YAAY,OAAA;AAAE,4GAAA,eAAe,OAAA;AAClE,kEAA+D;AAAtD,wHAAA,iBAAiB,OAAA;AAE1B,+FAA+F;AAC/F,8DAA+D;AAAtD,kHAAA,gBAAgB,OAAA;AACzB,gEAAiE;AAAxD,oHAAA,iBAAiB,OAAA;AAC1B,8DAA+D;AAAtD,kHAAA,gBAAgB,OAAA;AACzB,sEAAsE;AAA7D,yHAAA,mBAAmB,OAAA;AAC5B,8DAAgE;AAAvD,mHAAA,iBAAiB,OAAA;AAC1B,wEAAyE;AAAhE,4HAAA,qBAAqB,OAAA;AAC9B,gFAAiF;AAAxE,oIAAA,yBAAyB,OAAA;AAClC,wEAAyE;AAAhE,4HAAA,qBAAqB,OAAA;AAC9B,0EAA2E;AAAlE,8HAAA,sBAAsB,OAAA;AAC/B,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../packages/tooling/ai-hook-rules/src/index.ts"],"names":[],"mappings":";;;AAAA,iEAAiE;AACjE,sCAOsB;AALlB,kGAAA,SAAS,OAAA;AAAE,uGAAA,cAAc,OAAA;AAAE,4GAAA,mBAAmB,OAAA;AAC9C,oGAAA,WAAW,OAAA;AAAE,oGAAA,WAAW,OAAA;AAAE,oGAAA,WAAW,OAAA;AAErC,kGAAA,SAAS,OAAA;AAAE,sGAAA,aAAa,OAAA;AACxB,uGAAA,cAAc,OAAA;AAAE,2GAAA,kBAAkB,OAAA;AAGtC,gGAAgG;AAChG,8CAA6F;AAApF,yGAAA,YAAY,OAAA;AAAE,yGAAA,YAAY,OAAA;AAAE,yGAAA,YAAY,OAAA;AAAE,4GAAA,eAAe,OAAA;AAClE,kEAA+D;AAAtD,wHAAA,iBAAiB,OAAA;AAE1B,+FAA+F;AAC/F,8DAA+D;AAAtD,kHAAA,gBAAgB,OAAA;AACzB,gEAAiE;AAAxD,oHAAA,iBAAiB,OAAA;AAC1B,8DAA+D;AAAtD,kHAAA,gBAAgB,OAAA;AACzB,sEAAsE;AAA7D,yHAAA,mBAAmB,OAAA;AAC5B,8DAAgE;AAAvD,mHAAA,iBAAiB,OAAA;AAC1B,wEAAyE;AAAhE,4HAAA,qBAAqB,OAAA;AAC9B,gFAAiF;AAAxE,oIAAA,yBAAyB,OAAA;AAClC,wEAAyE;AAAhE,4HAAA,qBAAqB,OAAA;AAC9B,0EAA2E;AAAlE,8HAAA,sBAAsB,OAAA;AAC/B,wEAAwE;AAA/D,2HAAA,oBAAoB,OAAA;AAC7B,4EAA6E;AAApE,gIAAA,uBAAuB,OAAA;AAChC,oEAAqE;AAA5D,wHAAA,mBAAmB,OAAA;AAC5B,gFAAgF;AAAvE,mIAAA,wBAAwB,OAAA;AACjC,kEAAmE;AAA1D,sHAAA,kBAAkB,OAAA;AAC3B,sFAAqF;AAA5E,wIAAA,0BAA0B,OAAA;AACnC,wDAAyD;AAAhD,4GAAA,aAAa,OAAA;AACtB,0EAA2E;AAAlE,8HAAA,sBAAsB,OAAA;AAE/B,wCAAoC;AAA3B,6FAAA,GAAG,OAAA;AACZ,wDAAqD;AAA5C,8GAAA,YAAY,OAAA;AACrB,gEAAkG;AAAzF,qHAAA,eAAe,OAAA;AAAE,oHAAA,cAAc,OAAA;AAAE,0HAAA,oBAAoB,OAAA;AAC9D,wCAA6C;AAApC,sGAAA,YAAY,OAAA","sourcesContent":["// Pluggable write-time validation framework for AI coding agents\nexport {\n ToolKind, RuleScope, RuleOptions, IsLineDisabled,\n Violation, NormalizedEdit, NormalizedToolInput,\n EditContext, FileContext, BashContext,\n Rule, PlainRule,\n RuleGroup, BlockedResult,\n ResolvedConfig, ResolvedRuleConfig,\n} from './core/types';\n\n// Scope-specific rule bases (each extends the shared AbstractRule from @webpieces/rules-config)\nexport { EditRuleBase, FileRuleBase, BashRuleBase, EmptyRuleConfig } from './core/rule-base';\nexport { CustomRuleAdapter } from './core/custom-rule-adapter';\n\n// Built-in rule classes — each constructed with its typed *Config from @webpieces/rules-config\nexport { NoAnyUnknownRule } from './core/rules/no-any-unknown';\nexport { NoImplicitAnyRule } from './core/rules/no-implicit-any';\nexport { MaxFileLinesRule } from './core/rules/max-file-lines';\nexport { ValidateTsInSrcRule } from './core/rules/validate-ts-in-src';\nexport { NoDestructureRule } from './core/rules/no-destructure';\nexport { RequireReturnTypeRule } from './core/rules/require-return-type';\nexport { NoUnmanagedExceptionsRule } from './core/rules/no-unmanaged-exceptions';\nexport { CatchErrorPatternRule } from './core/rules/catch-error-pattern';\nexport { ThrowCauseRequiredRule } from './core/rules/throw-cause-required';\nexport { NoSymbolDiTokensRule } from './core/rules/no-symbol-di-tokens';\nexport { BranchCreationGuardRule } from './core/rules/branch-creation-guard';\nexport { PrCreationGuardRule } from './core/rules/pr-creation-guard';\nexport { MergeInProgressGuardRule } from './core/rules/merge-in-progress-guard';\nexport { PrMergeCleanupRule } from './core/rules/pr-merge-cleanup';\nexport { RedirectHowToMergeMainRule } from './core/rules/redirect-how-to-merge-main';\nexport { NoJsFilesRule } from './core/rules/no-js-files';\nexport { FeatureBranchGuardRule } from './core/rules/feature-branch-guard';\n\nexport { run } from './core/runner';\nexport { stripTsNoise } from './core/strip-ts-noise';\nexport { parseDirectives, DirectiveIndex, createIsLineDisabled } from './core/disable-directives';\nexport { formatReport } from './core/report';\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"no-direct-main-update.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/ai-hook-rules/src/core/rules/no-direct-main-update.ts"],"names":[],"mappings":";;;AAAA,iDAAyC;AAKzC,oCAA0C;AAC1C,4CAA4C;AAE5C,MAAM,QAAQ,GAAsB;IAChC,gNAAgN;CACnN,CAAC;AAEF,MAAM,qBAAqB,GAAa;IACpC,qCAAqC;IACrC,sCAAsC;IACtC,8BAA8B;CACjC,CAAC;AAEF,SAAS,QAAQ,CAAC,CAAS;IACvB,MAAM,GAAG,GAAG,GAAG,CAAC;IAChB,OAAO,CAAC,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,GAAG,CAAC;AACvD,CAAC;AAED,MAAa,sBAAuB,SAAQ,wBAAsC;IAC9E,YAAY,MAAgC,IAAI,KAAK,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAAC,CAAC,CAAC;IAEhF,WAAW,GAAG,0GAA0G,CAAC;IACzH,OAAO,GAAG,QAAQ,CAAC;IAE5B,KAAK,CAAC,GAAgB;QAClB,MAAM,OAAO,GAAG,qBAAqB,CAAC,IAAI,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;QAC/E,IAAI,CAAC,OAAO;YAAE,OAAO,EAAE,CAAC;QAExB,0GAA0G;QAC1G,IAAI,oCAAoC,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;YACzD,OAAO,EAAE,CAAC;QACd,CAAC;QAED,MAAM,aAAa,GAAG,IAAA,wBAAQ,EAAC,iCAAiC,EAAE;YAC9D,GAAG,EAAE,GAAG,CAAC,aAAa;YACtB,QAAQ,EAAE,MAAM;SACnB,CAAC,CAAC,IAAI,EAAE,CAAC;QAEV,IAAI,aAAa,KAAK,MAAM,EAAE,CAAC;YAC3B,OAAO,EAAE,CAAC;QACd,CAAC;QAED,OAAO,CAAC,IAAI,iBAAC,CACT,CAAC,EACD,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EACrB;gBACI,4CAA4C,aAAa,eAAe;gBACxE,4CAA4C;gBAC5C,wCAAwC;gBACxC,sBAAsB;gBACtB,uCAAuC;aAC1C,CAAC,IAAI,CAAC,IAAI,CAAC,CACf,CAAC,CAAC;IACP,CAAC;CACJ;AApCD,wDAoCC","sourcesContent":["import { execSync } from 'child_process';\n\nimport { NoDirectMainUpdateConfig } from '@webpieces/rules-config';\n\nimport type { BashContext, Violation } from '../types';\nimport { Violation as V } from '../types';\nimport { BashRuleBase } from '../rule-base';\n\nconst FIX_HINT: readonly string[] = [\n \"Run 'pnpm wp-git-update' to squash-update from main. This preserves the 3-point fork-point system (fork-point=A, feature-HEAD=B, main-HEAD=C) needed for clean PR diffs. See docs/git-workflow.md for details.\",\n];\n\nconst WRONG_UPDATE_PATTERNS: RegExp[] = [\n /git\\s+merge\\s+(origin\\/main|main)\\b/,\n /git\\s+rebase\\s+(origin\\/main|main)\\b/,\n /git\\s+pull\\s+origin\\s+main\\b/,\n];\n\nfunction truncate(s: string): string {\n const MAX = 120;\n return s.length <= MAX ? s : s.slice(0, MAX) + '…';\n}\n\nexport class NoDirectMainUpdateRule extends BashRuleBase<NoDirectMainUpdateConfig> {\n constructor(config: NoDirectMainUpdateConfig) { super(config, 'no-direct-main-update'); }\n\n readonly description = 'Block direct git merge/rebase/pull from main on feature branches. Use the squash-update process instead.';\n readonly fixHint = FIX_HINT;\n\n check(ctx: BashContext): readonly Violation[] {\n const matched = WRONG_UPDATE_PATTERNS.some((p: RegExp) => p.test(ctx.command));\n if (!matched) return [];\n\n // Allow 'git checkout main && git pull origin main' — switching to main first is the recommended workflow\n if (/git\\s+(?:checkout|switch)\\s+main\\b/.test(ctx.command)) {\n return [];\n }\n\n const currentBranch = execSync('git rev-parse --abbrev-ref HEAD', {\n cwd: ctx.workspaceRoot,\n encoding: 'utf8',\n }).trim();\n\n if (currentBranch === 'main') {\n return [];\n }\n\n return [new V(\n 1,\n truncate(ctx.command),\n [\n `Direct merge/rebase from main on branch '${currentBranch}' is blocked.`,\n 'This breaks the 3-point fork-point system.',\n 'Use the squash-update process instead:',\n ' pnpm wp-git-update',\n 'See docs/git-workflow.md for details.',\n ].join('\\n'),\n )];\n }\n}\n"]}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { NoShellSubstitutionConfig } from '@webpieces/rules-config';
|
|
2
|
-
import type { BashContext, Violation } from '../types';
|
|
3
|
-
import { BashRuleBase } from '../rule-base';
|
|
4
|
-
export declare class NoShellSubstitutionRule extends BashRuleBase<NoShellSubstitutionConfig> {
|
|
5
|
-
constructor(config: NoShellSubstitutionConfig);
|
|
6
|
-
readonly description = "Reject Bash commands containing shell substitutions ($(...), backticks, $VAR).";
|
|
7
|
-
readonly fixHint: readonly string[];
|
|
8
|
-
check(ctx: BashContext): readonly Violation[];
|
|
9
|
-
}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.NoShellSubstitutionRule = void 0;
|
|
4
|
-
const types_1 = require("../types");
|
|
5
|
-
const rule_base_1 = require("../rule-base");
|
|
6
|
-
const FIX_HINT = [
|
|
7
|
-
'Build a payload file with the Write tool and pass it as stdin: node script.js < /path/to/payload.json',
|
|
8
|
-
'Use the Read, Grep, or Glob tools directly instead of capturing output with $(...)',
|
|
9
|
-
'Write a small script file with the Write tool and execute it directly: bash /path/to/script.sh',
|
|
10
|
-
];
|
|
11
|
-
function stripSingleQuoted(cmd) {
|
|
12
|
-
return cmd.replace(/'[^']*'/g, "''");
|
|
13
|
-
}
|
|
14
|
-
function hasUnescapedBacktick(cmd) {
|
|
15
|
-
for (let i = 0; i < cmd.length; i += 1) {
|
|
16
|
-
if (cmd[i] === '`' && (i === 0 || cmd[i - 1] !== '\\'))
|
|
17
|
-
return true;
|
|
18
|
-
}
|
|
19
|
-
return false;
|
|
20
|
-
}
|
|
21
|
-
function hasBareVarExpansion(cmd) {
|
|
22
|
-
const re = /(^|[^\\])\$([A-Za-z_][A-Za-z0-9_]*)/g;
|
|
23
|
-
return re.test(cmd);
|
|
24
|
-
}
|
|
25
|
-
function truncate(s) {
|
|
26
|
-
const MAX = 120;
|
|
27
|
-
if (s.length <= MAX)
|
|
28
|
-
return s;
|
|
29
|
-
return s.slice(0, MAX) + '…';
|
|
30
|
-
}
|
|
31
|
-
class NoShellSubstitutionRule extends rule_base_1.BashRuleBase {
|
|
32
|
-
constructor(config) { super(config, 'no-shell-substitution'); }
|
|
33
|
-
description = 'Reject Bash commands containing shell substitutions ($(...), backticks, $VAR).';
|
|
34
|
-
fixHint = FIX_HINT;
|
|
35
|
-
check(ctx) {
|
|
36
|
-
const scanned = stripSingleQuoted(ctx.command);
|
|
37
|
-
const violations = [];
|
|
38
|
-
if (/\$\(/.test(scanned)) {
|
|
39
|
-
violations.push(new types_1.Violation(1, truncate(ctx.command), 'Command contains `$(...)` command substitution.'));
|
|
40
|
-
}
|
|
41
|
-
if (hasUnescapedBacktick(scanned)) {
|
|
42
|
-
violations.push(new types_1.Violation(1, truncate(ctx.command), 'Command contains backtick command substitution.'));
|
|
43
|
-
}
|
|
44
|
-
if (/\$\{[A-Za-z_][A-Za-z0-9_]*\}/.test(scanned) || hasBareVarExpansion(scanned)) {
|
|
45
|
-
violations.push(new types_1.Violation(1, truncate(ctx.command), 'Command contains `$VAR` or `${VAR}` variable expansion.'));
|
|
46
|
-
}
|
|
47
|
-
return violations;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
exports.NoShellSubstitutionRule = NoShellSubstitutionRule;
|
|
51
|
-
//# sourceMappingURL=no-shell-substitution.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"no-shell-substitution.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/ai-hook-rules/src/core/rules/no-shell-substitution.ts"],"names":[],"mappings":";;;AAGA,oCAA0C;AAC1C,4CAA4C;AAE5C,MAAM,QAAQ,GAAsB;IAChC,uGAAuG;IACvG,oFAAoF;IACpF,gGAAgG;CACnG,CAAC;AAEF,SAAS,iBAAiB,CAAC,GAAW;IAClC,OAAO,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;AACzC,CAAC;AAED,SAAS,oBAAoB,CAAC,GAAW;IACrC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACrC,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;IACxE,CAAC;IACD,OAAO,KAAK,CAAC;AACjB,CAAC;AAED,SAAS,mBAAmB,CAAC,GAAW;IACpC,MAAM,EAAE,GAAG,sCAAsC,CAAC;IAClD,OAAO,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACxB,CAAC;AAED,SAAS,QAAQ,CAAC,CAAS;IACvB,MAAM,GAAG,GAAG,GAAG,CAAC;IAChB,IAAI,CAAC,CAAC,MAAM,IAAI,GAAG;QAAE,OAAO,CAAC,CAAC;IAC9B,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,GAAG,CAAC;AACjC,CAAC;AAED,MAAa,uBAAwB,SAAQ,wBAAuC;IAChF,YAAY,MAAiC,IAAI,KAAK,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAAC,CAAC,CAAC;IAEjF,WAAW,GAAG,gFAAgF,CAAC;IAC/F,OAAO,GAAG,QAAQ,CAAC;IAE5B,KAAK,CAAC,GAAgB;QAClB,MAAM,OAAO,GAAG,iBAAiB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC/C,MAAM,UAAU,GAAgB,EAAE,CAAC;QAEnC,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YACvB,UAAU,CAAC,IAAI,CAAC,IAAI,iBAAC,CACjB,CAAC,EACD,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EACrB,iDAAiD,CACpD,CAAC,CAAC;QACP,CAAC;QACD,IAAI,oBAAoB,CAAC,OAAO,CAAC,EAAE,CAAC;YAChC,UAAU,CAAC,IAAI,CAAC,IAAI,iBAAC,CACjB,CAAC,EACD,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EACrB,iDAAiD,CACpD,CAAC,CAAC;QACP,CAAC;QACD,IAAI,8BAA8B,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,mBAAmB,CAAC,OAAO,CAAC,EAAE,CAAC;YAC/E,UAAU,CAAC,IAAI,CAAC,IAAI,iBAAC,CACjB,CAAC,EACD,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EACrB,yDAAyD,CAC5D,CAAC,CAAC;QACP,CAAC;QACD,OAAO,UAAU,CAAC;IACtB,CAAC;CACJ;AAjCD,0DAiCC","sourcesContent":["import { NoShellSubstitutionConfig } from '@webpieces/rules-config';\n\nimport type { BashContext, Violation } from '../types';\nimport { Violation as V } from '../types';\nimport { BashRuleBase } from '../rule-base';\n\nconst FIX_HINT: readonly string[] = [\n 'Build a payload file with the Write tool and pass it as stdin: node script.js < /path/to/payload.json',\n 'Use the Read, Grep, or Glob tools directly instead of capturing output with $(...)',\n 'Write a small script file with the Write tool and execute it directly: bash /path/to/script.sh',\n];\n\nfunction stripSingleQuoted(cmd: string): string {\n return cmd.replace(/'[^']*'/g, \"''\");\n}\n\nfunction hasUnescapedBacktick(cmd: string): boolean {\n for (let i = 0; i < cmd.length; i += 1) {\n if (cmd[i] === '`' && (i === 0 || cmd[i - 1] !== '\\\\')) return true;\n }\n return false;\n}\n\nfunction hasBareVarExpansion(cmd: string): boolean {\n const re = /(^|[^\\\\])\\$([A-Za-z_][A-Za-z0-9_]*)/g;\n return re.test(cmd);\n}\n\nfunction truncate(s: string): string {\n const MAX = 120;\n if (s.length <= MAX) return s;\n return s.slice(0, MAX) + '…';\n}\n\nexport class NoShellSubstitutionRule extends BashRuleBase<NoShellSubstitutionConfig> {\n constructor(config: NoShellSubstitutionConfig) { super(config, 'no-shell-substitution'); }\n\n readonly description = 'Reject Bash commands containing shell substitutions ($(...), backticks, $VAR).';\n readonly fixHint = FIX_HINT;\n\n check(ctx: BashContext): readonly Violation[] {\n const scanned = stripSingleQuoted(ctx.command);\n const violations: Violation[] = [];\n\n if (/\\$\\(/.test(scanned)) {\n violations.push(new V(\n 1,\n truncate(ctx.command),\n 'Command contains `$(...)` command substitution.',\n ));\n }\n if (hasUnescapedBacktick(scanned)) {\n violations.push(new V(\n 1,\n truncate(ctx.command),\n 'Command contains backtick command substitution.',\n ));\n }\n if (/\\$\\{[A-Za-z_][A-Za-z0-9_]*\\}/.test(scanned) || hasBareVarExpansion(scanned)) {\n violations.push(new V(\n 1,\n truncate(ctx.command),\n 'Command contains `$VAR` or `${VAR}` variable expansion.',\n ));\n }\n return violations;\n }\n}\n"]}
|