@afokapu/atdd-bun 0.10.31 → 0.10.33
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 +14 -120
- package/conventions/_profiles/architecture.yaml +190 -0
- package/conventions/_profiles/coder.yaml +804 -0
- package/conventions/_profiles/design.yaml +219 -0
- package/conventions/_profiles/docs.yaml +136 -0
- package/conventions/_profiles/htmx.yaml +436 -0
- package/conventions/_profiles/interlocking.yaml +248 -0
- package/conventions/_profiles/metrics.yaml +80 -0
- package/conventions/_profiles/planner.yaml +789 -0
- package/conventions/_profiles/runtime.yaml +62 -0
- package/conventions/_profiles/security.yaml +70 -0
- package/conventions/_profiles/telemetry.yaml +196 -0
- package/conventions/_profiles/tester.yaml +734 -0
- package/conventions/_profiles/topology.yaml +192 -0
- package/conventions/_profiles/traceability.yaml +94 -0
- package/conventions/atdd-bun.profiles/atdd-bun.profiles.presets.convention.yaml +21 -3
- package/conventions/planner.docs/planner.docs.area-index-required.convention.yaml +2 -2
- package/conventions/planner.docs/planner.docs.artifact-path-shape.convention.yaml +1 -1
- package/conventions/planner.docs/planner.docs.asciidoc-only.convention.yaml +0 -1
- package/conventions/planner.docs/planner.docs.identity-required.convention.yaml +1 -1
- package/conventions/planner.docs/planner.docs.undeclared-change.convention.yaml +1 -2
- package/detectors/bun_interlocking_coverage/checks/interlocking_train_sequence.mjs +7 -5
- package/detectors/planner_docs_capability/README.md +1 -1
- package/integrity.json +36 -50
- package/package.json +1 -1
- package/relationships.yaml +0 -151
- package/src/agent.ts +15 -31
- package/src/cli.ts +7 -8
- package/src/docs-capability.ts +6 -24
- package/src/enforce.ts +8 -9
- package/src/hooks.ts +4 -8
- package/src/index.ts +1 -2
- package/src/integrity.ts +3 -11
- package/src/profile-registry.ts +74 -0
- package/src/setup.ts +3 -5
- package/templates/agents/AGENTS.block.md +4 -8
- package/templates/github/atdd-bun.yml +0 -5
- package/conventions/delivery/delivery.approved-sha-resolves.convention.yaml +0 -33
- package/conventions/delivery/delivery.board.convention.yaml +0 -60
- package/conventions/delivery/delivery.config-schema.convention.yaml +0 -49
- package/conventions/delivery/delivery.evidence-schema.convention.yaml +0 -34
- package/conventions/delivery/delivery.findings-resolved.convention.yaml +0 -42
- package/conventions/delivery/delivery.merge-gate.convention.yaml +0 -46
- package/conventions/delivery/delivery.model-allowed.convention.yaml +0 -29
- package/conventions/delivery/delivery.operating-model.convention.yaml +0 -97
- package/conventions/delivery/delivery.review.convention.yaml +0 -42
- package/conventions/delivery/delivery.reviewer-independent.convention.yaml +0 -34
- package/conventions/delivery/delivery.stages-complete.convention.yaml +0 -33
- package/detectors/delivery_evidence/atdd.implementation.yaml +0 -33
- package/detectors/delivery_evidence/detect.mjs +0 -9
- package/detectors/delivery_evidence/fixtures/clean/atdd-bun.yaml +0 -8
- package/detectors/delivery_evidence/fixtures/clean/docs/delivery/tranches/api/evidence.yaml +0 -54
- package/detectors/delivery_evidence/fixtures/dirty/atdd-bun.yaml +0 -3
- package/detectors/delivery_evidence/fixtures/dirty/docs/delivery/tranches/api/evidence.yaml +0 -31
- package/detectors/delivery_evidence/fixtures/dirty/docs/delivery/tranches/data/evidence.yaml +0 -8
- package/detectors/delivery_evidence/fixtures/dirty/docs/delivery/tranches/orphan/README.md +0 -1
- package/detectors/delivery_evidence/fixtures/dirty/docs/delivery/tranches/ui/evidence.yaml +0 -5
- package/detectors/planner_docs_capability/fixtures/dirty_missing_index/docs/delivery/release.adoc +0 -10
- package/detectors/planner_docs_capability/fixtures/dirty_missing_index/docs/purpose/index.adoc +0 -5
- package/planner-schemas/delivery-config.schema.json +0 -95
- package/planner-schemas/delivery-evidence.schema.json +0 -103
- package/src/board-ui.ts +0 -91
- package/src/board.ts +0 -222
- package/src/delivery.ts +0 -567
- package/templates/agents/atdd/SKILL.md +0 -20
- package/templates/agents/delivery/SKILL.md +0 -15
package/src/setup.ts
CHANGED
|
@@ -11,12 +11,10 @@ import { join } from "node:path";
|
|
|
11
11
|
* without this a greenfield repository's first `profiles:` line could switch most of them off unreported. A
|
|
12
12
|
* brownfield repository trims the list before its first commit; after that, dropping one is a reported loosening.
|
|
13
13
|
* An existing atdd-bun.yaml is never touched. */
|
|
14
|
-
/** Profiles a repository adopts on purpose, never by default: delivery gates every change on a reviewed tranche record. */
|
|
15
|
-
const OPT_IN = ["delivery"];
|
|
16
14
|
export async function policyInit(root = process.cwd()) {
|
|
17
15
|
const file = join(root, "atdd-bun.yaml");
|
|
18
16
|
if (existsSync(file)) return { ok: true, message: `${file} kept` };
|
|
19
|
-
await writeFile(file, `# Generated by atdd-bun init. The profiles this repository enforces; trim the list before the first commit to\n# adopt gradually. Once committed, removing a profile or the list is reported by the integrity check.\nprofiles: [${concreteProfiles.
|
|
17
|
+
await writeFile(file, `# Generated by atdd-bun init. The profiles this repository enforces; trim the list before the first commit to\n# adopt gradually. Once committed, removing a profile or the list is reported by the integrity check.\nprofiles: [${concreteProfiles.join(", ")}]\n`);
|
|
20
18
|
return { ok: true, message: file };
|
|
21
19
|
}
|
|
22
20
|
|
|
@@ -35,10 +33,10 @@ export async function initializeRepository(root = process.cwd(), replace = false
|
|
|
35
33
|
|
|
36
34
|
const existingAgent = await agentStatus(root);
|
|
37
35
|
const agent = replace || !existingAgent.ok ? await agentInit(root, replace) : existingAgent;
|
|
38
|
-
if (!agent.ok) return { ok: false, message: `agent
|
|
36
|
+
if (!agent.ok) return { ok: false, message: `agent instructions: ${agent.message}` };
|
|
39
37
|
|
|
40
38
|
const existingIntegrity = await integrityStatus(root);
|
|
41
39
|
const integrity = replace || !existingIntegrity.ok ? await integrityInit(root, replace) : existingIntegrity;
|
|
42
40
|
if (!integrity.ok) return { ok: false, message: `integrity test: ${integrity.message}` };
|
|
43
|
-
return { ok: true, message: `hooks: ${hooks.message}\nCI workflow: ${ci.message}\nagent
|
|
41
|
+
return { ok: true, message: `hooks: ${hooks.message}\nCI workflow: ${ci.message}\nagent instructions: ${agent.message}\nintegrity test: ${integrity.message}\npolicy: ${policy.message}` };
|
|
44
42
|
}
|
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
<!-- atdd-bun:start — generated by @afokapu/atdd-bun {{VERSION}}; run `atdd-bun agent init --replace` to refresh -->
|
|
2
|
-
## ATDD
|
|
2
|
+
## ATDD
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
For each task, read `conventions/atdd-bun.profiles/atdd-bun.profiles.presets.convention.yaml` in `node_modules/@afokapu/atdd-bun` and propose the governing profile(s). If the human has not selected them, ask them to choose; do not activate or deactivate profiles yourself. Then read the matching `conventions/_profiles/<profile>.yaml` registry and only the convention files it identifies as relevant.
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
Follow the applicable conventions and their gates. Enter at the stage that fits the task; do not assume a linear lifecycle.
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
When `delivery` is active, deliver tranches through `.agents/skills/delivery/SKILL.md`: the reviews it requires are recorded under the delivery root and checked in CI.
|
|
11
|
-
|
|
12
|
-
Never modify the toolkit itself (`node_modules/@afokapu/atdd-bun`, or the files atdd-bun generates); change only the configuration it offers, and loosen it only when the user asks. The integrity test and CI fail if the toolkit is modified.
|
|
8
|
+
Never modify the toolkit itself (`node_modules/@afokapu/atdd-bun`) or its generated files. Change only its configuration, and loosen it only when the user asks.
|
|
13
9
|
<!-- atdd-bun:end -->
|
|
@@ -21,11 +21,6 @@ jobs:
|
|
|
21
21
|
- run: bun install --frozen-lockfile
|
|
22
22
|
- run: bun run atdd-bun integrity
|
|
23
23
|
- run: bun run atdd-bun all
|
|
24
|
-
env:
|
|
25
|
-
# The delivery profile's gate: before the merge on pull requests and the merge queue, after it on a push.
|
|
26
|
-
ATDD_DELIVERY_GATE: ${{ github.event_name == 'push' && 'post-merge' || 'merge' }}
|
|
27
|
-
# On a push, the gate judges everything since the previous tip, not only the last commit.
|
|
28
|
-
ATDD_BASE_REF: ${{ github.event_name == 'push' && github.event.before || '' }}
|
|
29
24
|
- run: bun test
|
|
30
25
|
- run: bun run atdd-bun release check
|
|
31
26
|
- uses: actions/upload-artifact@v4
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
schema_version: 1.1.0
|
|
2
|
-
rule_id: delivery.approved-sha-resolves
|
|
3
|
-
kind: rule
|
|
4
|
-
status: active
|
|
5
|
-
name: The approved SHA is a commit in this repository
|
|
6
|
-
statement: >-
|
|
7
|
-
A ready record's approved_sha resolves to a commit in the repository's history, every work entry names a commit in approved_sha's history, and every reviewed stage's last approval does too, each containing the one before it in lifecycle order (REQUIRED).
|
|
8
|
-
terms:
|
|
9
|
-
- term_id: approved_sha
|
|
10
|
-
text: >-
|
|
11
|
-
the commit the closing review approved and the tranche asks to merge.
|
|
12
|
-
content:
|
|
13
|
-
summary: >-
|
|
14
|
-
An approval of a commit nobody can find proves nothing: it may be a typo, a rewritten history, or an invention.
|
|
15
|
-
normative_text: |
|
|
16
|
-
The validator asks Git whether the commit exists. A rebase after approval changes every SHA and therefore needs a fresh review; the record cannot be updated by hand to follow it.
|
|
17
|
-
fix_hint: |
|
|
18
|
-
Record the full or abbreviated SHA the final review named. After a rebase, run the final review again on the new head.
|
|
19
|
-
exceptions:
|
|
20
|
-
- >-
|
|
21
|
-
At the gate, a record the change does not touch is not judged again: it was judged when it merged, and its tranche branch may be gone. The pre-push hook scopes the same way, from where the branch left its base branch; with no base found it judges every record. Everywhere else every ready record is judged.
|
|
22
|
-
- >-
|
|
23
|
-
A shallow clone may lack the commit: CI must fetch full history (the generated workflow uses fetch-depth 0).
|
|
24
|
-
metadata:
|
|
25
|
-
aliases:
|
|
26
|
-
- DELIVERY-APPROVED-SHA-RESOLVES-001
|
|
27
|
-
severity: 3
|
|
28
|
-
# strict: atdd-bun fails on every finding; it has no advisory mode and no ratchet baseline.
|
|
29
|
-
disposition: strict
|
|
30
|
-
introduced_in: 0.8.0
|
|
31
|
-
implementation:
|
|
32
|
-
type: validator
|
|
33
|
-
ref: delivery_evidence
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
schema_version: 1.1.0
|
|
2
|
-
rule_id: delivery.board
|
|
3
|
-
kind: policy
|
|
4
|
-
status: active
|
|
5
|
-
name: Agents talk through a local board, one topic per conversation
|
|
6
|
-
statement: >-
|
|
7
|
-
Where atdd-bun.yaml sets delivery.board, the coordinator and drivers talk through a local message board with atdd-bun chat, never by typing into another agent's pane: one topic for the program, one per tranche, one per review conversation, each agent launched with its identity and the only topics it may use, every message naming its sender and recipients. The board makes the work visible; the evidence record stays the only thing the delivery rules judge.
|
|
8
|
-
terms:
|
|
9
|
-
- term_id: topics
|
|
10
|
-
text: >-
|
|
11
|
-
Three levels, each its own topic, named by atdd-bun chat topic so every agent spells them alike. atdd-<program>: coordinator, drivers and humans; status only (started, blocked, ready, merged, a decision a human must take). atdd-<program>-<tranche>: the tranche's driver; the tasks it gives its writers and their results. atdd-<program>-<tranche>-<stage>-<round>: the driver; one review's request and verdict. A rebuttal opens the next round's topic.
|
|
12
|
-
values:
|
|
13
|
-
program: atdd-bun chat topic <program>
|
|
14
|
-
tranche: atdd-bun chat topic <program> <tranche>
|
|
15
|
-
review: atdd-bun chat topic <program> <tranche> <stage> <round>
|
|
16
|
-
- term_id: identity
|
|
17
|
-
text: >-
|
|
18
|
-
<role>@<tranche> for the whole tranche (driver@auth, writer-glm@auth, reviewer-codex@auth; a later round adds it: reviewer-codex-2@auth); coordinator for the coordinator.
|
|
19
|
-
- term_id: launch
|
|
20
|
-
text: >-
|
|
21
|
-
Whoever starts a coordinator or driver gives it, in its environment, ATDD_AGENT (its identity) and ATDD_TOPICS (the topics it may use, comma-separated), and ATDD_BOARD_URL when the board is not the configured one. The coordinator gives a driver its tranche topic and the program topic; the driver adds each review topic as it opens it. atdd-bun chat refuses any other topic, to read or to write. Writers and reviewers get no board access: each is a headless run whose task is its launch prompt and whose answer is its output, which the driver posts (a verdict as "verdict of <reviewer>"), so their tools stay minimal and no sandbox has to reach the board.
|
|
22
|
-
values:
|
|
23
|
-
coordinator: ATDD_AGENT=coordinator@<program> ATDD_TOPICS=atdd-<program>
|
|
24
|
-
driver: ATDD_AGENT=driver@<tranche> ATDD_TOPICS=atdd-<program>,atdd-<program>-<tranche>
|
|
25
|
-
- term_id: message
|
|
26
|
-
text: >-
|
|
27
|
-
atdd-bun chat post writes the header: from, to, participants and conversation always; kind (task, result, review-request, verdict, rebuttal, status, blocked, heartbeat), stage, reply-to, repo, branch, worktree, goal, base and sha when they apply. The body carries the whole instruction or answer, however long: the thread is the history. A heartbeat carries nothing else; anything that needs an answer goes as blocked, never inside a heartbeat.
|
|
28
|
-
- term_id: commands
|
|
29
|
-
text: >-
|
|
30
|
-
Post with the body on standard input; read what is on a topic; wait for the next message addressed to you on one or several topics (comma-separated), skipping kinds you do not act on (--skip heartbeat), bounded by --timeout so a tool call ends (exit 2: nothing yet). wait remembers where each identity stopped on each set of topics (~/.atdd-board/cursors), so re-arming a watcher is always the same command; --since still overrides it; follow is the listener for a host that wakes its agent on each line a running process prints (Claude Code's Monitor tool): it streams every message addressed to the identity as it arrives and keeps running, keeping the same saved place; a host that wakes its agent only when a process exits runs wait and re-arms it after each wake-up. One listener per identity. When nothing arrives (wait's timeout, or follow's --check-in seconds, 20 minutes by default and 0 to turn it off), the listener prints the owner's check-in, asking where the agent is, whether it is moving or blocked and who knows, whether its stakeholder is informed, and whether it is avoiding ceremony and rabbit holes. The agent acts on it, moving the work or posting once to whoever it waits on, and never posts just to say it is still there. And, for a human, atdd-bun chat alone opens the board: every topic on the left, the selected conversation on the right, live.
|
|
31
|
-
values:
|
|
32
|
-
post: atdd-bun chat post <topic> --to <agent> --kind <kind> [--reply-to <id>] < message.md
|
|
33
|
-
read: atdd-bun chat read <topic> [--mine]
|
|
34
|
-
wait: atdd-bun chat wait <topic>[,<topic>...] [--since <id>] [--skip heartbeat] --timeout 540
|
|
35
|
-
follow: atdd-bun chat follow <topic>[,<topic>...] [--skip heartbeat,progress] [--timeout <seconds>] [--check-in <seconds>]
|
|
36
|
-
board: atdd-bun chat
|
|
37
|
-
- term_id: server
|
|
38
|
-
text: >-
|
|
39
|
-
A local ntfy server, bound to the loopback address, keeping its messages in a cache file. Every agent on the machine reaches it from the same address, so ntfy's per-client limits are raised: requests, subscriptions, daily messages, and new topics (one topic per conversation creates many). With the defaults, ten parallel tranches exhaust them and posts are refused.
|
|
40
|
-
values:
|
|
41
|
-
docker: docker run -d --name atdd-board -p 127.0.0.1:2586:80 -v ~/.atdd-board:/var/cache/ntfy -e NTFY_CACHE_FILE=/var/cache/ntfy/cache.db -e NTFY_CACHE_DURATION=720h -e NTFY_MESSAGE_SIZE_LIMIT=64k -e NTFY_VISITOR_REQUEST_LIMIT_BURST=100000 -e NTFY_VISITOR_REQUEST_LIMIT_REPLENISH=1ms -e NTFY_VISITOR_SUBSCRIPTION_LIMIT=10000 -e NTFY_VISITOR_MESSAGE_DAILY_LIMIT=0 -e NTFY_VISITOR_TOPIC_CREATION_LIMIT_BURST=0 binwiederhier/ntfy serve
|
|
42
|
-
content:
|
|
43
|
-
summary: >-
|
|
44
|
-
Typing into an agent's pane loses messages to startup screens, busy prompts and cut pastes. A board with one topic per conversation delivers every message, keeps the history, and lets a human follow any thread.
|
|
45
|
-
normative_text: |
|
|
46
|
-
A reviewer never reads the tranche's conversation: its brief is the review request in its launch prompt, and its verdict is its output. The driver records that verdict in evidence.yaml and posts it on the review topic; the board is never evidence.
|
|
47
|
-
Agents use atdd-bun chat only. It refuses an address that is not local and a topic the agent was not given. Never call ntfy directly: in the ntfy client -u means credentials, and a topic without a server goes to the public ntfy.sh.
|
|
48
|
-
A running session that must be woken is reached through its own channel (codex queue --thread <id>; --resume <session> for Claude and Pi), never by typing into its pane; a driver's launch prompt tells it to wait on its topics between steps.
|
|
49
|
-
fix_hint: |
|
|
50
|
-
Derive the topic with atdd-bun chat topic, launch coordinators and drivers with ATDD_AGENT and ATDD_TOPICS, and post with --to. To follow the work, run atdd-bun chat in a terminal pane. ntfy cannot list its topics, so the first message on a topic also posts the topic's name to the directory topic atdd-topics, which the view reads.
|
|
51
|
-
exceptions:
|
|
52
|
-
- >-
|
|
53
|
-
The board is opt-in: without a delivery.board block there is none, and atdd-bun chat refuses to post or read. With the block and no url it is at http://127.0.0.1:2586; ATDD_BOARD_URL moves it on one machine but never switches it on. Switching it on or off changes how agents talk, not what a record must prove, so it is not a loosening.
|
|
54
|
-
metadata:
|
|
55
|
-
aliases:
|
|
56
|
-
- DELIVERY-BOARD-001
|
|
57
|
-
introduced_in: 0.10.0
|
|
58
|
-
# A policy, not a rule: how agents talk cannot be validated from the repository. atdd-bun chat enforces its guard rails.
|
|
59
|
-
implementation:
|
|
60
|
-
type: none
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
schema_version: 1.1.0
|
|
2
|
-
rule_id: delivery.config-schema
|
|
3
|
-
kind: rule
|
|
4
|
-
status: active
|
|
5
|
-
name: The delivery policy in atdd-bun.yaml is well-formed
|
|
6
|
-
statement: >-
|
|
7
|
-
The `delivery:` block of atdd-bun.yaml validates against delivery-config.schema.json: known keys only, each stage naming a writer list, a reviewer list or both, models named in lowercase, independence one of fresh-process or different-model, the root in canonical form (no leading, trailing or doubled slash, no dot segment) not overlapping the plan, source, test, e2e or telemetry root, and, inside docs/, exactly docs/delivery/tranches (REQUIRED).
|
|
8
|
-
terms:
|
|
9
|
-
- term_id: policy
|
|
10
|
-
text: >-
|
|
11
|
-
the `delivery:` block: root, independence, stages (plan, red, green, refactor, final; per stage: writer, reviewer, optional independence), fallback and commands. Every key is optional; an omitted key takes the package default.
|
|
12
|
-
content:
|
|
13
|
-
summary: >-
|
|
14
|
-
The skill and the validators read the same policy. A misspelled key would be ignored by one and not the other, so a malformed block is a finding, and the rest of the run judges evidence against the package defaults.
|
|
15
|
-
normative_text: |
|
|
16
|
-
The policy decides which models may write and review each stage (an allowed set, in no order; "*" allows any), how independent a reviewer must be, and when a model counts as unavailable. It is read by the delivery skill when it dispatches work and by this profile when it judges the record, so both must see the same, valid document.
|
|
17
|
-
fix_hint: |
|
|
18
|
-
Correct the key the finding names. The defaults are:
|
|
19
|
-
|
|
20
|
-
delivery:
|
|
21
|
-
root: docs/delivery/tranches
|
|
22
|
-
independence: different-model
|
|
23
|
-
stages:
|
|
24
|
-
plan: { writer: [codex, claude-opus, kimi], reviewer: [glm, claude-opus, codex, kimi] }
|
|
25
|
-
red: { writer: [glm, claude-sonnet, deepseek-flash, claude-opus, codex, kimi] }
|
|
26
|
-
green: { writer: [glm, claude-sonnet, deepseek-flash, claude-opus, codex, kimi] }
|
|
27
|
-
refactor: { writer: [glm, claude-sonnet, deepseek-flash, claude-opus, codex, kimi] }
|
|
28
|
-
final: { reviewer: [codex, glm, claude-opus, kimi] }
|
|
29
|
-
|
|
30
|
-
independence defaults to different-model. A stage may name a writer, a reviewer or both. The 0.9
|
|
31
|
-
names plan_review, test_review, code_review and final_review are still read, as plan, red, refactor
|
|
32
|
-
and final, with authors as writers and reviewers as reviewers.
|
|
33
|
-
exceptions:
|
|
34
|
-
- >-
|
|
35
|
-
Adoption is not exempt from the gate: the pull request that adopts delivery brings the generated skill and workflow,
|
|
36
|
-
outside the delivery root, so it carries its own ready tranche record like any other change. A later change to
|
|
37
|
-
atdd-bun.yaml alone needs no record (delivery.merge-gate).
|
|
38
|
-
- >-
|
|
39
|
-
Inert until adoption: with no `delivery:` block and `delivery` absent from `profiles:`, no delivery rule emits anything.
|
|
40
|
-
metadata:
|
|
41
|
-
aliases:
|
|
42
|
-
- DELIVERY-CONFIG-SCHEMA-001
|
|
43
|
-
severity: 3
|
|
44
|
-
# strict: atdd-bun fails on every finding; it has no advisory mode and no ratchet baseline.
|
|
45
|
-
disposition: strict
|
|
46
|
-
introduced_in: 0.8.0
|
|
47
|
-
implementation:
|
|
48
|
-
type: validator
|
|
49
|
-
ref: delivery_evidence
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
schema_version: 1.1.0
|
|
2
|
-
rule_id: delivery.evidence-schema
|
|
3
|
-
kind: rule
|
|
4
|
-
status: active
|
|
5
|
-
name: Every tranche folder holds a well-formed evidence record
|
|
6
|
-
statement: >-
|
|
7
|
-
Every folder under the delivery root holds an evidence.yaml that validates against delivery-evidence.schema.json, whose tranche matches the folder name, whose work entries each name a writer and a stage the policy lets someone write, whose reviews each name a stage the policy reviews, and whose reports are data files (json, jsonl, yaml, yml, txt, md, log) inside the tranche's own folder, one per review; a ready record names one for every review (delivery.stages-complete); and the records folder holds nothing else: a data file belongs only as a report a record in its tranche names, and every other file, including a loose file directly under the root, is a finding (REQUIRED).
|
|
8
|
-
terms:
|
|
9
|
-
- term_id: tranche
|
|
10
|
-
text: >-
|
|
11
|
-
one independently mergeable piece of a program, delivered on its own branch by one persistent driver through PLAN, RED, GREEN, SMOKE, REFACTOR and TRACE, with its reviews.
|
|
12
|
-
- term_id: evidence
|
|
13
|
-
text: >-
|
|
14
|
-
the tranche's record at `<root>/<tranche>/evidence.yaml`: status (open or ready), base and approved SHAs, the work (who wrote each stage, at which SHA, with fallbacks) and the chronological list of reviews, each with stage, reviewed SHA, reviewer, fallbacks, verdict, the checklist it went through and its findings.
|
|
15
|
-
content:
|
|
16
|
-
summary: >-
|
|
17
|
-
The record is what CI can check. A review that is not written down, or written down in a shape the validator cannot read, did not happen as far as the merge gate is concerned.
|
|
18
|
-
normative_text: |
|
|
19
|
-
The profile judges the record a tranche leaves, not the agents while they work. Each review is appended, never edited, so a repair loop shows as a request-changes entry followed by a fresh review of the same stage. A review answers for the work written since the previous reviewed stage; independence is judged against those writers, so a review with no recorded writer cannot be judged. A 0.9 record names the writer as the review's author.
|
|
20
|
-
fix_hint: |
|
|
21
|
-
Create or repair `<root>/<tranche>/evidence.yaml`; the finding names the schema path at fault. A request-changes review carries at least one finding; every review carries its `checked` list.
|
|
22
|
-
exceptions:
|
|
23
|
-
- >-
|
|
24
|
-
The default root, docs/delivery/tranches, sits in the docs profile's delivery area beside the program's reasoning (docs/delivery/index.adoc); the docs profile leaves the folder's record and data files to this profile, and AsciiDoc there stays documentation.
|
|
25
|
-
metadata:
|
|
26
|
-
aliases:
|
|
27
|
-
- DELIVERY-EVIDENCE-SCHEMA-001
|
|
28
|
-
severity: 3
|
|
29
|
-
# strict: atdd-bun fails on every finding; it has no advisory mode and no ratchet baseline.
|
|
30
|
-
disposition: strict
|
|
31
|
-
introduced_in: 0.8.0
|
|
32
|
-
implementation:
|
|
33
|
-
type: validator
|
|
34
|
-
ref: delivery_evidence
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
schema_version: 1.1.0
|
|
2
|
-
rule_id: delivery.findings-resolved
|
|
3
|
-
kind: rule
|
|
4
|
-
status: active
|
|
5
|
-
name: Every finding is fixed, withdrawn after one dispute, or ruled on by a human
|
|
6
|
-
statement: >-
|
|
7
|
-
Once a stage has a later review, or the record is ready, every finding of a request-changes review records its outcome: fixed (confirmed by a later review of the stage), withdrawn (after a written rebuttal, by a later review that does not raise it again) or human (with the decision). A finding disputed more than once goes to a human. An approving review carries no critical or high finding (REQUIRED).
|
|
8
|
-
terms:
|
|
9
|
-
- term_id: rebuttal
|
|
10
|
-
text: >-
|
|
11
|
-
the author's written dispute of a finding, with evidence: a test result, a rule id, a file and line. The next fresh reviewer upholds or withdraws the finding.
|
|
12
|
-
- term_id: outcome
|
|
13
|
-
text: >-
|
|
14
|
-
fixed, withdrawn or human, recorded on the finding where it was raised.
|
|
15
|
-
content:
|
|
16
|
-
summary: >-
|
|
17
|
-
A reviewer can be wrong and an author can be wrong. One written round, judged by a fresh reviewer, settles most disagreements; the rest go to a human instead of looping.
|
|
18
|
-
normative_text: |
|
|
19
|
-
No conversation between author and reviewer: a reviewer is stateless, and a long exchange turns it into a co-author. The author fixes a finding or disputes it once in writing; the next fresh reviewer decides. If that reviewer upholds a disputed finding, the tranche emits BLOCKED disputed-finding and a human rules.
|
|
20
|
-
fix_hint: |
|
|
21
|
-
On each finding of the request-changes review, record the outcome:
|
|
22
|
-
|
|
23
|
-
outcome: fixed
|
|
24
|
-
|
|
25
|
-
rebuttal: "handler.test.ts:31 proves the loop stops on abort"
|
|
26
|
-
outcome: withdrawn
|
|
27
|
-
|
|
28
|
-
outcome: human
|
|
29
|
-
decision: "Keep the retry; the caller owns the bound."
|
|
30
|
-
exceptions:
|
|
31
|
-
- >-
|
|
32
|
-
While a stage has no later review and the record is open, a finding without an outcome is work in progress, not a finding.
|
|
33
|
-
metadata:
|
|
34
|
-
aliases:
|
|
35
|
-
- DELIVERY-FINDINGS-RESOLVED-001
|
|
36
|
-
severity: 2
|
|
37
|
-
# strict: atdd-bun fails on every finding; it has no advisory mode and no ratchet baseline.
|
|
38
|
-
disposition: strict
|
|
39
|
-
introduced_in: 0.8.0
|
|
40
|
-
implementation:
|
|
41
|
-
type: validator
|
|
42
|
-
ref: delivery_evidence
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
schema_version: 1.1.0
|
|
2
|
-
rule_id: delivery.merge-gate
|
|
3
|
-
kind: rule
|
|
4
|
-
status: active
|
|
5
|
-
name: A tranche merges only its approved SHA
|
|
6
|
-
statement: >-
|
|
7
|
-
At the gate (ATDD_DELIVERY_GATE, which the generated CI sets to merge on pull requests and the merge queue and to post-merge on pushes to the protected branches), every evidence record the change touches is ready and approves a commit the head contains; before the merge the head differs from that commit only by the record and the reports it names; no record is deleted, and no record or report already on the base branch is modified (records 0.8.0 kept under delivery/ included, after the root moves); under the delivery root only records and the reports a changed record names change; and, with require_record (the default), a change outside the delivery root comes with a tranche record, unless atdd-bun.yaml is the only such file (REQUIRED).
|
|
8
|
-
terms:
|
|
9
|
-
- term_id: merge_gate
|
|
10
|
-
text: >-
|
|
11
|
-
the CI run that decides whether a pull request may merge. It compares the branch against the base it merges into; for a merge checkout, the base is the first parent and the head the second.
|
|
12
|
-
content:
|
|
13
|
-
summary: >-
|
|
14
|
-
Any commit after approval, a code change, a regenerated file, a conflict resolution or a rebase, invalidates it. The evidence commit itself is the one change allowed, since it cannot be in the SHA it records. A change with no record at all was never reviewed.
|
|
15
|
-
normative_text: |
|
|
16
|
-
This is where the profile becomes a merge rule rather than an instruction. Records that the change does not touch, earlier tranches already on the base branch, are not judged again; their approved SHAs may no longer be the head of anything.
|
|
17
|
-
After the merge, a push is judged from its previous tip (the generated CI passes it as ATDD_BASE_REF; a first push falls back to the parent): every record it brings in must approve a commit it contains. A deleted record never counts as the record that covers a change. A squash or rebase merge writes a new commit no reviewer saw and fails here, visibly, on the base branch; merge tranches with a merge commit. Drift is judged after the merge too, at the tranche's side of a merge commit or at the head of a direct push, over the files the push brings in. Only <root>/<tranche>/evidence.yaml is a record; an evidence.yaml at any other depth covers nothing. A rename is a deletion. When several tranches land in one change, a file another changed ready record approved with exactly that content is not drift.
|
|
18
|
-
fix_hint: |
|
|
19
|
-
Run the final review on the current head and record its SHA as approved_sha, or remove the change made after approval. Locally, reproduce the gate with ATDD_DELIVERY_GATE=merge ATDD_BASE_REF=origin/main bun run atdd-bun delivery.
|
|
20
|
-
exceptions:
|
|
21
|
-
- >-
|
|
22
|
-
Outside the gate (hooks, local runs) this rule emits nothing, so a tranche can push work in progress.
|
|
23
|
-
- >-
|
|
24
|
-
Before the merge, a pull request is judged at its head (the second parent of the test merge GitHub computes), not at
|
|
25
|
-
that merge commit; content only a merge commit introduces is judged after the merge, where a push is judged whole.
|
|
26
|
-
Judging GitHub's merge result instead would report the base branch's own changes to the same files as drift.
|
|
27
|
-
- >-
|
|
28
|
-
The policy governs the tree it sits in. With atdd-bun.yaml in a subfolder (a monorepo package run with --root),
|
|
29
|
-
require_record covers that subfolder, not the rest of the repository, which another policy or none governs; the
|
|
30
|
-
generated workflow runs from the repository root, and drift from an approved commit is judged repository-wide.
|
|
31
|
-
- >-
|
|
32
|
-
require_record false exempts changes with no record; turning it off is a loosening the integrity check reports.
|
|
33
|
-
- >-
|
|
34
|
-
A change to atdd-bun.yaml alone needs no record: which models may write and review is a human's decision, and
|
|
35
|
-
the integrity check already reports any loosening for a human to approve; a tightening needs no review. A policy
|
|
36
|
-
change that comes with any other file outside the delivery root is reviewed with it.
|
|
37
|
-
metadata:
|
|
38
|
-
aliases:
|
|
39
|
-
- DELIVERY-MERGE-GATE-001
|
|
40
|
-
severity: 3
|
|
41
|
-
# strict: atdd-bun fails on every finding; it has no advisory mode and no ratchet baseline.
|
|
42
|
-
disposition: strict
|
|
43
|
-
introduced_in: 0.8.0
|
|
44
|
-
implementation:
|
|
45
|
-
type: validator
|
|
46
|
-
ref: delivery_evidence
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
schema_version: 1.1.0
|
|
2
|
-
rule_id: delivery.model-allowed
|
|
3
|
-
kind: rule
|
|
4
|
-
status: active
|
|
5
|
-
name: Authors and reviewers are allowed models, and every fallback says why
|
|
6
|
-
statement: >-
|
|
7
|
-
Each work entry's writer is a model its stage allows for writers, and each review's reviewer a model it allows for reviewers. A stage's list is the set of allowed models, in no order; "*" allows any model. Which allowed model does the work is the operator's choice at any moment, so no fallback has to explain it; the record names the model that actually ran (REQUIRED).
|
|
8
|
-
terms:
|
|
9
|
-
- term_id: fallback
|
|
10
|
-
text: >-
|
|
11
|
-
a recorded switch from a preferred model to a later one in the stage's list, with role (writer or reviewer) and a reason: an outage, a rate limit, or no auditable report, counted by failures; or the operator's order, referenced by its ruling. A REQUEST CHANGES verdict is never a reason.
|
|
12
|
-
content:
|
|
13
|
-
summary: >-
|
|
14
|
-
The lists are the operator's choice of which models may do the work. Switching between allowed models needs no policy edit and no paperwork, so a rate limit or a preference change is handled on the spot; a model outside the list is still reported.
|
|
15
|
-
normative_text: |
|
|
16
|
-
The record must name the model that ran. Reviewer independence (a reviewer is never the model that wrote the work it reviews, under different-model) is judged by delivery.reviewer-independent, and a disputed finding upheld on a fresh review blocks the tranche, so switching reviewers cannot buy an approval.
|
|
17
|
-
A fallback entry (kind outage, rate_limit, no_report, timeout or operator) may still record why a model was used; it is optional and, when present, must be well formed.
|
|
18
|
-
fix_hint: |
|
|
19
|
-
Use a model the stage lists, or have the operator add it (or "*") to the stage's list in atdd-bun.yaml; the integrity check reports an added model once for the operator to approve.
|
|
20
|
-
metadata:
|
|
21
|
-
aliases:
|
|
22
|
-
- DELIVERY-MODEL-ALLOWED-001
|
|
23
|
-
severity: 2
|
|
24
|
-
# strict: atdd-bun fails on every finding; it has no advisory mode and no ratchet baseline.
|
|
25
|
-
disposition: strict
|
|
26
|
-
introduced_in: 0.8.0
|
|
27
|
-
implementation:
|
|
28
|
-
type: validator
|
|
29
|
-
ref: delivery_evidence
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
schema_version: 1.1.0
|
|
2
|
-
rule_id: delivery.operating-model
|
|
3
|
-
kind: policy
|
|
4
|
-
status: active
|
|
5
|
-
name: How a program is delivered in tranches, and who does what
|
|
6
|
-
statement: >-
|
|
7
|
-
A coordinator splits the program into tranches and keeps every slot busy; one persistent driver per tranche runs its lifecycle stages in order (plan, red, green, refactor, final), dispatching each stage's writer and reviewer from the delivery policy in atdd-bun.yaml as fresh headless processes, and records who wrote each stage and every review in the tranche's evidence.yaml.
|
|
8
|
-
terms:
|
|
9
|
-
- term_id: coordinator
|
|
10
|
-
text: >-
|
|
11
|
-
Owns throughput, never the work. It splits the program into tranches with explicit dependencies and writes why, the scope and the split in docs/delivery/index.adoc; activates a tranche once its own dependencies have merged (one still waiting may run plan and its review, nothing after); starts one driver per tranche in its own worktree; keeps provider health for the program, telling every driver to skip a model that is down; intervenes when a tranche is idle without being blocked, or has deliverables and no commit after two hours; and hands BLOCKED disputed-finding to a human with both sides. It never writes, reviews or merges.
|
|
12
|
-
- term_id: driver
|
|
13
|
-
text: >-
|
|
14
|
-
Owns one tranche end to end. For each stage of delivery.stages, in order, it starts the stage's writer (any model in its writer list, as the operator chooses) in the tranche worktree, commits red on its own before green starts, passes the stage's gate, and appends a work entry; for each stage with a reviewer it starts a review. It never reviews.
|
|
15
|
-
- term_id: review_run
|
|
16
|
-
text: >-
|
|
17
|
-
Every review is a fresh process in its own detached worktree at the exact SHA (git worktree add --detach), launched with a prompt that gives it the delivery.review convention, the stage, the base SHA, the SHA and the RED commit. Afterwards git status --porcelain must be empty and HEAD still the SHA, or the review is a REVIEWER_FAILURE and does not count. The raw output is kept in the tranche folder and named in the review's report.
|
|
18
|
-
- term_id: fallback
|
|
19
|
-
text: >-
|
|
20
|
-
Any model a stage lists may be used, so a switch needs no fallback: when a model is down or rate-limited, the driver moves to another listed model and records the one that ran. A fallback entry may still say why (outage, rate limit, no auditable report, timeout, or the operator's order); it is optional. A request-changes verdict is never a reason to switch reviewers: a disputed finding upheld on a fresh review blocks the tranche. When no listed model is available, when_exhausted block emits BLOCKED provider-unavailable.
|
|
21
|
-
- term_id: repair
|
|
22
|
-
text: >-
|
|
23
|
-
For each finding of a request-changes review the writer either fixes it or writes one rebuttal with evidence; a fresh review of the same stage follows. If that reviewer upholds a disputed finding, the driver emits BLOCKED disputed-finding and never disputes it again. Any commit, regenerated file, conflict fix or rebase after an approval cancels it and the change goes back to that stage's review.
|
|
24
|
-
- term_id: ready
|
|
25
|
-
text: >-
|
|
26
|
-
When the last reviewed stage approves, the driver sets status ready and approved_sha to that SHA, commits the evidence and its reports alone, pushes, and merges with a merge commit once CI is green. A squash or rebase merge writes a commit no reviewer saw, and CI fails it after the merge.
|
|
27
|
-
- term_id: events
|
|
28
|
-
text: >-
|
|
29
|
-
One line each, for the coordinator to wait on: PROGRAM_EVENT <tranche> <STAGE <stage> <sha> | WORKER_START <role> <model> <sha> | WORKER_END <role> <model> <verdict> | FALLBACK <role> <from>→<to> <reason> | PR_OPENED <url> | MERGED <sha> | BLOCKED <reason> | HEARTBEAT>.
|
|
30
|
-
- term_id: commands
|
|
31
|
-
text: >-
|
|
32
|
-
The default headless command per model, overridden per model under delivery.commands.<model>.author (the writer's command) and .review. {prompt} and {worktree} are substituted. Claude runs take project settings only, so a user's own allowances cannot widen a reviewer. glm, kimi (Moonshot kimi-k3, a replacement for codex and claude-opus) and deepseek-flash (a smaller coding model beside claude-sonnet) run through Pi, which has no permission system; kimi and deepseek-flash take their keys from MOONSHOT_API_KEY and DEEPSEEK_API_KEY, or point delivery.commands at a wrapper that provides them. Through Pi, as a reviewer it gets the read tool alone (the driver puts the diff in its prompt and records its output), and as a writer it runs only inside a container or sandbox limited to the worktree.
|
|
33
|
-
values:
|
|
34
|
-
codex:
|
|
35
|
-
author: codex exec --cd {worktree} --sandbox workspace-write "{prompt}"
|
|
36
|
-
review: codex exec --cd {worktree} --sandbox read-only "{prompt}"
|
|
37
|
-
claude-opus:
|
|
38
|
-
author: cd {worktree} && claude --model opus --setting-sources project --permission-mode acceptEdits --allowedTools Read Grep Glob Edit Write "Bash(bun:*)" "Bash(git:*)" --output-format json -p "{prompt}"
|
|
39
|
-
review: cd {worktree} && claude --model opus --setting-sources project --allowedTools Read Grep Glob "Bash(git show:*)" "Bash(git diff:*)" "Bash(git log:*)" --disallowedTools Edit Write NotebookEdit --output-format json -p "{prompt}"
|
|
40
|
-
claude-sonnet:
|
|
41
|
-
author: cd {worktree} && claude --model sonnet --setting-sources project --permission-mode acceptEdits --allowedTools Read Grep Glob Edit Write "Bash(bun:*)" "Bash(git:*)" --output-format json -p "{prompt}"
|
|
42
|
-
review: cd {worktree} && claude --model sonnet --setting-sources project --allowedTools Read Grep Glob "Bash(git show:*)" "Bash(git diff:*)" "Bash(git log:*)" --disallowedTools Edit Write NotebookEdit --output-format json -p "{prompt}"
|
|
43
|
-
glm:
|
|
44
|
-
author: cd {worktree} && pi -p --no-session --no-extensions --no-skills --no-context-files --tools read,bash,edit,write "{prompt}"
|
|
45
|
-
review: cd {worktree} && pi -p --no-session --no-extensions --no-skills --no-context-files --tools read "{prompt}"
|
|
46
|
-
kimi:
|
|
47
|
-
author: cd {worktree} && pi --provider moonshotai --model kimi-k3 -p --no-session --no-extensions --no-skills --no-context-files --tools read,bash,edit,write "{prompt}"
|
|
48
|
-
review: cd {worktree} && pi --provider moonshotai --model kimi-k3 -p --no-session --no-extensions --no-skills --no-context-files --tools read "{prompt}"
|
|
49
|
-
deepseek-flash:
|
|
50
|
-
author: cd {worktree} && pi --provider deepseek --model deepseek-flash -p --no-session --no-extensions --no-skills --no-context-files --tools read,bash,edit,write "{prompt}"
|
|
51
|
-
review: cd {worktree} && pi --provider deepseek --model deepseek-flash -p --no-session --no-extensions --no-skills --no-context-files --tools read "{prompt}"
|
|
52
|
-
- term_id: example_record
|
|
53
|
-
text: >-
|
|
54
|
-
A tranche in progress: the plan written by codex and approved by glm; red, green and refactor written by glm; the final review requesting changes. Only the finding's outcome is ever added to an earlier entry.
|
|
55
|
-
values:
|
|
56
|
-
tranche: api
|
|
57
|
-
status: open
|
|
58
|
-
base_sha: 3f2a91c
|
|
59
|
-
work:
|
|
60
|
-
- { stage: plan, sha: 8b10e44, writer: { model: codex, run: codex-plan-1 } }
|
|
61
|
-
- { stage: red, sha: 91aa0b2, writer: { model: glm, run: glm-red-1 } }
|
|
62
|
-
- { stage: green, sha: a4c0f11, writer: { model: glm, run: glm-green-1 } }
|
|
63
|
-
- { stage: refactor, sha: a4c0f11, writer: { model: glm, run: glm-refactor-1 } }
|
|
64
|
-
reviews:
|
|
65
|
-
- stage: plan
|
|
66
|
-
sha: 8b10e44
|
|
67
|
-
reviewer: { model: glm, run: glm-plan-review-1 }
|
|
68
|
-
verdict: approve
|
|
69
|
-
checked: [ACC-API-001, planner.decomposition]
|
|
70
|
-
report: docs/delivery/tranches/api/plan-1.json
|
|
71
|
-
- stage: final
|
|
72
|
-
sha: a4c0f11
|
|
73
|
-
reviewer: { model: codex, run: codex-final-1 }
|
|
74
|
-
verdict: request_changes
|
|
75
|
-
checked: [ACC-API-001, src/wagons/api, coder.bun.error-response-*]
|
|
76
|
-
findings:
|
|
77
|
-
- { id: F1, severity: high, evidence: "src/wagons/api/handler.ts:42", invariant: "coded error bodies", affects: [ui], proposed_fix: "return { code: 'API_NOT_FOUND' }" }
|
|
78
|
-
report: docs/delivery/tranches/api/final-1.json
|
|
79
|
-
content:
|
|
80
|
-
summary: >-
|
|
81
|
-
The policy says who may write and review each stage; this convention says how the coordinator and drivers carry it out. The record they leave is what the delivery rules judge.
|
|
82
|
-
normative_text: |
|
|
83
|
-
With delivery.board set, the coordinator and drivers talk on the board (delivery.board), and each driver posts its workers' tasks, results, review requests and verdicts there; workers never use the board. Without it, a task is the prompt an agent is launched with and its result is the run's output, which the driver keeps. Agents run in panes of the multiplexer named in delivery.multiplexer (default herdr) only for humans to watch; learn its commands from its own help before the first dispatch. Never deliver work to an agent by typing into its pane.
|
|
84
|
-
Before a hosted model receives private repository content, confirm the user or organization authorized it.
|
|
85
|
-
Never edit the delivery skill, these conventions, or loosen the delivery policy to get a tranche through. If the policy must change, stop and ask the human.
|
|
86
|
-
fix_hint: |
|
|
87
|
-
Follow the driver's order: writer, gate, work entry; review, repair, fresh review; ready and merge commit. The example_record term shows a record the profile accepts.
|
|
88
|
-
exceptions:
|
|
89
|
-
- >-
|
|
90
|
-
A stage the policy does not name has no writer and no review; a stage with a writer but no reviewer is held by its gate alone.
|
|
91
|
-
metadata:
|
|
92
|
-
aliases:
|
|
93
|
-
- DELIVERY-OPERATING-MODEL-001
|
|
94
|
-
introduced_in: 0.10.0
|
|
95
|
-
# A policy, not a rule: how agents carry out the delivery policy cannot be validated. The record they leave is.
|
|
96
|
-
implementation:
|
|
97
|
-
type: none
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
schema_version: 1.1.0
|
|
2
|
-
rule_id: delivery.review
|
|
3
|
-
kind: policy
|
|
4
|
-
status: active
|
|
5
|
-
name: What each review establishes, and how a reviewer works
|
|
6
|
-
statement: >-
|
|
7
|
-
A reviewer is a fresh, read-only process for one stage of one tranche, given the stage, the base SHA, the SHA and the RED commit. It reviews the change between the base and the SHA, working through its stage's checklist systematically, systemically, adversarially and economically, and returns one review entry with verdict, checked and findings.
|
|
8
|
-
terms:
|
|
9
|
-
- term_id: plan
|
|
10
|
-
text: >-
|
|
11
|
-
Are we building the right thing? The plan files the change adds or modifies: the decomposition (wagon, WMBT, acceptance, train, journey, contract) covers the intent; every acceptance is testable with one observable outcome and every WMBT has a SMOKE acceptance; edge cases, migrations, security and architecture constraints are represented; the acceptances can prove the feature; the plan builds on the wagons, contracts and components that already exist wherever they fit, and plans no machinery outside the tranche's scope; it follows the accepted architecture decisions (docs/architecture/decisions/index.adoc), and a new technology choice comes with its own ADR; owned files do not overlap other tranches.
|
|
12
|
-
- term_id: final
|
|
13
|
-
text: >-
|
|
14
|
-
Does the change satisfy the approved plan? The tests, implementation and refactoring the change brings are read together. Every acceptance the plan names has a test bound by URN that asserts the behaviour, not a mock; each acceptance test differs from its RED commit only by the removed RED marker and Phase header, and any other change is justified; behaviour is correct on edge and error paths; the changed code keeps layering, composition, DTO, error-response and security sound; SMOKE runs through the real entry point; the change reuses what the codebase already has, duplicates nothing, and adds no machinery beyond what the plan needs; it uses what the accepted ADRs chose and brings in no alternative to them; nothing drifts from the plan.
|
|
15
|
-
- term_id: red
|
|
16
|
-
text: >-
|
|
17
|
-
Where the policy gives red a reviewer. Every acceptance has a RED test bound by URN that fails for the missing behaviour and would still fail for a wrong implementation, asserting observable output rather than mocks.
|
|
18
|
-
- term_id: green_refactor
|
|
19
|
-
text: >-
|
|
20
|
-
Where the policy gives green or refactor a reviewer. Every behaviour is correct against its acceptance on edge and error paths; the changed code keeps layering, composition, DTO, error-response and security sound, reuses what exists and duplicates nothing; SMOKE runs through the real entry point.
|
|
21
|
-
- term_id: method
|
|
22
|
-
text: >-
|
|
23
|
-
Systematic, the whole checklist, with everything checked listed in checked, not only what failed. Systemic, from the change to what it affects (callers, contracts, other tranches, downstream owners), named in affects; code the change does not touch or affect is out of scope. Adversarial, assuming the change is wrong and proving it; a finding needs a file and line, a failing command or a counter-example. Economical, the change does its job with the least new machinery: it reuses what exists, duplicates nothing, and adds no framework, abstraction, configuration, tooling or meta machinery (machinery for building or checking machinery) beyond the tranche's scope; such a finding names the existing piece to reuse or the part to remove. Economy never trades away effectiveness: a smaller change that no longer satisfies an acceptance is not an improvement. A small change gets a short review.
|
|
24
|
-
content:
|
|
25
|
-
summary: >-
|
|
26
|
-
The two default reviews carry the judgement no gate can: the plan before RED, and the whole change at its head. The gates between them are deterministic.
|
|
27
|
-
normative_text: |
|
|
28
|
-
The reviewer runs in a detached worktree at the SHA and reads the change with git diff base..SHA. The gates are CI's, not the reviewer's: it does not re-run them, and judges what they cannot. It may read, search and use git show, git diff and git log. It never edits, commits or writes, including output-file options such as git diff --output=; the driver checks the worktree afterwards, and a review that wrote does not count (delivery.reviewer-independent). It judges and proposes; the author applies.
|
|
29
|
-
A finding carrying the author's rebuttal is withdrawn, left out, when the rebuttal holds, or upheld, repeated with the same id; there is no second round (delivery.findings-resolved).
|
|
30
|
-
The reviewer returns exactly one JSON object (valid YAML, so it goes into evidence.yaml unchanged, and a # inside a string is never read as a comment), the review entry of delivery-evidence.schema.json without fallback or report, which the driver adds: stage, sha, verdict (approve only with no critical or high finding), checked, and findings, each with id, severity (critical, high, medium, low), evidence, invariant, affects and proposed_fix, a precise description or short snippet, never a rewrite.
|
|
31
|
-
fix_hint: |
|
|
32
|
-
Give the reviewer this convention, the stage, the base SHA, the SHA and the RED commit. A review that skipped part of its checklist shows it in checked; run the stage again with a fresh reviewer.
|
|
33
|
-
exceptions:
|
|
34
|
-
- >-
|
|
35
|
-
A stage the policy does not name has no review; its checklist applies only where the policy names it.
|
|
36
|
-
metadata:
|
|
37
|
-
aliases:
|
|
38
|
-
- DELIVERY-REVIEW-001
|
|
39
|
-
introduced_in: 0.10.0
|
|
40
|
-
# A policy, not a rule: what a reviewer judges cannot be validated. The record it leaves is, by the delivery rules.
|
|
41
|
-
implementation:
|
|
42
|
-
type: none
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
schema_version: 1.1.0
|
|
2
|
-
rule_id: delivery.reviewer-independent
|
|
3
|
-
kind: rule
|
|
4
|
-
status: active
|
|
5
|
-
name: Every reviewer is a fresh process independent of the writers
|
|
6
|
-
statement: >-
|
|
7
|
-
A reviewer's run never wrote anything in the tranche and never reviewed another entry; where the stage requires different-model independence (the default), the reviewer's model wrote none of the work the review answers for: its own stage and every stage since the previous reviewed one (REQUIRED).
|
|
8
|
-
terms:
|
|
9
|
-
- term_id: run
|
|
10
|
-
text: >-
|
|
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
|
-
- term_id: independence
|
|
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, and a review whose range recorded no work answers for the latest recorded work before it.
|
|
15
|
-
content:
|
|
16
|
-
summary: >-
|
|
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.
|
|
18
|
-
normative_text: |
|
|
19
|
-
Every review is a new process. The run identifiers make that checkable: a reviewer run that appears as a writer anywhere in the tranche, or on a second review, is not independent. The stricter mode is chosen per stage in the policy.
|
|
20
|
-
fix_hint: |
|
|
21
|
-
Re-run the review in a fresh process and record its own run; under different-model, use the next reviewer model in the list that wrote none of the reviewed work.
|
|
22
|
-
exceptions:
|
|
23
|
-
- >-
|
|
24
|
-
The persistent driver dispatches the work and opens the PR; its run may never review.
|
|
25
|
-
metadata:
|
|
26
|
-
aliases:
|
|
27
|
-
- DELIVERY-REVIEWER-INDEPENDENT-001
|
|
28
|
-
severity: 3
|
|
29
|
-
# strict: atdd-bun fails on every finding; it has no advisory mode and no ratchet baseline.
|
|
30
|
-
disposition: strict
|
|
31
|
-
introduced_in: 0.8.0
|
|
32
|
-
implementation:
|
|
33
|
-
type: validator
|
|
34
|
-
ref: delivery_evidence
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
schema_version: 1.1.0
|
|
2
|
-
rule_id: delivery.stages-complete
|
|
3
|
-
kind: rule
|
|
4
|
-
status: active
|
|
5
|
-
name: A ready record has every configured stage approved
|
|
6
|
-
statement: >-
|
|
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
|
-
terms:
|
|
9
|
-
- term_id: closing_stage
|
|
10
|
-
text: >-
|
|
11
|
-
the last reviewed stage in lifecycle order (plan, red, green, refactor, final); by default final, the review of the PR head, which answers for everything written since the plan review.
|
|
12
|
-
content:
|
|
13
|
-
summary: >-
|
|
14
|
-
Ready is the driver's claim that the tranche can merge. It is only true when no stage is missing and the approval covers the commit being merged.
|
|
15
|
-
normative_text: |
|
|
16
|
-
Each stage may take several rounds; only its last review counts. The closing stage's approval names the SHA the whole tranche stands on, and approved_sha must be that SHA: the merge gate compares the branch head against it.
|
|
17
|
-
fix_hint: |
|
|
18
|
-
Run the missing review, or set status back to open until it has run. Set approved_sha to the SHA the final review approved.
|
|
19
|
-
exceptions:
|
|
20
|
-
- >-
|
|
21
|
-
A ready record is judged by the policy in atdd-bun.yaml at its approved_sha, the policy it was approved under; a later policy change does not re-judge it. A record in progress is judged by the current policy.
|
|
22
|
-
- >-
|
|
23
|
-
A stage the policy omits is not required. Omitting one loosens the policy and is reported by the integrity check until a human approves it.
|
|
24
|
-
metadata:
|
|
25
|
-
aliases:
|
|
26
|
-
- DELIVERY-STAGES-COMPLETE-001
|
|
27
|
-
severity: 3
|
|
28
|
-
# strict: atdd-bun fails on every finding; it has no advisory mode and no ratchet baseline.
|
|
29
|
-
disposition: strict
|
|
30
|
-
introduced_in: 0.8.0
|
|
31
|
-
implementation:
|
|
32
|
-
type: validator
|
|
33
|
-
ref: delivery_evidence
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
schema_version: "1.0.0"
|
|
2
|
-
kind: implementation
|
|
3
|
-
subtype: validator
|
|
4
|
-
implementation_id: delivery.evidence.impl
|
|
5
|
-
targets_workspace: atdd.workspace.bun
|
|
6
|
-
contract_version: "1.0.0"
|
|
7
|
-
# The delivery record: one <root>/<tranche>/evidence.yaml per tranche, judged against the `delivery:` policy
|
|
8
|
-
# in atdd-bun.yaml. Runs only under the delivery profile and is inert until the repository adopts it
|
|
9
|
-
# (a `delivery:` block, or `delivery` named in `profiles:`).
|
|
10
|
-
emits_rule_ids:
|
|
11
|
-
- delivery.config-schema
|
|
12
|
-
- delivery.evidence-schema
|
|
13
|
-
- delivery.model-allowed
|
|
14
|
-
- delivery.reviewer-independent
|
|
15
|
-
- delivery.findings-resolved
|
|
16
|
-
- delivery.stages-complete
|
|
17
|
-
- delivery.approved-sha-resolves
|
|
18
|
-
# Emitted only at the merge gate (ATDD_DELIVERY_GATE=merge, set by the generated CI on pull requests and the
|
|
19
|
-
# merge queue): it needs a change set against the base branch. tests/delivery.test.ts triggers it in a real
|
|
20
|
-
# repository.
|
|
21
|
-
api_emits_rule_ids:
|
|
22
|
-
- delivery.merge-gate
|
|
23
|
-
realizes_convention:
|
|
24
|
-
- delivery.config-schema
|
|
25
|
-
- delivery.evidence-schema
|
|
26
|
-
- delivery.model-allowed
|
|
27
|
-
- delivery.reviewer-independent
|
|
28
|
-
- delivery.findings-resolved
|
|
29
|
-
- delivery.stages-complete
|
|
30
|
-
- delivery.approved-sha-resolves
|
|
31
|
-
- delivery.merge-gate
|
|
32
|
-
entrypoint: detect.mjs
|
|
33
|
-
report: detect.mjs
|