@journeykit/canon 0.26.0 → 0.28.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/skills/SKILL.src.md +245 -89
- package/dist/skills/reference/brief-align.md +4 -2
- package/dist/skills/reference/brief-clarify.md +7 -5
- package/dist/skills/reference/brief-harden.md +4 -2
- package/dist/skills/reference/brief-polish.md +7 -5
- package/dist/skills/reference/brief-shape.md +4 -2
- package/dist/skills/reference/canon-artifact-ingest.md +11 -7
- package/dist/skills/reference/canon-authoring.md +16 -2
- package/dist/skills/reference/canon-context.md +21 -11
- package/dist/skills/reference/canon-fmt.md +10 -2
- package/dist/skills/reference/canon-gate.md +119 -83
- package/dist/skills/reference/canon-inventory.md +34 -22
- package/dist/skills/reference/canon-learn.md +23 -19
- package/dist/skills/reference/canon-plan-import.md +10 -7
- package/dist/skills/reference/canon-plugins.md +15 -8
- package/dist/skills/reference/canon-policy.md +20 -16
- package/dist/skills/reference/canon-report-dashboard.md +30 -19
- package/dist/skills/reference/canon-retrieve.md +13 -10
- package/dist/skills/reference/canon-review.md +96 -68
- package/dist/skills/reference/canon-session-ingest.md +7 -3
- package/dist/skills/reference/canon-storage.md +82 -51
- package/dist/skills/reference/canon-subject.md +123 -84
- package/dist/skills/reference/canon-vocab.md +1 -1
- package/dist/skills/reference/role-implementer.md +295 -64
- package/dist/skills/reference/role-orchestrator.md +547 -55
- package/dist/skills/reference/role-planner.md +189 -32
- package/dist/skills/reference/role-reviewer.md +257 -58
- package/dist/skills/scripts/canon-retrieve-pre-dispatch.sh +10 -5
- package/man/canon-adapter-authorize.1 +44 -0
- package/man/canon-adapter-validate.1 +44 -0
- package/man/canon-adapter.1 +46 -0
- package/man/canon-artifacts-move.1 +63 -0
- package/man/canon-artifacts-store.1 +54 -0
- package/man/canon-artifacts-verify.1 +48 -0
- package/man/canon-artifacts.1 +45 -0
- package/man/canon-brief-approve.1 +62 -0
- package/man/canon-brief-check.1 +44 -0
- package/man/canon-brief-show.1 +50 -0
- package/man/canon-brief.1 +63 -0
- package/man/canon-change-new.1 +66 -0
- package/man/canon-change.1 +42 -0
- package/man/canon-completion.1 +60 -0
- package/man/canon-context-pack-add.1 +47 -0
- package/man/canon-context-pack-show.1 +44 -0
- package/man/canon-context-pack-verify.1 +44 -0
- package/man/canon-context-pack.1 +50 -0
- package/man/canon-context.1 +44 -0
- package/man/canon-dashboard.1 +50 -0
- package/man/canon-demo-init.1 +44 -0
- package/man/canon-demo-review.1 +44 -0
- package/man/canon-demo.1 +47 -0
- package/man/canon-dispatch-begin.1 +80 -0
- package/man/canon-dispatch-diff.1 +41 -0
- package/man/canon-dispatch-end.1 +60 -0
- package/man/canon-dispatch.1 +45 -0
- package/man/canon-divergence-accept.1 +68 -0
- package/man/canon-divergence-add.1 +97 -0
- package/man/canon-divergence-defer.1 +71 -0
- package/man/canon-divergence-list.1 +56 -0
- package/man/canon-divergence-resolve.1 +68 -0
- package/man/canon-divergence.1 +51 -0
- package/man/canon-evidence-add.1 +168 -0
- package/man/canon-evidence-approval-payload.1 +65 -0
- package/man/canon-evidence-audit.1 +121 -0
- package/man/canon-evidence.1 +57 -0
- package/man/canon-export.1 +108 -0
- package/man/canon-feature-new.1 +62 -0
- package/man/canon-feature.1 +39 -0
- package/man/canon-finding-add.1 +196 -0
- package/man/canon-finding-close.1 +117 -0
- package/man/canon-finding-list.1 +59 -0
- package/man/canon-finding.1 +67 -0
- package/man/canon-format.1 +49 -0
- package/man/canon-gate-check.1 +44 -0
- package/man/canon-gate-install-hooks.1 +59 -0
- package/man/canon-gate-promote.1 +62 -0
- package/man/canon-gate.1 +50 -0
- package/man/canon-ingest-plans.1 +53 -0
- package/man/canon-ingest-records.1 +56 -0
- package/man/canon-ingest-sessions.1 +62 -0
- package/man/canon-ingest.1 +50 -0
- package/man/canon-init.1 +98 -0
- package/man/canon-inventory-sync.1 +50 -0
- package/man/canon-inventory.1 +39 -0
- package/man/canon-ledger-compact.1 +50 -0
- package/man/canon-ledger.1 +54 -0
- package/man/canon-migrate.1 +89 -0
- package/man/canon-plugin-sync.1 +53 -0
- package/man/canon-plugin.1 +39 -0
- package/man/canon-policy-approve.1 +50 -0
- package/man/canon-policy-show.1 +41 -0
- package/man/canon-policy.1 +52 -0
- package/man/canon-prompt-add.1 +47 -0
- package/man/canon-prompt-show.1 +41 -0
- package/man/canon-prompt.1 +43 -0
- package/man/canon-purge.1 +70 -0
- package/man/canon-query.1 +111 -0
- package/man/canon-regime-show.1 +50 -0
- package/man/canon-regime.1 +39 -0
- package/man/canon-report-build.1 +44 -0
- package/man/canon-report-check.1 +41 -0
- package/man/canon-report-snapshot.1 +47 -0
- package/man/canon-report.1 +45 -0
- package/man/canon-retrieve.1 +56 -0
- package/man/canon-review-change.1 +98 -0
- package/man/canon-review-scenario.1 +98 -0
- package/man/canon-review.1 +42 -0
- package/man/canon-scenario-new.1 +80 -0
- package/man/canon-scenario.1 +39 -0
- package/man/canon-schema.1 +63 -0
- package/man/canon-selftest.1 +69 -0
- package/man/canon-skills-check.1 +47 -0
- package/man/canon-skills-doctor.1 +47 -0
- package/man/canon-skills-install.1 +53 -0
- package/man/canon-skills-show.1 +104 -0
- package/man/canon-skills.1 +48 -0
- package/man/canon-status.1 +51 -0
- package/man/canon-strategy-approval-payload.1 +53 -0
- package/man/canon-strategy-promote.1 +59 -0
- package/man/canon-strategy-rollback.1 +62 -0
- package/man/canon-strategy.1 +45 -0
- package/man/canon-subject-adopt.1 +53 -0
- package/man/canon-subject-move.1 +80 -0
- package/man/canon-subject-new.1 +65 -0
- package/man/canon-subject-show.1 +44 -0
- package/man/canon-subject-unadopt.1 +63 -0
- package/man/canon-subject.1 +51 -0
- package/man/canon-task-done.1 +47 -0
- package/man/canon-task.1 +42 -0
- package/man/canon-tier-age.1 +50 -0
- package/man/canon-tier.1 +39 -0
- package/man/canon.1 +169 -0
- package/package.json +9 -5
|
@@ -3,30 +3,169 @@
|
|
|
3
3
|
You turn a request into an approved scope: a subject, a change and a PRD
|
|
4
4
|
brief the human answers once. You build nothing. Declare the role with
|
|
5
5
|
`CANON_ROLE=planner` (or `--as planner`); `canon status` and `meta.next`
|
|
6
|
-
then show your steps and count the rest under `waitingOn`.
|
|
6
|
+
then show your steps and count the rest under `waitingOn`. The approvals are
|
|
7
|
+
the human's: `brief approve`, `policy approve` and `divergence accept` refuse
|
|
8
|
+
every agent role (`HUMAN_ONLY`, `retryable: false`), and no flag grants them. You never run them, and never remove or unset your role (`env -u CANON_ROLE`,
|
|
9
|
+
dropping `--as`) to get past the refusal: report the exact call, slug filled in, and
|
|
10
|
+
wait; the human runs it (or uses `canon dashboard`).
|
|
7
11
|
|
|
8
12
|
## Commands
|
|
9
13
|
|
|
10
|
-
Every
|
|
14
|
+
Every leaf of this role is below with its full syntax line (every option the leaf
|
|
15
|
+
has) and an example generated from the CLI's own spec, which runs as written against
|
|
16
|
+
the example story (subject `demo`, change `add-login`, scenario `auth.login.01`): swap
|
|
17
|
+
in your ids. Use only the options on a line; never guess one. Ask `canon schema
|
|
18
|
+
<command> --json` only for a leaf this block does not list, or after a `USAGE` refusal.
|
|
11
19
|
|
|
20
|
+
<!-- canon:generated commands-planner begin -->
|
|
21
|
+
Every leaf takes `--as <ROLE>` and `--json`; `--repo <DIR>` too, except `completion`, `schema`, `skills show`. `--input <JSON|FILE|->` runs a leaf from one JSON document (an array is a batch) and is only on the lines ending `[--input]`. Its document keys are the option names in camelCase, singular even when the option repeats (the value is then an array), and `operands` holds the operands. `--fields <FIELDS>` is a comma list; camelCase and snake_case both match.
|
|
22
|
+
In a syntax line `<X>` is a value, `[x]` optional, `a | b` a choice, `(a | b)` exactly one is required, `[--x <V>]*` may repeat, `<X>+` is one or more, `[--a --b <V>]` go together. An option that is not on the line does not exist: it is refused (`USAGE`).
|
|
23
|
+
|
|
24
|
+
```text
|
|
25
|
+
# Read the brief against the rules
|
|
26
|
+
canon brief check [<CHANGE_ID>]
|
|
27
|
+
```
|
|
28
|
+
```bash
|
|
29
|
+
canon brief check
|
|
30
|
+
```
|
|
31
|
+
```text
|
|
32
|
+
# Show where the change stands and the next one to three steps; never edits
|
|
33
|
+
canon brief show [<CHANGE_ID>]
|
|
34
|
+
```
|
|
35
|
+
```bash
|
|
36
|
+
canon brief show
|
|
37
|
+
```
|
|
38
|
+
```text
|
|
39
|
+
# Write .canon/changes/<slug>/brief.md, import it, and adopt it into a subject
|
|
40
|
+
canon change new <CHANGE_ID> --subject-id <SUBJECT_ID> --title <TEXT> [--change-kind <feature|chore>] [--input]
|
|
41
|
+
```
|
|
42
|
+
```bash
|
|
43
|
+
canon change new add-search --subject-id demo --title "Add search"
|
|
44
|
+
```
|
|
45
|
+
```text
|
|
46
|
+
# Write the shell completion script for canon (bash, zsh or fish)
|
|
47
|
+
canon completion <SHELL>
|
|
48
|
+
```
|
|
49
|
+
```bash
|
|
50
|
+
canon completion zsh
|
|
51
|
+
```
|
|
52
|
+
```text
|
|
53
|
+
# Show what you can author here: record kinds, fields, enums, policies
|
|
54
|
+
canon context [--fields <FIELDS>]
|
|
55
|
+
```
|
|
56
|
+
```bash
|
|
57
|
+
canon context
|
|
58
|
+
```
|
|
59
|
+
```text
|
|
60
|
+
# List the current divergence burn-down state
|
|
61
|
+
canon divergence list [--as-of <TIMESTAMP>] [--limit <N> | --all] [--cursor <CURSOR>] [--fields <FIELDS>]
|
|
62
|
+
```
|
|
63
|
+
```bash
|
|
64
|
+
canon divergence list --as-of 2030-01-01
|
|
65
|
+
```
|
|
66
|
+
```text
|
|
67
|
+
# Create a fresh .feature file for a new area.surface
|
|
68
|
+
canon feature new <SURFACE> --title <TEXT> [--actor-id <ACTOR_ID>] [--session-id <SESSION_ID>] [--project-id <PROJECT_ID>] [--input]
|
|
69
|
+
```
|
|
70
|
+
```bash
|
|
71
|
+
canon feature new billing.invoice --title Invoices
|
|
72
|
+
```
|
|
73
|
+
```text
|
|
74
|
+
# List a change's committed findings at their latest version
|
|
75
|
+
canon finding list --change-id <CHANGE_ID> [--open] [--limit <N> | --all] [--cursor <CURSOR>] [--fields <FIELDS>]
|
|
76
|
+
```
|
|
77
|
+
```bash
|
|
78
|
+
canon finding list --change-id add-login
|
|
79
|
+
```
|
|
80
|
+
```text
|
|
81
|
+
# Validate a spec/artifact corpus against canon's format
|
|
82
|
+
canon format [<DIR>]
|
|
83
|
+
```
|
|
84
|
+
```bash
|
|
85
|
+
canon format .canon/specs
|
|
86
|
+
```
|
|
87
|
+
```text
|
|
88
|
+
# Run the coverage/ledger/staleness/trust checks (0 clean, 1 red, 2 usage)
|
|
89
|
+
canon gate check [--release]
|
|
90
|
+
```
|
|
12
91
|
```bash
|
|
13
|
-
canon
|
|
14
|
-
canon subject new <subject-id> --domain <domain> --title "<title>" --actor-id <unit> --as planner --json
|
|
15
|
-
canon change new <slug> --subject-id <subject-id> --title "<title>" --as planner --json
|
|
16
|
-
canon change new <slug> --subject-id <subject-id> --kind chore --title "<title>" --as planner --json
|
|
17
|
-
canon subject adopt <slug> --subject-id <other-subject-id> --as planner --json
|
|
18
|
-
canon subject unadopt <slug> --subject-id <subject-id> --as planner --json # a draft change off a live subject; refused once its brief is approved
|
|
19
|
-
canon brief check --change-id <slug> --as planner --json
|
|
20
|
-
canon brief approve --change-id <slug> --by "<the human>" --note "<their words>" --as planner --json
|
|
92
|
+
canon gate check
|
|
21
93
|
```
|
|
94
|
+
```text
|
|
95
|
+
# Read stored records across every storage tier
|
|
96
|
+
canon query --kind <change|task|scenario|session|run|event|handoff|review|divergence|trajectory|strategy_item|evidence|subject|finding> [--since <TIMESTAMP>] [--plugin-id <PLUGIN_ID> | --history] [--change-id <CHANGE_ID>] [--status <STATUS>] [--domain <NAME>] [--include-sensitive] [--limit <N> | --all] [--cursor <CURSOR>] [--fields <FIELDS>]
|
|
97
|
+
```
|
|
98
|
+
```bash
|
|
99
|
+
canon query --kind evidence
|
|
100
|
+
```
|
|
101
|
+
```text
|
|
102
|
+
# Fetch role-scoped strategy guidance
|
|
103
|
+
canon retrieve --for-role <ROLE> [--regime <KEY>] [--domain <NAME>] [--subject-id <SUBJECT_ID>] [--limit <N>]
|
|
104
|
+
```
|
|
105
|
+
```bash
|
|
106
|
+
canon retrieve --for-role reviewer --domain dev --limit 20
|
|
107
|
+
```
|
|
108
|
+
```text
|
|
109
|
+
# Append a tagged scenario stub to its .feature file (created if missing); many at once with `--input`
|
|
110
|
+
canon scenario new <SCENARIO_ID> --title <TEXT> [--subject-id <SUBJECT_ID>] [--lane <NAME>] [--case <NAME>] [--flow <FLOW_ID>] [--change-id <CHANGE_ID> (with --flow)] [--actor-id <ACTOR_ID>] [--session-id <SESSION_ID>] [--feature <FILE>] [--project-id <PROJECT_ID>] [--input]
|
|
111
|
+
```
|
|
112
|
+
```bash
|
|
113
|
+
canon scenario new auth.login.02 --title "Sign out" --feature .canon/specs/kind=feature/area=auth/login.feature
|
|
114
|
+
```
|
|
115
|
+
```text
|
|
116
|
+
# Describe canon's own commands
|
|
117
|
+
canon schema [<PATH>]* [--errors | --error <CODE>]
|
|
118
|
+
```
|
|
119
|
+
```bash
|
|
120
|
+
canon schema evidence add
|
|
121
|
+
```
|
|
122
|
+
```text
|
|
123
|
+
# Print a guide built into this binary (markdown on stdout); the installed SKILL.md is a stub that points here
|
|
124
|
+
canon skills show <NAME> [--full]
|
|
125
|
+
```
|
|
126
|
+
```bash
|
|
127
|
+
canon skills show canon --full
|
|
128
|
+
```
|
|
129
|
+
```text
|
|
130
|
+
# Show where this repo stands: subjects by status, their gaps, and the next commands
|
|
131
|
+
canon status [--fields <FIELDS>]
|
|
132
|
+
```
|
|
133
|
+
```bash
|
|
134
|
+
canon status
|
|
135
|
+
```
|
|
136
|
+
```text
|
|
137
|
+
# Link an imported plan change to a subject (adopting it under another subject adds that subject; a change may belong to several)
|
|
138
|
+
canon subject adopt <SUBJECT_ID> --change-id <CHANGE_ID> [--dry-run] [--input]
|
|
139
|
+
```
|
|
140
|
+
```bash
|
|
141
|
+
canon subject adopt demo --change-id add-login
|
|
142
|
+
```
|
|
143
|
+
```text
|
|
144
|
+
# Author a new subject at status `proposed`
|
|
145
|
+
canon subject new <SUBJECT_ID> --domain <NAME> --title <TEXT> [--summary <TEXT>] [--owner-role <ROLE>] [--actor-id <ACTOR_ID>] [--session-id <SESSION_ID>] [--input]
|
|
146
|
+
```
|
|
147
|
+
```bash
|
|
148
|
+
canon subject new payments --domain dev --title Payments
|
|
149
|
+
```
|
|
150
|
+
```text
|
|
151
|
+
# Take a change back out of a subject (the mirror of adopt; refused for a change whose brief is approved)
|
|
152
|
+
canon subject unadopt <SUBJECT_ID> --change-id <CHANGE_ID> [--dry-run] [--input]
|
|
153
|
+
```
|
|
154
|
+
```bash
|
|
155
|
+
canon subject unadopt demo --change-id add-login
|
|
156
|
+
```
|
|
157
|
+
<!-- canon:generated commands-planner end -->
|
|
22
158
|
|
|
23
159
|
After the first `status`, follow `meta.next` of each write. `brief check`
|
|
24
|
-
lists blockers and advisories
|
|
25
|
-
|
|
26
|
-
|
|
160
|
+
lists blockers and advisories and exits 1 when it finds blockers; `canon
|
|
161
|
+
brief show --as planner` names the next steps. The change is an optional
|
|
162
|
+
operand of both (`canon brief check add-login`); without it they read the
|
|
163
|
+
repo's only live change. While the brief has blockers, `status` and
|
|
164
|
+
`change new`'s `meta.next`
|
|
165
|
+
send you to write it (`write the brief: canon brief check <slug>
|
|
27
166
|
lists N blockers`); then, while prose advisories remain, to the polish pass
|
|
28
|
-
(`polish the brief in <path> (
|
|
29
|
-
brief check
|
|
167
|
+
(`polish the brief in <path> (canon skills show brief-polish), then run canon
|
|
168
|
+
brief check <slug>`, with the advisory count and the top rule
|
|
30
169
|
ids); the human step comes after it. A policy that no longer matches its approval fails closed
|
|
31
170
|
(`POLICY_CHANGED_SINCE_APPROVAL`): never edit it; the human re-approves.
|
|
32
171
|
|
|
@@ -69,11 +208,12 @@ ids); the human step comes after it. A policy that no longer matches its approva
|
|
|
69
208
|
edits the plan.
|
|
70
209
|
3. **Check it.** `brief check` (read-only) lists findings: fix every blocker
|
|
71
210
|
(structure) before you stop. Four optional refinement passes, each
|
|
72
|
-
standing alone and none needing another first
|
|
73
|
-
|
|
74
|
-
- `
|
|
75
|
-
- `
|
|
76
|
-
- `
|
|
211
|
+
standing alone and none needing another first; the text of each is
|
|
212
|
+
`canon skills show <name>`:
|
|
213
|
+
- `brief-shape`: structure (sections, order, leftover template text).
|
|
214
|
+
- `brief-clarify`: open questions.
|
|
215
|
+
- `brief-harden`: flow and step detail agree.
|
|
216
|
+
- `brief-align`: scenarios cover the flow.
|
|
77
217
|
|
|
78
218
|
**Compress, then polish.** Before the human reads it, shorten the brief.
|
|
79
219
|
A human reads it once, so every sentence has to earn its place:
|
|
@@ -84,7 +224,7 @@ ids); the human step comes after it. A policy that no longer matches its approva
|
|
|
84
224
|
|
|
85
225
|
Then, when `brief check` reports prose advisories (`prose.*`; `status` and
|
|
86
226
|
`meta.next` name the step), the polish pass is required before the human
|
|
87
|
-
stop: follow `
|
|
227
|
+
stop: follow `canon skills show brief-polish` and rerun `brief check` until
|
|
88
228
|
the advisories are gone or each remaining one is waived with a reason.
|
|
89
229
|
It never blocks approval, but you do not hand the human a brief with
|
|
90
230
|
unexamined advisories.
|
|
@@ -97,29 +237,46 @@ ids); the human step comes after it. A policy that no longer matches its approva
|
|
|
97
237
|
that report. The one answer approves the brief and the policy
|
|
98
238
|
(`.canon/policy.yaml`, written by `canon init`), which is what the gate
|
|
99
239
|
grades the work against.
|
|
100
|
-
5. **
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
240
|
+
5. **The human records the answer.** `brief approve` is the human's leaf: run
|
|
241
|
+
by an agent role it is refused (`HUMAN_ONLY`) with a hint addressed to the
|
|
242
|
+
human. Report the exact call, slug filled in, and wait: `canon brief approve
|
|
243
|
+
add-login --approver <their name> --note "<their own words>"`; the human
|
|
244
|
+
runs it in their own shell (`--approver` and `--note` are theirs to supply)
|
|
245
|
+
or approves in the dashboard. Never approve in their name, never remove or
|
|
246
|
+
unset your role (`env -u CANON_ROLE`, dropping `--as`) to run it, and never
|
|
247
|
+
edit the policy to make the gate pass.
|
|
248
|
+
`canon brief show <slug>` then reports `state: approved`. A brief edited
|
|
249
|
+
after its approval is not approved (`BRIEF_CHANGED_SINCE_APPROVAL`): it
|
|
250
|
+
needs a new answer and a new `brief approve` by the human. A follow-up that
|
|
251
|
+
adds or changes a step of the brief is a scope change and needs a new
|
|
252
|
+
answer.
|
|
105
253
|
|
|
106
254
|
When no human can answer one of the brief's questions, write the question
|
|
107
255
|
into Questions and assumptions, state the assumption you will build on, and
|
|
108
256
|
say so in your report. That applies to the brief's questions, never to the
|
|
109
257
|
approval.
|
|
110
258
|
|
|
259
|
+
**Done when:** `canon brief check add-login` exits 0 (no blockers, and the
|
|
260
|
+
prose advisories are gone or waived with a reason) and `canon brief show
|
|
261
|
+
add-login` reports `state: ready`: the brief is handed to the human and you
|
|
262
|
+
stop. The scope is approved when the same command reports `state:
|
|
263
|
+
approved`; read it in `data.state` of `canon brief show add-login --json`.
|
|
264
|
+
Nothing else starts before that.
|
|
265
|
+
|
|
111
266
|
## Non-behavior work is a chore
|
|
112
267
|
|
|
113
268
|
A refactor, dependency, build, CI or infra change that alters nothing a user
|
|
114
|
-
can observe: `change new
|
|
269
|
+
can observe: `change new --change-kind chore`. Its brief is short (intent,
|
|
115
270
|
category, invariants, checks, out of scope) and approved like any brief, one
|
|
116
271
|
human stop. A chore adds no scenarios: the
|
|
117
|
-
implementer runs the subject's suite again and binds
|
|
118
|
-
`canon evidence add --all-scenarios
|
|
119
|
-
|
|
272
|
+
implementer runs the subject's suite again where the code changed and binds
|
|
273
|
+
it with `canon evidence add --all-scenarios` (a docs-only chore changes no
|
|
274
|
+
code and needs no new evidence), then the reviewer records one
|
|
275
|
+
change-level review of the chore (`canon review change <slug>`). On a
|
|
120
276
|
shipped subject `change new` prints the reopen command for the orchestrator
|
|
121
|
-
(`subject
|
|
122
|
-
ship again until the
|
|
277
|
+
(`subject move <id> --to verifying --reason "<why>"`); the subject cannot
|
|
278
|
+
ship again until the chore's change-level review exists and every scenario
|
|
279
|
+
whose code changed is evidenced after the chore's approval. Work that
|
|
123
280
|
changes behavior is never a chore: it is a feature change.
|
|
124
281
|
|
|
125
282
|
### A migration is cut in phases
|