@vibecheckai/cli 3.4.0 → 3.5.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 (228) hide show
  1. package/bin/registry.js +154 -338
  2. package/bin/runners/context/generators/mcp.js +13 -15
  3. package/bin/runners/context/proof-context.js +1 -248
  4. package/bin/runners/lib/analysis-core.js +180 -198
  5. package/bin/runners/lib/analyzers.js +223 -1669
  6. package/bin/runners/lib/cli-output.js +210 -242
  7. package/bin/runners/lib/detectors-v2.js +785 -547
  8. package/bin/runners/lib/entitlements-v2.js +458 -96
  9. package/bin/runners/lib/error-handler.js +9 -16
  10. package/bin/runners/lib/global-flags.js +0 -37
  11. package/bin/runners/lib/route-truth.js +322 -1167
  12. package/bin/runners/lib/scan-output.js +469 -448
  13. package/bin/runners/lib/ship-output.js +27 -280
  14. package/bin/runners/lib/terminal-ui.js +733 -231
  15. package/bin/runners/lib/truth.js +321 -1004
  16. package/bin/runners/lib/unified-output.js +158 -162
  17. package/bin/runners/lib/upsell.js +204 -104
  18. package/bin/runners/runAllowlist.js +324 -0
  19. package/bin/runners/runAuth.js +95 -324
  20. package/bin/runners/runCheckpoint.js +21 -39
  21. package/bin/runners/runContext.js +24 -136
  22. package/bin/runners/runDoctor.js +67 -115
  23. package/bin/runners/runEvidencePack.js +219 -0
  24. package/bin/runners/runFix.js +5 -6
  25. package/bin/runners/runGuard.js +118 -212
  26. package/bin/runners/runInit.js +2 -14
  27. package/bin/runners/runInstall.js +281 -0
  28. package/bin/runners/runLabs.js +341 -0
  29. package/bin/runners/runMcp.js +52 -130
  30. package/bin/runners/runPolish.js +20 -43
  31. package/bin/runners/runProve.js +3 -13
  32. package/bin/runners/runReality.js +0 -14
  33. package/bin/runners/runReport.js +2 -3
  34. package/bin/runners/runScan.js +44 -511
  35. package/bin/runners/runShip.js +14 -28
  36. package/bin/runners/runValidate.js +2 -19
  37. package/bin/runners/runWatch.js +54 -118
  38. package/bin/vibecheck.js +41 -148
  39. package/mcp-server/ARCHITECTURE.md +339 -0
  40. package/mcp-server/__tests__/cache.test.ts +313 -0
  41. package/mcp-server/__tests__/executor.test.ts +239 -0
  42. package/mcp-server/__tests__/fixtures/exclusion-test/.cache/webpack/cache.pack +1 -0
  43. package/mcp-server/__tests__/fixtures/exclusion-test/.next/server/chunk.js +3 -0
  44. package/mcp-server/__tests__/fixtures/exclusion-test/.turbo/cache.json +3 -0
  45. package/mcp-server/__tests__/fixtures/exclusion-test/.venv/lib/env.py +3 -0
  46. package/mcp-server/__tests__/fixtures/exclusion-test/dist/bundle.js +3 -0
  47. package/mcp-server/__tests__/fixtures/exclusion-test/package.json +5 -0
  48. package/mcp-server/__tests__/fixtures/exclusion-test/src/app.ts +5 -0
  49. package/mcp-server/__tests__/fixtures/exclusion-test/venv/lib/config.py +4 -0
  50. package/mcp-server/__tests__/ids.test.ts +345 -0
  51. package/mcp-server/__tests__/integration/tools.test.ts +410 -0
  52. package/mcp-server/__tests__/registry.test.ts +365 -0
  53. package/mcp-server/__tests__/sandbox.test.ts +323 -0
  54. package/mcp-server/__tests__/schemas.test.ts +372 -0
  55. package/mcp-server/benchmarks/run-benchmarks.ts +304 -0
  56. package/mcp-server/examples/doctor.request.json +14 -0
  57. package/mcp-server/examples/doctor.response.json +53 -0
  58. package/mcp-server/examples/error.response.json +15 -0
  59. package/mcp-server/examples/scan.request.json +14 -0
  60. package/mcp-server/examples/scan.response.json +108 -0
  61. package/mcp-server/handlers/tool-handler.ts +671 -0
  62. package/mcp-server/index-v3.ts +293 -0
  63. package/mcp-server/index.js +1072 -1573
  64. package/mcp-server/index.old.js +4137 -0
  65. package/mcp-server/lib/cache.ts +341 -0
  66. package/mcp-server/lib/errors.ts +346 -0
  67. package/mcp-server/lib/executor.ts +792 -0
  68. package/mcp-server/lib/ids.ts +238 -0
  69. package/mcp-server/lib/logger.ts +368 -0
  70. package/mcp-server/lib/metrics.ts +365 -0
  71. package/mcp-server/lib/sandbox.ts +337 -0
  72. package/mcp-server/lib/validator.ts +229 -0
  73. package/mcp-server/package-lock.json +165 -0
  74. package/mcp-server/package.json +32 -7
  75. package/mcp-server/premium-tools.js +2 -2
  76. package/mcp-server/registry/tools.json +476 -0
  77. package/mcp-server/schemas/error-envelope.schema.json +125 -0
  78. package/mcp-server/schemas/finding.schema.json +167 -0
  79. package/mcp-server/schemas/report-artifact.schema.json +88 -0
  80. package/mcp-server/schemas/run-request.schema.json +75 -0
  81. package/mcp-server/schemas/verdict.schema.json +168 -0
  82. package/mcp-server/tier-auth.d.ts +71 -0
  83. package/mcp-server/tier-auth.js +371 -183
  84. package/mcp-server/truth-context.js +90 -131
  85. package/mcp-server/truth-firewall-tools.js +1000 -1611
  86. package/mcp-server/tsconfig.json +34 -0
  87. package/mcp-server/vibecheck-tools.js +2 -2
  88. package/mcp-server/vitest.config.ts +16 -0
  89. package/package.json +3 -4
  90. package/bin/runners/lib/agent-firewall/ai/false-positive-analyzer.js +0 -474
  91. package/bin/runners/lib/agent-firewall/change-packet/builder.js +0 -488
  92. package/bin/runners/lib/agent-firewall/change-packet/schema.json +0 -228
  93. package/bin/runners/lib/agent-firewall/change-packet/store.js +0 -200
  94. package/bin/runners/lib/agent-firewall/claims/claim-types.js +0 -21
  95. package/bin/runners/lib/agent-firewall/claims/extractor.js +0 -303
  96. package/bin/runners/lib/agent-firewall/claims/patterns.js +0 -24
  97. package/bin/runners/lib/agent-firewall/critic/index.js +0 -151
  98. package/bin/runners/lib/agent-firewall/critic/judge.js +0 -432
  99. package/bin/runners/lib/agent-firewall/critic/prompts.js +0 -305
  100. package/bin/runners/lib/agent-firewall/evidence/auth-evidence.js +0 -88
  101. package/bin/runners/lib/agent-firewall/evidence/contract-evidence.js +0 -75
  102. package/bin/runners/lib/agent-firewall/evidence/env-evidence.js +0 -127
  103. package/bin/runners/lib/agent-firewall/evidence/resolver.js +0 -102
  104. package/bin/runners/lib/agent-firewall/evidence/route-evidence.js +0 -213
  105. package/bin/runners/lib/agent-firewall/evidence/side-effect-evidence.js +0 -145
  106. package/bin/runners/lib/agent-firewall/fs-hook/daemon.js +0 -19
  107. package/bin/runners/lib/agent-firewall/fs-hook/installer.js +0 -87
  108. package/bin/runners/lib/agent-firewall/fs-hook/watcher.js +0 -184
  109. package/bin/runners/lib/agent-firewall/git-hook/pre-commit.js +0 -163
  110. package/bin/runners/lib/agent-firewall/ide-extension/cursor.js +0 -107
  111. package/bin/runners/lib/agent-firewall/ide-extension/vscode.js +0 -68
  112. package/bin/runners/lib/agent-firewall/ide-extension/windsurf.js +0 -66
  113. package/bin/runners/lib/agent-firewall/interceptor/base.js +0 -304
  114. package/bin/runners/lib/agent-firewall/interceptor/cursor.js +0 -35
  115. package/bin/runners/lib/agent-firewall/interceptor/vscode.js +0 -35
  116. package/bin/runners/lib/agent-firewall/interceptor/windsurf.js +0 -34
  117. package/bin/runners/lib/agent-firewall/lawbook/distributor.js +0 -465
  118. package/bin/runners/lib/agent-firewall/lawbook/evaluator.js +0 -604
  119. package/bin/runners/lib/agent-firewall/lawbook/index.js +0 -304
  120. package/bin/runners/lib/agent-firewall/lawbook/registry.js +0 -514
  121. package/bin/runners/lib/agent-firewall/lawbook/schema.js +0 -420
  122. package/bin/runners/lib/agent-firewall/logger.js +0 -141
  123. package/bin/runners/lib/agent-firewall/policy/default-policy.json +0 -90
  124. package/bin/runners/lib/agent-firewall/policy/engine.js +0 -103
  125. package/bin/runners/lib/agent-firewall/policy/loader.js +0 -451
  126. package/bin/runners/lib/agent-firewall/policy/rules/auth-drift.js +0 -50
  127. package/bin/runners/lib/agent-firewall/policy/rules/contract-drift.js +0 -50
  128. package/bin/runners/lib/agent-firewall/policy/rules/fake-success.js +0 -86
  129. package/bin/runners/lib/agent-firewall/policy/rules/ghost-env.js +0 -162
  130. package/bin/runners/lib/agent-firewall/policy/rules/ghost-route.js +0 -189
  131. package/bin/runners/lib/agent-firewall/policy/rules/scope.js +0 -93
  132. package/bin/runners/lib/agent-firewall/policy/rules/unsafe-side-effect.js +0 -57
  133. package/bin/runners/lib/agent-firewall/policy/schema.json +0 -183
  134. package/bin/runners/lib/agent-firewall/policy/verdict.js +0 -54
  135. package/bin/runners/lib/agent-firewall/proposal/extractor.js +0 -394
  136. package/bin/runners/lib/agent-firewall/proposal/index.js +0 -212
  137. package/bin/runners/lib/agent-firewall/proposal/schema.js +0 -251
  138. package/bin/runners/lib/agent-firewall/proposal/validator.js +0 -386
  139. package/bin/runners/lib/agent-firewall/reality/index.js +0 -332
  140. package/bin/runners/lib/agent-firewall/reality/state.js +0 -625
  141. package/bin/runners/lib/agent-firewall/reality/watcher.js +0 -322
  142. package/bin/runners/lib/agent-firewall/risk/index.js +0 -173
  143. package/bin/runners/lib/agent-firewall/risk/scorer.js +0 -328
  144. package/bin/runners/lib/agent-firewall/risk/thresholds.js +0 -321
  145. package/bin/runners/lib/agent-firewall/risk/vectors.js +0 -421
  146. package/bin/runners/lib/agent-firewall/simulator/diff-simulator.js +0 -472
  147. package/bin/runners/lib/agent-firewall/simulator/import-resolver.js +0 -346
  148. package/bin/runners/lib/agent-firewall/simulator/index.js +0 -181
  149. package/bin/runners/lib/agent-firewall/simulator/route-validator.js +0 -380
  150. package/bin/runners/lib/agent-firewall/time-machine/incident-correlator.js +0 -661
  151. package/bin/runners/lib/agent-firewall/time-machine/index.js +0 -267
  152. package/bin/runners/lib/agent-firewall/time-machine/replay-engine.js +0 -436
  153. package/bin/runners/lib/agent-firewall/time-machine/state-reconstructor.js +0 -490
  154. package/bin/runners/lib/agent-firewall/time-machine/timeline-builder.js +0 -530
  155. package/bin/runners/lib/agent-firewall/truthpack/index.js +0 -67
  156. package/bin/runners/lib/agent-firewall/truthpack/loader.js +0 -137
  157. package/bin/runners/lib/agent-firewall/unblock/planner.js +0 -337
  158. package/bin/runners/lib/agent-firewall/utils/ignore-checker.js +0 -118
  159. package/bin/runners/lib/api-client.js +0 -269
  160. package/bin/runners/lib/authority-badge.js +0 -425
  161. package/bin/runners/lib/engines/accessibility-engine.js +0 -190
  162. package/bin/runners/lib/engines/api-consistency-engine.js +0 -162
  163. package/bin/runners/lib/engines/ast-cache.js +0 -99
  164. package/bin/runners/lib/engines/code-quality-engine.js +0 -255
  165. package/bin/runners/lib/engines/console-logs-engine.js +0 -115
  166. package/bin/runners/lib/engines/cross-file-analysis-engine.js +0 -268
  167. package/bin/runners/lib/engines/dead-code-engine.js +0 -198
  168. package/bin/runners/lib/engines/deprecated-api-engine.js +0 -226
  169. package/bin/runners/lib/engines/empty-catch-engine.js +0 -150
  170. package/bin/runners/lib/engines/file-filter.js +0 -131
  171. package/bin/runners/lib/engines/hardcoded-secrets-engine.js +0 -251
  172. package/bin/runners/lib/engines/mock-data-engine.js +0 -272
  173. package/bin/runners/lib/engines/parallel-processor.js +0 -71
  174. package/bin/runners/lib/engines/performance-issues-engine.js +0 -265
  175. package/bin/runners/lib/engines/security-vulnerabilities-engine.js +0 -243
  176. package/bin/runners/lib/engines/todo-fixme-engine.js +0 -115
  177. package/bin/runners/lib/engines/type-aware-engine.js +0 -152
  178. package/bin/runners/lib/engines/unsafe-regex-engine.js +0 -225
  179. package/bin/runners/lib/engines/vibecheck-engines/README.md +0 -53
  180. package/bin/runners/lib/engines/vibecheck-engines/index.js +0 -15
  181. package/bin/runners/lib/engines/vibecheck-engines/lib/ast-cache.js +0 -164
  182. package/bin/runners/lib/engines/vibecheck-engines/lib/code-quality-engine.js +0 -291
  183. package/bin/runners/lib/engines/vibecheck-engines/lib/console-logs-engine.js +0 -83
  184. package/bin/runners/lib/engines/vibecheck-engines/lib/dead-code-engine.js +0 -198
  185. package/bin/runners/lib/engines/vibecheck-engines/lib/deprecated-api-engine.js +0 -275
  186. package/bin/runners/lib/engines/vibecheck-engines/lib/empty-catch-engine.js +0 -167
  187. package/bin/runners/lib/engines/vibecheck-engines/lib/file-filter.js +0 -217
  188. package/bin/runners/lib/engines/vibecheck-engines/lib/hardcoded-secrets-engine.js +0 -139
  189. package/bin/runners/lib/engines/vibecheck-engines/lib/mock-data-engine.js +0 -140
  190. package/bin/runners/lib/engines/vibecheck-engines/lib/parallel-processor.js +0 -164
  191. package/bin/runners/lib/engines/vibecheck-engines/lib/performance-issues-engine.js +0 -234
  192. package/bin/runners/lib/engines/vibecheck-engines/lib/type-aware-engine.js +0 -217
  193. package/bin/runners/lib/engines/vibecheck-engines/lib/unsafe-regex-engine.js +0 -78
  194. package/bin/runners/lib/engines/vibecheck-engines/package.json +0 -13
  195. package/bin/runners/lib/exit-codes.js +0 -275
  196. package/bin/runners/lib/fingerprint.js +0 -377
  197. package/bin/runners/lib/help-formatter.js +0 -413
  198. package/bin/runners/lib/logger.js +0 -38
  199. package/bin/runners/lib/ship-output-enterprise.js +0 -239
  200. package/bin/runners/lib/unified-cli-output.js +0 -604
  201. package/bin/runners/runAgent.d.ts +0 -5
  202. package/bin/runners/runAgent.js +0 -161
  203. package/bin/runners/runApprove.js +0 -1200
  204. package/bin/runners/runClassify.js +0 -859
  205. package/bin/runners/runContext.d.ts +0 -4
  206. package/bin/runners/runFirewall.d.ts +0 -5
  207. package/bin/runners/runFirewall.js +0 -134
  208. package/bin/runners/runFirewallHook.d.ts +0 -5
  209. package/bin/runners/runFirewallHook.js +0 -56
  210. package/bin/runners/runPolish.d.ts +0 -4
  211. package/bin/runners/runProof.zip +0 -0
  212. package/bin/runners/runTruth.d.ts +0 -5
  213. package/bin/runners/runTruth.js +0 -101
  214. package/mcp-server/HARDENING_SUMMARY.md +0 -299
  215. package/mcp-server/agent-firewall-interceptor.js +0 -500
  216. package/mcp-server/authority-tools.js +0 -569
  217. package/mcp-server/conductor/conflict-resolver.js +0 -588
  218. package/mcp-server/conductor/execution-planner.js +0 -544
  219. package/mcp-server/conductor/index.js +0 -377
  220. package/mcp-server/conductor/lock-manager.js +0 -615
  221. package/mcp-server/conductor/request-queue.js +0 -550
  222. package/mcp-server/conductor/session-manager.js +0 -500
  223. package/mcp-server/conductor/tools.js +0 -510
  224. package/mcp-server/lib/api-client.cjs +0 -13
  225. package/mcp-server/lib/logger.cjs +0 -30
  226. package/mcp-server/logger.js +0 -173
  227. package/mcp-server/tools-v3.js +0 -706
  228. package/mcp-server/vibecheck-mcp-server-3.2.0.tgz +0 -0
@@ -1,544 +0,0 @@
1
- /**
2
- * Conductor Execution Planner
3
- *
4
- * Plans deterministic execution ordering for multi-agent operations.
5
- * Uses topological sorting to respect dependencies.
6
- *
7
- * Codename: Conductor
8
- */
9
-
10
- "use strict";
11
-
12
- import path from "path";
13
-
14
- /**
15
- * @typedef {Object} ExecutionStep
16
- * @property {number} order - Execution order (0 = first)
17
- * @property {string} proposalId - Proposal to execute
18
- * @property {string} agentId - Agent that owns the proposal
19
- * @property {string[]} dependsOn - Proposal IDs this depends on
20
- * @property {string[]} blockedBy - Proposal IDs blocking this
21
- * @property {boolean} canExecuteNow - Can execute immediately
22
- * @property {string} status - pending, executing, completed, failed
23
- */
24
-
25
- /**
26
- * @typedef {Object} ExecutionPlan
27
- * @property {string} planId - Unique plan ID
28
- * @property {ExecutionStep[]} steps - Ordered execution steps
29
- * @property {boolean} canExecute - Can the plan be executed
30
- * @property {Object[]} conflicts - Unresolved conflicts blocking execution
31
- * @property {Date} createdAt - When plan was created
32
- */
33
-
34
- /**
35
- * Tier priority mapping (higher = more priority)
36
- */
37
- const TIER_PRIORITY = {
38
- ENTERPRISE: 4,
39
- PRO: 3,
40
- STARTER: 2,
41
- FREE: 1,
42
- };
43
-
44
- /**
45
- * Execution Planner class
46
- */
47
- class ExecutionPlanner {
48
- constructor(conflictResolver = null) {
49
- this.conflictResolver = conflictResolver;
50
- this.plans = new Map(); // planId -> ExecutionPlan
51
- this.executionHistory = []; // For auditing
52
- }
53
-
54
- /**
55
- * Set the conflict resolver
56
- * @param {Object} resolver - Conflict resolver instance
57
- */
58
- setConflictResolver(resolver) {
59
- this.conflictResolver = resolver;
60
- }
61
-
62
- /**
63
- * Create an execution plan from proposals
64
- * @param {Object[]} proposals - Proposals to plan
65
- * @param {Object} options - Planning options
66
- * @returns {ExecutionPlan} Execution plan
67
- */
68
- createPlan(proposals, options = {}) {
69
- const planId = `plan_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
70
-
71
- // Build dependency graph
72
- const graph = this.buildDependencyGraph(proposals);
73
-
74
- // Check for cycles
75
- const cycles = this.detectCycles(graph);
76
- if (cycles.length > 0) {
77
- return {
78
- planId,
79
- steps: [],
80
- canExecute: false,
81
- conflicts: cycles.map(c => ({
82
- type: "circular_dependency",
83
- proposals: c,
84
- description: `Circular dependency detected: ${c.join(" -> ")}`,
85
- })),
86
- createdAt: new Date(),
87
- };
88
- }
89
-
90
- // Topological sort
91
- const sortedOrder = this.topologicalSort(graph);
92
-
93
- if (!sortedOrder) {
94
- return {
95
- planId,
96
- steps: [],
97
- canExecute: false,
98
- conflicts: [{ type: "sort_failed", description: "Could not determine execution order" }],
99
- createdAt: new Date(),
100
- };
101
- }
102
-
103
- // Apply tier-based priority within independent groups
104
- const prioritizedOrder = this.applyTierPriority(sortedOrder, proposals);
105
-
106
- // Build execution steps
107
- const steps = this.buildExecutionSteps(prioritizedOrder, proposals, graph);
108
-
109
- // Check for blocking conflicts
110
- const blockingConflicts = this.getBlockingConflicts(proposals);
111
-
112
- const plan = {
113
- planId,
114
- steps,
115
- canExecute: blockingConflicts.length === 0,
116
- conflicts: blockingConflicts,
117
- createdAt: new Date(),
118
- };
119
-
120
- this.plans.set(planId, plan);
121
-
122
- return plan;
123
- }
124
-
125
- /**
126
- * Build a dependency graph from proposals
127
- * @param {Object[]} proposals - Proposals to analyze
128
- * @returns {Map} Dependency graph (proposalId -> Set<dependsOn>)
129
- */
130
- buildDependencyGraph(proposals) {
131
- const graph = new Map();
132
-
133
- // Initialize all nodes
134
- for (const proposal of proposals) {
135
- graph.set(proposal.proposalId, new Set());
136
- }
137
-
138
- // Build dependencies based on file overlaps and assumptions
139
- for (const proposalA of proposals) {
140
- const filesA = this.extractAffectedFiles(proposalA);
141
- const assumptionsA = proposalA.assumptions || [];
142
-
143
- for (const proposalB of proposals) {
144
- if (proposalA.proposalId === proposalB.proposalId) continue;
145
-
146
- const operationsB = proposalB.operations || [];
147
-
148
- // Check if A's assumptions depend on B's operations
149
- for (const assumption of assumptionsA) {
150
- for (const operation of operationsB) {
151
- if (this.assumptionDependsOnOperation(assumption, operation)) {
152
- // A depends on B (B must execute first)
153
- graph.get(proposalA.proposalId).add(proposalB.proposalId);
154
- }
155
- }
156
- }
157
-
158
- // Check for file-based dependencies
159
- const filesB = this.extractAffectedFiles(proposalB);
160
- for (const fileA of filesA) {
161
- for (const fileB of filesB) {
162
- const dependency = this.checkFileDependency(fileA, fileB, proposalA, proposalB);
163
- if (dependency) {
164
- graph.get(dependency.dependent).add(dependency.dependsOn);
165
- }
166
- }
167
- }
168
- }
169
- }
170
-
171
- return graph;
172
- }
173
-
174
- /**
175
- * Check if an assumption depends on an operation
176
- * @param {Object} assumption - Assumption to check
177
- * @param {Object} operation - Operation to check against
178
- * @returns {boolean} Has dependency
179
- */
180
- assumptionDependsOnOperation(assumption, operation) {
181
- const assumptionTarget = this.normalizePath(assumption.target || assumption.path || "");
182
- const operationTarget = this.normalizePath(operation.path || operation.file || "");
183
-
184
- if (!assumptionTarget || !operationTarget) return false;
185
-
186
- // If assumption is about a file that the operation creates/modifies
187
- if (assumptionTarget === operationTarget) {
188
- // file_exists depends on create
189
- if (assumption.type === "file_exists" && operation.type === "create") {
190
- return true;
191
- }
192
- // file_contains depends on modify that adds content
193
- if (assumption.type === "file_contains" && operation.type === "modify") {
194
- return true;
195
- }
196
- }
197
-
198
- return false;
199
- }
200
-
201
- /**
202
- * Check for file-based dependency between operations
203
- * @param {Object} fileA - First file operation
204
- * @param {Object} fileB - Second file operation
205
- * @param {Object} proposalA - First proposal
206
- * @param {Object} proposalB - Second proposal
207
- * @returns {Object|null} Dependency info or null
208
- */
209
- checkFileDependency(fileA, fileB, proposalA, proposalB) {
210
- const pathA = this.normalizePath(fileA.path);
211
- const pathB = this.normalizePath(fileB.path);
212
-
213
- if (pathA !== pathB) return null;
214
-
215
- // Create before modify/read
216
- if (fileB.operation === "create" && fileA.operation === "modify") {
217
- return { dependent: proposalA.proposalId, dependsOn: proposalB.proposalId };
218
- }
219
- if (fileA.operation === "create" && fileB.operation === "modify") {
220
- return { dependent: proposalB.proposalId, dependsOn: proposalA.proposalId };
221
- }
222
-
223
- return null;
224
- }
225
-
226
- /**
227
- * Extract affected files from a proposal
228
- * @param {Object} proposal - Proposal to analyze
229
- * @returns {Object[]} Affected files
230
- */
231
- extractAffectedFiles(proposal) {
232
- const files = [];
233
- for (const op of proposal.operations || []) {
234
- if (op.path || op.file || op.filePath) {
235
- files.push({
236
- path: op.path || op.file || op.filePath,
237
- operation: op.type || op.operation || "modify",
238
- });
239
- }
240
- }
241
- return files;
242
- }
243
-
244
- /**
245
- * Detect cycles in the dependency graph
246
- * @param {Map} graph - Dependency graph
247
- * @returns {string[][]} Detected cycles
248
- */
249
- detectCycles(graph) {
250
- const cycles = [];
251
- const visited = new Set();
252
- const inStack = new Set();
253
-
254
- const dfs = (node, path) => {
255
- if (inStack.has(node)) {
256
- const cycleStart = path.indexOf(node);
257
- cycles.push(path.slice(cycleStart));
258
- return;
259
- }
260
-
261
- if (visited.has(node)) return;
262
-
263
- visited.add(node);
264
- inStack.add(node);
265
- path.push(node);
266
-
267
- const deps = graph.get(node) || new Set();
268
- for (const dep of deps) {
269
- dfs(dep, [...path]);
270
- }
271
-
272
- inStack.delete(node);
273
- };
274
-
275
- for (const node of graph.keys()) {
276
- if (!visited.has(node)) {
277
- dfs(node, []);
278
- }
279
- }
280
-
281
- return cycles;
282
- }
283
-
284
- /**
285
- * Perform topological sort
286
- * @param {Map} graph - Dependency graph
287
- * @returns {string[]|null} Sorted order or null if not possible
288
- */
289
- topologicalSort(graph) {
290
- const inDegree = new Map();
291
- const sorted = [];
292
- const queue = [];
293
-
294
- // Initialize in-degrees
295
- for (const node of graph.keys()) {
296
- inDegree.set(node, 0);
297
- }
298
-
299
- // Calculate in-degrees
300
- for (const [, deps] of graph) {
301
- for (const dep of deps) {
302
- inDegree.set(dep, (inDegree.get(dep) || 0) + 1);
303
- }
304
- }
305
-
306
- // Find nodes with no dependencies
307
- for (const [node, degree] of inDegree) {
308
- if (degree === 0) {
309
- queue.push(node);
310
- }
311
- }
312
-
313
- // Process queue
314
- while (queue.length > 0) {
315
- const node = queue.shift();
316
- sorted.push(node);
317
-
318
- const deps = graph.get(node) || new Set();
319
- for (const dep of deps) {
320
- inDegree.set(dep, inDegree.get(dep) - 1);
321
- if (inDegree.get(dep) === 0) {
322
- queue.push(dep);
323
- }
324
- }
325
- }
326
-
327
- // Check if all nodes were processed
328
- if (sorted.length !== graph.size) {
329
- return null; // Cycle detected
330
- }
331
-
332
- // Reverse to get correct order (dependencies first)
333
- return sorted.reverse();
334
- }
335
-
336
- /**
337
- * Apply tier-based priority to execution order
338
- * @param {string[]} sortedOrder - Topologically sorted order
339
- * @param {Object[]} proposals - Proposals
340
- * @returns {string[]} Priority-adjusted order
341
- */
342
- applyTierPriority(sortedOrder, proposals) {
343
- const proposalMap = new Map(proposals.map(p => [p.proposalId, p]));
344
-
345
- // Group by dependency level
346
- const levels = this.groupByDependencyLevel(sortedOrder, proposalMap);
347
-
348
- // Sort within each level by tier priority
349
- const prioritized = [];
350
- for (const level of levels) {
351
- level.sort((a, b) => {
352
- const proposalA = proposalMap.get(a);
353
- const proposalB = proposalMap.get(b);
354
- const priorityA = TIER_PRIORITY[proposalA?.tier] || 1;
355
- const priorityB = TIER_PRIORITY[proposalB?.tier] || 1;
356
- return priorityB - priorityA; // Higher priority first
357
- });
358
- prioritized.push(...level);
359
- }
360
-
361
- return prioritized;
362
- }
363
-
364
- /**
365
- * Group proposals by dependency level
366
- * @param {string[]} sorted - Sorted order
367
- * @param {Map} proposalMap - Proposal map
368
- * @returns {string[][]} Grouped levels
369
- */
370
- groupByDependencyLevel(sorted, proposalMap) {
371
- // Simple grouping - items that can execute in parallel at each step
372
- // For now, return as individual levels
373
- return sorted.map(id => [id]);
374
- }
375
-
376
- /**
377
- * Build execution steps from sorted order
378
- * @param {string[]} order - Execution order
379
- * @param {Object[]} proposals - Proposals
380
- * @param {Map} graph - Dependency graph
381
- * @returns {ExecutionStep[]} Execution steps
382
- */
383
- buildExecutionSteps(order, proposals, graph) {
384
- const proposalMap = new Map(proposals.map(p => [p.proposalId, p]));
385
- const steps = [];
386
- const completed = new Set();
387
-
388
- for (let i = 0; i < order.length; i++) {
389
- const proposalId = order[i];
390
- const proposal = proposalMap.get(proposalId);
391
-
392
- if (!proposal) continue;
393
-
394
- const dependencies = Array.from(graph.get(proposalId) || []);
395
- const blockedBy = dependencies.filter(dep => !completed.has(dep));
396
-
397
- steps.push({
398
- order: i,
399
- proposalId,
400
- agentId: proposal.agentId,
401
- sessionId: proposal.sessionId,
402
- tier: proposal.tier,
403
- intent: proposal.intent,
404
- dependsOn: dependencies,
405
- blockedBy,
406
- canExecuteNow: blockedBy.length === 0,
407
- status: "pending",
408
- });
409
-
410
- // For planning purposes, mark as "completed"
411
- completed.add(proposalId);
412
- }
413
-
414
- return steps;
415
- }
416
-
417
- /**
418
- * Get blocking conflicts from the conflict resolver
419
- * @param {Object[]} proposals - Proposals to check
420
- * @returns {Object[]} Blocking conflicts
421
- */
422
- getBlockingConflicts(proposals) {
423
- if (!this.conflictResolver) return [];
424
-
425
- const blocking = [];
426
-
427
- for (const proposal of proposals) {
428
- const result = this.conflictResolver.canProceed(proposal.proposalId);
429
- if (!result.canProceed) {
430
- blocking.push(...result.mustResolve);
431
- }
432
- }
433
-
434
- return blocking;
435
- }
436
-
437
- /**
438
- * Update step status
439
- * @param {string} planId - Plan ID
440
- * @param {string} proposalId - Proposal ID
441
- * @param {string} status - New status
442
- */
443
- updateStepStatus(planId, proposalId, status) {
444
- const plan = this.plans.get(planId);
445
- if (!plan) return;
446
-
447
- const step = plan.steps.find(s => s.proposalId === proposalId);
448
- if (step) {
449
- step.status = status;
450
-
451
- // Update canExecuteNow for dependent steps
452
- if (status === "completed") {
453
- for (const s of plan.steps) {
454
- s.blockedBy = s.blockedBy.filter(b => b !== proposalId);
455
- s.canExecuteNow = s.blockedBy.length === 0 && s.status === "pending";
456
- }
457
- }
458
-
459
- // Record in history
460
- this.executionHistory.push({
461
- planId,
462
- proposalId,
463
- status,
464
- timestamp: new Date(),
465
- });
466
- }
467
- }
468
-
469
- /**
470
- * Get next executable steps from a plan
471
- * @param {string} planId - Plan ID
472
- * @returns {ExecutionStep[]} Executable steps
473
- */
474
- getNextExecutableSteps(planId) {
475
- const plan = this.plans.get(planId);
476
- if (!plan) return [];
477
-
478
- return plan.steps.filter(s => s.canExecuteNow && s.status === "pending");
479
- }
480
-
481
- /**
482
- * Check if plan is complete
483
- * @param {string} planId - Plan ID
484
- * @returns {boolean} Is complete
485
- */
486
- isPlanComplete(planId) {
487
- const plan = this.plans.get(planId);
488
- if (!plan) return false;
489
-
490
- return plan.steps.every(s => s.status === "completed" || s.status === "failed");
491
- }
492
-
493
- /**
494
- * Get plan summary
495
- * @param {string} planId - Plan ID
496
- * @returns {Object} Plan summary
497
- */
498
- getPlanSummary(planId) {
499
- const plan = this.plans.get(planId);
500
- if (!plan) return null;
501
-
502
- const pending = plan.steps.filter(s => s.status === "pending").length;
503
- const executing = plan.steps.filter(s => s.status === "executing").length;
504
- const completed = plan.steps.filter(s => s.status === "completed").length;
505
- const failed = plan.steps.filter(s => s.status === "failed").length;
506
-
507
- return {
508
- planId,
509
- totalSteps: plan.steps.length,
510
- pending,
511
- executing,
512
- completed,
513
- failed,
514
- canExecute: plan.canExecute,
515
- isComplete: pending === 0 && executing === 0,
516
- conflicts: plan.conflicts.length,
517
- };
518
- }
519
-
520
- /**
521
- * Normalize a file path
522
- * @param {string} filePath - Path to normalize
523
- * @returns {string} Normalized path
524
- */
525
- normalizePath(filePath) {
526
- if (!filePath) return "";
527
- return path.resolve(filePath).replace(/\\/g, "/").toLowerCase();
528
- }
529
- }
530
-
531
- /**
532
- * Create a new execution planner
533
- * @param {Object} conflictResolver - Optional conflict resolver
534
- * @returns {ExecutionPlanner} New planner
535
- */
536
- function createExecutionPlanner(conflictResolver = null) {
537
- return new ExecutionPlanner(conflictResolver);
538
- }
539
-
540
- export {
541
- ExecutionPlanner,
542
- createExecutionPlanner,
543
- TIER_PRIORITY,
544
- };