continuous-improvement 3.1.0 → 3.9.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 (136) hide show
  1. package/.claude-plugin/marketplace.json +66 -0
  2. package/CHANGELOG.md +216 -0
  3. package/QUICKSTART.md +79 -12
  4. package/README.md +229 -349
  5. package/SKILL.md +87 -9
  6. package/action.yml +1 -1
  7. package/bin/analyze.sh +9 -1
  8. package/bin/backfill.mjs +172 -0
  9. package/bin/check-doc-runtime-claims.mjs +120 -0
  10. package/bin/check-docs-substrings.mjs +333 -0
  11. package/bin/check-everything-mirror.mjs +145 -0
  12. package/bin/check-routing-targets.mjs +151 -0
  13. package/bin/check-skill-law-tag.mjs +128 -0
  14. package/bin/check-skill-mirror.mjs +119 -0
  15. package/bin/check-skill-tiers.mjs +116 -0
  16. package/bin/check-third-party-shape.mjs +202 -0
  17. package/bin/generate-plugin-manifests.mjs +171 -0
  18. package/bin/harvest-friction.mjs +279 -0
  19. package/bin/hook-stats.mjs +258 -0
  20. package/bin/install.mjs +407 -499
  21. package/bin/lint-transcript.mjs +182 -210
  22. package/bin/mcp-server.mjs +834 -608
  23. package/bin/observe.mjs +148 -0
  24. package/bin/pre-commit-block-strays.sh +49 -0
  25. package/bin/refresh-third-party.mjs +416 -0
  26. package/bin/unified-cli.mjs +533 -0
  27. package/commands/continuous-improvement.md +43 -2
  28. package/commands/discipline.md +14 -0
  29. package/commands/harvest.md +76 -0
  30. package/commands/learn-eval.md +117 -0
  31. package/commands/planning-with-files.md +66 -0
  32. package/commands/proceed-with-the-recommendation.md +62 -0
  33. package/commands/ralph.md +103 -0
  34. package/commands/release-train.md +81 -0
  35. package/commands/seven-laws.md +16 -0
  36. package/commands/superpowers.md +180 -0
  37. package/commands/swarm.md +101 -0
  38. package/commands/workspace-surface-audit.md +77 -0
  39. package/hooks/gateguard.mjs +172 -0
  40. package/hooks/observe.sh +42 -4
  41. package/hooks/session.sh +3 -3
  42. package/hooks/three-section-close.mjs +181 -0
  43. package/instinct-packs/meta.json +16 -0
  44. package/lib/cli-anything.mjs +401 -0
  45. package/lib/compound-engineering.mjs +831 -0
  46. package/lib/gateguard-state.mjs +85 -0
  47. package/lib/observe-event.mjs +128 -0
  48. package/lib/plugin-metadata.mjs +435 -0
  49. package/lib/pm-marketplace.mjs +61 -0
  50. package/lib/pm-skills.mjs +1274 -0
  51. package/lib/resolve-home-dir.mjs +43 -0
  52. package/lib/skill-tiers.mjs +137 -0
  53. package/lib/unified-plugin.mjs +924 -0
  54. package/llms.txt +32 -7
  55. package/package.json +29 -19
  56. package/plugins/beginner.json +17 -6
  57. package/plugins/continuous-improvement/.claude-plugin/marketplace.json +20 -0
  58. package/plugins/continuous-improvement/.claude-plugin/plugin.json +26 -0
  59. package/plugins/continuous-improvement/LICENSE +21 -0
  60. package/plugins/continuous-improvement/README.md +57 -0
  61. package/plugins/continuous-improvement/agents/README.md +120 -0
  62. package/plugins/continuous-improvement/agents/code-reviewer.md +97 -0
  63. package/plugins/continuous-improvement/agents/security-auditor.md +101 -0
  64. package/plugins/continuous-improvement/agents/test-engineer.md +95 -0
  65. package/plugins/continuous-improvement/bin/backfill.mjs +172 -0
  66. package/plugins/continuous-improvement/bin/mcp-server.mjs +889 -0
  67. package/plugins/continuous-improvement/bin/observe.mjs +148 -0
  68. package/plugins/continuous-improvement/commands/continuous-improvement.md +115 -0
  69. package/plugins/continuous-improvement/commands/dashboard.md +56 -0
  70. package/plugins/continuous-improvement/commands/discipline.md +51 -0
  71. package/plugins/continuous-improvement/commands/harvest.md +76 -0
  72. package/plugins/continuous-improvement/commands/learn-eval.md +117 -0
  73. package/plugins/continuous-improvement/commands/planning-with-files.md +66 -0
  74. package/plugins/continuous-improvement/commands/proceed-with-the-recommendation.md +62 -0
  75. package/plugins/continuous-improvement/commands/ralph.md +103 -0
  76. package/plugins/continuous-improvement/commands/release-train.md +81 -0
  77. package/plugins/continuous-improvement/commands/seven-laws.md +16 -0
  78. package/plugins/continuous-improvement/commands/superpowers.md +180 -0
  79. package/plugins/continuous-improvement/commands/swarm.md +101 -0
  80. package/plugins/continuous-improvement/commands/workspace-surface-audit.md +77 -0
  81. package/plugins/continuous-improvement/hooks/gateguard.mjs +172 -0
  82. package/plugins/continuous-improvement/hooks/hooks.json +65 -0
  83. package/plugins/continuous-improvement/hooks/observe.sh +172 -0
  84. package/plugins/continuous-improvement/hooks/session.sh +106 -0
  85. package/plugins/continuous-improvement/hooks/three-section-close.mjs +181 -0
  86. package/plugins/continuous-improvement/instinct-packs/go.json +58 -0
  87. package/plugins/continuous-improvement/instinct-packs/meta.json +16 -0
  88. package/plugins/continuous-improvement/instinct-packs/python.json +58 -0
  89. package/plugins/continuous-improvement/instinct-packs/react.json +58 -0
  90. package/plugins/continuous-improvement/lib/observe-event.mjs +128 -0
  91. package/plugins/continuous-improvement/lib/plugin-metadata.mjs +435 -0
  92. package/plugins/continuous-improvement/lib/resolve-home-dir.mjs +43 -0
  93. package/plugins/continuous-improvement/skills/README.md +37 -0
  94. package/plugins/continuous-improvement/skills/continuous-improvement/SKILL.md +249 -0
  95. package/plugins/continuous-improvement/skills/deploy-receipt/SKILL.md +178 -0
  96. package/plugins/continuous-improvement/skills/gateguard/SKILL.md +163 -0
  97. package/plugins/continuous-improvement/skills/para-memory-files/SKILL.md +108 -0
  98. package/plugins/continuous-improvement/skills/proceed-with-the-recommendation/SKILL.md +447 -0
  99. package/plugins/continuous-improvement/skills/ralph/SKILL.md +221 -0
  100. package/plugins/continuous-improvement/skills/recovery-classification/SKILL.md +73 -0
  101. package/plugins/continuous-improvement/skills/safety-guard/SKILL.md +76 -0
  102. package/plugins/continuous-improvement/skills/state-reconciliation/SKILL.md +63 -0
  103. package/plugins/continuous-improvement/skills/strategic-compact/SKILL.md +104 -0
  104. package/plugins/continuous-improvement/skills/superpowers/SKILL.md +219 -0
  105. package/plugins/continuous-improvement/skills/tdd-workflow/SKILL.md +411 -0
  106. package/plugins/continuous-improvement/skills/token-budget-advisor/SKILL.md +136 -0
  107. package/plugins/continuous-improvement/skills/verification-loop/SKILL.md +224 -0
  108. package/plugins/continuous-improvement/skills/wild-risa-balance/SKILL.md +191 -0
  109. package/plugins/continuous-improvement/skills/workspace-surface-audit/SKILL.md +147 -0
  110. package/plugins/continuous-improvement/skills/worktree-safety/SKILL.md +66 -0
  111. package/plugins/continuous-improvement/templates/planning-with-files/findings.md +8 -0
  112. package/plugins/continuous-improvement/templates/planning-with-files/progress.md +7 -0
  113. package/plugins/continuous-improvement/templates/planning-with-files/task_plan.md +23 -0
  114. package/plugins/expert.json +26 -5
  115. package/skills/README.md +79 -0
  116. package/skills/deploy-receipt.md +178 -0
  117. package/skills/gateguard.md +163 -0
  118. package/skills/para-memory-files.md +108 -0
  119. package/skills/proceed-with-the-recommendation.md +447 -0
  120. package/skills/ralph.md +221 -0
  121. package/skills/recovery-classification.md +73 -0
  122. package/skills/safety-guard.md +76 -0
  123. package/skills/state-reconciliation.md +63 -0
  124. package/skills/strategic-compact.md +104 -0
  125. package/skills/superpowers.md +219 -0
  126. package/skills/tdd-workflow.md +411 -0
  127. package/skills/token-budget-advisor.md +136 -0
  128. package/skills/verification-loop.md +224 -0
  129. package/skills/wild-risa-balance.md +191 -0
  130. package/skills/workspace-surface-audit.md +147 -0
  131. package/skills/worktree-safety.md +66 -0
  132. package/templates/insights-claude-md.md +91 -0
  133. package/templates/planning-with-files/findings.md +8 -0
  134. package/templates/planning-with-files/progress.md +7 -0
  135. package/templates/planning-with-files/task_plan.md +23 -0
  136. package/templates/verify-ladder.example.json +60 -0
@@ -1,5 +1,4 @@
1
1
  #!/usr/bin/env node
2
-
3
2
  /**
4
3
  * Agent Transcript Linter
5
4
  *
@@ -15,175 +14,154 @@
15
14
  * 0 — no violations (or --strict not set)
16
15
  * 1 — violations found (with --strict)
17
16
  */
18
-
19
17
  import { readFileSync } from "node:fs";
20
18
  import { createInterface } from "node:readline";
21
-
22
19
  const LAWS = {
23
- 1: { name: "Research Before Executing", patterns: [] },
24
- 2: { name: "Plan Is Sacred", patterns: [] },
25
- 3: { name: "One Thing at a Time", patterns: [] },
26
- 4: { name: "Verify Before Reporting", patterns: [] },
27
- 5: { name: "Reflect After Sessions", patterns: [] },
28
- 6: { name: "Iterate One Change", patterns: [] },
29
- 7: { name: "Learn From Every Session", patterns: [] },
20
+ 1: { name: "Research Before Executing", patterns: [] },
21
+ 2: { name: "Plan Is Sacred", patterns: [] },
22
+ 3: { name: "One Thing at a Time", patterns: [] },
23
+ 4: { name: "Verify Before Reporting", patterns: [] },
24
+ 5: { name: "Reflect After Sessions", patterns: [] },
25
+ 6: { name: "Iterate One Change", patterns: [] },
26
+ 7: { name: "Learn From Every Session", patterns: [] },
30
27
  };
31
-
32
- function analyzeTranscript(events) {
33
- const violations = [];
34
- const stats = {
35
- totalEvents: events.length,
36
- toolCalls: 0,
37
- researchTools: 0, // Grep, Glob, Read
38
- writeTools: 0, // Write, Edit, Bash
39
- verifyTools: 0, // Bash (test/build commands)
40
- sessions: new Set(),
41
- };
42
-
43
- // Classify events
44
- for (const event of events) {
45
- stats.toolCalls++;
46
- if (event.session_id) stats.sessions.add(event.session_id);
47
-
48
- const tool = event.tool || event.tool_name || "";
49
- const input = event.tool_input || event.input || {};
50
- const command = input.command || "";
51
-
52
- if (["Grep", "Glob", "Read"].includes(tool)) {
53
- stats.researchTools++;
28
+ function analyzeTranscript(events, parseFailures) {
29
+ const violations = [];
30
+ const stats = {
31
+ totalEvents: events.length,
32
+ toolCalls: 0,
33
+ researchTools: 0,
34
+ writeTools: 0,
35
+ verifyTools: 0,
36
+ sessions: new Set(),
37
+ parseFailures,
38
+ };
39
+ for (const event of events) {
40
+ stats.toolCalls++;
41
+ if (event.session_id) {
42
+ stats.sessions.add(event.session_id);
43
+ }
44
+ const tool = event.tool || event.tool_name || "";
45
+ const input = event.tool_input || event.input || {};
46
+ const command = typeof input.command === "string" ? input.command : "";
47
+ if (["Grep", "Glob", "Read"].includes(tool)) {
48
+ stats.researchTools++;
49
+ }
50
+ if (["Write", "Edit"].includes(tool)) {
51
+ stats.writeTools++;
52
+ }
53
+ if (tool === "Bash" && /\b(test|build|npm run|jest|vitest|bun test|deno test|ava|tap|mocha|pytest|go test|cargo test|gradle test|mvn test)\b/.test(command)) {
54
+ stats.verifyTools++;
55
+ }
54
56
  }
55
- if (["Write", "Edit"].includes(tool)) {
56
- stats.writeTools++;
57
+ let lastResearchIdx = -1;
58
+ for (let index = 0; index < events.length; index++) {
59
+ const tool = events[index]?.tool || events[index]?.tool_name || "";
60
+ if (["Grep", "Glob", "Read"].includes(tool)) {
61
+ lastResearchIdx = index;
62
+ }
63
+ if (["Write", "Edit"].includes(tool) && lastResearchIdx === -1) {
64
+ violations.push({
65
+ law: 1,
66
+ severity: "high",
67
+ message: `Write/Edit at event ${index} without any prior research (Grep/Glob/Read)`,
68
+ event: index,
69
+ });
70
+ // Continue checking for more violations
71
+ }
57
72
  }
58
- if (tool === "Bash" && /\b(test|build|npm run|jest|pytest|go test|cargo test)\b/.test(command)) {
59
- stats.verifyTools++;
73
+ if (stats.writeTools > 0 && stats.researchTools === 0) {
74
+ violations.push({
75
+ law: 1,
76
+ severity: "high",
77
+ message: `${stats.writeTools} writes with 0 research operations. Agent likely skipped research.`,
78
+ });
60
79
  }
61
- }
62
-
63
- // Law 1: Research Before Executing
64
- // Check if writes happen without prior reads/greps
65
- let lastResearchIdx = -1;
66
- for (let i = 0; i < events.length; i++) {
67
- const tool = events[i].tool || events[i].tool_name || "";
68
- if (["Grep", "Glob", "Read"].includes(tool)) {
69
- lastResearchIdx = i;
80
+ else if (stats.writeTools > stats.researchTools * 3) {
81
+ violations.push({
82
+ law: 1,
83
+ severity: "medium",
84
+ message: `Write-to-research ratio is ${stats.writeTools}:${stats.researchTools}. Consider more research.`,
85
+ });
70
86
  }
71
- if (["Write", "Edit"].includes(tool) && lastResearchIdx === -1) {
72
- violations.push({
73
- law: 1,
74
- severity: "high",
75
- message: `Write/Edit at event ${i} without any prior research (Grep/Glob/Read)`,
76
- event: i,
77
- });
78
- break; // Only report first occurrence
87
+ let consecutiveEdits = 0;
88
+ const editedFiles = new Set();
89
+ for (const event of events) {
90
+ const tool = event.tool || event.tool_name || "";
91
+ const input = event.tool_input || event.input || {};
92
+ if (["Write", "Edit"].includes(tool)) {
93
+ consecutiveEdits++;
94
+ if (typeof input.file_path === "string") {
95
+ editedFiles.add(input.file_path);
96
+ }
97
+ }
98
+ else {
99
+ // Reset on any non-write tool (verification, research, etc.)
100
+ consecutiveEdits = 0;
101
+ }
102
+ if (consecutiveEdits > 5) {
103
+ violations.push({
104
+ law: 3,
105
+ severity: "medium",
106
+ message: `${consecutiveEdits} consecutive edits without verification. Editing multiple files at once.`,
107
+ });
108
+ consecutiveEdits = 0;
109
+ }
79
110
  }
80
- }
81
-
82
- // Law 1 ratio check
83
- if (stats.writeTools > 0 && stats.researchTools === 0) {
84
- violations.push({
85
- law: 1,
86
- severity: "high",
87
- message: `${stats.writeTools} writes with 0 research operations. Agent likely skipped research.`,
88
- });
89
- } else if (stats.writeTools > stats.researchTools * 3) {
90
- violations.push({
91
- law: 1,
92
- severity: "medium",
93
- message: `Write-to-research ratio is ${stats.writeTools}:${stats.researchTools}. Consider more research.`,
94
- });
95
- }
96
-
97
- // Law 3: One Thing at a Time
98
- // Detect rapid context switching (different files edited in quick succession without verification)
99
- let consecutiveEdits = 0;
100
- const editedFiles = new Set();
101
- for (const event of events) {
102
- const tool = event.tool || event.tool_name || "";
103
- const input = event.tool_input || event.input || {};
104
-
105
- if (["Write", "Edit"].includes(tool)) {
106
- consecutiveEdits++;
107
- if (input.file_path) editedFiles.add(input.file_path);
108
- } else if (tool === "Bash") {
109
- consecutiveEdits = 0; // Reset on verification
111
+ if (stats.writeTools > 0 && stats.verifyTools === 0) {
112
+ violations.push({
113
+ law: 4,
114
+ severity: "high",
115
+ message: `${stats.writeTools} code changes with 0 verification commands (test/build). Agent may have declared done without verifying.`,
116
+ });
110
117
  }
111
-
112
- if (consecutiveEdits > 5) {
113
- violations.push({
114
- law: 3,
115
- severity: "medium",
116
- message: `${consecutiveEdits} consecutive edits without verification. Editing multiple files at once.`,
117
- });
118
- consecutiveEdits = 0;
118
+ if (editedFiles.size > 8) {
119
+ violations.push({
120
+ law: 6,
121
+ severity: "medium",
122
+ message: `${editedFiles.size} different files modified. Consider smaller, focused iterations.`,
123
+ });
119
124
  }
120
- }
121
-
122
- // Law 4: Verify Before Reporting
123
- if (stats.writeTools > 0 && stats.verifyTools === 0) {
124
- violations.push({
125
- law: 4,
126
- severity: "high",
127
- message: `${stats.writeTools} code changes with 0 verification commands (test/build). Agent may have declared done without verifying.`,
128
- });
129
- }
130
-
131
- // Law 6: Iterate One Change
132
- if (editedFiles.size > 8) {
133
- violations.push({
134
- law: 6,
135
- severity: "medium",
136
- message: `${editedFiles.size} different files modified. Consider smaller, focused iterations.`,
137
- });
138
- }
139
-
140
- // Calculate discipline score
141
- const maxViolations = 7; // One per law
142
- const violationWeight = violations.reduce((sum, v) => {
143
- return sum + (v.severity === "high" ? 2 : 1);
144
- }, 0);
145
- const score = Math.max(0, Math.round(100 - (violationWeight / maxViolations) * 100));
146
-
147
- return { violations, stats, score };
125
+ const maxViolations = 7;
126
+ const violationWeight = violations.reduce((sum, violation) => {
127
+ return sum + (violation.severity === "high" ? 2 : 1);
128
+ }, 0);
129
+ const score = Math.max(0, Math.round(100 - (violationWeight / maxViolations) * 100));
130
+ return { violations, stats, score, parseFailures };
148
131
  }
149
-
150
132
  function formatReport(result) {
151
- const { violations, stats, score } = result;
152
- const lines = [];
153
-
154
- lines.push("## Agent Discipline Report");
155
- lines.push("");
156
- lines.push(`**Score:** ${score}/100`);
157
- lines.push(`**Events analyzed:** ${stats.totalEvents}`);
158
- lines.push(`**Tool calls:** ${stats.toolCalls}`);
159
- lines.push(`**Research ops:** ${stats.researchTools} | **Write ops:** ${stats.writeTools} | **Verify ops:** ${stats.verifyTools}`);
160
- lines.push("");
161
-
162
- if (violations.length === 0) {
163
- lines.push("No law violations detected. Good discipline!");
164
- } else {
165
- lines.push(`### Violations (${violations.length})`);
133
+ const { violations, stats, score, parseFailures } = result;
134
+ const lines = [];
135
+ lines.push("## Agent Discipline Report");
166
136
  lines.push("");
167
- for (const v of violations) {
168
- const severity = v.severity === "high" ? "HIGH" : "MEDIUM";
169
- lines.push(`- **[${severity}] Law ${v.law}: ${LAWS[v.law].name}**`);
170
- lines.push(` ${v.message}`);
137
+ lines.push(`**Score:** ${score}/100`);
138
+ lines.push(`**Events analyzed:** ${stats.totalEvents}`);
139
+ lines.push(`**Tool calls:** ${stats.toolCalls}`);
140
+ lines.push(`**Research ops:** ${stats.researchTools} | **Write ops:** ${stats.writeTools} | **Verify ops:** ${stats.verifyTools}`);
141
+ if (parseFailures > 0) {
142
+ lines.push(`**Parse failures:** ${parseFailures} (malformed JSON lines skipped)`);
171
143
  }
172
- }
173
-
174
- lines.push("");
175
- lines.push("---");
176
- lines.push("*Generated by [continuous-improvement](https://github.com/naimkatiman/continuous-improvement) transcript linter*");
177
-
178
- return lines.join("\n");
144
+ lines.push("");
145
+ if (violations.length === 0) {
146
+ lines.push("No law violations detected. Good discipline!");
147
+ }
148
+ else {
149
+ lines.push(`### Violations (${violations.length})`);
150
+ lines.push("");
151
+ for (const violation of violations) {
152
+ const severity = violation.severity === "high" ? "HIGH" : "MEDIUM";
153
+ lines.push(`- **[${severity}] Law ${violation.law}: ${LAWS[violation.law].name}**`);
154
+ lines.push(` ${violation.message}`);
155
+ }
156
+ }
157
+ lines.push("");
158
+ lines.push("---");
159
+ lines.push("*Generated by [continuous-improvement](https://github.com/naimkatiman/continuous-improvement) transcript linter*");
160
+ return lines.join("\n");
179
161
  }
180
-
181
- // --- Main ---
182
-
183
162
  const args = process.argv.slice(2);
184
-
185
163
  if (args.includes("--help") || args.includes("-h")) {
186
- console.log(`
164
+ console.log(`
187
165
  Agent Transcript Linter — The 7 Laws of AI Agent Discipline
188
166
 
189
167
  Usage:
@@ -196,72 +174,66 @@ Options:
196
174
  --strict Exit 1 if violations found
197
175
  --json Output as JSON instead of markdown
198
176
  `);
199
- process.exit(0);
177
+ process.exit(0);
200
178
  }
201
-
202
179
  const isStrict = args.includes("--strict");
203
180
  const isJson = args.includes("--json");
204
181
  const isStdin = args.includes("--stdin");
205
-
206
182
  async function main() {
207
- let lines;
208
-
209
- if (isStdin) {
210
- const rl = createInterface({ input: process.stdin, terminal: false });
211
- lines = [];
212
- for await (const line of rl) {
213
- if (line.trim()) lines.push(line.trim());
183
+ let lines = [];
184
+ if (isStdin) {
185
+ const rl = createInterface({ input: process.stdin, terminal: false });
186
+ for await (const line of rl) {
187
+ if (line.trim()) {
188
+ lines.push(line.trim());
189
+ }
190
+ }
214
191
  }
215
- } else {
216
- const filePath = args.find((a) => !a.startsWith("--"));
217
- if (!filePath) {
218
- console.error("Error: provide a file path or use --stdin");
219
- process.exit(1);
192
+ else {
193
+ const filePath = args.find((arg) => !arg.startsWith("--"));
194
+ if (!filePath) {
195
+ console.error("Error: provide a file path or use --stdin");
196
+ process.exit(1);
197
+ }
198
+ const content = readFileSync(filePath, "utf8");
199
+ lines = content.split("\n").filter((line) => line.trim().length > 0);
220
200
  }
221
- const content = readFileSync(filePath, "utf8");
222
- lines = content.split("\n").filter((l) => l.trim());
223
- }
224
-
225
- const events = [];
226
- for (const line of lines) {
227
- try {
228
- events.push(JSON.parse(line));
229
- } catch {
230
- // skip non-JSON lines
201
+ const events = [];
202
+ let parseFailures = 0;
203
+ for (const line of lines) {
204
+ try {
205
+ events.push(JSON.parse(line));
206
+ }
207
+ catch {
208
+ parseFailures++;
209
+ }
231
210
  }
232
- }
233
-
234
- if (events.length === 0) {
235
- console.log("No events found to analyze.");
236
- process.exit(0);
237
- }
238
-
239
- const result = analyzeTranscript(events);
240
-
241
- if (isJson) {
242
- console.log(JSON.stringify(result, null, 2));
243
- } else {
244
- console.log(formatReport(result));
245
- }
246
-
247
- // GitHub Actions output
248
- if (process.env.GITHUB_OUTPUT) {
249
- const outputLines = [
250
- `violations=${result.violations.length}`,
251
- `score=${result.score}`,
252
- ];
253
- const { appendFileSync } = await import("node:fs");
254
- for (const line of outputLines) {
255
- appendFileSync(process.env.GITHUB_OUTPUT, line + "\n");
211
+ if (events.length === 0) {
212
+ console.log("No events found to analyze.");
213
+ process.exit(0);
214
+ }
215
+ const result = analyzeTranscript(events, parseFailures);
216
+ if (isJson) {
217
+ console.log(JSON.stringify(result, null, 2));
218
+ }
219
+ else {
220
+ console.log(formatReport(result));
221
+ }
222
+ if (process.env.GITHUB_OUTPUT) {
223
+ const outputLines = [
224
+ `violations=${result.violations.length}`,
225
+ `score=${result.score}`,
226
+ ];
227
+ const { appendFileSync } = await import("node:fs");
228
+ for (const line of outputLines) {
229
+ appendFileSync(process.env.GITHUB_OUTPUT, line + "\n");
230
+ }
231
+ }
232
+ if (isStrict && result.violations.length > 0) {
233
+ process.exit(1);
256
234
  }
257
- }
258
-
259
- if (isStrict && result.violations.length > 0) {
260
- process.exit(1);
261
- }
262
235
  }
263
-
264
- main().catch((err) => {
265
- console.error(err.message);
266
- process.exit(1);
236
+ main().catch((error) => {
237
+ console.error(error instanceof Error ? error.message : String(error));
238
+ process.exit(1);
267
239
  });