sprinty-mcp 0.1.12 → 0.1.14

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 CHANGED
@@ -121,8 +121,8 @@ subsprint_new({ description, goals, gates, dependencies? })
121
121
  item_add({ subsprint, title, description, code_locations, gates, dependencies?, high_priority? })
122
122
  next({})
123
123
  item_done({ id, commit_id, gate_results, changelog: { verb: "added" | "fixed" | "changed" | "removed" | "deprecated" | "security", line } })
124
- changelog({ path? }) -> { path }
125
- sprint_close({ coverage: { path, format: "lcov", command? } })
124
+ changelog({ path? }) -> { path } // generates SemVer Markdown
125
+ sprint_close({ coverage: { path, format: "lcov", command? } }) // after changelog generation
126
126
  ```
127
127
 
128
128
  Use `item_split` when an item is too large and `item_deprecate` when an item is intentionally
@@ -161,12 +161,12 @@ Dashboard tools:
161
161
  | `sprint_resume` | Reattach to an existing sprint after an MCP restart; returns dashboard info. |
162
162
  | `sprint_list` | List ledgers in a `data_dir` without creating a sprint. |
163
163
  | `sprint_detach` | Clear this MCP process binding and stop the dashboard. |
164
- | `sprint_close` | Re-run gates, require coverage evidence, and close only when all work is resolved. |
164
+ | `sprint_close` | After `changelog({ path? })` has generated SemVer Markdown, re-run gates, require coverage evidence, and close only when all work is resolved. |
165
165
  | `sprint_archive` | Archive an active sprint with a recovery reason. |
166
166
  | `overview` | Compact sprint summary for orientation. |
167
167
  | `next` | Compact active work window with available and blocked items. |
168
168
  | `search` | Regex search over the immutable sprint ledger. |
169
- | `changelog` | Write the semver Markdown changelog to `path` or the sprint data dir and return only the path. |
169
+ | `changelog` | Generate the SemVer Markdown changelog at `path` or the sprint data dir and return only the path. |
170
170
 
171
171
  ### Work Tools
172
172
 
@@ -209,8 +209,9 @@ keep it out of git unless you intentionally want to preserve it elsewhere. Sprin
209
209
  ledger into compact read models for agents and into the dashboard for humans.
210
210
 
211
211
  Completed items record the commit id, gate results, changelog entry, and Git-backed file change map.
212
- `sprint_close` re-checks commits, re-runs executable gates, requires coverage evidence, and refuses
213
- to close while any item is still open.
212
+ Call `changelog({ path? })` before close to generate the SemVer Markdown file from those entries.
213
+ `sprint_close` then re-checks commits, re-runs executable gates, requires coverage evidence, and
214
+ refuses to close while any item is still open.
214
215
 
215
216
  ## More Documentation
216
217
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sprinty",
3
- "version": "0.1.12",
3
+ "version": "0.1.14",
4
4
  "description": "Disciplined sprint workflow: dashboard-at-start, feature subsprints, artifacts, bug-id follow-ups, spike investigations, an immutable git-anchored ledger, and programmatic close gates.",
5
5
  "author": { "name": "Elie Bursztein" },
6
6
  "homepage": "https://github.com/ebursztein/sprinty",
@@ -34,8 +34,8 @@ subsprint should be one feature; use `spike()` for feature investigations, then
34
34
  outputs and `follow_up()` with bug ids for bugs found while moving fast. `next()` returns the active
35
35
  work window with relevant artifacts and recent activity: all available `high_priority` items first
36
36
  by default, then normal available items per subsprint. `item_update({ id, dependencies })` replaces
37
- dependencies, so pass `dependencies: []` to remove a bad edge. `done` records a Git-backed change map. `changelog()` returns Markdown with
38
- changelog and change-map tables. `sprint_close` rechecks commits, re-runs executable gates, requires
37
+ dependencies, so pass `dependencies: []` to remove a bad edge. `done` records a Git-backed change map and each item's SemVer changelog entry. `changelog({ path? })` generates the SemVer Markdown file with
38
+ sections, item entries, commits, coverage, and change-map tables; run it before `sprint_close`. `sprint_close` rechecks commits, re-runs executable gates, requires
39
39
  an LCOV coverage report path, and refuses to close on any blocker. Use `search(pattern,
40
40
  context_lines)` to query the immutable ledger. Show the dashboard URL returned by `sprint_new()` or
41
41
  `sprint_resume()` to the human so they can watch the sprint timeline; use `dashboard_info()` to
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sprinty",
3
- "version": "0.1.12",
3
+ "version": "0.1.14",
4
4
  "description": "Disciplined sprint workflow with dashboard-at-start, feature subsprints, artifacts, bug-id follow-ups, spike investigations, an immutable git-anchored ledger, and close gates.",
5
5
  "contextFileName": "GEMINI.md",
6
6
  "mcpServers": {
@@ -0,0 +1,53 @@
1
+ import type { TimelineEntry } from "../../domain/projection.js";
2
+ export type EventSegment = {
3
+ category: string;
4
+ count: number;
5
+ };
6
+ export type EventBucket = {
7
+ label: string;
8
+ total: number;
9
+ segments: EventSegment[];
10
+ };
11
+ export type CompletionPoint = {
12
+ time: number;
13
+ movingAverageMs: number;
14
+ durationMs: number;
15
+ };
16
+ export type CompletionRatePoint = {
17
+ time: number;
18
+ percent: number;
19
+ completed: number;
20
+ };
21
+ export interface CompletionSummary {
22
+ points: CompletionPoint[];
23
+ ratePoints: CompletionRatePoint[];
24
+ rateStart: number | null;
25
+ rateEnd: number | null;
26
+ avgMs: number | null;
27
+ medianMs: number | null;
28
+ minMs: number | null;
29
+ maxMs: number | null;
30
+ etaMs: number | null;
31
+ etaAt: string | null;
32
+ projectedAt: number | null;
33
+ openItems: number;
34
+ remainingItems: number;
35
+ }
36
+ export declare function parseTs(ts: string | null | undefined): number | null;
37
+ export declare function recentTimelineWindow(entries: TimelineEntry[], windowMs: number, nowMs: number, sprintStartedAtMs?: number | null): TimelineEntry[];
38
+ export declare function buildEventBuckets(entries: TimelineEntry[], options: {
39
+ nowMs: number;
40
+ windowMs: number;
41
+ sprintStartedAtMs?: number | null;
42
+ bucketCount: number;
43
+ categories: string[];
44
+ formatLabel: (ts: number) => string;
45
+ }): EventBucket[];
46
+ export declare function eventAction(entry: TimelineEntry): string | null;
47
+ export declare function buildCompletionSummary(entries: TimelineEntry[], openItems: number, totalItems: number, options: {
48
+ nowMs: number;
49
+ windowMs: number;
50
+ sprintStartedAtMs?: number | null;
51
+ movingAverageWindow: number;
52
+ formatEta: (ts: number) => string;
53
+ }): CompletionSummary;
@@ -0,0 +1,179 @@
1
+ export function parseTs(ts) {
2
+ if (!ts)
3
+ return null;
4
+ const value = Date.parse(ts);
5
+ return Number.isNaN(value) ? null : value;
6
+ }
7
+ export function recentTimelineWindow(entries, windowMs, nowMs, sprintStartedAtMs) {
8
+ const cutoff = fixedWindowStart({ nowMs, windowMs, sprintStartedAtMs });
9
+ return entries.filter((entry) => {
10
+ const time = parseTs(entry.ts);
11
+ return time !== null && time >= cutoff && time <= nowMs;
12
+ });
13
+ }
14
+ export function buildEventBuckets(entries, options) {
15
+ const bucketCount = Math.max(1, options.bucketCount);
16
+ const windowStart = fixedWindowStart(options);
17
+ const effectiveWindowMs = Math.max(1, options.nowMs - windowStart);
18
+ const bucketMs = Math.max(1, effectiveWindowMs / bucketCount);
19
+ const buckets = Array.from({ length: bucketCount }, (_, index) => ({
20
+ label: options.formatLabel(windowStart + index * bucketMs),
21
+ total: 0,
22
+ counts: new Map(),
23
+ }));
24
+ const normalized = entries
25
+ .map((entry) => ({ entry, time: parseTs(entry.ts) }))
26
+ .filter((row) => row.time !== null && row.time >= windowStart && row.time <= options.nowMs)
27
+ .sort((a, b) => a.time - b.time);
28
+ for (const { entry, time } of normalized) {
29
+ const category = eventAction(entry);
30
+ if (!category)
31
+ continue;
32
+ const bucketIndex = Math.min(bucketCount - 1, Math.max(0, Math.floor((time - windowStart) / bucketMs)));
33
+ const bucket = buckets[bucketIndex];
34
+ if (!bucket)
35
+ continue;
36
+ bucket.total += 1;
37
+ bucket.counts.set(category, (bucket.counts.get(category) ?? 0) + 1);
38
+ }
39
+ return buckets.map((bucket) => ({
40
+ label: bucket.label,
41
+ total: bucket.total,
42
+ segments: options.categories
43
+ .map((category) => ({ category, count: bucket.counts.get(category) ?? 0 }))
44
+ .filter((segment) => segment.count > 0),
45
+ }));
46
+ }
47
+ export function eventAction(entry) {
48
+ if (entry.type === "sprint_created" ||
49
+ entry.type === "subsprint_created" ||
50
+ entry.type === "item_added" ||
51
+ entry.type === "artifact_added" ||
52
+ entry.type === "follow_up_added" ||
53
+ entry.type === "dependencies_added")
54
+ return "added";
55
+ if (entry.type === "item_updated" ||
56
+ entry.type === "note_added" ||
57
+ entry.type === "note_updated" ||
58
+ entry.type === "dependencies_replaced" ||
59
+ entry.type === "artifact_amended")
60
+ return "edited";
61
+ if (entry.type === "sprint_closed" ||
62
+ entry.type === "sprint_archived" ||
63
+ entry.type === "item_resolved" ||
64
+ entry.type === "artifact_deprecated" ||
65
+ entry.type === "spike_concluded" ||
66
+ entry.type === "spike_deprecated")
67
+ return "closed";
68
+ return null;
69
+ }
70
+ export function buildCompletionSummary(entries, openItems, totalItems, options) {
71
+ const historyStart = fixedHistoryStart(options);
72
+ const normalized = entries
73
+ .map((entry) => ({ entry, time: parseTs(entry.ts) }))
74
+ .filter((row) => row.time !== null && row.time >= historyStart && row.time <= options.nowMs)
75
+ .sort((a, b) => a.time - b.time);
76
+ const windowStart = fixedWindowStart(options);
77
+ const starts = new Map();
78
+ const points = [];
79
+ const ratePoints = [];
80
+ const cadenceDurations = [];
81
+ const rateTotal = Math.max(0, totalItems);
82
+ const remainingItems = Math.max(0, openItems);
83
+ let completedItems = 0;
84
+ let lastResolvedAt = null;
85
+ if (rateTotal > 0) {
86
+ completedItems = Math.min(rateTotal, normalized.filter((row) => row.entry.type === "item_resolved" && row.time < windowStart).length);
87
+ ratePoints.push({ time: windowStart, percent: percent(completedItems, rateTotal), completed: completedItems });
88
+ }
89
+ for (const { entry, time } of normalized) {
90
+ if (entry.type === "item_added") {
91
+ starts.set(entry.id, time);
92
+ continue;
93
+ }
94
+ if (entry.type !== "item_resolved")
95
+ continue;
96
+ if (time < windowStart) {
97
+ starts.delete(entry.id);
98
+ lastResolvedAt = time;
99
+ continue;
100
+ }
101
+ const previousResolvedAt = lastResolvedAt;
102
+ const durationMs = previousResolvedAt === null ? 0 : Math.max(0, time - previousResolvedAt);
103
+ if (previousResolvedAt !== null)
104
+ cadenceDurations.push(durationMs);
105
+ lastResolvedAt = time;
106
+ starts.delete(entry.id);
107
+ points.push({ time, durationMs, movingAverageMs: 0 });
108
+ if (rateTotal > 0) {
109
+ completedItems = Math.min(rateTotal, completedItems + 1);
110
+ ratePoints.push({ time, percent: percent(completedItems, rateTotal), completed: completedItems });
111
+ }
112
+ }
113
+ if (rateTotal > 0 && remainingItems > 0) {
114
+ const last = ratePoints[ratePoints.length - 1];
115
+ if (last && last.time < options.nowMs) {
116
+ ratePoints.push({ time: options.nowMs, percent: percent(completedItems, rateTotal), completed: completedItems });
117
+ }
118
+ }
119
+ for (let i = 0; i < points.length; i++) {
120
+ const start = Math.max(0, i - options.movingAverageWindow + 1);
121
+ const window = points.slice(start, i + 1);
122
+ const sum = window.reduce((acc, point) => acc + point.durationMs, 0);
123
+ points[i] = { ...points[i], movingAverageMs: Math.round(sum / window.length) };
124
+ }
125
+ const stats = durationStats(cadenceDurations);
126
+ const etaMs = stats.avgMs && stats.avgMs > 0 ? stats.avgMs * remainingItems : null;
127
+ const projectedAt = etaMs && remainingItems > 0 ? options.nowMs + etaMs : null;
128
+ const etaAt = projectedAt ? options.formatEta(projectedAt) : null;
129
+ const lastRatePoint = ratePoints[ratePoints.length - 1];
130
+ const actualRateEnd = rateTotal > 0 && remainingItems === 0 && lastRatePoint ? lastRatePoint.time : options.nowMs;
131
+ const rateEnd = projectedAt && projectedAt > actualRateEnd ? projectedAt : actualRateEnd;
132
+ return {
133
+ points,
134
+ ratePoints,
135
+ rateStart: windowStart,
136
+ rateEnd,
137
+ avgMs: stats.avgMs,
138
+ medianMs: stats.medianMs,
139
+ minMs: stats.minMs,
140
+ maxMs: stats.maxMs,
141
+ etaMs,
142
+ etaAt,
143
+ projectedAt,
144
+ openItems,
145
+ remainingItems,
146
+ };
147
+ }
148
+ function fixedWindowStart(options) {
149
+ const requested = options.nowMs - options.windowMs;
150
+ if (options.sprintStartedAtMs === null || options.sprintStartedAtMs === undefined)
151
+ return requested;
152
+ const sprintStart = Math.min(options.nowMs, options.sprintStartedAtMs);
153
+ return Math.max(requested, sprintStart);
154
+ }
155
+ function fixedHistoryStart(options) {
156
+ if (options.sprintStartedAtMs === null || options.sprintStartedAtMs === undefined)
157
+ return Number.NEGATIVE_INFINITY;
158
+ return Math.min(options.nowMs, options.sprintStartedAtMs);
159
+ }
160
+ function percent(done, total) {
161
+ return total <= 0 ? 0 : Math.round((done / total) * 100);
162
+ }
163
+ function durationStats(durations) {
164
+ if (!durations.length)
165
+ return { avgMs: null, medianMs: null, minMs: null, maxMs: null };
166
+ const avgMs = Math.round(durations.reduce((sum, value) => sum + value, 0) / durations.length);
167
+ const sorted = [...durations].sort((a, b) => a - b);
168
+ const mid = Math.floor(sorted.length / 2);
169
+ const medianMs = sorted.length % 2 === 1
170
+ ? sorted[mid]
171
+ : (sorted[mid - 1] + sorted[mid]) / 2;
172
+ return {
173
+ avgMs,
174
+ medianMs,
175
+ minMs: sorted[0],
176
+ maxMs: sorted[sorted.length - 1],
177
+ };
178
+ }
179
+ //# sourceMappingURL=chart-windows.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chart-windows.js","sourceRoot":"","sources":["../../../src/dashboard/ui/chart-windows.ts"],"names":[],"mappings":"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"}