@howlil/ez-agents 2.0.0 → 3.0.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 (145) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +157 -110
  3. package/README.zh-CN.md +84 -84
  4. package/agents/ez-plan-checker.md +2 -2
  5. package/agents/ez-research-synthesizer.md +1 -1
  6. package/agents/ez-ui-auditor.md +0 -2
  7. package/agents/ez-ui-checker.md +2 -4
  8. package/agents/ez-ui-researcher.md +0 -2
  9. package/agents/ez-verifier.md +1 -1
  10. package/bin/install.js +211 -211
  11. package/commands/ez/debug.md +1 -1
  12. package/commands/ez/map-codebase.md +1 -1
  13. package/commands/ez/reapply-patches.md +3 -3
  14. package/commands/ez/research-phase.md +1 -1
  15. package/{get-shit-done → ez-agents}/bin/ez-tools.cjs +1 -1
  16. package/{get-shit-done → ez-agents}/bin/lib/assistant-adapter.cjs +205 -205
  17. package/{get-shit-done → ez-agents}/bin/lib/audit-exec.cjs +150 -150
  18. package/{get-shit-done → ez-agents}/bin/lib/auth.cjs +175 -175
  19. package/{get-shit-done → ez-agents}/bin/lib/circuit-breaker.cjs +118 -118
  20. package/{get-shit-done → ez-agents}/bin/lib/commands.cjs +666 -666
  21. package/{get-shit-done → ez-agents}/bin/lib/config.cjs +183 -183
  22. package/{get-shit-done → ez-agents}/bin/lib/core.cjs +495 -495
  23. package/{get-shit-done → ez-agents}/bin/lib/file-lock.cjs +236 -236
  24. package/{get-shit-done → ez-agents}/bin/lib/frontmatter.cjs +299 -299
  25. package/{get-shit-done → ez-agents}/bin/lib/fs-utils.cjs +153 -153
  26. package/{get-shit-done → ez-agents}/bin/lib/git-utils.cjs +203 -203
  27. package/{get-shit-done → ez-agents}/bin/lib/health-check.cjs +163 -163
  28. package/{get-shit-done → ez-agents}/bin/lib/index.cjs +113 -113
  29. package/{get-shit-done → ez-agents}/bin/lib/init.cjs +710 -710
  30. package/{get-shit-done → ez-agents}/bin/lib/logger.cjs +117 -117
  31. package/{get-shit-done → ez-agents}/bin/lib/milestone.cjs +241 -241
  32. package/{get-shit-done → ez-agents}/bin/lib/model-provider.cjs +146 -146
  33. package/{get-shit-done → ez-agents}/bin/lib/phase.cjs +908 -908
  34. package/{get-shit-done → ez-agents}/bin/lib/retry.cjs +119 -119
  35. package/{get-shit-done → ez-agents}/bin/lib/roadmap.cjs +305 -305
  36. package/{get-shit-done → ez-agents}/bin/lib/safe-exec.cjs +128 -128
  37. package/{get-shit-done → ez-agents}/bin/lib/safe-path.cjs +130 -130
  38. package/{get-shit-done → ez-agents}/bin/lib/state.cjs +721 -721
  39. package/{get-shit-done → ez-agents}/bin/lib/temp-file.cjs +239 -239
  40. package/{get-shit-done → ez-agents}/bin/lib/template.cjs +222 -222
  41. package/{get-shit-done → ez-agents}/bin/lib/test-file-lock.cjs +112 -112
  42. package/{get-shit-done → ez-agents}/bin/lib/test-graceful.cjs +93 -93
  43. package/{get-shit-done → ez-agents}/bin/lib/test-logger.cjs +60 -60
  44. package/{get-shit-done → ez-agents}/bin/lib/test-safe-exec.cjs +38 -38
  45. package/{get-shit-done → ez-agents}/bin/lib/test-safe-path.cjs +33 -33
  46. package/{get-shit-done → ez-agents}/bin/lib/test-temp-file.cjs +125 -125
  47. package/{get-shit-done → ez-agents}/bin/lib/timeout-exec.cjs +62 -62
  48. package/{get-shit-done → ez-agents}/bin/lib/verify.cjs +820 -820
  49. package/{get-shit-done → ez-agents}/references/checkpoints.md +776 -776
  50. package/{get-shit-done → ez-agents}/references/questioning.md +162 -162
  51. package/{get-shit-done → ez-agents}/references/tdd.md +263 -263
  52. package/{get-shit-done → ez-agents}/templates/codebase/concerns.md +310 -310
  53. package/{get-shit-done → ez-agents}/templates/codebase/conventions.md +307 -307
  54. package/{get-shit-done → ez-agents}/templates/codebase/integrations.md +280 -280
  55. package/{get-shit-done → ez-agents}/templates/codebase/stack.md +186 -186
  56. package/{get-shit-done → ez-agents}/templates/codebase/testing.md +480 -480
  57. package/{get-shit-done → ez-agents}/templates/config.json +37 -37
  58. package/{get-shit-done → ez-agents}/templates/continue-here.md +78 -78
  59. package/{get-shit-done → ez-agents}/templates/milestone-archive.md +123 -123
  60. package/{get-shit-done → ez-agents}/templates/milestone.md +115 -115
  61. package/{get-shit-done → ez-agents}/templates/requirements.md +231 -231
  62. package/{get-shit-done → ez-agents}/templates/research-project/ARCHITECTURE.md +204 -204
  63. package/{get-shit-done → ez-agents}/templates/research-project/FEATURES.md +147 -147
  64. package/{get-shit-done → ez-agents}/templates/research-project/PITFALLS.md +200 -200
  65. package/{get-shit-done → ez-agents}/templates/research-project/STACK.md +120 -120
  66. package/{get-shit-done → ez-agents}/templates/research-project/SUMMARY.md +170 -170
  67. package/{get-shit-done → ez-agents}/templates/retrospective.md +54 -54
  68. package/{get-shit-done → ez-agents}/templates/roadmap.md +202 -202
  69. package/{get-shit-done → ez-agents}/templates/summary-minimal.md +41 -41
  70. package/{get-shit-done → ez-agents}/templates/summary-standard.md +48 -48
  71. package/{get-shit-done → ez-agents}/templates/summary.md +248 -248
  72. package/{get-shit-done → ez-agents}/templates/user-setup.md +311 -311
  73. package/{get-shit-done → ez-agents}/templates/verification-report.md +322 -322
  74. package/{get-shit-done → ez-agents}/workflows/add-phase.md +112 -112
  75. package/{get-shit-done → ez-agents}/workflows/add-tests.md +351 -351
  76. package/{get-shit-done → ez-agents}/workflows/add-todo.md +158 -158
  77. package/{get-shit-done → ez-agents}/workflows/audit-milestone.md +332 -332
  78. package/{get-shit-done → ez-agents}/workflows/autonomous.md +743 -743
  79. package/{get-shit-done → ez-agents}/workflows/check-todos.md +177 -177
  80. package/{get-shit-done → ez-agents}/workflows/cleanup.md +152 -152
  81. package/{get-shit-done → ez-agents}/workflows/complete-milestone.md +766 -766
  82. package/ez-agents/workflows/debug.md +0 -0
  83. package/{get-shit-done → ez-agents}/workflows/diagnose-issues.md +219 -219
  84. package/{get-shit-done → ez-agents}/workflows/discovery-phase.md +289 -289
  85. package/{get-shit-done → ez-agents}/workflows/discuss-phase.md +762 -762
  86. package/{get-shit-done → ez-agents}/workflows/execute-phase.md +468 -468
  87. package/{get-shit-done → ez-agents}/workflows/execute-plan.md +483 -483
  88. package/{get-shit-done → ez-agents}/workflows/health.md +159 -159
  89. package/{get-shit-done → ez-agents}/workflows/help.md +492 -492
  90. package/{get-shit-done → ez-agents}/workflows/insert-phase.md +130 -130
  91. package/{get-shit-done → ez-agents}/workflows/list-phase-assumptions.md +178 -178
  92. package/{get-shit-done → ez-agents}/workflows/map-codebase.md +316 -316
  93. package/{get-shit-done → ez-agents}/workflows/new-milestone.md +384 -384
  94. package/{get-shit-done → ez-agents}/workflows/new-project.md +1111 -1111
  95. package/{get-shit-done → ez-agents}/workflows/node-repair.md +92 -92
  96. package/{get-shit-done → ez-agents}/workflows/pause-work.md +122 -122
  97. package/{get-shit-done → ez-agents}/workflows/plan-milestone-gaps.md +274 -274
  98. package/{get-shit-done → ez-agents}/workflows/plan-phase.md +651 -651
  99. package/{get-shit-done → ez-agents}/workflows/progress.md +382 -382
  100. package/{get-shit-done → ez-agents}/workflows/quick.md +610 -610
  101. package/{get-shit-done → ez-agents}/workflows/remove-phase.md +155 -155
  102. package/{get-shit-done → ez-agents}/workflows/research-phase.md +74 -74
  103. package/{get-shit-done → ez-agents}/workflows/resume-project.md +307 -307
  104. package/{get-shit-done → ez-agents}/workflows/set-profile.md +81 -81
  105. package/{get-shit-done → ez-agents}/workflows/settings.md +242 -242
  106. package/{get-shit-done → ez-agents}/workflows/stats.md +57 -57
  107. package/{get-shit-done → ez-agents}/workflows/transition.md +544 -544
  108. package/{get-shit-done → ez-agents}/workflows/ui-phase.md +290 -290
  109. package/{get-shit-done → ez-agents}/workflows/ui-review.md +157 -157
  110. package/{get-shit-done → ez-agents}/workflows/update.md +320 -320
  111. package/{get-shit-done → ez-agents}/workflows/validate-phase.md +167 -167
  112. package/{get-shit-done → ez-agents}/workflows/verify-phase.md +243 -243
  113. package/{get-shit-done → ez-agents}/workflows/verify-work.md +5 -5
  114. package/hooks/dist/ez-check-update.js +81 -0
  115. package/hooks/dist/ez-context-monitor.js +141 -0
  116. package/hooks/dist/ez-statusline.js +115 -0
  117. package/package.json +13 -3
  118. package/scripts/build-hooks.js +43 -43
  119. package/scripts/run-tests.cjs +29 -29
  120. /package/{get-shit-done → ez-agents}/references/continuation-format.md +0 -0
  121. /package/{get-shit-done → ez-agents}/references/decimal-phase-calculation.md +0 -0
  122. /package/{get-shit-done → ez-agents}/references/git-integration.md +0 -0
  123. /package/{get-shit-done → ez-agents}/references/git-planning-commit.md +0 -0
  124. /package/{get-shit-done → ez-agents}/references/model-profile-resolution.md +0 -0
  125. /package/{get-shit-done → ez-agents}/references/model-profiles.md +0 -0
  126. /package/{get-shit-done → ez-agents}/references/phase-argument-parsing.md +0 -0
  127. /package/{get-shit-done → ez-agents}/references/planning-config.md +0 -0
  128. /package/{get-shit-done → ez-agents}/references/ui-brand.md +0 -0
  129. /package/{get-shit-done → ez-agents}/references/verification-patterns.md +0 -0
  130. /package/{get-shit-done → ez-agents}/templates/DEBUG.md +0 -0
  131. /package/{get-shit-done → ez-agents}/templates/UAT.md +0 -0
  132. /package/{get-shit-done → ez-agents}/templates/UI-SPEC.md +0 -0
  133. /package/{get-shit-done → ez-agents}/templates/VALIDATION.md +0 -0
  134. /package/{get-shit-done → ez-agents}/templates/codebase/architecture.md +0 -0
  135. /package/{get-shit-done → ez-agents}/templates/codebase/structure.md +0 -0
  136. /package/{get-shit-done → ez-agents}/templates/context.md +0 -0
  137. /package/{get-shit-done → ez-agents}/templates/copilot-instructions.md +0 -0
  138. /package/{get-shit-done → ez-agents}/templates/debug-subagent-prompt.md +0 -0
  139. /package/{get-shit-done → ez-agents}/templates/discovery.md +0 -0
  140. /package/{get-shit-done → ez-agents}/templates/phase-prompt.md +0 -0
  141. /package/{get-shit-done → ez-agents}/templates/planner-subagent-prompt.md +0 -0
  142. /package/{get-shit-done → ez-agents}/templates/project.md +0 -0
  143. /package/{get-shit-done → ez-agents}/templates/research.md +0 -0
  144. /package/{get-shit-done → ez-agents}/templates/state.md +0 -0
  145. /package/{get-shit-done → ez-agents}/templates/summary-complex.md +0 -0
@@ -0,0 +1,141 @@
1
+ #!/usr/bin/env node
2
+ // Context Monitor - PostToolUse/AfterTool hook (Gemini uses AfterTool)
3
+ // Reads context metrics from the statusline bridge file and injects
4
+ // warnings when context usage is high. This makes the AGENT aware of
5
+ // context limits (the statusline only shows the user).
6
+ //
7
+ // How it works:
8
+ // 1. The statusline hook writes metrics to /tmp/claude-ctx-{session_id}.json
9
+ // 2. This hook reads those metrics after each tool use
10
+ // 3. When remaining context drops below thresholds, it injects a warning
11
+ // as additionalContext, which the agent sees in its conversation
12
+ //
13
+ // Thresholds:
14
+ // WARNING (remaining <= 35%): Agent should wrap up current task
15
+ // CRITICAL (remaining <= 25%): Agent should stop immediately and save state
16
+ //
17
+ // Debounce: 5 tool uses between warnings to avoid spam
18
+ // Severity escalation bypasses debounce (WARNING -> CRITICAL fires immediately)
19
+
20
+ const fs = require('fs');
21
+ const os = require('os');
22
+ const path = require('path');
23
+
24
+ const WARNING_THRESHOLD = 35; // remaining_percentage <= 35%
25
+ const CRITICAL_THRESHOLD = 25; // remaining_percentage <= 25%
26
+ const STALE_SECONDS = 60; // ignore metrics older than 60s
27
+ const DEBOUNCE_CALLS = 5; // min tool uses between warnings
28
+
29
+ let input = '';
30
+ // Timeout guard: if stdin doesn't close within 3s (e.g. pipe issues on
31
+ // Windows/Git Bash), exit silently instead of hanging until Claude Code
32
+ // kills the process and reports "hook error". See #775.
33
+ const stdinTimeout = setTimeout(() => process.exit(0), 3000);
34
+ process.stdin.setEncoding('utf8');
35
+ process.stdin.on('data', chunk => input += chunk);
36
+ process.stdin.on('end', () => {
37
+ clearTimeout(stdinTimeout);
38
+ try {
39
+ const data = JSON.parse(input);
40
+ const sessionId = data.session_id;
41
+
42
+ if (!sessionId) {
43
+ process.exit(0);
44
+ }
45
+
46
+ const tmpDir = os.tmpdir();
47
+ const metricsPath = path.join(tmpDir, `claude-ctx-${sessionId}.json`);
48
+
49
+ // If no metrics file, this is a subagent or fresh session -- exit silently
50
+ if (!fs.existsSync(metricsPath)) {
51
+ process.exit(0);
52
+ }
53
+
54
+ const metrics = JSON.parse(fs.readFileSync(metricsPath, 'utf8'));
55
+ const now = Math.floor(Date.now() / 1000);
56
+
57
+ // Ignore stale metrics
58
+ if (metrics.timestamp && (now - metrics.timestamp) > STALE_SECONDS) {
59
+ process.exit(0);
60
+ }
61
+
62
+ const remaining = metrics.remaining_percentage;
63
+ const usedPct = metrics.used_pct;
64
+
65
+ // No warning needed
66
+ if (remaining > WARNING_THRESHOLD) {
67
+ process.exit(0);
68
+ }
69
+
70
+ // Debounce: check if we warned recently
71
+ const warnPath = path.join(tmpDir, `claude-ctx-${sessionId}-warned.json`);
72
+ let warnData = { callsSinceWarn: 0, lastLevel: null };
73
+ let firstWarn = true;
74
+
75
+ if (fs.existsSync(warnPath)) {
76
+ try {
77
+ warnData = JSON.parse(fs.readFileSync(warnPath, 'utf8'));
78
+ firstWarn = false;
79
+ } catch (e) {
80
+ // Corrupted file, reset
81
+ }
82
+ }
83
+
84
+ warnData.callsSinceWarn = (warnData.callsSinceWarn || 0) + 1;
85
+
86
+ const isCritical = remaining <= CRITICAL_THRESHOLD;
87
+ const currentLevel = isCritical ? 'critical' : 'warning';
88
+
89
+ // Emit immediately on first warning, then debounce subsequent ones
90
+ // Severity escalation (WARNING -> CRITICAL) bypasses debounce
91
+ const severityEscalated = currentLevel === 'critical' && warnData.lastLevel === 'warning';
92
+ if (!firstWarn && warnData.callsSinceWarn < DEBOUNCE_CALLS && !severityEscalated) {
93
+ // Update counter and exit without warning
94
+ fs.writeFileSync(warnPath, JSON.stringify(warnData));
95
+ process.exit(0);
96
+ }
97
+
98
+ // Reset debounce counter
99
+ warnData.callsSinceWarn = 0;
100
+ warnData.lastLevel = currentLevel;
101
+ fs.writeFileSync(warnPath, JSON.stringify(warnData));
102
+
103
+ // Detect if EZ Agents is active (has .planning/STATE.md in working directory)
104
+ const cwd = data.cwd || process.cwd();
105
+ const isEzActive = fs.existsSync(path.join(cwd, '.planning', 'STATE.md'));
106
+
107
+ // Build advisory warning message (never use imperative commands that
108
+ // override user preferences — see #884)
109
+ let message;
110
+ if (isCritical) {
111
+ message = isEzActive
112
+ ? `CONTEXT CRITICAL: Usage at ${usedPct}%. Remaining: ${remaining}%. ` +
113
+ 'Context is nearly exhausted. Do NOT start new complex work or write handoff files — ' +
114
+ 'EZ Agents state is already tracked in STATE.md. Inform the user so they can run ' +
115
+ '/ez:pause-work at the next natural stopping point.'
116
+ : `CONTEXT CRITICAL: Usage at ${usedPct}%. Remaining: ${remaining}%. ` +
117
+ 'Context is nearly exhausted. Inform the user that context is low and ask how they ' +
118
+ 'want to proceed. Do NOT autonomously save state or write handoff files unless the user asks.';
119
+ } else {
120
+ message = isEzActive
121
+ ? `CONTEXT WARNING: Usage at ${usedPct}%. Remaining: ${remaining}%. ` +
122
+ 'Context is getting limited. Avoid starting new complex work. If not between ' +
123
+ 'defined plan steps, inform the user so they can prepare to pause.'
124
+ : `CONTEXT WARNING: Usage at ${usedPct}%. Remaining: ${remaining}%. ` +
125
+ 'Be aware that context is getting limited. Avoid unnecessary exploration or ' +
126
+ 'starting new complex work.';
127
+ }
128
+
129
+ const output = {
130
+ hookSpecificOutput: {
131
+ hookEventName: process.env.GEMINI_API_KEY ? "AfterTool" : "PostToolUse",
132
+ additionalContext: message
133
+ }
134
+ };
135
+
136
+ process.stdout.write(JSON.stringify(output));
137
+ } catch (e) {
138
+ // Silent fail -- never block tool execution
139
+ process.exit(0);
140
+ }
141
+ });
@@ -0,0 +1,115 @@
1
+ #!/usr/bin/env node
2
+ // Claude Code Statusline - EZ Agents Edition
3
+ // Shows: model | current task | directory | context usage
4
+
5
+ const fs = require('fs');
6
+ const path = require('path');
7
+ const os = require('os');
8
+
9
+ // Read JSON from stdin
10
+ let input = '';
11
+ // Timeout guard: if stdin doesn't close within 3s (e.g. pipe issues on
12
+ // Windows/Git Bash), exit silently instead of hanging. See #775.
13
+ const stdinTimeout = setTimeout(() => process.exit(0), 3000);
14
+ process.stdin.setEncoding('utf8');
15
+ process.stdin.on('data', chunk => input += chunk);
16
+ process.stdin.on('end', () => {
17
+ clearTimeout(stdinTimeout);
18
+ try {
19
+ const data = JSON.parse(input);
20
+ const model = data.model?.display_name || 'Claude';
21
+ const dir = data.workspace?.current_dir || process.cwd();
22
+ const session = data.session_id || '';
23
+ const remaining = data.context_window?.remaining_percentage;
24
+
25
+ // Context window display (shows USED percentage scaled to usable context)
26
+ // Claude Code reserves ~16.5% for autocompact buffer, so usable context
27
+ // is 83.5% of the total window. We normalize to show 100% at that point.
28
+ const AUTO_COMPACT_BUFFER_PCT = 16.5;
29
+ let ctx = '';
30
+ if (remaining != null) {
31
+ // Normalize: subtract buffer from remaining, scale to usable range
32
+ const usableRemaining = Math.max(0, ((remaining - AUTO_COMPACT_BUFFER_PCT) / (100 - AUTO_COMPACT_BUFFER_PCT)) * 100);
33
+ const used = Math.max(0, Math.min(100, Math.round(100 - usableRemaining)));
34
+
35
+ // Write context metrics to bridge file for the context-monitor PostToolUse hook.
36
+ // The monitor reads this file to inject agent-facing warnings when context is low.
37
+ if (session) {
38
+ try {
39
+ const bridgePath = path.join(os.tmpdir(), `claude-ctx-${session}.json`);
40
+ const bridgeData = JSON.stringify({
41
+ session_id: session,
42
+ remaining_percentage: remaining,
43
+ used_pct: used,
44
+ timestamp: Math.floor(Date.now() / 1000)
45
+ });
46
+ fs.writeFileSync(bridgePath, bridgeData);
47
+ } catch (e) {
48
+ // Silent fail -- bridge is best-effort, don't break statusline
49
+ }
50
+ }
51
+
52
+ // Build progress bar (10 segments)
53
+ const filled = Math.floor(used / 10);
54
+ const bar = '█'.repeat(filled) + '░'.repeat(10 - filled);
55
+
56
+ // Color based on usable context thresholds
57
+ if (used < 50) {
58
+ ctx = ` \x1b[32m${bar} ${used}%\x1b[0m`;
59
+ } else if (used < 65) {
60
+ ctx = ` \x1b[33m${bar} ${used}%\x1b[0m`;
61
+ } else if (used < 80) {
62
+ ctx = ` \x1b[38;5;208m${bar} ${used}%\x1b[0m`;
63
+ } else {
64
+ ctx = ` \x1b[5;31m💀 ${bar} ${used}%\x1b[0m`;
65
+ }
66
+ }
67
+
68
+ // Current task from todos
69
+ let task = '';
70
+ const homeDir = os.homedir();
71
+ // Respect CLAUDE_CONFIG_DIR for custom config directory setups (#870)
72
+ const claudeDir = process.env.CLAUDE_CONFIG_DIR || path.join(homeDir, '.claude');
73
+ const todosDir = path.join(claudeDir, 'todos');
74
+ if (session && fs.existsSync(todosDir)) {
75
+ try {
76
+ const files = fs.readdirSync(todosDir)
77
+ .filter(f => f.startsWith(session) && f.includes('-agent-') && f.endsWith('.json'))
78
+ .map(f => ({ name: f, mtime: fs.statSync(path.join(todosDir, f)).mtime }))
79
+ .sort((a, b) => b.mtime - a.mtime);
80
+
81
+ if (files.length > 0) {
82
+ try {
83
+ const todos = JSON.parse(fs.readFileSync(path.join(todosDir, files[0].name), 'utf8'));
84
+ const inProgress = todos.find(t => t.status === 'in_progress');
85
+ if (inProgress) task = inProgress.activeForm || '';
86
+ } catch (e) {}
87
+ }
88
+ } catch (e) {
89
+ // Silently fail on file system errors - don't break statusline
90
+ }
91
+ }
92
+
93
+ // EZ Agents update available?
94
+ let ezUpdate = '';
95
+ const cacheFile = path.join(claudeDir, 'cache', 'ez-update-check.json');
96
+ if (fs.existsSync(cacheFile)) {
97
+ try {
98
+ const cache = JSON.parse(fs.readFileSync(cacheFile, 'utf8'));
99
+ if (cache.update_available) {
100
+ ezUpdate = '\x1b[33m⬆ /ez:update\x1b[0m │ ';
101
+ }
102
+ } catch (e) {}
103
+ }
104
+
105
+ // Output
106
+ const dirname = path.basename(dir);
107
+ if (task) {
108
+ process.stdout.write(`${ezUpdate}\x1b[2m${model}\x1b[0m │ \x1b[1m${task}\x1b[0m │ \x1b[2m${dirname}\x1b[0m${ctx}`);
109
+ } else {
110
+ process.stdout.write(`${ezUpdate}\x1b[2m${model}\x1b[0m │ \x1b[2m${dirname}\x1b[0m${ctx}`);
111
+ }
112
+ } catch (e) {
113
+ // Silent fail - don't break statusline on parse errors
114
+ }
115
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@howlil/ez-agents",
3
- "version": "2.0.0",
3
+ "version": "3.0.0",
4
4
  "description": "EZ Agents — Meta-prompting with multi-model support (Qwen, Kimi, OpenAI)",
5
5
  "bin": {
6
6
  "ez-agents": "bin/install.js",
@@ -9,7 +9,7 @@
9
9
  "files": [
10
10
  "bin",
11
11
  "commands",
12
- "get-shit-done",
12
+ "ez-agents",
13
13
  "agents",
14
14
  "hooks/dist",
15
15
  "scripts"
@@ -44,12 +44,22 @@
44
44
  "devDependencies": {
45
45
  "c8": "^11.0.0",
46
46
  "esbuild": "^0.24.2",
47
+ "husky": "^9.1.7",
48
+ "lint-staged": "^15.5.2",
47
49
  "proper-lockfile": "^4.1.2"
48
50
  },
49
51
  "scripts": {
50
52
  "build:hooks": "node scripts/build-hooks.js",
51
53
  "prepublishOnly": "npm run build:hooks",
52
54
  "test": "node scripts/run-tests.cjs",
53
- "test:coverage": "c8 --check-coverage --lines 70 --reporter text --include 'get-shit-done/bin/lib/*.cjs' --exclude 'tests/**' --all node scripts/run-tests.cjs"
55
+ "test:coverage": "c8 --check-coverage --lines 70 --reporter text --include 'ez-agents/bin/lib/*.cjs' --exclude 'tests/**' --all node scripts/run-tests.cjs"
56
+ },
57
+ "lint-staged": {
58
+ "*.cjs": [
59
+ "node --test"
60
+ ],
61
+ "*.md": [
62
+ "node scripts/run-tests.cjs"
63
+ ]
54
64
  }
55
65
  }
@@ -1,43 +1,43 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Copy GSD hooks to dist for installation.
4
- */
5
-
6
- const fs = require('fs');
7
- const path = require('path');
8
-
9
- const HOOKS_DIR = path.join(__dirname, '..', 'hooks');
10
- const DIST_DIR = path.join(HOOKS_DIR, 'dist');
11
-
12
- // Hooks to copy (pure Node.js, no bundling needed)
13
- const HOOKS_TO_COPY = [
14
- 'gsd-check-update.js',
15
- 'gsd-context-monitor.js',
16
- 'gsd-statusline.js'
17
- ];
18
-
19
- function build() {
20
- // Ensure dist directory exists
21
- if (!fs.existsSync(DIST_DIR)) {
22
- fs.mkdirSync(DIST_DIR, { recursive: true });
23
- }
24
-
25
- // Copy hooks to dist
26
- for (const hook of HOOKS_TO_COPY) {
27
- const src = path.join(HOOKS_DIR, hook);
28
- const dest = path.join(DIST_DIR, hook);
29
-
30
- if (!fs.existsSync(src)) {
31
- console.warn(`Warning: ${hook} not found, skipping`);
32
- continue;
33
- }
34
-
35
- console.log(`Copying ${hook}...`);
36
- fs.copyFileSync(src, dest);
37
- console.log(` → ${dest}`);
38
- }
39
-
40
- console.log('\nBuild complete.');
41
- }
42
-
43
- build();
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Copy GSD hooks to dist for installation.
4
+ */
5
+
6
+ const fs = require('fs');
7
+ const path = require('path');
8
+
9
+ const HOOKS_DIR = path.join(__dirname, '..', 'hooks');
10
+ const DIST_DIR = path.join(HOOKS_DIR, 'dist');
11
+
12
+ // Hooks to copy (pure Node.js, no bundling needed)
13
+ const HOOKS_TO_COPY = [
14
+ 'ez-check-update.js',
15
+ 'ez-context-monitor.js',
16
+ 'ez-statusline.js'
17
+ ];
18
+
19
+ function build() {
20
+ // Ensure dist directory exists
21
+ if (!fs.existsSync(DIST_DIR)) {
22
+ fs.mkdirSync(DIST_DIR, { recursive: true });
23
+ }
24
+
25
+ // Copy hooks to dist
26
+ for (const hook of HOOKS_TO_COPY) {
27
+ const src = path.join(HOOKS_DIR, hook);
28
+ const dest = path.join(DIST_DIR, hook);
29
+
30
+ if (!fs.existsSync(src)) {
31
+ console.warn(`Warning: ${hook} not found, skipping`);
32
+ continue;
33
+ }
34
+
35
+ console.log(`Copying ${hook}...`);
36
+ fs.copyFileSync(src, dest);
37
+ console.log(` → ${dest}`);
38
+ }
39
+
40
+ console.log('\nBuild complete.');
41
+ }
42
+
43
+ build();
@@ -1,29 +1,29 @@
1
- #!/usr/bin/env node
2
- // Cross-platform test runner — resolves test file globs via Node
3
- // instead of relying on shell expansion (which fails on Windows PowerShell/cmd).
4
- // Propagates NODE_V8_COVERAGE so c8 collects coverage from the child process.
5
- 'use strict';
6
-
7
- const { readdirSync } = require('fs');
8
- const { join } = require('path');
9
- const { execFileSync } = require('child_process');
10
-
11
- const testDir = join(__dirname, '..', 'tests');
12
- const files = readdirSync(testDir)
13
- .filter(f => f.endsWith('.test.cjs'))
14
- .sort()
15
- .map(f => join('tests', f));
16
-
17
- if (files.length === 0) {
18
- console.error('No test files found in tests/');
19
- process.exit(1);
20
- }
21
-
22
- try {
23
- execFileSync(process.execPath, ['--test', ...files], {
24
- stdio: 'inherit',
25
- env: { ...process.env },
26
- });
27
- } catch (err) {
28
- process.exit(err.status || 1);
29
- }
1
+ #!/usr/bin/env node
2
+ // Cross-platform test runner — resolves test file globs via Node
3
+ // instead of relying on shell expansion (which fails on Windows PowerShell/cmd).
4
+ // Propagates NODE_V8_COVERAGE so c8 collects coverage from the child process.
5
+ 'use strict';
6
+
7
+ const { readdirSync } = require('fs');
8
+ const { join } = require('path');
9
+ const { execFileSync } = require('child_process');
10
+
11
+ const testDir = join(__dirname, '..', 'tests');
12
+ const files = readdirSync(testDir)
13
+ .filter(f => f.endsWith('.test.cjs'))
14
+ .sort()
15
+ .map(f => join('tests', f));
16
+
17
+ if (files.length === 0) {
18
+ console.error('No test files found in tests/');
19
+ process.exit(1);
20
+ }
21
+
22
+ try {
23
+ execFileSync(process.execPath, ['--test', ...files], {
24
+ stdio: 'inherit',
25
+ env: { ...process.env },
26
+ });
27
+ } catch (err) {
28
+ process.exit(err.status || 1);
29
+ }
File without changes
File without changes
File without changes