@accelerationguy/accel 1.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/CLAUDE.md +19 -0
- package/LICENSE +33 -0
- package/README.md +275 -0
- package/bin/install.js +661 -0
- package/docs/getting-started.md +164 -0
- package/docs/module-guide.md +139 -0
- package/modules/drive/LICENSE +21 -0
- package/modules/drive/PAUL-VS-GSD.md +171 -0
- package/modules/drive/README.md +555 -0
- package/modules/drive/assets/terminal.svg +67 -0
- package/modules/drive/bin/install.js +210 -0
- package/modules/drive/integration.js +76 -0
- package/modules/drive/package.json +38 -0
- package/modules/drive/src/commands/add-phase.md +36 -0
- package/modules/drive/src/commands/apply.md +83 -0
- package/modules/drive/src/commands/assumptions.md +37 -0
- package/modules/drive/src/commands/audit.md +57 -0
- package/modules/drive/src/commands/complete-milestone.md +36 -0
- package/modules/drive/src/commands/config.md +175 -0
- package/modules/drive/src/commands/consider-issues.md +41 -0
- package/modules/drive/src/commands/discover.md +48 -0
- package/modules/drive/src/commands/discuss-milestone.md +33 -0
- package/modules/drive/src/commands/discuss.md +34 -0
- package/modules/drive/src/commands/flows.md +73 -0
- package/modules/drive/src/commands/handoff.md +201 -0
- package/modules/drive/src/commands/help.md +525 -0
- package/modules/drive/src/commands/init.md +54 -0
- package/modules/drive/src/commands/map-codebase.md +34 -0
- package/modules/drive/src/commands/milestone.md +34 -0
- package/modules/drive/src/commands/pause.md +44 -0
- package/modules/drive/src/commands/plan-fix.md +216 -0
- package/modules/drive/src/commands/plan.md +36 -0
- package/modules/drive/src/commands/progress.md +138 -0
- package/modules/drive/src/commands/register.md +29 -0
- package/modules/drive/src/commands/remove-phase.md +37 -0
- package/modules/drive/src/commands/research-phase.md +209 -0
- package/modules/drive/src/commands/research.md +47 -0
- package/modules/drive/src/commands/resume.md +49 -0
- package/modules/drive/src/commands/status.md +78 -0
- package/modules/drive/src/commands/unify.md +87 -0
- package/modules/drive/src/commands/verify.md +60 -0
- package/modules/drive/src/references/checkpoints.md +234 -0
- package/modules/drive/src/references/context-management.md +219 -0
- package/modules/drive/src/references/git-strategy.md +206 -0
- package/modules/drive/src/references/loop-phases.md +254 -0
- package/modules/drive/src/references/plan-format.md +263 -0
- package/modules/drive/src/references/quality-principles.md +152 -0
- package/modules/drive/src/references/research-quality-control.md +247 -0
- package/modules/drive/src/references/sonarqube-integration.md +244 -0
- package/modules/drive/src/references/specialized-workflow-integration.md +186 -0
- package/modules/drive/src/references/subagent-criteria.md +179 -0
- package/modules/drive/src/references/tdd.md +219 -0
- package/modules/drive/src/references/work-units.md +161 -0
- package/modules/drive/src/rules/commands.md +108 -0
- package/modules/drive/src/rules/references.md +107 -0
- package/modules/drive/src/rules/style.md +123 -0
- package/modules/drive/src/rules/templates.md +51 -0
- package/modules/drive/src/rules/workflows.md +133 -0
- package/modules/drive/src/templates/CONTEXT.md +88 -0
- package/modules/drive/src/templates/DEBUG.md +164 -0
- package/modules/drive/src/templates/DISCOVERY.md +148 -0
- package/modules/drive/src/templates/HANDOFF.md +77 -0
- package/modules/drive/src/templates/ISSUES.md +93 -0
- package/modules/drive/src/templates/MILESTONES.md +167 -0
- package/modules/drive/src/templates/PLAN.md +328 -0
- package/modules/drive/src/templates/PROJECT.md +219 -0
- package/modules/drive/src/templates/RESEARCH.md +130 -0
- package/modules/drive/src/templates/ROADMAP.md +328 -0
- package/modules/drive/src/templates/SPECIAL-FLOWS.md +70 -0
- package/modules/drive/src/templates/STATE.md +210 -0
- package/modules/drive/src/templates/SUMMARY.md +221 -0
- package/modules/drive/src/templates/UAT-ISSUES.md +139 -0
- package/modules/drive/src/templates/codebase/architecture.md +259 -0
- package/modules/drive/src/templates/codebase/concerns.md +329 -0
- package/modules/drive/src/templates/codebase/conventions.md +311 -0
- package/modules/drive/src/templates/codebase/integrations.md +284 -0
- package/modules/drive/src/templates/codebase/stack.md +190 -0
- package/modules/drive/src/templates/codebase/structure.md +287 -0
- package/modules/drive/src/templates/codebase/testing.md +484 -0
- package/modules/drive/src/templates/config.md +181 -0
- package/modules/drive/src/templates/milestone-archive.md +236 -0
- package/modules/drive/src/templates/milestone-context.md +190 -0
- package/modules/drive/src/templates/paul-json.md +147 -0
- package/modules/drive/src/vector-config/PAUL +26 -0
- package/modules/drive/src/vector-config/PAUL.manifest +11 -0
- package/modules/drive/src/workflows/apply-phase.md +393 -0
- package/modules/drive/src/workflows/audit-plan.md +344 -0
- package/modules/drive/src/workflows/complete-milestone.md +479 -0
- package/modules/drive/src/workflows/configure-special-flows.md +283 -0
- package/modules/drive/src/workflows/consider-issues.md +172 -0
- package/modules/drive/src/workflows/create-milestone.md +268 -0
- package/modules/drive/src/workflows/debug.md +292 -0
- package/modules/drive/src/workflows/discovery.md +187 -0
- package/modules/drive/src/workflows/discuss-milestone.md +245 -0
- package/modules/drive/src/workflows/discuss-phase.md +231 -0
- package/modules/drive/src/workflows/init-project.md +698 -0
- package/modules/drive/src/workflows/map-codebase.md +459 -0
- package/modules/drive/src/workflows/pause-work.md +259 -0
- package/modules/drive/src/workflows/phase-assumptions.md +181 -0
- package/modules/drive/src/workflows/plan-phase.md +385 -0
- package/modules/drive/src/workflows/quality-gate.md +263 -0
- package/modules/drive/src/workflows/register-manifest.md +107 -0
- package/modules/drive/src/workflows/research.md +241 -0
- package/modules/drive/src/workflows/resume-project.md +200 -0
- package/modules/drive/src/workflows/roadmap-management.md +334 -0
- package/modules/drive/src/workflows/transition-phase.md +368 -0
- package/modules/drive/src/workflows/unify-phase.md +290 -0
- package/modules/drive/src/workflows/verify-work.md +241 -0
- package/modules/forge/README.md +281 -0
- package/modules/forge/bin/install.js +200 -0
- package/modules/forge/package.json +32 -0
- package/modules/forge/skillsmith/rules/checklists-rules.md +42 -0
- package/modules/forge/skillsmith/rules/context-rules.md +43 -0
- package/modules/forge/skillsmith/rules/entry-point-rules.md +44 -0
- package/modules/forge/skillsmith/rules/frameworks-rules.md +43 -0
- package/modules/forge/skillsmith/rules/tasks-rules.md +52 -0
- package/modules/forge/skillsmith/rules/templates-rules.md +43 -0
- package/modules/forge/skillsmith/skillsmith.md +82 -0
- package/modules/forge/skillsmith/tasks/audit.md +277 -0
- package/modules/forge/skillsmith/tasks/discover.md +145 -0
- package/modules/forge/skillsmith/tasks/distill.md +276 -0
- package/modules/forge/skillsmith/tasks/scaffold.md +349 -0
- package/modules/forge/specs/checklists.md +193 -0
- package/modules/forge/specs/context.md +223 -0
- package/modules/forge/specs/entry-point.md +320 -0
- package/modules/forge/specs/frameworks.md +228 -0
- package/modules/forge/specs/rules.md +245 -0
- package/modules/forge/specs/tasks.md +344 -0
- package/modules/forge/specs/templates.md +335 -0
- package/modules/forge/terminal.svg +70 -0
- package/modules/ignition/README.md +245 -0
- package/modules/ignition/bin/install.js +184 -0
- package/modules/ignition/checklists/planning-quality.md +55 -0
- package/modules/ignition/data/application/config.md +21 -0
- package/modules/ignition/data/application/guide.md +51 -0
- package/modules/ignition/data/application/skill-loadout.md +11 -0
- package/modules/ignition/data/campaign/config.md +18 -0
- package/modules/ignition/data/campaign/guide.md +36 -0
- package/modules/ignition/data/campaign/skill-loadout.md +10 -0
- package/modules/ignition/data/client/config.md +18 -0
- package/modules/ignition/data/client/guide.md +36 -0
- package/modules/ignition/data/client/skill-loadout.md +11 -0
- package/modules/ignition/data/utility/config.md +18 -0
- package/modules/ignition/data/utility/guide.md +31 -0
- package/modules/ignition/data/utility/skill-loadout.md +8 -0
- package/modules/ignition/data/workflow/config.md +19 -0
- package/modules/ignition/data/workflow/guide.md +41 -0
- package/modules/ignition/data/workflow/skill-loadout.md +10 -0
- package/modules/ignition/integration.js +54 -0
- package/modules/ignition/package.json +35 -0
- package/modules/ignition/seed.md +81 -0
- package/modules/ignition/tasks/add-type.md +164 -0
- package/modules/ignition/tasks/graduate.md +182 -0
- package/modules/ignition/tasks/ideate.md +221 -0
- package/modules/ignition/tasks/launch.md +137 -0
- package/modules/ignition/tasks/status.md +71 -0
- package/modules/ignition/templates/planning-application.md +193 -0
- package/modules/ignition/templates/planning-campaign.md +138 -0
- package/modules/ignition/templates/planning-client.md +149 -0
- package/modules/ignition/templates/planning-utility.md +112 -0
- package/modules/ignition/templates/planning-workflow.md +125 -0
- package/modules/ignition/terminal.svg +74 -0
- package/modules/mission-control/CONTEXT-CONTINUITY-SPEC.md +293 -0
- package/modules/mission-control/CONTEXT-ENGINEERING-GUIDE.md +282 -0
- package/modules/mission-control/README.md +91 -0
- package/modules/mission-control/assets/terminal.svg +80 -0
- package/modules/mission-control/examples/entities.example.json +133 -0
- package/modules/mission-control/examples/projects.example.json +318 -0
- package/modules/mission-control/examples/state.example.json +183 -0
- package/modules/mission-control/examples/vector.example.json +245 -0
- package/modules/mission-control/mission-control/checklists/install-verification.md +46 -0
- package/modules/mission-control/mission-control/frameworks/framework-registry.md +83 -0
- package/modules/mission-control/mission-control/mission-control.md +83 -0
- package/modules/mission-control/mission-control/tasks/insights.md +73 -0
- package/modules/mission-control/mission-control/tasks/install.md +194 -0
- package/modules/mission-control/mission-control/tasks/status.md +125 -0
- package/modules/mission-control/schemas/entities.schema.json +89 -0
- package/modules/mission-control/schemas/projects.schema.json +221 -0
- package/modules/mission-control/schemas/state.schema.json +108 -0
- package/modules/mission-control/schemas/vector.schema.json +200 -0
- package/modules/momentum/README.md +678 -0
- package/modules/momentum/bin/install.js +563 -0
- package/modules/momentum/integration.js +131 -0
- package/modules/momentum/package.json +42 -0
- package/modules/momentum/schemas/entities.schema.json +89 -0
- package/modules/momentum/schemas/projects.schema.json +221 -0
- package/modules/momentum/schemas/state.schema.json +108 -0
- package/modules/momentum/src/commands/audit-claude-md.md +31 -0
- package/modules/momentum/src/commands/audit.md +33 -0
- package/modules/momentum/src/commands/groom.md +35 -0
- package/modules/momentum/src/commands/history.md +27 -0
- package/modules/momentum/src/commands/pulse.md +33 -0
- package/modules/momentum/src/commands/scaffold.md +33 -0
- package/modules/momentum/src/commands/status.md +28 -0
- package/modules/momentum/src/commands/surface-convert.md +35 -0
- package/modules/momentum/src/commands/surface-create.md +34 -0
- package/modules/momentum/src/commands/surface-list.md +27 -0
- package/modules/momentum/src/commands/vector-hygiene.md +33 -0
- package/modules/momentum/src/framework/context/momentum-principles.md +71 -0
- package/modules/momentum/src/framework/frameworks/audit-strategies.md +53 -0
- package/modules/momentum/src/framework/frameworks/satellite-registration.md +44 -0
- package/modules/momentum/src/framework/tasks/audit-claude-md.md +68 -0
- package/modules/momentum/src/framework/tasks/audit.md +64 -0
- package/modules/momentum/src/framework/tasks/groom.md +164 -0
- package/modules/momentum/src/framework/tasks/history.md +34 -0
- package/modules/momentum/src/framework/tasks/pulse.md +83 -0
- package/modules/momentum/src/framework/tasks/scaffold.md +202 -0
- package/modules/momentum/src/framework/tasks/status.md +35 -0
- package/modules/momentum/src/framework/tasks/surface-convert.md +143 -0
- package/modules/momentum/src/framework/tasks/surface-create.md +184 -0
- package/modules/momentum/src/framework/tasks/surface-list.md +42 -0
- package/modules/momentum/src/framework/tasks/vector-hygiene.md +160 -0
- package/modules/momentum/src/framework/templates/workspace-json.md +96 -0
- package/modules/momentum/src/hooks/_template.py +129 -0
- package/modules/momentum/src/hooks/active-hook.py +178 -0
- package/modules/momentum/src/hooks/backlog-hook.py +115 -0
- package/modules/momentum/src/hooks/mission-control-insights.py +169 -0
- package/modules/momentum/src/hooks/momentum-pulse-check.py +351 -0
- package/modules/momentum/src/hooks/operator.py +53 -0
- package/modules/momentum/src/hooks/psmm-injector.py +67 -0
- package/modules/momentum/src/hooks/satellite-detection.py +248 -0
- package/modules/momentum/src/packages/momentum-mcp/index.js +119 -0
- package/modules/momentum/src/packages/momentum-mcp/package.json +10 -0
- package/modules/momentum/src/packages/momentum-mcp/tools/entities.js +226 -0
- package/modules/momentum/src/packages/momentum-mcp/tools/operator.js +106 -0
- package/modules/momentum/src/packages/momentum-mcp/tools/projects.js +322 -0
- package/modules/momentum/src/packages/momentum-mcp/tools/psmm.js +206 -0
- package/modules/momentum/src/packages/momentum-mcp/tools/state.js +199 -0
- package/modules/momentum/src/packages/momentum-mcp/tools/surfaces.js +404 -0
- package/modules/momentum/src/skill/momentum.md +111 -0
- package/modules/momentum/src/tasks/groom.md +164 -0
- package/modules/momentum/src/templates/operator.json +66 -0
- package/modules/momentum/src/templates/workspace.json +111 -0
- package/modules/momentum/terminal.svg +77 -0
- package/modules/radar/README.md +1552 -0
- package/modules/radar/commands/audit.md +233 -0
- package/modules/radar/commands/guardrails.md +194 -0
- package/modules/radar/commands/init.md +207 -0
- package/modules/radar/commands/playbook.md +176 -0
- package/modules/radar/commands/remediate.md +156 -0
- package/modules/radar/commands/report.md +172 -0
- package/modules/radar/commands/resume.md +176 -0
- package/modules/radar/commands/status.md +148 -0
- package/modules/radar/commands/transform.md +205 -0
- package/modules/radar/commands/validate.md +177 -0
- package/modules/radar/docs/ARCHITECTURE.md +336 -0
- package/modules/radar/docs/GETTING-STARTED.md +287 -0
- package/modules/radar/docs/standards/agents.md +197 -0
- package/modules/radar/docs/standards/commands.md +250 -0
- package/modules/radar/docs/standards/domains.md +191 -0
- package/modules/radar/docs/standards/personas.md +211 -0
- package/modules/radar/docs/standards/rules.md +218 -0
- package/modules/radar/docs/standards/runtime.md +445 -0
- package/modules/radar/docs/standards/schemas.md +269 -0
- package/modules/radar/docs/standards/tools.md +273 -0
- package/modules/radar/docs/standards/workflows.md +254 -0
- package/modules/radar/docs/terminal.svg +72 -0
- package/modules/radar/docs/validation/convention-compliance-report.md +183 -0
- package/modules/radar/docs/validation/cross-reference-report.md +195 -0
- package/modules/radar/docs/validation/validation-summary.md +118 -0
- package/modules/radar/docs/validation/version-manifest.yaml +363 -0
- package/modules/radar/install.sh +711 -0
- package/modules/radar/integration.js +53 -0
- package/modules/radar/src/core/agents/architect.md +25 -0
- package/modules/radar/src/core/agents/compliance-officer.md +25 -0
- package/modules/radar/src/core/agents/data-engineer.md +25 -0
- package/modules/radar/src/core/agents/devils-advocate.md +22 -0
- package/modules/radar/src/core/agents/performance-engineer.md +25 -0
- package/modules/radar/src/core/agents/principal-engineer.md +23 -0
- package/modules/radar/src/core/agents/reality-gap-analyst.md +22 -0
- package/modules/radar/src/core/agents/security-engineer.md +25 -0
- package/modules/radar/src/core/agents/senior-app-engineer.md +25 -0
- package/modules/radar/src/core/agents/sre.md +25 -0
- package/modules/radar/src/core/agents/staff-engineer.md +23 -0
- package/modules/radar/src/core/agents/test-engineer.md +25 -0
- package/modules/radar/src/core/personas/architect.md +111 -0
- package/modules/radar/src/core/personas/compliance-officer.md +104 -0
- package/modules/radar/src/core/personas/data-engineer.md +113 -0
- package/modules/radar/src/core/personas/devils-advocate.md +105 -0
- package/modules/radar/src/core/personas/performance-engineer.md +119 -0
- package/modules/radar/src/core/personas/principal-engineer.md +119 -0
- package/modules/radar/src/core/personas/reality-gap-analyst.md +111 -0
- package/modules/radar/src/core/personas/security-engineer.md +108 -0
- package/modules/radar/src/core/personas/senior-app-engineer.md +111 -0
- package/modules/radar/src/core/personas/sre.md +117 -0
- package/modules/radar/src/core/personas/staff-engineer.md +109 -0
- package/modules/radar/src/core/personas/test-engineer.md +109 -0
- package/modules/radar/src/core/workflows/disagreement-resolution.md +183 -0
- package/modules/radar/src/core/workflows/phase-0-context.md +148 -0
- package/modules/radar/src/core/workflows/phase-1-reconnaissance.md +169 -0
- package/modules/radar/src/core/workflows/phase-2-domain-audits.md +190 -0
- package/modules/radar/src/core/workflows/phase-3-cross-domain.md +177 -0
- package/modules/radar/src/core/workflows/phase-4-adversarial-review.md +165 -0
- package/modules/radar/src/core/workflows/phase-5-report.md +189 -0
- package/modules/radar/src/core/workflows/phase-checkpoint.md +222 -0
- package/modules/radar/src/core/workflows/session-handoff.md +152 -0
- package/modules/radar/src/domains/00-context.md +201 -0
- package/modules/radar/src/domains/01-architecture.md +248 -0
- package/modules/radar/src/domains/02-data.md +224 -0
- package/modules/radar/src/domains/03-correctness.md +230 -0
- package/modules/radar/src/domains/04-security.md +274 -0
- package/modules/radar/src/domains/05-compliance.md +228 -0
- package/modules/radar/src/domains/06-testing.md +228 -0
- package/modules/radar/src/domains/07-reliability.md +246 -0
- package/modules/radar/src/domains/08-performance.md +247 -0
- package/modules/radar/src/domains/09-maintainability.md +271 -0
- package/modules/radar/src/domains/10-operability.md +250 -0
- package/modules/radar/src/domains/11-change-risk.md +246 -0
- package/modules/radar/src/domains/12-team-risk.md +221 -0
- package/modules/radar/src/domains/13-risk-synthesis.md +202 -0
- package/modules/radar/src/rules/agent-boundaries.md +78 -0
- package/modules/radar/src/rules/disagreement-protocol.md +76 -0
- package/modules/radar/src/rules/epistemic-hygiene.md +78 -0
- package/modules/radar/src/schemas/confidence.md +185 -0
- package/modules/radar/src/schemas/disagreement.md +238 -0
- package/modules/radar/src/schemas/finding.md +287 -0
- package/modules/radar/src/schemas/report-section.md +150 -0
- package/modules/radar/src/schemas/signal.md +108 -0
- package/modules/radar/src/tools/checkov.md +463 -0
- package/modules/radar/src/tools/git-history.md +581 -0
- package/modules/radar/src/tools/gitleaks.md +447 -0
- package/modules/radar/src/tools/grype.md +611 -0
- package/modules/radar/src/tools/semgrep.md +378 -0
- package/modules/radar/src/tools/sonarqube.md +550 -0
- package/modules/radar/src/tools/syft.md +539 -0
- package/modules/radar/src/tools/trivy.md +439 -0
- package/modules/radar/src/transform/agents/change-risk-modeler.md +24 -0
- package/modules/radar/src/transform/agents/execution-validator.md +24 -0
- package/modules/radar/src/transform/agents/guardrail-generator.md +24 -0
- package/modules/radar/src/transform/agents/pedagogy-agent.md +24 -0
- package/modules/radar/src/transform/agents/remediation-architect.md +24 -0
- package/modules/radar/src/transform/personas/change-risk-modeler.md +95 -0
- package/modules/radar/src/transform/personas/execution-validator.md +95 -0
- package/modules/radar/src/transform/personas/guardrail-generator.md +103 -0
- package/modules/radar/src/transform/personas/pedagogy-agent.md +105 -0
- package/modules/radar/src/transform/personas/remediation-architect.md +95 -0
- package/modules/radar/src/transform/rules/change-risk-rules.md +87 -0
- package/modules/radar/src/transform/rules/safety-governance.md +87 -0
- package/modules/radar/src/transform/schemas/change-risk.md +139 -0
- package/modules/radar/src/transform/schemas/intervention-level.md +207 -0
- package/modules/radar/src/transform/schemas/playbook.md +205 -0
- package/modules/radar/src/transform/schemas/verification-plan.md +134 -0
- package/modules/radar/src/transform/workflows/phase-6-remediation.md +148 -0
- package/modules/radar/src/transform/workflows/phase-7-risk-validation.md +161 -0
- package/modules/radar/src/transform/workflows/phase-8-execution-planning.md +159 -0
- package/modules/radar/src/transform/workflows/transform-safety.md +158 -0
- package/modules/vector/.vector-template/sessions/.gitkeep +0 -0
- package/modules/vector/.vector-template/vector.json +72 -0
- package/modules/vector/AUDIT-CLAUDEMD.md +154 -0
- package/modules/vector/INSTALL.md +185 -0
- package/modules/vector/LICENSE +21 -0
- package/modules/vector/README.md +409 -0
- package/modules/vector/VECTOR-BLOCK.md +57 -0
- package/modules/vector/assets/terminal.svg +68 -0
- package/modules/vector/bin/install.js +455 -0
- package/modules/vector/bin/migrate-v1-to-v2.sh +492 -0
- package/modules/vector/commands/help.md +46 -0
- package/modules/vector/hooks/vector-hook.py +775 -0
- package/modules/vector/mcp/index.js +118 -0
- package/modules/vector/mcp/package.json +10 -0
- package/modules/vector/mcp/tools/decisions.js +269 -0
- package/modules/vector/mcp/tools/domains.js +361 -0
- package/modules/vector/mcp/tools/staging.js +252 -0
- package/modules/vector/mcp/tools/vector-json.js +647 -0
- package/modules/vector/package.json +38 -0
- package/modules/vector/schemas/vector.schema.json +237 -0
- package/package.json +39 -0
- package/shared/branding/branding.js +70 -0
- package/shared/config/defaults.json +59 -0
- package/shared/events/README.md +175 -0
- package/shared/events/event-bus.js +134 -0
- package/shared/events/event_bus.py +255 -0
- package/shared/events/integrations.js +161 -0
- package/shared/events/schemas/audit-complete.schema.json +21 -0
- package/shared/events/schemas/phase-progress.schema.json +23 -0
- package/shared/events/schemas/plan-created.schema.json +21 -0
|
@@ -0,0 +1,563 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const os = require('os');
|
|
6
|
+
const readline = require('readline');
|
|
7
|
+
const { execSync } = require('child_process');
|
|
8
|
+
|
|
9
|
+
// Colors
|
|
10
|
+
const cyan = '\x1b[36m';
|
|
11
|
+
const green = '\x1b[32m';
|
|
12
|
+
const yellow = '\x1b[33m';
|
|
13
|
+
const dim = '\x1b[2m';
|
|
14
|
+
const reset = '\x1b[0m';
|
|
15
|
+
|
|
16
|
+
// Get version from package.json
|
|
17
|
+
const pkg = require('../package.json');
|
|
18
|
+
|
|
19
|
+
const banner = `
|
|
20
|
+
${cyan} ███╗ ███╗ ██████╗ ███╗ ███╗███████╗███╗ ██╗████████╗██╗ ██╗███╗ ███╗
|
|
21
|
+
████╗ ████║██╔═══██╗████╗ ████║██╔════╝████╗ ██║╚══██╔══╝██║ ██║████╗ ████║
|
|
22
|
+
██╔████╔██║██║ ██║██╔████╔██║█████╗ ██╔██╗ ██║ ██║ ██║ ██║██╔████╔██║
|
|
23
|
+
██║╚██╔╝██║██║ ██║██║╚██╔╝██║██╔══╝ ██║╚██╗██║ ██║ ██║ ██║██║╚██╔╝██║
|
|
24
|
+
██║ ╚═╝ ██║╚██████╔╝██║ ╚═╝ ██║███████╗██║ ╚████║ ██║ ╚██████╔╝██║ ╚═╝ ██║
|
|
25
|
+
╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═══╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝${reset}
|
|
26
|
+
|
|
27
|
+
Momentum Framework ${dim}v${pkg.version}${reset}
|
|
28
|
+
Builder's Automated State Engine for Claude Code
|
|
29
|
+
`;
|
|
30
|
+
|
|
31
|
+
// Parse args
|
|
32
|
+
const args = process.argv.slice(2);
|
|
33
|
+
const hasGlobal = args.includes('--global') || args.includes('-g');
|
|
34
|
+
const hasLocal = args.includes('--local') || args.includes('-l');
|
|
35
|
+
const hasWorkspace = args.includes('--workspace') || args.includes('-w');
|
|
36
|
+
|
|
37
|
+
// Parse --config-dir argument
|
|
38
|
+
function parseConfigDirArg() {
|
|
39
|
+
const configDirIndex = args.findIndex(arg => arg === '--config-dir' || arg === '-c');
|
|
40
|
+
if (configDirIndex !== -1) {
|
|
41
|
+
const nextArg = args[configDirIndex + 1];
|
|
42
|
+
if (!nextArg || nextArg.startsWith('-')) {
|
|
43
|
+
console.error(` ${yellow}--config-dir requires a path argument${reset}`);
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
return nextArg;
|
|
47
|
+
}
|
|
48
|
+
const configDirArg = args.find(arg => arg.startsWith('--config-dir=') || arg.startsWith('-c='));
|
|
49
|
+
if (configDirArg) {
|
|
50
|
+
return configDirArg.split('=')[1];
|
|
51
|
+
}
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
const explicitConfigDir = parseConfigDirArg();
|
|
55
|
+
|
|
56
|
+
// Parse --workspace-dir argument
|
|
57
|
+
function parseWorkspaceDirArg() {
|
|
58
|
+
const idx = args.findIndex(arg => arg === '--workspace-dir');
|
|
59
|
+
if (idx !== -1) {
|
|
60
|
+
const nextArg = args[idx + 1];
|
|
61
|
+
if (!nextArg || nextArg.startsWith('-')) {
|
|
62
|
+
console.error(` ${yellow}--workspace-dir requires a path argument${reset}`);
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
return nextArg;
|
|
66
|
+
}
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
const explicitWorkspaceDir = parseWorkspaceDirArg();
|
|
70
|
+
const hasHelp = args.includes('--help') || args.includes('-h');
|
|
71
|
+
|
|
72
|
+
console.log(banner);
|
|
73
|
+
|
|
74
|
+
// Show help if requested
|
|
75
|
+
if (hasHelp) {
|
|
76
|
+
console.log(` ${yellow}Usage:${reset} npx momentum-framework [options]
|
|
77
|
+
|
|
78
|
+
${yellow}Options:${reset}
|
|
79
|
+
${cyan}-g, --global${reset} Install commands globally (to ~/.claude)
|
|
80
|
+
${cyan}-l, --local${reset} Install commands locally (to ./.claude)
|
|
81
|
+
${cyan}-w, --workspace${reset} Install workspace layer (.accel/momentum/ in current directory)
|
|
82
|
+
${cyan}-c, --config-dir <path>${reset} Specify custom Claude config directory
|
|
83
|
+
${cyan}--workspace-dir <path>${reset} Specify workspace root (default: cwd)
|
|
84
|
+
${cyan}-h, --help${reset} Show this help message
|
|
85
|
+
|
|
86
|
+
${yellow}Examples:${reset}
|
|
87
|
+
${dim}# Full install: global commands + workspace layer${reset}
|
|
88
|
+
npx momentum-framework --global --workspace
|
|
89
|
+
|
|
90
|
+
${dim}# Global commands only (no workspace data)${reset}
|
|
91
|
+
npx momentum-framework --global
|
|
92
|
+
|
|
93
|
+
${dim}# Workspace layer only (assumes commands already installed)${reset}
|
|
94
|
+
npx momentum-framework --workspace
|
|
95
|
+
|
|
96
|
+
${dim}# Install to current project only${reset}
|
|
97
|
+
npx momentum-framework --local --workspace
|
|
98
|
+
|
|
99
|
+
${yellow}What gets installed:${reset}
|
|
100
|
+
${cyan}Commands (--global or --local):${reset}
|
|
101
|
+
commands/momentum/ - Slash commands (/momentum:surface-create, etc.)
|
|
102
|
+
skills/momentum/ - Skill framework (tasks, templates, context)
|
|
103
|
+
|
|
104
|
+
${cyan}Workspace (--workspace):${reset}
|
|
105
|
+
.accel/momentum/data/ - JSON data surfaces (active, backlog, projects, entities, state)
|
|
106
|
+
.accel/momentum/hooks/ - All hooks (surface + session + command)
|
|
107
|
+
.accel/momentum/momentum-mcp/ - Momentum MCP server (npm install auto-runs)
|
|
108
|
+
.accel/momentum/workspace.json - Workspace manifest
|
|
109
|
+
.accel/momentum/operator.json - Operator profile (guided setup via /momentum:scaffold)
|
|
110
|
+
.mcp.json - MCP server registration (merged)
|
|
111
|
+
`);
|
|
112
|
+
process.exit(0);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Expand ~ to home directory
|
|
117
|
+
*/
|
|
118
|
+
function expandTilde(filePath) {
|
|
119
|
+
if (filePath && filePath.startsWith('~/')) {
|
|
120
|
+
return path.join(os.homedir(), filePath.slice(2));
|
|
121
|
+
}
|
|
122
|
+
return filePath;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Recursively copy directory
|
|
127
|
+
*/
|
|
128
|
+
function copyDir(srcDir, destDir) {
|
|
129
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
130
|
+
const entries = fs.readdirSync(srcDir, { withFileTypes: true });
|
|
131
|
+
for (const entry of entries) {
|
|
132
|
+
const srcPath = path.join(srcDir, entry.name);
|
|
133
|
+
const destPath = path.join(destDir, entry.name);
|
|
134
|
+
if (entry.isDirectory()) {
|
|
135
|
+
copyDir(srcPath, destPath);
|
|
136
|
+
} else {
|
|
137
|
+
fs.copyFileSync(srcPath, destPath);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Write JSON file only if it doesn't already exist
|
|
144
|
+
*/
|
|
145
|
+
function writeJsonIfNew(filePath, data) {
|
|
146
|
+
if (!fs.existsSync(filePath)) {
|
|
147
|
+
fs.writeFileSync(filePath, JSON.stringify(data, null, 2));
|
|
148
|
+
return true;
|
|
149
|
+
}
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Detect v1/v2 artifacts that need migration.
|
|
155
|
+
* Returns array of { path, label, type } objects.
|
|
156
|
+
* Does NOT modify anything — detection only.
|
|
157
|
+
*/
|
|
158
|
+
function detectV1Artifacts(claudeDir, workspaceDir) {
|
|
159
|
+
const found = [];
|
|
160
|
+
|
|
161
|
+
if (workspaceDir) {
|
|
162
|
+
// vector-mcp in .accel/momentum/ (no longer ships with Momentum)
|
|
163
|
+
const vectorMcpDir = path.join(workspaceDir, '.accel/momentum', 'vector-mcp');
|
|
164
|
+
if (fs.existsSync(vectorMcpDir)) {
|
|
165
|
+
found.push({
|
|
166
|
+
path: vectorMcpDir,
|
|
167
|
+
label: '.accel/momentum/vector-mcp/',
|
|
168
|
+
reason: 'Vector MCP no longer ships with Momentum — install vector-core separately',
|
|
169
|
+
type: 'directory'
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Session hooks in .claude/hooks/ that moved to .accel/momentum/hooks/
|
|
174
|
+
const movedHooks = ['momentum-pulse-check.py', 'psmm-injector.py', 'satellite-detection.py'];
|
|
175
|
+
const claudeHooksDir = path.join(workspaceDir, '.claude', 'hooks');
|
|
176
|
+
if (fs.existsSync(claudeHooksDir)) {
|
|
177
|
+
for (const hook of movedHooks) {
|
|
178
|
+
const hookPath = path.join(claudeHooksDir, hook);
|
|
179
|
+
if (fs.existsSync(hookPath)) {
|
|
180
|
+
found.push({
|
|
181
|
+
path: hookPath,
|
|
182
|
+
label: `.claude/hooks/${hook}`,
|
|
183
|
+
reason: 'Hooks now live in .accel/momentum/hooks/ — duplicate here causes double-fire',
|
|
184
|
+
type: 'file'
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// v2-suffixed hook files in .accel/momentum/hooks/ (now redundant — canonical names have v2 content)
|
|
191
|
+
const v2SuffixedHooks = ['active-hook-v2.py', 'backlog-hook-v2.py', 'momentum-pulse-check.py'];
|
|
192
|
+
const momentumHooksDir = path.join(workspaceDir, '.accel/momentum', 'hooks');
|
|
193
|
+
if (fs.existsSync(momentumHooksDir)) {
|
|
194
|
+
for (const hook of v2SuffixedHooks) {
|
|
195
|
+
const hookPath = path.join(momentumHooksDir, hook);
|
|
196
|
+
if (fs.existsSync(hookPath)) {
|
|
197
|
+
found.push({
|
|
198
|
+
path: hookPath,
|
|
199
|
+
label: `.accel/momentum/hooks/${hook}`,
|
|
200
|
+
reason: 'v2-suffixed duplicate — canonical name now has v2 content',
|
|
201
|
+
type: 'file'
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// Stale -v2 hook paths in .claude/settings.json
|
|
208
|
+
const settingsPath = path.join(workspaceDir, '.claude', 'settings.json');
|
|
209
|
+
if (fs.existsSync(settingsPath)) {
|
|
210
|
+
try {
|
|
211
|
+
const raw = fs.readFileSync(settingsPath, 'utf-8');
|
|
212
|
+
if (raw.includes('-v2.py')) {
|
|
213
|
+
found.push({
|
|
214
|
+
path: settingsPath,
|
|
215
|
+
label: '.claude/settings.json → stale -v2 hook paths',
|
|
216
|
+
reason: 'Hook paths reference -v2.py files that are now archived — will rewrite to canonical names',
|
|
217
|
+
type: 'settings-v2-paths'
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
} catch (e) { /* skip */ }
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// vector-mcp entry in .mcp.json
|
|
224
|
+
const mcpJsonPath = path.join(workspaceDir, '.mcp.json');
|
|
225
|
+
if (fs.existsSync(mcpJsonPath)) {
|
|
226
|
+
try {
|
|
227
|
+
const mcpConfig = JSON.parse(fs.readFileSync(mcpJsonPath, 'utf-8'));
|
|
228
|
+
if (mcpConfig.mcpServers && mcpConfig.mcpServers['vector-mcp']) {
|
|
229
|
+
found.push({
|
|
230
|
+
path: mcpJsonPath,
|
|
231
|
+
label: '.mcp.json → vector-mcp entry',
|
|
232
|
+
reason: 'Vector MCP no longer registered by Momentum — install vector-core for Vector MCP',
|
|
233
|
+
type: 'mcp-entry'
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
} catch (e) { /* skip */ }
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Old markdown templates in momentum-framework/
|
|
241
|
+
if (claudeDir) {
|
|
242
|
+
const oldTemplates = ['active-md.md', 'backlog-md.md', 'state-md.md'];
|
|
243
|
+
const templatesDir = path.join(claudeDir, 'momentum-framework', 'templates');
|
|
244
|
+
if (fs.existsSync(templatesDir)) {
|
|
245
|
+
for (const tmpl of oldTemplates) {
|
|
246
|
+
const tmplPath = path.join(templatesDir, tmpl);
|
|
247
|
+
if (fs.existsSync(tmplPath)) {
|
|
248
|
+
found.push({
|
|
249
|
+
path: tmplPath,
|
|
250
|
+
label: `momentum-framework/templates/${tmpl}`,
|
|
251
|
+
reason: 'Replaced by JSON templates in v3 — no longer used by scaffold',
|
|
252
|
+
type: 'file'
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
return found;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Archive a single artifact (file or directory) to .accel/momentum/_archive/upgrade-v3/
|
|
264
|
+
*/
|
|
265
|
+
function archiveArtifact(artifact, archiveDir) {
|
|
266
|
+
fs.mkdirSync(archiveDir, { recursive: true });
|
|
267
|
+
|
|
268
|
+
if (artifact.type === 'directory') {
|
|
269
|
+
const destName = path.basename(artifact.path);
|
|
270
|
+
const destPath = path.join(archiveDir, destName);
|
|
271
|
+
copyDir(artifact.path, destPath);
|
|
272
|
+
fs.rmSync(artifact.path, { recursive: true });
|
|
273
|
+
} else if (artifact.type === 'file') {
|
|
274
|
+
const destPath = path.join(archiveDir, path.basename(artifact.path));
|
|
275
|
+
fs.copyFileSync(artifact.path, destPath);
|
|
276
|
+
fs.unlinkSync(artifact.path);
|
|
277
|
+
} else if (artifact.type === 'mcp-entry') {
|
|
278
|
+
// For MCP entries, remove the key from JSON
|
|
279
|
+
const mcpConfig = JSON.parse(fs.readFileSync(artifact.path, 'utf-8'));
|
|
280
|
+
delete mcpConfig.mcpServers['vector-mcp'];
|
|
281
|
+
fs.writeFileSync(artifact.path, JSON.stringify(mcpConfig, null, 2));
|
|
282
|
+
} else if (artifact.type === 'settings-v2-paths') {
|
|
283
|
+
// Rewrite -v2.py hook paths to canonical names in settings.json
|
|
284
|
+
let raw = fs.readFileSync(artifact.path, 'utf-8');
|
|
285
|
+
raw = raw.replace(/active-hook-v2\.py/g, 'active-hook.py');
|
|
286
|
+
raw = raw.replace(/backlog-hook-v2\.py/g, 'backlog-hook.py');
|
|
287
|
+
raw = raw.replace(/momentum-pulse-check-v2\.py/g, 'momentum-pulse-check.py');
|
|
288
|
+
fs.writeFileSync(artifact.path, raw);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Run upgrade cleanup interactively.
|
|
294
|
+
* Detects v1/v2 artifacts, warns the user, prompts for confirmation, archives.
|
|
295
|
+
* Returns a promise that resolves when cleanup is complete or skipped.
|
|
296
|
+
*/
|
|
297
|
+
function runUpgradeCleanup(claudeDir, workspaceDir) {
|
|
298
|
+
const artifacts = detectV1Artifacts(claudeDir, workspaceDir);
|
|
299
|
+
if (artifacts.length === 0) return Promise.resolve();
|
|
300
|
+
|
|
301
|
+
const momentumDir = workspaceDir ? path.join(workspaceDir, '.accel/momentum') : path.join(process.cwd(), '.accel/momentum');
|
|
302
|
+
const archiveDir = path.join(momentumDir, '_archive', 'upgrade-v3');
|
|
303
|
+
|
|
304
|
+
console.log(` ${yellow}=== UPGRADE DETECTED ===${reset}`);
|
|
305
|
+
console.log(` Found ${artifacts.length} artifact(s) from a previous Momentum version:\n`);
|
|
306
|
+
for (const a of artifacts) {
|
|
307
|
+
console.log(` ${yellow}!${reset} ${a.label}`);
|
|
308
|
+
console.log(` ${dim}${a.reason}${reset}`);
|
|
309
|
+
}
|
|
310
|
+
console.log(`\n ${dim}These will be archived to: ${archiveDir.replace(os.homedir(), '~')}${reset}`);
|
|
311
|
+
console.log(` ${dim}Nothing is deleted — you can recover from the archive.${reset}\n`);
|
|
312
|
+
|
|
313
|
+
return new Promise((resolve) => {
|
|
314
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
315
|
+
rl.question(` Archive these artifacts? ${dim}[Y/n]${reset}: `, (answer) => {
|
|
316
|
+
rl.close();
|
|
317
|
+
const proceed = !answer.trim() || answer.trim().toLowerCase() === 'y';
|
|
318
|
+
if (proceed) {
|
|
319
|
+
for (const a of artifacts) {
|
|
320
|
+
archiveArtifact(a, archiveDir);
|
|
321
|
+
console.log(` ${green}archived${reset} ${a.label}`);
|
|
322
|
+
}
|
|
323
|
+
console.log('');
|
|
324
|
+
} else {
|
|
325
|
+
console.log(` ${dim}Skipped cleanup. Old artifacts left in place.${reset}\n`);
|
|
326
|
+
}
|
|
327
|
+
resolve();
|
|
328
|
+
});
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* Install commands and skill framework
|
|
334
|
+
*/
|
|
335
|
+
function installCommands(isGlobal) {
|
|
336
|
+
const src = path.join(__dirname, '..');
|
|
337
|
+
const configDir = expandTilde(explicitConfigDir) || expandTilde(process.env.CLAUDE_CONFIG_DIR);
|
|
338
|
+
const defaultGlobalDir = configDir || path.join(os.homedir(), '.claude');
|
|
339
|
+
const claudeDir = isGlobal ? defaultGlobalDir : path.join(process.cwd(), '.claude');
|
|
340
|
+
|
|
341
|
+
const locationLabel = isGlobal
|
|
342
|
+
? claudeDir.replace(os.homedir(), '~')
|
|
343
|
+
: claudeDir.replace(process.cwd(), '.');
|
|
344
|
+
|
|
345
|
+
console.log(` Installing commands to ${cyan}${locationLabel}${reset}\n`);
|
|
346
|
+
|
|
347
|
+
// Copy commands
|
|
348
|
+
const commandsSrc = path.join(src, 'src', 'commands');
|
|
349
|
+
const commandsDest = path.join(claudeDir, 'commands', 'momentum');
|
|
350
|
+
copyDir(commandsSrc, commandsDest);
|
|
351
|
+
const commandCount = fs.readdirSync(commandsSrc).filter(f => f.endsWith('.md')).length;
|
|
352
|
+
console.log(` ${green}+${reset} commands/momentum/ (${commandCount} slash commands)`);
|
|
353
|
+
|
|
354
|
+
// Copy skill entry point
|
|
355
|
+
const skillSrc = path.join(src, 'src', 'skill');
|
|
356
|
+
const skillDest = path.join(claudeDir, 'skills', 'momentum');
|
|
357
|
+
copyDir(skillSrc, skillDest);
|
|
358
|
+
console.log(` ${green}+${reset} skills/momentum/ (entry point + MCP package sources)`);
|
|
359
|
+
|
|
360
|
+
// Copy MCP package sources into skill (for scaffold reference)
|
|
361
|
+
const packagesSrc = path.join(src, 'src', 'packages');
|
|
362
|
+
const packagesDest = path.join(claudeDir, 'skills', 'momentum', 'packages');
|
|
363
|
+
copyDir(packagesSrc, packagesDest);
|
|
364
|
+
|
|
365
|
+
// Copy Momentum framework (tasks, templates, context, frameworks)
|
|
366
|
+
const frameworkSrc = path.join(src, 'src', 'framework');
|
|
367
|
+
const frameworkDest = path.join(claudeDir, 'momentum-framework');
|
|
368
|
+
copyDir(frameworkSrc, frameworkDest);
|
|
369
|
+
console.log(` ${green}+${reset} momentum-framework/ (tasks, templates, context, frameworks, utils)`);
|
|
370
|
+
|
|
371
|
+
// Copy all hooks to momentum-framework/hooks/ (source for scaffold)
|
|
372
|
+
const hooksFrameworkDest = path.join(claudeDir, 'momentum-framework', 'hooks');
|
|
373
|
+
fs.mkdirSync(hooksFrameworkDest, { recursive: true });
|
|
374
|
+
const hooksSrcDir = path.join(src, 'src', 'hooks');
|
|
375
|
+
const hookFiles = fs.readdirSync(hooksSrcDir).filter(f => f.endsWith('.py'));
|
|
376
|
+
for (const hookFile of hookFiles) {
|
|
377
|
+
fs.copyFileSync(path.join(hooksSrcDir, hookFile), path.join(hooksFrameworkDest, hookFile));
|
|
378
|
+
}
|
|
379
|
+
console.log(` ${green}+${reset} momentum-framework/hooks/ (${hookFiles.length} hooks for scaffold)`);
|
|
380
|
+
|
|
381
|
+
console.log(`\n ${green}Commands installed.${reset}\n`);
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* Install workspace layer (.accel/momentum/)
|
|
386
|
+
*/
|
|
387
|
+
function installWorkspace() {
|
|
388
|
+
const src = path.join(__dirname, '..');
|
|
389
|
+
const workspaceDir = expandTilde(explicitWorkspaceDir) || process.cwd();
|
|
390
|
+
const momentumDir = path.join(workspaceDir, '.accel/momentum');
|
|
391
|
+
|
|
392
|
+
console.log(` Installing workspace layer to ${cyan}${momentumDir.replace(os.homedir(), '~')}${reset}\n`);
|
|
393
|
+
|
|
394
|
+
// Create .accel/momentum directories
|
|
395
|
+
fs.mkdirSync(path.join(momentumDir, 'data'), { recursive: true });
|
|
396
|
+
fs.mkdirSync(path.join(momentumDir, 'hooks'), { recursive: true });
|
|
397
|
+
console.log(` ${green}+${reset} .accel/momentum/data/`);
|
|
398
|
+
console.log(` ${green}+${reset} .accel/momentum/hooks/`);
|
|
399
|
+
|
|
400
|
+
// Initialize JSON data surfaces (don't overwrite existing)
|
|
401
|
+
const dataSurfaces = {
|
|
402
|
+
'active.json': { items: [], last_updated: null },
|
|
403
|
+
'backlog.json': { items: [], last_updated: null },
|
|
404
|
+
'projects.json': { projects: [], last_updated: null },
|
|
405
|
+
'entities.json': { entities: [], last_updated: null },
|
|
406
|
+
'state.json': { drift_score: 0, areas: {}, last_groom: null, last_updated: null },
|
|
407
|
+
'psmm.json': { sessions: {} }
|
|
408
|
+
};
|
|
409
|
+
let surfaceCount = 0;
|
|
410
|
+
for (const [filename, data] of Object.entries(dataSurfaces)) {
|
|
411
|
+
if (writeJsonIfNew(path.join(momentumDir, 'data', filename), data)) {
|
|
412
|
+
surfaceCount++;
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
if (surfaceCount > 0) {
|
|
416
|
+
console.log(` ${green}+${reset} .accel/momentum/data/ (${surfaceCount} JSON surfaces initialized)`);
|
|
417
|
+
} else {
|
|
418
|
+
console.log(` ${dim} .accel/momentum/data/ (existing surfaces preserved)${reset}`);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
// Copy workspace.json template (don't overwrite existing)
|
|
422
|
+
const workspaceJsonDest = path.join(momentumDir, 'workspace.json');
|
|
423
|
+
if (!fs.existsSync(workspaceJsonDest)) {
|
|
424
|
+
const templateSrc = path.join(src, 'src', 'templates', 'workspace.json');
|
|
425
|
+
if (fs.existsSync(templateSrc)) {
|
|
426
|
+
const template = JSON.parse(fs.readFileSync(templateSrc, 'utf-8'));
|
|
427
|
+
template.workspace = path.basename(workspaceDir);
|
|
428
|
+
template.created = new Date().toISOString().split('T')[0];
|
|
429
|
+
fs.writeFileSync(workspaceJsonDest, JSON.stringify(template, null, 2));
|
|
430
|
+
console.log(` ${green}+${reset} .accel/momentum/workspace.json (manifest)`);
|
|
431
|
+
}
|
|
432
|
+
} else {
|
|
433
|
+
console.log(` ${dim} .accel/momentum/workspace.json (existing manifest preserved)${reset}`);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
// Copy operator.json template (don't overwrite existing)
|
|
437
|
+
const operatorJsonDest = path.join(momentumDir, 'operator.json');
|
|
438
|
+
if (!fs.existsSync(operatorJsonDest)) {
|
|
439
|
+
const operatorSrc = path.join(src, 'src', 'templates', 'operator.json');
|
|
440
|
+
if (fs.existsSync(operatorSrc)) {
|
|
441
|
+
fs.copyFileSync(operatorSrc, operatorJsonDest);
|
|
442
|
+
console.log(` ${green}+${reset} .accel/momentum/operator.json (operator profile — complete via /momentum:scaffold)`);
|
|
443
|
+
}
|
|
444
|
+
} else {
|
|
445
|
+
console.log(` ${dim} .accel/momentum/operator.json (existing profile preserved)${reset}`);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
// Copy momentum-mcp
|
|
449
|
+
const mcpSrc = path.join(src, 'src', 'packages', 'momentum-mcp');
|
|
450
|
+
const mcpDest = path.join(momentumDir, 'momentum-mcp');
|
|
451
|
+
copyDir(mcpSrc, mcpDest);
|
|
452
|
+
console.log(` ${green}+${reset} .accel/momentum/momentum-mcp/`);
|
|
453
|
+
|
|
454
|
+
// Copy all hooks to .accel/momentum/hooks/
|
|
455
|
+
const allHooksSrc = path.join(src, 'src', 'hooks');
|
|
456
|
+
const hookEntries = fs.readdirSync(allHooksSrc).filter(f => f.endsWith('.py'));
|
|
457
|
+
for (const file of hookEntries) {
|
|
458
|
+
fs.copyFileSync(path.join(allHooksSrc, file), path.join(momentumDir, 'hooks', file));
|
|
459
|
+
}
|
|
460
|
+
console.log(` ${green}+${reset} .accel/momentum/hooks/ (${hookEntries.length} hooks)`);
|
|
461
|
+
|
|
462
|
+
// npm install for momentum-mcp
|
|
463
|
+
console.log(`\n Installing MCP dependencies...`);
|
|
464
|
+
try {
|
|
465
|
+
execSync('npm install', { cwd: mcpDest, stdio: 'pipe' });
|
|
466
|
+
console.log(` ${green}+${reset} momentum-mcp dependencies installed`);
|
|
467
|
+
} catch (e) {
|
|
468
|
+
console.log(` ${yellow}!${reset} momentum-mcp npm install failed — run manually in .accel/momentum/momentum-mcp/`);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
// Merge MCP registration into .mcp.json
|
|
472
|
+
const mcpJsonPath = path.join(workspaceDir, '.mcp.json');
|
|
473
|
+
let mcpConfig = { mcpServers: {} };
|
|
474
|
+
if (fs.existsSync(mcpJsonPath)) {
|
|
475
|
+
try {
|
|
476
|
+
mcpConfig = JSON.parse(fs.readFileSync(mcpJsonPath, 'utf-8'));
|
|
477
|
+
} catch (e) { /* start fresh */ }
|
|
478
|
+
}
|
|
479
|
+
mcpConfig.mcpServers['momentum-mcp'] = {
|
|
480
|
+
type: 'stdio',
|
|
481
|
+
command: 'node',
|
|
482
|
+
args: ['./.accel/momentum/momentum-mcp/index.js']
|
|
483
|
+
};
|
|
484
|
+
fs.writeFileSync(mcpJsonPath, JSON.stringify(mcpConfig, null, 2));
|
|
485
|
+
console.log(` ${green}+${reset} .mcp.json (momentum-mcp registered)`);
|
|
486
|
+
|
|
487
|
+
console.log(`\n ${green}Workspace layer installed.${reset}`);
|
|
488
|
+
console.log(` Run ${cyan}/momentum:scaffold${reset} to complete setup (hook wiring, operator profile).\n`);
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* Prompt for install location
|
|
493
|
+
*/
|
|
494
|
+
function promptLocation() {
|
|
495
|
+
const rl = readline.createInterface({
|
|
496
|
+
input: process.stdin,
|
|
497
|
+
output: process.stdout
|
|
498
|
+
});
|
|
499
|
+
|
|
500
|
+
const configDir = expandTilde(explicitConfigDir) || expandTilde(process.env.CLAUDE_CONFIG_DIR);
|
|
501
|
+
const globalPath = configDir || path.join(os.homedir(), '.claude');
|
|
502
|
+
const globalLabel = globalPath.replace(os.homedir(), '~');
|
|
503
|
+
|
|
504
|
+
console.log(` ${yellow}What would you like to install?${reset}
|
|
505
|
+
|
|
506
|
+
${cyan}1${reset}) Full install ${dim}(commands to ${globalLabel} + workspace layer to .accel/momentum/)${reset}
|
|
507
|
+
${cyan}2${reset}) Commands only ${dim}(${globalLabel})${reset}
|
|
508
|
+
${cyan}3${reset}) Workspace only ${dim}(.accel/momentum/ in current directory)${reset}
|
|
509
|
+
`);
|
|
510
|
+
|
|
511
|
+
rl.question(` Choice ${dim}[1]${reset}: `, (answer) => {
|
|
512
|
+
rl.close();
|
|
513
|
+
const choice = answer.trim() || '1';
|
|
514
|
+
if (choice === '1' || choice === '2') {
|
|
515
|
+
installCommands(true);
|
|
516
|
+
}
|
|
517
|
+
if (choice === '1' || choice === '3') {
|
|
518
|
+
installWorkspace();
|
|
519
|
+
}
|
|
520
|
+
if (choice !== '1' && choice !== '2' && choice !== '3') {
|
|
521
|
+
installCommands(true);
|
|
522
|
+
installWorkspace();
|
|
523
|
+
}
|
|
524
|
+
console.log(` ${green}Done!${reset} Launch Claude Code and run ${cyan}/momentum:scaffold${reset} to complete setup.\n`);
|
|
525
|
+
});
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
// Main
|
|
529
|
+
async function main() {
|
|
530
|
+
if (hasHelp) {
|
|
531
|
+
return; // Already handled above
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
if (hasGlobal || hasLocal || hasWorkspace) {
|
|
535
|
+
if (hasGlobal && hasLocal) {
|
|
536
|
+
console.error(` ${yellow}Cannot specify both --global and --local${reset}`);
|
|
537
|
+
process.exit(1);
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
// Detect and offer cleanup of v1/v2 artifacts before installing
|
|
541
|
+
const configDir = expandTilde(explicitConfigDir) || expandTilde(process.env.CLAUDE_CONFIG_DIR);
|
|
542
|
+
const cleanupClaudeDir = (hasGlobal || hasLocal)
|
|
543
|
+
? (hasGlobal ? (configDir || path.join(os.homedir(), '.claude')) : path.join(process.cwd(), '.claude'))
|
|
544
|
+
: null;
|
|
545
|
+
const cleanupWorkspaceDir = hasWorkspace
|
|
546
|
+
? (expandTilde(explicitWorkspaceDir) || process.cwd())
|
|
547
|
+
: null;
|
|
548
|
+
|
|
549
|
+
await runUpgradeCleanup(cleanupClaudeDir, cleanupWorkspaceDir);
|
|
550
|
+
|
|
551
|
+
if (hasGlobal || hasLocal) {
|
|
552
|
+
installCommands(hasGlobal);
|
|
553
|
+
}
|
|
554
|
+
if (hasWorkspace) {
|
|
555
|
+
installWorkspace();
|
|
556
|
+
}
|
|
557
|
+
console.log(` ${green}Done!${reset} Launch Claude Code and run ${cyan}/momentum:scaffold${reset} to complete setup.\n`);
|
|
558
|
+
} else {
|
|
559
|
+
promptLocation();
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
main();
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Momentum Integration — consumes events from Drive and Radar
|
|
3
|
+
*
|
|
4
|
+
* Integration points:
|
|
5
|
+
* 1. Drive -> Momentum: Consumes `phase-progress` events to update workspace state.
|
|
6
|
+
* 2. Radar -> Momentum: Consumes `audit-complete` events to create backlog items
|
|
7
|
+
* for audit findings that need remediation.
|
|
8
|
+
*
|
|
9
|
+
* Event schemas consumed:
|
|
10
|
+
* - shared/events/schemas/phase-progress.schema.json (from Drive)
|
|
11
|
+
* - shared/events/schemas/audit-complete.schema.json (from Radar)
|
|
12
|
+
*
|
|
13
|
+
* Usage inside Momentum's hook or pulse check:
|
|
14
|
+
* const integration = require('./integration');
|
|
15
|
+
* const { stateUpdates, backlogItems } = integration.processIncomingEvents();
|
|
16
|
+
*
|
|
17
|
+
* @module modules/momentum/integration
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
const eventBus = require('../../shared/events/event-bus');
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Consume pending phase-progress events emitted by Drive.
|
|
24
|
+
*
|
|
25
|
+
* Returns raw events so Momentum can update its workspace state surface
|
|
26
|
+
* (e.g. the "active" or "state" data surface).
|
|
27
|
+
*
|
|
28
|
+
* @returns {Array<{file: string, event: object}>} Array of phase-progress events
|
|
29
|
+
*/
|
|
30
|
+
function consumePhaseProgress() {
|
|
31
|
+
return eventBus.consume('momentum', ['phase-progress']);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Consume pending audit-complete events emitted by Radar.
|
|
36
|
+
*
|
|
37
|
+
* @returns {Array<{file: string, event: object}>} Array of audit-complete events
|
|
38
|
+
*/
|
|
39
|
+
function consumeAuditResults() {
|
|
40
|
+
return eventBus.consume('momentum', ['audit-complete']);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Convert a single audit-complete event payload into a Momentum backlog item.
|
|
45
|
+
*
|
|
46
|
+
* The backlog item follows the structure expected by Momentum's backlog
|
|
47
|
+
* data surface: an object with title, priority, source, and metadata.
|
|
48
|
+
*
|
|
49
|
+
* @param {object} auditPayload - The event payload from an audit-complete event
|
|
50
|
+
* @param {number} auditPayload.findings - Total findings count
|
|
51
|
+
* @param {number} auditPayload.critical - Critical findings count
|
|
52
|
+
* @param {string} auditPayload.report - Path to the audit report
|
|
53
|
+
* @returns {object} A backlog item ready for insertion into the backlog surface
|
|
54
|
+
*/
|
|
55
|
+
function auditToBacklogItem(auditPayload) {
|
|
56
|
+
const { findings, critical, report } = auditPayload;
|
|
57
|
+
|
|
58
|
+
const priority = critical > 0 ? 'critical' : findings > 5 ? 'high' : 'normal';
|
|
59
|
+
|
|
60
|
+
return {
|
|
61
|
+
title: `Radar audit: ${findings} finding(s), ${critical} critical`,
|
|
62
|
+
priority,
|
|
63
|
+
source: 'radar',
|
|
64
|
+
status: 'pending',
|
|
65
|
+
createdAt: new Date().toISOString(),
|
|
66
|
+
metadata: {
|
|
67
|
+
findings,
|
|
68
|
+
critical,
|
|
69
|
+
report,
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Convert a phase-progress event payload into a workspace state update.
|
|
76
|
+
*
|
|
77
|
+
* @param {object} progressPayload - The event payload from a phase-progress event
|
|
78
|
+
* @param {string} progressPayload.phase - Phase name
|
|
79
|
+
* @param {string} progressPayload.status - Phase status
|
|
80
|
+
* @param {string} [progressPayload.planPath] - Path to the plan
|
|
81
|
+
* @param {number} [progressPayload.completedTasks] - Completed task count
|
|
82
|
+
* @param {number} [progressPayload.totalTasks] - Total task count
|
|
83
|
+
* @returns {object} A state update object for Momentum's state surface
|
|
84
|
+
*/
|
|
85
|
+
function progressToStateUpdate(progressPayload) {
|
|
86
|
+
const { phase, status, planPath, completedTasks, totalTasks } = progressPayload;
|
|
87
|
+
|
|
88
|
+
return {
|
|
89
|
+
surface: 'state',
|
|
90
|
+
key: `drive.${phase.replace(/\s+/g, '_').toLowerCase()}`,
|
|
91
|
+
value: {
|
|
92
|
+
phase,
|
|
93
|
+
status,
|
|
94
|
+
planPath: planPath || null,
|
|
95
|
+
completedTasks: completedTasks || 0,
|
|
96
|
+
totalTasks: totalTasks || 0,
|
|
97
|
+
updatedAt: new Date().toISOString(),
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Process all incoming events in one pass.
|
|
104
|
+
*
|
|
105
|
+
* This is the primary entry point for Momentum's integration layer.
|
|
106
|
+
* Call it during Momentum's hook execution or pulse check to:
|
|
107
|
+
* 1. Pull phase-progress events and build state updates
|
|
108
|
+
* 2. Pull audit-complete events and build backlog items
|
|
109
|
+
*
|
|
110
|
+
* @returns {{
|
|
111
|
+
* stateUpdates: Array<object>,
|
|
112
|
+
* backlogItems: Array<object>
|
|
113
|
+
* }}
|
|
114
|
+
*/
|
|
115
|
+
function processIncomingEvents() {
|
|
116
|
+
const progressEvents = consumePhaseProgress();
|
|
117
|
+
const auditEvents = consumeAuditResults();
|
|
118
|
+
|
|
119
|
+
const stateUpdates = progressEvents.map((e) => progressToStateUpdate(e.event.payload));
|
|
120
|
+
const backlogItems = auditEvents.map((e) => auditToBacklogItem(e.event.payload));
|
|
121
|
+
|
|
122
|
+
return { stateUpdates, backlogItems };
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
module.exports = {
|
|
126
|
+
consumePhaseProgress,
|
|
127
|
+
consumeAuditResults,
|
|
128
|
+
auditToBacklogItem,
|
|
129
|
+
progressToStateUpdate,
|
|
130
|
+
processIncomingEvents,
|
|
131
|
+
};
|