@howlil/ez-agents 3.4.2 → 4.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.
- package/README.md +735 -462
- package/agents/ez-architect-agent.md +267 -0
- package/agents/ez-backend-agent.md +303 -0
- package/agents/ez-chief-strategist.md +271 -0
- package/agents/ez-codebase-mapper.md +770 -770
- package/agents/ez-context-manager.md +319 -0
- package/agents/ez-debugger.md +1255 -1255
- package/agents/ez-design-expert.md +347 -0
- package/agents/ez-devops-agent.md +331 -0
- package/agents/ez-executor.md +487 -487
- package/agents/ez-frontend-agent.md +322 -0
- package/agents/ez-phase-researcher.md +553 -553
- package/agents/ez-planner.md +1307 -1307
- package/agents/ez-product-engineer.md +435 -0
- package/agents/ez-project-researcher.md +629 -629
- package/agents/ez-qa-agent.md +320 -0
- package/agents/ez-release-agent.md +333 -0
- package/agents/ez-requirements-agent.md +377 -0
- package/agents/ez-roadmapper.md +650 -650
- package/agents/ez-technical-writer.md +551 -0
- package/agents/ez-ux-expert.md +393 -0
- package/agents/ez-verifier.md +579 -579
- package/bin/guards/autonomy-guard.cjs +346 -0
- package/bin/guards/context-budget-guard.cjs +278 -0
- package/bin/guards/hallucination-guard.cjs +380 -0
- package/bin/guards/hidden-state-guard.cjs +182 -0
- package/bin/guards/team-overhead-guard.cjs +266 -0
- package/bin/guards/tool-sprawl-guard.cjs +271 -0
- package/bin/install.js +3221 -3272
- package/bin/lib/analytics/analytics-collector.cjs +86 -0
- package/bin/lib/analytics/analytics-reporter.cjs +130 -0
- package/bin/lib/analytics/cohort-analyzer.cjs +138 -0
- package/bin/lib/analytics/funnel-analyzer.cjs +147 -0
- package/bin/lib/analytics/nps-tracker.cjs +147 -0
- package/bin/lib/archetype-detector.cjs +289 -0
- package/bin/lib/assistant-adapter.cjs +361 -0
- package/bin/lib/audit-exec.cjs +175 -0
- package/bin/lib/auth.cjs +176 -0
- package/bin/lib/backup-service.cjs +422 -0
- package/bin/lib/bdd-validator.cjs +622 -0
- package/bin/lib/business-flow-mapper.cjs +429 -0
- package/bin/lib/circuit-breaker.cjs +276 -0
- package/bin/lib/code-complexity-analyzer.cjs +360 -0
- package/bin/lib/codebase-analyzer.cjs +241 -0
- package/bin/lib/commands.cjs +691 -0
- package/bin/lib/config.cjs +236 -0
- package/bin/lib/constraint-extractor.cjs +526 -0
- package/bin/lib/content-scanner.cjs +238 -0
- package/bin/lib/context-cache.cjs +154 -0
- package/bin/lib/context-compressor.cjs +102 -0
- package/bin/lib/context-deduplicator.cjs +105 -0
- package/bin/lib/context-errors.cjs +78 -0
- package/bin/lib/context-manager.cjs +338 -0
- package/bin/lib/context-metadata-tracker.cjs +140 -0
- package/bin/lib/context-relevance-scorer.cjs +99 -0
- package/bin/lib/core.cjs +507 -0
- package/bin/lib/cost-alerts.cjs +174 -0
- package/bin/lib/cost-tracker.cjs +275 -0
- package/bin/lib/crash-recovery.cjs +220 -0
- package/bin/lib/dependency-graph.cjs +319 -0
- package/bin/lib/deploy/deploy-audit-log.cjs +76 -0
- package/bin/lib/deploy/deploy-detector.cjs +69 -0
- package/bin/lib/deploy/deploy-env-manager.cjs +109 -0
- package/bin/lib/deploy/deploy-health-check.cjs +88 -0
- package/bin/lib/deploy/deploy-pre-flight.cjs +57 -0
- package/bin/lib/deploy/deploy-rollback.cjs +72 -0
- package/bin/lib/deploy/deploy-runner.cjs +97 -0
- package/bin/lib/deploy/deploy-status.cjs +74 -0
- package/bin/lib/discussion-synthesizer.cjs +439 -0
- package/bin/lib/error-cache.cjs +114 -0
- package/bin/lib/error-registry.cjs +177 -0
- package/bin/lib/file-access.cjs +207 -0
- package/bin/lib/file-lock.cjs +236 -0
- package/bin/lib/finops/budget-enforcer.cjs +126 -0
- package/bin/lib/finops/cost-reporter.cjs +132 -0
- package/bin/lib/finops/finops-analyzer.cjs +112 -0
- package/bin/lib/finops/spot-manager.cjs +118 -0
- package/bin/lib/framework-detector.cjs +396 -0
- package/bin/lib/frontmatter.cjs +313 -0
- package/bin/lib/fs-utils.cjs +153 -0
- package/bin/lib/gate-executor.cjs +272 -0
- package/bin/lib/gates/README.md +374 -0
- package/bin/lib/gates/gate-01-requirement.cjs +303 -0
- package/bin/lib/gates/gate-02-architecture.cjs +555 -0
- package/bin/lib/gates/gate-03-code.cjs +635 -0
- package/bin/lib/gates/gate-04-security.cjs +829 -0
- package/bin/lib/git-errors.cjs +83 -0
- package/bin/lib/git-utils.cjs +321 -0
- package/bin/lib/git-workflow-engine.cjs +1157 -0
- package/bin/lib/health-check.cjs +227 -0
- package/bin/lib/index.cjs +279 -0
- package/bin/lib/init.cjs +725 -0
- package/bin/lib/lock-logger.cjs +194 -0
- package/bin/lib/lock-state.cjs +263 -0
- package/bin/lib/lockfile-validator.cjs +227 -0
- package/bin/lib/log-rotation.cjs +71 -0
- package/bin/lib/logger.cjs +125 -0
- package/bin/lib/memory-compression.cjs +256 -0
- package/bin/lib/milestone.cjs +247 -0
- package/bin/lib/model-provider.cjs +241 -0
- package/bin/lib/package-manager-detector.cjs +203 -0
- package/bin/lib/package-manager-executor.cjs +385 -0
- package/bin/lib/package-manager-service.cjs +216 -0
- package/bin/lib/perf/api-monitor.cjs +88 -0
- package/bin/lib/perf/db-optimizer.cjs +78 -0
- package/bin/lib/perf/frontend-performance.cjs +56 -0
- package/bin/lib/perf/perf-analyzer.cjs +77 -0
- package/bin/lib/perf/perf-baseline.cjs +102 -0
- package/bin/lib/perf/perf-reporter.cjs +117 -0
- package/bin/lib/perf/regression-detector.cjs +92 -0
- package/bin/lib/phase.cjs +963 -0
- package/bin/lib/planning-write.cjs +123 -0
- package/bin/lib/project-reporter.cjs +565 -0
- package/bin/lib/quality-gate.cjs +332 -0
- package/bin/lib/quality-metrics.cjs +324 -0
- package/bin/lib/recovery-manager.cjs +98 -0
- package/bin/lib/release-validator.cjs +617 -0
- package/bin/lib/retry.cjs +119 -0
- package/bin/lib/roadmap.cjs +309 -0
- package/bin/lib/safe-exec.cjs +173 -0
- package/bin/lib/safe-path.cjs +130 -0
- package/bin/lib/security-errors.cjs +62 -0
- package/bin/lib/session-chain.cjs +304 -0
- package/bin/lib/session-errors.cjs +81 -0
- package/bin/lib/session-export.cjs +251 -0
- package/bin/lib/session-import.cjs +262 -0
- package/bin/lib/session-manager.cjs +280 -0
- package/bin/lib/skill-context.cjs +148 -0
- package/bin/lib/skill-matcher.cjs +236 -0
- package/bin/lib/skill-registry.cjs +360 -0
- package/bin/lib/skill-resolver.cjs +449 -0
- package/bin/lib/skill-triggers.cjs +90 -0
- package/bin/lib/skill-validator.cjs +270 -0
- package/bin/lib/skill-versioning.cjs +355 -0
- package/bin/lib/stack-detector.cjs +399 -0
- package/bin/lib/state.cjs +736 -0
- package/bin/lib/tech-debt-analyzer.cjs +309 -0
- package/bin/lib/temp-file.cjs +239 -0
- package/bin/lib/template.cjs +223 -0
- package/bin/lib/test-file-lock.cjs +112 -0
- package/bin/lib/test-graceful.cjs +93 -0
- package/bin/lib/test-logger.cjs +60 -0
- package/bin/lib/test-safe-exec.cjs +38 -0
- package/bin/lib/test-safe-path.cjs +33 -0
- package/bin/lib/test-temp-file.cjs +125 -0
- package/bin/lib/tier-manager.cjs +428 -0
- package/bin/lib/timeout-exec.cjs +63 -0
- package/bin/lib/tradeoff-analyzer.cjs +284 -0
- package/bin/lib/url-fetch.cjs +170 -0
- package/bin/lib/verify.cjs +863 -0
- package/bin/update.js +217 -214
- package/commands/deploy.cjs +53 -0
- package/commands/ez/add-tests.md +41 -41
- package/commands/ez/audit-milestone.md +36 -36
- package/commands/ez/complete-milestone.md +136 -136
- package/commands/ez/discuss-phase.md +90 -90
- package/commands/ez/execute-phase.md +52 -41
- package/commands/ez/help.md +22 -22
- package/commands/ez/map-codebase.md +71 -71
- package/commands/ez/new-milestone.md +44 -44
- package/commands/ez/new-project.md +51 -42
- package/commands/ez/plan-phase.md +53 -45
- package/commands/ez/progress.md +36 -24
- package/commands/ez/quick.md +45 -45
- package/commands/ez/resume-work.md +40 -40
- package/commands/ez/run-phase.md +580 -0
- package/commands/ez/settings.md +36 -36
- package/commands/ez/update.md +37 -37
- package/commands/ez/verify-work.md +402 -38
- package/commands/health-check.cjs +44 -0
- package/commands/rollback.cjs +47 -0
- package/ez-agents/bin/ez-tools.cjs +1692 -716
- package/ez-agents/bin/guards/autonomy-guard.cjs +346 -0
- package/ez-agents/bin/guards/context-budget-guard.cjs +247 -0
- package/ez-agents/bin/guards/hallucination-guard.cjs +271 -0
- package/ez-agents/bin/guards/hidden-state-guard.cjs +182 -0
- package/ez-agents/bin/guards/team-overhead-guard.cjs +266 -0
- package/ez-agents/bin/guards/tool-sprawl-guard.cjs +271 -0
- package/ez-agents/bin/lib/analytics/analytics-collector.cjs +86 -0
- package/ez-agents/bin/lib/analytics/analytics-reporter.cjs +130 -0
- package/ez-agents/bin/lib/analytics/cohort-analyzer.cjs +138 -0
- package/ez-agents/bin/lib/analytics/funnel-analyzer.cjs +147 -0
- package/ez-agents/bin/lib/analytics/nps-tracker.cjs +147 -0
- package/ez-agents/bin/lib/archetype-detector.cjs +289 -0
- package/ez-agents/bin/lib/audit-exec.cjs +166 -167
- package/ez-agents/bin/lib/auth.cjs +176 -176
- package/ez-agents/bin/lib/backup-service.cjs +422 -0
- package/ez-agents/bin/lib/bdd-validator.cjs +622 -0
- package/ez-agents/bin/lib/business-flow-mapper.cjs +429 -0
- package/ez-agents/bin/lib/code-complexity-analyzer.cjs +360 -0
- package/ez-agents/bin/lib/codebase-analyzer.cjs +241 -0
- package/ez-agents/bin/lib/commands.cjs +685 -685
- package/ez-agents/bin/lib/config.cjs +41 -1
- package/ez-agents/bin/lib/constraint-extractor.cjs +526 -0
- package/ez-agents/bin/lib/content-scanner.cjs +238 -0
- package/ez-agents/bin/lib/context-cache.cjs +154 -0
- package/ez-agents/bin/lib/context-errors.cjs +71 -0
- package/ez-agents/bin/lib/context-manager.cjs +220 -0
- package/ez-agents/bin/lib/core.cjs +507 -512
- package/ez-agents/bin/lib/cost-tracker.cjs +243 -0
- package/ez-agents/bin/lib/crash-recovery.cjs +172 -0
- package/ez-agents/bin/lib/dependency-graph.cjs +319 -0
- package/ez-agents/bin/lib/deploy/deploy-audit-log.cjs +76 -0
- package/ez-agents/bin/lib/deploy/deploy-detector.cjs +69 -0
- package/ez-agents/bin/lib/deploy/deploy-env-manager.cjs +109 -0
- package/ez-agents/bin/lib/deploy/deploy-health-check.cjs +88 -0
- package/ez-agents/bin/lib/deploy/deploy-pre-flight.cjs +57 -0
- package/ez-agents/bin/lib/deploy/deploy-rollback.cjs +72 -0
- package/ez-agents/bin/lib/deploy/deploy-runner.cjs +97 -0
- package/ez-agents/bin/lib/deploy/deploy-status.cjs +74 -0
- package/ez-agents/bin/lib/discussion-synthesizer.cjs +458 -0
- package/ez-agents/bin/lib/file-access.cjs +207 -0
- package/ez-agents/bin/lib/finops/budget-enforcer.cjs +126 -0
- package/ez-agents/bin/lib/finops/cost-reporter.cjs +132 -0
- package/ez-agents/bin/lib/finops/finops-analyzer.cjs +112 -0
- package/ez-agents/bin/lib/finops/spot-manager.cjs +118 -0
- package/ez-agents/bin/lib/framework-detector.cjs +396 -0
- package/ez-agents/bin/lib/frontmatter.cjs +3 -1
- package/ez-agents/bin/lib/gates/README.md +374 -0
- package/ez-agents/bin/lib/gates/gate-01-requirement.cjs +303 -0
- package/ez-agents/bin/lib/gates/gate-02-architecture.cjs +555 -0
- package/ez-agents/bin/lib/gates/gate-03-code.cjs +635 -0
- package/ez-agents/bin/lib/gates/gate-04-security.cjs +829 -0
- package/ez-agents/bin/lib/git-errors.cjs +83 -0
- package/ez-agents/bin/lib/git-utils.cjs +118 -0
- package/ez-agents/bin/lib/git-workflow-engine.cjs +1157 -0
- package/ez-agents/bin/lib/health-check.cjs +162 -162
- package/ez-agents/bin/lib/index.cjs +40 -2
- package/ez-agents/bin/lib/init.cjs +0 -2
- package/ez-agents/bin/lib/lockfile-validator.cjs +227 -0
- package/ez-agents/bin/lib/log-rotation.cjs +71 -0
- package/ez-agents/bin/lib/logger.cjs +99 -154
- package/ez-agents/bin/lib/memory-compression.cjs +256 -0
- package/ez-agents/bin/lib/package-manager-detector.cjs +203 -0
- package/ez-agents/bin/lib/package-manager-executor.cjs +385 -0
- package/ez-agents/bin/lib/package-manager-service.cjs +216 -0
- package/ez-agents/bin/lib/perf/api-monitor.cjs +88 -0
- package/ez-agents/bin/lib/perf/db-optimizer.cjs +78 -0
- package/ez-agents/bin/lib/perf/frontend-performance.cjs +56 -0
- package/ez-agents/bin/lib/perf/perf-analyzer.cjs +77 -0
- package/ez-agents/bin/lib/perf/perf-baseline.cjs +102 -0
- package/ez-agents/bin/lib/perf/perf-reporter.cjs +117 -0
- package/ez-agents/bin/lib/perf/regression-detector.cjs +92 -0
- package/ez-agents/bin/lib/project-reporter.cjs +502 -0
- package/ez-agents/bin/lib/quality-gate.cjs +332 -0
- package/ez-agents/bin/lib/recovery-manager.cjs +98 -0
- package/ez-agents/bin/lib/release-validator.cjs +617 -0
- package/ez-agents/bin/lib/safe-exec.cjs +128 -214
- package/ez-agents/bin/lib/security-errors.cjs +62 -0
- package/ez-agents/bin/lib/session-chain.cjs +304 -0
- package/ez-agents/bin/lib/session-errors.cjs +81 -0
- package/ez-agents/bin/lib/session-export.cjs +251 -0
- package/ez-agents/bin/lib/session-import.cjs +262 -0
- package/ez-agents/bin/lib/session-manager.cjs +280 -0
- package/ez-agents/bin/lib/skill-context.cjs +148 -0
- package/ez-agents/bin/lib/skill-matcher.cjs +236 -0
- package/ez-agents/bin/lib/skill-registry.cjs +341 -0
- package/ez-agents/bin/lib/skill-resolver.cjs +449 -0
- package/ez-agents/bin/lib/skill-triggers.cjs +90 -0
- package/ez-agents/bin/lib/skill-validator.cjs +270 -0
- package/ez-agents/bin/lib/skill-versioning.cjs +355 -0
- package/ez-agents/bin/lib/stack-detector.cjs +399 -0
- package/ez-agents/bin/lib/tech-debt-analyzer.cjs +309 -0
- package/ez-agents/bin/lib/tier-manager.cjs +428 -0
- package/ez-agents/bin/lib/tradeoff-analyzer.cjs +284 -0
- package/ez-agents/bin/lib/url-fetch.cjs +170 -0
- package/ez-agents/bin/lib/verify.cjs +863 -863
- package/ez-agents/references/decimal-phase-calculation.md +65 -65
- package/ez-agents/references/git-integration.md +248 -248
- package/ez-agents/references/git-planning-commit.md +38 -38
- package/ez-agents/references/metrics-schema.md +118 -0
- package/ez-agents/references/model-profile-resolution.md +34 -34
- package/ez-agents/references/model-profiles.md +93 -93
- package/ez-agents/references/phase-argument-parsing.md +61 -61
- package/ez-agents/references/planning-config.md +340 -200
- package/ez-agents/references/tier-strategy.md +103 -0
- package/ez-agents/references/ui-brand.md +160 -160
- package/ez-agents/references/verification-patterns.md +612 -612
- package/ez-agents/templates/DEBUG.md +164 -164
- package/ez-agents/templates/UAT.md +247 -247
- package/ez-agents/templates/agent-output-format.md +404 -0
- package/ez-agents/templates/bdd-feature.md +173 -0
- package/ez-agents/templates/codebase/architecture.md +255 -255
- package/ez-agents/templates/codebase/structure.md +285 -285
- package/ez-agents/templates/copilot-instructions.md +7 -7
- package/ez-agents/templates/debug-subagent-prompt.md +91 -91
- package/ez-agents/templates/discovery.md +146 -146
- package/ez-agents/templates/discussion.md +68 -0
- package/ez-agents/templates/handoff-protocol.md +294 -0
- package/ez-agents/templates/incident-runbook.md +205 -0
- package/ez-agents/templates/mode-workflow-templates.md +301 -0
- package/ez-agents/templates/phase-prompt.md +610 -610
- package/ez-agents/templates/planner-subagent-prompt.md +117 -117
- package/ez-agents/templates/project.md +184 -184
- package/ez-agents/templates/release-checklist.md +136 -0
- package/ez-agents/templates/research.md +552 -552
- package/ez-agents/templates/rollback-plan.md +201 -0
- package/ez-agents/templates/security-user-setup.md +244 -0
- package/ez-agents/templates/skill-validation-rules.md +476 -0
- package/ez-agents/templates/state.md +180 -176
- package/ez-agents/templates/summary-complex.md +59 -59
- package/ez-agents/tests/gates/gate-01-02.test.cjs +812 -0
- package/ez-agents/tests/gates/gate-03-04.test.cjs +762 -0
- package/ez-agents/tests/gates/gate-05-validator.test.cjs +145 -0
- package/ez-agents/tests/gates/gate-06-docs-validator.test.cjs +244 -0
- package/ez-agents/tests/gates/gate-07-release-validator.test.cjs +219 -0
- package/ez-agents/tests/guards/context-budget-guard.test.cjs +145 -0
- package/ez-agents/tests/guards/edge-case-guards.test.cjs +238 -0
- package/ez-agents/tests/guards/hallucination-guard.test.cjs +124 -0
- package/ez-agents/workflows/audit-milestone.md +1 -1
- package/ez-agents/workflows/autonomous.md +131 -30
- package/ez-agents/workflows/complete-milestone.md +1 -1
- package/ez-agents/workflows/discuss-phase.md +1 -1
- package/ez-agents/workflows/execute-phase.md +169 -3
- package/ez-agents/workflows/help.md +86 -133
- package/ez-agents/workflows/hotfix.md +291 -0
- package/ez-agents/workflows/new-milestone.md +340 -11
- package/ez-agents/workflows/new-project.md +294 -318
- package/ez-agents/workflows/plan-phase.md +22 -40
- package/ez-agents/workflows/progress.md +15 -25
- package/ez-agents/workflows/release.md +253 -0
- package/ez-agents/workflows/resume-session.md +215 -0
- package/ez-agents/workflows/run-phase.md +531 -0
- package/ez-agents/workflows/settings.md +2 -35
- package/hooks/dist/ez-check-update.js +81 -81
- package/hooks/dist/ez-context-monitor.js +148 -141
- package/hooks/dist/ez-statusline.js +115 -115
- package/package.json +78 -64
- package/scripts/fix-qwen-installation.js +144 -144
- package/agents/ez-integration-checker.md +0 -443
- package/agents/ez-nyquist-auditor.md +0 -176
- package/agents/ez-plan-checker.md +0 -706
- package/agents/ez-research-synthesizer.md +0 -247
- package/agents/ez-ui-auditor.md +0 -439
- package/agents/ez-ui-checker.md +0 -300
- package/agents/ez-ui-researcher.md +0 -353
- package/commands/ez/add-phase.md +0 -43
- package/commands/ez/add-todo.md +0 -47
- package/commands/ez/auth.md +0 -87
- package/commands/ez/autonomous.md +0 -41
- package/commands/ez/check-todos.md +0 -45
- package/commands/ez/cleanup.md +0 -18
- package/commands/ez/debug.md +0 -168
- package/commands/ez/health.md +0 -22
- package/commands/ez/insert-phase.md +0 -32
- package/commands/ez/join-discord.md +0 -18
- package/commands/ez/list-phase-assumptions.md +0 -46
- package/commands/ez/pause-work.md +0 -38
- package/commands/ez/plan-milestone-gaps.md +0 -34
- package/commands/ez/reapply-patches.md +0 -124
- package/commands/ez/remove-phase.md +0 -31
- package/commands/ez/research-phase.md +0 -190
- package/commands/ez/set-profile.md +0 -34
- package/commands/ez/stats.md +0 -18
- package/commands/ez/ui-phase.md +0 -34
- package/commands/ez/ui-review.md +0 -32
- package/commands/ez/validate-phase.md +0 -35
- package/ez-agents/templates/UI-SPEC.md +0 -100
- package/ez-agents/templates/VALIDATION.md +0 -76
- package/ez-agents/templates/context.md +0 -352
- package/ez-agents/templates/verification-report.md +0 -322
- package/ez-agents/workflows/research-phase.md +0 -74
- package/ez-agents/workflows/ui-phase.md +0 -290
- package/ez-agents/workflows/ui-review.md +0 -157
- package/ez-agents/workflows/validate-phase.md +0 -167
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Budget Enforcer — Enforces spending limits and auto-pauses over-budget operations
|
|
3
|
+
* Integrates with cost-tracker for budget ceiling enforcement
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
|
|
9
|
+
class BudgetEnforcer {
|
|
10
|
+
constructor(cwd) {
|
|
11
|
+
this.cwd = cwd || process.cwd();
|
|
12
|
+
this.configPath = path.join(this.cwd, '.planning', 'config.json');
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Check if budget is exceeded
|
|
17
|
+
* @param {number} currentCost - Current total cost
|
|
18
|
+
* @returns {Object} Budget status { ok, warning, exceeded, action }
|
|
19
|
+
*/
|
|
20
|
+
checkBudget(currentCost) {
|
|
21
|
+
const config = this.loadConfig();
|
|
22
|
+
const ceiling = config.cost_tracking?.budget?.ceiling || null;
|
|
23
|
+
const warningThreshold = config.cost_tracking?.warning_threshold || 80;
|
|
24
|
+
|
|
25
|
+
if (!ceiling) {
|
|
26
|
+
return { ok: true, warning: false, exceeded: false, action: 'none' };
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const percentage = (currentCost / ceiling) * 100;
|
|
30
|
+
|
|
31
|
+
if (percentage >= 100) {
|
|
32
|
+
return {
|
|
33
|
+
ok: false,
|
|
34
|
+
warning: false,
|
|
35
|
+
exceeded: true,
|
|
36
|
+
action: config.cost_tracking?.auto_pause ? 'pause' : 'alert',
|
|
37
|
+
percentage: Math.round(percentage)
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (percentage >= warningThreshold) {
|
|
42
|
+
return {
|
|
43
|
+
ok: true,
|
|
44
|
+
warning: true,
|
|
45
|
+
exceeded: false,
|
|
46
|
+
action: 'warn',
|
|
47
|
+
percentage: Math.round(percentage)
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return { ok: true, warning: false, exceeded: false, action: 'none', percentage: Math.round(percentage) };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Enforce budget (exit if exceeded and auto_pause enabled)
|
|
56
|
+
* @param {number} currentCost - Current total cost
|
|
57
|
+
*/
|
|
58
|
+
enforce(currentCost) {
|
|
59
|
+
const status = this.checkBudget(currentCost);
|
|
60
|
+
|
|
61
|
+
if (status.exceeded && status.action === 'pause') {
|
|
62
|
+
console.error(`Budget ceiling exceeded (${status.percentage}%) — operations paused`);
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (status.warning) {
|
|
67
|
+
console.warn(`Budget warning: ${status.percentage}% of ceiling used`);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return status;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Set budget ceiling
|
|
75
|
+
* @param {number} ceiling - Budget ceiling in USD
|
|
76
|
+
*/
|
|
77
|
+
setCeiling(ceiling) {
|
|
78
|
+
const config = this.loadConfig();
|
|
79
|
+
if (!config.cost_tracking) config.cost_tracking = {};
|
|
80
|
+
if (!config.cost_tracking.budget) config.cost_tracking.budget = {};
|
|
81
|
+
config.cost_tracking.budget.ceiling = ceiling;
|
|
82
|
+
this.saveConfig(config);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Load config
|
|
87
|
+
* @returns {Object} Config
|
|
88
|
+
*/
|
|
89
|
+
loadConfig() {
|
|
90
|
+
if (!fs.existsSync(this.configPath)) {
|
|
91
|
+
return { cost_tracking: { budget: {}, warning_threshold: 80 } };
|
|
92
|
+
}
|
|
93
|
+
return JSON.parse(fs.readFileSync(this.configPath, 'utf8'));
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Save config
|
|
98
|
+
* @param {Object} config - Config to save
|
|
99
|
+
*/
|
|
100
|
+
saveConfig(config) {
|
|
101
|
+
fs.writeFileSync(this.configPath, JSON.stringify(config, null, 2), 'utf8');
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Check budget status
|
|
107
|
+
* @param {number} currentCost - Current cost
|
|
108
|
+
* @param {string} cwd - Working directory
|
|
109
|
+
* @returns {Object} Budget status
|
|
110
|
+
*/
|
|
111
|
+
function checkBudget(currentCost, cwd) {
|
|
112
|
+
const enforcer = new BudgetEnforcer(cwd);
|
|
113
|
+
return enforcer.checkBudget(currentCost);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Enforce budget
|
|
118
|
+
* @param {number} currentCost - Current cost
|
|
119
|
+
* @param {string} cwd - Working directory
|
|
120
|
+
*/
|
|
121
|
+
function enforce(currentCost, cwd) {
|
|
122
|
+
const enforcer = new BudgetEnforcer(cwd);
|
|
123
|
+
return enforcer.enforce(currentCost);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
module.exports = { BudgetEnforcer, checkBudget, enforce };
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cost Reporter — Cost breakdown by phase/operation/provider with trend analysis
|
|
3
|
+
* Generates detailed cost reports from cost-tracker data
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
|
|
9
|
+
class CostReporter {
|
|
10
|
+
constructor(cwd) {
|
|
11
|
+
this.cwd = cwd || process.cwd();
|
|
12
|
+
this.metricsPath = path.join(this.cwd, '.planning', 'metrics.json');
|
|
13
|
+
this.reportsDir = path.join(this.cwd, '.planning', 'finops', 'reports');
|
|
14
|
+
this.ensureDir();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Generate cost breakdown report
|
|
19
|
+
* @param {Object} options - Report options
|
|
20
|
+
* @returns {Object} Cost report
|
|
21
|
+
*/
|
|
22
|
+
generateReport(options = {}) {
|
|
23
|
+
const { CostTracker } = require('../cost-tracker.cjs');
|
|
24
|
+
const tracker = new CostTracker(this.cwd);
|
|
25
|
+
const data = tracker.aggregate();
|
|
26
|
+
|
|
27
|
+
const report = {
|
|
28
|
+
timestamp: new Date().toISOString(),
|
|
29
|
+
total: data.total,
|
|
30
|
+
byPhase: data.by_phase || {},
|
|
31
|
+
byProvider: data.by_provider || {},
|
|
32
|
+
trend: this.calculateTrend(data),
|
|
33
|
+
recommendations: this.generateRecommendations(data)
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
return report;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Save report to file
|
|
41
|
+
* @param {Object} report - Report to save
|
|
42
|
+
* @param {string} filename - Optional filename
|
|
43
|
+
* @returns {string} Path to saved report
|
|
44
|
+
*/
|
|
45
|
+
saveReport(report, filename) {
|
|
46
|
+
const reportFilename = filename || `cost-${Date.now()}.json`;
|
|
47
|
+
const reportPath = path.join(this.reportsDir, reportFilename);
|
|
48
|
+
|
|
49
|
+
fs.writeFileSync(reportPath, JSON.stringify(report, null, 2), 'utf8');
|
|
50
|
+
return reportPath;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Calculate cost trend
|
|
55
|
+
* @param {Object} data - Aggregated cost data
|
|
56
|
+
* @returns {Array} Trend data
|
|
57
|
+
*/
|
|
58
|
+
calculateTrend(data) {
|
|
59
|
+
// Placeholder - would track historical trend
|
|
60
|
+
return [{
|
|
61
|
+
timestamp: new Date().toISOString(),
|
|
62
|
+
total: data.total.cost || 0
|
|
63
|
+
}];
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Generate cost optimization recommendations
|
|
68
|
+
* @param {Object} data - Cost data
|
|
69
|
+
* @returns {Array} Recommendations
|
|
70
|
+
*/
|
|
71
|
+
generateRecommendations(data) {
|
|
72
|
+
const recommendations = [];
|
|
73
|
+
|
|
74
|
+
// Check for high-cost phases
|
|
75
|
+
for (const [phase, costs] of Object.entries(data.by_phase || {})) {
|
|
76
|
+
if (costs.cost > 10) {
|
|
77
|
+
recommendations.push({
|
|
78
|
+
category: 'phase',
|
|
79
|
+
phase,
|
|
80
|
+
suggestion: `High cost phase ($${costs.cost}) — review operation efficiency`
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Check for expensive providers
|
|
86
|
+
for (const [provider, costs] of Object.entries(data.by_provider || {})) {
|
|
87
|
+
if (costs.cost > 5) {
|
|
88
|
+
recommendations.push({
|
|
89
|
+
category: 'provider',
|
|
90
|
+
provider,
|
|
91
|
+
suggestion: `Consider alternative models for ${provider}`
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return recommendations;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Ensure reports directory exists
|
|
101
|
+
*/
|
|
102
|
+
ensureDir() {
|
|
103
|
+
if (!fs.existsSync(this.reportsDir)) {
|
|
104
|
+
fs.mkdirSync(this.reportsDir, { recursive: true });
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Generate cost report
|
|
111
|
+
* @param {Object} options - Report options
|
|
112
|
+
* @param {string} cwd - Working directory
|
|
113
|
+
* @returns {Object} Cost report
|
|
114
|
+
*/
|
|
115
|
+
function generateReport(options = {}, cwd) {
|
|
116
|
+
const reporter = new CostReporter(cwd);
|
|
117
|
+
return reporter.generateReport(options);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Save cost report
|
|
122
|
+
* @param {Object} report - Report to save
|
|
123
|
+
* @param {string} filename - Filename
|
|
124
|
+
* @param {string} cwd - Working directory
|
|
125
|
+
* @returns {string} Path to saved report
|
|
126
|
+
*/
|
|
127
|
+
function saveReport(report, filename, cwd) {
|
|
128
|
+
const reporter = new CostReporter(cwd);
|
|
129
|
+
return reporter.saveReport(report, filename);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
module.exports = { CostReporter, generateReport, saveReport };
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FinOps Analyzer — Cloud resource cost analysis and rightsizing recommendations
|
|
3
|
+
* Analyzes resource usage and provides cost optimization recommendations
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
|
|
9
|
+
class FinopsAnalyzer {
|
|
10
|
+
constructor(cwd) {
|
|
11
|
+
this.cwd = cwd || process.cwd();
|
|
12
|
+
this.costsPath = path.join(this.cwd, '.planning', 'finops', 'costs.json');
|
|
13
|
+
this.ensureFile();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Analyze cloud resource costs
|
|
18
|
+
* @param {Object} resources - Resource usage data
|
|
19
|
+
* @returns {Object} Cost analysis with recommendations
|
|
20
|
+
*/
|
|
21
|
+
analyzeCosts(resources = {}) {
|
|
22
|
+
const analysis = {
|
|
23
|
+
timestamp: new Date().toISOString(),
|
|
24
|
+
totalCost: 0,
|
|
25
|
+
byResource: {},
|
|
26
|
+
byCategory: {},
|
|
27
|
+
recommendations: []
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
// Analyze each resource
|
|
31
|
+
for (const [name, resource] of Object.entries(resources)) {
|
|
32
|
+
const cost = resource.cost || 0;
|
|
33
|
+
const category = resource.category || 'other';
|
|
34
|
+
|
|
35
|
+
analysis.totalCost += cost;
|
|
36
|
+
analysis.byResource[name] = cost;
|
|
37
|
+
|
|
38
|
+
if (!analysis.byCategory[category]) {
|
|
39
|
+
analysis.byCategory[category] = 0;
|
|
40
|
+
}
|
|
41
|
+
analysis.byCategory[category] += cost;
|
|
42
|
+
|
|
43
|
+
// Generate rightsizing recommendations
|
|
44
|
+
if (resource.utilization < 30) {
|
|
45
|
+
analysis.recommendations.push({
|
|
46
|
+
resource: name,
|
|
47
|
+
type: 'rightsize',
|
|
48
|
+
reason: `Low utilization (${resource.utilization}%)`,
|
|
49
|
+
suggestion: 'Downsize instance or consolidate workloads',
|
|
50
|
+
potentialSavings: Math.round(cost * 0.4)
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return analysis;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Get cost trend over time
|
|
60
|
+
* @returns {Array} Cost trend data
|
|
61
|
+
*/
|
|
62
|
+
getTrend() {
|
|
63
|
+
if (!fs.existsSync(this.costsPath)) return [];
|
|
64
|
+
const costs = JSON.parse(fs.readFileSync(this.costsPath, 'utf8'));
|
|
65
|
+
return costs.trend || [];
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Save cost data
|
|
70
|
+
* @param {Object} costData - Cost data to save
|
|
71
|
+
*/
|
|
72
|
+
saveCostData(costData) {
|
|
73
|
+
const data = {
|
|
74
|
+
timestamp: new Date().toISOString(),
|
|
75
|
+
...costData
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
let existing = { trend: [] };
|
|
79
|
+
if (fs.existsSync(this.costsPath)) {
|
|
80
|
+
existing = JSON.parse(fs.readFileSync(this.costsPath, 'utf8'));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
existing.trend.push(data);
|
|
84
|
+
fs.writeFileSync(this.costsPath, JSON.stringify(existing, null, 2), 'utf8');
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Ensure costs file exists
|
|
89
|
+
*/
|
|
90
|
+
ensureFile() {
|
|
91
|
+
const dir = path.dirname(this.costsPath);
|
|
92
|
+
if (!fs.existsSync(dir)) {
|
|
93
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
94
|
+
}
|
|
95
|
+
if (!fs.existsSync(this.costsPath)) {
|
|
96
|
+
fs.writeFileSync(this.costsPath, '{"trend":[]}', 'utf8');
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Analyze cloud resource costs
|
|
103
|
+
* @param {Object} resources - Resource usage data
|
|
104
|
+
* @param {string} cwd - Working directory
|
|
105
|
+
* @returns {Object} Cost analysis
|
|
106
|
+
*/
|
|
107
|
+
function analyzeCosts(resources = {}, cwd) {
|
|
108
|
+
const analyzer = new FinopsAnalyzer(cwd);
|
|
109
|
+
return analyzer.analyzeCosts(resources);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
module.exports = { FinopsAnalyzer, analyzeCosts };
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spot Manager — Spot/preemptible instance management recommendations
|
|
3
|
+
* Analyzes workload patterns and recommends spot vs on-demand instances
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
|
|
9
|
+
class SpotManager {
|
|
10
|
+
constructor(cwd) {
|
|
11
|
+
this.cwd = cwd || process.cwd();
|
|
12
|
+
this.recommendationsPath = path.join(this.cwd, '.planning', 'finops', 'spot-recommendations.json');
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Analyze workload for spot instance suitability
|
|
17
|
+
* @param {Object} workload - Workload characteristics
|
|
18
|
+
* @returns {Object} Spot recommendations
|
|
19
|
+
*/
|
|
20
|
+
analyzeWorkload(workload = {}) {
|
|
21
|
+
const recommendations = {
|
|
22
|
+
timestamp: new Date().toISOString(),
|
|
23
|
+
workloads: [],
|
|
24
|
+
totalPotentialSavings: 0
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
for (const [name, characteristics] of Object.entries(workload)) {
|
|
28
|
+
const suitability = this.calculateSpotSuitability(characteristics);
|
|
29
|
+
const savings = this.calculateSavings(characteristics.cost, suitability);
|
|
30
|
+
|
|
31
|
+
recommendations.workloads.push({
|
|
32
|
+
name,
|
|
33
|
+
spotSuitable: suitability.score >= 70,
|
|
34
|
+
suitabilityScore: suitability.score,
|
|
35
|
+
reasons: suitability.reasons,
|
|
36
|
+
currentCost: characteristics.cost,
|
|
37
|
+
potentialSavings: savings,
|
|
38
|
+
recommendation: suitability.score >= 70 ? 'Use spot instances' : 'Use on-demand'
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
recommendations.totalPotentialSavings += savings;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return recommendations;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Calculate spot suitability score
|
|
49
|
+
* @param {Object} characteristics - Workload characteristics
|
|
50
|
+
* @returns {Object} Suitability analysis
|
|
51
|
+
*/
|
|
52
|
+
calculateSpotSuitability(characteristics) {
|
|
53
|
+
let score = 50; // Base score
|
|
54
|
+
const reasons = [];
|
|
55
|
+
|
|
56
|
+
// Fault tolerant workloads are good for spot
|
|
57
|
+
if (characteristics.faultTolerant) {
|
|
58
|
+
score += 30;
|
|
59
|
+
reasons.push('Fault tolerant workload');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Batch processing is good for spot
|
|
63
|
+
if (characteristics.batchProcessing) {
|
|
64
|
+
score += 20;
|
|
65
|
+
reasons.push('Batch processing workload');
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Stateful workloads are bad for spot
|
|
69
|
+
if (characteristics.stateful) {
|
|
70
|
+
score -= 20;
|
|
71
|
+
reasons.push('Stateful workload (checkpointing recommended)');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Time-sensitive workloads are bad for spot
|
|
75
|
+
if (characteristics.timeSensitive) {
|
|
76
|
+
score -= 30;
|
|
77
|
+
reasons.push('Time-sensitive workload');
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
score: Math.min(100, Math.max(0, score)),
|
|
82
|
+
reasons
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Calculate potential savings from spot
|
|
88
|
+
* @param {number} currentCost - Current on-demand cost
|
|
89
|
+
* @param {number} suitability - Suitability score
|
|
90
|
+
* @returns {number} Potential savings
|
|
91
|
+
*/
|
|
92
|
+
calculateSavings(currentCost, suitability) {
|
|
93
|
+
// Spot instances typically 60-90% cheaper
|
|
94
|
+
const savingsRate = 0.7;
|
|
95
|
+
return Math.round(currentCost * savingsRate * (suitability / 100));
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Save recommendations
|
|
100
|
+
* @param {Object} recommendations - Recommendations to save
|
|
101
|
+
*/
|
|
102
|
+
saveRecommendations(recommendations) {
|
|
103
|
+
fs.writeFileSync(this.recommendationsPath, JSON.stringify(recommendations, null, 2), 'utf8');
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Analyze workload for spot suitability
|
|
109
|
+
* @param {Object} workload - Workload characteristics
|
|
110
|
+
* @param {string} cwd - Working directory
|
|
111
|
+
* @returns {Object} Spot recommendations
|
|
112
|
+
*/
|
|
113
|
+
function analyzeWorkload(workload = {}, cwd) {
|
|
114
|
+
const manager = new SpotManager(cwd);
|
|
115
|
+
return manager.analyzeWorkload(workload);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
module.exports = { SpotManager, analyzeWorkload };
|