@howlil/ez-agents 3.1.0 → 3.4.2
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.
- package/LICENSE +21 -21
- package/README.md +288 -718
- package/bin/install.js +438 -71
- package/commands/ez/auth.md +87 -0
- package/commands/ez/join-discord.md +18 -18
- package/ez-agents/bin/ez-tools.cjs +120 -2
- package/ez-agents/bin/lib/assistant-adapter.cjs +264 -205
- package/ez-agents/bin/lib/audit-exec.cjs +26 -9
- package/ez-agents/bin/lib/auth.cjs +2 -1
- package/ez-agents/bin/lib/circuit-breaker.cjs +118 -118
- package/ez-agents/bin/lib/commands.cjs +42 -23
- package/ez-agents/bin/lib/config.cjs +190 -183
- package/ez-agents/bin/lib/core.cjs +42 -25
- package/ez-agents/bin/lib/file-lock.cjs +236 -236
- package/ez-agents/bin/lib/frontmatter.cjs +299 -299
- package/ez-agents/bin/lib/fs-utils.cjs +153 -153
- package/ez-agents/bin/lib/git-utils.cjs +203 -203
- package/ez-agents/bin/lib/health-check.cjs +2 -3
- package/ez-agents/bin/lib/index.cjs +113 -113
- package/ez-agents/bin/lib/init.cjs +757 -710
- package/ez-agents/bin/lib/logger.cjs +52 -15
- package/ez-agents/bin/lib/milestone.cjs +241 -241
- package/ez-agents/bin/lib/model-provider.cjs +241 -146
- package/ez-agents/bin/lib/phase.cjs +925 -908
- package/ez-agents/bin/lib/planning-write.cjs +107 -0
- package/ez-agents/bin/lib/retry.cjs +119 -119
- package/ez-agents/bin/lib/roadmap.cjs +306 -305
- package/ez-agents/bin/lib/safe-exec.cjs +91 -5
- package/ez-agents/bin/lib/safe-path.cjs +130 -130
- package/ez-agents/bin/lib/state.cjs +736 -721
- package/ez-agents/bin/lib/temp-file.cjs +239 -239
- package/ez-agents/bin/lib/template.cjs +223 -222
- package/ez-agents/bin/lib/test-file-lock.cjs +112 -112
- package/ez-agents/bin/lib/test-graceful.cjs +93 -93
- package/ez-agents/bin/lib/test-logger.cjs +60 -60
- package/ez-agents/bin/lib/test-safe-exec.cjs +38 -38
- package/ez-agents/bin/lib/test-safe-path.cjs +33 -33
- package/ez-agents/bin/lib/test-temp-file.cjs +125 -125
- package/ez-agents/bin/lib/timeout-exec.cjs +63 -62
- package/ez-agents/bin/lib/verify.cjs +69 -26
- package/ez-agents/references/checkpoints.md +776 -776
- package/ez-agents/references/continuation-format.md +249 -249
- package/ez-agents/references/questioning.md +162 -162
- package/ez-agents/references/tdd.md +263 -263
- package/ez-agents/templates/codebase/concerns.md +310 -310
- package/ez-agents/templates/codebase/conventions.md +307 -307
- package/ez-agents/templates/codebase/integrations.md +280 -280
- package/ez-agents/templates/codebase/stack.md +186 -186
- package/ez-agents/templates/codebase/testing.md +480 -480
- package/ez-agents/templates/config.json +37 -37
- package/ez-agents/templates/continue-here.md +78 -78
- package/ez-agents/templates/milestone-archive.md +123 -123
- package/ez-agents/templates/milestone.md +115 -115
- package/ez-agents/templates/requirements.md +231 -231
- package/ez-agents/templates/research-project/ARCHITECTURE.md +204 -204
- package/ez-agents/templates/research-project/FEATURES.md +147 -147
- package/ez-agents/templates/research-project/PITFALLS.md +200 -200
- package/ez-agents/templates/research-project/STACK.md +120 -120
- package/ez-agents/templates/research-project/SUMMARY.md +170 -170
- package/ez-agents/templates/retrospective.md +54 -54
- package/ez-agents/templates/roadmap.md +202 -202
- package/ez-agents/templates/summary-minimal.md +41 -41
- package/ez-agents/templates/summary-standard.md +48 -48
- package/ez-agents/templates/summary.md +248 -248
- package/ez-agents/templates/user-setup.md +311 -311
- package/ez-agents/templates/verification-report.md +322 -322
- package/ez-agents/workflows/add-phase.md +112 -112
- package/ez-agents/workflows/add-tests.md +351 -351
- package/ez-agents/workflows/add-todo.md +158 -158
- package/ez-agents/workflows/audit-milestone.md +332 -332
- package/ez-agents/workflows/autonomous.md +743 -743
- package/ez-agents/workflows/check-todos.md +177 -177
- package/ez-agents/workflows/cleanup.md +152 -152
- package/ez-agents/workflows/complete-milestone.md +766 -766
- package/ez-agents/workflows/diagnose-issues.md +219 -219
- package/ez-agents/workflows/discovery-phase.md +289 -289
- package/ez-agents/workflows/discuss-phase.md +762 -762
- package/ez-agents/workflows/execute-phase.md +468 -468
- package/ez-agents/workflows/execute-plan.md +483 -483
- package/ez-agents/workflows/health.md +159 -159
- package/ez-agents/workflows/help.md +492 -492
- package/ez-agents/workflows/insert-phase.md +130 -130
- package/ez-agents/workflows/list-phase-assumptions.md +178 -178
- package/ez-agents/workflows/map-codebase.md +316 -316
- package/ez-agents/workflows/new-milestone.md +384 -384
- package/ez-agents/workflows/new-project.md +1113 -1111
- package/ez-agents/workflows/node-repair.md +92 -92
- package/ez-agents/workflows/pause-work.md +122 -122
- package/ez-agents/workflows/plan-milestone-gaps.md +274 -274
- package/ez-agents/workflows/plan-phase.md +651 -651
- package/ez-agents/workflows/progress.md +382 -382
- package/ez-agents/workflows/quick.md +610 -610
- package/ez-agents/workflows/remove-phase.md +155 -155
- package/ez-agents/workflows/research-phase.md +74 -74
- package/ez-agents/workflows/resume-project.md +307 -307
- package/ez-agents/workflows/set-profile.md +81 -81
- package/ez-agents/workflows/settings.md +242 -242
- package/ez-agents/workflows/stats.md +57 -57
- package/ez-agents/workflows/transition.md +544 -544
- package/ez-agents/workflows/ui-phase.md +290 -290
- package/ez-agents/workflows/ui-review.md +157 -157
- package/ez-agents/workflows/update.md +320 -320
- package/ez-agents/workflows/validate-phase.md +167 -167
- package/ez-agents/workflows/verify-phase.md +243 -243
- package/ez-agents/workflows/verify-work.md +584 -584
- package/package.json +2 -3
- package/scripts/build-hooks.js +43 -43
- package/scripts/fix-qwen-installation.js +144 -0
- package/scripts/run-tests.cjs +29 -29
- package/README.zh-CN.md +0 -702
|
@@ -7,8 +7,9 @@ const path = require('path');
|
|
|
7
7
|
const { safeReadFile, normalizePhaseName, execGit, findPhaseInternal, getMilestoneInfo, output, error } = require('./core.cjs');
|
|
8
8
|
const { extractFrontmatter, parseMustHavesBlock } = require('./frontmatter.cjs');
|
|
9
9
|
const { writeStateMd } = require('./state.cjs');
|
|
10
|
+
const { defaultLogger: logger } = require('./logger.cjs');
|
|
10
11
|
|
|
11
|
-
function cmdVerifySummary(cwd, summaryPath, checkFileCount, raw) {
|
|
12
|
+
async function cmdVerifySummary(cwd, summaryPath, checkFileCount, raw) {
|
|
12
13
|
if (!summaryPath) {
|
|
13
14
|
error('summary-path required');
|
|
14
15
|
}
|
|
@@ -66,7 +67,7 @@ function cmdVerifySummary(cwd, summaryPath, checkFileCount, raw) {
|
|
|
66
67
|
let commitsExist = false;
|
|
67
68
|
if (hashes.length > 0) {
|
|
68
69
|
for (const hash of hashes.slice(0, 3)) {
|
|
69
|
-
const result = execGit(cwd, ['cat-file', '-t', hash]);
|
|
70
|
+
const result = await execGit(cwd, ['cat-file', '-t', hash]);
|
|
70
71
|
if (result.exitCode === 0 && result.stdout === 'commit') {
|
|
71
72
|
commitsExist = true;
|
|
72
73
|
break;
|
|
@@ -179,7 +180,13 @@ function cmdVerifyPhaseCompleteness(cwd, phase, raw) {
|
|
|
179
180
|
|
|
180
181
|
// List plans and summaries
|
|
181
182
|
let files;
|
|
182
|
-
try {
|
|
183
|
+
try {
|
|
184
|
+
files = fs.readdirSync(phaseDir);
|
|
185
|
+
} catch (err) {
|
|
186
|
+
logger.warn('Failed to read phase directory in cmdVerifyPhaseCompleteness', { phaseDir, error: err.message });
|
|
187
|
+
output({ error: 'Cannot read phase directory' }, raw);
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
183
190
|
|
|
184
191
|
const plans = files.filter(f => f.match(/-PLAN\.md$/i));
|
|
185
192
|
const summaries = files.filter(f => f.match(/-SUMMARY\.md$/i));
|
|
@@ -257,17 +264,31 @@ function cmdVerifyReferences(cwd, filePath, raw) {
|
|
|
257
264
|
}, raw, missing.length === 0 ? 'valid' : 'invalid');
|
|
258
265
|
}
|
|
259
266
|
|
|
260
|
-
function cmdVerifyCommits(cwd, hashes, raw) {
|
|
267
|
+
async function cmdVerifyCommits(cwd, hashes, raw) {
|
|
261
268
|
if (!hashes || hashes.length === 0) { error('At least one commit hash required'); }
|
|
262
269
|
|
|
263
270
|
const valid = [];
|
|
264
271
|
const invalid = [];
|
|
265
272
|
for (const hash of hashes) {
|
|
266
|
-
|
|
273
|
+
// Use git cat-file -t which supports both short and full hashes
|
|
274
|
+
// First try with the hash as-is (works for both short and full)
|
|
275
|
+
const result = await execGit(cwd, ['cat-file', '-t', hash]);
|
|
267
276
|
if (result.exitCode === 0 && result.stdout.trim() === 'commit') {
|
|
268
277
|
valid.push(hash);
|
|
269
278
|
} else {
|
|
270
|
-
|
|
279
|
+
// If that fails, try to resolve to full hash first
|
|
280
|
+
const resolveResult = await execGit(cwd, ['rev-parse', hash]);
|
|
281
|
+
if (resolveResult.exitCode === 0) {
|
|
282
|
+
const fullHash = resolveResult.stdout.trim();
|
|
283
|
+
const result2 = await execGit(cwd, ['cat-file', '-t', fullHash]);
|
|
284
|
+
if (result2.exitCode === 0 && result2.stdout.trim() === 'commit') {
|
|
285
|
+
valid.push(hash);
|
|
286
|
+
} else {
|
|
287
|
+
invalid.push(hash);
|
|
288
|
+
}
|
|
289
|
+
} else {
|
|
290
|
+
invalid.push(hash);
|
|
291
|
+
}
|
|
271
292
|
}
|
|
272
293
|
}
|
|
273
294
|
|
|
@@ -369,7 +390,8 @@ function cmdVerifyKeyLinks(cwd, planFilePath, raw) {
|
|
|
369
390
|
check.detail = `Pattern "${link.pattern}" not found in source or target`;
|
|
370
391
|
}
|
|
371
392
|
}
|
|
372
|
-
} catch {
|
|
393
|
+
} catch (err) {
|
|
394
|
+
logger.warn('Invalid regex while verifying key links', { pattern: link.pattern, error: err.message });
|
|
373
395
|
check.detail = `Invalid regex pattern: ${link.pattern}`;
|
|
374
396
|
}
|
|
375
397
|
} else {
|
|
@@ -426,7 +448,9 @@ function cmdValidateConsistency(cwd, raw) {
|
|
|
426
448
|
const dm = dir.match(/^(\d+[A-Z]?(?:\.\d+)*)/i);
|
|
427
449
|
if (dm) diskPhases.add(dm[1]);
|
|
428
450
|
}
|
|
429
|
-
} catch {
|
|
451
|
+
} catch (err) {
|
|
452
|
+
logger.warn('Failed to enumerate phase directories while validating consistency', { phasesDir, error: err.message });
|
|
453
|
+
}
|
|
430
454
|
|
|
431
455
|
// Check: phases in ROADMAP but not on disk
|
|
432
456
|
for (const p of roadmapPhases) {
|
|
@@ -488,7 +512,9 @@ function cmdValidateConsistency(cwd, raw) {
|
|
|
488
512
|
}
|
|
489
513
|
}
|
|
490
514
|
}
|
|
491
|
-
} catch {
|
|
515
|
+
} catch (err) {
|
|
516
|
+
logger.warn('Failed to validate plan numbering while validating consistency', { phasesDir, error: err.message });
|
|
517
|
+
}
|
|
492
518
|
|
|
493
519
|
// Check: frontmatter in plans has required fields
|
|
494
520
|
try {
|
|
@@ -508,7 +534,9 @@ function cmdValidateConsistency(cwd, raw) {
|
|
|
508
534
|
}
|
|
509
535
|
}
|
|
510
536
|
}
|
|
511
|
-
} catch {
|
|
537
|
+
} catch (err) {
|
|
538
|
+
logger.warn('Failed to validate plan frontmatter while validating consistency', { phasesDir, error: err.message });
|
|
539
|
+
}
|
|
512
540
|
|
|
513
541
|
const passed = errors.length === 0;
|
|
514
542
|
output({ passed, errors, warnings, warning_count: warnings.length }, raw, passed ? 'passed' : 'failed');
|
|
@@ -537,7 +565,7 @@ function cmdValidateHealth(cwd, options, raw) {
|
|
|
537
565
|
|
|
538
566
|
// ─── Check 1: .planning/ exists ───────────────────────────────────────────
|
|
539
567
|
if (!fs.existsSync(planningDir)) {
|
|
540
|
-
addIssue('error', 'E001', '.planning/ directory not found', 'Run /
|
|
568
|
+
addIssue('error', 'E001', '.planning/ directory not found', 'Run /ez:new-project to initialize');
|
|
541
569
|
output({
|
|
542
570
|
status: 'broken',
|
|
543
571
|
errors,
|
|
@@ -550,7 +578,7 @@ function cmdValidateHealth(cwd, options, raw) {
|
|
|
550
578
|
|
|
551
579
|
// ─── Check 2: PROJECT.md exists and has required sections ─────────────────
|
|
552
580
|
if (!fs.existsSync(projectPath)) {
|
|
553
|
-
addIssue('error', 'E002', 'PROJECT.md not found', 'Run /
|
|
581
|
+
addIssue('error', 'E002', 'PROJECT.md not found', 'Run /ez:new-project to create');
|
|
554
582
|
} else {
|
|
555
583
|
const content = fs.readFileSync(projectPath, 'utf-8');
|
|
556
584
|
const requiredSections = ['## What This Is', '## Core Value', '## Requirements'];
|
|
@@ -563,12 +591,12 @@ function cmdValidateHealth(cwd, options, raw) {
|
|
|
563
591
|
|
|
564
592
|
// ─── Check 3: ROADMAP.md exists ───────────────────────────────────────────
|
|
565
593
|
if (!fs.existsSync(roadmapPath)) {
|
|
566
|
-
addIssue('error', 'E003', 'ROADMAP.md not found', 'Run /
|
|
594
|
+
addIssue('error', 'E003', 'ROADMAP.md not found', 'Run /ez:new-milestone to create roadmap');
|
|
567
595
|
}
|
|
568
596
|
|
|
569
597
|
// ─── Check 4: STATE.md exists and references valid phases ─────────────────
|
|
570
598
|
if (!fs.existsSync(statePath)) {
|
|
571
|
-
addIssue('error', 'E004', 'STATE.md not found', 'Run /
|
|
599
|
+
addIssue('error', 'E004', 'STATE.md not found', 'Run /ez:health --repair to regenerate', true);
|
|
572
600
|
repairs.push('regenerateState');
|
|
573
601
|
} else {
|
|
574
602
|
const stateContent = fs.readFileSync(statePath, 'utf-8');
|
|
@@ -584,14 +612,16 @@ function cmdValidateHealth(cwd, options, raw) {
|
|
|
584
612
|
if (m) diskPhases.add(m[1]);
|
|
585
613
|
}
|
|
586
614
|
}
|
|
587
|
-
} catch {
|
|
615
|
+
} catch (err) {
|
|
616
|
+
logger.warn('Failed to read phase directories while validating STATE references', { phasesDir, error: err.message });
|
|
617
|
+
}
|
|
588
618
|
// Check for invalid references
|
|
589
619
|
for (const ref of phaseRefs) {
|
|
590
620
|
const normalizedRef = String(parseInt(ref, 10)).padStart(2, '0');
|
|
591
621
|
if (!diskPhases.has(ref) && !diskPhases.has(normalizedRef) && !diskPhases.has(String(parseInt(ref, 10)))) {
|
|
592
622
|
// Only warn if phases dir has any content (not just an empty project)
|
|
593
623
|
if (diskPhases.size > 0) {
|
|
594
|
-
addIssue('warning', 'W002', `STATE.md references phase ${ref}, but only phases ${[...diskPhases].sort().join(', ')} exist`, 'Run /
|
|
624
|
+
addIssue('warning', 'W002', `STATE.md references phase ${ref}, but only phases ${[...diskPhases].sort().join(', ')} exist`, 'Run /ez:health --repair to regenerate STATE.md', true);
|
|
595
625
|
if (!repairs.includes('regenerateState')) repairs.push('regenerateState');
|
|
596
626
|
}
|
|
597
627
|
}
|
|
@@ -600,7 +630,7 @@ function cmdValidateHealth(cwd, options, raw) {
|
|
|
600
630
|
|
|
601
631
|
// ─── Check 5: config.json valid JSON + valid schema ───────────────────────
|
|
602
632
|
if (!fs.existsSync(configPath)) {
|
|
603
|
-
addIssue('warning', 'W003', 'config.json not found', 'Run /
|
|
633
|
+
addIssue('warning', 'W003', 'config.json not found', 'Run /ez:health --repair to create with defaults', true);
|
|
604
634
|
repairs.push('createConfig');
|
|
605
635
|
} else {
|
|
606
636
|
try {
|
|
@@ -612,7 +642,8 @@ function cmdValidateHealth(cwd, options, raw) {
|
|
|
612
642
|
addIssue('warning', 'W004', `config.json: invalid model_profile "${parsed.model_profile}"`, `Valid values: ${validProfiles.join(', ')}`);
|
|
613
643
|
}
|
|
614
644
|
} catch (err) {
|
|
615
|
-
|
|
645
|
+
logger.warn('Failed to parse config.json in cmdValidateHealth', { configPath, error: err.message });
|
|
646
|
+
addIssue('error', 'E005', `config.json: JSON parse error - ${err.message}`, 'Run /ez:health --repair to reset to defaults', true);
|
|
616
647
|
repairs.push('resetConfig');
|
|
617
648
|
}
|
|
618
649
|
}
|
|
@@ -623,10 +654,12 @@ function cmdValidateHealth(cwd, options, raw) {
|
|
|
623
654
|
const configRaw = fs.readFileSync(configPath, 'utf-8');
|
|
624
655
|
const configParsed = JSON.parse(configRaw);
|
|
625
656
|
if (configParsed.workflow && configParsed.workflow.nyquist_validation === undefined) {
|
|
626
|
-
addIssue('warning', 'W008', 'config.json: workflow.nyquist_validation absent (defaults to enabled but agents may skip)', 'Run /
|
|
657
|
+
addIssue('warning', 'W008', 'config.json: workflow.nyquist_validation absent (defaults to enabled but agents may skip)', 'Run /ez:health --repair to add key', true);
|
|
627
658
|
if (!repairs.includes('addNyquistKey')) repairs.push('addNyquistKey');
|
|
628
659
|
}
|
|
629
|
-
} catch {
|
|
660
|
+
} catch (err) {
|
|
661
|
+
logger.warn('Failed to parse config for nyquist key check', { configPath, error: err.message });
|
|
662
|
+
}
|
|
630
663
|
}
|
|
631
664
|
|
|
632
665
|
// ─── Check 6: Phase directory naming (NN-name format) ─────────────────────
|
|
@@ -637,7 +670,9 @@ function cmdValidateHealth(cwd, options, raw) {
|
|
|
637
670
|
addIssue('warning', 'W005', `Phase directory "${e.name}" doesn't follow NN-name format`, 'Rename to match pattern (e.g., 01-setup)');
|
|
638
671
|
}
|
|
639
672
|
}
|
|
640
|
-
} catch {
|
|
673
|
+
} catch (err) {
|
|
674
|
+
logger.warn('Failed to inspect phase directory naming in health validation', { phasesDir, error: err.message });
|
|
675
|
+
}
|
|
641
676
|
|
|
642
677
|
// ─── Check 7: Orphaned plans (PLAN without SUMMARY) ───────────────────────
|
|
643
678
|
try {
|
|
@@ -656,7 +691,9 @@ function cmdValidateHealth(cwd, options, raw) {
|
|
|
656
691
|
}
|
|
657
692
|
}
|
|
658
693
|
}
|
|
659
|
-
} catch {
|
|
694
|
+
} catch (err) {
|
|
695
|
+
logger.warn('Failed to inspect orphaned plans in health validation', { phasesDir, error: err.message });
|
|
696
|
+
}
|
|
660
697
|
|
|
661
698
|
// ─── Check 7b: Nyquist VALIDATION.md consistency ────────────────────────
|
|
662
699
|
try {
|
|
@@ -670,11 +707,13 @@ function cmdValidateHealth(cwd, options, raw) {
|
|
|
670
707
|
const researchFile = phaseFiles.find(f => f.endsWith('-RESEARCH.md'));
|
|
671
708
|
const researchContent = fs.readFileSync(path.join(phasesDir, e.name, researchFile), 'utf-8');
|
|
672
709
|
if (researchContent.includes('## Validation Architecture')) {
|
|
673
|
-
addIssue('warning', 'W009', `Phase ${e.name}: has Validation Architecture in RESEARCH.md but no VALIDATION.md`, 'Re-run /
|
|
710
|
+
addIssue('warning', 'W009', `Phase ${e.name}: has Validation Architecture in RESEARCH.md but no VALIDATION.md`, 'Re-run /ez-plan-phase with --research to regenerate');
|
|
674
711
|
}
|
|
675
712
|
}
|
|
676
713
|
}
|
|
677
|
-
} catch {
|
|
714
|
+
} catch (err) {
|
|
715
|
+
logger.warn('Failed to inspect validation architecture consistency in health validation', { phasesDir, error: err.message });
|
|
716
|
+
}
|
|
678
717
|
|
|
679
718
|
// ─── Check 8: Run existing consistency checks ─────────────────────────────
|
|
680
719
|
// Inline subset of cmdValidateConsistency
|
|
@@ -696,7 +735,9 @@ function cmdValidateHealth(cwd, options, raw) {
|
|
|
696
735
|
if (dm) diskPhases.add(dm[1]);
|
|
697
736
|
}
|
|
698
737
|
}
|
|
699
|
-
} catch {
|
|
738
|
+
} catch (err) {
|
|
739
|
+
logger.warn('Failed to run roadmap/disk consistency checks in health validation', { roadmapPath, phasesDir, error: err.message });
|
|
740
|
+
}
|
|
700
741
|
|
|
701
742
|
// Phases in ROADMAP but not on disk
|
|
702
743
|
for (const p of roadmapPhases) {
|
|
@@ -755,7 +796,7 @@ function cmdValidateHealth(cwd, options, raw) {
|
|
|
755
796
|
stateContent += `**Current phase:** (determining...)\n`;
|
|
756
797
|
stateContent += `**Status:** Resuming\n\n`;
|
|
757
798
|
stateContent += `## Session Log\n\n`;
|
|
758
|
-
stateContent += `- ${new Date().toISOString().split('T')[0]}: STATE.md regenerated by /
|
|
799
|
+
stateContent += `- ${new Date().toISOString().split('T')[0]}: STATE.md regenerated by /ez:health --repair\n`;
|
|
759
800
|
writeStateMd(statePath, stateContent, cwd);
|
|
760
801
|
repairActions.push({ action: repair, success: true, path: 'STATE.md' });
|
|
761
802
|
break;
|
|
@@ -772,6 +813,7 @@ function cmdValidateHealth(cwd, options, raw) {
|
|
|
772
813
|
}
|
|
773
814
|
repairActions.push({ action: repair, success: true, path: 'config.json' });
|
|
774
815
|
} catch (err) {
|
|
816
|
+
logger.error('Failed to repair nyquist key', { error: err.message });
|
|
775
817
|
repairActions.push({ action: repair, success: false, error: err.message });
|
|
776
818
|
}
|
|
777
819
|
}
|
|
@@ -779,6 +821,7 @@ function cmdValidateHealth(cwd, options, raw) {
|
|
|
779
821
|
}
|
|
780
822
|
}
|
|
781
823
|
} catch (err) {
|
|
824
|
+
logger.error('Failed to perform repair action', { action: repair, error: err.message });
|
|
782
825
|
repairActions.push({ action: repair, success: false, error: err.message });
|
|
783
826
|
}
|
|
784
827
|
}
|