swarm-orchestrator 7.0.0-alpha.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 (174) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +199 -0
  3. package/agents/reviewer.agent.md +50 -0
  4. package/agents/worker.agent.md +41 -0
  5. package/config/default-agents.yaml +56 -0
  6. package/config/pm-agent.yaml +36 -0
  7. package/config/quality-gates.yaml +88 -0
  8. package/config/repair-agent.yaml +34 -0
  9. package/config/semgrep-rules/complexity-mismatch.yaml +6 -0
  10. package/config/semgrep-rules/exception-swallowing.yaml +13 -0
  11. package/config/semgrep-rules/hardcoded-answer.yaml +6 -0
  12. package/config/semgrep-rules/mock-mutation.yaml +6 -0
  13. package/config/semgrep-rules/test-modification.yaml +6 -0
  14. package/config/user-agents.yaml +23 -0
  15. package/dist/src/adapters/adapter-factory.js +29 -0
  16. package/dist/src/adapters/agent-adapter.js +32 -0
  17. package/dist/src/adapters/claude-code-adapter.js +126 -0
  18. package/dist/src/adapters/claude-code-teams.js +119 -0
  19. package/dist/src/adapters/codex-adapter.js +118 -0
  20. package/dist/src/adapters/copilot-adapter.js +224 -0
  21. package/dist/src/adapters/fatal-error-classifier.js +88 -0
  22. package/dist/src/adapters/index.js +44 -0
  23. package/dist/src/adapters/persistent-session.js +204 -0
  24. package/dist/src/adapters/process-supervisor.js +199 -0
  25. package/dist/src/agents-exporter.js +398 -0
  26. package/dist/src/analytics-log.js +161 -0
  27. package/dist/src/baseline-scanner.js +65 -0
  28. package/dist/src/bootstrap-evidence.js +88 -0
  29. package/dist/src/bootstrap-orchestrator.js +205 -0
  30. package/dist/src/bootstrap-types.js +5 -0
  31. package/dist/src/branch-merger.js +427 -0
  32. package/dist/src/cli/attest-handlers.js +44 -0
  33. package/dist/src/cli/cost-prompt.js +51 -0
  34. package/dist/src/cli/demo-handlers.js +274 -0
  35. package/dist/src/cli/flags.js +152 -0
  36. package/dist/src/cli/index.js +57 -0
  37. package/dist/src/cli/live-status.js +186 -0
  38. package/dist/src/cli/misc-handlers.js +242 -0
  39. package/dist/src/cli/plan-handlers.js +350 -0
  40. package/dist/src/cli/share-handlers.js +163 -0
  41. package/dist/src/cli/status-handlers.js +457 -0
  42. package/dist/src/cli/swarm-handlers.js +638 -0
  43. package/dist/src/cli/usage.js +72 -0
  44. package/dist/src/cli.js +217 -0
  45. package/dist/src/commit-pattern-detector.js +143 -0
  46. package/dist/src/commit-quality-analyzer.js +38 -0
  47. package/dist/src/config-loader.js +339 -0
  48. package/dist/src/context-broker.js +358 -0
  49. package/dist/src/copilot-cli-wrapper.js +258 -0
  50. package/dist/src/cost-estimator.js +241 -0
  51. package/dist/src/defaults.js +18 -0
  52. package/dist/src/demo-mode.js +180 -0
  53. package/dist/src/deployment-handler.js +78 -0
  54. package/dist/src/deployment-manager.js +228 -0
  55. package/dist/src/execution-queue.js +196 -0
  56. package/dist/src/external-tool-manager.js +184 -0
  57. package/dist/src/gate-prompt-builder.js +117 -0
  58. package/dist/src/gate-remediation.js +173 -0
  59. package/dist/src/github-issues-ingester.js +152 -0
  60. package/dist/src/github-mcp-integrator.js +164 -0
  61. package/dist/src/hook-generator.js +229 -0
  62. package/dist/src/index.js +48 -0
  63. package/dist/src/knowledge-base.js +300 -0
  64. package/dist/src/logger.js +111 -0
  65. package/dist/src/meta-analyzer.js +208 -0
  66. package/dist/src/metrics-collector.js +209 -0
  67. package/dist/src/metrics-types.js +5 -0
  68. package/dist/src/multi-repo-coordinator.js +179 -0
  69. package/dist/src/orchestrator/async-meta-analysis.js +84 -0
  70. package/dist/src/orchestrator/fatal-run-error.js +43 -0
  71. package/dist/src/orchestrator/final-gates-remediation.js +258 -0
  72. package/dist/src/orchestrator/git-state-utils.js +119 -0
  73. package/dist/src/orchestrator/pause-controller.js +55 -0
  74. package/dist/src/orchestrator/replan-runner.js +258 -0
  75. package/dist/src/orchestrator/step-executor.js +391 -0
  76. package/dist/src/orchestrator/wave-scheduler-loop.js +204 -0
  77. package/dist/src/owasp-mapper.js +153 -0
  78. package/dist/src/owasp-report-renderer.js +39 -0
  79. package/dist/src/plan-files.js +142 -0
  80. package/dist/src/plan-generator.js +1207 -0
  81. package/dist/src/pm-agent.js +296 -0
  82. package/dist/src/post-run-reporter.js +203 -0
  83. package/dist/src/pr-automation.js +103 -0
  84. package/dist/src/pr-manager.js +318 -0
  85. package/dist/src/presenter/index.js +209 -0
  86. package/dist/src/prompt-builder.js +173 -0
  87. package/dist/src/quality-gates/config-loader.js +196 -0
  88. package/dist/src/quality-gates/default-config.js +243 -0
  89. package/dist/src/quality-gates/file-utils.js +152 -0
  90. package/dist/src/quality-gates/gate-runner.js +171 -0
  91. package/dist/src/quality-gates/gates/accessibility.js +355 -0
  92. package/dist/src/quality-gates/gates/duplicate-blocks.js +144 -0
  93. package/dist/src/quality-gates/gates/hardcoded-config.js +52 -0
  94. package/dist/src/quality-gates/gates/readme-claims.js +62 -0
  95. package/dist/src/quality-gates/gates/runtime-checks.js +265 -0
  96. package/dist/src/quality-gates/gates/scaffold-defaults.js +108 -0
  97. package/dist/src/quality-gates/gates/test-coverage.js +240 -0
  98. package/dist/src/quality-gates/gates/test-file-protection.js +85 -0
  99. package/dist/src/quality-gates/gates/test-isolation.js +74 -0
  100. package/dist/src/quality-gates/index.js +17 -0
  101. package/dist/src/quality-gates/registry.js +205 -0
  102. package/dist/src/quality-gates/types.js +2 -0
  103. package/dist/src/quick-fix-mode.js +302 -0
  104. package/dist/src/recipe-loader.js +122 -0
  105. package/dist/src/repair-agent.js +396 -0
  106. package/dist/src/repo-analyzer.js +342 -0
  107. package/dist/src/report-generator.js +146 -0
  108. package/dist/src/report-renderer.js +90 -0
  109. package/dist/src/requirement-filter.js +52 -0
  110. package/dist/src/sarif-formatter.js +140 -0
  111. package/dist/src/scheduling/dependency-analyzer.js +178 -0
  112. package/dist/src/scheduling/work-stealing-queue.js +123 -0
  113. package/dist/src/secret-redactor.js +90 -0
  114. package/dist/src/session-executor.js +587 -0
  115. package/dist/src/session-manager.js +221 -0
  116. package/dist/src/share/transcript-verification.js +128 -0
  117. package/dist/src/share-parser.js +477 -0
  118. package/dist/src/spinner.js +146 -0
  119. package/dist/src/step-runner.js +365 -0
  120. package/dist/src/swarm-orchestrator.js +686 -0
  121. package/dist/src/task-classifier.js +134 -0
  122. package/dist/src/test-command-discovery.js +123 -0
  123. package/dist/src/text-similarity.js +24 -0
  124. package/dist/src/tier-maps.js +158 -0
  125. package/dist/src/types.js +5 -0
  126. package/dist/src/url-shortener.js +135 -0
  127. package/dist/src/verification/attestation.js +166 -0
  128. package/dist/src/verification/cheat-detector.js +240 -0
  129. package/dist/src/verification/command-runner.js +70 -0
  130. package/dist/src/verification/composite-score.js +157 -0
  131. package/dist/src/verification/cosign-attestation.js +137 -0
  132. package/dist/src/verification/diff-analysis.js +89 -0
  133. package/dist/src/verification/differential-gate.js +173 -0
  134. package/dist/src/verification/index.js +41 -0
  135. package/dist/src/verification/mutation-gate.js +242 -0
  136. package/dist/src/verification/property-gate.js +201 -0
  137. package/dist/src/verification/test-synthesizer.js +243 -0
  138. package/dist/src/verifier/outcome-checks.js +396 -0
  139. package/dist/src/verifier/transcript-checks.js +207 -0
  140. package/dist/src/verifier/verification-reporters.js +148 -0
  141. package/dist/src/verifier-engine.js +491 -0
  142. package/dist/src/wave-resizer.js +131 -0
  143. package/dist/src/wave-scheduler.js +44 -0
  144. package/dist/src/worktree-manager.js +368 -0
  145. package/dist/src/worktree-reserved-paths.js +97 -0
  146. package/package.json +80 -0
  147. package/plugin/agents/.gitkeep +0 -0
  148. package/plugin/agents/backend_master.agent.md +72 -0
  149. package/plugin/agents/devops_pro.agent.md +45 -0
  150. package/plugin/agents/frontend_expert.agent.md +59 -0
  151. package/plugin/agents/integrator_finalizer.agent.md +44 -0
  152. package/plugin/agents/meta_reviewer.agent.md +44 -0
  153. package/plugin/agents/security_auditor.agent.md +43 -0
  154. package/plugin/agents/tester_elite.agent.md +43 -0
  155. package/plugin/hooks/hooks.json +19 -0
  156. package/plugin/hooks/post-tool-use.json +9 -0
  157. package/plugin/hooks/pre-tool-use.json +9 -0
  158. package/plugin/plugin.json +47 -0
  159. package/plugin/skills/swarm-gates/SKILL.md +53 -0
  160. package/plugin/skills/swarm-orchestrate/SKILL.md +34 -0
  161. package/plugin/skills/swarm-verify/SKILL.md +44 -0
  162. package/templates/README.md +35 -0
  163. package/templates/cli-tool.json +31 -0
  164. package/templates/fullstack.json +52 -0
  165. package/templates/library.json +38 -0
  166. package/templates/react-app.json +45 -0
  167. package/templates/recipes/add-api-docs.json +35 -0
  168. package/templates/recipes/add-auth.json +47 -0
  169. package/templates/recipes/add-ci.json +39 -0
  170. package/templates/recipes/add-tests.json +39 -0
  171. package/templates/recipes/migrate-to-ts.json +42 -0
  172. package/templates/recipes/refactor-modularize.json +44 -0
  173. package/templates/recipes/security-audit.json +35 -0
  174. package/templates/rest-api.json +38 -0
@@ -0,0 +1,221 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.SessionManager = void 0;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const share_parser_1 = require("./share-parser");
40
+ class SessionManager {
41
+ runsDir;
42
+ constructor(runsDir) {
43
+ this.runsDir = runsDir || path.join(process.cwd(), 'runs');
44
+ }
45
+ /**
46
+ * create a new run directory structure
47
+ */
48
+ createRun(runId) {
49
+ const runDir = path.join(this.runsDir, runId);
50
+ if (!fs.existsSync(this.runsDir)) {
51
+ fs.mkdirSync(this.runsDir, { recursive: true });
52
+ }
53
+ if (fs.existsSync(runDir)) {
54
+ throw new Error(`run ${runId} already exists`);
55
+ }
56
+ fs.mkdirSync(runDir);
57
+ fs.mkdirSync(path.join(runDir, 'steps'));
58
+ return runDir;
59
+ }
60
+ /**
61
+ * create a step directory within a run
62
+ */
63
+ createStepDir(runId, stepNumber) {
64
+ const stepDir = path.join(this.runsDir, runId, 'steps', this.padStepNumber(stepNumber));
65
+ if (!fs.existsSync(stepDir)) {
66
+ fs.mkdirSync(stepDir, { recursive: true });
67
+ }
68
+ return stepDir;
69
+ }
70
+ /**
71
+ * import a /share transcript and parse it
72
+ */
73
+ importShare(runId, stepNumber, agentName, transcriptPathOrContent) {
74
+ const stepDir = this.createStepDir(runId, stepNumber);
75
+ // determine if input is path or content
76
+ let content;
77
+ if (fs.existsSync(transcriptPathOrContent)) {
78
+ // it's a file path
79
+ content = fs.readFileSync(transcriptPathOrContent, 'utf8');
80
+ }
81
+ else if (transcriptPathOrContent.startsWith('http')) {
82
+ // it's a URL - not supported yet
83
+ throw new Error('URL import not yet implemented');
84
+ }
85
+ else {
86
+ // treat as raw content
87
+ content = transcriptPathOrContent;
88
+ }
89
+ // parse the share transcript
90
+ const parser = new share_parser_1.ShareParser();
91
+ const index = parser.parse(content);
92
+ // save the share transcript to step directory
93
+ const sharePath = path.join(stepDir, 'share.md');
94
+ fs.writeFileSync(sharePath, content, 'utf8');
95
+ // save the index
96
+ const indexPath = path.join(stepDir, 'index.json');
97
+ fs.writeFileSync(indexPath, JSON.stringify(index, null, 2), 'utf8');
98
+ // create step share record
99
+ const stepShare = {
100
+ stepNumber,
101
+ agentName,
102
+ transcriptPath: sharePath,
103
+ index,
104
+ importedAt: new Date().toISOString()
105
+ };
106
+ // update run context
107
+ this.updateRunContext(runId, stepShare);
108
+ return stepShare;
109
+ }
110
+ /**
111
+ * get prior context for a step (all previous shares)
112
+ */
113
+ getPriorContext(runId, currentStep) {
114
+ const runContextPath = path.join(this.runsDir, runId, 'context.json');
115
+ if (!fs.existsSync(runContextPath)) {
116
+ return [];
117
+ }
118
+ const context = JSON.parse(fs.readFileSync(runContextPath, 'utf8'));
119
+ return context.shares
120
+ .filter(share => share.stepNumber < currentStep)
121
+ .sort((a, b) => a.stepNumber - b.stepNumber);
122
+ }
123
+ /**
124
+ * generate context summary for next step
125
+ */
126
+ generateContextSummary(runId, currentStep) {
127
+ const priorShares = this.getPriorContext(runId, currentStep);
128
+ if (priorShares.length === 0) {
129
+ return 'no prior context';
130
+ }
131
+ const lines = [];
132
+ lines.push('context from prior steps:');
133
+ lines.push('');
134
+ for (const share of priorShares) {
135
+ lines.push(`step ${share.stepNumber} (${share.agentName}):`);
136
+ if (share.index.changedFiles.length > 0) {
137
+ lines.push(` changed files: ${share.index.changedFiles.join(', ')}`);
138
+ }
139
+ if (share.index.testsRun.length > 0) {
140
+ const verifiedTests = share.index.testsRun.filter(t => t.verified);
141
+ if (verifiedTests.length > 0) {
142
+ lines.push(` tests verified: ${verifiedTests.map(t => t.command).join(', ')}`);
143
+ }
144
+ }
145
+ if (share.index.prLinks.length > 0) {
146
+ lines.push(` PRs created: ${share.index.prLinks.join(', ')}`);
147
+ }
148
+ // check for unverified claims
149
+ const unverified = share.index.claims.filter(c => !c.verified);
150
+ if (unverified.length > 0) {
151
+ lines.push(` ⚠ unverified claims: ${unverified.length}`);
152
+ unverified.forEach(claim => {
153
+ lines.push(` - ${claim.claim.substring(0, 80)}`);
154
+ lines.push(` reason: ${claim.evidence}`);
155
+ });
156
+ }
157
+ lines.push('');
158
+ }
159
+ return lines.join('\n');
160
+ }
161
+ /**
162
+ * save summary for a step
163
+ */
164
+ saveSummary(runId, stepNumber, summary) {
165
+ const stepDir = this.createStepDir(runId, stepNumber);
166
+ const summaryPath = path.join(stepDir, 'summary.md');
167
+ fs.writeFileSync(summaryPath, summary, 'utf8');
168
+ }
169
+ /**
170
+ * save verification notes for a step
171
+ */
172
+ saveVerification(runId, stepNumber, verification) {
173
+ const stepDir = this.createStepDir(runId, stepNumber);
174
+ const verificationPath = path.join(stepDir, 'verification.md');
175
+ fs.writeFileSync(verificationPath, verification, 'utf8');
176
+ }
177
+ /**
178
+ * get unverified claims across all steps in a run
179
+ */
180
+ getUnverifiedClaims(runId) {
181
+ const runContextPath = path.join(this.runsDir, runId, 'context.json');
182
+ if (!fs.existsSync(runContextPath)) {
183
+ return [];
184
+ }
185
+ const context = JSON.parse(fs.readFileSync(runContextPath, 'utf8'));
186
+ return context.shares
187
+ .map(share => ({
188
+ step: share.stepNumber,
189
+ agent: share.agentName,
190
+ claims: share.index.claims.filter(c => !c.verified)
191
+ }))
192
+ .filter(item => item.claims.length > 0);
193
+ }
194
+ updateRunContext(runId, stepShare) {
195
+ const runContextPath = path.join(this.runsDir, runId, 'context.json');
196
+ let context;
197
+ if (fs.existsSync(runContextPath)) {
198
+ context = JSON.parse(fs.readFileSync(runContextPath, 'utf8'));
199
+ }
200
+ else {
201
+ context = {
202
+ runId,
203
+ runDir: path.join(this.runsDir, runId),
204
+ shares: []
205
+ };
206
+ }
207
+ // remove any existing share for this step (replace)
208
+ context.shares = context.shares.filter(s => s.stepNumber !== stepShare.stepNumber);
209
+ // add new share
210
+ context.shares.push(stepShare);
211
+ // sort by step number
212
+ context.shares.sort((a, b) => a.stepNumber - b.stepNumber);
213
+ // save
214
+ fs.writeFileSync(runContextPath, JSON.stringify(context, null, 2), 'utf8');
215
+ }
216
+ padStepNumber(stepNumber) {
217
+ return stepNumber.toString().padStart(2, '0');
218
+ }
219
+ }
220
+ exports.SessionManager = SessionManager;
221
+ exports.default = SessionManager;
@@ -0,0 +1,128 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.extractClaims = extractClaims;
4
+ /**
5
+ * Probabilistic claim-verification pass: scan transcript lines for natural-language
6
+ * claims (tests passing, build successful, commit made) and cross-reference each
7
+ * claim against the deterministic extraction results already produced by the
8
+ * transcript-extraction pass.
9
+ *
10
+ * This is heuristic — line patterns are matched case-insensitively and lines
11
+ * that look like agent-prompt instructions are skipped. Returns a claims[] with
12
+ * verified=true when supporting evidence exists in the index, verified=false
13
+ * otherwise (with a reason).
14
+ */
15
+ function extractClaims(lines, index) {
16
+ const claims = [];
17
+ const instructionPrefixes = [
18
+ 'scope:',
19
+ 'done when:',
20
+ 'role:',
21
+ 'rules:',
22
+ 'rule:',
23
+ 'context:',
24
+ 'you are ',
25
+ 'your task',
26
+ 'your job',
27
+ 'your goal',
28
+ 'important:',
29
+ 'note:',
30
+ 'constraints:',
31
+ 'requirements:',
32
+ ];
33
+ for (const line of lines) {
34
+ const lowerLine = line.toLowerCase();
35
+ const trimmedLower = lowerLine.trim().toLowerCase();
36
+ if (instructionPrefixes.some((prefix) => trimmedLower.startsWith(prefix))) {
37
+ continue;
38
+ }
39
+ if (trimmedLower.match(/^[-*]\s+(ensure|make sure|verify|confirm|must|should)\b/)) {
40
+ continue;
41
+ }
42
+ // tests passing
43
+ if ((lowerLine.match(/\btests?\b/) && lowerLine.match(/\b(pass|passed|passing)\b/)) ||
44
+ lowerLine.includes('all tests passed') ||
45
+ lowerLine.includes('tests are passing')) {
46
+ const hasVerifiedTests = index.testsRun.some((t) => t.verified);
47
+ claims.push({
48
+ claim: line.trim(),
49
+ verified: hasVerifiedTests,
50
+ evidence: hasVerifiedTests
51
+ ? `verified test command: ${index.testsRun.find((t) => t.verified)?.command}`
52
+ : 'no test execution found in transcript',
53
+ });
54
+ }
55
+ // build succeeded
56
+ if (lowerLine.match(/\b(build|builds)\s+(succeed|succeeded|passed|successful)/i) ||
57
+ lowerLine.includes('compiled successfully')) {
58
+ const hasBuildCommand = index.buildOperations.some((b) => b.verified);
59
+ claims.push({
60
+ claim: line.trim(),
61
+ verified: hasBuildCommand,
62
+ evidence: hasBuildCommand
63
+ ? `verified build with: ${index.buildOperations.find((b) => b.verified)?.tool}`
64
+ : 'no build command found in transcript',
65
+ });
66
+ }
67
+ // lint passing
68
+ if (lowerLine.match(/\b(lint|linting)\s+(pass|passed|succeeded)/i) ||
69
+ lowerLine.match(/no\s+lint\s+errors?/i)) {
70
+ const hasLintCommand = index.lintOperations.some((l) => l.verified);
71
+ claims.push({
72
+ claim: line.trim(),
73
+ verified: hasLintCommand,
74
+ evidence: hasLintCommand
75
+ ? `verified lint with: ${index.lintOperations.find((l) => l.verified)?.tool}`
76
+ : 'no lint command found in transcript',
77
+ });
78
+ }
79
+ // deployment
80
+ if (lowerLine.match(/\b(deploy|deployed|deployment)\s+(succeed|succeeded|successful)/i)) {
81
+ const hasDeployCommand = index.commandsExecuted.some((cmd) => cmd.includes('deploy') || cmd.includes('publish'));
82
+ claims.push({
83
+ claim: line.trim(),
84
+ verified: hasDeployCommand,
85
+ evidence: hasDeployCommand
86
+ ? 'verified deployment command found'
87
+ : 'no deployment command found in transcript',
88
+ });
89
+ }
90
+ // package install
91
+ if (lowerLine.match(/\b(installed|added)\s+package/i) || lowerLine.match(/\bnpm\s+install/i)) {
92
+ const hasPackageOp = index.packageOperations.some((op) => op.operation === 'install');
93
+ claims.push({
94
+ claim: line.trim(),
95
+ verified: hasPackageOp,
96
+ evidence: hasPackageOp
97
+ ? `verified package install: ${index.packageOperations.find((op) => op.operation === 'install')?.packages.join(', ')}`
98
+ : 'no package install command found',
99
+ });
100
+ }
101
+ // git commit
102
+ if (lowerLine.match(/\bcommitted\s+(the\s+)?changes?/i) || lowerLine.match(/\bgit\s+commit/i)) {
103
+ const hasCommit = index.gitCommits.length > 0;
104
+ claims.push({
105
+ claim: line.trim(),
106
+ verified: hasCommit,
107
+ evidence: hasCommit
108
+ ? `verified commit: ${index.gitCommits[0]?.message}`
109
+ : 'no git commit found in transcript',
110
+ });
111
+ }
112
+ // MCP consultation
113
+ if (lowerLine.match(/\b(consulted|checked|reviewed)\s+(mcp|github|issues?)/i) &&
114
+ (lowerLine.includes('mcp') ||
115
+ lowerLine.includes('github') ||
116
+ lowerLine.includes('context'))) {
117
+ const hasMcp = index.mcpSections.some((m) => m.verified);
118
+ claims.push({
119
+ claim: line.trim(),
120
+ verified: hasMcp,
121
+ evidence: hasMcp
122
+ ? 'verified MCP Evidence section found'
123
+ : 'no MCP Evidence section or insufficient evidence',
124
+ });
125
+ }
126
+ }
127
+ return claims;
128
+ }