@sentropic/track 0.1.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/LICENSE +21 -0
- package/README.md +84 -0
- package/dist/accept/index.d.ts +3 -0
- package/dist/accept/index.d.ts.map +1 -0
- package/dist/accept/index.js +5 -0
- package/dist/accept/index.js.map +1 -0
- package/dist/accept/ingest.d.ts +16 -0
- package/dist/accept/ingest.d.ts.map +1 -0
- package/dist/accept/ingest.js +60 -0
- package/dist/accept/ingest.js.map +1 -0
- package/dist/accept/status.d.ts +15 -0
- package/dist/accept/status.d.ts.map +1 -0
- package/dist/accept/status.js +44 -0
- package/dist/accept/status.js.map +1 -0
- package/dist/branch/index.d.ts +2 -0
- package/dist/branch/index.d.ts.map +1 -0
- package/dist/branch/index.js +3 -0
- package/dist/branch/index.js.map +1 -0
- package/dist/branch/parse.d.ts +31 -0
- package/dist/branch/parse.d.ts.map +1 -0
- package/dist/branch/parse.js +116 -0
- package/dist/branch/parse.js.map +1 -0
- package/dist/cli/desync.d.ts +14 -0
- package/dist/cli/desync.d.ts.map +1 -0
- package/dist/cli/desync.js +35 -0
- package/dist/cli/desync.js.map +1 -0
- package/dist/cli/index.d.ts +8 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +402 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/events/canonical.d.ts +5 -0
- package/dist/events/canonical.d.ts.map +1 -0
- package/dist/events/canonical.js +134 -0
- package/dist/events/canonical.js.map +1 -0
- package/dist/events/frame.d.ts +11 -0
- package/dist/events/frame.d.ts.map +1 -0
- package/dist/events/frame.js +19 -0
- package/dist/events/frame.js.map +1 -0
- package/dist/events/head.d.ts +21 -0
- package/dist/events/head.d.ts.map +1 -0
- package/dist/events/head.js +54 -0
- package/dist/events/head.js.map +1 -0
- package/dist/events/index.d.ts +7 -0
- package/dist/events/index.d.ts.map +1 -0
- package/dist/events/index.js +9 -0
- package/dist/events/index.js.map +1 -0
- package/dist/events/store.d.ts +33 -0
- package/dist/events/store.d.ts.map +1 -0
- package/dist/events/store.js +121 -0
- package/dist/events/store.js.map +1 -0
- package/dist/events/types.d.ts +42 -0
- package/dist/events/types.d.ts.map +1 -0
- package/dist/events/types.js +22 -0
- package/dist/events/types.js.map +1 -0
- package/dist/events/validate.d.ts +72 -0
- package/dist/events/validate.d.ts.map +1 -0
- package/dist/events/validate.js +210 -0
- package/dist/events/validate.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/model/acceptance.d.ts +60 -0
- package/dist/model/acceptance.d.ts.map +1 -0
- package/dist/model/acceptance.js +2 -0
- package/dist/model/acceptance.js.map +1 -0
- package/dist/model/blocker.d.ts +33 -0
- package/dist/model/blocker.d.ts.map +1 -0
- package/dist/model/blocker.js +15 -0
- package/dist/model/blocker.js.map +1 -0
- package/dist/model/decision.d.ts +59 -0
- package/dist/model/decision.d.ts.map +1 -0
- package/dist/model/decision.js +17 -0
- package/dist/model/decision.js.map +1 -0
- package/dist/model/index.d.ts +6 -0
- package/dist/model/index.d.ts.map +1 -0
- package/dist/model/index.js +7 -0
- package/dist/model/index.js.map +1 -0
- package/dist/model/item.d.ts +51 -0
- package/dist/model/item.d.ts.map +1 -0
- package/dist/model/item.js +42 -0
- package/dist/model/item.js.map +1 -0
- package/dist/model/priority.d.ts +22 -0
- package/dist/model/priority.d.ts.map +1 -0
- package/dist/model/priority.js +13 -0
- package/dist/model/priority.js.map +1 -0
- package/dist/priority/index.d.ts +2 -0
- package/dist/priority/index.d.ts.map +1 -0
- package/dist/priority/index.js +4 -0
- package/dist/priority/index.js.map +1 -0
- package/dist/report/buckets.d.ts +18 -0
- package/dist/report/buckets.d.ts.map +1 -0
- package/dist/report/buckets.js +24 -0
- package/dist/report/buckets.js.map +1 -0
- package/dist/report/build.d.ts +44 -0
- package/dist/report/build.d.ts.map +1 -0
- package/dist/report/build.js +62 -0
- package/dist/report/build.js.map +1 -0
- package/dist/report/format.d.ts +5 -0
- package/dist/report/format.d.ts.map +1 -0
- package/dist/report/format.js +81 -0
- package/dist/report/format.js.map +1 -0
- package/dist/report/index.d.ts +4 -0
- package/dist/report/index.d.ts.map +1 -0
- package/dist/report/index.js +5 -0
- package/dist/report/index.js.map +1 -0
- package/dist/state/fold.d.ts +25 -0
- package/dist/state/fold.d.ts.map +1 -0
- package/dist/state/fold.js +208 -0
- package/dist/state/fold.js.map +1 -0
- package/dist/state/index.d.ts +3 -0
- package/dist/state/index.d.ts.map +1 -0
- package/dist/state/index.js +4 -0
- package/dist/state/index.js.map +1 -0
- package/dist/state/snapshot.d.ts +27 -0
- package/dist/state/snapshot.d.ts.map +1 -0
- package/dist/state/snapshot.js +49 -0
- package/dist/state/snapshot.js.map +1 -0
- package/dist/track.d.ts +118 -0
- package/dist/track.d.ts.map +1 -0
- package/dist/track.js +450 -0
- package/dist/track.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +2 -0
- package/dist/version.js.map +1 -0
- package/package.json +58 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { BUCKETS } from './buckets.js';
|
|
2
|
+
const BACKSLASH = String.fromCharCode(92);
|
|
3
|
+
// Markdown metacharacters escaped in `md` titles so a user title can't inject formatting.
|
|
4
|
+
const MD_META = new Set([
|
|
5
|
+
BACKSLASH, '`', '*', '_', '[', ']', '{', '}', '(', ')', '#', '+', '|', '<', '>', '!', '~', '-',
|
|
6
|
+
]);
|
|
7
|
+
/** Collapse control characters (newlines, tabs, line separators) to single spaces. */
|
|
8
|
+
function clean(s) {
|
|
9
|
+
let out = '';
|
|
10
|
+
let prevSpace = false;
|
|
11
|
+
for (const ch of s) {
|
|
12
|
+
const code = ch.codePointAt(0) ?? 0;
|
|
13
|
+
const isControlOrSpace = code < 0x20 || code === 0x7f || code === 0x2028 || code === 0x2029 || ch === ' ';
|
|
14
|
+
if (isControlOrSpace) {
|
|
15
|
+
if (!prevSpace) {
|
|
16
|
+
out += ' ';
|
|
17
|
+
prevSpace = true;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
out += ch;
|
|
22
|
+
prevSpace = false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return out.trim();
|
|
26
|
+
}
|
|
27
|
+
/** A display-safe title: control-normalized for text, plus markdown-metacharacter-escaped for md. */
|
|
28
|
+
function title(s, format) {
|
|
29
|
+
const t = clean(s);
|
|
30
|
+
if (format !== 'md')
|
|
31
|
+
return t;
|
|
32
|
+
let out = '';
|
|
33
|
+
for (const ch of t)
|
|
34
|
+
out += MD_META.has(ch) ? BACKSLASH + ch : ch;
|
|
35
|
+
return out;
|
|
36
|
+
}
|
|
37
|
+
function heading(label, count, format) {
|
|
38
|
+
return format === 'md' ? `## ${label} (${count})` : `${label} (${count})`;
|
|
39
|
+
}
|
|
40
|
+
function meta(r) {
|
|
41
|
+
return `${r.realization} · ${r.acceptance}${r.priority !== undefined ? ` · wsjf:${r.priority}` : ''}`;
|
|
42
|
+
}
|
|
43
|
+
function rowLine(r, format) {
|
|
44
|
+
return format === 'md'
|
|
45
|
+
? `- **${title(r.title, format)}** — ${meta(r)}`
|
|
46
|
+
: ` - ${title(r.title, format)} [${meta(r)}]`;
|
|
47
|
+
}
|
|
48
|
+
export function formatReport(report, format) {
|
|
49
|
+
if (format === 'json')
|
|
50
|
+
return JSON.stringify(report, null, 2);
|
|
51
|
+
const lines = [];
|
|
52
|
+
for (const bucket of BUCKETS) {
|
|
53
|
+
const rows = report.buckets[bucket];
|
|
54
|
+
lines.push(heading(bucket, rows.length, format));
|
|
55
|
+
for (const r of rows)
|
|
56
|
+
lines.push(rowLine(r, format));
|
|
57
|
+
lines.push('');
|
|
58
|
+
}
|
|
59
|
+
if (report.decisions !== undefined) {
|
|
60
|
+
lines.push(heading('DECISIONS', report.decisions.length, format));
|
|
61
|
+
for (const d of report.decisions) {
|
|
62
|
+
const t = title(d.title, format);
|
|
63
|
+
lines.push(format === 'md'
|
|
64
|
+
? `- **${t}** — ${d.decisionKind} · ${d.realization} · outcome:${d.outcome}`
|
|
65
|
+
: ` - ${t} [${d.decisionKind}, ${d.realization}, outcome:${d.outcome}]`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return lines.join('\n').trimEnd() + '\n';
|
|
69
|
+
}
|
|
70
|
+
export function formatRows(rows, format) {
|
|
71
|
+
if (format === 'json')
|
|
72
|
+
return JSON.stringify(rows, null, 2);
|
|
73
|
+
if (rows.length === 0)
|
|
74
|
+
return '';
|
|
75
|
+
return (rows
|
|
76
|
+
.map((r) => format === 'md'
|
|
77
|
+
? `- **${title(r.title, format)}** — ${r.bucket} · ${r.realization} · ${r.acceptance}`
|
|
78
|
+
: ` - ${title(r.title, format)} [${r.bucket}, ${r.realization}, ${r.acceptance}]`)
|
|
79
|
+
.join('\n') + '\n');
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/report/format.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { BUCKETS, bucketOf, type Bucket, type ReportConfig } from './buckets.js';
|
|
2
|
+
export { buildReport, query, type DecisionRow, type QueryFilter, type Report, type ReportOptions, type ReportRow, } from './build.js';
|
|
3
|
+
export { formatReport, formatRows, type Format } from './format.js';
|
|
4
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/report/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,MAAM,EAAE,KAAK,YAAY,EAAE,MAAM,cAAc,CAAA;AAChF,OAAO,EACL,WAAW,EACX,KAAK,EACL,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,MAAM,EACX,KAAK,aAAa,EAClB,KAAK,SAAS,GACf,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,KAAK,MAAM,EAAE,MAAM,aAAa,CAAA"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// report + query: bucket engine with SPEC §7 precedence (AWAITED > DROPPED > DONE > TO-DO).
|
|
2
|
+
export { BUCKETS, bucketOf } from './buckets.js';
|
|
3
|
+
export { buildReport, query, } from './build.js';
|
|
4
|
+
export { formatReport, formatRows } from './format.js';
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/report/index.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAkC,MAAM,cAAc,CAAA;AAChF,OAAO,EACL,WAAW,EACX,KAAK,GAMN,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,YAAY,EAAE,UAAU,EAAe,MAAM,aAAa,CAAA"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { TrackEvent } from '../events/types.js';
|
|
2
|
+
import type { CriterionState, EvidenceState } from '../model/acceptance.js';
|
|
3
|
+
import type { BlockerState } from '../model/blocker.js';
|
|
4
|
+
import type { DecisionState } from '../model/decision.js';
|
|
5
|
+
import type { BlockerId, ItemId, ItemState } from '../model/item.js';
|
|
6
|
+
/**
|
|
7
|
+
* Materialized state (SPEC §2). The fold *mechanism* (replay in stream order, per-aggregate by
|
|
8
|
+
* `seq`) is the frozen part (Lot 1); the *shape* below grows per lot. Acceptance *status* is a
|
|
9
|
+
* pure function of this state + a baselineCommit (see `accept/`), not stored here.
|
|
10
|
+
*
|
|
11
|
+
* Precondition: `events` is a VALIDATED stream (the store runs `validate` before every append).
|
|
12
|
+
*/
|
|
13
|
+
export interface State {
|
|
14
|
+
items: Map<ItemId, ItemState>;
|
|
15
|
+
decisions: Map<ItemId, DecisionState>;
|
|
16
|
+
blockers: Map<BlockerId, BlockerState>;
|
|
17
|
+
criteria: Map<string, CriterionState>;
|
|
18
|
+
evidence: Map<string, EvidenceState>;
|
|
19
|
+
}
|
|
20
|
+
export declare function fold(events: ReadonlyArray<TrackEvent>): State;
|
|
21
|
+
/** Open blockers across the whole backlog (SPEC §2.9; report AWAITED bucket, §7). */
|
|
22
|
+
export declare function openBlockers(state: State): BlockerState[];
|
|
23
|
+
/** Open blockers targeting a given item. */
|
|
24
|
+
export declare function openBlockersForItem(state: State, itemId: ItemId): BlockerState[];
|
|
25
|
+
//# sourceMappingURL=fold.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fold.d.ts","sourceRoot":"","sources":["../../src/state/fold.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AACpD,OAAO,KAAK,EACV,cAAc,EAEd,aAAa,EAEd,MAAM,wBAAwB,CAAA;AAC/B,OAAO,KAAK,EAAwB,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAC7E,OAAO,KAAK,EAEV,aAAa,EAGd,MAAM,sBAAsB,CAAA;AAG7B,OAAO,KAAK,EACV,SAAS,EAIT,MAAM,EACN,SAAS,EAGV,MAAM,kBAAkB,CAAA;AAEzB;;;;;;GAMG;AACH,MAAM,WAAW,KAAK;IACpB,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;IAC7B,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;IACrC,QAAQ,EAAE,GAAG,CAAC,SAAS,EAAE,YAAY,CAAC,CAAA;IACtC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAA;IACrC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;CACrC;AAYD,wBAAgB,IAAI,CAAC,MAAM,EAAE,aAAa,CAAC,UAAU,CAAC,GAAG,KAAK,CAS7D;AAED,qFAAqF;AACrF,wBAAgB,YAAY,CAAC,KAAK,EAAE,KAAK,GAAG,YAAY,EAAE,CAEzD;AAED,4CAA4C;AAC5C,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,GAAG,YAAY,EAAE,CAEhF"}
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { isSettled } from '../model/decision.js';
|
|
2
|
+
function emptyState() {
|
|
3
|
+
return {
|
|
4
|
+
items: new Map(),
|
|
5
|
+
decisions: new Map(),
|
|
6
|
+
blockers: new Map(),
|
|
7
|
+
criteria: new Map(),
|
|
8
|
+
evidence: new Map(),
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
export function fold(events) {
|
|
12
|
+
const state = emptyState();
|
|
13
|
+
for (const event of events) {
|
|
14
|
+
applyEvent(state, event);
|
|
15
|
+
}
|
|
16
|
+
for (const blocker of state.blockers.values()) {
|
|
17
|
+
blocker.open = isOpen(blocker, state.items);
|
|
18
|
+
}
|
|
19
|
+
return state;
|
|
20
|
+
}
|
|
21
|
+
/** Open blockers across the whole backlog (SPEC §2.9; report AWAITED bucket, §7). */
|
|
22
|
+
export function openBlockers(state) {
|
|
23
|
+
return [...state.blockers.values()].filter((b) => b.open);
|
|
24
|
+
}
|
|
25
|
+
/** Open blockers targeting a given item. */
|
|
26
|
+
export function openBlockersForItem(state, itemId) {
|
|
27
|
+
return openBlockers(state).filter((b) => b.targetId === itemId);
|
|
28
|
+
}
|
|
29
|
+
function applyEvent(state, event) {
|
|
30
|
+
switch (event.type) {
|
|
31
|
+
case 'item.created': {
|
|
32
|
+
const payload = event.payload;
|
|
33
|
+
const item = {
|
|
34
|
+
id: event.aggregateId,
|
|
35
|
+
kind: payload.kind,
|
|
36
|
+
title: payload.title,
|
|
37
|
+
workspace: payload.workspace,
|
|
38
|
+
specStatus: payload.kind === 'decision' ? 'n/a' : 'to-specify',
|
|
39
|
+
realization: 'to-do',
|
|
40
|
+
disposition: { orientation: 'required', commitment: 'required' },
|
|
41
|
+
...(payload.parentId !== undefined ? { parentId: payload.parentId } : {}),
|
|
42
|
+
...(payload.sourceKey !== undefined ? { sourceKey: payload.sourceKey } : {}),
|
|
43
|
+
...(payload.body !== undefined ? { body: payload.body } : {}),
|
|
44
|
+
...(payload.links !== undefined ? { links: payload.links } : {}),
|
|
45
|
+
};
|
|
46
|
+
state.items.set(item.id, item);
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
case 'decision.created': {
|
|
50
|
+
const payload = event.payload;
|
|
51
|
+
const decision = {
|
|
52
|
+
id: event.aggregateId,
|
|
53
|
+
kind: 'decision',
|
|
54
|
+
title: payload.title,
|
|
55
|
+
workspace: payload.workspace,
|
|
56
|
+
realization: 'to-do',
|
|
57
|
+
decisionKind: payload.decisionKind,
|
|
58
|
+
targets: payload.targets,
|
|
59
|
+
outcome: 'pending',
|
|
60
|
+
dossier: payload.dossier,
|
|
61
|
+
...(payload.parentId !== undefined ? { parentId: payload.parentId } : {}),
|
|
62
|
+
...(payload.sourceKey !== undefined ? { sourceKey: payload.sourceKey } : {}),
|
|
63
|
+
...(payload.body !== undefined ? { body: payload.body } : {}),
|
|
64
|
+
...(payload.links !== undefined ? { links: payload.links } : {}),
|
|
65
|
+
};
|
|
66
|
+
state.decisions.set(decision.id, decision);
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
case 'spec.transition': {
|
|
70
|
+
const item = state.items.get(event.aggregateId);
|
|
71
|
+
if (item)
|
|
72
|
+
item.specStatus = event.payload.to;
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
case 'realization.transition': {
|
|
76
|
+
const target = state.items.get(event.aggregateId) ?? state.decisions.get(event.aggregateId);
|
|
77
|
+
if (target)
|
|
78
|
+
target.realization = event.payload.to;
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
case 'decision.outcome': {
|
|
82
|
+
const decision = state.decisions.get(event.aggregateId);
|
|
83
|
+
if (!decision)
|
|
84
|
+
break;
|
|
85
|
+
const to = event.payload.to;
|
|
86
|
+
decision.outcome = to; // legality is checked at append; fold takes the latest in stream order
|
|
87
|
+
if (isSettled(to)) {
|
|
88
|
+
for (const targetId of decision.targets) {
|
|
89
|
+
const target = state.items.get(targetId);
|
|
90
|
+
if (target)
|
|
91
|
+
target.disposition[decision.decisionKind] = 'completed';
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
case 'decision.disposition': {
|
|
97
|
+
const payload = event.payload;
|
|
98
|
+
const item = state.items.get(payload.itemId);
|
|
99
|
+
if (item)
|
|
100
|
+
item.disposition[payload.gate] = payload.disposition;
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
103
|
+
case 'dossier.revised': {
|
|
104
|
+
const decision = state.decisions.get(event.aggregateId);
|
|
105
|
+
if (decision)
|
|
106
|
+
decision.dossier = event.payload.dossier;
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
case 'acceptance.criterion.added': {
|
|
110
|
+
const payload = event.payload;
|
|
111
|
+
state.criteria.set(payload.criterionId, {
|
|
112
|
+
id: payload.criterionId,
|
|
113
|
+
itemId: event.aggregateId,
|
|
114
|
+
statement: payload.statement,
|
|
115
|
+
});
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
case 'acceptance.evidence.linked': {
|
|
119
|
+
const payload = event.payload;
|
|
120
|
+
state.evidence.set(payload.evidenceId, {
|
|
121
|
+
id: payload.evidenceId,
|
|
122
|
+
criterionId: payload.criterionId,
|
|
123
|
+
kind: payload.kind,
|
|
124
|
+
locator: payload.locator,
|
|
125
|
+
});
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
case 'acceptance.run': {
|
|
129
|
+
const payload = event.payload;
|
|
130
|
+
const evidence = state.evidence.get(payload.evidenceId);
|
|
131
|
+
// latest run wins (stream order)
|
|
132
|
+
if (evidence) {
|
|
133
|
+
evidence.latestRun = {
|
|
134
|
+
evidenceId: payload.evidenceId,
|
|
135
|
+
commit: payload.commit,
|
|
136
|
+
env: payload.env,
|
|
137
|
+
runner: payload.runner,
|
|
138
|
+
result: payload.result,
|
|
139
|
+
at: event.at,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
case 'acceptance.waived': {
|
|
145
|
+
const payload = event.payload;
|
|
146
|
+
const criterion = state.criteria.get(payload.criterionId);
|
|
147
|
+
if (criterion) {
|
|
148
|
+
criterion.waiver = {
|
|
149
|
+
criterionId: payload.criterionId,
|
|
150
|
+
reason: payload.reason,
|
|
151
|
+
by: payload.by,
|
|
152
|
+
at: event.at,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
157
|
+
case 'blocker.opened': {
|
|
158
|
+
const payload = event.payload;
|
|
159
|
+
const resolutionRule = payload.resolutionRule ?? (payload.kind === 'dependency' ? 'linked-done' : undefined);
|
|
160
|
+
const blocker = {
|
|
161
|
+
id: event.aggregateId,
|
|
162
|
+
targetId: payload.targetId,
|
|
163
|
+
kind: payload.kind,
|
|
164
|
+
ref: payload.ref,
|
|
165
|
+
reason: payload.reason,
|
|
166
|
+
openedAt: event.at,
|
|
167
|
+
resolvedByEvent: false,
|
|
168
|
+
open: true,
|
|
169
|
+
...(resolutionRule !== undefined ? { resolutionRule } : {}),
|
|
170
|
+
...(payload.owner !== undefined ? { owner: payload.owner } : {}),
|
|
171
|
+
};
|
|
172
|
+
state.blockers.set(blocker.id, blocker);
|
|
173
|
+
break;
|
|
174
|
+
}
|
|
175
|
+
case 'blocker.resolved': {
|
|
176
|
+
const blocker = state.blockers.get(event.aggregateId);
|
|
177
|
+
if (blocker) {
|
|
178
|
+
blocker.resolvedByEvent = true;
|
|
179
|
+
blocker.resolvedAt = event.at;
|
|
180
|
+
}
|
|
181
|
+
break;
|
|
182
|
+
}
|
|
183
|
+
case 'priority.assessed': {
|
|
184
|
+
const payload = event.payload;
|
|
185
|
+
const item = state.items.get(event.aggregateId);
|
|
186
|
+
if (item)
|
|
187
|
+
item.priority = payload; // latest in stream order = live priority (SPEC §2.8)
|
|
188
|
+
break;
|
|
189
|
+
}
|
|
190
|
+
default:
|
|
191
|
+
// branch.imported provenance is folded in Lot 6.
|
|
192
|
+
break;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
function isOpen(blocker, items) {
|
|
196
|
+
if (blocker.resolvedByEvent)
|
|
197
|
+
return false;
|
|
198
|
+
// Dependency default is linked-done (robust even if the rule was omitted upstream).
|
|
199
|
+
if (blocker.kind === 'dependency' && (blocker.resolutionRule ?? 'linked-done') === 'linked-done') {
|
|
200
|
+
// NOTE (open question, flagged for Lot 5): a ref that ends `cancelled`/`rejected` keeps this
|
|
201
|
+
// blocker OPEN (target stays AWAITED) — SPEC §2.9 resolves only on ref `done`. Reversible.
|
|
202
|
+
return items.get(blocker.ref)?.realization !== 'done';
|
|
203
|
+
}
|
|
204
|
+
// decision blockers, manual dependency blockers, and (until Lot 4) linked-accepted stay open
|
|
205
|
+
// until an explicit blocker.resolved event (a decision blocker resolves on its go/no-go batch).
|
|
206
|
+
return true;
|
|
207
|
+
}
|
|
208
|
+
//# sourceMappingURL=fold.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fold.js","sourceRoot":"","sources":["../../src/state/fold.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/state/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,mBAAmB,EAAE,KAAK,KAAK,EAAE,MAAM,WAAW,CAAA;AAC/E,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,YAAY,EACZ,cAAc,EACd,KAAK,eAAe,EACpB,KAAK,QAAQ,GACd,MAAM,eAAe,CAAA"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
// State: fold(events) -> materialized state, rebuildable snapshots (SPEC §2, §3, §4).
|
|
2
|
+
export { fold, openBlockers, openBlockersForItem } from './fold.js';
|
|
3
|
+
export { deserializeState, loadLatestSnapshot, saveSnapshot, serializeState, } from './snapshot.js';
|
|
4
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/state/index.ts"],"names":[],"mappings":"AAAA,sFAAsF;AACtF,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,mBAAmB,EAAc,MAAM,WAAW,CAAA;AAC/E,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,YAAY,EACZ,cAAc,GAGf,MAAM,eAAe,CAAA"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { TrackEvent } from '../events/types.js';
|
|
2
|
+
import type { CriterionState, EvidenceState } from '../model/acceptance.js';
|
|
3
|
+
import type { BlockerState } from '../model/blocker.js';
|
|
4
|
+
import type { DecisionState } from '../model/decision.js';
|
|
5
|
+
import type { ItemState } from '../model/item.js';
|
|
6
|
+
import { type State } from './fold.js';
|
|
7
|
+
/**
|
|
8
|
+
* Snapshots are NON-AUTHORITATIVE caches of `fold(events)` keyed by stream length
|
|
9
|
+
* (SPEC §4: `.track/snapshots/<len>.json`). The append-only log is always the source of truth;
|
|
10
|
+
* a snapshot can be deleted and rebuilt by re-folding.
|
|
11
|
+
*/
|
|
12
|
+
export interface SerializedState {
|
|
13
|
+
items: ItemState[];
|
|
14
|
+
decisions: DecisionState[];
|
|
15
|
+
blockers: BlockerState[];
|
|
16
|
+
criteria: CriterionState[];
|
|
17
|
+
evidence: EvidenceState[];
|
|
18
|
+
}
|
|
19
|
+
export interface Snapshot {
|
|
20
|
+
streamLength: number;
|
|
21
|
+
state: SerializedState;
|
|
22
|
+
}
|
|
23
|
+
export declare function serializeState(state: State): SerializedState;
|
|
24
|
+
export declare function deserializeState(serialized: Partial<SerializedState>): State;
|
|
25
|
+
export declare function saveSnapshot(trackDir: string, events: ReadonlyArray<TrackEvent>): Snapshot;
|
|
26
|
+
export declare function loadLatestSnapshot(trackDir: string): Snapshot | null;
|
|
27
|
+
//# sourceMappingURL=snapshot.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot.d.ts","sourceRoot":"","sources":["../../src/state/snapshot.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAC3E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACzD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AACjD,OAAO,EAAQ,KAAK,KAAK,EAAE,MAAM,WAAW,CAAA;AAE5C;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,SAAS,EAAE,CAAA;IAClB,SAAS,EAAE,aAAa,EAAE,CAAA;IAC1B,QAAQ,EAAE,YAAY,EAAE,CAAA;IACxB,QAAQ,EAAE,cAAc,EAAE,CAAA;IAC1B,QAAQ,EAAE,aAAa,EAAE,CAAA;CAC1B;AAED,MAAM,WAAW,QAAQ;IACvB,YAAY,EAAE,MAAM,CAAA;IACpB,KAAK,EAAE,eAAe,CAAA;CACvB;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,KAAK,GAAG,eAAe,CAS5D;AAED,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,KAAK,CAU5E;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,UAAU,CAAC,GAAG,QAAQ,CAS1F;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAWpE"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { fold } from './fold.js';
|
|
4
|
+
export function serializeState(state) {
|
|
5
|
+
// Structured-clone so a caller mutating the serialized form cannot corrupt a live fold.
|
|
6
|
+
return {
|
|
7
|
+
items: [...state.items.values()].map((i) => structuredClone(i)),
|
|
8
|
+
decisions: [...state.decisions.values()].map((d) => structuredClone(d)),
|
|
9
|
+
blockers: [...state.blockers.values()].map((b) => structuredClone(b)),
|
|
10
|
+
criteria: [...state.criteria.values()].map((c) => structuredClone(c)),
|
|
11
|
+
evidence: [...state.evidence.values()].map((e) => structuredClone(e)),
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export function deserializeState(serialized) {
|
|
15
|
+
// Tolerate older (pre-Lot-4) snapshots missing newer collections — they are non-authoritative
|
|
16
|
+
// and rebuildable, so an absent array defaults to empty rather than crashing.
|
|
17
|
+
return {
|
|
18
|
+
items: new Map((serialized.items ?? []).map((i) => [i.id, i])),
|
|
19
|
+
decisions: new Map((serialized.decisions ?? []).map((d) => [d.id, d])),
|
|
20
|
+
blockers: new Map((serialized.blockers ?? []).map((b) => [b.id, b])),
|
|
21
|
+
criteria: new Map((serialized.criteria ?? []).map((c) => [c.id, c])),
|
|
22
|
+
evidence: new Map((serialized.evidence ?? []).map((e) => [e.id, e])),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
export function saveSnapshot(trackDir, events) {
|
|
26
|
+
const snapshot = {
|
|
27
|
+
streamLength: events.length,
|
|
28
|
+
state: serializeState(fold(events)),
|
|
29
|
+
};
|
|
30
|
+
const dir = join(trackDir, 'snapshots');
|
|
31
|
+
mkdirSync(dir, { recursive: true });
|
|
32
|
+
writeFileSync(join(dir, `${events.length}.json`), JSON.stringify(snapshot, null, 2));
|
|
33
|
+
return snapshot;
|
|
34
|
+
}
|
|
35
|
+
export function loadLatestSnapshot(trackDir) {
|
|
36
|
+
const dir = join(trackDir, 'snapshots');
|
|
37
|
+
if (!existsSync(dir))
|
|
38
|
+
return null;
|
|
39
|
+
const lengths = readdirSync(dir)
|
|
40
|
+
.filter((f) => f.endsWith('.json'))
|
|
41
|
+
.map((f) => Number.parseInt(f, 10))
|
|
42
|
+
.filter((n) => !Number.isNaN(n))
|
|
43
|
+
.sort((a, b) => b - a);
|
|
44
|
+
const latest = lengths[0];
|
|
45
|
+
if (latest === undefined)
|
|
46
|
+
return null;
|
|
47
|
+
return JSON.parse(readFileSync(join(dir, `${latest}.json`), 'utf8'));
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=snapshot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../../src/state/snapshot.ts"],"names":[],"mappings":"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"}
|
package/dist/track.d.ts
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { EventStore } from './events/store.js';
|
|
2
|
+
import type { ActorId, Ulid } from './events/types.js';
|
|
3
|
+
import { type RunReportFormat } from './accept/ingest.js';
|
|
4
|
+
import { type QueryFilter, type Report, type ReportOptions, type ReportRow } from './report/build.js';
|
|
5
|
+
import type { EvidenceKind, RunResult } from './model/acceptance.js';
|
|
6
|
+
import { type PriorityAssessment, type WsjfInputs } from './model/priority.js';
|
|
7
|
+
import { type BlockerKind, type ResolutionRule } from './model/blocker.js';
|
|
8
|
+
import { type DecisionCreatedPayload, type Dossier, type Outcome } from './model/decision.js';
|
|
9
|
+
import { type BlockerId, type Disposition, type Gate, type ItemCreatedPayload, type ItemId, type Realization, type SpecStatus } from './model/item.js';
|
|
10
|
+
import { type State } from './state/fold.js';
|
|
11
|
+
export interface ImportResult {
|
|
12
|
+
branchSlug: string;
|
|
13
|
+
featureId: ItemId;
|
|
14
|
+
created: number;
|
|
15
|
+
updated: number;
|
|
16
|
+
}
|
|
17
|
+
export interface TrackOptions {
|
|
18
|
+
/** Injectable clock (ISO-8601 ms). Defaults to wall clock. */
|
|
19
|
+
now?: () => string;
|
|
20
|
+
/** Injectable id generator. Defaults to ULID. */
|
|
21
|
+
newId?: () => Ulid;
|
|
22
|
+
/** Default actor recorded on events. */
|
|
23
|
+
by?: ActorId;
|
|
24
|
+
}
|
|
25
|
+
export interface OpenBlockerInput {
|
|
26
|
+
targetId: ItemId;
|
|
27
|
+
kind: BlockerKind;
|
|
28
|
+
ref: ItemId;
|
|
29
|
+
reason: string;
|
|
30
|
+
resolutionRule?: ResolutionRule;
|
|
31
|
+
owner?: ActorId;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Command facade over the frozen event store (SPEC §6). Each mutating command folds the current
|
|
35
|
+
* state, checks the transition against it (rejecting illegal ones BEFORE any append — SPEC §3),
|
|
36
|
+
* then appends. Lots 3+ extend this with decisions, acceptance, priority.
|
|
37
|
+
*/
|
|
38
|
+
export declare class Track {
|
|
39
|
+
private readonly store;
|
|
40
|
+
private readonly clock;
|
|
41
|
+
private readonly newId;
|
|
42
|
+
private readonly actor;
|
|
43
|
+
constructor(store: EventStore, opts?: TrackOptions);
|
|
44
|
+
/** Materialized state from a full replay of the log. */
|
|
45
|
+
state(): State;
|
|
46
|
+
createItem(input: ItemCreatedPayload): ItemId;
|
|
47
|
+
setSpec(itemId: ItemId, to: SpecStatus): void;
|
|
48
|
+
/**
|
|
49
|
+
* Public realization transitions: `in-progress`, `done`, `cancelled`. `rejected` is NOT
|
|
50
|
+
* settable here — it is the consequence of a `no-go` Decision (SPEC §2.3, §2.6) and is emitted
|
|
51
|
+
* internally by Lot 3's outcome batch (with a `cause`). `assertRealizationTransition(_, _, false)`
|
|
52
|
+
* rejects a direct `→rejected` here.
|
|
53
|
+
*/
|
|
54
|
+
setRealization(itemId: ItemId, to: Realization): void;
|
|
55
|
+
/**
|
|
56
|
+
* Create a Decision (SPEC §2.5): emits `decision.created` + one `blocker.opened` (kind:decision)
|
|
57
|
+
* per target as ONE atomic batch (A7). Targets must be existing non-decision items (A3 recursion
|
|
58
|
+
* guard). The decision starts `outcome:"pending"`, leaving every target AWAITED until it settles.
|
|
59
|
+
*/
|
|
60
|
+
createDecision(input: DecisionCreatedPayload): ItemId;
|
|
61
|
+
/**
|
|
62
|
+
* Settle (or defer) a Decision's outcome (SPEC §2.6). Legal: pending→{go,no-go,deferred};
|
|
63
|
+
* deferred→{go,no-go}; go/no-go terminal. Emits the effect as ONE atomic batch (A5):
|
|
64
|
+
* `go` resolves each target's decision blocker; `no-go` also rejects each non-terminal target
|
|
65
|
+
* (cause:{decisionId}); `deferred` emits only the outcome (target stays AWAITED).
|
|
66
|
+
*/
|
|
67
|
+
setOutcome(decisionId: ItemId, to: Outcome): void;
|
|
68
|
+
reviseDossier(decisionId: ItemId, dossier: Dossier): void;
|
|
69
|
+
/**
|
|
70
|
+
* Set a gate disposition explicitly (SPEC §2.10). `completed` is NOT settable here — it is set
|
|
71
|
+
* automatically when a Decision of that gate targeting the item settles.
|
|
72
|
+
*/
|
|
73
|
+
setDisposition(itemId: ItemId, gate: Gate, disposition: Disposition, reason?: string): void;
|
|
74
|
+
openBlocker(input: OpenBlockerInput): BlockerId;
|
|
75
|
+
resolveBlocker(blockerId: BlockerId): void;
|
|
76
|
+
/** Add an acceptance criterion to a non-decision item (A3 forbids criteria on a Decision). */
|
|
77
|
+
addCriterion(itemId: ItemId, statement: string): string;
|
|
78
|
+
linkEvidence(criterionId: string, kind: EvidenceKind, locator: string): string;
|
|
79
|
+
recordRun(evidenceId: string, run: {
|
|
80
|
+
commit: string;
|
|
81
|
+
env: string;
|
|
82
|
+
runner: string;
|
|
83
|
+
result: RunResult;
|
|
84
|
+
}): void;
|
|
85
|
+
waive(criterionId: string, reason: string): void;
|
|
86
|
+
/**
|
|
87
|
+
* Ingest a test report (`accept run --from`): match each entry to an evidence by `locator` and
|
|
88
|
+
* emit one `acceptance.run` per match as a single atomic batch. Returns the number of runs.
|
|
89
|
+
*/
|
|
90
|
+
ingestRuns(content: string, format: RunReportFormat, run: {
|
|
91
|
+
commit: string;
|
|
92
|
+
env: string;
|
|
93
|
+
runner: string;
|
|
94
|
+
}): number;
|
|
95
|
+
/** Append a WSJF priority assessment; the latest becomes the item's live `priority`. */
|
|
96
|
+
assessPriority(itemId: ItemId, inputs: WsjfInputs): PriorityAssessment;
|
|
97
|
+
/** Bucketed backlog report over non-decision items (SPEC §7). */
|
|
98
|
+
report(options: ReportOptions): Report;
|
|
99
|
+
/** Flat, filtered query over the report rows (SPEC §6). */
|
|
100
|
+
query(filter: QueryFilter, options: ReportOptions): ReportRow[];
|
|
101
|
+
/**
|
|
102
|
+
* Idempotent, read-only import of a `BRANCH.md` file: derive a parent `feature` Item + one
|
|
103
|
+
* `chore` Item per lot (resolved by stable `sourceKey = branchSlug/lotSlug`), map lot `[x]`→done
|
|
104
|
+
* and nested UAT checkboxes → acceptance criteria (`[x]` → a manual pass run). Re-import emits
|
|
105
|
+
* ONLY deltas (survives lot reordering) and NEVER writes the file. Returns the change counts.
|
|
106
|
+
*/
|
|
107
|
+
importBranch(content: string, opts: {
|
|
108
|
+
locator: string;
|
|
109
|
+
fileSlug?: string;
|
|
110
|
+
commit?: string;
|
|
111
|
+
}): ImportResult;
|
|
112
|
+
private evidenceOwner;
|
|
113
|
+
private requireItem;
|
|
114
|
+
private emit;
|
|
115
|
+
/** Append a command's events; a multi-event command is one atomic `cmdId` batch (SPEC §3). */
|
|
116
|
+
private emitBatch;
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=track.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"track.d.ts","sourceRoot":"","sources":["../src/track.ts"],"names":[],"mappings":"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"}
|