@howlil/ez-agents 3.5.0 → 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 -537
- 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 -333
- package/agents/ez-requirements-agent.md +377 -377
- 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/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 -52
- 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 -53
- package/commands/ez/progress.md +36 -36
- 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 +599 -2
- 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 -622
- 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 -238
- package/ez-agents/bin/lib/context-cache.cjs +154 -154
- package/ez-agents/bin/lib/context-errors.cjs +71 -71
- package/ez-agents/bin/lib/context-manager.cjs +220 -220
- 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/file-access.cjs +207 -207
- 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 -83
- package/ez-agents/bin/lib/git-utils.cjs +321 -321
- package/ez-agents/bin/lib/git-workflow-engine.cjs +1157 -1157
- package/ez-agents/bin/lib/health-check.cjs +162 -162
- package/ez-agents/bin/lib/index.cjs +2 -8
- package/ez-agents/bin/lib/init.cjs +0 -2
- package/ez-agents/bin/lib/lockfile-validator.cjs +227 -227
- package/ez-agents/bin/lib/log-rotation.cjs +71 -0
- package/ez-agents/bin/lib/logger.cjs +22 -47
- package/ez-agents/bin/lib/memory-compression.cjs +256 -256
- package/ez-agents/bin/lib/package-manager-detector.cjs +203 -203
- package/ez-agents/bin/lib/package-manager-executor.cjs +385 -385
- package/ez-agents/bin/lib/package-manager-service.cjs +216 -216
- 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 -614
- package/ez-agents/bin/lib/security-errors.cjs +62 -0
- package/ez-agents/bin/lib/session-chain.cjs +304 -304
- package/ez-agents/bin/lib/session-errors.cjs +81 -81
- package/ez-agents/bin/lib/session-export.cjs +251 -251
- package/ez-agents/bin/lib/session-import.cjs +262 -262
- package/ez-agents/bin/lib/session-manager.cjs +280 -280
- 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 -428
- package/ez-agents/bin/lib/tradeoff-analyzer.cjs +284 -0
- package/ez-agents/bin/lib/url-fetch.cjs +170 -170
- 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 -118
- 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 -340
- package/ez-agents/references/tier-strategy.md +103 -103
- 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 -173
- 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 -68
- package/ez-agents/templates/handoff-protocol.md +294 -0
- package/ez-agents/templates/incident-runbook.md +205 -205
- 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 -133
- package/ez-agents/templates/research.md +552 -552
- package/ez-agents/templates/rollback-plan.md +201 -201
- 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 +844 -844
- 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 +124 -3
- package/ez-agents/workflows/help.md +42 -181
- package/ez-agents/workflows/hotfix.md +291 -291
- package/ez-agents/workflows/new-milestone.md +713 -713
- package/ez-agents/workflows/new-project.md +1089 -1107
- package/ez-agents/workflows/plan-phase.md +0 -40
- package/ez-agents/workflows/release.md +253 -253
- package/ez-agents/workflows/resume-session.md +215 -215
- 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 -71
- 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-observer-agent.md +0 -260
- package/agents/ez-plan-checker.md +0 -706
- package/agents/ez-research-synthesizer.md +0 -247
- package/agents/ez-scrum-master-agent.md +0 -242
- package/agents/ez-tech-lead-agent.md +0 -267
- 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/arch-review.md +0 -102
- 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/export-session.md +0 -79
- package/commands/ez/gather-requirements.md +0 -117
- package/commands/ez/git-workflow.md +0 -72
- package/commands/ez/health.md +0 -22
- package/commands/ez/hotfix.md +0 -120
- package/commands/ez/import-session.md +0 -82
- 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/list-sessions.md +0 -96
- package/commands/ez/package-manager.md +0 -316
- package/commands/ez/pause-work.md +0 -38
- package/commands/ez/plan-milestone-gaps.md +0 -34
- package/commands/ez/preflight.md +0 -79
- package/commands/ez/reapply-patches.md +0 -124
- package/commands/ez/release.md +0 -153
- package/commands/ez/remove-phase.md +0 -31
- package/commands/ez/research-phase.md +0 -190
- package/commands/ez/resume.md +0 -107
- package/commands/ez/set-profile.md +0 -34
- package/commands/ez/standup.md +0 -85
- 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/bin/lib/metrics-tracker.cjs +0 -406
- 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/arch-review.md +0 -54
- package/ez-agents/workflows/export-session.md +0 -255
- package/ez-agents/workflows/gather-requirements.md +0 -206
- package/ez-agents/workflows/import-session.md +0 -303
- package/ez-agents/workflows/research-phase.md +0 -74
- package/ez-agents/workflows/standup.md +0 -64
- 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
|
@@ -1,280 +1,280 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Session Manager — Core session state persistence module
|
|
5
|
-
*
|
|
6
|
-
* Manages session lifecycle: create, load, update, end, list
|
|
7
|
-
* Sessions stored in .planning/sessions/session-{timestamp}.json
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
const fs = require('fs');
|
|
11
|
-
const path = require('path');
|
|
12
|
-
const { safePlanningWriteSync } = require('./planning-write.cjs');
|
|
13
|
-
const { defaultLogger: logger } = require('./logger.cjs');
|
|
14
|
-
|
|
15
|
-
class SessionManager {
|
|
16
|
-
/**
|
|
17
|
-
* Create a SessionManager instance
|
|
18
|
-
* @param {string} sessionsDir - Directory for session files (default: .planning/sessions)
|
|
19
|
-
*/
|
|
20
|
-
constructor(sessionsDir = '.planning/sessions') {
|
|
21
|
-
this.sessionsDir = sessionsDir;
|
|
22
|
-
this._ensureDir();
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Ensure sessions directory exists
|
|
27
|
-
* @private
|
|
28
|
-
*/
|
|
29
|
-
_ensureDir() {
|
|
30
|
-
if (!fs.existsSync(this.sessionsDir)) {
|
|
31
|
-
fs.mkdirSync(this.sessionsDir, { recursive: true });
|
|
32
|
-
logger.info('Sessions directory created', { dir: this.sessionsDir });
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Generate session ID from timestamp
|
|
38
|
-
* Format: session-YYYYMMDD-HHMMSS
|
|
39
|
-
* @private
|
|
40
|
-
* @returns {string} Session ID
|
|
41
|
-
*/
|
|
42
|
-
_generateSessionId() {
|
|
43
|
-
const now = new Date();
|
|
44
|
-
const timestamp = now.toISOString()
|
|
45
|
-
.replace(/[:.]/g, '-')
|
|
46
|
-
.replace('T', '-')
|
|
47
|
-
.slice(0, -5); // Remove milliseconds and Z
|
|
48
|
-
return `session-${timestamp}`;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Deep merge source into target
|
|
53
|
-
* @private
|
|
54
|
-
* @param {Object} target - Target object
|
|
55
|
-
* @param {Object} source - Source object
|
|
56
|
-
* @returns {Object} Merged object
|
|
57
|
-
*/
|
|
58
|
-
_deepMerge(target, source) {
|
|
59
|
-
const result = { ...target };
|
|
60
|
-
for (const key in source) {
|
|
61
|
-
if (source.hasOwnProperty(key)) {
|
|
62
|
-
if (source[key] instanceof Object && key !== null) {
|
|
63
|
-
result[key] = this._deepMerge(result[key] || {}, source[key]);
|
|
64
|
-
} else {
|
|
65
|
-
result[key] = source[key];
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
return result;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Create a new session
|
|
74
|
-
* @param {Object} options - Session options
|
|
75
|
-
* @param {string} [options.model] - Model identifier
|
|
76
|
-
* @param {number} [options.phase] - Phase number
|
|
77
|
-
* @param {number} [options.plan] - Plan number
|
|
78
|
-
* @param {string} [options.objective] - Session objective
|
|
79
|
-
* @returns {string} Session ID
|
|
80
|
-
*/
|
|
81
|
-
createSession(options = {}) {
|
|
82
|
-
const sessionId = this._generateSessionId();
|
|
83
|
-
const sessionPath = path.join(this.sessionsDir, `${sessionId}.json`);
|
|
84
|
-
|
|
85
|
-
const session = {
|
|
86
|
-
metadata: {
|
|
87
|
-
session_id: sessionId,
|
|
88
|
-
session_version: '1.0',
|
|
89
|
-
started_at: new Date().toISOString(),
|
|
90
|
-
ended_at: null,
|
|
91
|
-
model: options.model || null,
|
|
92
|
-
phase: options.phase || null,
|
|
93
|
-
plan: options.plan || null,
|
|
94
|
-
status: 'active',
|
|
95
|
-
session_chain: [],
|
|
96
|
-
token_usage: {
|
|
97
|
-
input: 0,
|
|
98
|
-
output: 0,
|
|
99
|
-
total: 0
|
|
100
|
-
}
|
|
101
|
-
},
|
|
102
|
-
context: {
|
|
103
|
-
transcript: '',
|
|
104
|
-
tasks: [],
|
|
105
|
-
decisions: [],
|
|
106
|
-
file_changes: [],
|
|
107
|
-
open_questions: [],
|
|
108
|
-
blockers: []
|
|
109
|
-
},
|
|
110
|
-
state: {
|
|
111
|
-
current_phase: options.phase || null,
|
|
112
|
-
current_plan: options.plan || null,
|
|
113
|
-
incomplete_tasks: [],
|
|
114
|
-
last_action: null,
|
|
115
|
-
next_recommended_action: options.objective || null
|
|
116
|
-
}
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
try {
|
|
120
|
-
safePlanningWriteSync(sessionPath, JSON.stringify(session, null, 2));
|
|
121
|
-
logger.info('Session created', { sessionId, sessionPath });
|
|
122
|
-
return sessionId;
|
|
123
|
-
} catch (err) {
|
|
124
|
-
logger.error('Failed to create session', { sessionId, error: err.message });
|
|
125
|
-
throw err;
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* Load a session by ID
|
|
131
|
-
* @param {string} sessionId - Session ID
|
|
132
|
-
* @returns {Object|null} Session object or null if not found
|
|
133
|
-
*/
|
|
134
|
-
loadSession(sessionId) {
|
|
135
|
-
const sessionPath = path.join(this.sessionsDir, `${sessionId}.json`);
|
|
136
|
-
|
|
137
|
-
if (!fs.existsSync(sessionPath)) {
|
|
138
|
-
logger.error('Session not found', { sessionId, sessionPath });
|
|
139
|
-
return null;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
try {
|
|
143
|
-
const content = fs.readFileSync(sessionPath, 'utf-8');
|
|
144
|
-
const session = JSON.parse(content);
|
|
145
|
-
logger.info('Session loaded', { sessionId });
|
|
146
|
-
return session;
|
|
147
|
-
} catch (err) {
|
|
148
|
-
logger.error('Failed to load session', { sessionId, error: err.message });
|
|
149
|
-
return null;
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* Get the most recent session
|
|
155
|
-
* @returns {Object|null} Last session or null if none exist
|
|
156
|
-
*/
|
|
157
|
-
getLastSession() {
|
|
158
|
-
const sessionFiles = this._getSessionFiles();
|
|
159
|
-
|
|
160
|
-
if (sessionFiles.length === 0) {
|
|
161
|
-
logger.info('No sessions found');
|
|
162
|
-
return null;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
// Files are sorted, newest first
|
|
166
|
-
const lastFile = sessionFiles[0];
|
|
167
|
-
const sessionId = lastFile.replace('.json', '');
|
|
168
|
-
return this.loadSession(sessionId);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
/**
|
|
172
|
-
* Update a session with new data
|
|
173
|
-
* @param {string} sessionId - Session ID
|
|
174
|
-
* @param {Object} updates - Updates to merge into session
|
|
175
|
-
* @returns {boolean} True on success, false if session not found
|
|
176
|
-
*/
|
|
177
|
-
updateSession(sessionId, updates) {
|
|
178
|
-
const session = this.loadSession(sessionId);
|
|
179
|
-
if (!session) {
|
|
180
|
-
return false;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
const updatedSession = this._deepMerge(session, updates);
|
|
184
|
-
const sessionPath = path.join(this.sessionsDir, `${sessionId}.json`);
|
|
185
|
-
|
|
186
|
-
try {
|
|
187
|
-
safePlanningWriteSync(sessionPath, JSON.stringify(updatedSession, null, 2));
|
|
188
|
-
logger.info('Session updated', { sessionId });
|
|
189
|
-
return true;
|
|
190
|
-
} catch (err) {
|
|
191
|
-
logger.error('Failed to update session', { sessionId, error: err.message });
|
|
192
|
-
return false;
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
/**
|
|
197
|
-
* End a session
|
|
198
|
-
* @param {string} sessionId - Session ID
|
|
199
|
-
* @param {Object} finalState - Final state information
|
|
200
|
-
* @param {string} [finalState.status] - Final status (default: 'completed')
|
|
201
|
-
* @param {Array} [finalState.incomplete_tasks] - Incomplete tasks
|
|
202
|
-
* @param {string} [finalState.next_recommended_action] - Next recommended action
|
|
203
|
-
* @returns {boolean} True on success, false if session not found
|
|
204
|
-
*/
|
|
205
|
-
endSession(sessionId, finalState = {}) {
|
|
206
|
-
const session = this.loadSession(sessionId);
|
|
207
|
-
if (!session) {
|
|
208
|
-
return false;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
const updates = {
|
|
212
|
-
metadata: {
|
|
213
|
-
ended_at: new Date().toISOString(),
|
|
214
|
-
status: finalState.status || 'completed'
|
|
215
|
-
},
|
|
216
|
-
state: {}
|
|
217
|
-
};
|
|
218
|
-
|
|
219
|
-
if (finalState.incomplete_tasks) {
|
|
220
|
-
updates.state.incomplete_tasks = finalState.incomplete_tasks;
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
if (finalState.next_recommended_action) {
|
|
224
|
-
updates.state.next_recommended_action = finalState.next_recommended_action;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
return this.updateSession(sessionId, updates);
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
/**
|
|
231
|
-
* List all sessions
|
|
232
|
-
* @returns {Array} Array of session metadata sorted by date (newest first)
|
|
233
|
-
*/
|
|
234
|
-
listSessions() {
|
|
235
|
-
const sessionFiles = this._getSessionFiles();
|
|
236
|
-
const sessions = [];
|
|
237
|
-
|
|
238
|
-
for (const file of sessionFiles) {
|
|
239
|
-
const sessionId = file.replace('.json', '');
|
|
240
|
-
const session = this.loadSession(sessionId);
|
|
241
|
-
if (session) {
|
|
242
|
-
sessions.push({
|
|
243
|
-
session_id: session.metadata.session_id,
|
|
244
|
-
started_at: session.metadata.started_at,
|
|
245
|
-
ended_at: session.metadata.ended_at,
|
|
246
|
-
model: session.metadata.model,
|
|
247
|
-
phase: session.metadata.phase,
|
|
248
|
-
plan: session.metadata.plan,
|
|
249
|
-
status: session.metadata.status
|
|
250
|
-
});
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
return sessions;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
/**
|
|
258
|
-
* Get session files sorted by name (newest first)
|
|
259
|
-
* @private
|
|
260
|
-
* @returns {Array} Array of filenames
|
|
261
|
-
*/
|
|
262
|
-
_getSessionFiles() {
|
|
263
|
-
if (!fs.existsSync(this.sessionsDir)) {
|
|
264
|
-
return [];
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
try {
|
|
268
|
-
const files = fs.readdirSync(this.sessionsDir)
|
|
269
|
-
.filter(file => /^session-.*\.json$/.test(file))
|
|
270
|
-
.sort()
|
|
271
|
-
.reverse();
|
|
272
|
-
return files;
|
|
273
|
-
} catch (err) {
|
|
274
|
-
logger.error('Failed to read sessions directory', { error: err.message });
|
|
275
|
-
return [];
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
module.exports = SessionManager;
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Session Manager — Core session state persistence module
|
|
5
|
+
*
|
|
6
|
+
* Manages session lifecycle: create, load, update, end, list
|
|
7
|
+
* Sessions stored in .planning/sessions/session-{timestamp}.json
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const fs = require('fs');
|
|
11
|
+
const path = require('path');
|
|
12
|
+
const { safePlanningWriteSync } = require('./planning-write.cjs');
|
|
13
|
+
const { defaultLogger: logger } = require('./logger.cjs');
|
|
14
|
+
|
|
15
|
+
class SessionManager {
|
|
16
|
+
/**
|
|
17
|
+
* Create a SessionManager instance
|
|
18
|
+
* @param {string} sessionsDir - Directory for session files (default: .planning/sessions)
|
|
19
|
+
*/
|
|
20
|
+
constructor(sessionsDir = '.planning/sessions') {
|
|
21
|
+
this.sessionsDir = sessionsDir;
|
|
22
|
+
this._ensureDir();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Ensure sessions directory exists
|
|
27
|
+
* @private
|
|
28
|
+
*/
|
|
29
|
+
_ensureDir() {
|
|
30
|
+
if (!fs.existsSync(this.sessionsDir)) {
|
|
31
|
+
fs.mkdirSync(this.sessionsDir, { recursive: true });
|
|
32
|
+
logger.info('Sessions directory created', { dir: this.sessionsDir });
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Generate session ID from timestamp
|
|
38
|
+
* Format: session-YYYYMMDD-HHMMSS
|
|
39
|
+
* @private
|
|
40
|
+
* @returns {string} Session ID
|
|
41
|
+
*/
|
|
42
|
+
_generateSessionId() {
|
|
43
|
+
const now = new Date();
|
|
44
|
+
const timestamp = now.toISOString()
|
|
45
|
+
.replace(/[:.]/g, '-')
|
|
46
|
+
.replace('T', '-')
|
|
47
|
+
.slice(0, -5); // Remove milliseconds and Z
|
|
48
|
+
return `session-${timestamp}`;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Deep merge source into target
|
|
53
|
+
* @private
|
|
54
|
+
* @param {Object} target - Target object
|
|
55
|
+
* @param {Object} source - Source object
|
|
56
|
+
* @returns {Object} Merged object
|
|
57
|
+
*/
|
|
58
|
+
_deepMerge(target, source) {
|
|
59
|
+
const result = { ...target };
|
|
60
|
+
for (const key in source) {
|
|
61
|
+
if (source.hasOwnProperty(key)) {
|
|
62
|
+
if (source[key] instanceof Object && key !== null) {
|
|
63
|
+
result[key] = this._deepMerge(result[key] || {}, source[key]);
|
|
64
|
+
} else {
|
|
65
|
+
result[key] = source[key];
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return result;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Create a new session
|
|
74
|
+
* @param {Object} options - Session options
|
|
75
|
+
* @param {string} [options.model] - Model identifier
|
|
76
|
+
* @param {number} [options.phase] - Phase number
|
|
77
|
+
* @param {number} [options.plan] - Plan number
|
|
78
|
+
* @param {string} [options.objective] - Session objective
|
|
79
|
+
* @returns {string} Session ID
|
|
80
|
+
*/
|
|
81
|
+
createSession(options = {}) {
|
|
82
|
+
const sessionId = this._generateSessionId();
|
|
83
|
+
const sessionPath = path.join(this.sessionsDir, `${sessionId}.json`);
|
|
84
|
+
|
|
85
|
+
const session = {
|
|
86
|
+
metadata: {
|
|
87
|
+
session_id: sessionId,
|
|
88
|
+
session_version: '1.0',
|
|
89
|
+
started_at: new Date().toISOString(),
|
|
90
|
+
ended_at: null,
|
|
91
|
+
model: options.model || null,
|
|
92
|
+
phase: options.phase || null,
|
|
93
|
+
plan: options.plan || null,
|
|
94
|
+
status: 'active',
|
|
95
|
+
session_chain: [],
|
|
96
|
+
token_usage: {
|
|
97
|
+
input: 0,
|
|
98
|
+
output: 0,
|
|
99
|
+
total: 0
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
context: {
|
|
103
|
+
transcript: '',
|
|
104
|
+
tasks: [],
|
|
105
|
+
decisions: [],
|
|
106
|
+
file_changes: [],
|
|
107
|
+
open_questions: [],
|
|
108
|
+
blockers: []
|
|
109
|
+
},
|
|
110
|
+
state: {
|
|
111
|
+
current_phase: options.phase || null,
|
|
112
|
+
current_plan: options.plan || null,
|
|
113
|
+
incomplete_tasks: [],
|
|
114
|
+
last_action: null,
|
|
115
|
+
next_recommended_action: options.objective || null
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
try {
|
|
120
|
+
safePlanningWriteSync(sessionPath, JSON.stringify(session, null, 2));
|
|
121
|
+
logger.info('Session created', { sessionId, sessionPath });
|
|
122
|
+
return sessionId;
|
|
123
|
+
} catch (err) {
|
|
124
|
+
logger.error('Failed to create session', { sessionId, error: err.message });
|
|
125
|
+
throw err;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Load a session by ID
|
|
131
|
+
* @param {string} sessionId - Session ID
|
|
132
|
+
* @returns {Object|null} Session object or null if not found
|
|
133
|
+
*/
|
|
134
|
+
loadSession(sessionId) {
|
|
135
|
+
const sessionPath = path.join(this.sessionsDir, `${sessionId}.json`);
|
|
136
|
+
|
|
137
|
+
if (!fs.existsSync(sessionPath)) {
|
|
138
|
+
logger.error('Session not found', { sessionId, sessionPath });
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
try {
|
|
143
|
+
const content = fs.readFileSync(sessionPath, 'utf-8');
|
|
144
|
+
const session = JSON.parse(content);
|
|
145
|
+
logger.info('Session loaded', { sessionId });
|
|
146
|
+
return session;
|
|
147
|
+
} catch (err) {
|
|
148
|
+
logger.error('Failed to load session', { sessionId, error: err.message });
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Get the most recent session
|
|
155
|
+
* @returns {Object|null} Last session or null if none exist
|
|
156
|
+
*/
|
|
157
|
+
getLastSession() {
|
|
158
|
+
const sessionFiles = this._getSessionFiles();
|
|
159
|
+
|
|
160
|
+
if (sessionFiles.length === 0) {
|
|
161
|
+
logger.info('No sessions found');
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Files are sorted, newest first
|
|
166
|
+
const lastFile = sessionFiles[0];
|
|
167
|
+
const sessionId = lastFile.replace('.json', '');
|
|
168
|
+
return this.loadSession(sessionId);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Update a session with new data
|
|
173
|
+
* @param {string} sessionId - Session ID
|
|
174
|
+
* @param {Object} updates - Updates to merge into session
|
|
175
|
+
* @returns {boolean} True on success, false if session not found
|
|
176
|
+
*/
|
|
177
|
+
updateSession(sessionId, updates) {
|
|
178
|
+
const session = this.loadSession(sessionId);
|
|
179
|
+
if (!session) {
|
|
180
|
+
return false;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const updatedSession = this._deepMerge(session, updates);
|
|
184
|
+
const sessionPath = path.join(this.sessionsDir, `${sessionId}.json`);
|
|
185
|
+
|
|
186
|
+
try {
|
|
187
|
+
safePlanningWriteSync(sessionPath, JSON.stringify(updatedSession, null, 2));
|
|
188
|
+
logger.info('Session updated', { sessionId });
|
|
189
|
+
return true;
|
|
190
|
+
} catch (err) {
|
|
191
|
+
logger.error('Failed to update session', { sessionId, error: err.message });
|
|
192
|
+
return false;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* End a session
|
|
198
|
+
* @param {string} sessionId - Session ID
|
|
199
|
+
* @param {Object} finalState - Final state information
|
|
200
|
+
* @param {string} [finalState.status] - Final status (default: 'completed')
|
|
201
|
+
* @param {Array} [finalState.incomplete_tasks] - Incomplete tasks
|
|
202
|
+
* @param {string} [finalState.next_recommended_action] - Next recommended action
|
|
203
|
+
* @returns {boolean} True on success, false if session not found
|
|
204
|
+
*/
|
|
205
|
+
endSession(sessionId, finalState = {}) {
|
|
206
|
+
const session = this.loadSession(sessionId);
|
|
207
|
+
if (!session) {
|
|
208
|
+
return false;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const updates = {
|
|
212
|
+
metadata: {
|
|
213
|
+
ended_at: new Date().toISOString(),
|
|
214
|
+
status: finalState.status || 'completed'
|
|
215
|
+
},
|
|
216
|
+
state: {}
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
if (finalState.incomplete_tasks) {
|
|
220
|
+
updates.state.incomplete_tasks = finalState.incomplete_tasks;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
if (finalState.next_recommended_action) {
|
|
224
|
+
updates.state.next_recommended_action = finalState.next_recommended_action;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
return this.updateSession(sessionId, updates);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* List all sessions
|
|
232
|
+
* @returns {Array} Array of session metadata sorted by date (newest first)
|
|
233
|
+
*/
|
|
234
|
+
listSessions() {
|
|
235
|
+
const sessionFiles = this._getSessionFiles();
|
|
236
|
+
const sessions = [];
|
|
237
|
+
|
|
238
|
+
for (const file of sessionFiles) {
|
|
239
|
+
const sessionId = file.replace('.json', '');
|
|
240
|
+
const session = this.loadSession(sessionId);
|
|
241
|
+
if (session) {
|
|
242
|
+
sessions.push({
|
|
243
|
+
session_id: session.metadata.session_id,
|
|
244
|
+
started_at: session.metadata.started_at,
|
|
245
|
+
ended_at: session.metadata.ended_at,
|
|
246
|
+
model: session.metadata.model,
|
|
247
|
+
phase: session.metadata.phase,
|
|
248
|
+
plan: session.metadata.plan,
|
|
249
|
+
status: session.metadata.status
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
return sessions;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Get session files sorted by name (newest first)
|
|
259
|
+
* @private
|
|
260
|
+
* @returns {Array} Array of filenames
|
|
261
|
+
*/
|
|
262
|
+
_getSessionFiles() {
|
|
263
|
+
if (!fs.existsSync(this.sessionsDir)) {
|
|
264
|
+
return [];
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
try {
|
|
268
|
+
const files = fs.readdirSync(this.sessionsDir)
|
|
269
|
+
.filter(file => /^session-.*\.json$/.test(file))
|
|
270
|
+
.sort()
|
|
271
|
+
.reverse();
|
|
272
|
+
return files;
|
|
273
|
+
} catch (err) {
|
|
274
|
+
logger.error('Failed to read sessions directory', { error: err.message });
|
|
275
|
+
return [];
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
module.exports = SessionManager;
|