@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,284 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Trade-off Analyzer — Generate trade-off analysis for architecture decisions
|
|
5
|
+
*
|
|
6
|
+
* Provides structured trade-off analysis with:
|
|
7
|
+
* - Options comparison (pros/cons)
|
|
8
|
+
* - Reversibility assessment
|
|
9
|
+
* - Long-term implications
|
|
10
|
+
* - Decision templates
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* const { TradeOffAnalyzer } = require('./tradeoff-analyzer');
|
|
14
|
+
* const analyzer = new TradeOffAnalyzer();
|
|
15
|
+
* const analysis = analyzer.generateAnalysis(options, context);
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
const Logger = require('./logger.cjs');
|
|
19
|
+
const logger = new Logger();
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Trade-off analysis template
|
|
23
|
+
*/
|
|
24
|
+
const TRADEOFF_TEMPLATE = `## Trade-off Analysis
|
|
25
|
+
|
|
26
|
+
**Decision:** {decision}
|
|
27
|
+
|
|
28
|
+
**Context:**
|
|
29
|
+
- Project Phase: {project_phase}
|
|
30
|
+
- Team Size: {team_size}
|
|
31
|
+
- Deadline: {deadline}
|
|
32
|
+
- User Count: {user_count}
|
|
33
|
+
- Compliance: {compliance}
|
|
34
|
+
|
|
35
|
+
**Options Considered:**
|
|
36
|
+
|
|
37
|
+
{options_section}
|
|
38
|
+
|
|
39
|
+
**Decision:** {selected_option}
|
|
40
|
+
|
|
41
|
+
**Rationale:**
|
|
42
|
+
{rationale}
|
|
43
|
+
|
|
44
|
+
**Trade-offs Accepted:**
|
|
45
|
+
{tradeoffs_accepted}
|
|
46
|
+
|
|
47
|
+
**Reversibility:** {reversibility}
|
|
48
|
+
- {reversal_details}
|
|
49
|
+
|
|
50
|
+
**Review Date:** {review_date}
|
|
51
|
+
`;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Trade-off Analyzer class
|
|
55
|
+
*/
|
|
56
|
+
class TradeOffAnalyzer {
|
|
57
|
+
constructor(options = {}) {
|
|
58
|
+
this.logger = logger;
|
|
59
|
+
this.template = options.template || TRADEOFF_TEMPLATE;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Generate trade-off analysis
|
|
64
|
+
* @param {Array} options - Options to analyze
|
|
65
|
+
* @param {Object} context - Project context
|
|
66
|
+
* @returns {string} Markdown analysis
|
|
67
|
+
*/
|
|
68
|
+
generateAnalysis(options, context = {}) {
|
|
69
|
+
const ctx = {
|
|
70
|
+
decision: context.decision || 'Architecture Decision',
|
|
71
|
+
project_phase: context.project_phase || 'Not specified',
|
|
72
|
+
team_size: context.team_size || 'Not specified',
|
|
73
|
+
deadline: context.deadline || 'Not specified',
|
|
74
|
+
user_count: context.user_count || 'Not specified',
|
|
75
|
+
compliance: context.compliance || 'Not specified'
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const optionsSection = this._generateOptionsSection(options);
|
|
79
|
+
const selectedOption = this._selectOption(options, context);
|
|
80
|
+
const rationale = this._generateRationale(selectedOption, context);
|
|
81
|
+
const tradeoffsAccepted = this._generateTradeoffs(selectedOption, options);
|
|
82
|
+
const reversibility = this.assessReversibility(selectedOption, context);
|
|
83
|
+
const reviewDate = this._calculateReviewDate(reversibility.level);
|
|
84
|
+
|
|
85
|
+
return this.template
|
|
86
|
+
.replace('{decision}', ctx.decision)
|
|
87
|
+
.replace('{project_phase}', ctx.project_phase)
|
|
88
|
+
.replace('{team_size}', ctx.team_size)
|
|
89
|
+
.replace('{deadline}', ctx.deadline)
|
|
90
|
+
.replace('{user_count}', ctx.user_count)
|
|
91
|
+
.replace('{compliance}', ctx.compliance)
|
|
92
|
+
.replace('{options_section}', optionsSection)
|
|
93
|
+
.replace('{selected_option}', selectedOption.name)
|
|
94
|
+
.replace('{rationale}', rationale)
|
|
95
|
+
.replace('{tradeoffs_accepted}', tradeoffsAccepted)
|
|
96
|
+
.replace('{reversibility}', reversibility.level)
|
|
97
|
+
.replace('{reversal_details}', reversibility.details)
|
|
98
|
+
.replace('{review_date}', reviewDate);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Assess reversibility of a decision
|
|
103
|
+
* @param {Object} option - Selected option
|
|
104
|
+
* @param {Object} context - Project context
|
|
105
|
+
* @returns {Object} { level, details, estimated_effort }
|
|
106
|
+
*/
|
|
107
|
+
assessReversibility(option, context = {}) {
|
|
108
|
+
const reversibilityFactors = {
|
|
109
|
+
'monolith': { level: 'Easy', effort: 'Low - refactor to modules' },
|
|
110
|
+
'modular-monolith': { level: 'Medium', effort: 'Medium - extract modules to services' },
|
|
111
|
+
'microservices': { level: 'Hard', effort: 'High - merge services, consolidate databases' },
|
|
112
|
+
'event-driven': { level: 'Medium', effort: 'Medium - revert to synchronous calls' },
|
|
113
|
+
'queue-based': { level: 'Easy', effort: 'Low - revert to synchronous processing' },
|
|
114
|
+
'caching': { level: 'Easy', effort: 'Low - disable cache layers' },
|
|
115
|
+
'api-gateway': { level: 'Medium', effort: 'Medium - route directly to services' }
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
const patternKey = option.name?.toLowerCase().replace(/\s+/g, '-');
|
|
119
|
+
const factor = reversibilityFactors[patternKey] || {
|
|
120
|
+
level: 'Medium',
|
|
121
|
+
effort: 'Unknown - depends on implementation'
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
// Adjust based on implementation depth
|
|
125
|
+
if (context.implementation_stage === 'production') {
|
|
126
|
+
factor.level = factor.level === 'Easy' ? 'Medium' : 'Hard';
|
|
127
|
+
factor.effort = `${factor.effort} (production data migration needed)`;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return {
|
|
131
|
+
level: factor.level,
|
|
132
|
+
details: factor.effort,
|
|
133
|
+
estimated_effort: this._estimateEffort(factor.level)
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Generate options section
|
|
139
|
+
* @param {Array} options - Options to format
|
|
140
|
+
* @returns {string} Markdown section
|
|
141
|
+
* @private
|
|
142
|
+
*/
|
|
143
|
+
_generateOptionsSection(options) {
|
|
144
|
+
return options.map((opt, idx) => {
|
|
145
|
+
const pros = opt.pros?.map(p => ` - ${p}`).join('\n') || ' - Not specified';
|
|
146
|
+
const cons = opt.cons?.map(c => ` - ${c}`).join('\n') || ' - Not specified';
|
|
147
|
+
const implications = opt.long_term_implications?.map(i => ` - ${i}`).join('\n') || ' - Not specified';
|
|
148
|
+
|
|
149
|
+
return `### Option ${idx + 1}: ${opt.name}
|
|
150
|
+
|
|
151
|
+
**Pros:**
|
|
152
|
+
${pros}
|
|
153
|
+
|
|
154
|
+
**Cons:**
|
|
155
|
+
${cons}
|
|
156
|
+
|
|
157
|
+
**Long-term Implications:**
|
|
158
|
+
${implications}`;
|
|
159
|
+
}).join('\n\n');
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Select best option based on context
|
|
164
|
+
* @param {Array} options - Options to choose from
|
|
165
|
+
* @param {Object} context - Project context
|
|
166
|
+
* @returns {Object} Selected option
|
|
167
|
+
* @private
|
|
168
|
+
*/
|
|
169
|
+
_selectOption(options, context) {
|
|
170
|
+
if (options.length === 0) {
|
|
171
|
+
return { name: 'No options provided', pros: [], cons: [] };
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
if (options.length === 1) {
|
|
175
|
+
return options[0];
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Simple scoring based on context
|
|
179
|
+
const scores = options.map(opt => {
|
|
180
|
+
let score = 0;
|
|
181
|
+
|
|
182
|
+
// More pros = higher score
|
|
183
|
+
score += (opt.pros?.length || 0) * 2;
|
|
184
|
+
|
|
185
|
+
// Fewer cons = higher score
|
|
186
|
+
score -= (opt.cons?.length || 0);
|
|
187
|
+
|
|
188
|
+
// Context alignment
|
|
189
|
+
if (opt.context_fit?.includes(context.project_phase)) {
|
|
190
|
+
score += 10;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
return { option: opt, score };
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
scores.sort((a, b) => b.score - a.score);
|
|
197
|
+
return scores[0].option;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Generate rationale for selected option
|
|
202
|
+
* @param {Object} option - Selected option
|
|
203
|
+
* @param {Object} context - Project context
|
|
204
|
+
* @returns {string} Rationale text
|
|
205
|
+
* @private
|
|
206
|
+
*/
|
|
207
|
+
_generateRationale(option, context) {
|
|
208
|
+
const reasons = [];
|
|
209
|
+
|
|
210
|
+
if (option.pros?.length) {
|
|
211
|
+
reasons.push(`Key advantages: ${option.pros.slice(0, 3).join(', ')}`);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (option.context_fit?.includes(context.project_phase)) {
|
|
215
|
+
reasons.push(`Well-suited for ${context.project_phase} phase`);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
if (option.alignment?.length) {
|
|
219
|
+
reasons.push(`Aligns with: ${option.alignment.join(', ')}`);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
return reasons.join('. ') || 'Selected based on project requirements and constraints.';
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Generate trade-offs accepted
|
|
227
|
+
* @param {Object} selected - Selected option
|
|
228
|
+
* @param {Array} options - All options
|
|
229
|
+
* @returns {string} Trade-offs text
|
|
230
|
+
* @private
|
|
231
|
+
*/
|
|
232
|
+
_generateTradeoffs(selected, options) {
|
|
233
|
+
const rejected = options.filter(o => o !== selected);
|
|
234
|
+
|
|
235
|
+
if (rejected.length === 0) {
|
|
236
|
+
return 'No alternative options were considered.';
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
return rejected.map(opt => {
|
|
240
|
+
const lostBenefits = opt.pros?.join(', ') || 'None';
|
|
241
|
+
return `- By not choosing ${opt.name}, losing: ${lostBenefits}`;
|
|
242
|
+
}).join('\n');
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Calculate review date based on reversibility
|
|
247
|
+
* @param {string} level - Reversibility level
|
|
248
|
+
* @returns {string} Review date
|
|
249
|
+
* @private
|
|
250
|
+
*/
|
|
251
|
+
_calculateReviewDate(level) {
|
|
252
|
+
const months = {
|
|
253
|
+
'Easy': 6,
|
|
254
|
+
'Medium': 3,
|
|
255
|
+
'Hard': 1
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
const reviewMonths = months[level] || 3;
|
|
259
|
+
const reviewDate = new Date();
|
|
260
|
+
reviewDate.setMonth(reviewDate.getMonth() + reviewMonths);
|
|
261
|
+
|
|
262
|
+
return reviewDate.toISOString().split('T')[0];
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Estimate effort to reverse decision
|
|
267
|
+
* @param {string} level - Reversibility level
|
|
268
|
+
* @returns {string} Effort estimate
|
|
269
|
+
* @private
|
|
270
|
+
*/
|
|
271
|
+
_estimateEffort(level) {
|
|
272
|
+
const efforts = {
|
|
273
|
+
'Easy': '1-2 weeks',
|
|
274
|
+
'Medium': '2-6 weeks',
|
|
275
|
+
'Hard': '6+ weeks'
|
|
276
|
+
};
|
|
277
|
+
return efforts[level] || 'Unknown';
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
module.exports = {
|
|
282
|
+
TradeOffAnalyzer,
|
|
283
|
+
TRADEOFF_TEMPLATE
|
|
284
|
+
};
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* URL Fetch Service
|
|
5
|
+
*
|
|
6
|
+
* Provides secure URL fetching with HTTPS validation and user confirmation.
|
|
7
|
+
* Only HTTPS URLs are allowed. HTTP, file, data, javascript, and vbscript protocols are blocked.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const { URL } = require('url');
|
|
11
|
+
const { URLFetchError } = require('./context-errors.cjs');
|
|
12
|
+
|
|
13
|
+
const DEFAULT_TIMEOUT = 30000; // 30 seconds
|
|
14
|
+
const BLOCKED_PROTOCOLS = ['http:', 'file:', 'data:', 'javascript:', 'vbscript:'];
|
|
15
|
+
|
|
16
|
+
class URLValidator {
|
|
17
|
+
/**
|
|
18
|
+
* Validate a URL string
|
|
19
|
+
* @param {string} urlString - The URL to validate
|
|
20
|
+
* @returns {{valid: boolean, error?: string}} - Validation result
|
|
21
|
+
*/
|
|
22
|
+
static validate(urlString) {
|
|
23
|
+
if (!urlString || typeof urlString !== 'string') {
|
|
24
|
+
return { valid: false, error: 'URL is required' };
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
const url = new URL(urlString);
|
|
29
|
+
|
|
30
|
+
// Check protocol
|
|
31
|
+
if (url.protocol !== 'https:') {
|
|
32
|
+
if (BLOCKED_PROTOCOLS.includes(url.protocol)) {
|
|
33
|
+
return {
|
|
34
|
+
valid: false,
|
|
35
|
+
error: `Protocol '${url.protocol}' is not allowed. Only HTTPS is permitted.`
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
return {
|
|
39
|
+
valid: false,
|
|
40
|
+
error: `Invalid protocol '${url.protocol}'. Only HTTPS is allowed.`
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Check hostname exists
|
|
45
|
+
if (!url.hostname || url.hostname.trim() === '') {
|
|
46
|
+
return { valid: false, error: 'Invalid URL: missing hostname' };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Reject localhost URLs
|
|
50
|
+
if (url.hostname === 'localhost' ||
|
|
51
|
+
url.hostname === '127.0.0.1' ||
|
|
52
|
+
url.hostname === '::1' ||
|
|
53
|
+
url.hostname.endsWith('.localhost')) {
|
|
54
|
+
return {
|
|
55
|
+
valid: false,
|
|
56
|
+
error: 'Localhost URLs are not allowed. Use a publicly accessible HTTPS URL.'
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return { valid: true };
|
|
61
|
+
} catch (err) {
|
|
62
|
+
return {
|
|
63
|
+
valid: false,
|
|
64
|
+
error: `Invalid URL format: ${err.message}`
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
class URLFetchService {
|
|
71
|
+
/**
|
|
72
|
+
* Create a new URLFetchService instance
|
|
73
|
+
* @param {number} timeout - Request timeout in milliseconds (default: 30000)
|
|
74
|
+
*/
|
|
75
|
+
constructor(timeout = DEFAULT_TIMEOUT) {
|
|
76
|
+
this.timeout = timeout;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Validate a URL
|
|
81
|
+
* @param {string} urlString - The URL to validate
|
|
82
|
+
* @returns {{valid: boolean, error?: string}} - Validation result
|
|
83
|
+
*/
|
|
84
|
+
validateUrl(urlString) {
|
|
85
|
+
return URLValidator.validate(urlString);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Fetch content from a URL
|
|
90
|
+
* @param {string} url - The URL to fetch
|
|
91
|
+
* @returns {{content: string, contentType: string}} - Fetched content
|
|
92
|
+
* @throws {URLFetchError} - On fetch errors
|
|
93
|
+
*/
|
|
94
|
+
async fetchUrl(url) {
|
|
95
|
+
// Validate URL first
|
|
96
|
+
const validation = this.validateUrl(url);
|
|
97
|
+
if (!validation.valid) {
|
|
98
|
+
throw new URLFetchError(url, validation.error);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
try {
|
|
102
|
+
// Create abort controller for timeout
|
|
103
|
+
const controller = new AbortController();
|
|
104
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
105
|
+
|
|
106
|
+
const response = await fetch(url, {
|
|
107
|
+
headers: {
|
|
108
|
+
'User-Agent': 'ez-agents/1.0'
|
|
109
|
+
},
|
|
110
|
+
signal: controller.signal,
|
|
111
|
+
redirect: 'follow'
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
clearTimeout(timeoutId);
|
|
115
|
+
|
|
116
|
+
// Check for HTTP errors
|
|
117
|
+
if (!response.ok) {
|
|
118
|
+
throw new URLFetchError(
|
|
119
|
+
url,
|
|
120
|
+
`HTTP ${response.status}: ${response.statusText}`
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Get content type
|
|
125
|
+
const contentType = response.headers.get('content-type') || 'text/plain';
|
|
126
|
+
|
|
127
|
+
// Get content
|
|
128
|
+
const content = await response.text();
|
|
129
|
+
|
|
130
|
+
return {
|
|
131
|
+
content,
|
|
132
|
+
contentType
|
|
133
|
+
};
|
|
134
|
+
} catch (err) {
|
|
135
|
+
if (err.name === 'AbortError') {
|
|
136
|
+
throw new URLFetchError(url, `Request timeout after ${this.timeout}ms`);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (err.name === 'URLFetchError') {
|
|
140
|
+
throw err;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
throw new URLFetchError(url, `Network error: ${err.message}`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Prompt user for confirmation before fetching a URL
|
|
149
|
+
* @param {string} url - The URL to fetch
|
|
150
|
+
* @returns {Promise<boolean>} - True if user confirmed
|
|
151
|
+
*/
|
|
152
|
+
static async confirmUrlFetch(url) {
|
|
153
|
+
const readline = require('readline');
|
|
154
|
+
|
|
155
|
+
return new Promise((resolve) => {
|
|
156
|
+
const rl = readline.createInterface({
|
|
157
|
+
input: process.stdin,
|
|
158
|
+
output: process.stdout
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
rl.question(`Fetch ${url}? (y/n): `, (answer) => {
|
|
162
|
+
rl.close();
|
|
163
|
+
resolve(answer.toLowerCase() === 'y');
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
module.exports = URLFetchService;
|
|
170
|
+
module.exports.URLValidator = URLValidator;
|