@assuredloop/cli 3.0.0 → 3.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/package.json +1 -1
- package/src/v4/blocks.js +1 -1
- package/src/v4/checks.js +19 -4
- package/src/v4/state.js +3 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@assuredloop/cli",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"description": "AssuredLoop keeps an AI focused on one change: the al command gathers and checks a change's requirement, spec, decisions, code and tests.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
package/src/v4/blocks.js
CHANGED
|
@@ -175,7 +175,7 @@ export const citedMessage = (c) => (c.next.length
|
|
|
175
175
|
|
|
176
176
|
// The ADR that a link value or word names: `ADR-n` and `ADR-n-k` name ADR-n.
|
|
177
177
|
const ADR_REF = /^ADR-(\d+)(?:-\d+)?$/;
|
|
178
|
-
const adrOf = (ref) => (ADR_REF.test(ref) ? `ADR-${Number(ADR_REF.exec(ref)[1])}` : null);
|
|
178
|
+
export const adrOf = (ref) => (ADR_REF.test(ref) ? `ADR-${Number(ADR_REF.exec(ref)[1])}` : null);
|
|
179
179
|
const MARKER = /^\s*<!--(.*)-->\s*$/;
|
|
180
180
|
|
|
181
181
|
// The words that name ADRs in a text (adr-lists R1): `ADR-n`, or the number
|
package/src/v4/checks.js
CHANGED
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
import { NEAR, closeness, diffWords, marks, requirementWords, sentencesOf, showHunk } from './words.js';
|
|
19
19
|
import { groupOf, markerLines, onlyLinksAdded, sameBlocks } from './markers.js';
|
|
20
20
|
import { canAlignTo, declaredNow, isCentral } from './indexer.js';
|
|
21
|
-
import { recordBlocks, supersededBlocks } from './blocks.js';
|
|
21
|
+
import { adrOf, recordBlocks, supersededBlocks } from './blocks.js';
|
|
22
22
|
import { phraseFindings } from './phrases.js';
|
|
23
23
|
import { issueHints } from './issues.js';
|
|
24
24
|
|
|
@@ -388,11 +388,22 @@ export function checks(top, { base, phrases = [], issues = null }) {
|
|
|
388
388
|
// changed (#4) and the rest unchanged; that gives no finding.
|
|
389
389
|
const linksAdded = (a, h) => a.status === 'accepted' && a.head && h.head && a.rest === h.rest
|
|
390
390
|
&& onlyLinksAdded(a.marker, h.marker, now.kinds);
|
|
391
|
+
// A status goes only forward: accepted to superseded, and a superseded-by
|
|
392
|
+
// list only gains ADRs (#31). Any other change of a known status line is a
|
|
393
|
+
// change of the ADR; an unknown one has its own hint, adr-status.
|
|
394
|
+
const statusBack = (a, h) => h.known
|
|
395
|
+
&& !(h.status === 'superseded' ? a.by.every((b) => h.by.includes(b)) : h.status === a.status);
|
|
391
396
|
for (const [id, a] of was?.adrs ?? []) {
|
|
392
397
|
if (!['accepted', 'superseded'].includes(a.status)) continue;
|
|
393
398
|
const h = now.adrs.get(id);
|
|
394
|
-
if (!h)
|
|
395
|
-
|
|
399
|
+
if (!h) {
|
|
400
|
+
add('hint', 'adr-changed', a.file, id, `${id} was ${a.status} and its file is gone: check that its decision is not lost; an ADR that no longer holds is superseded by a new ADR, not deleted`);
|
|
401
|
+
continue;
|
|
402
|
+
}
|
|
403
|
+
const back = statusBack(a, h);
|
|
404
|
+
const changed = h.body !== a.body && !linksAdded(a, h);
|
|
405
|
+
if (back) add('hint', 'adr-changed', h.head ?? h.file, id, `${id}'s status changed from "${a.line}" to "${h.line}"${changed ? ', and its text changed' : ''}, but a status goes only forward: proposed, accepted, superseded by ADR-n; check that its decision is unchanged; if the decision changed, write a new ADR that supersedes it`);
|
|
406
|
+
else if (changed) add('hint', 'adr-changed', h.head ?? h.file, id, `${id}'s text changed: check that its decision is unchanged; if the decision changed, write a new ADR that supersedes it`);
|
|
396
407
|
}
|
|
397
408
|
// Every ADR, whatever its status (#4): a first line that is not a known
|
|
398
409
|
// status, and a marker line that holds more than its ID, a kind and links.
|
|
@@ -410,9 +421,13 @@ export function checks(top, { base, phrases = [], issues = null }) {
|
|
|
410
421
|
if (missing.length) add('hint', 'adr-links', a.head ?? a.file, a.id, `${a.id} has ${missing.map((w) => `no ${w}:`).join(' and ')}; add the links to its marker`);
|
|
411
422
|
}
|
|
412
423
|
for (const a of now.adrs.values()) {
|
|
413
|
-
|
|
424
|
+
// ADR-n-k, a paragraph of ADR-n, names ADR-n (schema.md 5), once each.
|
|
425
|
+
for (const old of new Set((a.head?.links.supersedes ?? []).map(adrOf).filter(Boolean))) {
|
|
414
426
|
const o = now.adrs.get(old);
|
|
415
427
|
if (o && o.status !== 'superseded') add('hint', 'adr-supersede', a.head, a.id, `${a.id} supersedes ${old}, whose status is ${o.status ?? 'missing'}; set it to superseded`);
|
|
428
|
+
// The other direction of superseded-status (#31): the status line of
|
|
429
|
+
// the superseded ADR names each ADR that supersedes it.
|
|
430
|
+
else if (o && !o.by.includes(a.id)) add('hint', 'adr-supersede', a.head, a.id, `${a.id} supersedes ${old}, but the status line of ${old} leaves out ${a.id}: write "Status: superseded by ${[...o.by, a.id].join(', ')}"`);
|
|
416
431
|
}
|
|
417
432
|
}
|
|
418
433
|
for (const c of changes.filter((x) => !x.request)) {
|
package/src/v4/state.js
CHANGED
|
@@ -175,7 +175,9 @@ export function loadState(top, rev = null) {
|
|
|
175
175
|
const by = [...new Set([...(s?.[2] ?? '').matchAll(/ADR-(\d+)/gi)].map((m) => `ADR-${Number(m[1])}`))];
|
|
176
176
|
const known = Boolean(s) && !/[\r\n]/.test(s[1]);
|
|
177
177
|
const marker = head && lf(text).split('\n')[head.line - 1];
|
|
178
|
-
|
|
178
|
+
// The words after `Status:`, for a hint that names a changed status (#31).
|
|
179
|
+
const line = /^\s*Status:[ \t]*([^\r\n]*)/i.exec(text)?.[1].trim() ?? null;
|
|
180
|
+
adrs.set(id, { id, file, text, status, by, known, line, body: adrBody(text), rest: head && adrRest(text, head), paragraphs, head, marker });
|
|
179
181
|
}
|
|
180
182
|
return { top, rev, config, kinds, root, get, docs, scopes, lints, spec, requests, adrs, unreadableAdrs };
|
|
181
183
|
}
|