chamba 0.6.0 → 0.7.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/README.md +13 -6
- package/dist/commands/dev.js +11 -11
- package/dist/commands/settings.js +1 -1
- package/dist/lib/agent-context.js +33 -7
- package/dist/lib/chamba-yaml.js +1 -1
- package/dist/lib/constants.js +4 -4
- package/dist/lib/dockerfile-builder.js +2 -1
- package/dist/lib/ports.js +4 -4
- package/dist/lib/safe-rm.js +13 -3
- package/dist/lib/webterm.js +7 -7
- package/package.json +3 -5
- package/templates/Dockerfile +20 -1
- package/templates/context/web-pane-craft.md +1 -1
- package/templates/pane-apps/client/assets/specs-B1970L17.css +1 -0
- package/templates/pane-apps/client/assets/specs-cEee_SPn.js +23 -0
- package/templates/pane-apps/client/specs/index.html +13 -0
- package/templates/pane-apps/server/specs.mjs +1588 -0
- package/templates/skills/chamba-statusline/SKILL.md +1 -1
- package/templates/skills/dx-spec/SKILL.md +365 -0
- package/templates/skills/dx-spec/references/imagination-guide.md +140 -0
- package/templates/skills/dx-spec/references/review-guide.md +173 -0
- package/templates/skills/dx-spec/references/spec-guide.md +125 -0
- package/templates/skills/dx-spec/references/stages.md +399 -0
- package/templates/skills/dx-spec-config/SKILL.md +313 -0
- package/templates/skills/dx-spec-config/references/principles-template.md +12 -0
- package/templates/skills/dx-spec-execute/SKILL.md +324 -0
- package/templates/specs.sh +106 -0
- package/templates/webterm/README.md +50 -14
- package/templates/webterm/artifacts.js +11 -11
- package/templates/webterm/config.js +52 -9
- package/templates/webterm/conversation.js +3 -3
- package/templates/webterm/pane.js +14 -3
- package/templates/webterm/proc.js +1 -1
- package/templates/webterm/public/app/alerts.js +5 -5
- package/templates/webterm/public/app/composer.js +5 -2
- package/templates/webterm/public/app/connection.js +2 -2
- package/templates/webterm/public/app/dictation.js +1 -1
- package/templates/webterm/public/app/dom.js +13 -5
- package/templates/webterm/public/app/frames.js +8 -1
- package/templates/webterm/public/app/main.js +8 -2
- package/templates/webterm/public/app/new-session.js +1 -1
- package/templates/webterm/public/app/pane-shell.js +315 -0
- package/templates/webterm/public/app/pane.js +58 -183
- package/templates/webterm/public/app/specs-host.js +222 -0
- package/templates/webterm/public/app/state.js +1 -1
- package/templates/webterm/public/app/tabs.js +1 -1
- package/templates/webterm/public/app/terminal.js +8 -0
- package/templates/webterm/public/index.html +51 -27
- package/templates/webterm/public/styles.css +144 -30
- package/templates/webterm/server.js +300 -11
- package/templates/webterm/sessions.js +7 -7
- package/templates/webterm/snapshot.js +2 -2
- package/templates/webterm/specs.js +358 -0
- package/templates/webterm/tool-document.js +67 -0
- package/templates/webterm/typed-line.js +85 -0
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# The quality review
|
|
2
|
+
|
|
3
|
+
This file holds the reviewer briefs, the detection lenses, the severities, the report format, and the design-blockers loop.
|
|
4
|
+
The stage itself is defined in `stages.md`.
|
|
5
|
+
Read this file when the stage starts, and not before.
|
|
6
|
+
|
|
7
|
+
## The reviewer brief
|
|
8
|
+
|
|
9
|
+
Every reviewer subagent gets this brief, with the angle-bracket parts filled in.
|
|
10
|
+
An agent that runs the review itself acts as both the reviewer and the assembler.
|
|
11
|
+
|
|
12
|
+
```markdown
|
|
13
|
+
You are reviewing a written specification you did not help write.
|
|
14
|
+
Your focus is <the reviewer's one focus>, and the lenses that belong to it are <the lenses of that focus>.
|
|
15
|
+
|
|
16
|
+
Read every file in the spec directory at <path to the spec directory>, in this order, whichever of them exist: `README.md` first, since it tells you which stages this work ran, then `intake.md`, `spec/SPEC.md`, `research/RESEARCH.md`, `plan/PLAN.md` and the phase files beside it, and every page directly under `mocks/`.
|
|
17
|
+
Skip `mocks/candidates/`: it is a record of directions nobody chose, and it is not part of the work under review.
|
|
18
|
+
The screens to build are the mocks the `Mocks` section of `spec/SPEC.md` lists.
|
|
19
|
+
Read the principles file at <path to principles.md>.
|
|
20
|
+
Read the repo's own rule files, `CLAUDE.md` and `AGENTS.md`, wherever they exist.
|
|
21
|
+
|
|
22
|
+
Judge the artifacts as written.
|
|
23
|
+
Do not take the conclusions of the session that wrote them as settled: you were not in that session, and judging this work with fresh eyes is exactly your value.
|
|
24
|
+
You share no context with the other reviewers, you are not told what they found, and you must not ask another agent for context.
|
|
25
|
+
The deviations recorded in the plan's principles check are exceptions the user already approved, so raise one only when the reason written next to it does not hold.
|
|
26
|
+
|
|
27
|
+
Before you read anything, turn your lenses into a checklist: one check per lens, split further where a lens covers several things.
|
|
28
|
+
Then run every check, and return that checklist in your reply, with a pass or fail line per check.
|
|
29
|
+
Return every failed check as a finding, carrying its severity from the levels below, the artifact and the section it points at, a one-line title, and the reasoning behind it.
|
|
30
|
+
When a check fails on a decision that is the user's to make rather than a plain fix, say so, list the options, and name the one you would pick.
|
|
31
|
+
A check that passes can still leave you with something better to propose - a simpler shape, a design choice you would make differently, code the repo already ships that does part of the work.
|
|
32
|
+
Report that as a finding in the same form, and say in its reasoning that nothing failed and this is an improvement you are offering.
|
|
33
|
+
Give it the severity of what it would be worth.
|
|
34
|
+
Give your findings no id and no state, and write no header block: the agent running the review assembles the report and fills those in.
|
|
35
|
+
A finding you are unsure about is still reported, and you say in its reasoning that it is a judgment call.
|
|
36
|
+
|
|
37
|
+
Change no file and write nothing to disk.
|
|
38
|
+
Your reply is everything you produce.
|
|
39
|
+
|
|
40
|
+
<the severity levels of this file, copied into the brief>
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## The detection lenses
|
|
44
|
+
|
|
45
|
+
Each lens has one line, so a brief names the lenses that belong to its focus.
|
|
46
|
+
|
|
47
|
+
- Inconsistency between artifacts - reads `spec/SPEC.md`, `research/RESEARCH.md`, `plan/PLAN.md` and the mocks against each other, for two statements that cannot both be true.
|
|
48
|
+
- Coverage of the requirements - see the block below.
|
|
49
|
+
- Missing detail and unhandled edge cases - reads the requirements and the flows for the empty, error and limit cases nobody wrote down.
|
|
50
|
+
- Ambiguity and untestable requirements - reads `spec/SPEC.md` for an open `[NEEDS CLARIFICATION: ...]` marker, a requirement with no acceptance criterion, and a requirement nobody could call pass or fail.
|
|
51
|
+
- Duplication and overlap - reads the artifacts for the same thing stated twice, in two places that can drift apart.
|
|
52
|
+
- Terminology drift - reads every artifact for one idea under several names, or one name over several ideas.
|
|
53
|
+
- Principles alignment - reads the artifacts against the principles file and the repo's own rule files.
|
|
54
|
+
- Better ways to do this - reads the design against the codebase for a simpler shape, and for code the repo already ships that does part of the work.
|
|
55
|
+
- Design blockers - reads the design for what would send the build wrong, and reports at HIGH and CRITICAL alone.
|
|
56
|
+
|
|
57
|
+
The consistency-and-completeness reviewer takes every lens except principles alignment, better ways to do this, and design blockers, which go to the reviewers of those names.
|
|
58
|
+
A focus outside this set takes the lenses that touch it.
|
|
59
|
+
Every lens goes to exactly one reviewer on the confirmed panel, so a panel that drops a focus hands that focus's lenses to the reviewer nearest to it.
|
|
60
|
+
|
|
61
|
+
## The coverage lens
|
|
62
|
+
|
|
63
|
+
When the protocol includes the execution plan stage, the coverage lens runs two checks.
|
|
64
|
+
It checks that every requirement ID in `spec/SPEC.md` appears in some phase's `Covers` line in `plan/PLAN.md`.
|
|
65
|
+
It also checks that every ID named in a `Covers` line exists in `spec/SPEC.md`.
|
|
66
|
+
A requirement with no plan coverage is a CRITICAL finding.
|
|
67
|
+
The reviewer states which of two causes it looks like: a missing phase, or scope that belongs in the non-goals.
|
|
68
|
+
When the protocol has no execution plan stage, the lens checks instead that every requirement carries its own acceptance criterion, and reads as a pass or a fail.
|
|
69
|
+
|
|
70
|
+
## The severity levels
|
|
71
|
+
|
|
72
|
+
- **CRITICAL** - a principles violation, a contradiction between artifacts, or a requirement with no plan coverage.
|
|
73
|
+
- **HIGH** - a conflicting or untestable requirement, an ambiguous security or performance attribute.
|
|
74
|
+
- **MEDIUM** - terminology drift, an edge case with missing detail.
|
|
75
|
+
- **LOW** - style and wording.
|
|
76
|
+
|
|
77
|
+
Fix a conflict with a principle by changing the work.
|
|
78
|
+
Never resolve it by softening the principle.
|
|
79
|
+
|
|
80
|
+
## The design-blockers loop
|
|
81
|
+
|
|
82
|
+
One reviewer on every panel has the design-blockers focus.
|
|
83
|
+
Its brief is the brief above, with two additions:
|
|
84
|
+
|
|
85
|
+
- It reports HIGH and CRITICAL findings alone. Anything below that is not its business, and another reviewer has it.
|
|
86
|
+
- It reads for what would send the build wrong: a design that cannot hold, a contract two artifacts read differently, a requirement whose shape makes it unbuildable as written.
|
|
87
|
+
|
|
88
|
+
**The loop.**
|
|
89
|
+
Run the blockers reviewer.
|
|
90
|
+
Fix what it found.
|
|
91
|
+
Then run it again, with fresh context, over the fixed artifacts.
|
|
92
|
+
Repeat until a round returns nothing.
|
|
93
|
+
A fresh run each time is the point: a reviewer that saw the last round would grade its own fixes.
|
|
94
|
+
|
|
95
|
+
**The guardrail.**
|
|
96
|
+
A scoped reviewer has no natural zero.
|
|
97
|
+
Given fixed artifacts and a mandate to find HIGH findings, a reviewer finds HIGH findings, and the rounds degrade into ever smaller material dressed in a severity it does not carry.
|
|
98
|
+
|
|
99
|
+
So judge every returned finding before you loop again, against one criterion:
|
|
100
|
+
|
|
101
|
+
> A finding an executing agent would likely have resolved on its own is not a true design blocker, whatever severity the reviewer gave it.
|
|
102
|
+
|
|
103
|
+
An executing agent reads the code, runs the tests, and makes the small calls the spec left open.
|
|
104
|
+
That is its job.
|
|
105
|
+
A finding that names one of those calls is execution's work, and the plan's own review checkpoints cover it.
|
|
106
|
+
|
|
107
|
+
**The close.**
|
|
108
|
+
A round whose findings all fail that test closes the loop.
|
|
109
|
+
Record the judgment per finding in the report - what it was, and why it failed the test - and leave that material to execution.
|
|
110
|
+
Only a finding that passes the test justifies another round.
|
|
111
|
+
|
|
112
|
+
Convergence here is judged, never awaited.
|
|
113
|
+
Do not run a further round in the hope of a zero.
|
|
114
|
+
|
|
115
|
+
## The report format
|
|
116
|
+
|
|
117
|
+
`review/REVIEW.md`:
|
|
118
|
+
|
|
119
|
+
```markdown
|
|
120
|
+
# Quality review - <title of the work>
|
|
121
|
+
|
|
122
|
+
- Run: YYYY-MM-DD
|
|
123
|
+
- Mode: fresh-context subagents | inline - the session that wrote the spec
|
|
124
|
+
- Panel: <one focus per reviewer>
|
|
125
|
+
- Blockers loop: <n> rounds, closed by <a zero round | judgment>
|
|
126
|
+
- Findings: <total>, of which <n> applied, <n> dismissed, <n> waiting on you
|
|
127
|
+
|
|
128
|
+
## <the first reviewer's focus>
|
|
129
|
+
|
|
130
|
+
- [x] <a check this reviewer ran and passed>
|
|
131
|
+
- [ ] <a check it ran and failed>
|
|
132
|
+
|
|
133
|
+
### RV-01 - <the finding in one line>
|
|
134
|
+
|
|
135
|
+
- Severity: HIGH
|
|
136
|
+
- Points at: SPEC.md, the Requirements section, FR-04
|
|
137
|
+
- State: FOR YOUR DECISION
|
|
138
|
+
- Options: <first option> | <second option>
|
|
139
|
+
- Reasoning: <why the reviewer raised it>
|
|
140
|
+
- Note: <the fix applied, the reason it was dismissed, or what the reviewer recommends>
|
|
141
|
+
|
|
142
|
+
### RV-02 - <the finding in one line>
|
|
143
|
+
|
|
144
|
+
- Severity: MEDIUM
|
|
145
|
+
- Points at: SPEC.md, the Data section
|
|
146
|
+
- State: APPLIED
|
|
147
|
+
- Reasoning: <why the reviewer raised it>
|
|
148
|
+
- Note: <the fix that was applied>
|
|
149
|
+
|
|
150
|
+
## Design blockers
|
|
151
|
+
|
|
152
|
+
### Round 1
|
|
153
|
+
|
|
154
|
+
<the findings of that round, in the form above>
|
|
155
|
+
|
|
156
|
+
### Round 2 - closed by judgment
|
|
157
|
+
|
|
158
|
+
<each finding, with the judgment against the criterion and where the material was left>
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
The running agent assembles this report from the reviewers' replies.
|
|
162
|
+
It writes the header block, and puts each reviewer's checklist and findings under that reviewer's focus.
|
|
163
|
+
It assigns the ids and the states.
|
|
164
|
+
Finding ids run `RV-01`, `RV-02`, and so on, in writing order across the whole report.
|
|
165
|
+
An id never changes, so a decision that names a finding still points at the same finding.
|
|
166
|
+
|
|
167
|
+
`State:` holds `APPLIED`, `DISMISSED` or `FOR YOUR DECISION`.
|
|
168
|
+
A finding that waits on the user carries an `Options:` line, recommended option first.
|
|
169
|
+
Every other finding leaves that line out.
|
|
170
|
+
The report keeps every finding, applied and dismissed included.
|
|
171
|
+
A finding the user decides on keeps its id and gains the outcome in its `Note:` line.
|
|
172
|
+
Applying that decision changes its `State:` line: `APPLIED` when the decision changed the artifacts, and `DISMISSED` when the user left them as they are.
|
|
173
|
+
Either way, drop the `Options:` line and update the counts in the header.
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# What goes in SPEC.md
|
|
2
|
+
|
|
3
|
+
The technical specs stage of `/dx-spec` uses this guide, and so does every other stage that writes into `SPEC.md`.
|
|
4
|
+
|
|
5
|
+
**No fixed template.**
|
|
6
|
+
Write the sections the work needs, and name and order them to fit the work.
|
|
7
|
+
A small chore may need a few lines. A large feature may need many sections.
|
|
8
|
+
Common sections are: goal, context, scope and **non-goals**, requirements or behavior, edge cases and errors, data and contracts, constraints, and acceptance criteria.
|
|
9
|
+
For the constraints, follow the repo's own rules in `CLAUDE.md` or `AGENTS.md`.
|
|
10
|
+
Drop every section that does not apply.
|
|
11
|
+
Label anything left open as an **assumption** or an **open question**.
|
|
12
|
+
Write each date as an absolute date.
|
|
13
|
+
Reference code as `path:line`.
|
|
14
|
+
|
|
15
|
+
**Mark each ambiguity that is worth the user's time.**
|
|
16
|
+
Write the mark where the ambiguity sits: `[NEEDS CLARIFICATION: <the specific question>]`.
|
|
17
|
+
Add a mark when a choice changes the scope or the behavior by a large amount, when more than one reading is reasonable, or when no reasonable default exists.
|
|
18
|
+
For an ambiguity below that bar, write a labeled assumption stating the guess, so no choice stays silent.
|
|
19
|
+
|
|
20
|
+
**At most 3 markers stay open at one time.**
|
|
21
|
+
When more candidates clear the bar, keep the markers in this priority order: scope first, then security and privacy, then the user's experience, then technical detail.
|
|
22
|
+
Turn the rest into labeled assumptions.
|
|
23
|
+
To clear a marker, ask the user. The answer replaces the marker in `SPEC.md`, in the same round the user answered.
|
|
24
|
+
A doubt anywhere outside these stages does not wait: ask it in the next round.
|
|
25
|
+
The finalize gate does not pass while a marker stays open.
|
|
26
|
+
|
|
27
|
+
**Requirements carry IDs and acceptance criteria** when the protocol includes the execution plan stage or the quality review stage.
|
|
28
|
+
With neither stage, write the requirements in plain language instead.
|
|
29
|
+
Number each ID in writing order, as `FR-01`, `FR-02`, and so on.
|
|
30
|
+
Never renumber an ID after you write it, so a phase or a finding that names one still points at the same requirement.
|
|
31
|
+
Give each ID exactly one requirement.
|
|
32
|
+
Phrase each requirement so a reviewer can call it a pass or a fail.
|
|
33
|
+
Write its acceptance criterion under it, on its own line, as `AC: <how to tell it holds>`.
|
|
34
|
+
|
|
35
|
+
The spec also states its success criteria: the measures that show the work is done.
|
|
36
|
+
Write each one so it can be measured, and without naming a technology where the work allows that.
|
|
37
|
+
Success criteria carry no IDs.
|
|
38
|
+
|
|
39
|
+
```markdown
|
|
40
|
+
- **FR-01**: the cart banner shows the discount total on every page of the checkout flow.
|
|
41
|
+
AC: a cart with a discount shows that total on cart, address, and payment.
|
|
42
|
+
- **FR-02**: an expired discount code is rejected with a message naming its expiry date.
|
|
43
|
+
AC: submitting an expired code leaves the total unchanged and shows that date.
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**Add a `Decisions` section** to any work that picks a stack, a package, or an algorithm.
|
|
47
|
+
Write one entry per choice: the choice, the reason for it, and the alternatives the work rejected with the reason for each.
|
|
48
|
+
The research stage produces the comparison behind a decision, and the spec records its outcome.
|
|
49
|
+
|
|
50
|
+
**Add a `Mocks` section** when the UI mocks stage runs.
|
|
51
|
+
Write one line per screen: its id, its title, and the path to its page relative to `SPEC.md`.
|
|
52
|
+
After the user approves the mocks, add a line `Approved: YYYY-MM-DD`.
|
|
53
|
+
|
|
54
|
+
```markdown
|
|
55
|
+
## Mocks
|
|
56
|
+
|
|
57
|
+
- `cart-banner` - Cart banner - ../mocks/cart-banner.html
|
|
58
|
+
- `discount-field` - Discount field - ../mocks/discount-field.html
|
|
59
|
+
|
|
60
|
+
Approved: 2026-08-14
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**Add a `North star` section** when the run ran in imagination mode, and under no other condition.
|
|
64
|
+
The section holds the ideal the run reached for, beside what the work chose.
|
|
65
|
+
Write it in three parts:
|
|
66
|
+
|
|
67
|
+
- The ideal, in a few lines: what the best possible version of this work does for the user.
|
|
68
|
+
- What the work chose, and what that choice gives up against the ideal.
|
|
69
|
+
- A short note on what shaped the candidates: the prior art and the patterns the creative pass found.
|
|
70
|
+
|
|
71
|
+
The executing agent steers its small decisions by this section, so write the ideal in terms of what the user gets, not in terms of files.
|
|
72
|
+
|
|
73
|
+
**Add a visual to a section only where it earns its place.**
|
|
74
|
+
Put it in the markdown itself: inline SVG for a flow or an architecture, or an HTML table or figure where markdown cannot show the same thing.
|
|
75
|
+
The agent that reads `SPEC.md` and the user reading it on the tab then see the same content.
|
|
76
|
+
The same rule holds for `PLAN.md` and `RESEARCH.md`.
|
|
77
|
+
A visual that stands on its own goes beside the document instead, as `stages.md` says under **Visuals**.
|
|
78
|
+
Either way, keep it self-contained: no external image, and no script.
|
|
79
|
+
|
|
80
|
+
**Every spec carries these two notes.**
|
|
81
|
+
|
|
82
|
+
1. At the top of the spec, close to as written:
|
|
83
|
+
|
|
84
|
+
> **For the implementing agent - read this first.** This spec was written during planning with limited knowledge of the code.
|
|
85
|
+
> Before building anything, review it carefully against the actual codebase and **plan first** (in plan mode, where your environment has one).
|
|
86
|
+
> Treat nothing here as settled: if the spec turns out misaligned with the code, or you see a better path, **push back and raise it** rather than building something you can tell is off.
|
|
87
|
+
|
|
88
|
+
2. Inside a solution sketch, where the spec has one, close to as written:
|
|
89
|
+
|
|
90
|
+
> **This solution sketch is non-binding.** It is a suggested direction formed with limited knowledge during spec-writing, not a fixed instruction.
|
|
91
|
+
> The implementing agent is free - and expected - to find the better design while building, and must flag any noticeable departure so the user stays informed.
|
|
92
|
+
|
|
93
|
+
## The coherence rewrite
|
|
94
|
+
|
|
95
|
+
A spec grows by rounds: the user says something at a gate, a reviewer finds something, a decision changes an artifact.
|
|
96
|
+
Each of those leaves a scar - a paragraph patched in, a section that answers a question nobody reading it can see, a note about what changed.
|
|
97
|
+
The artifacts then read as a history of the work rather than as a description of it, and the agent that builds from them pays for that.
|
|
98
|
+
|
|
99
|
+
**Rewrite the touched artifacts right before the finalize gate, so they read as if written with everything known from the start.**
|
|
100
|
+
The rewrite carries no review metadata, no revision note, and no trace of the round that caused a change.
|
|
101
|
+
|
|
102
|
+
**When it runs.** When anything after the first writing changed the artifacts: the user's feedback, a review fix, a decision.
|
|
103
|
+
**When it is skipped.** When nothing changed them. A spec that went through its stages once and was approved as written needs no rewrite.
|
|
104
|
+
|
|
105
|
+
Keep a copy of each artifact before you touch it.
|
|
106
|
+
Put the copies in `.rewrite/` inside the spec directory, under the same names.
|
|
107
|
+
The review below reads them, and it is the only reader they have: without them a fresh reviewer can only read the new text, and the completeness check has nothing to check against.
|
|
108
|
+
Delete `.rewrite/` when the review is done, before the finalize gate.
|
|
109
|
+
|
|
110
|
+
Rewrite from meaning, not by patching.
|
|
111
|
+
Read the whole artifact first and understand what it now says.
|
|
112
|
+
Then write it again.
|
|
113
|
+
Do not scan for the scars and repair only those spots: that leaves a stitched document, which is the thing this step exists to remove.
|
|
114
|
+
Keep every fact, every requirement ID, every acceptance criterion, and every labeled assumption.
|
|
115
|
+
An ID never changes, because a phase and a finding point at it.
|
|
116
|
+
|
|
117
|
+
**One round of review follows every rewrite.**
|
|
118
|
+
Run one fresh reviewer, once, scoped to the rewrite alone:
|
|
119
|
+
|
|
120
|
+
- Completeness against the copies in `.rewrite/`, so no meaning was lost. Give the reviewer both paths and let it read them itself. Never summarize the old text for it: a summary of yours is what it is there to check.
|
|
121
|
+
- The repo's own writing rules.
|
|
122
|
+
|
|
123
|
+
Fix what it finds.
|
|
124
|
+
That ends the step.
|
|
125
|
+
There is no second round: a rewrite review that loops would be the scar-making round it exists to remove.
|