wdi-method 0.3.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/LICENSE +21 -0
- package/README.md +203 -0
- package/bin/wdi-method.js +906 -0
- package/kit/.constitution/README.md +66 -0
- package/kit/.constitution/codebase/brownfield-guide.md +18 -0
- package/kit/.constitution/codebase/conventions-guide.md +18 -0
- package/kit/.constitution/codebase/stack-guide.md +18 -0
- package/kit/.constitution/constitution.md +135 -0
- package/kit/.constitution/document/architecture-guide.md +209 -0
- package/kit/.constitution/document/bmad-guide.md +151 -0
- package/kit/.constitution/document/bmad-skill-register.md +71 -0
- package/kit/.constitution/document/brief-guide.md +94 -0
- package/kit/.constitution/document/corpus-guide.md +341 -0
- package/kit/.constitution/document/decision-guide.md +134 -0
- package/kit/.constitution/document/delivery-flow-guide.md +338 -0
- package/kit/.constitution/document/prd-guide.md +202 -0
- package/kit/.constitution/document/sdd-guide.md +206 -0
- package/kit/.constitution/document/srs-guide.md +147 -0
- package/kit/.constitution/document/templates/addendum.md +71 -0
- package/kit/.constitution/document/templates/architecture-spine.md +100 -0
- package/kit/.constitution/document/templates/brief.md +110 -0
- package/kit/.constitution/document/templates/c4.md +77 -0
- package/kit/.constitution/document/templates/contract.md +52 -0
- package/kit/.constitution/document/templates/cross-cutting.md +80 -0
- package/kit/.constitution/document/templates/decision.md +64 -0
- package/kit/.constitution/document/templates/design-system.md +67 -0
- package/kit/.constitution/document/templates/flow.md +51 -0
- package/kit/.constitution/document/templates/integration.md +69 -0
- package/kit/.constitution/document/templates/inventory.md +69 -0
- package/kit/.constitution/document/templates/lc.md +47 -0
- package/kit/.constitution/document/templates/lifecycle.md +52 -0
- package/kit/.constitution/document/templates/meeting.md +47 -0
- package/kit/.constitution/document/templates/model.md +55 -0
- package/kit/.constitution/document/templates/oq.md +45 -0
- package/kit/.constitution/document/templates/prd.md +226 -0
- package/kit/.constitution/document/templates/questions.md +75 -0
- package/kit/.constitution/document/templates/rtr.md +61 -0
- package/kit/.constitution/document/templates/rules.md +47 -0
- package/kit/.constitution/document/templates/scn.md +40 -0
- package/kit/.constitution/document/templates/sdd.md +146 -0
- package/kit/.constitution/document/templates/srs.md +149 -0
- package/kit/.constitution/document/templates/structure-codebase.md +129 -0
- package/kit/.constitution/document/templates/structure-document.md +90 -0
- package/kit/.constitution/document/templates/uc.md +69 -0
- package/kit/.constitution/document/templates/ux.md +77 -0
- package/kit/.constitution/document/ux-guide.md +99 -0
- package/kit/.constitution/language-guide.md +69 -0
- package/kit/.constitution/method/README.md +169 -0
- package/kit/.constitution/method/artifact-map.md +155 -0
- package/kit/.constitution/method/portability.md +91 -0
- package/kit/.constitution/method/rationale.md +246 -0
- package/kit/.constitution/method-glossary.md +169 -0
- package/kit/.constitution/project/README.md +68 -0
- package/kit/.constitution/repo-guide.md +97 -0
- package/kit/.constitution/scripts/inventory.py +527 -0
- package/kit/.constitution/scripts/timeline.py +665 -0
- package/kit/.constitution/scripts/validate.py +1579 -0
- package/kit/.constitution/structure-guide.md +202 -0
- package/kit/assets/bmad-custom/bmad-advanced-elicitation.toml +15 -0
- package/kit/assets/bmad-custom/bmad-architecture.toml +31 -0
- package/kit/assets/bmad-custom/bmad-build-auto.toml +10 -0
- package/kit/assets/bmad-custom/bmad-build.toml +52 -0
- package/kit/assets/bmad-custom/bmad-code-review.toml +12 -0
- package/kit/assets/bmad-custom/bmad-correct-course.toml +27 -0
- package/kit/assets/bmad-custom/bmad-deep-recon.toml +11 -0
- package/kit/assets/bmad-custom/bmad-prd.toml +42 -0
- package/kit/assets/bmad-custom/bmad-product-brief.toml +34 -0
- package/kit/assets/bmad-custom/bmad-retrospective.toml +9 -0
- package/kit/assets/bmad-custom/bmad-spec.toml +15 -0
- package/kit/assets/bmad-custom/bmad-ux.toml +19 -0
- package/kit/assets/bmad-custom/config.toml +6 -0
- package/kit/skills/wdi-blueprint/SKILL.md +203 -0
- package/kit/skills/wdi-build/SKILL.md +244 -0
- package/kit/skills/wdi-component/SKILL.md +172 -0
- package/kit/skills/wdi-decision/.gitkeep +0 -0
- package/kit/skills/wdi-decision/SKILL.md +183 -0
- package/kit/skills/wdi-help/.gitkeep +0 -0
- package/kit/skills/wdi-help/SKILL.md +98 -0
- package/kit/skills/wdi-init/SKILL.md +149 -0
- package/kit/skills/wdi-log/SKILL.md +107 -0
- package/kit/skills/wdi-problem/SKILL.md +90 -0
- package/kit/skills/wdi-product/SKILL.md +127 -0
- package/kit/skills/wdi-question/.gitkeep +0 -0
- package/kit/skills/wdi-question/SKILL.md +88 -0
- package/kit/skills/wdi-reconcile/.gitkeep +0 -0
- package/kit/skills/wdi-reconcile/SKILL.md +146 -0
- package/kit/skills/wdi-report/SKILL.md +205 -0
- package/kit/skills/wdi-review/SKILL.md +118 -0
- package/kit/skills/wdi-systematic-debugging/SKILL.md +193 -0
- package/kit/skills/wdi-systematic-debugging/references/condition-based-waiting.md +115 -0
- package/kit/skills/wdi-systematic-debugging/references/defense-in-depth.md +122 -0
- package/kit/skills/wdi-systematic-debugging/references/find-polluter.sh +72 -0
- package/kit/skills/wdi-systematic-debugging/references/root-cause-tracing.md +169 -0
- package/kit/skills/wdi-ux/SKILL.md +145 -0
- package/kit-overlay/AGENTS.md +196 -0
- package/kit-overlay/README.md +66 -0
- package/kit-overlay/constitution.md +135 -0
- package/kit-overlay/portability.md +91 -0
- package/kit-overlay/repo-guide.md +97 -0
- package/lib/agents-block.mjs +52 -0
- package/lib/identity.mjs +65 -0
- package/package.json +37 -0
- package/scaffold/.control/decisions/.gitkeep +0 -0
- package/scaffold/.control/generated/.gitkeep +2 -0
- package/scaffold/.control/meetings/.gitkeep +0 -0
- package/scaffold/.control/memlog/.gitkeep +0 -0
- package/scaffold/.control/product-glossary.md +21 -0
- package/scaffold/.control/project-non-technical-log.md +23 -0
- package/scaffold/.control/questions/answered.md +11 -0
- package/scaffold/.control/questions/assumptions.md +15 -0
- package/scaffold/.control/questions/blocking.md +21 -0
- package/scaffold/.control/questions/external.md +11 -0
- package/scaffold/.control/registry/components.yaml +21 -0
- package/scaffold/.control/registry/decisions.yaml +6 -0
- package/scaffold/.control/registry/defects.yaml +3 -0
- package/scaffold/.control/registry/index.yaml +46 -0
- package/scaffold/.control/registry/requirements.yaml +15 -0
- package/scaffold/.control/registry/risks.yaml +5 -0
- package/scaffold/.control/registry/usecases.yaml +6 -0
- package/scaffold/.control/registry/waves.yaml +5 -0
- package/scaffold/.control/structure-codebase.md +19 -0
- package/scaffold/.control/structure-document.md +25 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: c4
|
|
3
|
+
level: 2 # 1 (system context) · 2 (containers) · 3 (components)
|
|
4
|
+
container: '{container}' # level 3 only — one file per container
|
|
5
|
+
created: '{YYYY-MM-DD}'
|
|
6
|
+
updated: '{YYYY-MM-DD}'
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# C4 L{n} — {title}
|
|
10
|
+
|
|
11
|
+
<!-- TEMPLATE GUIDE — act on these comments, then delete them.
|
|
12
|
+
|
|
13
|
+
Three levels, three files, three different questions. All live in .how/_platform/.
|
|
14
|
+
|
|
15
|
+
L1 c4-l1-system-context.md Who uses the system, and what it talks to. Once per product.
|
|
16
|
+
EXTERNAL SYSTEMS LIVE HERE, and nowhere else.
|
|
17
|
+
L2 c4-l2-containers.md What runs and what stores, and how they communicate. OWNS the
|
|
18
|
+
container list, and carries the PC x container matrix.
|
|
19
|
+
L3 c4-l3-<container>.md ONE FILE PER CONTAINER WE BUILD. The boxes are Product Components.
|
|
20
|
+
Only where a container holds more than one PC — the L2 matrix
|
|
21
|
+
already says which PC lives where, so a one-PC container needs no
|
|
22
|
+
file of its own.
|
|
23
|
+
|
|
24
|
+
ALL THREE LAND AT G3, and not one of them waits for a wave. Which container a PC lives in cannot
|
|
25
|
+
be discovered by a wave, because a wave picks its stories FROM that answer.
|
|
26
|
+
|
|
27
|
+
THE AXIS THAT CONFUSES PEOPLE: a container runs its own code or stores its own data; a Product
|
|
28
|
+
Component is a domain slice. They cross. One container holds several PC boxes, and one PC may
|
|
29
|
+
appear in more than one container — which is the whole reason the L2 matrix exists.
|
|
30
|
+
|
|
31
|
+
A container with `built: false` — a database, a web server, anything whose implementation is
|
|
32
|
+
someone else's — appears at L2 and gets NO L3: there are no boxes inside it that anyone here
|
|
33
|
+
authored. What IS ours about it, its configuration and the invariant it enforces, belongs in an
|
|
34
|
+
AD-N or in cross-cutting.md. A C4 note MUST NOT be that fact's only home.
|
|
35
|
+
|
|
36
|
+
Together, L1 and L2 are what a normal project calls the HLD. ARCHITECTURE-SPINE.md is NOT that
|
|
37
|
+
— it constrains rather than describes. Deployment topology belongs to the devops repository and
|
|
38
|
+
is referenced from L2, never drawn here. -->
|
|
39
|
+
|
|
40
|
+
## Diagram
|
|
41
|
+
|
|
42
|
+
<!-- Author as valid mermaid. A diagram that does not render is worse than a table. -->
|
|
43
|
+
|
|
44
|
+
## Elements
|
|
45
|
+
|
|
46
|
+
<!-- One row per box, with what it is and why it exists. At L2 include the technology; at L1 do not
|
|
47
|
+
— L1 is for people who do not care. -->
|
|
48
|
+
|
|
49
|
+
| Element | What it is | Notes |
|
|
50
|
+
| --- | --- | --- |
|
|
51
|
+
|
|
52
|
+
## Relationships
|
|
53
|
+
|
|
54
|
+
<!-- One row per arrow: who talks to whom, about what, over what. -->
|
|
55
|
+
|
|
56
|
+
| From | To | Purpose | Over |
|
|
57
|
+
| --- | --- | --- | --- |
|
|
58
|
+
|
|
59
|
+
## Product Components per container
|
|
60
|
+
|
|
61
|
+
<!-- L2 ONLY, and MANDATORY there — complete at G3, with no exceptions and no dependence on `mode`.
|
|
62
|
+
|
|
63
|
+
One row per container with `built: true`, listing every PC that lives in it. This table is a
|
|
64
|
+
RENDERING of each PC's `containers:` in components.yaml; that registry is the SSOT and V25 fails
|
|
65
|
+
when the two disagree.
|
|
66
|
+
|
|
67
|
+
A `built: false` container is NOT a row here. Every PC's data lives in the database by
|
|
68
|
+
definition, so a column for it would say the same thing seven times, and the data inventory
|
|
69
|
+
already records which PC owns which table. -->
|
|
70
|
+
|
|
71
|
+
| Container | Product Components living in it |
|
|
72
|
+
| --- | --- |
|
|
73
|
+
|
|
74
|
+
## What is deliberately not shown
|
|
75
|
+
|
|
76
|
+
<!-- Cut clutter on purpose and say what you cut. A diagram that shows everything shows nothing, and
|
|
77
|
+
the next reader needs to know an omission was a choice. -->
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: contract
|
|
3
|
+
component: '{pc}'
|
|
4
|
+
lc: LC-{NNN} # the gateway this contract belongs to
|
|
5
|
+
direction: exposed # exposed (we serve it) · consumed (a third party serves it)
|
|
6
|
+
created: '{YYYY-MM-DD}'
|
|
7
|
+
updated: '{YYYY-MM-DD}'
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Contract — {name}
|
|
11
|
+
|
|
12
|
+
<!-- TEMPLATE GUIDE — act on these comments, then delete them.
|
|
13
|
+
|
|
14
|
+
Lives in .how/<pc>/02-contracts/ when we expose it, .how/<pc>/03-integrations/ when we consume
|
|
15
|
+
someone else's.
|
|
16
|
+
|
|
17
|
+
Where a machine-readable spec exists — OpenAPI, protobuf, a schema file — THAT is the source of
|
|
18
|
+
truth and this document MUST point at it rather than restate it. A restated schema drifts from
|
|
19
|
+
the generated one within a wave. Write here only what the machine spec cannot carry. -->
|
|
20
|
+
|
|
21
|
+
## Source of truth
|
|
22
|
+
|
|
23
|
+
<!-- Path or URL to the machine-readable spec, or `none` if this contract is prose-only. -->
|
|
24
|
+
|
|
25
|
+
## Purpose
|
|
26
|
+
|
|
27
|
+
<!-- Which UC this serves, and what the caller is trying to achieve. -->
|
|
28
|
+
|
|
29
|
+
## Operations
|
|
30
|
+
|
|
31
|
+
<!-- One row per operation. Keep it thin — detail belongs to the machine spec. -->
|
|
32
|
+
|
|
33
|
+
| Operation | Purpose | Realizes |
|
|
34
|
+
| --- | --- | --- |
|
|
35
|
+
|
|
36
|
+
## Error behaviour
|
|
37
|
+
|
|
38
|
+
<!-- What the caller sees when things go wrong, and which of those are expected rather than
|
|
39
|
+
exceptional. This is the part a generated spec carries worst and a caller needs most. -->
|
|
40
|
+
|
|
41
|
+
| Condition | Response | Caller should |
|
|
42
|
+
| --- | --- | --- |
|
|
43
|
+
|
|
44
|
+
## Compatibility
|
|
45
|
+
|
|
46
|
+
<!-- What counts as a breaking change here, and how it is announced. A contract with no stated
|
|
47
|
+
breaking-change policy will be broken by someone acting in good faith. -->
|
|
48
|
+
|
|
49
|
+
## Constraints
|
|
50
|
+
|
|
51
|
+
<!-- Rate limits, size limits, timeouts, idempotency, ordering guarantees. Anything the caller MUST
|
|
52
|
+
honour that the schema does not express. -->
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: cross-cutting
|
|
3
|
+
scope: _platform
|
|
4
|
+
status: draft # draft · reviewed · locked · superseded
|
|
5
|
+
created: '{YYYY-MM-DD}'
|
|
6
|
+
updated: '{YYYY-MM-DD}'
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Cross-Cutting — {product}
|
|
10
|
+
|
|
11
|
+
<!-- TEMPLATE GUIDE — act on these comments, then delete them.
|
|
12
|
+
|
|
13
|
+
Home: .how/_platform/cross-cutting.md. Blueprint output, born at G3 by wdi-blueprint intent
|
|
14
|
+
`platform`. It exists at every `mode`.
|
|
15
|
+
|
|
16
|
+
WHAT THIS FILE IS FOR: the things defined ONCE for the whole product and referenced everywhere
|
|
17
|
+
else. Without a fixed shape they grow into four error formats, each of which looked reasonable
|
|
18
|
+
on its own page — and that is not a hypothetical failure, it is the standard one.
|
|
19
|
+
|
|
20
|
+
WHAT IT IS NOT: a place for rules. A statement that FORBIDS something across components is an
|
|
21
|
+
AD-N and belongs in the spine. This file DESCRIBES what is shared. One fact, one home — a rule
|
|
22
|
+
written here as well as in the spine gives the reader two versions to choose between. -->
|
|
23
|
+
|
|
24
|
+
## Error envelope
|
|
25
|
+
|
|
26
|
+
<!-- The shape of an error response, defined once. Every contract in .how/<pc>/02-contracts/
|
|
27
|
+
REFERENCES this rather than restating it, and documents its 4xx and 5xx IN this envelope — never
|
|
28
|
+
as an ad-hoc { "message": "..." }.
|
|
29
|
+
|
|
30
|
+
Field names are English: they are machine-facing keys, and language-guide.md governs that. What
|
|
31
|
+
the user reads is not a field name. -->
|
|
32
|
+
|
|
33
|
+
```json
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
| Field | Type | Means | Always present |
|
|
37
|
+
| --- | --- | --- | --- |
|
|
38
|
+
|
|
39
|
+
## Error catalogue
|
|
40
|
+
|
|
41
|
+
<!-- The codes this envelope may carry, and what each means to the caller. A code with no row here is
|
|
42
|
+
a code nobody can handle. -->
|
|
43
|
+
|
|
44
|
+
| Code | HTTP | Means | Caller should |
|
|
45
|
+
| --- | --- | --- | --- |
|
|
46
|
+
|
|
47
|
+
## Milik platform
|
|
48
|
+
|
|
49
|
+
<!-- REQUIRED as soon as anything is owned by `_platform` — a `platform_owns` entity, an inventory row,
|
|
50
|
+
an LC. V21 checks it.
|
|
51
|
+
|
|
52
|
+
Something lands here only when NO Product Component's promise is the reason it exists AND more than
|
|
53
|
+
one component depends on it. corpus-guide.md owns that test, and it refuses the one use people
|
|
54
|
+
reach for: "the owner is hard to decide".
|
|
55
|
+
|
|
56
|
+
`Jenis` is data · endpoint · job · screen, and the list is open. What is not open is the test.
|
|
57
|
+
|
|
58
|
+
`_platform` has no `FR`, so there is no owner-FR for another component to point at. What replaces
|
|
59
|
+
"one writer" is ONE DOCUMENTED SHAPE — stated here, once. A component that wants it different is
|
|
60
|
+
proposing a change to this file, not making a local choice. -->
|
|
61
|
+
|
|
62
|
+
| Apa | Jenis | Kenapa tidak ada komponen yang menjelaskannya | Siapa yang menyentuhnya | Bentuk yang setiap penyentuh patuhi |
|
|
63
|
+
| --- | --- | --- | --- | --- |
|
|
64
|
+
|
|
65
|
+
<!-- `Siapa yang menyentuhnya` menyebut komponen, dan menyebut lebih dari satu adalah keadaan NORMAL —
|
|
66
|
+
itu separuh alasan barisnya ada di sini. Satu penyentuh adalah sinyal ia milik komponen itu. -->
|
|
67
|
+
|
|
68
|
+
## Other product-level agreements
|
|
69
|
+
|
|
70
|
+
<!-- One subsection each, only for what genuinely crosses components. Candidates that earn a place:
|
|
71
|
+
identity and session shape · timestamp and timezone convention · pagination shape ·
|
|
72
|
+
idempotency key convention · logging fields · rate-limit response shape.
|
|
73
|
+
|
|
74
|
+
Each MUST state where it is enforced. An agreement nothing enforces is a preference, and
|
|
75
|
+
preferences belong in codebase/conventions-guide.md where nothing has to justify itself. -->
|
|
76
|
+
|
|
77
|
+
### {agreement}
|
|
78
|
+
|
|
79
|
+
**Applies to:** {which components or containers — `all` is a valid answer and MUST be written}
|
|
80
|
+
**Enforced by:** {a middleware, a shared helper, a test name — not "convention"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: decision
|
|
3
|
+
id: DEC-{NNN} # allocated from .control/registry/decisions.yaml, globally
|
|
4
|
+
status: draft # draft · accepted · applied · superseded · rejected
|
|
5
|
+
touches: [] # empty until applied; then the files this decision actually changed
|
|
6
|
+
supersedes: null
|
|
7
|
+
superseded_by: null
|
|
8
|
+
created: '{YYYY-MM-DD}'
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# DEC-{NNN} — {the decision, stated as what now holds}
|
|
12
|
+
|
|
13
|
+
<!-- TEMPLATE GUIDE — act on these comments, then delete them.
|
|
14
|
+
|
|
15
|
+
Three sections are required: Decision, Why, Cost. The three below them are required only when
|
|
16
|
+
this decision reaches a Product Component whose `risk_accepted` is `low`. Anywhere else, drop
|
|
17
|
+
the ones you have nothing to put under — a heading with nothing beneath it reads as an omission.
|
|
18
|
+
|
|
19
|
+
A `DEC-` records ONE event. It freezes when its status reaches `applied`, not when it is
|
|
20
|
+
accepted. A changed mind after that produces a new `DEC-`, and this one becomes `superseded`
|
|
21
|
+
with a pointer forward.
|
|
22
|
+
|
|
23
|
+
Do not confuse this with AD-N in the architecture spine, which is a living rule edited in place.
|
|
24
|
+
|
|
25
|
+
Add `type:` to the frontmatter when it is useful — `risk-acceptance`, `course-correction`. -->
|
|
26
|
+
|
|
27
|
+
## Decision
|
|
28
|
+
|
|
29
|
+
<!-- One sentence, present tense, quotable into a rule. Not "we will". -->
|
|
30
|
+
|
|
31
|
+
## Why
|
|
32
|
+
|
|
33
|
+
<!-- The context that forced it. A few lines, written so a reader in a year needs no other document.
|
|
34
|
+
The memlog is where the reasoning lives, and the memlog MUST NOT be quoted into the corpus.
|
|
35
|
+
If this came out of a third failed fix attempt, say so — that is the signal
|
|
36
|
+
wdi-systematic-debugging exists to raise. -->
|
|
37
|
+
|
|
38
|
+
## Cost
|
|
39
|
+
|
|
40
|
+
<!-- What becomes harder. A decision with only benefits was not thought through. -->
|
|
41
|
+
|
|
42
|
+
## Alternatives
|
|
43
|
+
|
|
44
|
+
<!-- Required only at `risk_accepted: low`. What else was considered, and why each lost.
|
|
45
|
+
"We considered X" with no reason is not an alternative. -->
|
|
46
|
+
|
|
47
|
+
| Option | Why not |
|
|
48
|
+
| --- | --- |
|
|
49
|
+
|
|
50
|
+
## Reversal trigger
|
|
51
|
+
|
|
52
|
+
<!-- Required only at `risk_accepted: low`. The observable condition that makes revisiting this
|
|
53
|
+
correct. A decision with no reversal condition is a belief. -->
|
|
54
|
+
|
|
55
|
+
## Trace
|
|
56
|
+
|
|
57
|
+
<!-- Required only at `risk_accepted: low`. Where this came from. What it landed in belongs in
|
|
58
|
+
`touches:` above, not here — one fact, one home. -->
|
|
59
|
+
|
|
60
|
+
| | |
|
|
61
|
+
| --- | --- |
|
|
62
|
+
| Meeting note | `.control/meetings/{YYYY-MM-DD-slug}.md` — or `—` |
|
|
63
|
+
| Open question | `OQ-{n}` — or `—` |
|
|
64
|
+
| Source material | path, or `—` |
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: design-system
|
|
3
|
+
scope: _platform
|
|
4
|
+
status: draft # draft · reviewed · locked · superseded
|
|
5
|
+
created: '{YYYY-MM-DD}'
|
|
6
|
+
updated: '{YYYY-MM-DD}'
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Design System — {product}
|
|
10
|
+
|
|
11
|
+
<!-- TEMPLATE GUIDE — act on these comments, then delete them.
|
|
12
|
+
|
|
13
|
+
Home: .how/_platform/design-system.md. Written by wdi-ux, and it is the ONE file in _platform/
|
|
14
|
+
that wdi-blueprint does not own. Optional, like the rest of UX: it exists when the interface is
|
|
15
|
+
a substantial part of what the PRD promises.
|
|
16
|
+
|
|
17
|
+
WHY IT IS NOT IN A COMPONENT: tokens and base elements cross Product Components by definition. A
|
|
18
|
+
colour scale living in one component's 01-ux/ is a colour scale the other six will each redefine.
|
|
19
|
+
|
|
20
|
+
WHY ux.md DOES NOT SERVE IT: ux.md is the shape of DESIGN.md and EXPERIENCE.md, which are per
|
|
21
|
+
component. This is the third file, at product level, and it had no template at all.
|
|
22
|
+
|
|
23
|
+
THE CODE IS THE SSOT FOR VALUES. Where this repo's web side states a token in tokens.css, this
|
|
24
|
+
file MUST reference it rather than repeat the value. Two homes for one hex code is two hex codes
|
|
25
|
+
within a month. Read web/README.md before writing anything here — it is the authority for the
|
|
26
|
+
web side, and it MUST NOT be contradicted from this file.
|
|
27
|
+
|
|
28
|
+
Token and element NAMES are English: they are machine-facing keys, per language-guide.md. -->
|
|
29
|
+
|
|
30
|
+
## Where the values actually live
|
|
31
|
+
|
|
32
|
+
<!-- One line per source of truth — the stylesheet, the config, the generated file — with its path.
|
|
33
|
+
This section is what stops the rest of the document becoming a stale copy. -->
|
|
34
|
+
|
|
35
|
+
## Tokens
|
|
36
|
+
|
|
37
|
+
<!-- One table per scale. Name, what it is for, and where it resolves. NOT the raw value, unless this
|
|
38
|
+
file is genuinely the only place it exists. -->
|
|
39
|
+
|
|
40
|
+
| Token | For | Resolves in |
|
|
41
|
+
| --- | --- | --- |
|
|
42
|
+
|
|
43
|
+
## Base elements
|
|
44
|
+
|
|
45
|
+
<!-- The LC type `ui-element`, registered in components.yaml. One row each: what it is, its states,
|
|
46
|
+
and where its implementation lives. A composite reused across screens is `ui-composite` and
|
|
47
|
+
belongs in .how/<pc>/01-ux/, not here. -->
|
|
48
|
+
|
|
49
|
+
| Element | States it MUST support | Implementation |
|
|
50
|
+
| --- | --- | --- |
|
|
51
|
+
|
|
52
|
+
<!-- Every element MUST state its empty, loading, error, and disabled states where they apply. The
|
|
53
|
+
populated state is the one that always gets designed; the others are the ones that ship broken. -->
|
|
54
|
+
|
|
55
|
+
## Rules that bind every screen
|
|
56
|
+
|
|
57
|
+
<!-- Only what a screen cannot legitimately override. Each MUST state what it prevents — a rule with
|
|
58
|
+
no failure behind it is a preference, and preferences go to codebase/conventions-guide.md.
|
|
59
|
+
|
|
60
|
+
A rule here that also holds for non-UI code is an AD-N and belongs in the spine instead. -->
|
|
61
|
+
|
|
62
|
+
| Rule | Prevents |
|
|
63
|
+
| --- | --- |
|
|
64
|
+
|
|
65
|
+
## What this system deliberately does not cover
|
|
66
|
+
|
|
67
|
+
<!-- Where a component is free to choose for itself. Absent, every local choice reads as a violation. -->
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: flow
|
|
3
|
+
component: '{pc}'
|
|
4
|
+
realizes: [] # UC ids this flow implements
|
|
5
|
+
risky: false # true when money, irreversible state, or a third party is involved
|
|
6
|
+
created: '{YYYY-MM-DD}'
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Flow — {name}
|
|
10
|
+
|
|
11
|
+
<!-- TEMPLATE GUIDE — act on these comments, then delete them.
|
|
12
|
+
|
|
13
|
+
Lives in .how/<pc>/06-flows/. This is the TECHNICAL path — components calling components. The
|
|
14
|
+
behavioural path the user experiences belongs to the UC in .what/<pc>/04-usecases/, and the two
|
|
15
|
+
MUST NOT be merged: one is reviewed by the Product Owner, the other is not.
|
|
16
|
+
|
|
17
|
+
A sequence diagram is written ONLY when `risky: true`. Drawing one for every flow costs more
|
|
18
|
+
than it returns and buries the ones that matter. -->
|
|
19
|
+
|
|
20
|
+
## Realizes
|
|
21
|
+
|
|
22
|
+
<!-- The UC ids, and one line on which part of them this covers. -->
|
|
23
|
+
|
|
24
|
+
## Participants
|
|
25
|
+
|
|
26
|
+
<!-- The LC ids involved, in the order they enter. -->
|
|
27
|
+
|
|
28
|
+
## Happy path
|
|
29
|
+
|
|
30
|
+
<!-- Numbered, one hop per line: who calls whom, carrying what. -->
|
|
31
|
+
|
|
32
|
+
1.
|
|
33
|
+
|
|
34
|
+
## Sequence diagram
|
|
35
|
+
|
|
36
|
+
<!-- ONLY when risky: true. Author as valid mermaid — never an empty graph. Cut this section
|
|
37
|
+
entirely otherwise. -->
|
|
38
|
+
|
|
39
|
+
## Failure modes
|
|
40
|
+
|
|
41
|
+
<!-- Per hop: what failure looks like, what the system does, and whether the operation can be
|
|
42
|
+
retried safely. The retry column is the one that gets skipped and the one that causes double
|
|
43
|
+
charges. -->
|
|
44
|
+
|
|
45
|
+
| Hop | Failure | System does | Safe to retry |
|
|
46
|
+
| --- | --- | --- | --- |
|
|
47
|
+
|
|
48
|
+
## Guarantees
|
|
49
|
+
|
|
50
|
+
<!-- Idempotency, ordering, at-least-once versus exactly-once, timeout budget. State what actually
|
|
51
|
+
holds, not what would be nice. -->
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: integration
|
|
3
|
+
component: '{pc}'
|
|
4
|
+
status: draft # draft · reviewed · locked · superseded
|
|
5
|
+
created: '{YYYY-MM-DD}'
|
|
6
|
+
updated: '{YYYY-MM-DD}'
|
|
7
|
+
provider: '{who owns it outside the team}'
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Integration — {third-party name}
|
|
11
|
+
|
|
12
|
+
<!-- TEMPLATE GUIDE — act on these comments, then delete them.
|
|
13
|
+
|
|
14
|
+
Home: .how/<pc>/03-integrations/<name>.md. Written at G4, from mode: guarded up, and only when
|
|
15
|
+
the component actually consumes a third party.
|
|
16
|
+
|
|
17
|
+
WHY THIS IS NOT contract.md: contract.md is the shape of an endpoint WE publish, and we can
|
|
18
|
+
change it. This is something SOMEBODY ELSE owns. Two things have no column in contract.md and
|
|
19
|
+
are the whole reason this template exists — who owns it outside the team, and what happens when
|
|
20
|
+
they change it without telling anyone.
|
|
21
|
+
|
|
22
|
+
COMMERCIAL FACTS MUST NOT APPEAR HERE. A rate limit that exists because of what was negotiated
|
|
23
|
+
is written as the technical fact — "300 requests per minute" — and never as the negotiation.
|
|
24
|
+
repo-guide.md owns that boundary, and this file is the most common place it leaks. -->
|
|
25
|
+
|
|
26
|
+
## Who owns it
|
|
27
|
+
|
|
28
|
+
| | |
|
|
29
|
+
| --- | --- |
|
|
30
|
+
| Provider | {the organisation} |
|
|
31
|
+
| Our contact | {a role, and where the person's name is recorded — not the name} |
|
|
32
|
+
| Where credentials live | {the devops repo and path. NEVER the credential} |
|
|
33
|
+
| Notice we get before a breaking change | {a period, or `none` — and `none` is the answer that changes the design} |
|
|
34
|
+
|
|
35
|
+
## What we use it for
|
|
36
|
+
|
|
37
|
+
<!-- Which FR or UC depends on it, by id. An integration no promise depends on is one we are
|
|
38
|
+
carrying for free. -->
|
|
39
|
+
|
|
40
|
+
## What we send and receive
|
|
41
|
+
|
|
42
|
+
<!-- Only the surface we actually touch. A full API description belongs to their documentation, cited
|
|
43
|
+
by URL, and copying it here creates a second version that goes stale silently. -->
|
|
44
|
+
|
|
45
|
+
| Direction | Operation | Carries | Contains personal data |
|
|
46
|
+
| --- | --- | --- | --- |
|
|
47
|
+
|
|
48
|
+
## When it changes without telling us
|
|
49
|
+
|
|
50
|
+
<!-- The section that earns this file. For each: how we would notice, how long we would run wrong
|
|
51
|
+
before noticing, and what happens meanwhile. "We would see errors" is not an answer unless
|
|
52
|
+
something is actually watching. -->
|
|
53
|
+
|
|
54
|
+
| Change | How we notice | Blast radius | What we do |
|
|
55
|
+
| --- | --- | --- | --- |
|
|
56
|
+
|
|
57
|
+
## When it is slow, absent, or lying
|
|
58
|
+
|
|
59
|
+
<!-- The same three failures the SDD's Failure Behaviour asks about, for this boundary. State the
|
|
60
|
+
timeout, the retry policy, what the user sees, and what gets logged. A retry policy with no cap
|
|
61
|
+
is an outage amplifier. -->
|
|
62
|
+
|
|
63
|
+
| Failure | Timeout | Retry | What the user sees | What is logged |
|
|
64
|
+
| --- | --- | --- | --- | --- |
|
|
65
|
+
|
|
66
|
+
## What we would do without them
|
|
67
|
+
|
|
68
|
+
<!-- One paragraph. Not a migration plan — the honest answer, which is sometimes "the feature stops".
|
|
69
|
+
Writing it is what makes the dependency visible before it has to be replaced in a hurry. -->
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: inventory
|
|
3
|
+
kind: db # db · api · screen · endpoint — decides the row shape below
|
|
4
|
+
scope: _platform # `_platform` for the three product-level inventories; `{pc}` for kind: endpoint
|
|
5
|
+
status: draft # draft · reviewed · locked · superseded
|
|
6
|
+
created: '{YYYY-MM-DD}'
|
|
7
|
+
updated: '{YYYY-MM-DD}'
|
|
8
|
+
derived_from: plan # plan · code — see the TEMPLATE GUIDE
|
|
9
|
+
verified: '' # commit SHA the derivation was read at; required when derived_from: code
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Inventory — {tables | endpoints | screens | endpoints of {pc}}
|
|
13
|
+
|
|
14
|
+
<!-- TEMPLATE GUIDE — act on these comments, then delete them.
|
|
15
|
+
|
|
16
|
+
ONE template, four kinds. Only the row shape differs; the rules are the same for all four.
|
|
17
|
+
|
|
18
|
+
kind: db -> .how/_platform/inventory-db.md
|
|
19
|
+
kind: api -> .how/_platform/inventory-api.md
|
|
20
|
+
kind: screen -> .how/_platform/inventory-screen.md
|
|
21
|
+
kind: endpoint-> .how/<pc>/02-contracts/00-inventory.md, at mode: deep only
|
|
22
|
+
|
|
23
|
+
The first three are BLUEPRINT output, born at G3 by wdi-blueprint intent `platform`. They exist
|
|
24
|
+
at every `mode`, including catalog, and they are what makes catalog usable at all: the use case
|
|
25
|
+
list plus these three plus C4 is the whole record a builder gets there.
|
|
26
|
+
|
|
27
|
+
THE NUMBER IS STABLE. A new row takes the next `No`, never a renumber. Renumbering renames every
|
|
28
|
+
file after it and breaks every link pointing at them. A removed row keeps its number and its
|
|
29
|
+
status becomes `removed`; the number MUST NOT be reused.
|
|
30
|
+
|
|
31
|
+
TWO WAYS THIS FILE COMES TO EXIST, and derived_from says which:
|
|
32
|
+
plan no code yet. Written as intent — the tables, endpoints, or screens planned. Nothing can
|
|
33
|
+
be derived, because there is no source.
|
|
34
|
+
code code exists. Derived by .constitution/scripts/inventory.py — migrations for tables,
|
|
35
|
+
route registration for endpoints, pages for screens — and THEN compared with the plan.
|
|
36
|
+
The difference is a FINDING, reported. It MUST NOT be patched into agreement by hand.
|
|
37
|
+
|
|
38
|
+
MUST NOT be assembled from a README, from a route name that looks plausible, or from memory. -->
|
|
39
|
+
|
|
40
|
+
## Rows
|
|
41
|
+
|
|
42
|
+
<!-- kind: db -->
|
|
43
|
+
|
|
44
|
+
| No | Table | Owning component | What it holds | Key columns | Status |
|
|
45
|
+
| --- | --- | --- | --- | --- | --- |
|
|
46
|
+
|
|
47
|
+
<!-- kind: api — keep this block and delete the others
|
|
48
|
+
| No | Method | Path | Owning component | Description | Status |
|
|
49
|
+
| --- | --- | --- | --- | --- | --- |
|
|
50
|
+
-->
|
|
51
|
+
|
|
52
|
+
<!-- kind: screen
|
|
53
|
+
| No | Screen | Route | Owning component | Actor | UC served |
|
|
54
|
+
| --- | --- | --- | --- | --- | --- |
|
|
55
|
+
-->
|
|
56
|
+
|
|
57
|
+
<!-- kind: endpoint
|
|
58
|
+
| No | Method | Path | Spec file | Status |
|
|
59
|
+
| --- | --- | --- | --- | --- |
|
|
60
|
+
-->
|
|
61
|
+
|
|
62
|
+
<!-- Status values: draft · published · deprecated · removed. A row with no status reads as
|
|
63
|
+
published, which is the one reading that is never safe. -->
|
|
64
|
+
|
|
65
|
+
## Findings
|
|
66
|
+
|
|
67
|
+
<!-- Only when derived_from: code. Each difference between the plan and what the code actually does,
|
|
68
|
+
one line each, with which side is being reported — not which side was changed. Nothing here is
|
|
69
|
+
resolved by editing the other side; a finding routes to the skill that owns it. -->
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: lc
|
|
3
|
+
id: LC-{NNN} # allocated from .control/registry/components.yaml
|
|
4
|
+
name: '{name}'
|
|
5
|
+
lc_type: service # ui-screen · ui-composite · ui-element · gateway · service · job · store
|
|
6
|
+
container: '{container}' # the runnable/deployable unit it lives in
|
|
7
|
+
component: '{pc}' # the Product Component it belongs to
|
|
8
|
+
owner: '{team or person}'
|
|
9
|
+
area: '{area}'
|
|
10
|
+
created: '{YYYY-MM-DD}'
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# LC-{NNN} — {name}
|
|
14
|
+
|
|
15
|
+
<!-- TEMPLATE GUIDE — act on these comments, then delete them.
|
|
16
|
+
|
|
17
|
+
A Logical Component is ONE addressable unit of build. It is not a Product Component: a PC is a
|
|
18
|
+
domain slice and the box at C4 L3; an LC is something you can point at and change.
|
|
19
|
+
|
|
20
|
+
`lc_type` decides where this prose lives, and the mapping is not negotiable:
|
|
21
|
+
ui-screen · ui-composite → .how/<pc>/01-ux/
|
|
22
|
+
ui-element → .how/_platform/design-system.md
|
|
23
|
+
gateway → .how/<pc>/02-contracts/ or 03-integrations/
|
|
24
|
+
service · job → .how/<pc>/04-components/
|
|
25
|
+
store → .how/<pc>/05-model/
|
|
26
|
+
|
|
27
|
+
An LC MUST be registered by the time its wave CLOSES — V12 checks that
|
|
28
|
+
every `touches` entry resolves. -->
|
|
29
|
+
|
|
30
|
+
## Responsibility
|
|
31
|
+
|
|
32
|
+
<!-- One paragraph. What this unit is answerable for. If it needs "and" more than once, it is
|
|
33
|
+
probably two units. -->
|
|
34
|
+
|
|
35
|
+
## Depends on
|
|
36
|
+
|
|
37
|
+
<!-- Other LC ids, and the direction. Dependency direction is a rule carried by the spine, not a
|
|
38
|
+
preference — a dependency pointing the wrong way is a conflict to surface, not to document. -->
|
|
39
|
+
|
|
40
|
+
## Interface
|
|
41
|
+
|
|
42
|
+
<!-- What it exposes to the rest of the system. For a gateway this points at the contract in
|
|
43
|
+
02-contracts/ rather than restating it. -->
|
|
44
|
+
|
|
45
|
+
## Notes
|
|
46
|
+
|
|
47
|
+
<!-- Anything a builder cannot read off the code. Cut if there is nothing. -->
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: lifecycle
|
|
3
|
+
component: '{pc}'
|
|
4
|
+
status: draft # draft · reviewed · locked · superseded
|
|
5
|
+
created: '{YYYY-MM-DD}'
|
|
6
|
+
updated: '{YYYY-MM-DD}'
|
|
7
|
+
entities: [] # the domain entities whose lifecycles this file carries
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# State Lifecycle — {Product Component}
|
|
11
|
+
|
|
12
|
+
<!-- TEMPLATE GUIDE — act on these comments, then delete them.
|
|
13
|
+
|
|
14
|
+
Home: .what/<pc>/03-domain/state-machines.md. Written at G4, at mode: deep ONLY. Below deep it
|
|
15
|
+
MUST NOT be written to fill a slot.
|
|
16
|
+
|
|
17
|
+
One section per entity that has more than one state. An entity with a single state has no
|
|
18
|
+
lifecycle and MUST NOT get a section.
|
|
19
|
+
|
|
20
|
+
WHY THIS HAS ITS OWN TEMPLATE: a transition table does not resemble an ERD, so it cannot be
|
|
21
|
+
lodged inside model.md. What it needs stated — who may move a thing, and what makes a state
|
|
22
|
+
terminal — has no column in an entity diagram.
|
|
23
|
+
|
|
24
|
+
THIS IS BEHAVIOUR, NOT SCHEMA. The state VALUES are English, because they are enum values and
|
|
25
|
+
language-guide.md governs that. Their LABELS — what a user reads — are not written here; they
|
|
26
|
+
belong to the screen. A value rendered straight to the screen is the known pitfall this repo
|
|
27
|
+
already records.
|
|
28
|
+
|
|
29
|
+
G3 asks whether there is a state that can be entered but not left. This file is where that is
|
|
30
|
+
answered, and an unreachable or inescapable state is a FINDING, not a documented fact. -->
|
|
31
|
+
|
|
32
|
+
## {Entity}
|
|
33
|
+
|
|
34
|
+
**States:** `{value}` · `{value}` · `{value}`
|
|
35
|
+
**Initial:** `{value}` — and what creates it
|
|
36
|
+
**Terminal:** `{value}` · `{value}` — and why nothing leaves them
|
|
37
|
+
|
|
38
|
+
| From | To | Trigger | Who may | Guard | Side effect |
|
|
39
|
+
| --- | --- | --- | --- | --- | --- |
|
|
40
|
+
|
|
41
|
+
<!-- `Who may` names an actor from the SRS Actor Register, or `System` for an automatic transition.
|
|
42
|
+
`Guard` is the business rule that has to hold — cite the BR- id rather than restating it.
|
|
43
|
+
`Side effect` is what else changes; a transition with an invisible side effect is the one that
|
|
44
|
+
surprises someone while the code is being written.
|
|
45
|
+
|
|
46
|
+
Every state in the list above MUST appear at least once as a `To`, except the initial one, and
|
|
47
|
+
at least once as a `From`, except a terminal one. That is the check, and it is mechanical. -->
|
|
48
|
+
|
|
49
|
+
### What is deliberately not modelled
|
|
50
|
+
|
|
51
|
+
<!-- A state someone will look for and not find, and why. A schema value nothing uses — say so:
|
|
52
|
+
until the schema is cleaned, it has no label, no transition, and no meaning. -->
|