@hongmaple0820/scale-engine 0.40.2 → 0.43.0

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 (200) hide show
  1. package/README.md +30 -2
  2. package/dist/api/cli.js +19 -0
  3. package/dist/api/cli.js.map +1 -1
  4. package/dist/api/quickstart.d.ts +11 -0
  5. package/dist/api/quickstart.js +98 -1
  6. package/dist/api/quickstart.js.map +1 -1
  7. package/dist/artifact/fsmDefinitions.js +15 -2
  8. package/dist/artifact/fsmDefinitions.js.map +1 -1
  9. package/dist/artifact/types.d.ts +1 -1
  10. package/dist/artifact/types.js.map +1 -1
  11. package/dist/cache/ScanCache.d.ts +41 -0
  12. package/dist/cache/ScanCache.js +120 -0
  13. package/dist/cache/ScanCache.js.map +1 -0
  14. package/dist/capabilities/BrowserQACapability.d.ts +14 -0
  15. package/dist/capabilities/BrowserQACapability.js +94 -0
  16. package/dist/capabilities/BrowserQACapability.js.map +1 -1
  17. package/dist/cli/autofixCommands.d.ts +22 -0
  18. package/dist/cli/autofixCommands.js +32 -0
  19. package/dist/cli/autofixCommands.js.map +1 -0
  20. package/dist/cli/cortexCommands.d.ts +71 -0
  21. package/dist/cli/cortexCommands.js +335 -0
  22. package/dist/cli/cortexCommands.js.map +1 -0
  23. package/dist/cli/costCommands.d.ts +13 -0
  24. package/dist/cli/costCommands.js +48 -0
  25. package/dist/cli/costCommands.js.map +1 -0
  26. package/dist/cli/orchCommands.d.ts +43 -0
  27. package/dist/cli/orchCommands.js +135 -0
  28. package/dist/cli/orchCommands.js.map +1 -0
  29. package/dist/cli/phaseCommands.js +1 -2
  30. package/dist/cli/phaseCommands.js.map +1 -1
  31. package/dist/cli/qaCommands.d.ts +22 -0
  32. package/dist/cli/qaCommands.js +84 -0
  33. package/dist/cli/qaCommands.js.map +1 -0
  34. package/dist/cli/quickstartCommands.d.ts +17 -0
  35. package/dist/cli/quickstartCommands.js +47 -0
  36. package/dist/cli/quickstartCommands.js.map +1 -0
  37. package/dist/cli/shieldCommands.d.ts +30 -0
  38. package/dist/cli/shieldCommands.js +212 -0
  39. package/dist/cli/shieldCommands.js.map +1 -0
  40. package/dist/cli/tuiCommands.d.ts +7 -0
  41. package/dist/cli/tuiCommands.js +33 -0
  42. package/dist/cli/tuiCommands.js.map +1 -0
  43. package/dist/config/profiles.js +26 -0
  44. package/dist/config/profiles.js.map +1 -1
  45. package/dist/cortex/GovernanceMetrics.d.ts +66 -0
  46. package/dist/cortex/GovernanceMetrics.js +230 -0
  47. package/dist/cortex/GovernanceMetrics.js.map +1 -0
  48. package/dist/cortex/InstinctExtractor.d.ts +61 -0
  49. package/dist/cortex/InstinctExtractor.js +184 -0
  50. package/dist/cortex/InstinctExtractor.js.map +1 -0
  51. package/dist/cortex/InstinctStore.d.ts +54 -0
  52. package/dist/cortex/InstinctStore.js +266 -0
  53. package/dist/cortex/InstinctStore.js.map +1 -0
  54. package/dist/cortex/ReflexionEngine.d.ts +34 -0
  55. package/dist/cortex/ReflexionEngine.js +157 -0
  56. package/dist/cortex/ReflexionEngine.js.map +1 -0
  57. package/dist/cortex/SessionInjector.d.ts +44 -0
  58. package/dist/cortex/SessionInjector.js +127 -0
  59. package/dist/cortex/SessionInjector.js.map +1 -0
  60. package/dist/cortex/adapters/ClaudeAdapter.d.ts +17 -0
  61. package/dist/cortex/adapters/ClaudeAdapter.js +61 -0
  62. package/dist/cortex/adapters/ClaudeAdapter.js.map +1 -0
  63. package/dist/cortex/adapters/CodexAdapter.d.ts +10 -0
  64. package/dist/cortex/adapters/CodexAdapter.js +52 -0
  65. package/dist/cortex/adapters/CodexAdapter.js.map +1 -0
  66. package/dist/cortex/adapters/CursorAdapter.d.ts +10 -0
  67. package/dist/cortex/adapters/CursorAdapter.js +46 -0
  68. package/dist/cortex/adapters/CursorAdapter.js.map +1 -0
  69. package/dist/cortex/adapters/GeminiAdapter.d.ts +11 -0
  70. package/dist/cortex/adapters/GeminiAdapter.js +48 -0
  71. package/dist/cortex/adapters/GeminiAdapter.js.map +1 -0
  72. package/dist/eval/BenchmarkPublisher.d.ts +25 -0
  73. package/dist/eval/BenchmarkPublisher.js +27 -0
  74. package/dist/eval/BenchmarkPublisher.js.map +1 -0
  75. package/dist/guardrails/DependencyAuditor.js +10 -1
  76. package/dist/guardrails/DependencyAuditor.js.map +1 -1
  77. package/dist/orchestrator/OrchestratorDaemon.d.ts +44 -0
  78. package/dist/orchestrator/OrchestratorDaemon.js +150 -0
  79. package/dist/orchestrator/OrchestratorDaemon.js.map +1 -0
  80. package/dist/orchestrator/PolicyLoader.d.ts +80 -0
  81. package/dist/orchestrator/PolicyLoader.js +229 -0
  82. package/dist/orchestrator/PolicyLoader.js.map +1 -0
  83. package/dist/orchestrator/ReconciliationLoop.d.ts +71 -0
  84. package/dist/orchestrator/ReconciliationLoop.js +266 -0
  85. package/dist/orchestrator/ReconciliationLoop.js.map +1 -0
  86. package/dist/orchestrator/TrackerAdapter.d.ts +60 -0
  87. package/dist/orchestrator/TrackerAdapter.js +147 -0
  88. package/dist/orchestrator/TrackerAdapter.js.map +1 -0
  89. package/dist/orchestrator/WorkspaceManager.d.ts +66 -0
  90. package/dist/orchestrator/WorkspaceManager.js +257 -0
  91. package/dist/orchestrator/WorkspaceManager.js.map +1 -0
  92. package/dist/qa/BrowserDaemon.d.ts +23 -0
  93. package/dist/qa/BrowserDaemon.js +79 -0
  94. package/dist/qa/BrowserDaemon.js.map +1 -0
  95. package/dist/qa/E2ETestOrchestrator.d.ts +14 -0
  96. package/dist/qa/E2ETestOrchestrator.js +19 -0
  97. package/dist/qa/E2ETestOrchestrator.js.map +1 -0
  98. package/dist/review/CrossModelReviewer.d.ts +35 -0
  99. package/dist/review/CrossModelReviewer.js +75 -0
  100. package/dist/review/CrossModelReviewer.js.map +1 -0
  101. package/dist/review/ReviewAggregator.d.ts +13 -0
  102. package/dist/review/ReviewAggregator.js +28 -0
  103. package/dist/review/ReviewAggregator.js.map +1 -0
  104. package/dist/review/reviewCommands.d.ts +15 -0
  105. package/dist/review/reviewCommands.js +24 -0
  106. package/dist/review/reviewCommands.js.map +1 -0
  107. package/dist/routing/LocalModelProvider.d.ts +11 -0
  108. package/dist/routing/LocalModelProvider.js +21 -0
  109. package/dist/routing/LocalModelProvider.js.map +1 -0
  110. package/dist/routing/ModelRouter.d.ts +12 -0
  111. package/dist/routing/ModelRouter.js +31 -4
  112. package/dist/routing/ModelRouter.js.map +1 -1
  113. package/dist/runtime/AiOsRuntime.d.ts +1 -0
  114. package/dist/runtime/AiOsRuntime.js +15 -0
  115. package/dist/runtime/AiOsRuntime.js.map +1 -1
  116. package/dist/runtime/CostAnalyzer.d.ts +53 -0
  117. package/dist/runtime/CostAnalyzer.js +160 -0
  118. package/dist/runtime/CostAnalyzer.js.map +1 -0
  119. package/dist/runtime/CostOptimizer.d.ts +11 -0
  120. package/dist/runtime/CostOptimizer.js +21 -0
  121. package/dist/runtime/CostOptimizer.js.map +1 -0
  122. package/dist/shield/PolicyCompiler.d.ts +70 -0
  123. package/dist/shield/PolicyCompiler.js +540 -0
  124. package/dist/shield/PolicyCompiler.js.map +1 -0
  125. package/dist/shield/ProtectedPaths.d.ts +39 -0
  126. package/dist/shield/ProtectedPaths.js +179 -0
  127. package/dist/shield/ProtectedPaths.js.map +1 -0
  128. package/dist/shield/ShieldProtocol.d.ts +50 -0
  129. package/dist/shield/ShieldProtocol.js +103 -0
  130. package/dist/shield/ShieldProtocol.js.map +1 -0
  131. package/dist/skills/SkillMdStandard.d.ts +33 -0
  132. package/dist/skills/SkillMdStandard.js +88 -0
  133. package/dist/skills/SkillMdStandard.js.map +1 -0
  134. package/dist/skills/SkillRegistry.d.ts +9 -1
  135. package/dist/skills/SkillRegistry.js +20 -0
  136. package/dist/skills/SkillRegistry.js.map +1 -1
  137. package/dist/skills/interop/GStackInterop.d.ts +15 -0
  138. package/dist/skills/interop/GStackInterop.js +34 -0
  139. package/dist/skills/interop/GStackInterop.js.map +1 -0
  140. package/dist/skills/interop/OMCInterop.d.ts +15 -0
  141. package/dist/skills/interop/OMCInterop.js +34 -0
  142. package/dist/skills/interop/OMCInterop.js.map +1 -0
  143. package/dist/tui/TuiDashboard.d.ts +3 -0
  144. package/dist/tui/TuiDashboard.js +120 -0
  145. package/dist/tui/TuiDashboard.js.map +1 -0
  146. package/dist/workflow/GateCatalog.d.ts +2 -0
  147. package/dist/workflow/GateCatalog.js +59 -3
  148. package/dist/workflow/GateCatalog.js.map +1 -1
  149. package/dist/workflow/GovernanceTemplatePacks.d.ts +1 -1
  150. package/dist/workflow/GovernanceTemplatePacks.js +15 -0
  151. package/dist/workflow/GovernanceTemplatePacks.js.map +1 -1
  152. package/dist/workflow/TddLoop.d.ts +2 -0
  153. package/dist/workflow/TddLoop.js +2 -0
  154. package/dist/workflow/TddLoop.js.map +1 -1
  155. package/dist/workflow/UpgradeManager.d.ts +10 -1
  156. package/dist/workflow/UpgradeManager.js +55 -0
  157. package/dist/workflow/UpgradeManager.js.map +1 -1
  158. package/dist/workflow/VerificationProfile.d.ts +8 -0
  159. package/dist/workflow/VerificationProfile.js +61 -0
  160. package/dist/workflow/VerificationProfile.js.map +1 -1
  161. package/dist/workflow/VerificationSchema.d.ts +46 -0
  162. package/dist/workflow/VerificationSchema.js +97 -0
  163. package/dist/workflow/VerificationSchema.js.map +1 -0
  164. package/dist/workflow/autofix/AutoFixEngine.d.ts +37 -0
  165. package/dist/workflow/autofix/AutoFixEngine.js +169 -0
  166. package/dist/workflow/autofix/AutoFixEngine.js.map +1 -0
  167. package/dist/workflow/execution/RalphEngine.d.ts +18 -0
  168. package/dist/workflow/execution/RalphEngine.js +22 -0
  169. package/dist/workflow/execution/RalphEngine.js.map +1 -1
  170. package/dist/workflow/gates/EnhancedGates.d.ts +74 -0
  171. package/dist/workflow/gates/EnhancedGates.js +653 -0
  172. package/dist/workflow/gates/EnhancedGates.js.map +1 -0
  173. package/dist/workflow/gates/GateSystem.d.ts +3 -0
  174. package/dist/workflow/gates/GateSystem.js +94 -1
  175. package/dist/workflow/gates/GateSystem.js.map +1 -1
  176. package/dist/workflow/types.d.ts +1 -1
  177. package/docs/README.md +3 -0
  178. package/docs/guides/DEVELOPMENT_WORKFLOW.md +28 -9
  179. package/docs/guides/GETTING_STARTED.md +19 -0
  180. package/docs/guides/MIGRATION.md +119 -0
  181. package/docs/workflow/GATES_AND_SCORE.md +34 -1
  182. package/docs/workflow/README.md +58 -10
  183. package/package.json +5 -17
  184. package/docs/ACTIVE_SECURITY_VISUAL_GATES.md +0 -87
  185. package/docs/AI_ENGINEERING_OS_POSITIONING.md +0 -607
  186. package/docs/BACKGROUND_HUNTER.md +0 -62
  187. package/docs/CODE_INTELLIGENCE.md +0 -180
  188. package/docs/CONTEXT_BUDGET.md +0 -165
  189. package/docs/DEPENDENCY_AUDIT.md +0 -118
  190. package/docs/EVOLUTION_SHADOW_MODE.md +0 -63
  191. package/docs/GITLAB_FLOW.md +0 -125
  192. package/docs/GOVERNANCE_DASHBOARD.md +0 -92
  193. package/docs/MEMORY_BRAIN.md +0 -104
  194. package/docs/MEMORY_FABRIC.md +0 -161
  195. package/docs/RESOURCE_GOVERNANCE.md +0 -92
  196. package/docs/RUNTIME_EVIDENCE.md +0 -101
  197. package/docs/WORKFLOW_EVAL.md +0 -151
  198. package/image/wechat-public.jpg +0 -0
  199. package/image/wxPay.jpg +0 -0
  200. package/image/zfb.jpg +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CostOptimizer.js","sourceRoot":"","sources":["../../src/runtime/CostOptimizer.ts"],"names":[],"mappings":"AAYA,MAAM,UAAU,uBAAuB,CAAC,WAAqC;IAC3E,MAAM,YAAY,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,uBAAuB,EAAE,CAAC,CAAC,CAAA;IACvF,MAAM,QAAQ,GAAG,WAAW;SACzB,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACT,UAAU,EAAE,CAAC;QACb,MAAM,EAAE,CAAC,CAAC,QAAQ,KAAK,mBAAmB,CAAC,CAAC,CAAC,KAAc,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,KAAK,iBAAiB,CAAC,CAAC,CAAC,KAAc,CAAC,CAAC,CAAC,QAAiB;QACnI,WAAW,EAAE,CAAC,CAAC,uBAAuB,GAAG,CAAC,CAAC,CAAC,CAAC,MAAe,CAAC,CAAC,CAAC,CAAC,CAAC,uBAAuB,GAAG,GAAG,CAAC,CAAC,CAAC,QAAiB,CAAC,CAAC,CAAC,KAAc;KACpI,CAAC,CAAC;SACF,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACb,MAAM,WAAW,GAAG,EAAE,GAAG,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAA;QAClD,MAAM,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,uBAAuB,GAAG,IAAI,CAAC,CAAC,CAAA;QAChH,MAAM,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,uBAAuB,GAAG,IAAI,CAAC,CAAC,CAAA;QAChH,OAAO,MAAM,GAAG,MAAM,CAAA;IACxB,CAAC,CAAC,CAAA;IAEJ,OAAO;QACL,WAAW;QACX,qBAAqB,EAAE,YAAY;QACnC,sBAAsB,EAAE,QAAQ;KACjC,CAAA;AACH,CAAC"}
@@ -0,0 +1,70 @@
1
+ export interface ShieldPolicy {
2
+ version: number;
3
+ rules: ShieldPolicyRule[];
4
+ settings?: {
5
+ blockMode?: 'strict' | 'warn';
6
+ hookStateDir?: string;
7
+ notifyOnBlock?: boolean;
8
+ };
9
+ }
10
+ export interface ShieldPolicyRule {
11
+ id: string;
12
+ description: string;
13
+ hookType: 'PreToolUse' | 'PostToolUse' | 'Stop' | 'SessionStart';
14
+ matcher: string;
15
+ action: 'block' | 'warn' | 'allow';
16
+ conditions: ShieldCondition[];
17
+ }
18
+ export interface ShieldCondition {
19
+ type: 'protected_path' | 'dangerous_command' | 'gate_required' | 'secret_pattern' | 'file_size' | 'custom';
20
+ pattern?: string;
21
+ value?: string | number;
22
+ message: string;
23
+ }
24
+ export interface CompiledHook {
25
+ fileName: string;
26
+ hookType: string;
27
+ matcher: string;
28
+ scriptPath: string;
29
+ hash: string;
30
+ }
31
+ export interface CompilerOutput {
32
+ hooks: CompiledHook[];
33
+ settingsPatches: {
34
+ claude: string;
35
+ codex: string;
36
+ cursor: string;
37
+ };
38
+ policyHash: string;
39
+ }
40
+ export declare class PolicyCompiler {
41
+ /**
42
+ * Load policy from .scale/policy.yaml. Returns default if file missing or invalid.
43
+ */
44
+ loadPolicy(projectDir: string): ShieldPolicy;
45
+ /**
46
+ * Minimal YAML parser for policy frontmatter.
47
+ * Handles the subset of YAML needed for policy rules.
48
+ */
49
+ parseYamlPolicy(raw: string): ShieldPolicy;
50
+ /**
51
+ * Compile policy into hook scripts.
52
+ */
53
+ compile(projectDir: string): CompilerOutput;
54
+ /**
55
+ * Write hook registrations to settings.json files for each harness.
56
+ */
57
+ writeSettingsPatches(output: CompilerOutput): void;
58
+ /**
59
+ * Verify compiled hooks match current policy (anti-tamper check).
60
+ */
61
+ verify(projectDir: string): {
62
+ valid: boolean;
63
+ mismatches: string[];
64
+ };
65
+ private compileRule;
66
+ private generateHookScript;
67
+ private generateCombinedPreToolScript;
68
+ private patchClaudeSettings;
69
+ private patchHarnessSettings;
70
+ }
@@ -0,0 +1,540 @@
1
+ // SCALE Shield — Policy Compiler
2
+ // 对齐 agent-hooks-in-depth: YAML 声明式策略 → 运行时 hook 脚本
3
+ // 输出 JS hook 脚本注入到 Claude/Codex/Cursor settings.json
4
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
5
+ import { join } from 'node:path';
6
+ import { createHash } from 'node:crypto';
7
+ import { logger } from '../core/logger.js';
8
+ // ---------------------------------------------------------------------------
9
+ // Default policy
10
+ // ---------------------------------------------------------------------------
11
+ const DEFAULT_POLICY = {
12
+ version: 1,
13
+ rules: [
14
+ {
15
+ id: 'protect-scale-dir',
16
+ description: 'Protect .scale/ governance infrastructure from unauthorized modification',
17
+ hookType: 'PreToolUse',
18
+ matcher: 'Write|Edit',
19
+ action: 'block',
20
+ conditions: [
21
+ { type: 'protected_path', pattern: '.scale/', message: 'Modifying .scale/ governance files is blocked' },
22
+ ],
23
+ },
24
+ {
25
+ id: 'block-dangerous-commands',
26
+ description: 'Block dangerous shell commands: rm -rf, DROP TABLE, force push, curl-pipe-bash',
27
+ hookType: 'PreToolUse',
28
+ matcher: 'Bash',
29
+ action: 'block',
30
+ conditions: [
31
+ { type: 'dangerous_command', message: 'Dangerous command detected' },
32
+ ],
33
+ },
34
+ {
35
+ id: 'require-gate-quality',
36
+ description: 'Block git commits without passing gate-quality checks',
37
+ hookType: 'PreToolUse',
38
+ matcher: 'Bash',
39
+ action: 'block',
40
+ conditions: [
41
+ { type: 'gate_required', pattern: 'git commit', message: 'Gate quality must pass before commit' },
42
+ ],
43
+ },
44
+ {
45
+ id: 'block-secret-exposure',
46
+ description: 'Block commands that may expose secrets (cat .env, echo $API_KEY)',
47
+ hookType: 'PreToolUse',
48
+ matcher: 'Bash',
49
+ action: 'block',
50
+ conditions: [
51
+ { type: 'secret_pattern', message: 'Potential secret exposure detected' },
52
+ ],
53
+ },
54
+ {
55
+ id: 'prevent-hook-bypass',
56
+ description: 'Block attempts to skip hooks or bypass governance',
57
+ hookType: 'PreToolUse',
58
+ matcher: 'Bash',
59
+ action: 'block',
60
+ conditions: [
61
+ { type: 'custom', pattern: '(--no-verify|--no-gpg-sign|SKIP_HOOKS|bypass|dang[eo]rously)', message: 'Governance bypass attempt blocked' },
62
+ ],
63
+ },
64
+ ],
65
+ settings: {
66
+ blockMode: 'strict',
67
+ hookStateDir: '.hook-state',
68
+ notifyOnBlock: true,
69
+ },
70
+ };
71
+ // ---------------------------------------------------------------------------
72
+ // PolicyCompiler
73
+ // ---------------------------------------------------------------------------
74
+ export class PolicyCompiler {
75
+ /**
76
+ * Load policy from .scale/policy.yaml. Returns default if file missing or invalid.
77
+ */
78
+ loadPolicy(projectDir) {
79
+ const policyPath = join(projectDir, '.scale', 'policy.yaml');
80
+ if (!existsSync(policyPath)) {
81
+ logger.warn('No .scale/policy.yaml found, using default policy');
82
+ return { ...DEFAULT_POLICY };
83
+ }
84
+ try {
85
+ const raw = readFileSync(policyPath, 'utf-8');
86
+ return this.parseYamlPolicy(raw);
87
+ }
88
+ catch (err) {
89
+ logger.warn({ err }, 'Failed to read policy.yaml, using default policy');
90
+ return { ...DEFAULT_POLICY };
91
+ }
92
+ }
93
+ /**
94
+ * Minimal YAML parser for policy frontmatter.
95
+ * Handles the subset of YAML needed for policy rules.
96
+ */
97
+ parseYamlPolicy(raw) {
98
+ const policy = { version: 1, rules: [] };
99
+ const lines = raw.split('\n');
100
+ let currentRule = null;
101
+ let inRules = false;
102
+ let inConditions = false;
103
+ for (const line of lines) {
104
+ const trimmed = line.trim();
105
+ if (!trimmed || trimmed.startsWith('#'))
106
+ continue;
107
+ // Top-level keys
108
+ if (trimmed.startsWith('version:')) {
109
+ policy.version = parseInt(trimmed.split(':')[1]?.trim() ?? '1', 10) || 1;
110
+ continue;
111
+ }
112
+ if (trimmed.startsWith('blockMode:') || trimmed.startsWith('block_mode:')) {
113
+ policy.settings ??= {};
114
+ policy.settings.blockMode = trimmed.split(':')[1]?.trim() ?? 'strict';
115
+ continue;
116
+ }
117
+ if (trimmed === 'rules:') {
118
+ inRules = true;
119
+ continue;
120
+ }
121
+ if (!inRules)
122
+ continue;
123
+ // Rule entry
124
+ if (trimmed.startsWith('- id:')) {
125
+ if (currentRule && currentRule.id) {
126
+ policy.rules.push(currentRule);
127
+ }
128
+ currentRule = { id: trimmed.split(':')[1]?.trim() ?? '', conditions: [], description: '', hookType: 'PreToolUse', matcher: '', action: 'block' };
129
+ inConditions = false;
130
+ continue;
131
+ }
132
+ if (!currentRule)
133
+ continue;
134
+ if (trimmed.startsWith('description:')) {
135
+ currentRule.description = trimmed.split(':').slice(1).join(':').trim();
136
+ continue;
137
+ }
138
+ if (trimmed.startsWith('hookType:') || trimmed.startsWith('hook_type:')) {
139
+ currentRule.hookType = trimmed.split(':')[1]?.trim() ?? 'PreToolUse';
140
+ continue;
141
+ }
142
+ if (trimmed.startsWith('matcher:')) {
143
+ currentRule.matcher = trimmed.split(':')[1]?.trim() ?? '';
144
+ continue;
145
+ }
146
+ if (trimmed.startsWith('action:')) {
147
+ currentRule.action = trimmed.split(':')[1]?.trim() ?? 'block';
148
+ continue;
149
+ }
150
+ if (trimmed === 'conditions:') {
151
+ inConditions = true;
152
+ continue;
153
+ }
154
+ if (inConditions && trimmed.startsWith('- type:')) {
155
+ const cond = {
156
+ type: trimmed.split(':')[1]?.trim() ?? 'custom',
157
+ message: '',
158
+ };
159
+ currentRule.conditions.push(cond);
160
+ }
161
+ }
162
+ // Flush last rule
163
+ if (currentRule && currentRule.id) {
164
+ policy.rules.push(currentRule);
165
+ }
166
+ // Fallback to default rules if parsing yielded nothing
167
+ if (policy.rules.length === 0) {
168
+ logger.warn('Policy YAML parsed but no rules found, using defaults');
169
+ return { ...DEFAULT_POLICY, version: policy.version, settings: policy.settings };
170
+ }
171
+ return policy;
172
+ }
173
+ /**
174
+ * Compile policy into hook scripts.
175
+ */
176
+ compile(projectDir) {
177
+ const policy = this.loadPolicy(projectDir);
178
+ const hooksDir = join(projectDir, '.claude', 'hooks');
179
+ if (!existsSync(hooksDir))
180
+ mkdirSync(hooksDir, { recursive: true });
181
+ const policyHash = createHash('sha256')
182
+ .update(JSON.stringify(policy))
183
+ .digest('hex')
184
+ .slice(0, 12);
185
+ const compiled = [];
186
+ for (const rule of policy.rules) {
187
+ const hook = this.compileRule(rule, hooksDir, policyHash);
188
+ compiled.push(hook);
189
+ writeFileSync(hook.scriptPath, this.generateHookScript(rule, policy), 'utf-8');
190
+ }
191
+ // Always generate a combined pre-tool hook for runtime efficiency
192
+ const combinedPath = join(hooksDir, 'shield-pre-tool.js');
193
+ const combinedScript = this.generateCombinedPreToolScript(policy);
194
+ writeFileSync(combinedPath, combinedScript, 'utf-8');
195
+ compiled.push({
196
+ fileName: 'shield-pre-tool.js',
197
+ hookType: 'PreToolUse',
198
+ matcher: '',
199
+ scriptPath: combinedPath,
200
+ hash: policyHash,
201
+ });
202
+ logger.info({ count: compiled.length, policyHash }, 'Shield policy compiled');
203
+ return {
204
+ hooks: compiled,
205
+ settingsPatches: {
206
+ claude: join(projectDir, '.claude', 'settings.json'),
207
+ codex: join(projectDir, '.codex', 'hooks.json'),
208
+ cursor: join(projectDir, '.cursor', 'hooks.json'),
209
+ },
210
+ policyHash,
211
+ };
212
+ }
213
+ /**
214
+ * Write hook registrations to settings.json files for each harness.
215
+ */
216
+ writeSettingsPatches(output) {
217
+ // Claude Code settings.json
218
+ this.patchClaudeSettings(output);
219
+ // Codex hooks.json
220
+ this.patchHarnessSettings(output.settingsPatches.codex, output, 'codex');
221
+ // Cursor hooks.json
222
+ this.patchHarnessSettings(output.settingsPatches.cursor, output, 'cursor');
223
+ }
224
+ /**
225
+ * Verify compiled hooks match current policy (anti-tamper check).
226
+ */
227
+ verify(projectDir) {
228
+ const policy = this.loadPolicy(projectDir);
229
+ const hooksDir = join(projectDir, '.claude', 'hooks');
230
+ const mismatches = [];
231
+ const expectedHash = createHash('sha256')
232
+ .update(JSON.stringify(policy))
233
+ .digest('hex')
234
+ .slice(0, 12);
235
+ // Check combined hook exists
236
+ const combinedPath = join(hooksDir, 'shield-pre-tool.js');
237
+ if (!existsSync(combinedPath)) {
238
+ mismatches.push('shield-pre-tool.js missing — run scale shield compile');
239
+ }
240
+ else {
241
+ const content = readFileSync(combinedPath, 'utf-8');
242
+ if (!content.includes(expectedHash)) {
243
+ mismatches.push(`shield-pre-tool.js hash mismatch (expected ${expectedHash}) — run scale shield compile`);
244
+ }
245
+ }
246
+ return { valid: mismatches.length === 0, mismatches };
247
+ }
248
+ // -----------------------------------------------------------------------
249
+ // Internal
250
+ // -----------------------------------------------------------------------
251
+ compileRule(rule, hooksDir, hash) {
252
+ const fileName = `shield-${rule.id.replace(/[^a-zA-Z0-9_-]/g, '-')}.js`;
253
+ return {
254
+ fileName,
255
+ hookType: rule.hookType,
256
+ matcher: rule.matcher,
257
+ scriptPath: join(hooksDir, fileName),
258
+ hash,
259
+ };
260
+ }
261
+ generateHookScript(rule, policy) {
262
+ const conditions = rule.conditions.map(c => JSON.stringify(c)).join(',\n ');
263
+ const isStrict = policy.settings?.blockMode !== 'warn';
264
+ const blockFn = isStrict ? 'process.exit(2)' : 'console.warn("[SCALE WARN]", reason)';
265
+ return `// SCALE Shield: ${rule.id}
266
+ // Auto-generated by scale shield compile — DO NOT EDIT MANUALLY
267
+ // Rule: ${rule.description}
268
+ // Matcher: ${rule.matcher || '(all)'} | Action: ${rule.action} | Mode: ${policy.settings?.blockMode ?? 'strict'}
269
+
270
+ const CONDITIONS = [${conditions}];
271
+
272
+ function check(input) {
273
+ const toolName = input.tool_name || '';
274
+ const toolInput = input.tool_input || {};
275
+ const command = toolInput.command || '';
276
+
277
+ for (const cond of CONDITIONS) {
278
+ switch (cond.type) {
279
+ case 'protected_path': {
280
+ const filePath = toolInput.file_path || toolInput.path || '';
281
+ if (filePath.includes('.scale/') || filePath.includes('.hook-state/')) {
282
+ return { blocked: true, reason: cond.message || 'Protected path: ' + filePath };
283
+ }
284
+ break;
285
+ }
286
+ case 'dangerous_command': {
287
+ const patterns = [
288
+ /\\brm\\s+-rf\\b/, /\\bDROP\\s+TABLE\\b/i, /\\bDROP\\s+DATABASE\\b/i,
289
+ /\\bTRUNCATE\\s+TABLE\\b/i, /git\\s+push\\s+--force/, /git\\s+push\\s+-f\\b/,
290
+ /git\\s+reset\\s+--hard/, /curl.*\\|\\s*bash\\b/, /wget.*\\|\\s*bash\\b/,
291
+ /\\bchmod\\s+777\\b/, /\\bDELETE\\s+FROM\\b(?!.*\\bWHERE\\b)/i,
292
+ /\\bdocker\\s+rm\\s+-f\\b/, /\\bkubectl\\s+delete\\b/,
293
+ ];
294
+ for (const p of patterns) {
295
+ if (p.test(command)) {
296
+ return { blocked: true, reason: cond.message || 'Dangerous command: ' + command };
297
+ }
298
+ }
299
+ break;
300
+ }
301
+ case 'gate_required': {
302
+ if (/git\\s+commit/.test(command)) {
303
+ try {
304
+ const fs = require('fs');
305
+ const path = require('path');
306
+ const stateFile = path.join(input.cwd || process.cwd(), '.hook-state', 'Stop.json');
307
+ if (fs.existsSync(stateFile)) {
308
+ const state = JSON.parse(fs.readFileSync(stateFile, 'utf-8'));
309
+ if (!state.reason || !state.reason.includes('gate-quality:PASS')) {
310
+ return { blocked: true, reason: 'Gate quality not passed. Run: scale gate-quality' };
311
+ }
312
+ } else {
313
+ return { blocked: true, reason: 'No gate state found. Run: scale gate-quality before commit' };
314
+ }
315
+ } catch (e) { /* allow if state file can't be read */ }
316
+ }
317
+ break;
318
+ }
319
+ case 'secret_pattern': {
320
+ const secretPatterns = [
321
+ /\\bcat\\s+.*\\.env\\b/, /\\becho\\s+.*\\$?API[_-]?KEY\\b/i,
322
+ /\\becho\\s+.*\\$?TOKEN\\b/i, /\\becho\\s+.*\\$?SECRET\\b/i,
323
+ /\\becho\\s+.*\\$?PASSWORD\\b/i,
324
+ ];
325
+ for (const p of secretPatterns) {
326
+ if (p.test(command)) {
327
+ return { blocked: true, reason: cond.message || 'Potential secret exposure' };
328
+ }
329
+ }
330
+ break;
331
+ }
332
+ case 'custom': {
333
+ if (cond.pattern) {
334
+ try {
335
+ const re = new RegExp(cond.pattern, 'i');
336
+ if (re.test(command)) {
337
+ return { blocked: true, reason: cond.message || 'Custom rule matched' };
338
+ }
339
+ } catch (e) { /* invalid regex */ }
340
+ }
341
+ break;
342
+ }
343
+ }
344
+ }
345
+ return { blocked: false, reason: 'OK' };
346
+ }
347
+
348
+ try {
349
+ const raw = process.argv[2] || '{}';
350
+ const input = JSON.parse(raw);
351
+ const result = check(input);
352
+ if (result.blocked) {
353
+ process.stderr.write('[SCALE SHIELD BLOCKED] ' + result.reason + '\\n');
354
+ ${blockFn};
355
+ }
356
+ process.exit(0);
357
+ } catch (e) {
358
+ process.stderr.write('[SCALE SHIELD ERROR] ' + e.message + '\\n');
359
+ process.exit(0); // fail open on parse error
360
+ }
361
+ `;
362
+ }
363
+ generateCombinedPreToolScript(policy) {
364
+ const policyHash = createHash('sha256').update(JSON.stringify(policy)).digest('hex').slice(0, 12);
365
+ // Generate an efficient combined check that runs all pre-tool rules in one pass
366
+ const preToolRules = policy.rules.filter(r => r.hookType === 'PreToolUse');
367
+ const isStrict = policy.settings?.blockMode !== 'warn';
368
+ return `// SCALE Shield Combined PreToolUse Hook
369
+ // Policy hash: ${policyHash} | Rules: ${preToolRules.length} | Mode: ${policy.settings?.blockMode ?? 'strict'}
370
+ // Auto-generated — DO NOT EDIT
371
+
372
+ const BLOCKED_COMMANDS = ${JSON.stringify([
373
+ 'rm -rf', 'DROP TABLE', 'DROP DATABASE', 'TRUNCATE TABLE',
374
+ 'git push --force', 'git push -f', 'git reset --hard',
375
+ 'curl | bash', 'wget | bash', 'chmod 777', 'chmod -R 777',
376
+ 'docker rm -f', 'docker system prune', 'kubectl delete',
377
+ 'cat .env', 'eval ', '--no-verify', 'allowDangerously',
378
+ ])};
379
+
380
+ const BLOCKED_COMMAND_PATTERNS = [
381
+ { re: /\\brm\\s+-rf\\b/, reason: 'rm -rf is blocked' },
382
+ { re: /\\bDROP\\s+TABLE\\b/i, reason: 'DROP TABLE is blocked' },
383
+ { re: /\\bDROP\\s+DATABASE\\b/i, reason: 'DROP DATABASE is blocked' },
384
+ { re: /\\bTRUNCATE\\s+TABLE\\b/i, reason: 'TRUNCATE TABLE is blocked' },
385
+ { re: /git\\s+push\\s+--force/, reason: 'Force push is blocked' },
386
+ { re: /git\\s+reset\\s+--hard/, reason: 'Hard reset is blocked' },
387
+ { re: /git\\s+clean\\s+-[fd]+/, reason: 'Git clean with force flags is blocked' },
388
+ { re: /curl.*\\|\\s*bash/, reason: 'curl-pipe-bash is blocked' },
389
+ { re: /wget.*\\|\\s*bash/, reason: 'wget-pipe-bash is blocked' },
390
+ { re: /\\bchmod\\s+777\\b/, reason: 'chmod 777 is blocked' },
391
+ { re: /\\beval\\s+/i, reason: 'eval is blocked' },
392
+ { re: /--no-verify/, reason: 'No-verify is blocked' },
393
+ { re: /\\bDELETE\\s+FROM\\b(?!.*\\bWHERE\\b)/i, reason: 'DELETE without WHERE is blocked' },
394
+ { re: /\\bdocker\\s+rm\\s+-f\\b/, reason: 'Docker force remove is blocked' },
395
+ { re: /\\bkubectl\\s+delete\\b/, reason: 'kubectl delete is blocked' },
396
+ { re: /\\bcat\\s+.*\\.env\\b/, reason: 'Reading .env files is blocked' },
397
+ { re: /\\becho\\s+.*\\$?(API[_-]?KEY|TOKEN|SECRET|PASSWORD)\\b/i, reason: 'Echoing secrets is blocked' },
398
+ { re: /SKIP_HOOKS|DISABLE_OMC|dang[eo]rously|bypass/i, reason: 'Governance bypass is blocked' },
399
+ ];
400
+
401
+ function isProtectedPath(filePath) {
402
+ const protected = ['.scale/', '.hook-state/', '.env', 'credentials', '.pem', '-key.json'];
403
+ for (const p of protected) {
404
+ if (filePath.includes(p)) return true;
405
+ }
406
+ return false;
407
+ }
408
+
409
+ try {
410
+ const raw = process.argv[2] || '{}';
411
+ const input = typeof raw === 'string' ? JSON.parse(raw) : raw;
412
+ const toolName = input.tool_name || '';
413
+ const toolInput = input.tool_input || {};
414
+ const command = String(toolInput.command || '');
415
+
416
+ // Check protected paths for Write/Edit
417
+ if (toolName === 'Write' || toolName === 'Edit') {
418
+ const fp = String(toolInput.file_path || toolInput.path || '');
419
+ if (fp && isProtectedPath(fp)) {
420
+ process.stderr.write('[SCALE SHIELD BLOCKED] Protected path: ' + fp + '\\n');
421
+ process.exit(2);
422
+ }
423
+ }
424
+
425
+ // Check dangerous commands for Bash
426
+ if (toolName === 'Bash' && command) {
427
+ for (const { re, reason } of BLOCKED_COMMAND_PATTERNS) {
428
+ if (re.test(command)) {
429
+ process.stderr.write('[SCALE SHIELD BLOCKED] ' + reason + '\\n');
430
+ process.exit(2);
431
+ }
432
+ }
433
+ // Gate check for git commit
434
+ if (/git\\s+commit/.test(command)) {
435
+ try {
436
+ const fs = require('fs');
437
+ const path = require('path');
438
+ const cwd = input.cwd || process.cwd();
439
+ const stopState = path.join(cwd, '.hook-state', 'Stop.json');
440
+ if (fs.existsSync(stopState)) {
441
+ const state = JSON.parse(fs.readFileSync(stopState, 'utf-8'));
442
+ if (!state.reason || !state.reason.includes('gate-quality:PASS')) {
443
+ process.stderr.write('[SCALE SHIELD BLOCKED] Gate quality check required before commit. Run: scale gate-quality\\n');
444
+ process.exit(2);
445
+ }
446
+ }
447
+ } catch (e) { /* allow on error */ }
448
+ }
449
+ }
450
+
451
+ // Write state for PostToolUse and Stop hooks
452
+ try {
453
+ const fs = require('fs');
454
+ const path = require('path');
455
+ const cwd = input.cwd || process.cwd();
456
+ const stateDir = path.join(cwd, '.hook-state');
457
+ if (!fs.existsSync(stateDir)) fs.mkdirSync(stateDir, { recursive: true });
458
+ fs.writeFileSync(path.join(stateDir, 'PreToolUse.json'), JSON.stringify({
459
+ hook: 'PreToolUse',
460
+ timestamp: new Date().toISOString(),
461
+ sessionId: input.session_id || 'unknown',
462
+ toolName,
463
+ blocked: false,
464
+ }));
465
+ } catch (e) { /* state write is best-effort */ }
466
+
467
+ process.exit(0);
468
+ } catch (e) {
469
+ // Fail open on parse errors
470
+ process.stderr.write('[SCALE SHIELD WARN] Parse error: ' + e.message + '\\n');
471
+ process.exit(0);
472
+ }
473
+ `;
474
+ }
475
+ patchClaudeSettings(output) {
476
+ const settingsPath = output.settingsPatches.claude;
477
+ if (!existsSync(settingsPath))
478
+ return;
479
+ try {
480
+ const settings = JSON.parse(readFileSync(settingsPath, 'utf-8'));
481
+ if (!settings.hooks)
482
+ settings.hooks = {};
483
+ // Register PreToolUse hook if not already present
484
+ if (!settings.hooks.PreToolUse)
485
+ settings.hooks.PreToolUse = [];
486
+ const preToolHooks = settings.hooks.PreToolUse;
487
+ const hasShieldHook = preToolHooks.some((h) => h?.scriptPath?.includes('shield-pre-tool'));
488
+ if (!hasShieldHook) {
489
+ preToolHooks.push({
490
+ type: 'command',
491
+ command: `node .claude/hooks/shield-pre-tool.js`,
492
+ timeout: 5000,
493
+ });
494
+ writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
495
+ logger.info('Shield hook registered in Claude Code settings');
496
+ }
497
+ }
498
+ catch (err) {
499
+ logger.warn({ err }, 'Failed to patch Claude settings.json');
500
+ }
501
+ }
502
+ patchHarnessSettings(settingsPath, output, _harness) {
503
+ if (!existsSync(settingsPath)) {
504
+ // Create hooks.json if directory exists
505
+ const dir = settingsPath.replace(/[/\\][^/\\]+$/, '');
506
+ if (existsSync(dir)) {
507
+ const config = {
508
+ hooks: {
509
+ PreToolUse: [
510
+ { type: 'command', command: `node .claude/hooks/shield-pre-tool.js`, timeout: 5000 },
511
+ ],
512
+ },
513
+ };
514
+ writeFileSync(settingsPath, JSON.stringify(config, null, 2));
515
+ logger.info({ harness: _harness }, 'Shield hooks config created');
516
+ }
517
+ return;
518
+ }
519
+ try {
520
+ const config = JSON.parse(readFileSync(settingsPath, 'utf-8'));
521
+ if (!config.hooks)
522
+ config.hooks = {};
523
+ if (!config.hooks.PreToolUse)
524
+ config.hooks.PreToolUse = [];
525
+ if (!config.hooks.PreToolUse.some((h) => h?.command?.includes('shield-pre-tool'))) {
526
+ config.hooks.PreToolUse.push({
527
+ type: 'command',
528
+ command: `node .claude/hooks/shield-pre-tool.js`,
529
+ timeout: 5000,
530
+ });
531
+ writeFileSync(settingsPath, JSON.stringify(config, null, 2));
532
+ logger.info({ harness: _harness }, 'Shield hooks config patched');
533
+ }
534
+ }
535
+ catch (err) {
536
+ logger.warn({ err, harness: _harness }, 'Failed to patch harness settings');
537
+ }
538
+ }
539
+ }
540
+ //# sourceMappingURL=PolicyCompiler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PolicyCompiler.js","sourceRoot":"","sources":["../../src/shield/PolicyCompiler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ import type { ShieldInput, ShieldDecision } from './ShieldProtocol.js';
2
+ export interface ProtectedPathRule {
3
+ glob: string;
4
+ reason: string;
5
+ allowReads: boolean;
6
+ }
7
+ export interface CommandBlockRule {
8
+ pattern: RegExp;
9
+ reason: string;
10
+ severity: 'block' | 'warn';
11
+ category: 'destructive' | 'data-loss' | 'security' | 'governance-bypass';
12
+ }
13
+ export interface PathCheckResult {
14
+ blocked: boolean;
15
+ matchedRule?: ProtectedPathRule;
16
+ targetPath: string;
17
+ }
18
+ /**
19
+ * Check if a file write target is a protected path.
20
+ * Returns { blocked: true } if the path matches any protected glob.
21
+ */
22
+ export declare function checkProtectedPath(targetPath: string, cwd?: string, toolName?: string): PathCheckResult;
23
+ /**
24
+ * Check if a command contains any blocked patterns.
25
+ * Returns list of matched rules.
26
+ */
27
+ export declare function checkCommand(command: string): CommandBlockRule[];
28
+ /**
29
+ * Full pre-flight check for a tool input.
30
+ * Returns allow/block decision.
31
+ */
32
+ export declare function checkToolInput(input: ShieldInput): ShieldDecision;
33
+ /**
34
+ * Verify .scale/ directory integrity.
35
+ */
36
+ export declare function verifyScaleIntegrity(cwd: string): {
37
+ intact: boolean;
38
+ missing: string[];
39
+ };