@slope-dev/slope 1.64.1 → 2.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 +4 -0
- package/dist/cli/commands/agent.d.ts +3 -3
- package/dist/cli/commands/agent.d.ts.map +1 -1
- package/dist/cli/commands/agent.js +20 -12
- package/dist/cli/commands/agent.js.map +1 -1
- package/dist/cli/commands/auto-card.d.ts +2 -1
- package/dist/cli/commands/auto-card.d.ts.map +1 -1
- package/dist/cli/commands/auto-card.js +7 -7
- package/dist/cli/commands/auto-card.js.map +1 -1
- package/dist/cli/commands/briefing.d.ts.map +1 -1
- package/dist/cli/commands/briefing.js +16 -9
- package/dist/cli/commands/briefing.js.map +1 -1
- package/dist/cli/commands/claim.d.ts.map +1 -1
- package/dist/cli/commands/claim.js +6 -4
- package/dist/cli/commands/claim.js.map +1 -1
- package/dist/cli/commands/commit-ready.d.ts.map +1 -1
- package/dist/cli/commands/commit-ready.js.map +1 -1
- package/dist/cli/commands/context.d.ts.map +1 -1
- package/dist/cli/commands/context.js +2 -1
- package/dist/cli/commands/context.js.map +1 -1
- package/dist/cli/commands/dashboard.d.ts.map +1 -1
- package/dist/cli/commands/dashboard.js +3 -3
- package/dist/cli/commands/dashboard.js.map +1 -1
- package/dist/cli/commands/distill.d.ts.map +1 -1
- package/dist/cli/commands/distill.js +8 -20
- package/dist/cli/commands/distill.js.map +1 -1
- package/dist/cli/commands/enrich.d.ts.map +1 -1
- package/dist/cli/commands/enrich.js +2 -1
- package/dist/cli/commands/enrich.js.map +1 -1
- package/dist/cli/commands/escalate.d.ts.map +1 -1
- package/dist/cli/commands/escalate.js +11 -3
- package/dist/cli/commands/escalate.js.map +1 -1
- package/dist/cli/commands/extract.d.ts.map +1 -1
- package/dist/cli/commands/extract.js +20 -6
- package/dist/cli/commands/extract.js.map +1 -1
- package/dist/cli/commands/gate.d.ts.map +1 -1
- package/dist/cli/commands/gate.js +10 -7
- package/dist/cli/commands/gate.js.map +1 -1
- package/dist/cli/commands/index-cmd.d.ts.map +1 -1
- package/dist/cli/commands/index-cmd.js +2 -1
- package/dist/cli/commands/index-cmd.js.map +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +26 -12
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/initiative.d.ts.map +1 -1
- package/dist/cli/commands/initiative.js +9 -8
- package/dist/cli/commands/initiative.js.map +1 -1
- package/dist/cli/commands/inspirations.js +5 -5
- package/dist/cli/commands/inspirations.js.map +1 -1
- package/dist/cli/commands/interview.d.ts.map +1 -1
- package/dist/cli/commands/interview.js +2 -2
- package/dist/cli/commands/interview.js.map +1 -1
- package/dist/cli/commands/issue.d.ts.map +1 -1
- package/dist/cli/commands/issue.js +6 -9
- package/dist/cli/commands/issue.js.map +1 -1
- package/dist/cli/commands/map.d.ts +1 -1
- package/dist/cli/commands/map.d.ts.map +1 -1
- package/dist/cli/commands/map.js +34 -10
- package/dist/cli/commands/map.js.map +1 -1
- package/dist/cli/commands/next.js +2 -2
- package/dist/cli/commands/next.js.map +1 -1
- package/dist/cli/commands/now.d.ts +2 -2
- package/dist/cli/commands/now.d.ts.map +1 -1
- package/dist/cli/commands/now.js +23 -15
- package/dist/cli/commands/now.js.map +1 -1
- package/dist/cli/commands/pr.d.ts +3 -3
- package/dist/cli/commands/pr.d.ts.map +1 -1
- package/dist/cli/commands/pr.js +9 -8
- package/dist/cli/commands/pr.js.map +1 -1
- package/dist/cli/commands/prep.d.ts.map +1 -1
- package/dist/cli/commands/prep.js +2 -1
- package/dist/cli/commands/prep.js.map +1 -1
- package/dist/cli/commands/release.d.ts.map +1 -1
- package/dist/cli/commands/release.js +9 -11
- package/dist/cli/commands/release.js.map +1 -1
- package/dist/cli/commands/retro.d.ts +1 -1
- package/dist/cli/commands/retro.d.ts.map +1 -1
- package/dist/cli/commands/retro.js +35 -11
- package/dist/cli/commands/retro.js.map +1 -1
- package/dist/cli/commands/review-packet.d.ts +2 -2
- package/dist/cli/commands/review-packet.d.ts.map +1 -1
- package/dist/cli/commands/review-packet.js +3 -3
- package/dist/cli/commands/review-packet.js.map +1 -1
- package/dist/cli/commands/review-run.d.ts +3 -2
- package/dist/cli/commands/review-run.d.ts.map +1 -1
- package/dist/cli/commands/review-run.js +4 -4
- package/dist/cli/commands/review-run.js.map +1 -1
- package/dist/cli/commands/review-state.d.ts.map +1 -1
- package/dist/cli/commands/review-state.js +57 -30
- package/dist/cli/commands/review-state.js.map +1 -1
- package/dist/cli/commands/review.js +6 -6
- package/dist/cli/commands/review.js.map +1 -1
- package/dist/cli/commands/roadmap.d.ts.map +1 -1
- package/dist/cli/commands/roadmap.js +138 -78
- package/dist/cli/commands/roadmap.js.map +1 -1
- package/dist/cli/commands/session.d.ts.map +1 -1
- package/dist/cli/commands/session.js +47 -16
- package/dist/cli/commands/session.js.map +1 -1
- package/dist/cli/commands/sprint-plan.d.ts.map +1 -1
- package/dist/cli/commands/sprint-plan.js +10 -8
- package/dist/cli/commands/sprint-plan.js.map +1 -1
- package/dist/cli/commands/sprint.d.ts.map +1 -1
- package/dist/cli/commands/sprint.js +253 -38
- package/dist/cli/commands/sprint.js.map +1 -1
- package/dist/cli/commands/standup.d.ts.map +1 -1
- package/dist/cli/commands/standup.js +9 -4
- package/dist/cli/commands/standup.js.map +1 -1
- package/dist/cli/commands/start.js +2 -2
- package/dist/cli/commands/start.js.map +1 -1
- package/dist/cli/commands/stats.d.ts +4 -4
- package/dist/cli/commands/stats.d.ts.map +1 -1
- package/dist/cli/commands/stats.js +5 -5
- package/dist/cli/commands/stats.js.map +1 -1
- package/dist/cli/commands/status.d.ts +1 -1
- package/dist/cli/commands/status.d.ts.map +1 -1
- package/dist/cli/commands/status.js +12 -8
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/commands/store.d.ts +37 -0
- package/dist/cli/commands/store.d.ts.map +1 -1
- package/dist/cli/commands/store.js +262 -12
- package/dist/cli/commands/store.js.map +1 -1
- package/dist/cli/commands/ticket.d.ts.map +1 -1
- package/dist/cli/commands/ticket.js +4 -4
- package/dist/cli/commands/ticket.js.map +1 -1
- package/dist/cli/commands/tournament.d.ts.map +1 -1
- package/dist/cli/commands/tournament.js +7 -6
- package/dist/cli/commands/tournament.js.map +1 -1
- package/dist/cli/commands/validate.d.ts +4 -3
- package/dist/cli/commands/validate.d.ts.map +1 -1
- package/dist/cli/commands/validate.js +37 -10
- package/dist/cli/commands/validate.js.map +1 -1
- package/dist/cli/commands/version.d.ts +1 -1
- package/dist/cli/commands/version.d.ts.map +1 -1
- package/dist/cli/commands/version.js +13 -10
- package/dist/cli/commands/version.js.map +1 -1
- package/dist/cli/commands/worktree.d.ts.map +1 -1
- package/dist/cli/commands/worktree.js +36 -31
- package/dist/cli/commands/worktree.js.map +1 -1
- package/dist/cli/guards/claim-required.d.ts.map +1 -1
- package/dist/cli/guards/claim-required.js +2 -3
- package/dist/cli/guards/claim-required.js.map +1 -1
- package/dist/cli/guards/compaction.d.ts.map +1 -1
- package/dist/cli/guards/git-utils.d.ts +5 -0
- package/dist/cli/guards/git-utils.d.ts.map +1 -1
- package/dist/cli/guards/git-utils.js +36 -8
- package/dist/cli/guards/git-utils.js.map +1 -1
- package/dist/cli/guards/hazard.d.ts.map +1 -1
- package/dist/cli/guards/hazard.js +8 -7
- package/dist/cli/guards/hazard.js.map +1 -1
- package/dist/cli/guards/next-action.d.ts +5 -5
- package/dist/cli/guards/next-action.d.ts.map +1 -1
- package/dist/cli/guards/next-action.js +8 -8
- package/dist/cli/guards/next-action.js.map +1 -1
- package/dist/cli/guards/phase-boundary.d.ts.map +1 -1
- package/dist/cli/guards/phase-boundary.js +24 -14
- package/dist/cli/guards/phase-boundary.js.map +1 -1
- package/dist/cli/guards/post-hole-enforcement.d.ts.map +1 -1
- package/dist/cli/guards/post-hole-enforcement.js +9 -8
- package/dist/cli/guards/post-hole-enforcement.js.map +1 -1
- package/dist/cli/guards/post-push.d.ts.map +1 -1
- package/dist/cli/guards/post-push.js +7 -3
- package/dist/cli/guards/post-push.js.map +1 -1
- package/dist/cli/guards/review-stale.d.ts.map +1 -1
- package/dist/cli/guards/review-stale.js +6 -4
- package/dist/cli/guards/review-stale.js.map +1 -1
- package/dist/cli/guards/review-tier.d.ts.map +1 -1
- package/dist/cli/guards/review-tier.js +6 -7
- package/dist/cli/guards/review-tier.js.map +1 -1
- package/dist/cli/guards/roadmap-edit-shipped.d.ts.map +1 -1
- package/dist/cli/guards/roadmap-edit-shipped.js +34 -21
- package/dist/cli/guards/roadmap-edit-shipped.js.map +1 -1
- package/dist/cli/guards/scope-drift.d.ts.map +1 -1
- package/dist/cli/guards/scope-drift.js +2 -1
- package/dist/cli/guards/scope-drift.js.map +1 -1
- package/dist/cli/guards/session-briefing.d.ts.map +1 -1
- package/dist/cli/guards/session-briefing.js +34 -13
- package/dist/cli/guards/session-briefing.js.map +1 -1
- package/dist/cli/guards/sprint-completion.d.ts.map +1 -1
- package/dist/cli/guards/sprint-completion.js +32 -16
- package/dist/cli/guards/sprint-completion.js.map +1 -1
- package/dist/cli/guards/stop-check.d.ts.map +1 -1
- package/dist/cli/guards/stop-check.js +8 -10
- package/dist/cli/guards/stop-check.js.map +1 -1
- package/dist/cli/guards/transcript.d.ts.map +1 -1
- package/dist/cli/guards/transcript.js +2 -1
- package/dist/cli/guards/transcript.js.map +1 -1
- package/dist/cli/guards/workflow-step-gate.d.ts.map +1 -1
- package/dist/cli/guards/workflow-step-gate.js +25 -28
- package/dist/cli/guards/workflow-step-gate.js.map +1 -1
- package/dist/cli/guards/worktree-check.d.ts.map +1 -1
- package/dist/cli/guards/worktree-check.js +38 -13
- package/dist/cli/guards/worktree-check.js.map +1 -1
- package/dist/cli/hooks-config.d.ts.map +1 -1
- package/dist/cli/hooks-config.js +6 -4
- package/dist/cli/hooks-config.js.map +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/loop/executor.d.ts +1 -0
- package/dist/cli/loop/executor.d.ts.map +1 -1
- package/dist/cli/loop/executor.js +20 -13
- package/dist/cli/loop/executor.js.map +1 -1
- package/dist/cli/loop/pr-lifecycle.d.ts +2 -1
- package/dist/cli/loop/pr-lifecycle.d.ts.map +1 -1
- package/dist/cli/loop/pr-lifecycle.js +14 -8
- package/dist/cli/loop/pr-lifecycle.js.map +1 -1
- package/dist/cli/loop/worktree.d.ts.map +1 -1
- package/dist/cli/loop/worktree.js +1 -48
- package/dist/cli/loop/worktree.js.map +1 -1
- package/dist/cli/pr-closeout.d.ts +3 -2
- package/dist/cli/pr-closeout.d.ts.map +1 -1
- package/dist/cli/pr-closeout.js +14 -6
- package/dist/cli/pr-closeout.js.map +1 -1
- package/dist/cli/pr-review-state.d.ts +8 -7
- package/dist/cli/pr-review-state.d.ts.map +1 -1
- package/dist/cli/pr-review-state.js +3 -2
- package/dist/cli/pr-review-state.js.map +1 -1
- package/dist/cli/pre-sprint-reality.d.ts +4 -4
- package/dist/cli/pre-sprint-reality.d.ts.map +1 -1
- package/dist/cli/pre-sprint-reality.js +9 -2
- package/dist/cli/pre-sprint-reality.js.map +1 -1
- package/dist/cli/registries/api-registry.d.ts +2 -2
- package/dist/cli/registries/api-registry.d.ts.map +1 -1
- package/dist/cli/registries/api-registry.js +1 -1
- package/dist/cli/registries/api-registry.js.map +1 -1
- package/dist/cli/registries/file-registry.d.ts +3 -3
- package/dist/cli/registries/file-registry.d.ts.map +1 -1
- package/dist/cli/registries/file-registry.js +12 -2
- package/dist/cli/registries/file-registry.js.map +1 -1
- package/dist/cli/registries/index.d.ts +1 -1
- package/dist/cli/registries/index.d.ts.map +1 -1
- package/dist/cli/registries/index.js +2 -2
- package/dist/cli/registries/index.js.map +1 -1
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/cli/registry.js +4 -0
- package/dist/cli/registry.js.map +1 -1
- package/dist/cli/reviewer-agents.d.ts +2 -1
- package/dist/cli/reviewer-agents.d.ts.map +1 -1
- package/dist/cli/reviewer-agents.js.map +1 -1
- package/dist/cli/roadmap-source-migration.d.ts.map +1 -1
- package/dist/cli/roadmap-source-migration.js +15 -13
- package/dist/cli/roadmap-source-migration.js.map +1 -1
- package/dist/cli/roadmap-source-store.d.ts +4 -4
- package/dist/cli/roadmap-source-store.d.ts.map +1 -1
- package/dist/cli/roadmap-source-store.js +38 -32
- package/dist/cli/roadmap-source-store.js.map +1 -1
- package/dist/cli/session-heartbeat.d.ts +12 -0
- package/dist/cli/session-heartbeat.d.ts.map +1 -0
- package/dist/cli/session-heartbeat.js +46 -0
- package/dist/cli/session-heartbeat.js.map +1 -0
- package/dist/cli/session-scope.d.ts.map +1 -1
- package/dist/cli/session-scope.js +4 -16
- package/dist/cli/session-scope.js.map +1 -1
- package/dist/cli/session-state.js +5 -5
- package/dist/cli/session-state.js.map +1 -1
- package/dist/cli/sprint-inference.d.ts +5 -5
- package/dist/cli/sprint-inference.d.ts.map +1 -1
- package/dist/cli/sprint-inference.js +63 -33
- package/dist/cli/sprint-inference.js.map +1 -1
- package/dist/cli/sprint-resume.d.ts +7 -7
- package/dist/cli/sprint-resume.d.ts.map +1 -1
- package/dist/cli/sprint-resume.js +43 -21
- package/dist/cli/sprint-resume.js.map +1 -1
- package/dist/cli/sprint-rollover.d.ts +19 -19
- package/dist/cli/sprint-rollover.d.ts.map +1 -1
- package/dist/cli/sprint-rollover.js +116 -69
- package/dist/cli/sprint-rollover.js.map +1 -1
- package/dist/cli/sprint-state.d.ts +8 -6
- package/dist/cli/sprint-state.d.ts.map +1 -1
- package/dist/cli/sprint-state.js +39 -12
- package/dist/cli/sprint-state.js.map +1 -1
- package/dist/cli/store.d.ts.map +1 -1
- package/dist/cli/store.js +5 -3
- package/dist/cli/store.js.map +1 -1
- package/dist/cli/workflow-closeout.d.ts +11 -0
- package/dist/cli/workflow-closeout.d.ts.map +1 -0
- package/dist/cli/workflow-closeout.js +30 -0
- package/dist/cli/workflow-closeout.js.map +1 -0
- package/dist/cli/workflow-resync.d.ts +13 -9
- package/dist/cli/workflow-resync.d.ts.map +1 -1
- package/dist/cli/workflow-resync.js +75 -22
- package/dist/cli/workflow-resync.js.map +1 -1
- package/dist/core/advisor.d.ts.map +1 -1
- package/dist/core/advisor.js +5 -2
- package/dist/core/advisor.js.map +1 -1
- package/dist/core/analytics.d.ts +2 -2
- package/dist/core/analytics.d.ts.map +1 -1
- package/dist/core/analytics.js +4 -3
- package/dist/core/analytics.js.map +1 -1
- package/dist/core/analyzers/git.d.ts +3 -2
- package/dist/core/analyzers/git.d.ts.map +1 -1
- package/dist/core/analyzers/git.js +6 -5
- package/dist/core/analyzers/git.js.map +1 -1
- package/dist/core/briefing.d.ts +6 -5
- package/dist/core/briefing.d.ts.map +1 -1
- package/dist/core/briefing.js +52 -36
- package/dist/core/briefing.js.map +1 -1
- package/dist/core/builder.d.ts +3 -1
- package/dist/core/builder.d.ts.map +1 -1
- package/dist/core/builder.js +6 -4
- package/dist/core/builder.js.map +1 -1
- package/dist/core/config.d.ts +2 -1
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +26 -6
- package/dist/core/config.js.map +1 -1
- package/dist/core/dashboard.d.ts +2 -2
- package/dist/core/dashboard.d.ts.map +1 -1
- package/dist/core/dashboard.js +2 -1
- package/dist/core/dashboard.js.map +1 -1
- package/dist/core/deferred.d.ts +7 -6
- package/dist/core/deferred.d.ts.map +1 -1
- package/dist/core/deferred.js +30 -7
- package/dist/core/deferred.js.map +1 -1
- package/dist/core/enrich.d.ts +1 -1
- package/dist/core/escalation.d.ts +2 -1
- package/dist/core/escalation.d.ts.map +1 -1
- package/dist/core/escalation.js +3 -1
- package/dist/core/escalation.js.map +1 -1
- package/dist/core/event-ingestion.d.ts.map +1 -1
- package/dist/core/event-ingestion.js +8 -3
- package/dist/core/event-ingestion.js.map +1 -1
- package/dist/core/findings.d.ts +6 -4
- package/dist/core/findings.d.ts.map +1 -1
- package/dist/core/findings.js +30 -7
- package/dist/core/findings.js.map +1 -1
- package/dist/core/formatter.d.ts +2 -1
- package/dist/core/formatter.d.ts.map +1 -1
- package/dist/core/formatter.js.map +1 -1
- package/dist/core/generators/roadmap.js +2 -2
- package/dist/core/generators/roadmap.js.map +1 -1
- package/dist/core/index.d.ts +8 -5
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +4 -2
- package/dist/core/index.js.map +1 -1
- package/dist/core/initiative.d.ts +5 -4
- package/dist/core/initiative.d.ts.map +1 -1
- package/dist/core/initiative.js +39 -11
- package/dist/core/initiative.js.map +1 -1
- package/dist/core/inspirations.d.ts +4 -3
- package/dist/core/inspirations.d.ts.map +1 -1
- package/dist/core/inspirations.js +19 -4
- package/dist/core/inspirations.js.map +1 -1
- package/dist/core/interview-engine.d.ts +2 -1
- package/dist/core/interview-engine.d.ts.map +1 -1
- package/dist/core/interview-engine.js +26 -17
- package/dist/core/interview-engine.js.map +1 -1
- package/dist/core/interview-steps.d.ts.map +1 -1
- package/dist/core/interview-steps.js +7 -6
- package/dist/core/interview-steps.js.map +1 -1
- package/dist/core/interview.d.ts +2 -1
- package/dist/core/interview.d.ts.map +1 -1
- package/dist/core/interview.js +13 -7
- package/dist/core/interview.js.map +1 -1
- package/dist/core/issue-scout.d.ts +2 -1
- package/dist/core/issue-scout.d.ts.map +1 -1
- package/dist/core/issue-scout.js.map +1 -1
- package/dist/core/loader.d.ts +4 -4
- package/dist/core/loader.d.ts.map +1 -1
- package/dist/core/loader.js +71 -33
- package/dist/core/loader.js.map +1 -1
- package/dist/core/memory.d.ts.map +1 -1
- package/dist/core/memory.js +16 -6
- package/dist/core/memory.js.map +1 -1
- package/dist/core/org.d.ts +1 -1
- package/dist/core/org.d.ts.map +1 -1
- package/dist/core/org.js +2 -1
- package/dist/core/org.js.map +1 -1
- package/dist/core/pipeline.d.ts +1 -1
- package/dist/core/pipeline.d.ts.map +1 -1
- package/dist/core/pipeline.js +10 -6
- package/dist/core/pipeline.js.map +1 -1
- package/dist/core/player.d.ts.map +1 -1
- package/dist/core/player.js +2 -1
- package/dist/core/player.js.map +1 -1
- package/dist/core/prep.d.ts +3 -3
- package/dist/core/registry.d.ts +6 -2
- package/dist/core/registry.d.ts.map +1 -1
- package/dist/core/registry.js +2 -1
- package/dist/core/registry.js.map +1 -1
- package/dist/core/repo-state-scope.d.ts +27 -0
- package/dist/core/repo-state-scope.d.ts.map +1 -0
- package/dist/core/repo-state-scope.js +105 -0
- package/dist/core/repo-state-scope.js.map +1 -0
- package/dist/core/report.d.ts +1 -1
- package/dist/core/report.d.ts.map +1 -1
- package/dist/core/report.js +2 -1
- package/dist/core/report.js.map +1 -1
- package/dist/core/retro.d.ts +3 -2
- package/dist/core/retro.d.ts.map +1 -1
- package/dist/core/retro.js +6 -3
- package/dist/core/retro.js.map +1 -1
- package/dist/core/roadmap-focus.d.ts +8 -7
- package/dist/core/roadmap-focus.d.ts.map +1 -1
- package/dist/core/roadmap-focus.js +45 -34
- package/dist/core/roadmap-focus.js.map +1 -1
- package/dist/core/roadmap-migration.d.ts +2 -1
- package/dist/core/roadmap-migration.d.ts.map +1 -1
- package/dist/core/roadmap-migration.js +110 -51
- package/dist/core/roadmap-migration.js.map +1 -1
- package/dist/core/roadmap-source-patch.d.ts +2 -1
- package/dist/core/roadmap-source-patch.d.ts.map +1 -1
- package/dist/core/roadmap-source-patch.js +9 -4
- package/dist/core/roadmap-source-patch.js.map +1 -1
- package/dist/core/roadmap-sources.d.ts +2 -1
- package/dist/core/roadmap-sources.d.ts.map +1 -1
- package/dist/core/roadmap-sources.js +38 -26
- package/dist/core/roadmap-sources.js.map +1 -1
- package/dist/core/roadmap.d.ts +22 -16
- package/dist/core/roadmap.d.ts.map +1 -1
- package/dist/core/roadmap.js +152 -84
- package/dist/core/roadmap.js.map +1 -1
- package/dist/core/session-branch.d.ts +17 -0
- package/dist/core/session-branch.d.ts.map +1 -0
- package/dist/core/session-branch.js +85 -0
- package/dist/core/session-branch.js.map +1 -0
- package/dist/core/sprint-id.d.ts +13 -5
- package/dist/core/sprint-id.d.ts.map +1 -1
- package/dist/core/sprint-id.js +16 -0
- package/dist/core/sprint-id.js.map +1 -1
- package/dist/core/standup.d.ts +2 -1
- package/dist/core/standup.d.ts.map +1 -1
- package/dist/core/standup.js.map +1 -1
- package/dist/core/store.d.ts +16 -8
- package/dist/core/store.d.ts.map +1 -1
- package/dist/core/store.js +34 -0
- package/dist/core/store.js.map +1 -1
- package/dist/core/tournament.d.ts.map +1 -1
- package/dist/core/tournament.js +4 -3
- package/dist/core/tournament.js.map +1 -1
- package/dist/core/types.d.ts +9 -7
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/validation.d.ts +2 -1
- package/dist/core/validation.d.ts.map +1 -1
- package/dist/core/validation.js +2 -1
- package/dist/core/validation.js.map +1 -1
- package/dist/core/webhooks.d.ts +3 -2
- package/dist/core/webhooks.d.ts.map +1 -1
- package/dist/core/webhooks.js +9 -2
- package/dist/core/webhooks.js.map +1 -1
- package/dist/core/workflow-loader.d.ts.map +1 -1
- package/dist/core/workflow-loader.js +2 -1
- package/dist/core/workflow-loader.js.map +1 -1
- package/dist/mcp/index.d.ts +5 -1
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +97 -59
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/index.test.js +14 -3
- package/dist/mcp/index.test.js.map +1 -1
- package/dist/mcp/registry.d.ts +1 -1
- package/dist/mcp/registry.d.ts.map +1 -1
- package/dist/mcp/registry.js +36 -28
- package/dist/mcp/registry.js.map +1 -1
- package/dist/store/index.d.ts +13 -11
- package/dist/store/index.d.ts.map +1 -1
- package/dist/store/index.js +217 -36
- package/dist/store/index.js.map +1 -1
- package/dist/store-pg/index.d.ts +18 -12
- package/dist/store-pg/index.d.ts.map +1 -1
- package/dist/store-pg/index.js +124 -38
- package/dist/store-pg/index.js.map +1 -1
- package/package.json +1 -1
- package/templates/codex/plugins/slope/.codex-plugin/plugin.json +1 -1
package/dist/core/roadmap.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// SLOPE — Roadmap: Strategic planning types and compute functions
|
|
2
2
|
// Course-level methodology — vision → roadmap → review → iteration
|
|
3
|
+
import { compareSprintIdKeys, parseSprintId, sprintIdKey } from './sprint-id.js';
|
|
3
4
|
/** Return true for legacy encoded inserted half-sprint ids like 435 => S43.5.
|
|
4
5
|
* Decimal roadmap ids such as 75.5 are already explicit and are left as-is.
|
|
5
6
|
* The encoding is intentionally limited to pre-S100-style three-digit ids
|
|
@@ -19,6 +20,8 @@ export function sprintOrderValue(id) {
|
|
|
19
20
|
}
|
|
20
21
|
/** Format the numeric portion of a sprint id for human-facing output. */
|
|
21
22
|
export function formatSprintNumber(id) {
|
|
23
|
+
if (typeof id === 'string')
|
|
24
|
+
return sprintIdKey(id) ?? id;
|
|
22
25
|
if (isEncodedInsertedSprintId(id)) {
|
|
23
26
|
return `${Math.floor(id / 10)}.${id % 10}`;
|
|
24
27
|
}
|
|
@@ -91,13 +94,13 @@ export function compareSprintIds(a, b) {
|
|
|
91
94
|
}
|
|
92
95
|
/** Return the next canonical sprint id after a completed sprint/inserted sprint. */
|
|
93
96
|
export function nextCanonicalSprintId(id) {
|
|
94
|
-
if (isEncodedInsertedSprintId(id)) {
|
|
95
|
-
return Math.floor(id / 10) + 1;
|
|
96
|
-
}
|
|
97
|
-
if (!Number.isInteger(id)) {
|
|
98
|
-
return Math.floor(id) + 1;
|
|
97
|
+
if (typeof id === 'number' && isEncodedInsertedSprintId(id)) {
|
|
98
|
+
return String(Math.floor(id / 10) + 1);
|
|
99
99
|
}
|
|
100
|
-
|
|
100
|
+
const parsed = parseSprintId(id);
|
|
101
|
+
if (!parsed)
|
|
102
|
+
return '1';
|
|
103
|
+
return String(parsed.base + 1);
|
|
101
104
|
}
|
|
102
105
|
export const ROADMAP_TERMINAL_STATUSES = new Set([
|
|
103
106
|
'complete',
|
|
@@ -169,13 +172,31 @@ export function isEncodedInsertedSprintInRoadmap(roadmap, id) {
|
|
|
169
172
|
return sprintIds.has(base) || sprintIds.has(base + 1);
|
|
170
173
|
}
|
|
171
174
|
export function roadmapSprintOrderValue(roadmap, id) {
|
|
172
|
-
|
|
175
|
+
const key = roadmapSprintKeyFromId(roadmap, id);
|
|
176
|
+
const parsed = key ? parseSprintId(key) : null;
|
|
177
|
+
if (!parsed)
|
|
178
|
+
return typeof id === 'number' ? id : Number(id);
|
|
179
|
+
if (parsed.insert === null)
|
|
180
|
+
return parsed.base;
|
|
181
|
+
return parsed.base + parsed.insert / (10 ** parsed.insertDigits.length);
|
|
173
182
|
}
|
|
174
183
|
export function compareRoadmapSprintIds(roadmap, a, b) {
|
|
175
|
-
|
|
184
|
+
const ka = roadmapSprintKeyFromId(roadmap, a) ?? String(a);
|
|
185
|
+
const kb = roadmapSprintKeyFromId(roadmap, b) ?? String(b);
|
|
186
|
+
return compareSprintIdKeys(ka, kb);
|
|
187
|
+
}
|
|
188
|
+
function areAdjacentSprintKeys(previousKey, currentKey) {
|
|
189
|
+
const previous = parseSprintId(previousKey);
|
|
190
|
+
const current = parseSprintId(currentKey);
|
|
191
|
+
if (!previous || !current)
|
|
192
|
+
return false;
|
|
193
|
+
if (previous.base === current.base) {
|
|
194
|
+
return current.insert !== null && compareSprintIdKeys(previousKey, currentKey) < 0;
|
|
195
|
+
}
|
|
196
|
+
return current.base === previous.base + 1 && current.insert === null;
|
|
176
197
|
}
|
|
177
198
|
export function formatRoadmapSprintLabel(roadmap, id) {
|
|
178
|
-
return
|
|
199
|
+
return `S${roadmapSprintKeyFromId(roadmap, id) ?? id}`;
|
|
179
200
|
}
|
|
180
201
|
/**
|
|
181
202
|
* Canonical string identity for a sprint: the authored `id_key` when present
|
|
@@ -190,6 +211,24 @@ export function roadmapSprintKey(roadmap, sprint) {
|
|
|
190
211
|
? formatSprintNumber(sprint.id)
|
|
191
212
|
: String(sprint.id);
|
|
192
213
|
}
|
|
214
|
+
/** Resolve a canonical sprint key from either a key or a legacy numeric mirror. */
|
|
215
|
+
export function roadmapSprintKeyFromId(roadmap, id) {
|
|
216
|
+
const inputKey = sprintIdKey(id);
|
|
217
|
+
if (inputKey === null)
|
|
218
|
+
return null;
|
|
219
|
+
const canonical = roadmap.sprints.find(sprint => roadmapSprintKey(roadmap, sprint) === inputKey);
|
|
220
|
+
if (canonical)
|
|
221
|
+
return roadmapSprintKey(roadmap, canonical);
|
|
222
|
+
const mirror = roadmap.sprints.find(sprint => sprint.id === Number(inputKey));
|
|
223
|
+
return mirror ? roadmapSprintKey(roadmap, mirror) : inputKey;
|
|
224
|
+
}
|
|
225
|
+
/** Find one roadmap sprint by canonical key, with numeric mirrors as legacy input. */
|
|
226
|
+
export function findRoadmapSprint(roadmap, id) {
|
|
227
|
+
const key = roadmapSprintKeyFromId(roadmap, id);
|
|
228
|
+
return key == null
|
|
229
|
+
? undefined
|
|
230
|
+
: roadmap.sprints.find(sprint => roadmapSprintKey(roadmap, sprint) === key);
|
|
231
|
+
}
|
|
193
232
|
/** Validate a roadmap definition for structural correctness.
|
|
194
233
|
* Optionally cross-check sprint status against scorecards and/or shipped
|
|
195
234
|
* sprint commits on main when provided. Caller is responsible for collecting
|
|
@@ -198,8 +237,7 @@ export function roadmapSprintKey(roadmap, sprint) {
|
|
|
198
237
|
export function validateRoadmap(roadmap, scorecards, shippedSprintIds) {
|
|
199
238
|
const errors = [];
|
|
200
239
|
const warnings = [];
|
|
201
|
-
const sprintIds = new Set(roadmap.sprints.map(s => s
|
|
202
|
-
const orderOf = (id) => roadmapSprintOrderValue(roadmap, id);
|
|
240
|
+
const sprintIds = new Set(roadmap.sprints.map(s => roadmapSprintKey(roadmap, s)));
|
|
203
241
|
const labelOf = (id) => formatRoadmapSprintLabel(roadmap, id);
|
|
204
242
|
// Canonical identity so 458.10 and 458.1 are distinct sprints with distinct
|
|
205
243
|
// ticket-key prefixes (GH #635).
|
|
@@ -210,12 +248,9 @@ export function validateRoadmap(roadmap, scorecards, shippedSprintIds) {
|
|
|
210
248
|
return { valid: false, errors, warnings };
|
|
211
249
|
}
|
|
212
250
|
// Check: sprint numbering continuity
|
|
213
|
-
const sortedIds = [...sprintIds].sort((a, b) =>
|
|
251
|
+
const sortedIds = [...sprintIds].sort((a, b) => compareSprintIdKeys(a, b));
|
|
214
252
|
for (let i = 1; i < sortedIds.length; i++) {
|
|
215
|
-
|
|
216
|
-
const current = orderOf(sortedIds[i]);
|
|
217
|
-
const allowedInsertedStep = current > prev && current <= Math.floor(prev) + 1;
|
|
218
|
-
if (!allowedInsertedStep && current !== prev + 1) {
|
|
253
|
+
if (!areAdjacentSprintKeys(sortedIds[i - 1], sortedIds[i])) {
|
|
219
254
|
// A long-lived roadmap legitimately skips numbers as sprints are
|
|
220
255
|
// absorbed, cancelled, or renumbered, so a numbering discontinuity is
|
|
221
256
|
// informational rather than a structural error. Genuinely-structural
|
|
@@ -236,19 +271,20 @@ export function validateRoadmap(roadmap, scorecards, shippedSprintIds) {
|
|
|
236
271
|
// Build a set of all ticket keys across all sprints for cross-sprint dependency validation
|
|
237
272
|
const allTicketKeys = new Set(roadmap.sprints.flatMap(s => s.tickets.map(getRoadmapTicketKey).filter((key) => key !== null)));
|
|
238
273
|
for (const sprint of roadmap.sprints) {
|
|
274
|
+
const sprintKey = roadmapSprintKey(roadmap, sprint);
|
|
239
275
|
// Check: ticket count (3-4 per sprint)
|
|
240
276
|
if (sprint.tickets.length < 3) {
|
|
241
277
|
warnings.push({
|
|
242
278
|
type: 'warning',
|
|
243
|
-
sprint:
|
|
244
|
-
message: `${
|
|
279
|
+
sprint: sprintKey,
|
|
280
|
+
message: `${keyLabelOf(sprint)} has ${sprint.tickets.length} tickets (recommended 3-4)`,
|
|
245
281
|
});
|
|
246
282
|
}
|
|
247
283
|
if (sprint.tickets.length > 4) {
|
|
248
284
|
warnings.push({
|
|
249
285
|
type: 'warning',
|
|
250
|
-
sprint:
|
|
251
|
-
message: `${
|
|
286
|
+
sprint: sprintKey,
|
|
287
|
+
message: `${keyLabelOf(sprint)} has ${sprint.tickets.length} tickets (recommended 3-4)`,
|
|
252
288
|
});
|
|
253
289
|
}
|
|
254
290
|
// Check: ticket key format matches sprint
|
|
@@ -258,15 +294,15 @@ export function validateRoadmap(roadmap, scorecards, shippedSprintIds) {
|
|
|
258
294
|
if (!ticketKey) {
|
|
259
295
|
errors.push({
|
|
260
296
|
type: 'error',
|
|
261
|
-
sprint:
|
|
262
|
-
message: `Ticket in ${
|
|
297
|
+
sprint: sprintKey,
|
|
298
|
+
message: `Ticket in ${keyLabelOf(sprint)} is missing key/id`,
|
|
263
299
|
});
|
|
264
300
|
continue;
|
|
265
301
|
}
|
|
266
302
|
if (!ticketKey.startsWith(expected)) {
|
|
267
303
|
errors.push({
|
|
268
304
|
type: 'error',
|
|
269
|
-
sprint:
|
|
305
|
+
sprint: sprintKey,
|
|
270
306
|
ticket: ticketKey,
|
|
271
307
|
message: `Ticket ${ticketKey} does not match sprint ${keyLabelOf(sprint)} (expected prefix ${expected})`,
|
|
272
308
|
});
|
|
@@ -281,7 +317,7 @@ export function validateRoadmap(roadmap, scorecards, shippedSprintIds) {
|
|
|
281
317
|
if (!allTicketKeys.has(dep)) {
|
|
282
318
|
errors.push({
|
|
283
319
|
type: 'error',
|
|
284
|
-
sprint:
|
|
320
|
+
sprint: sprintKey,
|
|
285
321
|
ticket: ticketKey,
|
|
286
322
|
message: `Ticket ${ticketKey} depends on ${dep} which does not exist in the roadmap`,
|
|
287
323
|
});
|
|
@@ -290,11 +326,12 @@ export function validateRoadmap(roadmap, scorecards, shippedSprintIds) {
|
|
|
290
326
|
}
|
|
291
327
|
// Check: sprint dependencies exist
|
|
292
328
|
for (const dep of sprint.depends_on ?? []) {
|
|
293
|
-
|
|
329
|
+
const depKey = roadmapSprintKeyFromId(roadmap, dep);
|
|
330
|
+
if (depKey === null || !sprintIds.has(depKey)) {
|
|
294
331
|
errors.push({
|
|
295
332
|
type: 'error',
|
|
296
|
-
sprint:
|
|
297
|
-
message: `${labelOf(sprint
|
|
333
|
+
sprint: sprintKey,
|
|
334
|
+
message: `${labelOf(roadmapSprintKey(roadmap, sprint))} depends on ${labelOf(dep)} which does not exist in the roadmap`,
|
|
298
335
|
});
|
|
299
336
|
}
|
|
300
337
|
}
|
|
@@ -302,8 +339,8 @@ export function validateRoadmap(roadmap, scorecards, shippedSprintIds) {
|
|
|
302
339
|
if (sprint.par < 3 || sprint.par > 5) {
|
|
303
340
|
errors.push({
|
|
304
341
|
type: 'error',
|
|
305
|
-
sprint:
|
|
306
|
-
message: `${
|
|
342
|
+
sprint: sprintKey,
|
|
343
|
+
message: `${keyLabelOf(sprint)} has invalid par ${sprint.par} (must be 3, 4, or 5)`,
|
|
307
344
|
});
|
|
308
345
|
}
|
|
309
346
|
}
|
|
@@ -317,8 +354,10 @@ export function validateRoadmap(roadmap, scorecards, shippedSprintIds) {
|
|
|
317
354
|
}
|
|
318
355
|
// Check: phases reference valid sprint IDs
|
|
319
356
|
for (const phase of roadmap.phases) {
|
|
320
|
-
|
|
321
|
-
|
|
357
|
+
const phaseSprintIds = phase.sprint_keys ?? phase.sprints;
|
|
358
|
+
for (const sid of phaseSprintIds) {
|
|
359
|
+
const sidKey = roadmapSprintKeyFromId(roadmap, sid);
|
|
360
|
+
if (sidKey === null || !sprintIds.has(sidKey)) {
|
|
322
361
|
errors.push({
|
|
323
362
|
type: 'error',
|
|
324
363
|
message: `Phase "${phase.name}" references ${labelOf(sid)} which does not exist`,
|
|
@@ -328,22 +367,22 @@ export function validateRoadmap(roadmap, scorecards, shippedSprintIds) {
|
|
|
328
367
|
}
|
|
329
368
|
// Cross-validate sprint status against scorecards when provided
|
|
330
369
|
if (scorecards) {
|
|
331
|
-
const scorecardSprintIds = new Set(scorecards.map(s => s.sprint_number));
|
|
370
|
+
const scorecardSprintIds = new Set(scorecards.map(s => roadmapSprintKeyFromId(roadmap, s.sprint_number)));
|
|
332
371
|
for (const sprint of roadmap.sprints) {
|
|
333
|
-
const hasScorecard = scorecardSprintIds.has(sprint
|
|
372
|
+
const hasScorecard = scorecardSprintIds.has(roadmapSprintKey(roadmap, sprint));
|
|
334
373
|
const status = sprint.status;
|
|
335
374
|
if (hasScorecard && status !== 'complete') {
|
|
336
375
|
warnings.push({
|
|
337
376
|
type: 'warning',
|
|
338
|
-
sprint: sprint
|
|
339
|
-
message: `${
|
|
377
|
+
sprint: roadmapSprintKey(roadmap, sprint),
|
|
378
|
+
message: `${keyLabelOf(sprint)} has a scorecard but roadmap status is "${status ?? 'planned'}" — expected "complete"`,
|
|
340
379
|
});
|
|
341
380
|
}
|
|
342
381
|
if (!hasScorecard && status === 'complete') {
|
|
343
382
|
warnings.push({
|
|
344
383
|
type: 'warning',
|
|
345
|
-
sprint: sprint
|
|
346
|
-
message: `${
|
|
384
|
+
sprint: roadmapSprintKey(roadmap, sprint),
|
|
385
|
+
message: `${keyLabelOf(sprint)} is marked "complete" in roadmap but no scorecard exists (phantom sprint)`,
|
|
347
386
|
});
|
|
348
387
|
}
|
|
349
388
|
}
|
|
@@ -355,21 +394,25 @@ export function validateRoadmap(roadmap, scorecards, shippedSprintIds) {
|
|
|
355
394
|
// bookkeeping, not a feature ship). Treat those terminal-but-not-complete
|
|
356
395
|
// statuses as final rather than demanding "complete".
|
|
357
396
|
const TERMINAL_NOT_COMPLETE = new Set(['superseded', 'skipped', 'cancelled', 'cancelled-absorbed', 'absorbed']);
|
|
397
|
+
const shippedSprintKeys = new Set([...shippedSprintIds]
|
|
398
|
+
.map(id => roadmapSprintKeyFromId(roadmap, id))
|
|
399
|
+
.filter((id) => id !== null));
|
|
358
400
|
for (const sprint of roadmap.sprints) {
|
|
359
401
|
const status = sprint.status;
|
|
360
|
-
const
|
|
402
|
+
const key = roadmapSprintKey(roadmap, sprint);
|
|
403
|
+
const isShipped = shippedSprintKeys.has(key);
|
|
361
404
|
if (isShipped && status !== 'complete' && !TERMINAL_NOT_COMPLETE.has(status ?? '')) {
|
|
362
405
|
errors.push({
|
|
363
406
|
type: 'error',
|
|
364
|
-
sprint:
|
|
365
|
-
message: `${
|
|
407
|
+
sprint: key,
|
|
408
|
+
message: `${keyLabelOf(sprint)} has shipped commits on main but status is "${status ?? 'planned'}" — expected "complete"`,
|
|
366
409
|
});
|
|
367
410
|
}
|
|
368
411
|
if (!isShipped && status === 'complete') {
|
|
369
412
|
warnings.push({
|
|
370
413
|
type: 'warning',
|
|
371
|
-
sprint:
|
|
372
|
-
message: `${
|
|
414
|
+
sprint: key,
|
|
415
|
+
message: `${keyLabelOf(sprint)} is marked "complete" but no shipped commits found on main`,
|
|
373
416
|
});
|
|
374
417
|
}
|
|
375
418
|
}
|
|
@@ -379,29 +422,34 @@ export function validateRoadmap(roadmap, scorecards, shippedSprintIds) {
|
|
|
379
422
|
// --- Dependency Graph ---
|
|
380
423
|
/** Detect cycles in sprint dependency graph. Returns cycle path or null. */
|
|
381
424
|
function detectCycle(sprints) {
|
|
425
|
+
const roadmap = { name: '', phases: [], sprints };
|
|
426
|
+
const sprintMap = new Map(sprints.map(sprint => [roadmapSprintKey(roadmap, sprint), sprint]));
|
|
382
427
|
const visited = new Set();
|
|
383
428
|
const inStack = new Set();
|
|
384
429
|
const parent = new Map();
|
|
385
430
|
function dfs(id) {
|
|
386
431
|
visited.add(id);
|
|
387
432
|
inStack.add(id);
|
|
388
|
-
const sprint =
|
|
433
|
+
const sprint = sprintMap.get(id);
|
|
389
434
|
for (const dep of sprint?.depends_on ?? []) {
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
435
|
+
const depKey = roadmapSprintKeyFromId(roadmap, dep);
|
|
436
|
+
if (depKey === null)
|
|
437
|
+
continue;
|
|
438
|
+
if (!visited.has(depKey)) {
|
|
439
|
+
parent.set(depKey, id);
|
|
440
|
+
const result = dfs(depKey);
|
|
393
441
|
if (result)
|
|
394
442
|
return result;
|
|
395
443
|
}
|
|
396
|
-
else if (inStack.has(
|
|
444
|
+
else if (inStack.has(depKey)) {
|
|
397
445
|
// Build cycle path
|
|
398
|
-
const cycle = [
|
|
446
|
+
const cycle = [depKey];
|
|
399
447
|
let current = id;
|
|
400
|
-
while (current !==
|
|
448
|
+
while (current !== depKey) {
|
|
401
449
|
cycle.push(current);
|
|
402
450
|
current = parent.get(current);
|
|
403
451
|
}
|
|
404
|
-
cycle.push(
|
|
452
|
+
cycle.push(depKey);
|
|
405
453
|
return cycle.reverse();
|
|
406
454
|
}
|
|
407
455
|
}
|
|
@@ -409,8 +457,9 @@ function detectCycle(sprints) {
|
|
|
409
457
|
return null;
|
|
410
458
|
}
|
|
411
459
|
for (const sprint of sprints) {
|
|
412
|
-
|
|
413
|
-
|
|
460
|
+
const key = roadmapSprintKey(roadmap, sprint);
|
|
461
|
+
if (!visited.has(key)) {
|
|
462
|
+
const result = dfs(key);
|
|
414
463
|
if (result)
|
|
415
464
|
return result;
|
|
416
465
|
}
|
|
@@ -419,7 +468,7 @@ function detectCycle(sprints) {
|
|
|
419
468
|
}
|
|
420
469
|
/** Compute the critical path (longest dependency chain) through the roadmap */
|
|
421
470
|
export function computeCriticalPath(roadmap) {
|
|
422
|
-
const sprintMap = new Map(roadmap.sprints.map(s => [s
|
|
471
|
+
const sprintMap = new Map(roadmap.sprints.map(s => [roadmapSprintKey(roadmap, s), s]));
|
|
423
472
|
// Compute longest path ending at each sprint via topological order
|
|
424
473
|
const longestTo = new Map();
|
|
425
474
|
// Topological sort
|
|
@@ -433,7 +482,8 @@ export function computeCriticalPath(roadmap) {
|
|
|
433
482
|
else {
|
|
434
483
|
let best = { length: 0, path: [] };
|
|
435
484
|
for (const dep of deps) {
|
|
436
|
-
const
|
|
485
|
+
const depKey = roadmapSprintKeyFromId(roadmap, dep);
|
|
486
|
+
const depPath = depKey ? longestTo.get(depKey) : undefined;
|
|
437
487
|
if (depPath && depPath.length > best.length) {
|
|
438
488
|
best = depPath;
|
|
439
489
|
}
|
|
@@ -460,16 +510,22 @@ export function computeCriticalPath(roadmap) {
|
|
|
460
510
|
}
|
|
461
511
|
/** Topological sort of sprints by dependency order */
|
|
462
512
|
function topologicalSort(sprints) {
|
|
513
|
+
const roadmap = { name: '', phases: [], sprints };
|
|
463
514
|
const inDegree = new Map();
|
|
464
515
|
const adjacency = new Map();
|
|
465
516
|
for (const sprint of sprints) {
|
|
466
|
-
|
|
467
|
-
|
|
517
|
+
const key = roadmapSprintKey(roadmap, sprint);
|
|
518
|
+
inDegree.set(key, 0);
|
|
519
|
+
adjacency.set(key, []);
|
|
468
520
|
}
|
|
469
521
|
for (const sprint of sprints) {
|
|
522
|
+
const key = roadmapSprintKey(roadmap, sprint);
|
|
470
523
|
for (const dep of sprint.depends_on ?? []) {
|
|
471
|
-
|
|
472
|
-
|
|
524
|
+
const depKey = roadmapSprintKeyFromId(roadmap, dep);
|
|
525
|
+
if (depKey === null)
|
|
526
|
+
continue;
|
|
527
|
+
adjacency.get(depKey)?.push(key);
|
|
528
|
+
inDegree.set(key, (inDegree.get(key) ?? 0) + 1);
|
|
473
529
|
}
|
|
474
530
|
}
|
|
475
531
|
const queue = [];
|
|
@@ -504,7 +560,7 @@ export function findParallelOpportunities(roadmap) {
|
|
|
504
560
|
for (const [depth, ids] of byDepth) {
|
|
505
561
|
if (ids.length > 1) {
|
|
506
562
|
groups.push({
|
|
507
|
-
sprints: ids.sort(
|
|
563
|
+
sprints: ids.sort(compareSprintIdKeys),
|
|
508
564
|
reason: `Same dependency depth (${depth}) — no mutual dependencies`,
|
|
509
565
|
});
|
|
510
566
|
}
|
|
@@ -513,19 +569,23 @@ export function findParallelOpportunities(roadmap) {
|
|
|
513
569
|
}
|
|
514
570
|
/** Compute the depth (longest path from a root) of each sprint */
|
|
515
571
|
function computeDepthMap(sprints) {
|
|
572
|
+
const roadmap = { name: '', phases: [], sprints };
|
|
516
573
|
const depthMap = new Map();
|
|
517
|
-
const sprintMap = new Map(sprints.map(s => [s
|
|
574
|
+
const sprintMap = new Map(sprints.map(s => [roadmapSprintKey(roadmap, s), s]));
|
|
518
575
|
function getDepth(id) {
|
|
519
576
|
if (depthMap.has(id))
|
|
520
577
|
return depthMap.get(id);
|
|
521
578
|
const sprint = sprintMap.get(id);
|
|
522
579
|
const deps = sprint?.depends_on ?? [];
|
|
523
|
-
const
|
|
580
|
+
const depKeys = deps
|
|
581
|
+
.map(dep => roadmapSprintKeyFromId(roadmap, dep))
|
|
582
|
+
.filter((dep) => dep !== null);
|
|
583
|
+
const depth = depKeys.length === 0 ? 0 : Math.max(...depKeys.map(getDepth)) + 1;
|
|
524
584
|
depthMap.set(id, depth);
|
|
525
585
|
return depth;
|
|
526
586
|
}
|
|
527
587
|
for (const sprint of sprints) {
|
|
528
|
-
getDepth(sprint
|
|
588
|
+
getDepth(roadmapSprintKey(roadmap, sprint));
|
|
529
589
|
}
|
|
530
590
|
return depthMap;
|
|
531
591
|
}
|
|
@@ -593,29 +653,30 @@ export function formatRoadmapSummary(roadmap) {
|
|
|
593
653
|
lines.push('');
|
|
594
654
|
// Phases
|
|
595
655
|
for (const phase of roadmap.phases) {
|
|
596
|
-
const phaseSprintIds = phase.sprints;
|
|
597
|
-
const
|
|
656
|
+
const phaseSprintIds = phase.sprint_keys ?? phase.sprints;
|
|
657
|
+
const phaseSprintKeys = new Set(phaseSprintIds.map(id => roadmapSprintKeyFromId(roadmap, id)));
|
|
658
|
+
const phaseSprints = roadmap.sprints.filter(sprint => phaseSprintKeys.has(roadmapSprintKey(roadmap, sprint)));
|
|
598
659
|
lines.push(`## ${phase.name}`);
|
|
599
660
|
lines.push('');
|
|
600
661
|
for (const sprint of phaseSprints) {
|
|
601
662
|
const deps = sprint.depends_on?.length
|
|
602
|
-
? ` (depends on: ${sprint.depends_on.map(
|
|
663
|
+
? ` (depends on: ${sprint.depends_on.map(id => formatRoadmapSprintLabel(roadmap, id)).join(', ')})`
|
|
603
664
|
: ' (no dependencies)';
|
|
604
|
-
lines.push(`- **${
|
|
665
|
+
lines.push(`- **${formatRoadmapSprintLabel(roadmap, roadmapSprintKey(roadmap, sprint))}** — ${sprint.theme} | Par ${sprint.par} | ${sprint.tickets.length} tickets${deps}`);
|
|
605
666
|
}
|
|
606
667
|
lines.push('');
|
|
607
668
|
}
|
|
608
669
|
// Critical path
|
|
609
670
|
lines.push('## Critical Path');
|
|
610
671
|
lines.push('');
|
|
611
|
-
lines.push(`${criticalPath.path.map(
|
|
672
|
+
lines.push(`${criticalPath.path.map(id => formatRoadmapSprintLabel(roadmap, id)).join(' → ')} (${criticalPath.length} sprints, par ${criticalPath.totalPar})`);
|
|
612
673
|
lines.push('');
|
|
613
674
|
// Parallel opportunities
|
|
614
675
|
if (parallelGroups.length > 0) {
|
|
615
676
|
lines.push('## Parallel Opportunities');
|
|
616
677
|
lines.push('');
|
|
617
678
|
for (const group of parallelGroups) {
|
|
618
|
-
lines.push(`- ${group.sprints.map(
|
|
679
|
+
lines.push(`- ${group.sprints.map(id => formatRoadmapSprintLabel(roadmap, id)).join(', ')}: ${group.reason}`);
|
|
619
680
|
}
|
|
620
681
|
lines.push('');
|
|
621
682
|
}
|
|
@@ -630,21 +691,23 @@ export function formatRoadmapSummary(roadmap) {
|
|
|
630
691
|
}
|
|
631
692
|
/** Format strategic context for briefings — concise 3-5 line summary */
|
|
632
693
|
export function formatStrategicContext(roadmap, currentSprint) {
|
|
633
|
-
const
|
|
634
|
-
const sprint = roadmap.sprints.find(s => roadmapSprintOrderValue(roadmap, s.id) === currentOrder);
|
|
694
|
+
const sprint = findRoadmapSprint(roadmap, currentSprint);
|
|
635
695
|
if (!sprint)
|
|
636
696
|
return null;
|
|
637
|
-
const resolvedSprint = sprint
|
|
697
|
+
const resolvedSprint = roadmapSprintKey(roadmap, sprint);
|
|
638
698
|
const criticalPath = computeCriticalPath(roadmap);
|
|
639
|
-
const onCriticalPath = criticalPath.path.
|
|
699
|
+
const onCriticalPath = criticalPath.path.includes(resolvedSprint);
|
|
640
700
|
const totalSprints = roadmap.sprints.length;
|
|
641
|
-
const sprintIndex = roadmap.sprints.findIndex(s => s
|
|
701
|
+
const sprintIndex = roadmap.sprints.findIndex(s => roadmapSprintKey(roadmap, s) === resolvedSprint) + 1;
|
|
642
702
|
// Find which phase this sprint belongs to
|
|
643
|
-
const phase = roadmap.phases.find(p =>
|
|
703
|
+
const phase = roadmap.phases.find(p => {
|
|
704
|
+
const keys = p.sprint_keys ?? p.sprints;
|
|
705
|
+
return keys.some(id => roadmapSprintKeyFromId(roadmap, id) === resolvedSprint);
|
|
706
|
+
});
|
|
644
707
|
// Find what depends on this sprint
|
|
645
708
|
const dependents = roadmap.sprints
|
|
646
|
-
.filter(s => s.depends_on?.some(id =>
|
|
647
|
-
.map(s => formatRoadmapSprintLabel(roadmap, s
|
|
709
|
+
.filter(s => s.depends_on?.some(id => roadmapSprintKeyFromId(roadmap, id) === resolvedSprint))
|
|
710
|
+
.map(s => formatRoadmapSprintLabel(roadmap, roadmapSprintKey(roadmap, s)));
|
|
648
711
|
const lines = [];
|
|
649
712
|
lines.push(`Sprint ${sprintIndex} of ${totalSprints} — ${formatRoadmapSprintLabel(roadmap, resolvedSprint)}: ${sprint.theme}`);
|
|
650
713
|
if (phase) {
|
|
@@ -661,14 +724,13 @@ export function formatStrategicContext(roadmap, currentSprint) {
|
|
|
661
724
|
if (next) {
|
|
662
725
|
const blockers = (next.depends_on ?? [])
|
|
663
726
|
.filter(d => {
|
|
664
|
-
const
|
|
665
|
-
const dep = roadmap.sprints.find(s => roadmapSprintOrderValue(roadmap, s.id) === depOrder);
|
|
727
|
+
const dep = findRoadmapSprint(roadmap, d);
|
|
666
728
|
return !dep || dep.status !== 'complete';
|
|
667
729
|
});
|
|
668
730
|
const status = blockers.length === 0
|
|
669
731
|
? 'ready'
|
|
670
732
|
: `blocked by ${blockers.map(id => formatRoadmapSprintLabel(roadmap, id)).join(', ')}`;
|
|
671
|
-
lines.push(`Next: ${formatRoadmapSprintLabel(roadmap, next
|
|
733
|
+
lines.push(`Next: ${formatRoadmapSprintLabel(roadmap, roadmapSprintKey(roadmap, next))}: ${next.theme} (${status})`);
|
|
672
734
|
}
|
|
673
735
|
return lines.join('\n');
|
|
674
736
|
}
|
|
@@ -678,19 +740,25 @@ export function formatStrategicContext(roadmap, currentSprint) {
|
|
|
678
740
|
* Returns null if no candidate found.
|
|
679
741
|
*/
|
|
680
742
|
export function findNextPlannedSprint(roadmap, currentSprint) {
|
|
681
|
-
const
|
|
743
|
+
const currentKey = roadmapSprintKeyFromId(roadmap, currentSprint);
|
|
744
|
+
if (currentKey === null)
|
|
745
|
+
return null;
|
|
682
746
|
const candidates = roadmap.sprints
|
|
683
747
|
.filter(s => {
|
|
684
|
-
return isRoadmapSprintPending(s)
|
|
748
|
+
return isRoadmapSprintPending(s)
|
|
749
|
+
&& compareSprintIdKeys(roadmapSprintKey(roadmap, s), currentKey) > 0;
|
|
685
750
|
})
|
|
686
|
-
.sort((a, b) =>
|
|
751
|
+
.sort((a, b) => compareSprintIdKeys(roadmapSprintKey(roadmap, a), roadmapSprintKey(roadmap, b)));
|
|
687
752
|
if (candidates.length === 0)
|
|
688
753
|
return null;
|
|
689
754
|
const completedIds = new Set(roadmap.sprints
|
|
690
755
|
.filter(s => s.status === 'complete')
|
|
691
|
-
.map(s =>
|
|
756
|
+
.map(s => roadmapSprintKey(roadmap, s)));
|
|
692
757
|
// Prefer the lowest-id candidate whose dependencies are all complete
|
|
693
|
-
const ready = candidates.find(s => (s.depends_on ?? []).every(d =>
|
|
758
|
+
const ready = candidates.find(s => (s.depends_on ?? []).every(d => {
|
|
759
|
+
const key = roadmapSprintKeyFromId(roadmap, d);
|
|
760
|
+
return key !== null && completedIds.has(key);
|
|
761
|
+
}));
|
|
694
762
|
return ready ?? candidates[0];
|
|
695
763
|
}
|
|
696
764
|
//# sourceMappingURL=roadmap.js.map
|