@rundiffusion/ledger 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/dist/ledger.js ADDED
@@ -0,0 +1,445 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { DONE_WHEN, PRIORITIES, SHIPLOG_KINDS, SHIPLOG_STATUSES, TASK_STATUSES, TASK_TYPES, } from './types.js';
4
+ import { checkboxState, readMarkdown, section } from './markdown.js';
5
+ import { changedCodeFiles, changedLedgerFiles, commitSubjects, currentBranch, dirtyLedgerFiles, ensureCommit, remoteRefs, tracked, } from './git.js';
6
+ import { ageDays, asObject, asString, asStringList, isPlaceholder, repoRelative, safeRepoPath, validDate, } from './util.js';
7
+ const TASK_IGNORED = new Set(['README.md', 'TEMPLATE.md']);
8
+ const SHIPLOG_IGNORED = new Set(['README.md', 'TEMPLATE.md']);
9
+ const PENDING_SHIPLOG = new Set(['pending-delivery', 'pending-verification']);
10
+ function markdownFiles(directory, ignored) {
11
+ if (!fs.existsSync(directory))
12
+ return [];
13
+ const output = [];
14
+ const visit = (current) => {
15
+ for (const entry of fs.readdirSync(current, { withFileTypes: true })) {
16
+ const file = path.join(current, entry.name);
17
+ if (entry.isDirectory())
18
+ visit(file);
19
+ else if (entry.isFile() && entry.name.endsWith('.md') && !ignored.has(entry.name))
20
+ output.push(file);
21
+ }
22
+ };
23
+ visit(directory);
24
+ return output.sort();
25
+ }
26
+ export function loadTasks(root) {
27
+ return markdownFiles(path.join(root, 'tasks'), TASK_IGNORED).map(file => {
28
+ const parsed = readMarkdown(file);
29
+ const data = parsed.data;
30
+ return {
31
+ ...parsed,
32
+ file,
33
+ relativePath: repoRelative(root, file),
34
+ id: asString(data.id),
35
+ title: asString(data.title),
36
+ status: asString(data.status),
37
+ priority: asString(data.priority),
38
+ type: asString(data.type),
39
+ doneWhen: asString(data.done_when),
40
+ areas: asStringList(data.areas) ?? [],
41
+ dependsOn: asStringList(data.depends_on) ?? [],
42
+ created: asString(data.created),
43
+ updated: asString(data.updated),
44
+ };
45
+ });
46
+ }
47
+ export function loadShiplogs(root) {
48
+ return markdownFiles(path.join(root, 'shiplog'), SHIPLOG_IGNORED).map(file => {
49
+ const parsed = readMarkdown(file);
50
+ const data = parsed.data;
51
+ return {
52
+ ...parsed,
53
+ file,
54
+ relativePath: repoRelative(root, file),
55
+ title: asString(data.title),
56
+ date: asString(data.date),
57
+ kind: asString(data.kind),
58
+ status: asString(data.status),
59
+ tasks: asStringList(data.tasks) ?? [],
60
+ responsible: asString(data.responsible),
61
+ };
62
+ });
63
+ }
64
+ function finding(findings, severity, code, scope, message, responsible) {
65
+ findings.push({ severity, code, scope, message, ...(responsible ? { responsible } : {}) });
66
+ }
67
+ function validateTaskShape(task, config, findings) {
68
+ const scope = task.relativePath;
69
+ const idRegex = new RegExp(config.id_pattern);
70
+ if (!task.id || !idRegex.test(task.id))
71
+ finding(findings, 'error', 'task.id', scope, `invalid id: ${task.id || '(missing)'}`);
72
+ const basename = path.basename(task.file);
73
+ if (task.id && !basename.startsWith(`${task.id}-`))
74
+ finding(findings, 'error', 'task.filename', scope, `filename must begin ${task.id}-`);
75
+ if (!task.title || isPlaceholder(task.title))
76
+ finding(findings, 'error', 'task.title', scope, 'title must be factual and non-placeholder');
77
+ if (!TASK_STATUSES.includes(task.status))
78
+ finding(findings, 'error', 'task.status', scope, `invalid status: ${task.status || '(missing)'}`);
79
+ if (!PRIORITIES.includes(task.priority))
80
+ finding(findings, 'error', 'task.priority', scope, `invalid priority: ${task.priority || '(missing)'}`);
81
+ if (!TASK_TYPES.includes(task.type))
82
+ finding(findings, 'error', 'task.type', scope, `invalid type: ${task.type || '(missing)'}`);
83
+ if (!DONE_WHEN.includes(task.doneWhen))
84
+ finding(findings, 'error', 'task.done_when', scope, `invalid done_when: ${task.doneWhen || '(missing)'}`);
85
+ if (!validDate(task.created))
86
+ finding(findings, 'error', 'task.created', scope, 'created must be YYYY-MM-DD');
87
+ if (!validDate(task.updated))
88
+ finding(findings, 'error', 'task.updated', scope, 'updated must be YYYY-MM-DD');
89
+ for (const field of ['owner', 'claimed_at']) {
90
+ if (Object.hasOwn(task.data, field)) {
91
+ finding(findings, 'error', `task.${field}`, scope, `${field} is derived from the remote work/<ID> ref and must not be stored in task frontmatter`);
92
+ }
93
+ }
94
+ const areas = asStringList(task.data.areas);
95
+ if (!areas?.length)
96
+ finding(findings, 'error', 'task.areas', scope, 'areas must be a non-empty string list');
97
+ else if (config.areas.length) {
98
+ for (const area of areas) {
99
+ if (!config.areas.includes(area))
100
+ finding(findings, 'warning', 'task.area.unknown', scope, `unknown area: ${area}`);
101
+ }
102
+ }
103
+ if (asStringList(task.data.depends_on) === null)
104
+ finding(findings, 'error', 'task.depends_on', scope, 'depends_on must be a string list');
105
+ for (const heading of ['Outcome', 'Context', 'Acceptance criteria', 'Validation', 'Work log']) {
106
+ if (!section(task.body, heading))
107
+ finding(findings, 'error', 'task.section', scope, `missing or empty ${heading} section`);
108
+ }
109
+ for (const heading of ['Acceptance criteria', 'Validation']) {
110
+ const boxes = checkboxState(task.body, heading);
111
+ if (!boxes.total)
112
+ finding(findings, 'error', 'task.checklist', scope, `${heading} must contain at least one checkbox`);
113
+ }
114
+ if (task.type === 'bug') {
115
+ for (const heading of ['Observed', 'Expected', 'Reproduction']) {
116
+ if (!section(task.body, heading))
117
+ finding(findings, 'error', 'task.bug-section', scope, `bug requires ${heading}`);
118
+ }
119
+ }
120
+ const source = asString(task.data.source);
121
+ if (source && isPlaceholder(source))
122
+ finding(findings, 'error', 'task.source', scope, 'source must be factual when supplied');
123
+ const handoff = asObject(task.data.handoff);
124
+ if (task.data.handoff !== undefined && !handoff) {
125
+ finding(findings, 'error', 'task.handoff', scope, 'handoff must be a mapping');
126
+ }
127
+ else if (handoff) {
128
+ const ref = asString(handoff.ref);
129
+ const commit = asString(handoff.commit);
130
+ const sourceBranch = asString(handoff.source_branch);
131
+ if (ref !== `handoff/${task.id}`)
132
+ finding(findings, 'error', 'task.handoff.ref', scope, `handoff ref must be handoff/${task.id}`);
133
+ if (!/^[0-9a-f]{40}$/i.test(commit))
134
+ finding(findings, 'error', 'task.handoff.commit', scope, 'handoff commit must be a full Git SHA');
135
+ if (!sourceBranch || isPlaceholder(sourceBranch))
136
+ finding(findings, 'error', 'task.handoff.source', scope, 'handoff source_branch must be factual');
137
+ }
138
+ const shiplog = asString(task.data.shiplog);
139
+ if (shiplog && (!safeRepoPath(shiplog) || !shiplog.startsWith('shiplog/'))) {
140
+ finding(findings, 'error', 'task.shiplog', scope, 'shiplog must be a repo-relative shiplog/ path');
141
+ }
142
+ if (task.status === 'blocked') {
143
+ const reason = asString(task.data.blocked_reason);
144
+ if (!reason || isPlaceholder(reason))
145
+ finding(findings, 'error', 'task.blocked_reason', scope, 'blocked tasks require blocked_reason');
146
+ }
147
+ if (task.status === 'done') {
148
+ if (!validDate(asString(task.data.completed)))
149
+ finding(findings, 'error', 'task.completed', scope, 'done tasks require completed date');
150
+ if (checkboxState(task.body, 'Acceptance criteria').unchecked)
151
+ finding(findings, 'error', 'task.acceptance.incomplete', scope, 'done task has unchecked acceptance criteria');
152
+ if (checkboxState(task.body, 'Validation').unchecked)
153
+ finding(findings, 'error', 'task.validation.incomplete', scope, 'done task has unchecked validation');
154
+ }
155
+ }
156
+ function validateShiplogShape(shiplog, findings) {
157
+ const scope = shiplog.relativePath;
158
+ const prefix = /^(\d{4}-\d{2}-\d{2})-/.exec(path.basename(shiplog.file))?.[1] ?? '';
159
+ if (!prefix)
160
+ finding(findings, 'error', 'shiplog.filename', scope, 'filename must begin YYYY-MM-DD-');
161
+ if (!shiplog.title || isPlaceholder(shiplog.title))
162
+ finding(findings, 'error', 'shiplog.title', scope, 'title must be factual');
163
+ if (!validDate(shiplog.date))
164
+ finding(findings, 'error', 'shiplog.date', scope, 'date must be YYYY-MM-DD');
165
+ if (prefix && shiplog.date !== prefix)
166
+ finding(findings, 'error', 'shiplog.date-match', scope, `date ${shiplog.date} does not match filename`);
167
+ if (!SHIPLOG_KINDS.includes(shiplog.kind))
168
+ finding(findings, 'error', 'shiplog.kind', scope, `invalid kind: ${shiplog.kind || '(missing)'}`);
169
+ if (!SHIPLOG_STATUSES.includes(shiplog.status))
170
+ finding(findings, 'error', 'shiplog.status', scope, `invalid status: ${shiplog.status || '(missing)'}`);
171
+ const tasks = asStringList(shiplog.data.tasks);
172
+ if (!tasks?.length)
173
+ finding(findings, 'error', 'shiplog.tasks', scope, 'tasks must be a non-empty string list');
174
+ const target = asString(shiplog.data.target);
175
+ if (!target || isPlaceholder(target))
176
+ finding(findings, 'error', 'shiplog.target', scope, 'target must be factual and non-placeholder');
177
+ const commit = asString(shiplog.data.commit);
178
+ const external = asString(shiplog.data.external_reference);
179
+ if (Boolean(commit) === Boolean(external))
180
+ finding(findings, 'error', 'shiplog.provenance', scope, 'supply exactly one of commit or external_reference');
181
+ if (commit && !/^[0-9a-f]{7,40}(?:\.\.[0-9a-f]{7,40})?$/i.test(commit))
182
+ finding(findings, 'error', 'shiplog.commit', scope, 'commit must be a Git SHA or SHA range');
183
+ if (external && isPlaceholder(external))
184
+ finding(findings, 'error', 'shiplog.external', scope, 'external_reference must be factual');
185
+ if (PENDING_SHIPLOG.has(shiplog.status) && (!shiplog.responsible || isPlaceholder(shiplog.responsible))) {
186
+ finding(findings, 'error', 'shiplog.responsible', scope, 'pending shiplogs require responsible');
187
+ }
188
+ for (const heading of ['Evidence', 'Verification', 'History']) {
189
+ if (!section(shiplog.body, heading))
190
+ finding(findings, 'error', 'shiplog.section', scope, `missing or empty ${heading} section`);
191
+ }
192
+ const verification = checkboxState(shiplog.body, 'Verification');
193
+ if (!verification.total)
194
+ finding(findings, 'error', 'shiplog.verification', scope, 'Verification must contain at least one checkbox');
195
+ if (shiplog.status === 'verified' && verification.unchecked)
196
+ finding(findings, 'error', 'shiplog.verification.incomplete', scope, 'verified shiplog has unchecked verification');
197
+ }
198
+ function validateGraph(tasks, findings) {
199
+ const byId = new Map();
200
+ for (const task of tasks) {
201
+ if (task.id && byId.has(task.id))
202
+ finding(findings, 'error', 'task.id.duplicate', task.relativePath, `duplicate id also used by ${byId.get(task.id)?.relativePath}`);
203
+ else if (task.id)
204
+ byId.set(task.id, task);
205
+ }
206
+ for (const task of tasks) {
207
+ for (const dependency of task.dependsOn) {
208
+ if (!byId.has(dependency))
209
+ finding(findings, 'error', 'task.dependency.missing', task.relativePath, `missing dependency ${dependency}`);
210
+ if (dependency === task.id)
211
+ finding(findings, 'error', 'task.dependency.self', task.relativePath, 'task cannot depend on itself');
212
+ }
213
+ }
214
+ const visiting = new Set();
215
+ const visited = new Set();
216
+ const visit = (id, chain) => {
217
+ if (visiting.has(id)) {
218
+ finding(findings, 'error', 'task.dependency.cycle', byId.get(id)?.relativePath ?? id, `dependency cycle: ${[...chain, id].join(' -> ')}`);
219
+ return;
220
+ }
221
+ if (visited.has(id))
222
+ return;
223
+ visiting.add(id);
224
+ const task = byId.get(id);
225
+ if (task)
226
+ for (const dependency of task.dependsOn)
227
+ visit(dependency, [...chain, id]);
228
+ visiting.delete(id);
229
+ visited.add(id);
230
+ };
231
+ for (const id of byId.keys())
232
+ visit(id, []);
233
+ }
234
+ function validateRelationships(tasks, shiplogs, findings) {
235
+ const byId = new Map(tasks.map(task => [task.id, task]));
236
+ const byPath = new Map(shiplogs.map(shiplog => [shiplog.relativePath, shiplog]));
237
+ const activeByTask = new Map();
238
+ for (const shiplog of shiplogs) {
239
+ for (const id of shiplog.tasks) {
240
+ const task = byId.get(id);
241
+ if (!task) {
242
+ finding(findings, 'error', 'shiplog.task.missing', shiplog.relativePath, `unknown task ${id}`);
243
+ continue;
244
+ }
245
+ if (asString(task.data.shiplog) !== shiplog.relativePath)
246
+ finding(findings, 'error', 'shiplog.task.reciprocal', shiplog.relativePath, `${id} does not point back to this shiplog`);
247
+ if (PENDING_SHIPLOG.has(shiplog.status))
248
+ activeByTask.set(id, [...(activeByTask.get(id) ?? []), shiplog.relativePath]);
249
+ const expectedKind = task.doneWhen === 'released' ? 'release' : 'deploy';
250
+ if (task.doneWhen !== 'merged' && shiplog.kind !== expectedKind)
251
+ finding(findings, 'error', 'shiplog.kind.task', shiplog.relativePath, `${id} done_when ${task.doneWhen} requires kind ${expectedKind}`);
252
+ }
253
+ }
254
+ for (const task of tasks) {
255
+ const shiplogPath = asString(task.data.shiplog);
256
+ if (shiplogPath) {
257
+ const shiplog = byPath.get(shiplogPath);
258
+ if (!shiplog)
259
+ finding(findings, 'error', 'task.shiplog.missing', task.relativePath, `missing ${shiplogPath}`);
260
+ else if (!shiplog.tasks.includes(task.id))
261
+ finding(findings, 'error', 'task.shiplog.reciprocal', task.relativePath, `${shiplogPath} does not list ${task.id}`);
262
+ }
263
+ const active = activeByTask.get(task.id) ?? [];
264
+ if (active.length > 1)
265
+ finding(findings, 'error', 'task.shiplog.multiple', task.relativePath, `multiple pending shiplogs: ${active.join(', ')}`);
266
+ if (task.status === 'done' && task.doneWhen !== 'merged') {
267
+ const shiplog = shiplogPath ? byPath.get(shiplogPath) : undefined;
268
+ if (!shiplog || shiplog.status !== 'verified')
269
+ finding(findings, 'error', 'task.done.evidence', task.relativePath, `done_when ${task.doneWhen} requires a verified shiplog`);
270
+ }
271
+ }
272
+ }
273
+ function provenanceRefs(task, shiplog) {
274
+ const refs = [];
275
+ const handoff = asObject(task.data.handoff);
276
+ const handoffCommit = handoff ? asString(handoff.commit) : '';
277
+ if (handoffCommit)
278
+ refs.push(handoffCommit);
279
+ if (shiplog) {
280
+ const commit = asString(shiplog.data.commit);
281
+ if (commit)
282
+ refs.push(...commit.split('..'));
283
+ }
284
+ return refs;
285
+ }
286
+ export function validateLedger(root, config, options = {}) {
287
+ const findings = [];
288
+ let tasks = [];
289
+ let shiplogs = [];
290
+ try {
291
+ tasks = loadTasks(root);
292
+ }
293
+ catch (error) {
294
+ finding(findings, 'error', 'tasks.parse', 'tasks', error instanceof Error ? error.message : String(error));
295
+ }
296
+ try {
297
+ shiplogs = loadShiplogs(root);
298
+ }
299
+ catch (error) {
300
+ finding(findings, 'error', 'shiplog.parse', 'shiplog', error instanceof Error ? error.message : String(error));
301
+ }
302
+ for (const task of tasks) {
303
+ validateTaskShape(task, config, findings);
304
+ findings.push(...trackedReferenceFindings(root, task));
305
+ }
306
+ for (const shiplog of shiplogs)
307
+ validateShiplogShape(shiplog, findings);
308
+ validateGraph(tasks, findings);
309
+ validateRelationships(tasks, shiplogs, findings);
310
+ if (options.verifyProvenance || options.audit || options.ci) {
311
+ const changed = new Set(options.audit ? [...tasks.map(task => task.relativePath), ...shiplogs.map(item => item.relativePath)] : changedLedgerFiles(root, config));
312
+ const shiplogByPath = new Map(shiplogs.map(item => [item.relativePath, item]));
313
+ for (const task of tasks) {
314
+ const linked = asString(task.data.shiplog);
315
+ const shiplog = linked ? shiplogByPath.get(linked) : undefined;
316
+ if (!options.audit && !changed.has(task.relativePath) && !(shiplog && changed.has(shiplog.relativePath)))
317
+ continue;
318
+ for (const ref of provenanceRefs(task, shiplog)) {
319
+ if (!ensureCommit(root, config, ref, Boolean(options.audit)))
320
+ finding(findings, 'error', 'provenance.missing', task.relativePath, `Git commit not found: ${ref}`);
321
+ }
322
+ }
323
+ }
324
+ if (options.hygiene || options.audit)
325
+ validateHygiene(root, config, tasks, shiplogs, findings);
326
+ if (!options.ci) {
327
+ for (const entry of dirtyLedgerFiles(root))
328
+ finding(findings, 'warning', 'ledger.dirty', 'working tree', `uncommitted ledger file: ${entry.slice(3)}`);
329
+ }
330
+ validateLinkage(root, config, tasks, findings);
331
+ return { findings, tasks, shiplogs };
332
+ }
333
+ function validateLinkage(root, config, tasks, findings) {
334
+ const codeFiles = changedCodeFiles(root, config);
335
+ if (!codeFiles.length)
336
+ return;
337
+ const branch = (() => {
338
+ try {
339
+ return currentBranch(root);
340
+ }
341
+ catch {
342
+ return '';
343
+ }
344
+ })();
345
+ const branchId = /^work\/(.+)$/.exec(branch)?.[1];
346
+ const changedTasks = new Set(changedLedgerFiles(root, config).filter(file => file.startsWith('tasks/')));
347
+ const messages = commitSubjects(root, config).join('\n');
348
+ const linked = tasks.some(task => task.id === branchId || changedTasks.has(task.relativePath) || new RegExp(`(?:Task|RDT):\\s*${task.id}(?:\\s|$)`, 'i').test(messages));
349
+ if (!linked)
350
+ finding(findings, config.linkage === 'required' ? 'error' : 'warning', 'code.task-link', 'pull request', `code changes (${codeFiles.length} files) have no task linkage`);
351
+ }
352
+ function validateHygiene(root, config, tasks, shiplogs, findings) {
353
+ const byId = new Map(tasks.map(task => [task.id, task]));
354
+ const claims = remoteRefs(root, config, 'work/');
355
+ for (const claim of claims) {
356
+ const id = claim.name.slice('work/'.length);
357
+ const task = byId.get(id);
358
+ if (!task)
359
+ finding(findings, 'warning', 'claim.orphan', claim.name, 'claim has no task');
360
+ else if (task.status === 'done' || task.status === 'cancelled')
361
+ finding(findings, 'warning', 'claim.closed', claim.name, `claim remains for ${task.status} task`);
362
+ const date = claim.date.slice(0, 10);
363
+ if (ageDays(date) > config.claim_stale_days)
364
+ finding(findings, 'warning', 'claim.stale', claim.name, `claim has been idle ${ageDays(date)} days`, claim.author || undefined);
365
+ }
366
+ for (const handoff of remoteRefs(root, config, 'handoff/')) {
367
+ const id = handoff.name.slice('handoff/'.length);
368
+ const task = byId.get(id);
369
+ if (!task)
370
+ finding(findings, 'warning', 'handoff.orphan', handoff.name, 'handoff has no task');
371
+ else {
372
+ const metadata = asObject(task.data.handoff);
373
+ if (!metadata || asString(metadata.commit) !== handoff.sha)
374
+ finding(findings, 'warning', 'handoff.divergence', handoff.name, 'task metadata does not pin this handoff SHA');
375
+ }
376
+ }
377
+ for (const shiplog of shiplogs) {
378
+ if (PENDING_SHIPLOG.has(shiplog.status)) {
379
+ const updated = asString(shiplog.data.updated) || shiplog.date;
380
+ if (ageDays(updated) > config.delivery_stale_days)
381
+ finding(findings, 'warning', 'delivery.stale', shiplog.relativePath, `${shiplog.status} has been open ${ageDays(updated)} days`, shiplog.responsible || undefined);
382
+ }
383
+ }
384
+ for (const task of tasks) {
385
+ if (task.status === 'blocked' && ageDays(task.updated) > config.blocked_stale_days)
386
+ finding(findings, 'warning', 'task.blocked.stale', task.relativePath, `blocked task has not changed for ${ageDays(task.updated)} days`);
387
+ }
388
+ }
389
+ export function claimMap(root, config) {
390
+ return new Map(remoteRefs(root, config, 'work/').map(ref => [ref.name.slice('work/'.length), ref]));
391
+ }
392
+ export function pendingByTask(shiplogs) {
393
+ const pending = new Map();
394
+ for (const shiplog of shiplogs) {
395
+ if (!PENDING_SHIPLOG.has(shiplog.status))
396
+ continue;
397
+ for (const id of shiplog.tasks)
398
+ pending.set(id, shiplog);
399
+ }
400
+ return pending;
401
+ }
402
+ export function eligibleTasks(tasks, shiplogs, claims) {
403
+ const byId = new Map(tasks.map(task => [task.id, task]));
404
+ const pending = pendingByTask(shiplogs);
405
+ return tasks
406
+ .filter(task => task.status === 'open')
407
+ .filter(task => !claims.has(task.id))
408
+ .filter(task => !pending.has(task.id))
409
+ .filter(task => task.dependsOn.every(id => byId.get(id)?.status === 'done'))
410
+ .sort((left, right) => {
411
+ const priority = PRIORITIES.indexOf(left.priority) - PRIORITIES.indexOf(right.priority);
412
+ return priority || left.created.localeCompare(right.created) || left.id.localeCompare(right.id);
413
+ });
414
+ }
415
+ export function derivedState(task, claims, pending) {
416
+ const shiplog = pending.get(task.id);
417
+ if (shiplog)
418
+ return shiplog.status;
419
+ if (claims.has(task.id))
420
+ return 'active';
421
+ return task.status;
422
+ }
423
+ export function nextTaskId(tasks, config, now = new Date()) {
424
+ const year = now.getFullYear();
425
+ const prefix = `${config.id_prefix}-${year}-`;
426
+ const values = tasks
427
+ .map(task => task.id)
428
+ .filter(id => id.startsWith(prefix))
429
+ .map(id => Number(id.slice(prefix.length)))
430
+ .filter(Number.isInteger);
431
+ const next = Math.max(0, ...values) + 1;
432
+ return `${prefix}${String(next).padStart(3, '0')}`;
433
+ }
434
+ export function trackedReferenceFindings(root, record) {
435
+ const findings = [];
436
+ const related = asStringList(record.data.related) ?? [];
437
+ for (const item of related) {
438
+ if (!safeRepoPath(item))
439
+ finding(findings, 'error', 'task.related.path', record.relativePath, `invalid related path: ${item}`);
440
+ else if (!tracked(root, item) && !fs.existsSync(path.join(root, item)))
441
+ finding(findings, 'warning', 'task.related.missing', record.relativePath, `related path is absent: ${item}`);
442
+ }
443
+ return findings;
444
+ }
445
+ //# sourceMappingURL=ledger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ledger.js","sourceRoot":"","sources":["../src/ledger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { Frontmatter, ParsedMarkdown } from './types.js';
2
+ export declare function parseMarkdown(source: string, scope?: string): ParsedMarkdown;
3
+ export declare function readMarkdown(file: string): ParsedMarkdown;
4
+ export declare function formatMarkdown(data: Frontmatter, body: string): string;
5
+ export declare function writeMarkdown(file: string, data: Frontmatter, body: string): void;
6
+ export declare function section(body: string, name: string): string;
7
+ export declare function hasSection(body: string, name: string): boolean;
8
+ export declare function replaceSection(body: string, name: string, content: string): string;
9
+ export declare function appendHistory(body: string, heading: string, entry: string): string;
10
+ export declare function checkboxState(body: string, heading: string): {
11
+ total: number;
12
+ unchecked: number;
13
+ };
14
+ //# sourceMappingURL=markdown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../src/markdown.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE9D,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,SAAa,GAAG,cAAc,CAWhF;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CAEzD;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAGtE;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAEjF;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAS1D;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAE9D;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAOlF;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAIlF;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAOjG"}
@@ -0,0 +1,61 @@
1
+ import fs from 'node:fs';
2
+ import { parse as parseYaml, stringify as stringifyYaml } from 'yaml';
3
+ export function parseMarkdown(source, scope = 'Markdown') {
4
+ const normalized = source.replace(/\r\n/g, '\n');
5
+ const match = /^---\n([\s\S]*?)\n---(?:\n|$)([\s\S]*)$/.exec(normalized);
6
+ if (!match)
7
+ throw new Error(`${scope} must begin with YAML frontmatter`);
8
+ const yaml = match[1] ?? '';
9
+ const body = match[2] ?? '';
10
+ const parsed = parseYaml(yaml);
11
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
12
+ throw new Error(`${scope} frontmatter must be a mapping`);
13
+ }
14
+ return { data: parsed, body };
15
+ }
16
+ export function readMarkdown(file) {
17
+ return parseMarkdown(fs.readFileSync(file, 'utf8'), file);
18
+ }
19
+ export function formatMarkdown(data, body) {
20
+ const yaml = stringifyYaml(data, { lineWidth: 0 }).trimEnd();
21
+ return `---\n${yaml}\n---\n${body.trim()}\n`;
22
+ }
23
+ export function writeMarkdown(file, data, body) {
24
+ fs.writeFileSync(file, formatMarkdown(data, body), 'utf8');
25
+ }
26
+ export function section(body, name) {
27
+ const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
28
+ const expression = new RegExp(`^##\\s+${escaped}\\s*$`, 'im');
29
+ const match = expression.exec(body);
30
+ if (!match)
31
+ return '';
32
+ const start = match.index + match[0].length;
33
+ const rest = body.slice(start);
34
+ const next = rest.search(/^##\s+/m);
35
+ return (next < 0 ? rest : rest.slice(0, next)).trim();
36
+ }
37
+ export function hasSection(body, name) {
38
+ return section(body, name).length > 0;
39
+ }
40
+ export function replaceSection(body, name, content) {
41
+ const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
42
+ const expression = new RegExp(`(^##\\s+${escaped}\\s*$)([\\s\\S]*?)(?=^##\\s+|(?![\\s\\S]))`, 'im');
43
+ if (!expression.test(body)) {
44
+ return `${body.trimEnd()}\n\n## ${name}\n\n${content.trim()}\n`;
45
+ }
46
+ return body.replace(expression, `$1\n\n${content.trim()}\n\n`);
47
+ }
48
+ export function appendHistory(body, heading, entry) {
49
+ const current = section(body, heading);
50
+ const next = current ? `${current.trimEnd()}\n- ${entry}` : `- ${entry}`;
51
+ return replaceSection(body, heading, next);
52
+ }
53
+ export function checkboxState(body, heading) {
54
+ const content = section(body, heading);
55
+ const boxes = [...content.matchAll(/^\s*[-*]\s+\[([ xX])\]\s+.+$/gm)];
56
+ return {
57
+ total: boxes.length,
58
+ unchecked: boxes.filter(match => (match[1] ?? '').toLowerCase() !== 'x').length,
59
+ };
60
+ }
61
+ //# sourceMappingURL=markdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown.js","sourceRoot":"","sources":["../src/markdown.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,SAAS,IAAI,aAAa,EAAE,MAAM,MAAM,CAAC;AAGtE,MAAM,UAAU,aAAa,CAAC,MAAc,EAAE,KAAK,GAAG,UAAU;IAC9D,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACjD,MAAM,KAAK,GAAG,yCAAyC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACzE,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,mCAAmC,CAAC,CAAC;IACzE,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC5B,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC5B,MAAM,MAAM,GAAY,SAAS,CAAC,IAAI,CAAC,CAAC;IACxC,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACnE,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,gCAAgC,CAAC,CAAC;IAC5D,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,MAAqB,EAAE,IAAI,EAAE,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,OAAO,aAAa,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC;AAC5D,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAAiB,EAAE,IAAY;IAC5D,MAAM,IAAI,GAAG,aAAa,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;IAC7D,OAAO,QAAQ,IAAI,UAAU,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,IAAiB,EAAE,IAAY;IACzE,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC;AAC7D,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,IAAY,EAAE,IAAY;IAChD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;IAC5D,MAAM,UAAU,GAAG,IAAI,MAAM,CAAC,UAAU,OAAO,OAAO,EAAE,IAAI,CAAC,CAAC;IAC9D,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpC,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IACtB,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IAC5C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC/B,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACpC,OAAO,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;AACxD,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,IAAY;IACnD,OAAO,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,IAAY,EAAE,OAAe;IACxE,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;IAC5D,MAAM,UAAU,GAAG,IAAI,MAAM,CAAC,WAAW,OAAO,4CAA4C,EAAE,IAAI,CAAC,CAAC;IACpG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3B,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,UAAU,IAAI,OAAO,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC;IAClE,CAAC;IACD,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,SAAS,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,OAAe,EAAE,KAAa;IACxE,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACvC,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,OAAO,EAAE,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,EAAE,CAAC;IACzE,OAAO,cAAc,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,OAAe;IACzD,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACvC,MAAM,KAAK,GAAG,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,gCAAgC,CAAC,CAAC,CAAC;IACtE,OAAO;QACL,KAAK,EAAE,KAAK,CAAC,MAAM;QACnB,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,KAAK,GAAG,CAAC,CAAC,MAAM;KAChF,CAAC;AACJ,CAAC"}