@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.
Files changed (127) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +84 -0
  3. package/dist/accept/index.d.ts +3 -0
  4. package/dist/accept/index.d.ts.map +1 -0
  5. package/dist/accept/index.js +5 -0
  6. package/dist/accept/index.js.map +1 -0
  7. package/dist/accept/ingest.d.ts +16 -0
  8. package/dist/accept/ingest.d.ts.map +1 -0
  9. package/dist/accept/ingest.js +60 -0
  10. package/dist/accept/ingest.js.map +1 -0
  11. package/dist/accept/status.d.ts +15 -0
  12. package/dist/accept/status.d.ts.map +1 -0
  13. package/dist/accept/status.js +44 -0
  14. package/dist/accept/status.js.map +1 -0
  15. package/dist/branch/index.d.ts +2 -0
  16. package/dist/branch/index.d.ts.map +1 -0
  17. package/dist/branch/index.js +3 -0
  18. package/dist/branch/index.js.map +1 -0
  19. package/dist/branch/parse.d.ts +31 -0
  20. package/dist/branch/parse.d.ts.map +1 -0
  21. package/dist/branch/parse.js +116 -0
  22. package/dist/branch/parse.js.map +1 -0
  23. package/dist/cli/desync.d.ts +14 -0
  24. package/dist/cli/desync.d.ts.map +1 -0
  25. package/dist/cli/desync.js +35 -0
  26. package/dist/cli/desync.js.map +1 -0
  27. package/dist/cli/index.d.ts +8 -0
  28. package/dist/cli/index.d.ts.map +1 -0
  29. package/dist/cli/index.js +402 -0
  30. package/dist/cli/index.js.map +1 -0
  31. package/dist/events/canonical.d.ts +5 -0
  32. package/dist/events/canonical.d.ts.map +1 -0
  33. package/dist/events/canonical.js +134 -0
  34. package/dist/events/canonical.js.map +1 -0
  35. package/dist/events/frame.d.ts +11 -0
  36. package/dist/events/frame.d.ts.map +1 -0
  37. package/dist/events/frame.js +19 -0
  38. package/dist/events/frame.js.map +1 -0
  39. package/dist/events/head.d.ts +21 -0
  40. package/dist/events/head.d.ts.map +1 -0
  41. package/dist/events/head.js +54 -0
  42. package/dist/events/head.js.map +1 -0
  43. package/dist/events/index.d.ts +7 -0
  44. package/dist/events/index.d.ts.map +1 -0
  45. package/dist/events/index.js +9 -0
  46. package/dist/events/index.js.map +1 -0
  47. package/dist/events/store.d.ts +33 -0
  48. package/dist/events/store.d.ts.map +1 -0
  49. package/dist/events/store.js +121 -0
  50. package/dist/events/store.js.map +1 -0
  51. package/dist/events/types.d.ts +42 -0
  52. package/dist/events/types.d.ts.map +1 -0
  53. package/dist/events/types.js +22 -0
  54. package/dist/events/types.js.map +1 -0
  55. package/dist/events/validate.d.ts +72 -0
  56. package/dist/events/validate.d.ts.map +1 -0
  57. package/dist/events/validate.js +210 -0
  58. package/dist/events/validate.js.map +1 -0
  59. package/dist/index.d.ts +10 -0
  60. package/dist/index.d.ts.map +1 -0
  61. package/dist/index.js +11 -0
  62. package/dist/index.js.map +1 -0
  63. package/dist/model/acceptance.d.ts +60 -0
  64. package/dist/model/acceptance.d.ts.map +1 -0
  65. package/dist/model/acceptance.js +2 -0
  66. package/dist/model/acceptance.js.map +1 -0
  67. package/dist/model/blocker.d.ts +33 -0
  68. package/dist/model/blocker.d.ts.map +1 -0
  69. package/dist/model/blocker.js +15 -0
  70. package/dist/model/blocker.js.map +1 -0
  71. package/dist/model/decision.d.ts +59 -0
  72. package/dist/model/decision.d.ts.map +1 -0
  73. package/dist/model/decision.js +17 -0
  74. package/dist/model/decision.js.map +1 -0
  75. package/dist/model/index.d.ts +6 -0
  76. package/dist/model/index.d.ts.map +1 -0
  77. package/dist/model/index.js +7 -0
  78. package/dist/model/index.js.map +1 -0
  79. package/dist/model/item.d.ts +51 -0
  80. package/dist/model/item.d.ts.map +1 -0
  81. package/dist/model/item.js +42 -0
  82. package/dist/model/item.js.map +1 -0
  83. package/dist/model/priority.d.ts +22 -0
  84. package/dist/model/priority.d.ts.map +1 -0
  85. package/dist/model/priority.js +13 -0
  86. package/dist/model/priority.js.map +1 -0
  87. package/dist/priority/index.d.ts +2 -0
  88. package/dist/priority/index.d.ts.map +1 -0
  89. package/dist/priority/index.js +4 -0
  90. package/dist/priority/index.js.map +1 -0
  91. package/dist/report/buckets.d.ts +18 -0
  92. package/dist/report/buckets.d.ts.map +1 -0
  93. package/dist/report/buckets.js +24 -0
  94. package/dist/report/buckets.js.map +1 -0
  95. package/dist/report/build.d.ts +44 -0
  96. package/dist/report/build.d.ts.map +1 -0
  97. package/dist/report/build.js +62 -0
  98. package/dist/report/build.js.map +1 -0
  99. package/dist/report/format.d.ts +5 -0
  100. package/dist/report/format.d.ts.map +1 -0
  101. package/dist/report/format.js +81 -0
  102. package/dist/report/format.js.map +1 -0
  103. package/dist/report/index.d.ts +4 -0
  104. package/dist/report/index.d.ts.map +1 -0
  105. package/dist/report/index.js +5 -0
  106. package/dist/report/index.js.map +1 -0
  107. package/dist/state/fold.d.ts +25 -0
  108. package/dist/state/fold.d.ts.map +1 -0
  109. package/dist/state/fold.js +208 -0
  110. package/dist/state/fold.js.map +1 -0
  111. package/dist/state/index.d.ts +3 -0
  112. package/dist/state/index.d.ts.map +1 -0
  113. package/dist/state/index.js +4 -0
  114. package/dist/state/index.js.map +1 -0
  115. package/dist/state/snapshot.d.ts +27 -0
  116. package/dist/state/snapshot.d.ts.map +1 -0
  117. package/dist/state/snapshot.js +49 -0
  118. package/dist/state/snapshot.js.map +1 -0
  119. package/dist/track.d.ts +118 -0
  120. package/dist/track.d.ts.map +1 -0
  121. package/dist/track.js +450 -0
  122. package/dist/track.js.map +1 -0
  123. package/dist/version.d.ts +2 -0
  124. package/dist/version.d.ts.map +1 -0
  125. package/dist/version.js +2 -0
  126. package/dist/version.js.map +1 -0
  127. package/package.json +58 -0
package/dist/track.js ADDED
@@ -0,0 +1,450 @@
1
+ import { ulid } from 'ulid';
2
+ import { EventStore } from './events/store.js';
3
+ import { parseRunReport } from './accept/ingest.js';
4
+ import { parseBranch, slugify } from './branch/parse.js';
5
+ import { computeHash } from './events/canonical.js';
6
+ import { buildReport, query as runQuery, } from './report/build.js';
7
+ import { WSJF_SCHEME_VERSION, wsjfScore, } from './model/priority.js';
8
+ import { assertManualResolve, } from './model/blocker.js';
9
+ import { assertOutcomeTransition, } from './model/decision.js';
10
+ import { assertRealizationTransition, assertSpecTransition, DomainError, } from './model/item.js';
11
+ import { fold } from './state/fold.js';
12
+ /**
13
+ * Command facade over the frozen event store (SPEC §6). Each mutating command folds the current
14
+ * state, checks the transition against it (rejecting illegal ones BEFORE any append — SPEC §3),
15
+ * then appends. Lots 3+ extend this with decisions, acceptance, priority.
16
+ */
17
+ export class Track {
18
+ store;
19
+ clock;
20
+ newId;
21
+ actor;
22
+ constructor(store, opts = {}) {
23
+ this.store = store;
24
+ this.clock = opts.now ?? (() => new Date().toISOString());
25
+ this.newId = opts.newId ?? (() => ulid());
26
+ this.actor = opts.by ?? 'system';
27
+ }
28
+ /** Materialized state from a full replay of the log. */
29
+ state() {
30
+ return fold(this.store.readAll());
31
+ }
32
+ createItem(input) {
33
+ if (input.kind === 'decision') {
34
+ throw new DomainError('use createDecision for kind:"decision" (Lot 3) — it needs targets, a dossier, and an atomic blocker batch (SPEC §2.5)');
35
+ }
36
+ const itemId = this.newId();
37
+ this.emit('item', itemId, 'item.created', { ...input });
38
+ return itemId;
39
+ }
40
+ setSpec(itemId, to) {
41
+ assertSpecTransition(this.requireItem(itemId), to);
42
+ this.emit('item', itemId, 'spec.transition', { to });
43
+ }
44
+ /**
45
+ * Public realization transitions: `in-progress`, `done`, `cancelled`. `rejected` is NOT
46
+ * settable here — it is the consequence of a `no-go` Decision (SPEC §2.3, §2.6) and is emitted
47
+ * internally by Lot 3's outcome batch (with a `cause`). `assertRealizationTransition(_, _, false)`
48
+ * rejects a direct `→rejected` here.
49
+ */
50
+ setRealization(itemId, to) {
51
+ const state = this.state();
52
+ const item = state.items.get(itemId);
53
+ if (item) {
54
+ assertRealizationTransition(item, to, false);
55
+ this.emit('item', itemId, 'realization.transition', { to });
56
+ return;
57
+ }
58
+ const decision = state.decisions.get(itemId);
59
+ if (decision) {
60
+ assertRealizationTransition(decision, to, false);
61
+ this.emit('decision', itemId, 'realization.transition', { to });
62
+ return;
63
+ }
64
+ throw new DomainError(`unknown item ${itemId}`);
65
+ }
66
+ /**
67
+ * Create a Decision (SPEC §2.5): emits `decision.created` + one `blocker.opened` (kind:decision)
68
+ * per target as ONE atomic batch (A7). Targets must be existing non-decision items (A3 recursion
69
+ * guard). The decision starts `outcome:"pending"`, leaving every target AWAITED until it settles.
70
+ */
71
+ createDecision(input) {
72
+ if (input.targets.length === 0) {
73
+ throw new DomainError('a decision needs at least one target (SPEC §2.5)');
74
+ }
75
+ if (new Set(input.targets).size !== input.targets.length) {
76
+ throw new DomainError('a decision cannot list the same target twice');
77
+ }
78
+ const state = this.state();
79
+ for (const targetId of input.targets) {
80
+ if (state.decisions.has(targetId)) {
81
+ throw new DomainError(`a decision cannot target another decision (${targetId}) [A3]`);
82
+ }
83
+ if (!state.items.has(targetId)) {
84
+ throw new DomainError(`unknown target item ${targetId}`);
85
+ }
86
+ }
87
+ const decisionId = this.newId();
88
+ const parts = [
89
+ { aggregate: 'decision', aggregateId: decisionId, type: 'decision.created', payload: { ...input } },
90
+ ];
91
+ for (const targetId of input.targets) {
92
+ const blockerId = this.newId();
93
+ parts.push({
94
+ aggregate: 'blocker',
95
+ aggregateId: blockerId,
96
+ type: 'blocker.opened',
97
+ payload: {
98
+ blockerId,
99
+ targetId,
100
+ kind: 'decision',
101
+ ref: decisionId,
102
+ reason: `awaiting ${input.decisionKind} decision`,
103
+ },
104
+ });
105
+ }
106
+ this.emitBatch(parts);
107
+ return decisionId;
108
+ }
109
+ /**
110
+ * Settle (or defer) a Decision's outcome (SPEC §2.6). Legal: pending→{go,no-go,deferred};
111
+ * deferred→{go,no-go}; go/no-go terminal. Emits the effect as ONE atomic batch (A5):
112
+ * `go` resolves each target's decision blocker; `no-go` also rejects each non-terminal target
113
+ * (cause:{decisionId}); `deferred` emits only the outcome (target stays AWAITED).
114
+ */
115
+ setOutcome(decisionId, to) {
116
+ const state = this.state();
117
+ const decision = state.decisions.get(decisionId);
118
+ if (!decision)
119
+ throw new DomainError(`unknown decision ${decisionId}`);
120
+ assertOutcomeTransition(decision.outcome, to);
121
+ const parts = [
122
+ { aggregate: 'decision', aggregateId: decisionId, type: 'decision.outcome', payload: { to } },
123
+ ];
124
+ if (to === 'go' || to === 'no-go') {
125
+ for (const targetId of decision.targets) {
126
+ const blocker = [...state.blockers.values()].find((b) => b.kind === 'decision' && b.ref === decisionId && b.targetId === targetId && b.open);
127
+ if (blocker) {
128
+ parts.push({
129
+ aggregate: 'blocker',
130
+ aggregateId: blocker.id,
131
+ type: 'blocker.resolved',
132
+ payload: { blockerId: blocker.id, decisionId },
133
+ });
134
+ }
135
+ if (to === 'no-go') {
136
+ const target = state.items.get(targetId);
137
+ // Reject only NON-terminal targets. A target already done/cancelled/rejected keeps its
138
+ // realization (we do not retro-reject finished work); its decision blocker is still
139
+ // resolved above. Rejecting the whole no-go when a target is terminal would make a
140
+ // decision with an independently-finished (done) target UN-SETTLEABLE forever — strictly
141
+ // worse. (Reviewer split here; the done-under-no-go semantics are flagged for the user.)
142
+ if (target && (target.realization === 'to-do' || target.realization === 'in-progress')) {
143
+ parts.push({
144
+ aggregate: 'item',
145
+ aggregateId: targetId,
146
+ type: 'realization.transition',
147
+ payload: { to: 'rejected', cause: { decisionId } },
148
+ });
149
+ }
150
+ }
151
+ }
152
+ }
153
+ this.emitBatch(parts);
154
+ }
155
+ reviseDossier(decisionId, dossier) {
156
+ if (!this.state().decisions.has(decisionId)) {
157
+ throw new DomainError(`unknown decision ${decisionId}`);
158
+ }
159
+ this.emit('decision', decisionId, 'dossier.revised', { dossier });
160
+ }
161
+ /**
162
+ * Set a gate disposition explicitly (SPEC §2.10). `completed` is NOT settable here — it is set
163
+ * automatically when a Decision of that gate targeting the item settles.
164
+ */
165
+ setDisposition(itemId, gate, disposition, reason) {
166
+ if (disposition === 'completed') {
167
+ throw new DomainError('disposition "completed" is set automatically when a decision settles (SPEC §2.10)');
168
+ }
169
+ if (!this.state().items.has(itemId))
170
+ throw new DomainError(`unknown item ${itemId}`);
171
+ this.emit('item', itemId, 'decision.disposition', {
172
+ itemId,
173
+ gate,
174
+ disposition,
175
+ ...(reason !== undefined ? { reason } : {}),
176
+ });
177
+ }
178
+ openBlocker(input) {
179
+ const state = this.state();
180
+ if (!state.items.has(input.targetId)) {
181
+ throw new DomainError(`unknown target item ${input.targetId}`);
182
+ }
183
+ if (input.kind === 'decision') {
184
+ if (!state.decisions.has(input.ref)) {
185
+ throw new DomainError(`a decision blocker's ref must be an existing decision (${input.ref})`);
186
+ }
187
+ }
188
+ else if (!state.items.has(input.ref)) {
189
+ throw new DomainError(`unknown ref item ${input.ref}`);
190
+ }
191
+ const blockerId = this.newId();
192
+ const resolutionRule = input.kind === 'dependency' ? (input.resolutionRule ?? 'linked-done') : undefined;
193
+ if (resolutionRule === 'linked-accepted') {
194
+ throw new DomainError("resolutionRule 'linked-accepted' is not implemented in the MVP (SPEC §10, v2+) — it would never resolve");
195
+ }
196
+ this.emit('blocker', blockerId, 'blocker.opened', {
197
+ blockerId,
198
+ targetId: input.targetId,
199
+ kind: input.kind,
200
+ ref: input.ref,
201
+ reason: input.reason,
202
+ ...(resolutionRule !== undefined ? { resolutionRule } : {}),
203
+ ...(input.owner !== undefined ? { owner: input.owner } : {}),
204
+ });
205
+ return blockerId;
206
+ }
207
+ resolveBlocker(blockerId) {
208
+ const blocker = this.state().blockers.get(blockerId);
209
+ if (!blocker)
210
+ throw new DomainError(`unknown blocker ${blockerId}`);
211
+ assertManualResolve(blocker);
212
+ if (!blocker.open)
213
+ throw new DomainError(`blocker ${blockerId} is already resolved`);
214
+ this.emit('blocker', blockerId, 'blocker.resolved', { blockerId });
215
+ }
216
+ // ---- Acceptance (SPEC §2.4) ----
217
+ /** Add an acceptance criterion to a non-decision item (A3 forbids criteria on a Decision). */
218
+ addCriterion(itemId, statement) {
219
+ const state = this.state();
220
+ if (state.decisions.has(itemId)) {
221
+ throw new DomainError(`cannot add an acceptance criterion to a decision (${itemId}) [A3]`);
222
+ }
223
+ if (!state.items.has(itemId))
224
+ throw new DomainError(`unknown item ${itemId}`);
225
+ const criterionId = this.newId();
226
+ this.emit('item', itemId, 'acceptance.criterion.added', { criterionId, statement });
227
+ return criterionId;
228
+ }
229
+ linkEvidence(criterionId, kind, locator) {
230
+ const criterion = this.state().criteria.get(criterionId);
231
+ if (!criterion)
232
+ throw new DomainError(`unknown criterion ${criterionId}`);
233
+ const evidenceId = this.newId();
234
+ this.emit('item', criterion.itemId, 'acceptance.evidence.linked', {
235
+ evidenceId,
236
+ criterionId,
237
+ kind,
238
+ locator,
239
+ });
240
+ return evidenceId;
241
+ }
242
+ recordRun(evidenceId, run) {
243
+ this.emit('item', this.evidenceOwner(evidenceId), 'acceptance.run', { evidenceId, ...run });
244
+ }
245
+ waive(criterionId, reason) {
246
+ const criterion = this.state().criteria.get(criterionId);
247
+ if (!criterion)
248
+ throw new DomainError(`unknown criterion ${criterionId}`);
249
+ this.emit('item', criterion.itemId, 'acceptance.waived', {
250
+ criterionId,
251
+ reason,
252
+ by: this.actor,
253
+ });
254
+ }
255
+ /**
256
+ * Ingest a test report (`accept run --from`): match each entry to an evidence by `locator` and
257
+ * emit one `acceptance.run` per match as a single atomic batch. Returns the number of runs.
258
+ */
259
+ ingestRuns(content, format, run) {
260
+ const state = this.state();
261
+ const parts = [];
262
+ for (const entry of parseRunReport(content, format)) {
263
+ // A locator may be shared by several evidence — record the run for ALL of them.
264
+ for (const evidence of state.evidence.values()) {
265
+ if (evidence.locator !== entry.locator)
266
+ continue;
267
+ const criterion = state.criteria.get(evidence.criterionId);
268
+ if (!criterion)
269
+ continue;
270
+ parts.push({
271
+ aggregate: 'item',
272
+ aggregateId: criterion.itemId,
273
+ type: 'acceptance.run',
274
+ payload: {
275
+ evidenceId: evidence.id,
276
+ commit: run.commit,
277
+ env: run.env,
278
+ runner: run.runner,
279
+ result: entry.result,
280
+ },
281
+ });
282
+ }
283
+ }
284
+ if (parts.length === 0)
285
+ return 0;
286
+ this.emitBatch(parts);
287
+ return parts.length;
288
+ }
289
+ // ---- Prioritization (SPEC §2.8) ----
290
+ /** Append a WSJF priority assessment; the latest becomes the item's live `priority`. */
291
+ assessPriority(itemId, inputs) {
292
+ if (!this.state().items.has(itemId))
293
+ throw new DomainError(`unknown item ${itemId}`);
294
+ const assessment = {
295
+ itemId,
296
+ schemeId: 'wsjf',
297
+ schemeVersion: WSJF_SCHEME_VERSION,
298
+ inputs: { ...inputs },
299
+ score: wsjfScore(inputs),
300
+ at: this.clock(),
301
+ };
302
+ this.emit('item', itemId, 'priority.assessed', { ...assessment });
303
+ return assessment;
304
+ }
305
+ // ---- Reporting (read-only, SPEC §6/§7) ----
306
+ /** Bucketed backlog report over non-decision items (SPEC §7). */
307
+ report(options) {
308
+ return buildReport(this.state(), options);
309
+ }
310
+ /** Flat, filtered query over the report rows (SPEC §6). */
311
+ query(filter, options) {
312
+ return runQuery(this.state(), filter, options);
313
+ }
314
+ // ---- BRANCH.md import (SPEC §5) ----
315
+ /**
316
+ * Idempotent, read-only import of a `BRANCH.md` file: derive a parent `feature` Item + one
317
+ * `chore` Item per lot (resolved by stable `sourceKey = branchSlug/lotSlug`), map lot `[x]`→done
318
+ * and nested UAT checkboxes → acceptance criteria (`[x]` → a manual pass run). Re-import emits
319
+ * ONLY deltas (survives lot reordering) and NEVER writes the file. Returns the change counts.
320
+ */
321
+ importBranch(content, opts) {
322
+ const parsed = parseBranch(content, opts.fileSlug !== undefined ? { fileSlug: opts.fileSlug } : {});
323
+ const sourceHash = computeHash(content);
324
+ const link = { kind: 'branch.md', locator: opts.locator };
325
+ let created = 0;
326
+ let updated = 0;
327
+ const findBySourceKey = (sourceKey) => [...this.state().items.values()].find((i) => i.sourceKey === sourceKey);
328
+ const feature = findBySourceKey(parsed.branchSlug);
329
+ const featureId = feature?.id ??
330
+ this.createItem({
331
+ kind: 'feature',
332
+ title: parsed.feature.title || parsed.branchSlug,
333
+ workspace: parsed.branchSlug,
334
+ sourceKey: parsed.branchSlug,
335
+ links: [link],
336
+ ...(parsed.feature.body ? { body: parsed.feature.body } : {}),
337
+ });
338
+ if (!feature)
339
+ created++;
340
+ for (const lot of parsed.lots) {
341
+ const lotKey = `${parsed.branchSlug}/${lot.lotSlug}`;
342
+ const item = findBySourceKey(lotKey);
343
+ const lotId = item?.id ??
344
+ this.createItem({
345
+ kind: 'chore',
346
+ title: lot.title,
347
+ workspace: parsed.branchSlug,
348
+ parentId: featureId,
349
+ sourceKey: lotKey,
350
+ links: [link],
351
+ });
352
+ if (!item)
353
+ created++;
354
+ // checkbox -> realization (forward only; `done` is terminal, so an unchecked lot stays done)
355
+ if (lot.done) {
356
+ const current = this.state().items.get(lotId).realization;
357
+ if (current === 'to-do') {
358
+ this.setRealization(lotId, 'in-progress');
359
+ this.setRealization(lotId, 'done');
360
+ updated++;
361
+ }
362
+ else if (current === 'in-progress') {
363
+ this.setRealization(lotId, 'done');
364
+ updated++;
365
+ }
366
+ }
367
+ // nested UAT -> acceptance criterion (resolved by stable uatSlug; + a manual pass run when [x])
368
+ for (const uat of lot.uat) {
369
+ const existing = [...this.state().criteria.values()].find((c) => c.itemId === lotId && slugify(c.statement) === uat.uatSlug);
370
+ if (existing) {
371
+ // delta: a UAT newly checked [x] records a manual pass run if not already passing
372
+ if (uat.passed) {
373
+ const evidence = [...this.state().evidence.values()].find((e) => e.criterionId === existing.id);
374
+ if (evidence?.latestRun?.result !== 'pass') {
375
+ const evidenceId = evidence?.id ??
376
+ this.linkEvidence(existing.id, 'manual', `${opts.locator}#${uat.uatSlug}`);
377
+ this.recordRun(evidenceId, {
378
+ commit: opts.commit ?? 'HEAD',
379
+ env: 'uat',
380
+ runner: 'manual',
381
+ result: 'pass',
382
+ });
383
+ updated++;
384
+ }
385
+ }
386
+ continue;
387
+ }
388
+ const criterionId = this.addCriterion(lotId, uat.statement);
389
+ const evidenceId = this.linkEvidence(criterionId, 'manual', `${opts.locator}#${uat.uatSlug}`);
390
+ if (uat.passed) {
391
+ this.recordRun(evidenceId, {
392
+ commit: opts.commit ?? 'HEAD',
393
+ env: 'uat',
394
+ runner: 'manual',
395
+ result: 'pass',
396
+ });
397
+ }
398
+ created++;
399
+ }
400
+ }
401
+ // provenance — emitted only when the import actually changed something (no-op re-import is silent)
402
+ if (created + updated > 0) {
403
+ this.emit('item', featureId, 'branch.imported', {
404
+ locator: opts.locator,
405
+ branchSlug: parsed.branchSlug,
406
+ sourceHash,
407
+ });
408
+ }
409
+ return { branchSlug: parsed.branchSlug, featureId, created, updated };
410
+ }
411
+ evidenceOwner(evidenceId) {
412
+ const state = this.state();
413
+ const evidence = state.evidence.get(evidenceId);
414
+ if (!evidence)
415
+ throw new DomainError(`unknown evidence ${evidenceId}`);
416
+ const criterion = state.criteria.get(evidence.criterionId);
417
+ if (!criterion)
418
+ throw new DomainError(`evidence ${evidenceId} references an unknown criterion`);
419
+ return criterion.itemId;
420
+ }
421
+ requireItem(itemId) {
422
+ const item = this.state().items.get(itemId);
423
+ if (!item)
424
+ throw new DomainError(`unknown item ${itemId}`);
425
+ return item;
426
+ }
427
+ emit(aggregate, aggregateId, type, payload) {
428
+ this.emitBatch([{ aggregate, aggregateId, type, payload }]);
429
+ }
430
+ /** Append a command's events; a multi-event command is one atomic `cmdId` batch (SPEC §3). */
431
+ emitBatch(parts) {
432
+ const at = this.clock();
433
+ const events = parts.map((part) => ({
434
+ id: this.newId(),
435
+ type: part.type,
436
+ aggregate: part.aggregate,
437
+ aggregateId: part.aggregateId,
438
+ at,
439
+ by: this.actor,
440
+ payload: part.payload,
441
+ }));
442
+ if (events.length > 1) {
443
+ this.store.appendCommand(events, { cmdId: this.newId() });
444
+ }
445
+ else {
446
+ this.store.appendCommand(events);
447
+ }
448
+ }
449
+ }
450
+ //# sourceMappingURL=track.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"track.js","sourceRoot":"","sources":["../src/track.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare const VERSION = "0.0.0";
2
+ //# sourceMappingURL=version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,OAAO,UAAU,CAAA"}
@@ -0,0 +1,2 @@
1
+ export const VERSION = '0.0.0';
2
+ //# sourceMappingURL=version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAA"}
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "@sentropic/track",
3
+ "version": "0.1.0",
4
+ "description": "Typed product-backlog and spec/plan/UAT system of record for the sentropic ecosystem (record-only MVP).",
5
+ "license": "MIT",
6
+ "author": "Fabien Antoine",
7
+ "homepage": "https://github.com/rhanka/track#readme",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/rhanka/track.git"
11
+ },
12
+ "bugs": {
13
+ "url": "https://github.com/rhanka/track/issues"
14
+ },
15
+ "keywords": [
16
+ "backlog",
17
+ "spec",
18
+ "acceptance",
19
+ "event-sourcing",
20
+ "system-of-record",
21
+ "wsjf",
22
+ "cli"
23
+ ],
24
+ "type": "module",
25
+ "publishConfig": {
26
+ "access": "public"
27
+ },
28
+ "engines": {
29
+ "node": ">=20"
30
+ },
31
+ "bin": {
32
+ "track": "dist/cli/index.js"
33
+ },
34
+ "exports": {
35
+ ".": "./dist/index.js"
36
+ },
37
+ "files": [
38
+ "dist"
39
+ ],
40
+ "scripts": {
41
+ "build": "tsc -p tsconfig.build.json",
42
+ "typecheck": "tsc -p tsconfig.json --noEmit",
43
+ "lint": "tsc -p tsconfig.json --noEmit",
44
+ "test": "vitest run",
45
+ "test:watch": "vitest",
46
+ "dev": "tsx src/cli/index.ts",
47
+ "prepublishOnly": "npm run build"
48
+ },
49
+ "dependencies": {
50
+ "ulid": "^3.0.2"
51
+ },
52
+ "devDependencies": {
53
+ "@types/node": "^25.9.1",
54
+ "tsx": "^4.22.4",
55
+ "typescript": "^6.0.3",
56
+ "vitest": "^4.1.8"
57
+ }
58
+ }