do-better 1.0.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.
@@ -0,0 +1,98 @@
1
+ # Roadmap Scoring & Sequencing — D3 Rubric
2
+
3
+ The frontier model **proposes** per-finding attributes; deterministic code
4
+ **computes** scores and order. Judgment supplies inputs; arithmetic is never
5
+ delegated to a model.
6
+
7
+ ## Per-finding attributes (frontier proposes)
8
+
9
+ For every verified finding, the model assigns:
10
+
11
+ | Attribute | Values | Meaning |
12
+ |---|---|---|
13
+ | `impact` | S / M / L / XL | how much better the system gets if addressed |
14
+ | `effort` | S / M / L / XL | cost to address, including verification |
15
+ | `confidence` | 0..1 | how sure we are the fix delivers the impact |
16
+ | `dependsOn` | finding ids | what must land first |
17
+ | `railsNeeded` | true/false | whether characterization rails must exist before touching it |
18
+ | `declineReason` | string (optional) | why this should NOT be done (conflicts with charter intent/constraints) |
19
+
20
+ Reconciliation is **by id**: findings the model omits get conservative defaults
21
+ `impact: M, effort: M, confidence: 0.5` — never dropped. Nothing silently
22
+ disappears between findings and roadmap.
23
+
24
+ ## T-shirt tables
25
+
26
+ | Size | Impact value | Effort value |
27
+ |---|---|---|
28
+ | S | 1 | 1 |
29
+ | M | 2 | 2 |
30
+ | L | 3 | 3 |
31
+ | XL | 5 | 5 |
32
+
33
+ ## The score
34
+
35
+ ```
36
+ score = impact × confidence ÷ effort
37
+ ```
38
+
39
+ then weighted by the approved charter (D0):
40
+
41
+ ```
42
+ weighted = score × (charterWeight[dimension] / 3)
43
+ ```
44
+
45
+ A weight of 3 is neutral; the floor guarantees every dimension has weight ≥ 1,
46
+ so no dimension can be zeroed out of the roadmap — only de-emphasized.
47
+
48
+ Worked example: a `high` security finding, impact L (3), confidence 0.8,
49
+ effort M (2), security charter weight 5:
50
+ `3 × 0.8 ÷ 2 = 1.2`, weighted `1.2 × (5/3) = 2.0`.
51
+
52
+ ## Thresholds (deterministic)
53
+
54
+ | Rule | Threshold |
55
+ |---|---|
56
+ | Quick win (front-loaded into Now) | weighted score ≥ 1.5 AND effort = S |
57
+ | Declined (listed, never silently dropped) | weighted score < 0.3, or explicit `declineReason` |
58
+ | Phase bands | Now / Next / Later by descending score, subject to dependency feasibility |
59
+
60
+ ## Sequencing rules (deterministic)
61
+
62
+ 1. **Topological order** on `dependsOn` — an item never appears before its
63
+ prerequisites.
64
+ 2. **Rails-first Phase 0**: environment-fix items (preflight red → "make it
65
+ runnable") and rail-prerequisite items (`railsNeeded` ancestors) come before
66
+ everything. You don't refactor what you can't run, and you don't change what
67
+ you can't pin.
68
+ 3. **Quick wins forward**: qualifying items lead the Now phase — early visible
69
+ value buys trust for the long items.
70
+ 4. **Score bands** fill Now → Next → Later, demoting items whose dependencies
71
+ sit in a later band.
72
+ 5. **Cycles**: break the lowest-weighted-score edge in the cycle and warn. A
73
+ cycle is a planning bug, not a reason to halt.
74
+
75
+ ## Declined items (D6)
76
+
77
+ Every finding that does not become a roadmap item appears in the roadmap's
78
+ `## Declined` section with its reason **and a risk-of-inaction line**. A
79
+ stakeholder must be able to see what was consciously not done and what that
80
+ choice costs. Silent omission is the failure mode this section exists to kill.
81
+
82
+ ## Ticket derivation
83
+
84
+ Each Now and Next item becomes one ADLC-P2-shaped ticket
85
+ ([templates/ticket-template.md](./templates/ticket-template.md)): self-contained
86
+ body, motivation linking back to `findings/F-*.md`, machine-verifiable
87
+ acceptance criteria each naming its verification method, scope globs, rails
88
+ paths, dependency edges with contract files. Tickets are **cold-start tested**
89
+ (D6 gate): a fresh agent with only the ticket must be able to execute it. Gaps
90
+ are repaired up to 2 rounds; a ticket still gapped is demoted to Later — and if
91
+ any Now/Next ticket remains gapped, the roadmap gate fails (exit 2).
92
+
93
+ ## What scoring refuses to optimize
94
+
95
+ Findings count, roadmap length, and artifact volume are vanity metrics (D11).
96
+ The score exists to maximize **ticket survival rate** — items accepted into
97
+ execution without rework — and to keep retained functionality intact. A shorter
98
+ roadmap with higher ticket survival beats a longer one every time.
@@ -0,0 +1,136 @@
1
+ # The Fixed Taxonomy Floor (D5)
2
+
3
+ Eight dimensions of "better," in canonical order. This is the **floor**, not a
4
+ menu: every engagement charter MUST carry a weight (1–5) for every dimension
5
+ below. The charter interview (D0) may *weight* dimensions and *add*
6
+ engagement-specific ones, but it may never drop one — the floor exists to
7
+ prevent charter blind spots ("nobody asked about security, so nobody looked").
8
+ A synthesized charter missing a dimension is corrected to weight 1 with a
9
+ `(floor)` note, never dropped.
10
+
11
+ Weight also governs **D2 finder-pool width**: with `--n` as the ceiling, a
12
+ weight 4–5 dimension fans the full `--n` distinct-lens finders per pass, weight
13
+ 2–3 fans `max(1, floor(--n / 2))`, and weight 1 runs a single finder (no
14
+ pooling). So a heavily-weighted dimension is searched both first (descending
15
+ weight order) and wider. See the flag tables in `SKILL.md` / `README.md`.
16
+
17
+ Each section below is the **finder charter** for that dimension: what a
18
+ D2 finder chartered on this dimension hunts for, and what counts as concrete
19
+ evidence. Finders operate under the refutation doctrine in
20
+ [refute-charter.md](./refute-charter.md) — they are told to *disprove* the
21
+ claim that the codebase is acceptable on the dimension, with file:line
22
+ citations for every claim.
23
+
24
+ Canonical ids (used in charter weights, finding ids, and ticket categories):
25
+ `correctness`, `security`, `maintainability`, `performance`, `operability`,
26
+ `test-quality`, `dependency-health`, `dx`.
27
+
28
+ ## Correctness risk
29
+
30
+ `id: correctness`
31
+
32
+ Hunt for code that can silently produce wrong results: unhandled error paths,
33
+ swallowed exceptions, race conditions and unsynchronized shared state, off-by-one
34
+ and boundary errors, implicit type coercions at trust boundaries, null/undefined
35
+ dereferences on optional data, time-zone and floating-point hazards, partial
36
+ writes without transactions or rollback, retry logic that double-applies effects,
37
+ and logic that contradicts the documented or evident intent (comments, names,
38
+ tests asserting one thing while code does another). Evidence is the exact
39
+ file:line where the wrong result can be produced, plus the input or sequence that
40
+ triggers it. The strongest correctness findings come with a runnable
41
+ reproduction; propose one whenever the claim is mechanically checkable.
42
+
43
+ ## Security
44
+
45
+ `id: security`
46
+
47
+ Hunt for ways an attacker — external or internal — gains capability they should
48
+ not have: injection (SQL, shell, template, path traversal), missing or bypassable
49
+ authentication/authorization checks, secrets in source or config committed to the
50
+ repo, unvalidated input crossing a trust boundary, unsafe deserialization,
51
+ `eval`/dynamic-require on tainted data, child processes built from string
52
+ concatenation, permissive CORS, missing rate limits on state-changing endpoints,
53
+ sensitive data in logs or error messages, and outdated crypto or homegrown
54
+ crypto. Cite the exact sink and the path tainted data takes to reach it. Severity
55
+ tracks exploitability × blast radius, not theoretical purity.
56
+
57
+ ## Maintainability / debt
58
+
59
+ `id: maintainability`
60
+
61
+ Hunt for structures that make every future change slower or riskier: god files
62
+ and god functions, copy-paste clones that must be changed in lockstep, cyclic
63
+ dependencies, dead code that still has to be read, abstraction layers that leak
64
+ or that exist for exactly one caller, configuration scattered across hardcoded
65
+ literals, naming that lies, TODO/FIXME/HACK clusters that mark known unfinished
66
+ surgery, and modules whose churn history shows repeated bug-fix commits (hot,
67
+ fragile code). Evidence is structural and locational — name the files, the line
68
+ ranges, and where possible the churn or clone counterpart that proves the cost
69
+ recurs.
70
+
71
+ ## Performance
72
+
73
+ `id: performance`
74
+
75
+ Hunt for work the system does that it does not need to do, at the moments it can
76
+ least afford it: N+1 query patterns, unbounded result sets, synchronous I/O on
77
+ hot paths, O(n²) loops over data that grows, missing indexes implied by query
78
+ shapes, per-request recomputation of invariants, oversized payloads, chatty
79
+ service calls inside loops, memory retained beyond its useful life, and absent
80
+ caching where reads dwarf writes (or caching with no invalidation where writes
81
+ matter). Claims must name the code path and the scaling variable that makes it
82
+ hurt; "this could be slow" without a growth factor is not a finding.
83
+
84
+ ## Operability
85
+
86
+ `id: operability`
87
+
88
+ Hunt for everything that makes the system hard to run, observe, and recover:
89
+ missing or useless logging at failure points, no health/readiness signals,
90
+ swallowed errors that turn outages into mysteries, absent timeouts and circuit
91
+ breakers on outbound calls, no graceful shutdown, configuration that only works
92
+ on one machine, deploy and migration steps that exist only in someone's head,
93
+ unbounded queues and retries that amplify incidents, and startup that fails
94
+ late instead of failing fast on missing prerequisites. Evidence cites where the
95
+ signal is missing (the catch block that drops the error, the fetch with no
96
+ timeout) — absence is locational too.
97
+
98
+ ## Test quality
99
+
100
+ `id: test-quality`
101
+
102
+ Hunt for the gap between what the test suite appears to guarantee and what it
103
+ actually guarantees: load-bearing behaviors with no test at all (cross-check the
104
+ behavior inventory and rails map), tests with no assertions or assertions that
105
+ cannot fail, tests that mock the very thing under test, snapshot tests nobody
106
+ reads, flaky patterns (sleeps, ordering dependence, shared mutable fixtures),
107
+ test code that swallows errors, and suites that pass with the implementation
108
+ deleted (hollowness). Evidence cites the test file and line, and names the
109
+ production behavior left unguarded. Coverage percentage alone is never evidence.
110
+
111
+ ## Dependency health
112
+
113
+ `id: dependency-health`
114
+
115
+ Hunt for risk imported through the dependency graph: dependencies past
116
+ end-of-life or unmaintained, known-vulnerable version ranges, lockfile drift or
117
+ absence, duplicate dependencies solving the same problem, deep coupling to a
118
+ dependency's internals (imports from `dist/` or private paths), licenses
119
+ incompatible with the engagement's constraints, and single points of failure
120
+ (one maintainer, one registry). Flag what can be verified from manifests and
121
+ lockfiles deterministically; mark CVE/EOL claims that require network
122
+ verification as "needs verification" rather than asserting them — see
123
+ [verification.md](./verification.md).
124
+
125
+ ## Developer experience
126
+
127
+ `id: dx`
128
+
129
+ Hunt for friction that taxes every contributor on every change: setup that takes
130
+ hours or requires tribal knowledge, build/test cycles measured in tens of
131
+ minutes, incantations that exist only in CI config or shell history, missing or
132
+ lying README instructions, inconsistent formatting with no enforcement, error
133
+ messages that don't say what to do, slow or noisy CI that trains people to
134
+ ignore it, and onboarding gaps the glossary and codemap expose. Evidence is the
135
+ concrete command, file, or absence — "DX is bad" is vibes; "`npm test` takes 14
136
+ minutes because X (file:line)" is a finding.
@@ -0,0 +1,71 @@
1
+ # Charter Template — `.dobetter/charter.md` (D0 output)
2
+
3
+ Fill every placeholder. The frontmatter keys and shapes below are a contract:
4
+ `parseCharter` validates them, and the taxonomy floor (D5) requires **all 8
5
+ dimension ids present with weight 1–5** — a dimension the interview didn't
6
+ prioritize gets weight 1 with a `(floor)` note in the rationale, never removed.
7
+
8
+ Frontmatter uses the zero-dependency subset: flat scalars, inline arrays of
9
+ scalars, one level of nesting. Each `extraDimensions` entry is a single
10
+ pipe-delimited scalar string `id|Label|weight` (e.g. `ci-reliability|CI
11
+ reliability|4`); the list is empty when the engagement adds none.
12
+
13
+ ```markdown
14
+ ---
15
+ approved: false
16
+ headSha: <40-hex sha the interview facts were drawn from>
17
+ generatedAt: <ISO 8601 timestamp>
18
+ intent: <stabilize | scale | extend | handoff>
19
+ weights:
20
+ correctness: <1-5>
21
+ security: <1-5>
22
+ maintainability: <1-5>
23
+ performance: <1-5>
24
+ operability: <1-5>
25
+ test-quality: <1-5>
26
+ dependency-health: <1-5>
27
+ dx: <1-5>
28
+ extraDimensions: [<id|Label|weight>, ...]
29
+ ---
30
+
31
+ # Engagement Charter — <repo name>
32
+
33
+ ## Pain
34
+
35
+ <What hurts today, in the stakeholder's words. One bullet per pain point, each
36
+ tied where possible to a scan fact that evidences it
37
+ (`path/to/file.js:123@a1b2c3d`).>
38
+
39
+ ## Intent
40
+
41
+ <The 12-month intent — stabilize, scale, extend, or hand off — and what that
42
+ implies for prioritization. One short paragraph.>
43
+
44
+ ## Constraints
45
+
46
+ <Hard constraints the roadmap must respect: freeze windows, compliance,
47
+ budgets, no-touch areas, team capacity. One bullet each. "None stated" is a
48
+ valid entry — absence must be explicit.>
49
+
50
+ ## Dimension weights
51
+
52
+ <One bullet per taxonomy dimension, in canonical order: the weight, and one
53
+ sentence of rationale citing the interview answer or scan fact that justifies
54
+ it. Floor-corrected dimensions read: "1 (floor) — not prioritized by
55
+ stakeholder; retained per taxonomy floor.">
56
+
57
+ ## Established from the codebase
58
+
59
+ <Questions answered deterministically from D-1 scan facts instead of asked —
60
+ each as "Q → answer, evidence: <citation or scan fact>". Empty section allowed
61
+ but must be present.>
62
+
63
+ ## Engagement dimensions
64
+
65
+ <One bullet per extra dimension: id, label, weight, and why this engagement
66
+ needs it beyond the fixed taxonomy. "None" if extraDimensions is empty.>
67
+ ```
68
+
69
+ Approval: a human reviews and edits this file, then approves (interactively at
70
+ the end of the interview, or later via `do-better charter --approve`). Approval
71
+ hashes the file; the hash is the anchor every downstream phase trusts.
@@ -0,0 +1,56 @@
1
+ # Finding Template — `.dobetter/findings/F-<DIM>-NNNN.md` (D2 output)
2
+
3
+ One file per **verified** finding. Unverified candidates are killed, never
4
+ written — if a file exists in `findings/`, it survived reproduce-or-kill
5
+ ([../verification.md](../verification.md)). The id embeds the dimension
6
+ (first 4 letters, uppercase) and a zero-padded sequence: `F-SEC-0003`,
7
+ `F-CORR-0012`.
8
+
9
+ Frontmatter shapes are a contract (`readFindings` parses them). `evidence` is
10
+ an inline array of canonical citation strings `path:line@sha`; `reproduction`
11
+ is one level of nesting; `stale` is written `false` here and only ever flipped
12
+ by `refresh`, never by identify.
13
+
14
+ ```markdown
15
+ ---
16
+ id: F-<DIM>-NNNN
17
+ dimension: <correctness|security|maintainability|performance|operability|test-quality|dependency-health|dx|<extra-dimension-id>>
18
+ title: <short imperative summary>
19
+ severity: <critical|high|medium|low>
20
+ confidence: <0..1>
21
+ evidence: [<path/to/file.js:123@a1b2c3d>, ...]
22
+ reproduction:
23
+ method: <command|reread|static>
24
+ record: <command + captured output, or blind-reread verdict rationale; single line, escaped>
25
+ exitCode: <integer or null>
26
+ status: verified
27
+ foundAt: <ISO 8601 timestamp>
28
+ headSha: <40-hex repo HEAD at verification time>
29
+ stale: false
30
+ ---
31
+
32
+ # <title>
33
+
34
+ ## Claim
35
+
36
+ <One paragraph: what is wrong, why it matters on this dimension, what triggers
37
+ it. Plain language a stakeholder can read.>
38
+
39
+ ## Evidence
40
+
41
+ <One bullet per citation: the citation (`path/to/file.js:123@a1b2c3d`) plus a
42
+ one-line quote or description of what that location shows. Every bullet's
43
+ citation must verify deterministically — file exists, line in range.>
44
+
45
+ ## Reproduction record
46
+
47
+ <The full reproduction: for `command`, the exact command, its stdout/stderr,
48
+ and exit code; for `reread`, the blind verifier's CONFIRM rationale; for
49
+ `static`, the deterministic check and its result. This record is what refresh
50
+ re-runs to decide resolved-vs-still-present.>
51
+
52
+ ## Impact
53
+
54
+ <What happens if nothing is done — the risk-of-inaction in concrete terms.
55
+ Feeds the roadmap's risk-of-inaction line.>
56
+ ```
@@ -0,0 +1,74 @@
1
+ # Rail Template — Characterization-Test Authoring (D4)
2
+
3
+ A **rail** is a characterization test that pins a behavior exactly as it is
4
+ today, so execution work can prove it broke nothing. Rails are authored in a
5
+ **fresh context** that sees ONLY: the behavior-inventory entry, the boundary
6
+ I/O shape, and this template — never implementation internals (P3
7
+ separate-context doctrine). A rail written by someone who read the
8
+ implementation tests the implementation's opinion of itself.
9
+
10
+ ## Where rails live
11
+
12
+ - File: `<repo>/test/dobetter-rails/<behaviorId>.rail.test.js` (or the repo's
13
+ idiomatic test directory if one is detected — rails run under the repo's own
14
+ runner or `node --test`).
15
+ - Pointers only in `.dobetter/rails/manifest.md`; the tests live in the repo's
16
+ test tree and ship with it.
17
+
18
+ ## Authoring rules
19
+
20
+ 1. **Boundary-level golden-master style.** Capture the behavior at its
21
+ observable surface, by kind:
22
+ - `route` — start the app locally, hit it with builtin `fetch`, assert
23
+ status + headers that matter + body (normalized for timestamps/ids).
24
+ - `cli` — spawn the command (`spawnSync`, no shell), assert exit code,
25
+ stdout, stderr.
26
+ - `job`/`event` — invoke the entry, assert emitted effects.
27
+ - `db-write` — snapshot relevant rows before, run, assert the after-state
28
+ delta.
29
+ 2. **Bug-compatible pinning.** Assert the *current actual* output, even when it
30
+ is odd or known-wrong. Annotate, don't fix:
31
+
32
+ ```js
33
+ // pinned current behavior, possibly a bug: see F-CORR-0007
34
+ assert.equal(res.status, 200); // (spec says 404; current code returns 200)
35
+ ```
36
+
37
+ Rails preserve behavior; the roadmap changes it. A rail that asserts the
38
+ *desired* behavior is red on arrival and useless as a rail.
39
+ 3. **Deterministic.** Normalize or freeze time, ids, ordering, and environment.
40
+ A flaky rail is worse than no rail — it trains people to ignore red.
41
+ 4. **One behavior per rail file.** Named by behavior id (`B-014.rail.test.js`),
42
+ header comment citing the inventory entry and its citation
43
+ (`path:line@sha`).
44
+ 5. **Self-contained setup.** The rail starts/seeds what it needs and tears it
45
+ down; it must pass on a fresh clone where preflight is green.
46
+
47
+ ## Quality gates the rail must survive
48
+
49
+ - **Green on current code** — any rail red after 2 fix rounds is deleted and
50
+ the behavior recorded as `gap: could not pin`. Never ship a red rail.
51
+ - **Hollow-test audit** — mutants in the rail's assertions must be killed. A
52
+ rail that passes with its assertions mutated is fog, not glass; survivors get
53
+ one fix round, then the rail is deleted and the gap recorded. When
54
+ hollow-test is unavailable: deletion spot-check (comment out the behavior's
55
+ entry line; the rail must go red).
56
+ - **Frozen** — once green and audited, the rail path is appended to every
57
+ backlog ticket's `rails` array so ADLC rails-guard freezes it mechanically.
58
+ Execution agents may not edit rails; a rail change is a human decision.
59
+
60
+ ## Manifest row shape — `.dobetter/rails/manifest.md`
61
+
62
+ One table row per authored rail:
63
+
64
+ ```markdown
65
+ | behavior | rail file | style | pinned-at SHA | audit | frozen |
66
+ |---|---|---|---|---|---|
67
+ | B-014 | test/dobetter-rails/B-014.rail.test.js | http golden-master | a1b2c3d | hollow: killed 4/4 | yes |
68
+ | B-021 | test/dobetter-rails/B-021.rail.test.js | cli golden-master | a1b2c3d | spot-check | yes |
69
+ ```
70
+
71
+ `audit` values: `hollow: killed n/n` · `spot-check` · `unaudited (hollow-test
72
+ absent)`. Below the table, a `## Gaps` section lists every targeted behavior
73
+ without a green rail and why (`could not pin`, `env not runnable`, `vacuous —
74
+ deleted`). A gap declared is a known risk; a gap omitted is a lie.
@@ -0,0 +1,67 @@
1
+ # Roadmap Template — `.dobetter/ROADMAP.md` (D3 output)
2
+
3
+ The executive deliverable. Dual artifact, one source of truth: every item here
4
+ maps to verified findings (`findings/F-*.md`) and Now/Next items map to backlog
5
+ tickets. It is a **living document** — idempotent re-runs reconcile prior state
6
+ and move items into Done / Regressed rather than regenerating from scratch.
7
+
8
+ ```markdown
9
+ ---
10
+ generatedAt: <ISO 8601 timestamp>
11
+ headSha: <40-hex repo HEAD this roadmap was generated against>
12
+ basedOnFindings: <count of verified findings consumed>
13
+ approved: false
14
+ ---
15
+
16
+ # Technical Roadmap — <repo name>
17
+
18
+ ## Executive summary
19
+
20
+ <3–6 sentences: the state of the codebase against the charter, the top risks,
21
+ what Now buys, and what was consciously declined. No item lists here —
22
+ judgment, written for a stakeholder who reads nothing else.>
23
+
24
+ ## Phase 0 — Rails & runnability
25
+
26
+ <Items that must precede all change: environment fixes (preflight red →
27
+ "Make the environment runnable"), and characterization-rail prerequisites.
28
+ Empty phase must say "None required — environment runnable, rails in place.">
29
+
30
+ <!-- Item shape, used in every phase section: -->
31
+ - **<title>** (T<id> · score <weighted score> · <severity>)
32
+ - Evidence: <links to findings files, e.g. [F-SEC-0003](findings/F-SEC-0003.md)>
33
+ - Risk of inaction: <one concrete sentence>
34
+
35
+ ## Now
36
+
37
+ <Quick wins first (score ≥ 1.5, effort S), then highest-scored
38
+ dependency-feasible items. Each item: title, finding links, score,
39
+ risk-of-inaction.>
40
+
41
+ ## Next
42
+
43
+ <Same item shape. Items here have tickets too; items demoted by coldstart
44
+ failures land in Later, flagged.>
45
+
46
+ ## Later
47
+
48
+ <Same item shape, lighter detail allowed. Includes coldstart-demoted tickets,
49
+ flagged `coldstart: failed`.>
50
+
51
+ ## Done / Regressed
52
+
53
+ <Living-document ledger. `✅ done — <title> (resolved @ <sha>)` for items whose
54
+ findings no longer reproduce; `⚠ regressed — <title> (re-verified @ <sha>)` for
55
+ previously-done items whose finding came back, and for retained behaviors that
56
+ changed with no roadmap item claiming the change. Empty on first run.>
57
+
58
+ ## Declined
59
+
60
+ <Every finding that did not become a roadmap item: title, finding link, reason
61
+ (explicit declineReason or score < 0.3), and a risk-of-inaction line. Nothing
62
+ is silently dropped — an empty section must state "Nothing declined.">
63
+ ```
64
+
65
+ Approval: human gate 2. Review this file and `backlog/`, edit freely (edits are
66
+ re-hashed, not rejected), then `do-better roadmap --approve`. Approval requires
67
+ the coldstart gate clean.
@@ -0,0 +1,78 @@
1
+ # Ticket Template — `.dobetter/backlog/<id>.md` (D3 output)
2
+
3
+ One markdown file per Now/Next roadmap item, **plus** the machine mirror
4
+ `backlog/tickets.json` in the exact ADLC `.adlc/tickets.json` schema
5
+ (`{ "tickets": [ { id, title, body, scope, rails, edges, duration, category,
6
+ budget? } ] }`). The JSON is the source of truth consumed by `coldstart
7
+ --tickets .dobetter/backlog/tickets.json` and ADLC P3/P4 intake; the markdown
8
+ is the human-review surface. The two are written together and must agree.
9
+
10
+ A ticket must be **self-contained**: a fresh agent with only this ticket (and
11
+ the repo) can execute it. That is what the coldstart gate tests. Embed data
12
+ shapes, contracts, and file paths — never reference "the discussion" or "as
13
+ mentioned above."
14
+
15
+ ```markdown
16
+ ---
17
+ id: T<n>
18
+ title: <short imperative title>
19
+ category: <dimension id of the driving finding>
20
+ duration: <relative build-time estimate, positive number>
21
+ scope: [<glob>, ...]
22
+ rails: [<path>, ...]
23
+ ---
24
+
25
+ # T<n> — <title>
26
+
27
+ ## Motivation
28
+
29
+ <Why this work exists, linking every driving finding:
30
+ [F-SEC-0003](../findings/F-SEC-0003.md). Quote the risk-of-inaction. A ticket
31
+ whose motivation cites no finding is not a do-better ticket.>
32
+
33
+ ## Acceptance criteria
34
+
35
+ <Each criterion is machine-verifiable and NAMES its verification method (F1
36
+ defense). One bullet per criterion, exactly one method each:>
37
+ - <criterion> — verified by: <a test to be written at `<path>`>
38
+ - <criterion> — verified by: <a command whose output is asserted: `<command>` → <expected>>
39
+ - <criterion> — verified by: <a behavior demonstrated: <observable before/after>>
40
+
41
+ ## Scope
42
+
43
+ <The declared file globs this ticket may touch, one per line, matching the
44
+ frontmatter `scope` array. Work outside scope is escalation, not improvisation.>
45
+
46
+ ## Rails
47
+
48
+ <The characterization rails that must stay green while executing this ticket
49
+ (paths matching the frontmatter `rails` array — frozen, hollow-audited; see
50
+ rails/manifest.md). D4 appends authored rail paths here mechanically.>
51
+
52
+ ## Dependencies
53
+
54
+ <One line per edge: `T<m> — contract: <path/to/contract/file>` meaning this
55
+ ticket must complete before T<m>, with the named file as the interface between
56
+ them. "None" if independent. Mirrors `edges` in tickets.json.>
57
+
58
+ ## Partition hints
59
+
60
+ <How to split execution contexts if the ticket is run by parallel agents: which
61
+ files group together, what must be sequential. Optional but recommended.>
62
+
63
+ ## Suppression allowances
64
+
65
+ <Optional `allow-suppression: <marker>` lines, one per allowed lint/test
66
+ suppression marker this ticket may legitimately introduce. Omit the section if
67
+ none — absence means zero suppressions allowed.>
68
+
69
+ ## Coldstart
70
+
71
+ <Gate record: `clean` (round N) or `failed — demoted to Later`, with the gap
72
+ list from the coldstart run. Written by the tool, kept current on re-runs.>
73
+ ```
74
+
75
+ Validation (mirrors aidlc `validateTicket`, applied before writing): string
76
+ `id` and `title` required; `scope`/`rails` arrays; every `edges[].to` a string
77
+ naming a known ticket id; `duration` a positive number. An invalid ticket gets
78
+ one repair round, then is demoted to Later with a warning.