@slope-dev/slope 1.64.0 → 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 +144 -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 +13 -1
- package/dist/cli/commands/validate.d.ts.map +1 -1
- package/dist/cli/commands/validate.js +47 -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 +15 -4
- package/dist/cli/roadmap-source-store.d.ts.map +1 -1
- package/dist/cli/roadmap-source-store.js +79 -33
- 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 +35 -17
- package/dist/core/roadmap.d.ts.map +1 -1
- package/dist/core/roadmap.js +167 -86
- 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',
|
|
@@ -107,13 +110,26 @@ export const ROADMAP_TERMINAL_STATUSES = new Set([
|
|
|
107
110
|
'cancelled-absorbed',
|
|
108
111
|
'absorbed',
|
|
109
112
|
]);
|
|
113
|
+
/**
|
|
114
|
+
* Statuses that are not durably terminal but are intentionally not offered as
|
|
115
|
+
* the next sprint to work on. A deferred sprint is postponed by choice — it is
|
|
116
|
+
* neither done (so not terminal) nor queued work (so not selectable). It becomes
|
|
117
|
+
* selectable again once its status is edited back to planned/active (GH #660).
|
|
118
|
+
*/
|
|
119
|
+
export const ROADMAP_DEFERRED_STATUSES = new Set(['deferred']);
|
|
110
120
|
/** Return true when a roadmap sprint has a durable terminal disposition. */
|
|
111
121
|
export function isRoadmapSprintTerminal(sprint) {
|
|
112
122
|
return ROADMAP_TERMINAL_STATUSES.has(sprint.status ?? '');
|
|
113
123
|
}
|
|
114
|
-
/**
|
|
124
|
+
/**
|
|
125
|
+
* Return true when a roadmap sprint should still be considered selectable work —
|
|
126
|
+
* the pool the "next sprint" pickers, rollover target, and current-sprint
|
|
127
|
+
* inference draw from. Excludes both terminal statuses and deferred (a
|
|
128
|
+
* deliberately postponed sprint must not be surfaced as the next thing to do).
|
|
129
|
+
*/
|
|
115
130
|
export function isRoadmapSprintPending(sprint) {
|
|
116
|
-
return !isRoadmapSprintTerminal(sprint)
|
|
131
|
+
return !isRoadmapSprintTerminal(sprint)
|
|
132
|
+
&& !ROADMAP_DEFERRED_STATUSES.has(sprint.status ?? '');
|
|
117
133
|
}
|
|
118
134
|
export function getRoadmapTicketKey(ticket) {
|
|
119
135
|
const key = ticket.key;
|
|
@@ -156,13 +172,31 @@ export function isEncodedInsertedSprintInRoadmap(roadmap, id) {
|
|
|
156
172
|
return sprintIds.has(base) || sprintIds.has(base + 1);
|
|
157
173
|
}
|
|
158
174
|
export function roadmapSprintOrderValue(roadmap, id) {
|
|
159
|
-
|
|
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);
|
|
160
182
|
}
|
|
161
183
|
export function compareRoadmapSprintIds(roadmap, a, b) {
|
|
162
|
-
|
|
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;
|
|
163
197
|
}
|
|
164
198
|
export function formatRoadmapSprintLabel(roadmap, id) {
|
|
165
|
-
return
|
|
199
|
+
return `S${roadmapSprintKeyFromId(roadmap, id) ?? id}`;
|
|
166
200
|
}
|
|
167
201
|
/**
|
|
168
202
|
* Canonical string identity for a sprint: the authored `id_key` when present
|
|
@@ -177,6 +211,24 @@ export function roadmapSprintKey(roadmap, sprint) {
|
|
|
177
211
|
? formatSprintNumber(sprint.id)
|
|
178
212
|
: String(sprint.id);
|
|
179
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
|
+
}
|
|
180
232
|
/** Validate a roadmap definition for structural correctness.
|
|
181
233
|
* Optionally cross-check sprint status against scorecards and/or shipped
|
|
182
234
|
* sprint commits on main when provided. Caller is responsible for collecting
|
|
@@ -185,8 +237,7 @@ export function roadmapSprintKey(roadmap, sprint) {
|
|
|
185
237
|
export function validateRoadmap(roadmap, scorecards, shippedSprintIds) {
|
|
186
238
|
const errors = [];
|
|
187
239
|
const warnings = [];
|
|
188
|
-
const sprintIds = new Set(roadmap.sprints.map(s => s
|
|
189
|
-
const orderOf = (id) => roadmapSprintOrderValue(roadmap, id);
|
|
240
|
+
const sprintIds = new Set(roadmap.sprints.map(s => roadmapSprintKey(roadmap, s)));
|
|
190
241
|
const labelOf = (id) => formatRoadmapSprintLabel(roadmap, id);
|
|
191
242
|
// Canonical identity so 458.10 and 458.1 are distinct sprints with distinct
|
|
192
243
|
// ticket-key prefixes (GH #635).
|
|
@@ -197,12 +248,9 @@ export function validateRoadmap(roadmap, scorecards, shippedSprintIds) {
|
|
|
197
248
|
return { valid: false, errors, warnings };
|
|
198
249
|
}
|
|
199
250
|
// Check: sprint numbering continuity
|
|
200
|
-
const sortedIds = [...sprintIds].sort((a, b) =>
|
|
251
|
+
const sortedIds = [...sprintIds].sort((a, b) => compareSprintIdKeys(a, b));
|
|
201
252
|
for (let i = 1; i < sortedIds.length; i++) {
|
|
202
|
-
|
|
203
|
-
const current = orderOf(sortedIds[i]);
|
|
204
|
-
const allowedInsertedStep = current > prev && current <= Math.floor(prev) + 1;
|
|
205
|
-
if (!allowedInsertedStep && current !== prev + 1) {
|
|
253
|
+
if (!areAdjacentSprintKeys(sortedIds[i - 1], sortedIds[i])) {
|
|
206
254
|
// A long-lived roadmap legitimately skips numbers as sprints are
|
|
207
255
|
// absorbed, cancelled, or renumbered, so a numbering discontinuity is
|
|
208
256
|
// informational rather than a structural error. Genuinely-structural
|
|
@@ -223,19 +271,20 @@ export function validateRoadmap(roadmap, scorecards, shippedSprintIds) {
|
|
|
223
271
|
// Build a set of all ticket keys across all sprints for cross-sprint dependency validation
|
|
224
272
|
const allTicketKeys = new Set(roadmap.sprints.flatMap(s => s.tickets.map(getRoadmapTicketKey).filter((key) => key !== null)));
|
|
225
273
|
for (const sprint of roadmap.sprints) {
|
|
274
|
+
const sprintKey = roadmapSprintKey(roadmap, sprint);
|
|
226
275
|
// Check: ticket count (3-4 per sprint)
|
|
227
276
|
if (sprint.tickets.length < 3) {
|
|
228
277
|
warnings.push({
|
|
229
278
|
type: 'warning',
|
|
230
|
-
sprint:
|
|
231
|
-
message: `${
|
|
279
|
+
sprint: sprintKey,
|
|
280
|
+
message: `${keyLabelOf(sprint)} has ${sprint.tickets.length} tickets (recommended 3-4)`,
|
|
232
281
|
});
|
|
233
282
|
}
|
|
234
283
|
if (sprint.tickets.length > 4) {
|
|
235
284
|
warnings.push({
|
|
236
285
|
type: 'warning',
|
|
237
|
-
sprint:
|
|
238
|
-
message: `${
|
|
286
|
+
sprint: sprintKey,
|
|
287
|
+
message: `${keyLabelOf(sprint)} has ${sprint.tickets.length} tickets (recommended 3-4)`,
|
|
239
288
|
});
|
|
240
289
|
}
|
|
241
290
|
// Check: ticket key format matches sprint
|
|
@@ -245,15 +294,15 @@ export function validateRoadmap(roadmap, scorecards, shippedSprintIds) {
|
|
|
245
294
|
if (!ticketKey) {
|
|
246
295
|
errors.push({
|
|
247
296
|
type: 'error',
|
|
248
|
-
sprint:
|
|
249
|
-
message: `Ticket in ${
|
|
297
|
+
sprint: sprintKey,
|
|
298
|
+
message: `Ticket in ${keyLabelOf(sprint)} is missing key/id`,
|
|
250
299
|
});
|
|
251
300
|
continue;
|
|
252
301
|
}
|
|
253
302
|
if (!ticketKey.startsWith(expected)) {
|
|
254
303
|
errors.push({
|
|
255
304
|
type: 'error',
|
|
256
|
-
sprint:
|
|
305
|
+
sprint: sprintKey,
|
|
257
306
|
ticket: ticketKey,
|
|
258
307
|
message: `Ticket ${ticketKey} does not match sprint ${keyLabelOf(sprint)} (expected prefix ${expected})`,
|
|
259
308
|
});
|
|
@@ -268,7 +317,7 @@ export function validateRoadmap(roadmap, scorecards, shippedSprintIds) {
|
|
|
268
317
|
if (!allTicketKeys.has(dep)) {
|
|
269
318
|
errors.push({
|
|
270
319
|
type: 'error',
|
|
271
|
-
sprint:
|
|
320
|
+
sprint: sprintKey,
|
|
272
321
|
ticket: ticketKey,
|
|
273
322
|
message: `Ticket ${ticketKey} depends on ${dep} which does not exist in the roadmap`,
|
|
274
323
|
});
|
|
@@ -277,11 +326,12 @@ export function validateRoadmap(roadmap, scorecards, shippedSprintIds) {
|
|
|
277
326
|
}
|
|
278
327
|
// Check: sprint dependencies exist
|
|
279
328
|
for (const dep of sprint.depends_on ?? []) {
|
|
280
|
-
|
|
329
|
+
const depKey = roadmapSprintKeyFromId(roadmap, dep);
|
|
330
|
+
if (depKey === null || !sprintIds.has(depKey)) {
|
|
281
331
|
errors.push({
|
|
282
332
|
type: 'error',
|
|
283
|
-
sprint:
|
|
284
|
-
message: `${labelOf(sprint
|
|
333
|
+
sprint: sprintKey,
|
|
334
|
+
message: `${labelOf(roadmapSprintKey(roadmap, sprint))} depends on ${labelOf(dep)} which does not exist in the roadmap`,
|
|
285
335
|
});
|
|
286
336
|
}
|
|
287
337
|
}
|
|
@@ -289,8 +339,8 @@ export function validateRoadmap(roadmap, scorecards, shippedSprintIds) {
|
|
|
289
339
|
if (sprint.par < 3 || sprint.par > 5) {
|
|
290
340
|
errors.push({
|
|
291
341
|
type: 'error',
|
|
292
|
-
sprint:
|
|
293
|
-
message: `${
|
|
342
|
+
sprint: sprintKey,
|
|
343
|
+
message: `${keyLabelOf(sprint)} has invalid par ${sprint.par} (must be 3, 4, or 5)`,
|
|
294
344
|
});
|
|
295
345
|
}
|
|
296
346
|
}
|
|
@@ -304,8 +354,10 @@ export function validateRoadmap(roadmap, scorecards, shippedSprintIds) {
|
|
|
304
354
|
}
|
|
305
355
|
// Check: phases reference valid sprint IDs
|
|
306
356
|
for (const phase of roadmap.phases) {
|
|
307
|
-
|
|
308
|
-
|
|
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)) {
|
|
309
361
|
errors.push({
|
|
310
362
|
type: 'error',
|
|
311
363
|
message: `Phase "${phase.name}" references ${labelOf(sid)} which does not exist`,
|
|
@@ -315,22 +367,22 @@ export function validateRoadmap(roadmap, scorecards, shippedSprintIds) {
|
|
|
315
367
|
}
|
|
316
368
|
// Cross-validate sprint status against scorecards when provided
|
|
317
369
|
if (scorecards) {
|
|
318
|
-
const scorecardSprintIds = new Set(scorecards.map(s => s.sprint_number));
|
|
370
|
+
const scorecardSprintIds = new Set(scorecards.map(s => roadmapSprintKeyFromId(roadmap, s.sprint_number)));
|
|
319
371
|
for (const sprint of roadmap.sprints) {
|
|
320
|
-
const hasScorecard = scorecardSprintIds.has(sprint
|
|
372
|
+
const hasScorecard = scorecardSprintIds.has(roadmapSprintKey(roadmap, sprint));
|
|
321
373
|
const status = sprint.status;
|
|
322
374
|
if (hasScorecard && status !== 'complete') {
|
|
323
375
|
warnings.push({
|
|
324
376
|
type: 'warning',
|
|
325
|
-
sprint: sprint
|
|
326
|
-
message: `${
|
|
377
|
+
sprint: roadmapSprintKey(roadmap, sprint),
|
|
378
|
+
message: `${keyLabelOf(sprint)} has a scorecard but roadmap status is "${status ?? 'planned'}" — expected "complete"`,
|
|
327
379
|
});
|
|
328
380
|
}
|
|
329
381
|
if (!hasScorecard && status === 'complete') {
|
|
330
382
|
warnings.push({
|
|
331
383
|
type: 'warning',
|
|
332
|
-
sprint: sprint
|
|
333
|
-
message: `${
|
|
384
|
+
sprint: roadmapSprintKey(roadmap, sprint),
|
|
385
|
+
message: `${keyLabelOf(sprint)} is marked "complete" in roadmap but no scorecard exists (phantom sprint)`,
|
|
334
386
|
});
|
|
335
387
|
}
|
|
336
388
|
}
|
|
@@ -342,21 +394,25 @@ export function validateRoadmap(roadmap, scorecards, shippedSprintIds) {
|
|
|
342
394
|
// bookkeeping, not a feature ship). Treat those terminal-but-not-complete
|
|
343
395
|
// statuses as final rather than demanding "complete".
|
|
344
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));
|
|
345
400
|
for (const sprint of roadmap.sprints) {
|
|
346
401
|
const status = sprint.status;
|
|
347
|
-
const
|
|
402
|
+
const key = roadmapSprintKey(roadmap, sprint);
|
|
403
|
+
const isShipped = shippedSprintKeys.has(key);
|
|
348
404
|
if (isShipped && status !== 'complete' && !TERMINAL_NOT_COMPLETE.has(status ?? '')) {
|
|
349
405
|
errors.push({
|
|
350
406
|
type: 'error',
|
|
351
|
-
sprint:
|
|
352
|
-
message: `${
|
|
407
|
+
sprint: key,
|
|
408
|
+
message: `${keyLabelOf(sprint)} has shipped commits on main but status is "${status ?? 'planned'}" — expected "complete"`,
|
|
353
409
|
});
|
|
354
410
|
}
|
|
355
411
|
if (!isShipped && status === 'complete') {
|
|
356
412
|
warnings.push({
|
|
357
413
|
type: 'warning',
|
|
358
|
-
sprint:
|
|
359
|
-
message: `${
|
|
414
|
+
sprint: key,
|
|
415
|
+
message: `${keyLabelOf(sprint)} is marked "complete" but no shipped commits found on main`,
|
|
360
416
|
});
|
|
361
417
|
}
|
|
362
418
|
}
|
|
@@ -366,29 +422,34 @@ export function validateRoadmap(roadmap, scorecards, shippedSprintIds) {
|
|
|
366
422
|
// --- Dependency Graph ---
|
|
367
423
|
/** Detect cycles in sprint dependency graph. Returns cycle path or null. */
|
|
368
424
|
function detectCycle(sprints) {
|
|
425
|
+
const roadmap = { name: '', phases: [], sprints };
|
|
426
|
+
const sprintMap = new Map(sprints.map(sprint => [roadmapSprintKey(roadmap, sprint), sprint]));
|
|
369
427
|
const visited = new Set();
|
|
370
428
|
const inStack = new Set();
|
|
371
429
|
const parent = new Map();
|
|
372
430
|
function dfs(id) {
|
|
373
431
|
visited.add(id);
|
|
374
432
|
inStack.add(id);
|
|
375
|
-
const sprint =
|
|
433
|
+
const sprint = sprintMap.get(id);
|
|
376
434
|
for (const dep of sprint?.depends_on ?? []) {
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
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);
|
|
380
441
|
if (result)
|
|
381
442
|
return result;
|
|
382
443
|
}
|
|
383
|
-
else if (inStack.has(
|
|
444
|
+
else if (inStack.has(depKey)) {
|
|
384
445
|
// Build cycle path
|
|
385
|
-
const cycle = [
|
|
446
|
+
const cycle = [depKey];
|
|
386
447
|
let current = id;
|
|
387
|
-
while (current !==
|
|
448
|
+
while (current !== depKey) {
|
|
388
449
|
cycle.push(current);
|
|
389
450
|
current = parent.get(current);
|
|
390
451
|
}
|
|
391
|
-
cycle.push(
|
|
452
|
+
cycle.push(depKey);
|
|
392
453
|
return cycle.reverse();
|
|
393
454
|
}
|
|
394
455
|
}
|
|
@@ -396,8 +457,9 @@ function detectCycle(sprints) {
|
|
|
396
457
|
return null;
|
|
397
458
|
}
|
|
398
459
|
for (const sprint of sprints) {
|
|
399
|
-
|
|
400
|
-
|
|
460
|
+
const key = roadmapSprintKey(roadmap, sprint);
|
|
461
|
+
if (!visited.has(key)) {
|
|
462
|
+
const result = dfs(key);
|
|
401
463
|
if (result)
|
|
402
464
|
return result;
|
|
403
465
|
}
|
|
@@ -406,7 +468,7 @@ function detectCycle(sprints) {
|
|
|
406
468
|
}
|
|
407
469
|
/** Compute the critical path (longest dependency chain) through the roadmap */
|
|
408
470
|
export function computeCriticalPath(roadmap) {
|
|
409
|
-
const sprintMap = new Map(roadmap.sprints.map(s => [s
|
|
471
|
+
const sprintMap = new Map(roadmap.sprints.map(s => [roadmapSprintKey(roadmap, s), s]));
|
|
410
472
|
// Compute longest path ending at each sprint via topological order
|
|
411
473
|
const longestTo = new Map();
|
|
412
474
|
// Topological sort
|
|
@@ -420,7 +482,8 @@ export function computeCriticalPath(roadmap) {
|
|
|
420
482
|
else {
|
|
421
483
|
let best = { length: 0, path: [] };
|
|
422
484
|
for (const dep of deps) {
|
|
423
|
-
const
|
|
485
|
+
const depKey = roadmapSprintKeyFromId(roadmap, dep);
|
|
486
|
+
const depPath = depKey ? longestTo.get(depKey) : undefined;
|
|
424
487
|
if (depPath && depPath.length > best.length) {
|
|
425
488
|
best = depPath;
|
|
426
489
|
}
|
|
@@ -447,16 +510,22 @@ export function computeCriticalPath(roadmap) {
|
|
|
447
510
|
}
|
|
448
511
|
/** Topological sort of sprints by dependency order */
|
|
449
512
|
function topologicalSort(sprints) {
|
|
513
|
+
const roadmap = { name: '', phases: [], sprints };
|
|
450
514
|
const inDegree = new Map();
|
|
451
515
|
const adjacency = new Map();
|
|
452
516
|
for (const sprint of sprints) {
|
|
453
|
-
|
|
454
|
-
|
|
517
|
+
const key = roadmapSprintKey(roadmap, sprint);
|
|
518
|
+
inDegree.set(key, 0);
|
|
519
|
+
adjacency.set(key, []);
|
|
455
520
|
}
|
|
456
521
|
for (const sprint of sprints) {
|
|
522
|
+
const key = roadmapSprintKey(roadmap, sprint);
|
|
457
523
|
for (const dep of sprint.depends_on ?? []) {
|
|
458
|
-
|
|
459
|
-
|
|
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);
|
|
460
529
|
}
|
|
461
530
|
}
|
|
462
531
|
const queue = [];
|
|
@@ -491,7 +560,7 @@ export function findParallelOpportunities(roadmap) {
|
|
|
491
560
|
for (const [depth, ids] of byDepth) {
|
|
492
561
|
if (ids.length > 1) {
|
|
493
562
|
groups.push({
|
|
494
|
-
sprints: ids.sort(
|
|
563
|
+
sprints: ids.sort(compareSprintIdKeys),
|
|
495
564
|
reason: `Same dependency depth (${depth}) — no mutual dependencies`,
|
|
496
565
|
});
|
|
497
566
|
}
|
|
@@ -500,19 +569,23 @@ export function findParallelOpportunities(roadmap) {
|
|
|
500
569
|
}
|
|
501
570
|
/** Compute the depth (longest path from a root) of each sprint */
|
|
502
571
|
function computeDepthMap(sprints) {
|
|
572
|
+
const roadmap = { name: '', phases: [], sprints };
|
|
503
573
|
const depthMap = new Map();
|
|
504
|
-
const sprintMap = new Map(sprints.map(s => [s
|
|
574
|
+
const sprintMap = new Map(sprints.map(s => [roadmapSprintKey(roadmap, s), s]));
|
|
505
575
|
function getDepth(id) {
|
|
506
576
|
if (depthMap.has(id))
|
|
507
577
|
return depthMap.get(id);
|
|
508
578
|
const sprint = sprintMap.get(id);
|
|
509
579
|
const deps = sprint?.depends_on ?? [];
|
|
510
|
-
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;
|
|
511
584
|
depthMap.set(id, depth);
|
|
512
585
|
return depth;
|
|
513
586
|
}
|
|
514
587
|
for (const sprint of sprints) {
|
|
515
|
-
getDepth(sprint
|
|
588
|
+
getDepth(roadmapSprintKey(roadmap, sprint));
|
|
516
589
|
}
|
|
517
590
|
return depthMap;
|
|
518
591
|
}
|
|
@@ -580,29 +653,30 @@ export function formatRoadmapSummary(roadmap) {
|
|
|
580
653
|
lines.push('');
|
|
581
654
|
// Phases
|
|
582
655
|
for (const phase of roadmap.phases) {
|
|
583
|
-
const phaseSprintIds = phase.sprints;
|
|
584
|
-
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)));
|
|
585
659
|
lines.push(`## ${phase.name}`);
|
|
586
660
|
lines.push('');
|
|
587
661
|
for (const sprint of phaseSprints) {
|
|
588
662
|
const deps = sprint.depends_on?.length
|
|
589
|
-
? ` (depends on: ${sprint.depends_on.map(
|
|
663
|
+
? ` (depends on: ${sprint.depends_on.map(id => formatRoadmapSprintLabel(roadmap, id)).join(', ')})`
|
|
590
664
|
: ' (no dependencies)';
|
|
591
|
-
lines.push(`- **${
|
|
665
|
+
lines.push(`- **${formatRoadmapSprintLabel(roadmap, roadmapSprintKey(roadmap, sprint))}** — ${sprint.theme} | Par ${sprint.par} | ${sprint.tickets.length} tickets${deps}`);
|
|
592
666
|
}
|
|
593
667
|
lines.push('');
|
|
594
668
|
}
|
|
595
669
|
// Critical path
|
|
596
670
|
lines.push('## Critical Path');
|
|
597
671
|
lines.push('');
|
|
598
|
-
lines.push(`${criticalPath.path.map(
|
|
672
|
+
lines.push(`${criticalPath.path.map(id => formatRoadmapSprintLabel(roadmap, id)).join(' → ')} (${criticalPath.length} sprints, par ${criticalPath.totalPar})`);
|
|
599
673
|
lines.push('');
|
|
600
674
|
// Parallel opportunities
|
|
601
675
|
if (parallelGroups.length > 0) {
|
|
602
676
|
lines.push('## Parallel Opportunities');
|
|
603
677
|
lines.push('');
|
|
604
678
|
for (const group of parallelGroups) {
|
|
605
|
-
lines.push(`- ${group.sprints.map(
|
|
679
|
+
lines.push(`- ${group.sprints.map(id => formatRoadmapSprintLabel(roadmap, id)).join(', ')}: ${group.reason}`);
|
|
606
680
|
}
|
|
607
681
|
lines.push('');
|
|
608
682
|
}
|
|
@@ -617,21 +691,23 @@ export function formatRoadmapSummary(roadmap) {
|
|
|
617
691
|
}
|
|
618
692
|
/** Format strategic context for briefings — concise 3-5 line summary */
|
|
619
693
|
export function formatStrategicContext(roadmap, currentSprint) {
|
|
620
|
-
const
|
|
621
|
-
const sprint = roadmap.sprints.find(s => roadmapSprintOrderValue(roadmap, s.id) === currentOrder);
|
|
694
|
+
const sprint = findRoadmapSprint(roadmap, currentSprint);
|
|
622
695
|
if (!sprint)
|
|
623
696
|
return null;
|
|
624
|
-
const resolvedSprint = sprint
|
|
697
|
+
const resolvedSprint = roadmapSprintKey(roadmap, sprint);
|
|
625
698
|
const criticalPath = computeCriticalPath(roadmap);
|
|
626
|
-
const onCriticalPath = criticalPath.path.
|
|
699
|
+
const onCriticalPath = criticalPath.path.includes(resolvedSprint);
|
|
627
700
|
const totalSprints = roadmap.sprints.length;
|
|
628
|
-
const sprintIndex = roadmap.sprints.findIndex(s => s
|
|
701
|
+
const sprintIndex = roadmap.sprints.findIndex(s => roadmapSprintKey(roadmap, s) === resolvedSprint) + 1;
|
|
629
702
|
// Find which phase this sprint belongs to
|
|
630
|
-
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
|
+
});
|
|
631
707
|
// Find what depends on this sprint
|
|
632
708
|
const dependents = roadmap.sprints
|
|
633
|
-
.filter(s => s.depends_on?.some(id =>
|
|
634
|
-
.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)));
|
|
635
711
|
const lines = [];
|
|
636
712
|
lines.push(`Sprint ${sprintIndex} of ${totalSprints} — ${formatRoadmapSprintLabel(roadmap, resolvedSprint)}: ${sprint.theme}`);
|
|
637
713
|
if (phase) {
|
|
@@ -648,14 +724,13 @@ export function formatStrategicContext(roadmap, currentSprint) {
|
|
|
648
724
|
if (next) {
|
|
649
725
|
const blockers = (next.depends_on ?? [])
|
|
650
726
|
.filter(d => {
|
|
651
|
-
const
|
|
652
|
-
const dep = roadmap.sprints.find(s => roadmapSprintOrderValue(roadmap, s.id) === depOrder);
|
|
727
|
+
const dep = findRoadmapSprint(roadmap, d);
|
|
653
728
|
return !dep || dep.status !== 'complete';
|
|
654
729
|
});
|
|
655
730
|
const status = blockers.length === 0
|
|
656
731
|
? 'ready'
|
|
657
732
|
: `blocked by ${blockers.map(id => formatRoadmapSprintLabel(roadmap, id)).join(', ')}`;
|
|
658
|
-
lines.push(`Next: ${formatRoadmapSprintLabel(roadmap, next
|
|
733
|
+
lines.push(`Next: ${formatRoadmapSprintLabel(roadmap, roadmapSprintKey(roadmap, next))}: ${next.theme} (${status})`);
|
|
659
734
|
}
|
|
660
735
|
return lines.join('\n');
|
|
661
736
|
}
|
|
@@ -665,19 +740,25 @@ export function formatStrategicContext(roadmap, currentSprint) {
|
|
|
665
740
|
* Returns null if no candidate found.
|
|
666
741
|
*/
|
|
667
742
|
export function findNextPlannedSprint(roadmap, currentSprint) {
|
|
668
|
-
const
|
|
743
|
+
const currentKey = roadmapSprintKeyFromId(roadmap, currentSprint);
|
|
744
|
+
if (currentKey === null)
|
|
745
|
+
return null;
|
|
669
746
|
const candidates = roadmap.sprints
|
|
670
747
|
.filter(s => {
|
|
671
|
-
return isRoadmapSprintPending(s)
|
|
748
|
+
return isRoadmapSprintPending(s)
|
|
749
|
+
&& compareSprintIdKeys(roadmapSprintKey(roadmap, s), currentKey) > 0;
|
|
672
750
|
})
|
|
673
|
-
.sort((a, b) =>
|
|
751
|
+
.sort((a, b) => compareSprintIdKeys(roadmapSprintKey(roadmap, a), roadmapSprintKey(roadmap, b)));
|
|
674
752
|
if (candidates.length === 0)
|
|
675
753
|
return null;
|
|
676
754
|
const completedIds = new Set(roadmap.sprints
|
|
677
755
|
.filter(s => s.status === 'complete')
|
|
678
|
-
.map(s =>
|
|
756
|
+
.map(s => roadmapSprintKey(roadmap, s)));
|
|
679
757
|
// Prefer the lowest-id candidate whose dependencies are all complete
|
|
680
|
-
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
|
+
}));
|
|
681
762
|
return ready ?? candidates[0];
|
|
682
763
|
}
|
|
683
764
|
//# sourceMappingURL=roadmap.js.map
|