@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,289 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Archetype Detector — Project type classification from codebase patterns
|
|
3
|
+
*
|
|
4
|
+
* Provides:
|
|
5
|
+
* - detect(structure, stack, flows): Pattern-based archetype detection
|
|
6
|
+
* - calculateConfidence(archetype, evidence): Confidence scoring
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const fs = require('fs');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
|
|
12
|
+
class ArchetypeDetector {
|
|
13
|
+
constructor(rootPath) {
|
|
14
|
+
this.rootPath = rootPath;
|
|
15
|
+
|
|
16
|
+
// Archetype patterns for detection
|
|
17
|
+
this.archetypePatterns = {
|
|
18
|
+
dashboard: {
|
|
19
|
+
patterns: ['Chart', 'Metric', 'Dashboard', 'Admin', 'Analytics', 'stats', 'metrics', 'analytics', 'graph', 'widget', 'kpi', 'report'],
|
|
20
|
+
routes: ['/dashboard', '/admin', '/analytics', '/reports', '/metrics'],
|
|
21
|
+
dependencies: ['recharts', 'chart.js', 'd3', 'plotly', 'highcharts', 'apexcharts']
|
|
22
|
+
},
|
|
23
|
+
POS: {
|
|
24
|
+
patterns: ['Product', 'Order', 'Payment', 'Cart', 'Checkout', 'Inventory', 'Store', 'Register', 'Terminal', 'Receipt', 'Cashier'],
|
|
25
|
+
routes: ['/pos', '/checkout', '/register', '/inventory', '/products'],
|
|
26
|
+
dependencies: ['stripe-terminal', 'square', '@stripe/stripe-js']
|
|
27
|
+
},
|
|
28
|
+
SaaS: {
|
|
29
|
+
patterns: ['Subscription', 'Tenant', 'Plan', 'Billing', 'User', 'Account', 'Recurring', 'Invoice', 'Pricing'],
|
|
30
|
+
routes: ['/subscription', '/billing', '/pricing', '/plans', '/account', '/settings'],
|
|
31
|
+
dependencies: ['stripe', '@stripe/stripe-js', 'paddle', 'lemonsqueezy']
|
|
32
|
+
},
|
|
33
|
+
ecommerce: {
|
|
34
|
+
patterns: ['Cart', 'Checkout', 'Product', 'Order', 'Shipping', 'Payment', 'Catalog', 'Wishlist', 'Review'],
|
|
35
|
+
routes: ['/products', '/cart', '/checkout', '/orders', '/wishlist', '/reviews'],
|
|
36
|
+
dependencies: ['@stripe/stripe-js', 'stripe', 'paypal', 'snipcart']
|
|
37
|
+
},
|
|
38
|
+
LMS: {
|
|
39
|
+
patterns: ['Course', 'Lesson', 'Student', 'Teacher', 'Quiz', 'Enrollment', 'Curriculum', 'Assignment', 'Grade'],
|
|
40
|
+
routes: ['/courses', '/lessons', '/students', '/teachers', '/quiz', '/assignments'],
|
|
41
|
+
dependencies: ['video.js', 'hls.js', 'plyr']
|
|
42
|
+
},
|
|
43
|
+
booking: {
|
|
44
|
+
patterns: ['Appointment', 'Booking', 'Availability', 'Calendar', 'Reservation', 'Schedule', 'Timeslot'],
|
|
45
|
+
routes: ['/booking', '/appointments', '/calendar', '/schedule', '/availability'],
|
|
46
|
+
dependencies: ['react-big-calendar', 'fullcalendar', 'react-calendar']
|
|
47
|
+
},
|
|
48
|
+
fintech: {
|
|
49
|
+
patterns: ['Transaction', 'Account', 'Payment', 'Balance', 'Compliance', 'KYC', 'AML', 'Ledger', 'Wallet', 'Transfer'],
|
|
50
|
+
routes: ['/accounts', '/transactions', '/transfer', '/wallet', '/ledger', '/compliance'],
|
|
51
|
+
dependencies: ['stripe', 'plaid', 'dwolla', 'unit']
|
|
52
|
+
},
|
|
53
|
+
internalTools: {
|
|
54
|
+
patterns: ['Admin', 'CRUD', 'Form', 'Table', 'Dashboard', 'Report', 'Config', 'Settings', 'Management'],
|
|
55
|
+
routes: ['/admin', '/management', '/config', '/settings', '/users', '/roles'],
|
|
56
|
+
dependencies: ['@tanstack/react-table', 'ag-grid', 'handsontable']
|
|
57
|
+
},
|
|
58
|
+
cms: {
|
|
59
|
+
patterns: ['Article', 'Page', 'Post', 'Media', 'Content', 'Block', 'Editor', 'Publish'],
|
|
60
|
+
routes: ['/articles', '/pages', '/posts', '/media', '/content'],
|
|
61
|
+
dependencies: ['@tiptap', 'slate', 'draft-js', 'quill', 'ckeditor']
|
|
62
|
+
},
|
|
63
|
+
social: {
|
|
64
|
+
patterns: ['Post', 'Comment', 'Feed', 'Follow', 'Like', 'Share', 'Profile', 'Notification', 'Message'],
|
|
65
|
+
routes: ['/feed', '/posts', '/profile', '/notifications', '/messages', '/followers'],
|
|
66
|
+
dependencies: ['socket.io', 'pusher', 'stream-chat']
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Detect project archetype from structure, stack, and flows
|
|
73
|
+
* @param {object} structure - Structure from CodebaseAnalyzer
|
|
74
|
+
* @param {object} stack - Stack from StackDetector
|
|
75
|
+
* @param {object} flows - Flows from BusinessFlowMapper
|
|
76
|
+
* @returns {object} Archetype detection result with name, confidence, evidence
|
|
77
|
+
*/
|
|
78
|
+
detect(structure = {}, stack = {}, flows = {}) {
|
|
79
|
+
const scores = {};
|
|
80
|
+
const evidence = {};
|
|
81
|
+
|
|
82
|
+
// Initialize scores for each archetype
|
|
83
|
+
for (const archetype of Object.keys(this.archetypePatterns)) {
|
|
84
|
+
scores[archetype] = 0;
|
|
85
|
+
evidence[archetype] = [];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Score based on file names
|
|
89
|
+
const files = structure.files || [];
|
|
90
|
+
for (const file of files) {
|
|
91
|
+
const fileName = path.basename(file);
|
|
92
|
+
this._scoreByFileName(fileName, scores, evidence);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Score based on directory names
|
|
96
|
+
const directories = structure.directories || [];
|
|
97
|
+
for (const dir of directories) {
|
|
98
|
+
const dirName = path.basename(dir.path);
|
|
99
|
+
this._scoreByDirectoryName(dirName, scores, evidence);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Score based on routes
|
|
103
|
+
const routes = flows.routes || [];
|
|
104
|
+
for (const route of routes) {
|
|
105
|
+
this._scoreByRoute(route.path, scores, evidence);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Score based on dependencies
|
|
109
|
+
const frameworks = stack.frameworks || [];
|
|
110
|
+
const infrastructure = stack.infrastructure || [];
|
|
111
|
+
const allDeps = [...frameworks, ...infrastructure];
|
|
112
|
+
this._scoreByDependencies(allDeps, scores, evidence);
|
|
113
|
+
|
|
114
|
+
// Find the highest scoring archetype
|
|
115
|
+
let bestArchetype = 'internalTools'; // Default
|
|
116
|
+
let bestScore = 0;
|
|
117
|
+
|
|
118
|
+
for (const [archetype, score] of Object.entries(scores)) {
|
|
119
|
+
if (score > bestScore) {
|
|
120
|
+
bestScore = score;
|
|
121
|
+
bestArchetype = archetype;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const confidence = this.calculateConfidence(bestArchetype, evidence[bestArchetype]);
|
|
126
|
+
|
|
127
|
+
return {
|
|
128
|
+
archetype: bestArchetype,
|
|
129
|
+
confidence: confidence.score,
|
|
130
|
+
confidenceLevel: confidence.level,
|
|
131
|
+
scores,
|
|
132
|
+
evidence: evidence[bestArchetype],
|
|
133
|
+
allEvidence: evidence
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Calculate confidence score for an archetype
|
|
139
|
+
* @param {string} archetype - Archetype name
|
|
140
|
+
* @param {Array} evidence - Array of evidence items
|
|
141
|
+
* @returns {object} Confidence with score (0-100) and level (High/Medium/Low)
|
|
142
|
+
*/
|
|
143
|
+
calculateConfidence(archetype, evidence = []) {
|
|
144
|
+
// Base score: evidence.length * 10
|
|
145
|
+
let score = evidence.length * 10;
|
|
146
|
+
|
|
147
|
+
// Bonus for file matches: +20 per file
|
|
148
|
+
const fileMatches = evidence.filter(e => e.type === 'file').length;
|
|
149
|
+
score += fileMatches * 20;
|
|
150
|
+
|
|
151
|
+
// Bonus for dependency matches: +15 per dependency
|
|
152
|
+
const depMatches = evidence.filter(e => e.type === 'dependency').length;
|
|
153
|
+
score += depMatches * 15;
|
|
154
|
+
|
|
155
|
+
// Bonus for route matches: +10 per route
|
|
156
|
+
const routeMatches = evidence.filter(e => e.type === 'route').length;
|
|
157
|
+
score += routeMatches * 10;
|
|
158
|
+
|
|
159
|
+
// Cap at 100
|
|
160
|
+
score = Math.min(score, 100);
|
|
161
|
+
|
|
162
|
+
// Determine level
|
|
163
|
+
let level;
|
|
164
|
+
if (score >= 80) {
|
|
165
|
+
level = 'High';
|
|
166
|
+
} else if (score >= 60) {
|
|
167
|
+
level = 'Medium';
|
|
168
|
+
} else {
|
|
169
|
+
level = 'Low';
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return { score, level };
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Score archetype by file name
|
|
177
|
+
* @private
|
|
178
|
+
*/
|
|
179
|
+
_scoreByFileName(fileName, scores, evidence) {
|
|
180
|
+
const nameWithoutExt = fileName.replace(/\.[^.]+$/, '');
|
|
181
|
+
|
|
182
|
+
for (const [archetype, config] of Object.entries(this.archetypePatterns)) {
|
|
183
|
+
for (const pattern of config.patterns) {
|
|
184
|
+
if (nameWithoutExt.toLowerCase().includes(pattern.toLowerCase())) {
|
|
185
|
+
scores[archetype] += 1;
|
|
186
|
+
evidence[archetype].push({
|
|
187
|
+
type: 'file',
|
|
188
|
+
value: fileName,
|
|
189
|
+
pattern
|
|
190
|
+
});
|
|
191
|
+
break; // Don't double-count same file
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Score archetype by directory name
|
|
199
|
+
* @private
|
|
200
|
+
*/
|
|
201
|
+
_scoreByDirectoryName(dirName, scores, evidence) {
|
|
202
|
+
for (const [archetype, config] of Object.entries(this.archetypePatterns)) {
|
|
203
|
+
for (const pattern of config.patterns) {
|
|
204
|
+
if (dirName.toLowerCase().includes(pattern.toLowerCase())) {
|
|
205
|
+
scores[archetype] += 2; // Directories are stronger signals
|
|
206
|
+
evidence[archetype].push({
|
|
207
|
+
type: 'directory',
|
|
208
|
+
value: dirName,
|
|
209
|
+
pattern
|
|
210
|
+
});
|
|
211
|
+
break;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Score archetype by route
|
|
219
|
+
* @private
|
|
220
|
+
*/
|
|
221
|
+
_scoreByRoute(routePath, scores, evidence) {
|
|
222
|
+
for (const [archetype, config] of Object.entries(this.archetypePatterns)) {
|
|
223
|
+
for (const routePattern of config.routes) {
|
|
224
|
+
if (routePath.toLowerCase().includes(routePattern.toLowerCase())) {
|
|
225
|
+
scores[archetype] += 2;
|
|
226
|
+
evidence[archetype].push({
|
|
227
|
+
type: 'route',
|
|
228
|
+
value: routePath,
|
|
229
|
+
pattern: routePattern
|
|
230
|
+
});
|
|
231
|
+
break;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Score archetype by dependencies
|
|
239
|
+
* @private
|
|
240
|
+
*/
|
|
241
|
+
_scoreByDependencies(dependencies, scores, evidence) {
|
|
242
|
+
for (const [archetype, config] of Object.entries(this.archetypePatterns)) {
|
|
243
|
+
for (const depPattern of config.dependencies) {
|
|
244
|
+
for (const dep of dependencies) {
|
|
245
|
+
if (dep.toLowerCase().includes(depPattern.toLowerCase())) {
|
|
246
|
+
scores[archetype] += 3; // Dependencies are strong signals
|
|
247
|
+
evidence[archetype].push({
|
|
248
|
+
type: 'dependency',
|
|
249
|
+
value: dep,
|
|
250
|
+
pattern: depPattern
|
|
251
|
+
});
|
|
252
|
+
break;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Get all supported archetypes
|
|
261
|
+
* @returns {Array} Array of archetype names
|
|
262
|
+
*/
|
|
263
|
+
getSupportedArchetypes() {
|
|
264
|
+
return Object.keys(this.archetypePatterns);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Get archetype description
|
|
269
|
+
* @param {string} archetype - Archetype name
|
|
270
|
+
* @returns {string} Description
|
|
271
|
+
*/
|
|
272
|
+
getArchetypeDescription(archetype) {
|
|
273
|
+
const descriptions = {
|
|
274
|
+
dashboard: 'Analytics dashboard with charts, metrics, and data visualization',
|
|
275
|
+
POS: 'Point of Sale system for retail transactions and inventory management',
|
|
276
|
+
SaaS: 'Software as a Service with subscription billing and multi-tenant architecture',
|
|
277
|
+
ecommerce: 'E-commerce platform with product catalog, cart, and checkout',
|
|
278
|
+
LMS: 'Learning Management System for courses, lessons, and student tracking',
|
|
279
|
+
booking: 'Booking and appointment scheduling system',
|
|
280
|
+
fintech: 'Financial technology application for transactions and account management',
|
|
281
|
+
internalTools: 'Internal business tools and admin panels',
|
|
282
|
+
cms: 'Content Management System for articles, pages, and media',
|
|
283
|
+
social: 'Social platform with feeds, posts, and user interactions'
|
|
284
|
+
};
|
|
285
|
+
return descriptions[archetype] || 'Unknown project type';
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
module.exports = { ArchetypeDetector };
|
|
@@ -1,167 +1,166 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* EZ Audit Exec — Command execution with full audit logging
|
|
5
|
-
*
|
|
6
|
-
* Logs all command executions to audit file for security review:
|
|
7
|
-
* - Timestamp, command, arguments, context
|
|
8
|
-
* - Duration and result status
|
|
9
|
-
* - Error details if failed
|
|
10
|
-
*
|
|
11
|
-
* Usage:
|
|
12
|
-
* const { auditExec } = require('./audit-exec.cjs');
|
|
13
|
-
* const result = await auditExec('git', ['status'], { context: 'my-module' });
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
const { execFile } = require('child_process');
|
|
17
|
-
const { promisify } = require('util');
|
|
18
|
-
const { appendFileSync, existsSync, mkdirSync } = require('fs');
|
|
19
|
-
const { join } = require('path');
|
|
20
|
-
const Logger = require('./logger.cjs');
|
|
21
|
-
const logger = new Logger();
|
|
22
|
-
|
|
23
|
-
const execFileAsync = promisify(execFile);
|
|
24
|
-
|
|
25
|
-
// Audit log file path - lazy init
|
|
26
|
-
let _AUDIT_DIR;
|
|
27
|
-
let _AUDIT_FILE;
|
|
28
|
-
|
|
29
|
-
function getAuditDir() {
|
|
30
|
-
if (!_AUDIT_DIR) {
|
|
31
|
-
_AUDIT_DIR = join('.planning', 'logs');
|
|
32
|
-
if (!existsSync(_AUDIT_DIR)) {
|
|
33
|
-
mkdirSync(_AUDIT_DIR, { recursive: true });
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
return _AUDIT_DIR;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function getAuditFile() {
|
|
40
|
-
if (!_AUDIT_FILE) {
|
|
41
|
-
_AUDIT_FILE = join(getAuditDir(), `audit-${new Date().toISOString().split('T')[0]}.jsonl`);
|
|
42
|
-
}
|
|
43
|
-
return _AUDIT_FILE;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Write audit log entry
|
|
48
|
-
* @param {Object} entry - Audit entry
|
|
49
|
-
*/
|
|
50
|
-
function writeAudit(entry) {
|
|
51
|
-
try {
|
|
52
|
-
const line = JSON.stringify(entry) + '\n';
|
|
53
|
-
appendFileSync(getAuditFile(), line, 'utf-8');
|
|
54
|
-
} catch (err) {
|
|
55
|
-
// Silently ignore audit write failures - logging is best-effort
|
|
56
|
-
// This can happen in temp test directories or when .planning doesn't exist
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Execute command with full audit logging
|
|
62
|
-
* @param {string} cmd - Command to execute
|
|
63
|
-
* @param {string[]} args - Command arguments
|
|
64
|
-
* @param {Object} options - Execution options
|
|
65
|
-
* @param {string} options.context - Calling context (which module/function)
|
|
66
|
-
* @param {string} options.user - User identifier
|
|
67
|
-
* @returns {Promise<string>} - Command stdout
|
|
68
|
-
*/
|
|
69
|
-
async function auditExec(cmd, args = [], options = {}) {
|
|
70
|
-
const { context = 'unknown', user = 'system', timeout = 30000 } = options;
|
|
71
|
-
|
|
72
|
-
const entry = {
|
|
73
|
-
timestamp: new Date().toISOString(),
|
|
74
|
-
cmd,
|
|
75
|
-
args,
|
|
76
|
-
context,
|
|
77
|
-
user,
|
|
78
|
-
status: 'started'
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
// Log start
|
|
82
|
-
writeAudit(entry);
|
|
83
|
-
logger.info('Audit: command started', { cmd, args: args.join(' '), context });
|
|
84
|
-
|
|
85
|
-
const startTime = Date.now();
|
|
86
|
-
|
|
87
|
-
try {
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
*
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
*
|
|
137
|
-
* @
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
*
|
|
153
|
-
* @param {string}
|
|
154
|
-
* @
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
};
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* EZ Audit Exec — Command execution with full audit logging
|
|
5
|
+
*
|
|
6
|
+
* Logs all command executions to audit file for security review:
|
|
7
|
+
* - Timestamp, command, arguments, context
|
|
8
|
+
* - Duration and result status
|
|
9
|
+
* - Error details if failed
|
|
10
|
+
*
|
|
11
|
+
* Usage:
|
|
12
|
+
* const { auditExec } = require('./audit-exec.cjs');
|
|
13
|
+
* const result = await auditExec('git', ['status'], { context: 'my-module' });
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
const { execFile } = require('child_process');
|
|
17
|
+
const { promisify } = require('util');
|
|
18
|
+
const { appendFileSync, existsSync, mkdirSync } = require('fs');
|
|
19
|
+
const { join } = require('path');
|
|
20
|
+
const Logger = require('./logger.cjs');
|
|
21
|
+
const logger = new Logger();
|
|
22
|
+
|
|
23
|
+
const execFileAsync = promisify(execFile);
|
|
24
|
+
|
|
25
|
+
// Audit log file path - lazy init
|
|
26
|
+
let _AUDIT_DIR;
|
|
27
|
+
let _AUDIT_FILE;
|
|
28
|
+
|
|
29
|
+
function getAuditDir() {
|
|
30
|
+
if (!_AUDIT_DIR) {
|
|
31
|
+
_AUDIT_DIR = join('.planning', 'logs');
|
|
32
|
+
if (!existsSync(_AUDIT_DIR)) {
|
|
33
|
+
mkdirSync(_AUDIT_DIR, { recursive: true });
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return _AUDIT_DIR;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function getAuditFile() {
|
|
40
|
+
if (!_AUDIT_FILE) {
|
|
41
|
+
_AUDIT_FILE = join(getAuditDir(), `audit-${new Date().toISOString().split('T')[0]}.jsonl`);
|
|
42
|
+
}
|
|
43
|
+
return _AUDIT_FILE;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Write audit log entry
|
|
48
|
+
* @param {Object} entry - Audit entry
|
|
49
|
+
*/
|
|
50
|
+
function writeAudit(entry) {
|
|
51
|
+
try {
|
|
52
|
+
const line = JSON.stringify(entry) + '\n';
|
|
53
|
+
appendFileSync(getAuditFile(), line, 'utf-8');
|
|
54
|
+
} catch (err) {
|
|
55
|
+
// Silently ignore audit write failures - logging is best-effort
|
|
56
|
+
// This can happen in temp test directories or when .planning doesn't exist
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Execute command with full audit logging
|
|
62
|
+
* @param {string} cmd - Command to execute
|
|
63
|
+
* @param {string[]} args - Command arguments
|
|
64
|
+
* @param {Object} options - Execution options
|
|
65
|
+
* @param {string} options.context - Calling context (which module/function)
|
|
66
|
+
* @param {string} options.user - User identifier
|
|
67
|
+
* @returns {Promise<string>} - Command stdout
|
|
68
|
+
*/
|
|
69
|
+
async function auditExec(cmd, args = [], options = {}) {
|
|
70
|
+
const { context = 'unknown', user = 'system', timeout = 30000, cwd } = options;
|
|
71
|
+
|
|
72
|
+
const entry = {
|
|
73
|
+
timestamp: new Date().toISOString(),
|
|
74
|
+
cmd,
|
|
75
|
+
args,
|
|
76
|
+
context,
|
|
77
|
+
user,
|
|
78
|
+
status: 'started'
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
// Log start
|
|
82
|
+
writeAudit(entry);
|
|
83
|
+
logger.info('Audit: command started', { cmd, args: args.join(' '), context });
|
|
84
|
+
|
|
85
|
+
const startTime = Date.now();
|
|
86
|
+
|
|
87
|
+
try {
|
|
88
|
+
const execOpts = { timeout, maxBuffer: 10 * 1024 * 1024 };
|
|
89
|
+
if (cwd) execOpts.cwd = cwd;
|
|
90
|
+
const result = await execFileAsync(cmd, args, execOpts);
|
|
91
|
+
|
|
92
|
+
const duration = Date.now() - startTime;
|
|
93
|
+
|
|
94
|
+
// Log success
|
|
95
|
+
const successEntry = {
|
|
96
|
+
...entry,
|
|
97
|
+
status: 'success',
|
|
98
|
+
duration,
|
|
99
|
+
stdout_length: result.stdout?.length || 0
|
|
100
|
+
};
|
|
101
|
+
writeAudit(successEntry);
|
|
102
|
+
|
|
103
|
+
logger.debug('Audit: command completed', { cmd, duration, context });
|
|
104
|
+
|
|
105
|
+
return result.stdout.trim();
|
|
106
|
+
} catch (err) {
|
|
107
|
+
const duration = Date.now() - startTime;
|
|
108
|
+
|
|
109
|
+
// Log failure
|
|
110
|
+
const errorEntry = {
|
|
111
|
+
...entry,
|
|
112
|
+
status: 'error',
|
|
113
|
+
duration,
|
|
114
|
+
error: err.message,
|
|
115
|
+
code: err.code,
|
|
116
|
+
signal: err.signal
|
|
117
|
+
};
|
|
118
|
+
writeAudit(errorEntry);
|
|
119
|
+
|
|
120
|
+
logger.error('Audit: command failed', { cmd, error: err.message, duration, context });
|
|
121
|
+
|
|
122
|
+
throw err;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Get today's audit log path
|
|
128
|
+
* @returns {string} - Audit file path
|
|
129
|
+
*/
|
|
130
|
+
function getAuditFilePath() {
|
|
131
|
+
return AUDIT_FILE;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Read audit log entries for a specific date
|
|
136
|
+
* @param {string} date - Date string (YYYY-MM-DD)
|
|
137
|
+
* @returns {Object[]} - Array of audit entries
|
|
138
|
+
*/
|
|
139
|
+
function readAuditLog(date = new Date().toISOString().split('T')[0]) {
|
|
140
|
+
const filePath = join(AUDIT_DIR, `audit-${date}.jsonl`);
|
|
141
|
+
|
|
142
|
+
if (!existsSync(filePath)) {
|
|
143
|
+
return [];
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const content = require('fs').readFileSync(filePath, 'utf-8');
|
|
147
|
+
return content.trim().split('\n').map(line => JSON.parse(line));
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Search audit log for specific command
|
|
152
|
+
* @param {string} cmdFilter - Command to filter by
|
|
153
|
+
* @param {string} date - Date string
|
|
154
|
+
* @returns {Object[]} - Matching entries
|
|
155
|
+
*/
|
|
156
|
+
function searchAuditLog(cmdFilter, date) {
|
|
157
|
+
const entries = readAuditLog(date);
|
|
158
|
+
return entries.filter(e => e.cmd === cmdFilter);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
module.exports = {
|
|
162
|
+
auditExec,
|
|
163
|
+
getAuditFilePath,
|
|
164
|
+
readAuditLog,
|
|
165
|
+
searchAuditLog
|
|
166
|
+
};
|