@afokapu/atdd-bun 0.10.3 → 0.10.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -164,6 +164,9 @@ From 0.10.3 each ready record is judged by the delivery policy in `atdd-bun.yaml
|
|
|
164
164
|
a later policy change (dropping or reordering a model, removing a review) never makes a merged record
|
|
165
165
|
fail. Records in progress are judged by the current policy.
|
|
166
166
|
|
|
167
|
+
From 0.10.4 a stage with nothing written (a plan-only or no-op tranche) records no work; a review
|
|
168
|
+
whose range recorded none answers for the latest recorded work before it.
|
|
169
|
+
|
|
167
170
|
Every key is optional; these are the defaults:
|
|
168
171
|
|
|
169
172
|
```yaml
|
|
@@ -11,7 +11,7 @@ terms:
|
|
|
11
11
|
the identity of one process: a session id, a pane id with its start time, or the retained report. Two entries with the same run were produced by the same process.
|
|
12
12
|
- term_id: independence
|
|
13
13
|
text: >-
|
|
14
|
-
fresh-process: the reviewer is a new process that wrote nothing. different-model: additionally, its model wrote none of the work it reviews; the final review answers for red, green and refactor when none of them is reviewed.
|
|
14
|
+
fresh-process: the reviewer is a new process that wrote nothing. different-model: additionally, its model wrote none of the work it reviews; the final review answers for red, green and refactor when none of them is reviewed, and a review whose range recorded no work answers for the latest recorded work before it.
|
|
15
15
|
content:
|
|
16
16
|
summary: >-
|
|
17
17
|
A reviewer that edits becomes a writer, and a reviewer that already saw an earlier round is anchored to it. Independence is what makes an approval evidence.
|
|
@@ -4,7 +4,7 @@ kind: rule
|
|
|
4
4
|
status: active
|
|
5
5
|
name: A ready record has every configured stage approved
|
|
6
6
|
statement: >-
|
|
7
|
-
A record with status ready has, for every stage the policy gives a
|
|
7
|
+
A record with status ready has, for every stage the policy gives a reviewer, a last review that approves (a stage with nothing written records no work); its approved_sha is the SHA the last review of the closing stage approved; and every review names its retained raw report, which exists (REQUIRED).
|
|
8
8
|
terms:
|
|
9
9
|
- term_id: closing_stage
|
|
10
10
|
text: >-
|
package/integrity.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.10.
|
|
2
|
+
"version": "0.10.4",
|
|
3
3
|
"files": {
|
|
4
4
|
"HOOK_AUDIT.md": "5329d840db37671b1918f688ead26865473b87db73dbc75f7c8b2a8bbe8d6d43",
|
|
5
5
|
"PLANNER_PORT.md": "fb5935bac8b7ac18994de21e43ace3a5ef8cd55f85b0e3349fca261280054f11",
|
|
6
|
-
"README.md": "
|
|
6
|
+
"README.md": "afff8ee1ca16773915650f8ed3c1e58bbd839259a7963d16441a0259423c8756",
|
|
7
7
|
"bunfig.toml": "b9fc65eca9014c5179380259d70e76385a6a80788fa9a2df5fb3eaa5554fd2fe",
|
|
8
8
|
"conventions/atdd-bun.planner/atdd-bun.planner.acceptance-identity.convention.yaml": "81c5c773d5ee15e8d99a2c237aa9846b110b2533df45ebf407d0e3ec6ed3dd03",
|
|
9
9
|
"conventions/atdd-bun.planner/atdd-bun.planner.identity-required.convention.yaml": "e96d7c1455d0c221072d82e7f2b55da1c4f9ceb17718eb6ed96affdeef37675b",
|
|
@@ -100,8 +100,8 @@
|
|
|
100
100
|
"conventions/delivery/delivery.model-allowed.convention.yaml": "1071a727f61bacd21d70921885826974234ef0a58c0a814454b9375a0432b0fe",
|
|
101
101
|
"conventions/delivery/delivery.operating-model.convention.yaml": "980858b735974093c98e850d8f6dd83cb21eea86a8b6e8249de678f0fc336f1b",
|
|
102
102
|
"conventions/delivery/delivery.review.convention.yaml": "d71b889a92ca695bc7bc989636ef16272860a4d3389a2f1e2cf3776257e97af8",
|
|
103
|
-
"conventions/delivery/delivery.reviewer-independent.convention.yaml": "
|
|
104
|
-
"conventions/delivery/delivery.stages-complete.convention.yaml": "
|
|
103
|
+
"conventions/delivery/delivery.reviewer-independent.convention.yaml": "8c436d66ef5b1f6d6bc5dd55a235caca2490020e88665eecadb2ca41cd4149c5",
|
|
104
|
+
"conventions/delivery/delivery.stages-complete.convention.yaml": "0e5dd8057ad51eff7906e3424a9686a81be1814447afb9a30acab43d39e49b4c",
|
|
105
105
|
"conventions/planner.docs/planner.docs.adr-registry-derived.convention.yaml": "0ea4232beba90280c664f93d097cafa44c67c2919c1468d4823fdc9e686aa5d2",
|
|
106
106
|
"conventions/planner.docs/planner.docs.area-index-required.convention.yaml": "fd931e9f225bfbb5e78436d0d8a2a89cc0f5114493579962c72dd971301becce",
|
|
107
107
|
"conventions/planner.docs/planner.docs.artifact-path-shape.convention.yaml": "a9f6178d29abe9385342a46a2c57470a3631aaf5e26f01e3660b7088b042418e",
|
|
@@ -1195,7 +1195,7 @@
|
|
|
1195
1195
|
"src/board.ts": "f04c425f74edc003609baec7b5b2d75c1bc98b0e177d702de865dd42d9dd95e5",
|
|
1196
1196
|
"src/ci.ts": "67e54d2cbfc44a9e42837d5e750af526d6255c539d3c452a4d5fca3226c0d9ac",
|
|
1197
1197
|
"src/cli.ts": "b1618d7a7b3b0d42238cb1160aea4ee7962fef8135a7c75b89b0f3fa30dc1f45",
|
|
1198
|
-
"src/delivery.ts": "
|
|
1198
|
+
"src/delivery.ts": "3fd36b6f7dbe9b5682241cff16362618ac0a85c0ac93a238141ebabdbe402e52",
|
|
1199
1199
|
"src/docs-capability.ts": "115cf27049a5cf19c133bac5ec237072be6f969a59a2ef6767e054108a21dc5c",
|
|
1200
1200
|
"src/enforce.ts": "41a6f8c058a2a034996c817f224191403cc66ccc4ed4e04bbefc430014c783d8",
|
|
1201
1201
|
"src/hooks.ts": "9779eb48f9d0cb6234c33f6616f98dde6583d2ee03ac3c19f3ace2d156af26d0",
|
package/package.json
CHANGED
package/src/delivery.ts
CHANGED
|
@@ -258,12 +258,17 @@ function checkFallbacks(file: string, at: string, fallbacks: Fallback[], fallbac
|
|
|
258
258
|
return out;
|
|
259
259
|
}
|
|
260
260
|
|
|
261
|
-
/** The stages a review of `stage` answers for: its own, and every stage after the previous reviewed one
|
|
262
|
-
* covers red, green and refactor when none of them is reviewed.
|
|
263
|
-
|
|
261
|
+
/** The stages a review of `stage` answers for: its own, and every stage after the previous reviewed one (the final review
|
|
262
|
+
* covers red, green and refactor when none of them is reviewed). A stage with nothing written records nothing; when no
|
|
263
|
+
* work is recorded in that range, the review answers for the latest recorded work before it, so a plan-only final review
|
|
264
|
+
* is still independent of the plan's writer. */
|
|
265
|
+
function coveredStages(stage: Stage, policy: DeliveryPolicy, work: Work[]): Stage[] {
|
|
264
266
|
const position = STAGES.indexOf(stage);
|
|
265
267
|
const previous = STAGES.slice(0, position).findLastIndex(name => (policy.stages[name]?.reviewer.length ?? 0) > 0);
|
|
266
|
-
|
|
268
|
+
const range = STAGES.slice(previous + 1, position + 1);
|
|
269
|
+
if (work.some(entry => range.includes(entry.stage))) return range;
|
|
270
|
+
const latest = STAGES.slice(0, previous + 1).findLast(name => work.some(entry => entry.stage === name));
|
|
271
|
+
return latest ? [latest] : range;
|
|
267
272
|
}
|
|
268
273
|
|
|
269
274
|
/** Reports are data, never code: a report path is exempt from drift, so it must not be able to name a source file. */
|
|
@@ -303,7 +308,7 @@ function checkEvidence(file: string, evidence: Evidence, policy: DeliveryPolicy)
|
|
|
303
308
|
out.push(...checkFallbacks(file, at, fallbacks, policy.fallback), ...checkModel(file, at, review.stage, "reviewer", review.reviewer, stage.reviewer, fallbacks, "reviewer", policy.fallback));
|
|
304
309
|
if (review.author && stage.writer.length) out.push(...checkModel(file, at, review.stage, "writer", review.author, stage.writer, fallbacks, "reviewer", policy.fallback));
|
|
305
310
|
// Independence is judged against everyone who wrote what this review answers for.
|
|
306
|
-
const covered = coveredStages(review.stage, policy), writers = [...work.filter(entry => covered.includes(entry.stage)).map(entry => entry.writer), ...(review.author ? [review.author] : [])];
|
|
311
|
+
const covered = coveredStages(review.stage, policy, work), writers = [...work.filter(entry => covered.includes(entry.stage)).map(entry => entry.writer), ...(review.author ? [review.author] : [])];
|
|
307
312
|
if (!writers.length) out.push(finding("delivery.evidence-schema", file, `${at}: names no writer of the work it reviews (${covered.join(", ")}); record each stage's work, or the review's author, so independence can be judged`));
|
|
308
313
|
if (writerRuns.has(review.reviewer.run)) out.push(finding("delivery.reviewer-independent", file, `${at}: reviewer run '${review.reviewer.run}' also wrote in this tranche; a reviewer that edits becomes a writer`));
|
|
309
314
|
if (reviewerRuns.has(review.reviewer.run)) out.push(finding("delivery.reviewer-independent", file, `${at}: reviewer run '${review.reviewer.run}' already reviewed reviews[${reviewerRuns.get(review.reviewer.run)}]; every review is a fresh process`));
|
|
@@ -339,9 +344,6 @@ function checkEvidence(file: string, evidence: Evidence, policy: DeliveryPolicy)
|
|
|
339
344
|
if (evidence.status === "ready") {
|
|
340
345
|
const configured = STAGES.filter(stage => policy.stages[stage]);
|
|
341
346
|
for (const stage of configured) {
|
|
342
|
-
// A 0.9 record names writers as the authors of the reviews that covered their stages.
|
|
343
|
-
const written = work.some(entry => entry.stage === stage) || reviews.some(review => review.author && coveredStages(review.stage, policy).includes(stage));
|
|
344
|
-
if (policy.stages[stage]!.writer.length && !written) out.push(finding("delivery.stages-complete", file, `status is ready, but ${stage} records no work; name who wrote it`));
|
|
345
347
|
if (!policy.stages[stage]!.reviewer.length) continue;
|
|
346
348
|
const last = reviews.filter(review => review.stage === stage).at(-1);
|
|
347
349
|
if (!last) out.push(finding("delivery.stages-complete", file, `status is ready, but ${stage} has no review`));
|