@agile-vibe-coding/avc 0.1.1 → 0.3.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 (239) hide show
  1. package/cli/agent-loader.js +21 -0
  2. package/cli/agents/agent-selector.md +152 -0
  3. package/cli/agents/architecture-recommender.md +418 -0
  4. package/cli/agents/code-implementer.md +117 -0
  5. package/cli/agents/code-validator.md +80 -0
  6. package/cli/agents/context-reviewer-epic.md +101 -0
  7. package/cli/agents/context-reviewer-story.md +92 -0
  8. package/cli/agents/context-writer-epic.md +145 -0
  9. package/cli/agents/context-writer-story.md +111 -0
  10. package/cli/agents/database-deep-dive.md +470 -0
  11. package/cli/agents/database-recommender.md +634 -0
  12. package/cli/agents/doc-distributor.md +176 -0
  13. package/cli/agents/doc-writer-epic.md +42 -0
  14. package/cli/agents/doc-writer-story.md +43 -0
  15. package/cli/agents/documentation-updater.md +203 -0
  16. package/cli/agents/duplicate-detector.md +110 -0
  17. package/cli/agents/epic-story-decomposer.md +559 -0
  18. package/cli/agents/feature-context-generator.md +91 -0
  19. package/cli/agents/gap-checker-epic.md +52 -0
  20. package/cli/agents/impact-checker-story.md +51 -0
  21. package/cli/agents/migration-guide-generator.md +305 -0
  22. package/cli/agents/mission-scope-generator.md +143 -0
  23. package/cli/agents/mission-scope-validator.md +146 -0
  24. package/cli/agents/project-context-extractor.md +122 -0
  25. package/cli/agents/project-documentation-creator.json +226 -0
  26. package/cli/agents/project-documentation-creator.md +595 -0
  27. package/cli/agents/question-prefiller.md +269 -0
  28. package/cli/agents/refiner-epic.md +39 -0
  29. package/cli/agents/refiner-story.md +42 -0
  30. package/cli/agents/scaffolding-generator.md +99 -0
  31. package/cli/agents/seed-validator.md +71 -0
  32. package/cli/agents/story-doc-enricher.md +133 -0
  33. package/cli/agents/story-scope-reviewer.md +147 -0
  34. package/cli/agents/story-splitter.md +83 -0
  35. package/cli/agents/suggestion-business-analyst.md +88 -0
  36. package/cli/agents/suggestion-deployment-architect.md +263 -0
  37. package/cli/agents/suggestion-product-manager.md +129 -0
  38. package/cli/agents/suggestion-security-specialist.md +156 -0
  39. package/cli/agents/suggestion-technical-architect.md +269 -0
  40. package/cli/agents/suggestion-ux-researcher.md +93 -0
  41. package/cli/agents/task-subtask-decomposer.md +188 -0
  42. package/cli/agents/validator-documentation.json +183 -0
  43. package/cli/agents/validator-documentation.md +455 -0
  44. package/cli/agents/validator-selector.md +211 -0
  45. package/cli/ansi-colors.js +21 -0
  46. package/cli/api-reference-tool.js +368 -0
  47. package/cli/build-docs.js +29 -8
  48. package/cli/ceremony-history.js +369 -0
  49. package/cli/checks/catalog.json +76 -0
  50. package/cli/checks/code/quality.json +26 -0
  51. package/cli/checks/code/testing.json +14 -0
  52. package/cli/checks/code/traceability.json +26 -0
  53. package/cli/checks/cross-refs/epic.json +171 -0
  54. package/cli/checks/cross-refs/story.json +149 -0
  55. package/cli/checks/epic/api.json +114 -0
  56. package/cli/checks/epic/backend.json +126 -0
  57. package/cli/checks/epic/cloud.json +126 -0
  58. package/cli/checks/epic/data.json +102 -0
  59. package/cli/checks/epic/database.json +114 -0
  60. package/cli/checks/epic/developer.json +182 -0
  61. package/cli/checks/epic/devops.json +174 -0
  62. package/cli/checks/epic/frontend.json +162 -0
  63. package/cli/checks/epic/mobile.json +102 -0
  64. package/cli/checks/epic/qa.json +90 -0
  65. package/cli/checks/epic/security.json +184 -0
  66. package/cli/checks/epic/solution-architect.json +192 -0
  67. package/cli/checks/epic/test-architect.json +90 -0
  68. package/cli/checks/epic/ui.json +102 -0
  69. package/cli/checks/epic/ux.json +90 -0
  70. package/cli/checks/fixes/epic-fix-template.md +10 -0
  71. package/cli/checks/fixes/story-fix-template.md +10 -0
  72. package/cli/checks/story/api.json +186 -0
  73. package/cli/checks/story/backend.json +102 -0
  74. package/cli/checks/story/cloud.json +102 -0
  75. package/cli/checks/story/data.json +210 -0
  76. package/cli/checks/story/database.json +102 -0
  77. package/cli/checks/story/developer.json +168 -0
  78. package/cli/checks/story/devops.json +102 -0
  79. package/cli/checks/story/frontend.json +174 -0
  80. package/cli/checks/story/mobile.json +102 -0
  81. package/cli/checks/story/qa.json +210 -0
  82. package/cli/checks/story/security.json +198 -0
  83. package/cli/checks/story/solution-architect.json +230 -0
  84. package/cli/checks/story/test-architect.json +210 -0
  85. package/cli/checks/story/ui.json +102 -0
  86. package/cli/checks/story/ux.json +102 -0
  87. package/cli/coding-order.js +401 -0
  88. package/cli/command-logger.js +49 -12
  89. package/cli/components/static-output.js +63 -0
  90. package/cli/console-output-manager.js +94 -0
  91. package/cli/dependency-checker.js +72 -0
  92. package/cli/docs-sync.js +306 -0
  93. package/cli/epic-story-validator.js +659 -0
  94. package/cli/evaluation-prompts.js +1008 -0
  95. package/cli/execution-context.js +195 -0
  96. package/cli/generate-summary-table.js +340 -0
  97. package/cli/init-model-config.js +704 -0
  98. package/cli/init.js +1737 -278
  99. package/cli/kanban-server-manager.js +227 -0
  100. package/cli/llm-claude.js +150 -1
  101. package/cli/llm-gemini.js +109 -0
  102. package/cli/llm-local.js +493 -0
  103. package/cli/llm-mock.js +233 -0
  104. package/cli/llm-openai.js +454 -0
  105. package/cli/llm-provider.js +379 -3
  106. package/cli/llm-token-limits.js +211 -0
  107. package/cli/llm-verifier.js +662 -0
  108. package/cli/llm-xiaomi.js +143 -0
  109. package/cli/message-constants.js +49 -0
  110. package/cli/message-manager.js +334 -0
  111. package/cli/message-types.js +96 -0
  112. package/cli/messaging-api.js +291 -0
  113. package/cli/micro-check-fixer.js +335 -0
  114. package/cli/micro-check-runner.js +449 -0
  115. package/cli/micro-check-scorer.js +148 -0
  116. package/cli/micro-check-validator.js +538 -0
  117. package/cli/model-pricing.js +192 -0
  118. package/cli/model-query-engine.js +468 -0
  119. package/cli/model-recommendation-analyzer.js +495 -0
  120. package/cli/model-selector.js +270 -0
  121. package/cli/output-buffer.js +107 -0
  122. package/cli/process-manager.js +73 -2
  123. package/cli/prompt-logger.js +57 -0
  124. package/cli/repl-ink.js +4625 -1094
  125. package/cli/repl-old.js +3 -4
  126. package/cli/seed-processor.js +962 -0
  127. package/cli/sprint-planning-processor.js +4162 -0
  128. package/cli/template-processor.js +2149 -105
  129. package/cli/templates/project.md +25 -8
  130. package/cli/templates/vitepress-config.mts.template +5 -4
  131. package/cli/token-tracker.js +547 -0
  132. package/cli/tools/generate-story-validators.js +317 -0
  133. package/cli/tools/generate-validators.js +669 -0
  134. package/cli/update-checker.js +19 -17
  135. package/cli/update-notifier.js +4 -4
  136. package/cli/validation-router.js +667 -0
  137. package/cli/verification-tracker.js +563 -0
  138. package/cli/worktree-runner.js +654 -0
  139. package/kanban/README.md +386 -0
  140. package/kanban/client/README.md +205 -0
  141. package/kanban/client/components.json +20 -0
  142. package/kanban/client/dist/assets/index-D_KC5EQT.css +1 -0
  143. package/kanban/client/dist/assets/index-DjY5zqW7.js +351 -0
  144. package/kanban/client/dist/index.html +16 -0
  145. package/kanban/client/dist/vite.svg +1 -0
  146. package/kanban/client/index.html +15 -0
  147. package/kanban/client/package-lock.json +9442 -0
  148. package/kanban/client/package.json +44 -0
  149. package/kanban/client/postcss.config.js +6 -0
  150. package/kanban/client/public/vite.svg +1 -0
  151. package/kanban/client/src/App.jsx +651 -0
  152. package/kanban/client/src/components/ProjectFileEditorPopup.jsx +117 -0
  153. package/kanban/client/src/components/ceremony/AskArchPopup.jsx +420 -0
  154. package/kanban/client/src/components/ceremony/AskModelPopup.jsx +629 -0
  155. package/kanban/client/src/components/ceremony/CeremonyWorkflowModal.jsx +1133 -0
  156. package/kanban/client/src/components/ceremony/EpicStorySelectionModal.jsx +254 -0
  157. package/kanban/client/src/components/ceremony/ProviderSwitcherButton.jsx +290 -0
  158. package/kanban/client/src/components/ceremony/SponsorCallModal.jsx +686 -0
  159. package/kanban/client/src/components/ceremony/SprintPlanningModal.jsx +838 -0
  160. package/kanban/client/src/components/ceremony/steps/ArchitectureStep.jsx +150 -0
  161. package/kanban/client/src/components/ceremony/steps/CompleteStep.jsx +136 -0
  162. package/kanban/client/src/components/ceremony/steps/DatabaseStep.jsx +202 -0
  163. package/kanban/client/src/components/ceremony/steps/DeploymentStep.jsx +123 -0
  164. package/kanban/client/src/components/ceremony/steps/MissionStep.jsx +106 -0
  165. package/kanban/client/src/components/ceremony/steps/ReviewAnswersStep.jsx +329 -0
  166. package/kanban/client/src/components/ceremony/steps/RunningStep.jsx +249 -0
  167. package/kanban/client/src/components/kanban/CardDetailModal.jsx +646 -0
  168. package/kanban/client/src/components/kanban/EpicSection.jsx +146 -0
  169. package/kanban/client/src/components/kanban/FilterToolbar.jsx +222 -0
  170. package/kanban/client/src/components/kanban/GroupingSelector.jsx +63 -0
  171. package/kanban/client/src/components/kanban/KanbanBoard.jsx +211 -0
  172. package/kanban/client/src/components/kanban/KanbanCard.jsx +147 -0
  173. package/kanban/client/src/components/kanban/KanbanColumn.jsx +90 -0
  174. package/kanban/client/src/components/kanban/RefineWorkItemPopup.jsx +784 -0
  175. package/kanban/client/src/components/kanban/RunButton.jsx +162 -0
  176. package/kanban/client/src/components/kanban/SeedButton.jsx +176 -0
  177. package/kanban/client/src/components/layout/LoadingScreen.jsx +82 -0
  178. package/kanban/client/src/components/process/ProcessMonitorBar.jsx +80 -0
  179. package/kanban/client/src/components/settings/AgentEditorPopup.jsx +171 -0
  180. package/kanban/client/src/components/settings/AgentsTab.jsx +381 -0
  181. package/kanban/client/src/components/settings/ApiKeysTab.jsx +142 -0
  182. package/kanban/client/src/components/settings/CeremonyModelsTab.jsx +105 -0
  183. package/kanban/client/src/components/settings/CheckEditorPopup.jsx +507 -0
  184. package/kanban/client/src/components/settings/CostThresholdsTab.jsx +95 -0
  185. package/kanban/client/src/components/settings/ModelPricingTab.jsx +269 -0
  186. package/kanban/client/src/components/settings/OpenAIAuthSection.jsx +412 -0
  187. package/kanban/client/src/components/settings/ServersTab.jsx +121 -0
  188. package/kanban/client/src/components/settings/SettingsModal.jsx +84 -0
  189. package/kanban/client/src/components/stats/CostModal.jsx +384 -0
  190. package/kanban/client/src/components/ui/badge.jsx +27 -0
  191. package/kanban/client/src/components/ui/dialog.jsx +121 -0
  192. package/kanban/client/src/components/ui/tabs.jsx +85 -0
  193. package/kanban/client/src/hooks/__tests__/useGrouping.test.js +232 -0
  194. package/kanban/client/src/hooks/useGrouping.js +177 -0
  195. package/kanban/client/src/hooks/useWebSocket.js +120 -0
  196. package/kanban/client/src/lib/__tests__/api.test.js +196 -0
  197. package/kanban/client/src/lib/__tests__/status-grouping.test.js +94 -0
  198. package/kanban/client/src/lib/api.js +515 -0
  199. package/kanban/client/src/lib/status-grouping.js +154 -0
  200. package/kanban/client/src/lib/utils.js +11 -0
  201. package/kanban/client/src/main.jsx +10 -0
  202. package/kanban/client/src/store/__tests__/kanbanStore.test.js +164 -0
  203. package/kanban/client/src/store/ceremonyStore.js +172 -0
  204. package/kanban/client/src/store/filterStore.js +201 -0
  205. package/kanban/client/src/store/kanbanStore.js +123 -0
  206. package/kanban/client/src/store/processStore.js +65 -0
  207. package/kanban/client/src/store/sprintPlanningStore.js +33 -0
  208. package/kanban/client/src/styles/globals.css +59 -0
  209. package/kanban/client/tailwind.config.js +77 -0
  210. package/kanban/client/vite.config.js +28 -0
  211. package/kanban/client/vitest.config.js +28 -0
  212. package/kanban/dev-start.sh +47 -0
  213. package/kanban/package.json +12 -0
  214. package/kanban/server/index.js +537 -0
  215. package/kanban/server/routes/ceremony.js +454 -0
  216. package/kanban/server/routes/costs.js +163 -0
  217. package/kanban/server/routes/openai-oauth.js +366 -0
  218. package/kanban/server/routes/processes.js +50 -0
  219. package/kanban/server/routes/settings.js +736 -0
  220. package/kanban/server/routes/websocket.js +281 -0
  221. package/kanban/server/routes/work-items.js +487 -0
  222. package/kanban/server/services/CeremonyService.js +1441 -0
  223. package/kanban/server/services/FileSystemScanner.js +95 -0
  224. package/kanban/server/services/FileWatcher.js +144 -0
  225. package/kanban/server/services/HierarchyBuilder.js +196 -0
  226. package/kanban/server/services/ProcessRegistry.js +122 -0
  227. package/kanban/server/services/TaskRunnerService.js +261 -0
  228. package/kanban/server/services/WorkItemReader.js +123 -0
  229. package/kanban/server/services/WorkItemRefineService.js +510 -0
  230. package/kanban/server/start.js +49 -0
  231. package/kanban/server/utils/kanban-logger.js +132 -0
  232. package/kanban/server/utils/markdown.js +91 -0
  233. package/kanban/server/utils/status-grouping.js +107 -0
  234. package/kanban/server/workers/run-task-worker.js +121 -0
  235. package/kanban/server/workers/seed-worker.js +94 -0
  236. package/kanban/server/workers/sponsor-call-worker.js +92 -0
  237. package/kanban/server/workers/sprint-planning-worker.js +212 -0
  238. package/package.json +19 -7
  239. package/cli/agents/documentation.md +0 -302
@@ -0,0 +1,563 @@
1
+ /**
2
+ * VerificationTracker - Tracks LLM verification workflow efficiency
3
+ *
4
+ * Provides comprehensive tracking of verification sessions:
5
+ * - Per-rule execution metrics (timing, results, content changes)
6
+ * - Per-agent session statistics (violations, API calls, duration)
7
+ * - Ceremony-level summaries (total overhead, most violated rules)
8
+ *
9
+ * Outputs:
10
+ * - Real-time console logs during execution
11
+ * - Structured JSON data for analysis
12
+ * - Human-readable summary report
13
+ */
14
+
15
+ import fs from 'fs';
16
+ import path from 'path';
17
+
18
+ class VerificationTracker {
19
+ constructor(ceremonyName) {
20
+ this.ceremonyName = ceremonyName;
21
+ this.ceremonyStartTime = Date.now();
22
+ this.sessions = [];
23
+ this.currentSession = null;
24
+ this.currentRuleExecution = null;
25
+ this.verificationCache = new Map(); // Cache for current ceremony
26
+ this.ruleProfiles = this.loadRuleProfiles(); // Load historical pass rates
27
+ }
28
+
29
+ /**
30
+ * Start tracking a verification session for an agent
31
+ */
32
+ startSession(agentName, inputContent) {
33
+ this.currentSession = {
34
+ sessionId: `verify-${this.sessions.length + 1}`,
35
+ agentName,
36
+ startTime: new Date().toISOString(),
37
+ startTimeMs: Date.now(),
38
+ input: {
39
+ contentLength: inputContent.length,
40
+ contentPreview: inputContent.substring(0, 200),
41
+ contentHash: this.hashContent(inputContent)
42
+ },
43
+ ruleExecutions: [],
44
+ violations: []
45
+ };
46
+ }
47
+
48
+ /**
49
+ * Start tracking a rule check
50
+ */
51
+ startRuleCheck(rule) {
52
+ this.currentRuleExecution = {
53
+ ruleId: rule.id,
54
+ ruleName: rule.name,
55
+ severity: rule.severity,
56
+ checkStartTime: new Date().toISOString(),
57
+ checkStartTimeMs: Date.now()
58
+ };
59
+ }
60
+
61
+ /**
62
+ * End tracking a rule check
63
+ */
64
+ endRuleCheck(result) {
65
+ this.currentRuleExecution.checkEndTime = new Date().toISOString();
66
+ this.currentRuleExecution.checkEndTimeMs = Date.now();
67
+ this.currentRuleExecution.checkDurationMs =
68
+ this.currentRuleExecution.checkEndTimeMs - this.currentRuleExecution.checkStartTimeMs;
69
+ this.currentRuleExecution.checkResult = result;
70
+ this.currentRuleExecution.wasViolated = result === 'YES';
71
+ }
72
+
73
+ /**
74
+ * Start tracking a rule fix
75
+ */
76
+ startRuleFix(contentLength) {
77
+ this.currentRuleExecution.fixApplied = true;
78
+ this.currentRuleExecution.fixStartTime = new Date().toISOString();
79
+ this.currentRuleExecution.fixStartTimeMs = Date.now();
80
+ this.currentRuleExecution.contentLengthBefore = contentLength;
81
+ }
82
+
83
+ /**
84
+ * End tracking a rule fix
85
+ */
86
+ endRuleFix(contentLength) {
87
+ this.currentRuleExecution.fixEndTime = new Date().toISOString();
88
+ this.currentRuleExecution.fixEndTimeMs = Date.now();
89
+ this.currentRuleExecution.fixDurationMs =
90
+ this.currentRuleExecution.fixEndTimeMs - this.currentRuleExecution.fixStartTimeMs;
91
+ this.currentRuleExecution.contentLengthAfter = contentLength;
92
+ this.currentRuleExecution.contentChangedBy =
93
+ contentLength - this.currentRuleExecution.contentLengthBefore;
94
+
95
+ // Add to violations list
96
+ this.currentSession.violations.push({
97
+ ruleId: this.currentRuleExecution.ruleId,
98
+ severity: this.currentRuleExecution.severity,
99
+ fixed: true
100
+ });
101
+ }
102
+
103
+ /**
104
+ * Complete the current rule execution
105
+ */
106
+ completeRule() {
107
+ if (this.currentRuleExecution && this.currentSession) {
108
+ this.currentSession.ruleExecutions.push(this.currentRuleExecution);
109
+ this.currentRuleExecution = null;
110
+ }
111
+ }
112
+
113
+ /**
114
+ * End the current verification session
115
+ */
116
+ endSession(outputContent, rulesApplied) {
117
+ this.currentSession.endTime = new Date().toISOString();
118
+ this.currentSession.endTimeMs = Date.now();
119
+ this.currentSession.durationMs =
120
+ this.currentSession.endTimeMs - this.currentSession.startTimeMs;
121
+
122
+ this.currentSession.output = {
123
+ contentLength: outputContent.length,
124
+ contentPreview: outputContent.substring(0, 200),
125
+ contentChangedBy: outputContent.length - this.currentSession.input.contentLength,
126
+ rulesAppliedCount: rulesApplied.length
127
+ };
128
+
129
+ // Calculate statistics
130
+ const executions = this.currentSession.ruleExecutions;
131
+ this.currentSession.ruleStats = {
132
+ totalRulesChecked: executions.length,
133
+ rulesPassed: executions.filter(e => !e.wasViolated).length,
134
+ rulesViolated: executions.filter(e => e.wasViolated).length,
135
+ rulesFixed: executions.filter(e => e.fixApplied).length,
136
+ rulesSkipped: 0
137
+ };
138
+
139
+ this.currentSession.apiCalls = {
140
+ checkCalls: executions.length,
141
+ fixCalls: executions.filter(e => e.fixApplied).length,
142
+ totalCalls: executions.length + executions.filter(e => e.fixApplied).length
143
+ };
144
+
145
+ this.sessions.push(this.currentSession);
146
+ this.currentSession = null;
147
+ }
148
+
149
+ /**
150
+ * Record a simple validation check (for multi-agent validation)
151
+ * Lighter-weight alternative to full startSession/endSession flow
152
+ */
153
+ recordCheck(agentName, checkType, passed) {
154
+ const checkRecord = {
155
+ agentName,
156
+ checkType,
157
+ passed,
158
+ timestamp: new Date().toISOString()
159
+ };
160
+
161
+ // Add to sessions as a lightweight record
162
+ this.sessions.push({
163
+ sessionId: `check-${this.sessions.length + 1}`,
164
+ agentName,
165
+ checkType,
166
+ passed,
167
+ startTime: checkRecord.timestamp,
168
+ endTime: checkRecord.timestamp,
169
+ durationMs: 0,
170
+ ruleStats: {
171
+ totalRulesChecked: 1,
172
+ rulesPassed: passed ? 1 : 0,
173
+ rulesViolated: passed ? 0 : 1,
174
+ rulesFixed: 0,
175
+ rulesSkipped: 0
176
+ },
177
+ apiCalls: {
178
+ checkCalls: 1,
179
+ fixCalls: 0,
180
+ totalCalls: 1
181
+ },
182
+ violations: []
183
+ });
184
+ }
185
+
186
+ /**
187
+ * Get complete ceremony summary
188
+ */
189
+ getCeremonySummary() {
190
+ const ceremonyEndTime = Date.now();
191
+ const ceremonyDurationMs = ceremonyEndTime - this.ceremonyStartTime;
192
+
193
+ const summary = {
194
+ ceremonyName: this.ceremonyName,
195
+ ceremonyStartTime: new Date(this.ceremonyStartTime).toISOString(),
196
+ ceremonyEndTime: new Date(ceremonyEndTime).toISOString(),
197
+ ceremonyDurationMs,
198
+ verificationSessions: this.sessions,
199
+ summary: this.calculateSummary(ceremonyDurationMs),
200
+ byAgent: this.calculateByAgent(),
201
+ mostViolatedRules: this.calculateMostViolatedRules()
202
+ };
203
+
204
+ return summary;
205
+ }
206
+
207
+ /**
208
+ * Calculate overall summary statistics
209
+ */
210
+ calculateSummary(ceremonyDurationMs) {
211
+ const totalRulesChecked = this.sessions.reduce((sum, s) =>
212
+ sum + s.ruleStats.totalRulesChecked, 0);
213
+ const totalRulesViolated = this.sessions.reduce((sum, s) =>
214
+ sum + s.ruleStats.rulesViolated, 0);
215
+ const totalApiCalls = this.sessions.reduce((sum, s) =>
216
+ sum + s.apiCalls.totalCalls, 0);
217
+ const totalVerificationTimeMs = this.sessions.reduce((sum, s) =>
218
+ sum + s.durationMs, 0);
219
+
220
+ return {
221
+ totalVerificationSessions: this.sessions.length,
222
+ totalRulesChecked,
223
+ totalRulesViolated,
224
+ totalRulesFixed: totalRulesViolated,
225
+ totalApiCalls,
226
+ totalVerificationTimeMs,
227
+ verificationTimePercentage:
228
+ ceremonyDurationMs > 0 ? (totalVerificationTimeMs / ceremonyDurationMs) * 100 : 0
229
+ };
230
+ }
231
+
232
+ /**
233
+ * Calculate statistics by agent
234
+ */
235
+ calculateByAgent() {
236
+ const byAgent = {};
237
+ this.sessions.forEach(session => {
238
+ byAgent[session.agentName] = {
239
+ rulesChecked: session.ruleStats.totalRulesChecked,
240
+ rulesViolated: session.ruleStats.rulesViolated,
241
+ apiCalls: session.apiCalls.totalCalls,
242
+ durationMs: session.durationMs
243
+ };
244
+ });
245
+ return byAgent;
246
+ }
247
+
248
+ /**
249
+ * Calculate most violated rules across all sessions
250
+ */
251
+ calculateMostViolatedRules() {
252
+ const ruleViolations = {};
253
+ this.sessions.forEach(session => {
254
+ session.violations.forEach(v => {
255
+ if (!ruleViolations[v.ruleId]) {
256
+ ruleViolations[v.ruleId] = { count: 0, agents: [] };
257
+ }
258
+ ruleViolations[v.ruleId].count++;
259
+ ruleViolations[v.ruleId].agents.push(session.agentName);
260
+ });
261
+ });
262
+
263
+ return Object.entries(ruleViolations)
264
+ .map(([ruleId, data]) => ({ ruleId, ...data }))
265
+ .sort((a, b) => b.count - a.count);
266
+ }
267
+
268
+ /**
269
+ * Generate simple hash for content deduplication
270
+ */
271
+ hashContent(content) {
272
+ let hash = 0;
273
+ for (let i = 0; i < content.length; i++) {
274
+ const char = content.charCodeAt(i);
275
+ hash = ((hash << 5) - hash) + char;
276
+ hash = hash & hash;
277
+ }
278
+ return hash.toString(16);
279
+ }
280
+
281
+ /**
282
+ * Load rule profiles from disk
283
+ * @returns {object} Rule profiles by agent:rule key
284
+ */
285
+ loadRuleProfiles() {
286
+ try {
287
+ const profilePath = path.join(process.cwd(), '.avc', 'verification-profiles.json');
288
+ if (fs.existsSync(profilePath)) {
289
+ return JSON.parse(fs.readFileSync(profilePath, 'utf8'));
290
+ }
291
+ } catch (error) {
292
+ console.warn('Could not load rule profiles:', error.message);
293
+ }
294
+ return {};
295
+ }
296
+
297
+ /**
298
+ * Save rule profiles to disk
299
+ * @param {object} profiles - Rule profiles to save
300
+ */
301
+ saveRuleProfiles(profiles) {
302
+ try {
303
+ const profilePath = path.join(process.cwd(), '.avc', 'verification-profiles.json');
304
+ fs.writeFileSync(profilePath, JSON.stringify(profiles, null, 2));
305
+ } catch (error) {
306
+ console.warn('Could not save rule profiles:', error.message);
307
+ }
308
+ }
309
+
310
+ /**
311
+ * Check if rule should be skipped based on historical pass rate
312
+ * @param {string} agentName - Agent name
313
+ * @param {string} ruleId - Rule ID
314
+ * @returns {boolean} - True if rule should be skipped
315
+ */
316
+ shouldSkipRule(agentName, ruleId) {
317
+ const key = `${agentName}:${ruleId}`;
318
+ const profile = this.ruleProfiles[key];
319
+
320
+ if (!profile) {
321
+ return false;
322
+ }
323
+
324
+ // Skip if: passed >20 times, never violated, pass rate 100%
325
+ const shouldSkip = profile.passed > 20 && profile.violated === 0 && profile.passRate === 1.0;
326
+
327
+ if (shouldSkip) {
328
+ console.log(`[DEBUG] Skipping rule ${ruleId} for ${agentName} (100% pass rate over ${profile.passed} checks)`);
329
+ }
330
+
331
+ return shouldSkip;
332
+ }
333
+
334
+ /**
335
+ * Update rule profile after check
336
+ * @param {string} agentName - Agent name
337
+ * @param {string} ruleId - Rule ID
338
+ * @param {boolean} violated - Whether rule was violated
339
+ */
340
+ updateRuleProfile(agentName, ruleId, violated) {
341
+ const key = `${agentName}:${ruleId}`;
342
+
343
+ if (!this.ruleProfiles[key]) {
344
+ this.ruleProfiles[key] = { passed: 0, violated: 0, passRate: 0 };
345
+ }
346
+
347
+ if (violated) {
348
+ this.ruleProfiles[key].violated++;
349
+ } else {
350
+ this.ruleProfiles[key].passed++;
351
+ }
352
+
353
+ const total = this.ruleProfiles[key].passed + this.ruleProfiles[key].violated;
354
+ this.ruleProfiles[key].passRate = total > 0 ? this.ruleProfiles[key].passed / total : 0;
355
+
356
+ console.log(`[DEBUG] Updated profile for ${key}: ${this.ruleProfiles[key].passed} passed, ${this.ruleProfiles[key].violated} violated (${(this.ruleProfiles[key].passRate * 100).toFixed(1)}% pass rate)`);
357
+ }
358
+
359
+ /**
360
+ * Save tracking data to files
361
+ */
362
+ saveToFile() {
363
+ const summary = this.getCeremonySummary();
364
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
365
+
366
+ // Include ceremony name in filename: {ceremony}-verification-{timestamp}.json
367
+ const jsonPath = path.join(process.cwd(), '.avc', 'logs',
368
+ `${this.ceremonyName}-verification-${timestamp}.json`);
369
+ const summaryPath = path.join(process.cwd(), '.avc', 'logs',
370
+ `${this.ceremonyName}-verification-summary-${timestamp}.txt`);
371
+
372
+ try {
373
+ // Save JSON
374
+ fs.writeFileSync(jsonPath, JSON.stringify(summary, null, 2));
375
+
376
+ // Save human-readable summary
377
+ const summaryText = this.formatSummaryText(summary);
378
+ fs.writeFileSync(summaryPath, summaryText);
379
+
380
+ // Save rule profiles
381
+ this.saveRuleProfiles(this.ruleProfiles);
382
+
383
+ // Clear cache after saving
384
+ if (this.verificationCache) {
385
+ console.log('[DEBUG] Verification cache cleared');
386
+ this.verificationCache.clear();
387
+ }
388
+
389
+ return { jsonPath, summaryPath };
390
+ } catch (error) {
391
+ console.error('Error saving verification tracking:', error.message);
392
+ return { jsonPath: null, summaryPath: null };
393
+ }
394
+ }
395
+
396
+ /**
397
+ * Format summary as human-readable text
398
+ */
399
+ formatSummaryText(summary) {
400
+ const text = [];
401
+ text.push('='.repeat(80));
402
+ text.push(`VERIFICATION SUMMARY: ${summary.ceremonyName}`);
403
+ text.push(`Time: ${summary.ceremonyStartTime}`);
404
+ text.push('='.repeat(80));
405
+ text.push('');
406
+
407
+ text.push('OVERALL STATISTICS');
408
+ text.push('-'.repeat(80));
409
+ text.push(`Total verification sessions: ${summary.summary.totalVerificationSessions}`);
410
+ text.push(`Total rules checked: ${summary.summary.totalRulesChecked}`);
411
+ text.push(`Total rules violated: ${summary.summary.totalRulesViolated}`);
412
+ text.push(`Total API calls: ${summary.summary.totalApiCalls}`);
413
+ text.push(`Total verification time: ${(summary.summary.totalVerificationTimeMs / 1000).toFixed(2)}s`);
414
+ text.push(`Verification overhead: ${summary.summary.verificationTimePercentage.toFixed(1)}%`);
415
+ text.push('');
416
+
417
+ text.push('BY AGENT');
418
+ text.push('-'.repeat(80));
419
+ Object.entries(summary.byAgent).forEach(([agent, stats]) => {
420
+ text.push(`${agent}:`);
421
+ text.push(` Rules checked: ${stats.rulesChecked}`);
422
+ text.push(` Rules violated: ${stats.rulesViolated}`);
423
+ text.push(` API calls: ${stats.apiCalls}`);
424
+ text.push(` Duration: ${(stats.durationMs / 1000).toFixed(2)}s`);
425
+ text.push('');
426
+ });
427
+
428
+ if (summary.mostViolatedRules.length > 0) {
429
+ text.push('MOST VIOLATED RULES');
430
+ text.push('-'.repeat(80));
431
+ summary.mostViolatedRules.forEach(rule => {
432
+ text.push(`${rule.ruleId}: ${rule.count} violations`);
433
+ text.push(` Agents: ${rule.agents.join(', ')}`);
434
+ });
435
+ text.push('');
436
+ }
437
+
438
+ text.push('='.repeat(80));
439
+ return text.join('\n');
440
+ }
441
+
442
+ /**
443
+ * Log session summary to console
444
+ */
445
+ logSessionSummary() {
446
+ const session = this.sessions[this.sessions.length - 1];
447
+ if (!session) return;
448
+
449
+ console.log('');
450
+ console.log('='.repeat(60));
451
+ console.log(`VERIFICATION SESSION: ${session.agentName}`);
452
+ console.log('='.repeat(60));
453
+ console.log(`Rules checked: ${session.ruleStats.totalRulesChecked}`);
454
+ console.log(`Rules violated: ${session.ruleStats.rulesViolated} (${((session.ruleStats.rulesViolated / session.ruleStats.totalRulesChecked) * 100).toFixed(1)}%)`);
455
+ console.log(`Rules fixed: ${session.ruleStats.rulesFixed}`);
456
+ console.log(`API calls: ${session.apiCalls.totalCalls} (${session.apiCalls.checkCalls} checks + ${session.apiCalls.fixCalls} fixes)`);
457
+ console.log(`Duration: ${(session.durationMs / 1000).toFixed(2)}s`);
458
+ console.log(`Content changed: ${session.output.contentChangedBy} chars`);
459
+
460
+ if (session.violations.length > 0) {
461
+ console.log('');
462
+ console.log('Violations fixed:');
463
+ session.violations.forEach(v => {
464
+ console.log(` - ${v.ruleId} (${v.severity})`);
465
+ });
466
+ }
467
+ console.log('='.repeat(60));
468
+ console.log('');
469
+ }
470
+
471
+ /**
472
+ * Log ceremony summary to console
473
+ */
474
+ logCeremonySummary() {
475
+ const summary = this.getCeremonySummary();
476
+
477
+ console.log('');
478
+ console.log('Verification Summary');
479
+ console.log('');
480
+ console.log(`Total verification sessions: ${summary.summary.totalVerificationSessions}`);
481
+ console.log(`Total rules checked: ${summary.summary.totalRulesChecked}`);
482
+ console.log(`Total rules violated: ${summary.summary.totalRulesViolated} (${((summary.summary.totalRulesViolated / summary.summary.totalRulesChecked) * 100).toFixed(1)}%)`);
483
+ console.log(`Total API calls: ${summary.summary.totalApiCalls}`);
484
+ console.log(`Total verification time: ${(summary.summary.totalVerificationTimeMs / 1000).toFixed(2)}s (${summary.summary.verificationTimePercentage.toFixed(1)}% of ceremony)`);
485
+ console.log('');
486
+
487
+ if (Object.keys(summary.byAgent).length > 0) {
488
+ console.log('By Agent:');
489
+ Object.entries(summary.byAgent).forEach(([agent, stats]) => {
490
+ console.log(` ${agent}: ${stats.rulesViolated} violations, ${stats.apiCalls} calls, ${(stats.durationMs / 1000).toFixed(2)}s`);
491
+ });
492
+ console.log('');
493
+ }
494
+
495
+ if (summary.mostViolatedRules.length > 0) {
496
+ console.log('Most Violated Rules:');
497
+ summary.mostViolatedRules.forEach((rule, index) => {
498
+ console.log(` ${index + 1}. ${rule.ruleId}: ${rule.count} violations (${rule.agents.join(', ')})`);
499
+ });
500
+ console.log('');
501
+ }
502
+ }
503
+
504
+ /**
505
+ * Clean up old verification log files (keep last N logs per ceremony)
506
+ */
507
+ static cleanupOldLogs(ceremonyName, projectRoot = process.cwd(), keepCount = 10) {
508
+ const logsDir = path.join(projectRoot, '.avc', 'logs');
509
+
510
+ if (!fs.existsSync(logsDir)) return;
511
+
512
+ try {
513
+ const files = fs.readdirSync(logsDir);
514
+
515
+ // Find all verification files for this ceremony
516
+ const jsonFiles = [];
517
+ const summaryFiles = [];
518
+
519
+ files.forEach(file => {
520
+ if (file.startsWith(`${ceremonyName}-verification-`) && file.endsWith('.json')) {
521
+ jsonFiles.push({
522
+ name: file,
523
+ path: path.join(logsDir, file),
524
+ mtime: fs.statSync(path.join(logsDir, file)).mtime
525
+ });
526
+ }
527
+ if (file.startsWith(`${ceremonyName}-verification-summary-`) && file.endsWith('.txt')) {
528
+ summaryFiles.push({
529
+ name: file,
530
+ path: path.join(logsDir, file),
531
+ mtime: fs.statSync(path.join(logsDir, file)).mtime
532
+ });
533
+ }
534
+ });
535
+
536
+ // Sort by modification time (newest first)
537
+ jsonFiles.sort((a, b) => b.mtime - a.mtime);
538
+ summaryFiles.sort((a, b) => b.mtime - a.mtime);
539
+
540
+ // Delete old JSON files
541
+ jsonFiles.slice(keepCount).forEach(file => {
542
+ try {
543
+ fs.unlinkSync(file.path);
544
+ } catch (error) {
545
+ // Ignore deletion errors
546
+ }
547
+ });
548
+
549
+ // Delete old summary files
550
+ summaryFiles.slice(keepCount).forEach(file => {
551
+ try {
552
+ fs.unlinkSync(file.path);
553
+ } catch (error) {
554
+ // Ignore deletion errors
555
+ }
556
+ });
557
+ } catch (error) {
558
+ // Silently fail
559
+ }
560
+ }
561
+ }
562
+
563
+ export { VerificationTracker };