wdi-method 0.6.30 → 0.6.31
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/CHANGELOG.md +68 -0
- package/README.md +3 -0
- package/bin/wdi-method.js +121 -14
- package/kit/.constitution/method/document/architecture-guide.md +217 -209
- package/kit/.constitution/method/document/corpus-guide.md +522 -517
- package/kit/.constitution/method/document/decision-guide.md +236 -216
- package/kit/.constitution/method/document/delivery-flow-guide.md +20 -0
- package/kit/.constitution/method/document/prd-guide.md +245 -245
- package/kit/.constitution/method/document/templates/design-system.md +96 -66
- package/kit/.constitution/method/document/templates/experience.md +62 -0
- package/kit/.constitution/method/document/templates/structure-codebase.md +131 -129
- package/kit/.constitution/method/document/templates/ux.md +78 -76
- package/kit/.constitution/method/document/ux-guide.md +161 -115
- package/kit/.constitution/method/method-glossary.md +3 -0
- package/kit/.constitution/method/scripts/validate.py +3310 -3200
- package/kit/.constitution/method/structure-guide.md +204 -202
- package/kit/.constitution/method/why/artifact-map.md +158 -157
- package/kit/skills/wdi-blueprint/SKILL.md +271 -264
- package/kit/skills/wdi-component/SKILL.md +179 -174
- package/kit/skills/wdi-decision/SKILL.md +206 -203
- package/kit/skills/wdi-help/SKILL.md +127 -125
- package/kit/skills/wdi-init/SKILL.md +9 -4
- package/kit/skills/wdi-problem/SKILL.md +114 -108
- package/kit/skills/wdi-product/SKILL.md +167 -162
- package/kit/skills/wdi-reconcile/SKILL.md +170 -169
- package/kit/skills/wdi-upgrade/SKILL.md +234 -215
- package/kit/skills/wdi-ux/SKILL.md +187 -169
- package/kit-overlay/AGENTS.md +3 -1
- package/package.json +1 -1
- package/scaffold/.control/registry/index.yaml +2 -1
|
@@ -1,202 +1,204 @@
|
|
|
1
|
-
---
|
|
2
|
-
status: Accepted
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# Structure Guide
|
|
6
|
-
|
|
7
|
-
**Loaded when:** writing, reading, or refreshing a structure map — `.control/structure-codebase.md`
|
|
8
|
-
or `.control/structure-document.md`.
|
|
9
|
-
|
|
10
|
-
## Two maps
|
|
11
|
-
|
|
12
|
-
| Map | Describes | Derived | Refreshed by |
|
|
13
|
-
|---|---|---|---|
|
|
14
|
-
| `.control/structure-codebase.md` | The code tree: what runs, what it is built from, where new code goes | `wdi-init` intent `structure` | `wdi-init` intent `structure` |
|
|
15
|
-
| `.control/structure-document.md` | The corpus tree: which layers and slots actually carry content today | `wdi-init` intent `structure` | `wdi-init` intent `structure` |
|
|
16
|
-
|
|
17
|
-
Both ship as empty skeletons, so the slot is taken from day one. The first run replaces a skeleton
|
|
18
|
-
**wholesale** rather than filling it in; a half-derived map that still carries skeleton headings
|
|
19
|
-
cannot be told apart from a stale one. The intent MAY be run read-only — derive, report the drift,
|
|
20
|
-
write nothing — and that is the right mode when the caller is unsure.
|
|
21
|
-
|
|
22
|
-
**The maps live in `.control/`, this guide lives here, and the split is deliberate.** A guide states
|
|
23
|
-
a rule that holds before the thing exists; a map states what is currently true. That is the same
|
|
24
|
-
line the kit already draws between `decision-guide.md` and `.control/decisions/`, and between
|
|
25
|
-
`corpus-guide.md` and `.control/registry/`. The two MUST NOT be merged, and a map MUST NOT be moved
|
|
26
|
-
into `.constitution/` because it happens to be read alongside these guides.
|
|
27
|
-
|
|
28
|
-
Consequence worth knowing: `.control/` is `{project_knowledge}`, so both maps are visible to the
|
|
29
|
-
BMad skills that read it. That is intended — a builder that knows where code goes is the point.
|
|
30
|
-
|
|
31
|
-
## Descriptive, not prescriptive — the line that MUST hold
|
|
32
|
-
|
|
33
|
-
This is the whole reason the maps can exist without colliding with the guides already in
|
|
34
|
-
`.constitution/`.
|
|
35
|
-
|
|
36
|
-
| Question | Answered by |
|
|
37
|
-
|---|---|
|
|
38
|
-
| Where does this live, and what is already there? | **structure map** |
|
|
39
|
-
| Which layer owns it, and what is it named? | `document/corpus-guide.md` |
|
|
40
|
-
| How is code named, and which patterns apply? | `../project/codebase-conventions-guide.md` |
|
|
41
|
-
| What is it built with, and on which version? | `../project/codebase-stack-guide.md` |
|
|
42
|
-
| Which legacy shapes are ratified rather than fixed? | `../project/codebase-brownfield-guide.md` |
|
|
43
|
-
|
|
44
|
-
- A structure map MUST NOT restate a naming rule, a layer rule, or a version. It MUST reference the
|
|
45
|
-
guide that owns it.
|
|
46
|
-
- A guide MUST NOT carry a directory tree. A tree in a guide goes stale silently, because nothing
|
|
47
|
-
refreshes it.
|
|
48
|
-
- Where a map and a guide disagree, the **guide** wins on the rule and the **map** wins on the fact.
|
|
49
|
-
The disagreement itself MUST be reported, not smoothed over — one of the two is lying.
|
|
50
|
-
|
|
51
|
-
## What a map MUST contain
|
|
52
|
-
|
|
53
|
-
1. A **Verified** line: date plus the commit the tree was read at.
|
|
54
|
-
2. A **top-level tree**: every base folder in the root, complete, one annotated line each.
|
|
55
|
-
3. A **section per unit**, each carrying its folder convention as an annotated tree.
|
|
56
|
-
4. **Key files marked `★` inline**, inside those trees.
|
|
57
|
-
|
|
58
|
-
Nothing else. A map that also explains how the system works has become an architecture document,
|
|
59
|
-
and `.how/` already owns that.
|
|
60
|
-
|
|
61
|
-
The form is an **annotated tree**, not prose and not a file table. A tree shows convention and
|
|
62
|
-
location in the same glance, and a `★` next to a filename is read at the moment it matters. Both
|
|
63
|
-
maps MUST close with the one-line legend for `★`.
|
|
64
|
-
|
|
65
|
-
## How units are split
|
|
66
|
-
|
|
67
|
-
Each map splits its sections along the axis its reader is lost on, and the two axes differ:
|
|
68
|
-
|
|
69
|
-
| Map | Sections | Split by |
|
|
70
|
-
|---|---|---|
|
|
71
|
-
| `structure-codebase.md` | Containers · Libraries · the non-unit sections below | **Deployability** |
|
|
72
|
-
| `structure-document.md` | One per layer that carries content | **Layer** |
|
|
73
|
-
|
|
74
|
-
For the codebase map the distinction is exact and MUST NOT be softened:
|
|
75
|
-
|
|
76
|
-
- A **container** runs its own code or stores its own data, and can be replaced without rebuilding
|
|
77
|
-
another one. `architecture-guide.md` owns the two-question test; this map only applies it. The term
|
|
78
|
-
MUST NOT be renamed to "application", "service", or "app" here — a synonym for a term that already
|
|
79
|
-
has a glossary entry is drift, and `wdi-reconcile` hunts for it. It does not mean a Docker image.
|
|
80
|
-
- A **library** is an includable artifact — compiled into or imported by something else, never run
|
|
81
|
-
on its own. A library with an entry point is a container wearing the wrong label, and a library
|
|
82
|
-
MUST NOT appear at C4 L2.
|
|
83
|
-
- Anything that is neither is not a unit. It stays a line in the top-level tree, or in one of the
|
|
84
|
-
non-unit sections below.
|
|
85
|
-
- A unit that stops being separately deployable MUST move sections, not keep its old heading.
|
|
86
|
-
|
|
87
|
-
### The registry match is one-directional
|
|
88
|
-
|
|
89
|
-
**Every container heading MUST be a container registered in `components.yaml`. Not every registered
|
|
90
|
-
container gets a heading.** Reading it both ways makes the rule unsatisfiable: a `built: false` container
|
|
91
|
-
— a database, a web server — MUST be registered, because it runs inside the boundary and carries NFRs,
|
|
92
|
-
and MUST NOT get a heading, because no code of ours lives there. So the check is **heading = exactly the
|
|
93
|
-
`built: true` containers
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
|
103
|
-
|
|
104
|
-
| **
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
- MUST
|
|
114
|
-
|
|
115
|
-
- MUST
|
|
116
|
-
|
|
117
|
-
- MUST
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
-
|
|
126
|
-
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
-
|
|
138
|
-
|
|
139
|
-
-
|
|
140
|
-
|
|
141
|
-
-
|
|
142
|
-
a
|
|
143
|
-
- A map
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
-
|
|
149
|
-
|
|
150
|
-
-
|
|
151
|
-
|
|
152
|
-
- Each
|
|
153
|
-
|
|
154
|
-
- Each container
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
- MUST
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
- MUST
|
|
172
|
-
|
|
173
|
-
- Product Component
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
|
185
|
-
|
|
186
|
-
|
|
|
187
|
-
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
1
|
+
---
|
|
2
|
+
status: Accepted
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Structure Guide
|
|
6
|
+
|
|
7
|
+
**Loaded when:** writing, reading, or refreshing a structure map — `.control/structure-codebase.md`
|
|
8
|
+
or `.control/structure-document.md`.
|
|
9
|
+
|
|
10
|
+
## Two maps
|
|
11
|
+
|
|
12
|
+
| Map | Describes | Derived | Refreshed by |
|
|
13
|
+
|---|---|---|---|
|
|
14
|
+
| `.control/structure-codebase.md` | The code tree: what runs, what it is built from, where new code goes | `wdi-init` intent `structure` | `wdi-init` intent `structure` |
|
|
15
|
+
| `.control/structure-document.md` | The corpus tree: which layers and slots actually carry content today | `wdi-init` intent `structure` | `wdi-init` intent `structure` |
|
|
16
|
+
|
|
17
|
+
Both ship as empty skeletons, so the slot is taken from day one. The first run replaces a skeleton
|
|
18
|
+
**wholesale** rather than filling it in; a half-derived map that still carries skeleton headings
|
|
19
|
+
cannot be told apart from a stale one. The intent MAY be run read-only — derive, report the drift,
|
|
20
|
+
write nothing — and that is the right mode when the caller is unsure.
|
|
21
|
+
|
|
22
|
+
**The maps live in `.control/`, this guide lives here, and the split is deliberate.** A guide states
|
|
23
|
+
a rule that holds before the thing exists; a map states what is currently true. That is the same
|
|
24
|
+
line the kit already draws between `decision-guide.md` and `.control/decisions/`, and between
|
|
25
|
+
`corpus-guide.md` and `.control/registry/`. The two MUST NOT be merged, and a map MUST NOT be moved
|
|
26
|
+
into `.constitution/` because it happens to be read alongside these guides.
|
|
27
|
+
|
|
28
|
+
Consequence worth knowing: `.control/` is `{project_knowledge}`, so both maps are visible to the
|
|
29
|
+
BMad skills that read it. That is intended — a builder that knows where code goes is the point.
|
|
30
|
+
|
|
31
|
+
## Descriptive, not prescriptive — the line that MUST hold
|
|
32
|
+
|
|
33
|
+
This is the whole reason the maps can exist without colliding with the guides already in
|
|
34
|
+
`.constitution/`.
|
|
35
|
+
|
|
36
|
+
| Question | Answered by |
|
|
37
|
+
|---|---|
|
|
38
|
+
| Where does this live, and what is already there? | **structure map** |
|
|
39
|
+
| Which layer owns it, and what is it named? | `document/corpus-guide.md` |
|
|
40
|
+
| How is code named, and which patterns apply? | `../project/codebase-conventions-guide.md` |
|
|
41
|
+
| What is it built with, and on which version? | `../project/codebase-stack-guide.md` |
|
|
42
|
+
| Which legacy shapes are ratified rather than fixed? | `../project/codebase-brownfield-guide.md` |
|
|
43
|
+
|
|
44
|
+
- A structure map MUST NOT restate a naming rule, a layer rule, or a version. It MUST reference the
|
|
45
|
+
guide that owns it.
|
|
46
|
+
- A guide MUST NOT carry a directory tree. A tree in a guide goes stale silently, because nothing
|
|
47
|
+
refreshes it.
|
|
48
|
+
- Where a map and a guide disagree, the **guide** wins on the rule and the **map** wins on the fact.
|
|
49
|
+
The disagreement itself MUST be reported, not smoothed over — one of the two is lying.
|
|
50
|
+
|
|
51
|
+
## What a map MUST contain
|
|
52
|
+
|
|
53
|
+
1. A **Verified** line: date plus the commit the tree was read at.
|
|
54
|
+
2. A **top-level tree**: every base folder in the root, complete, one annotated line each.
|
|
55
|
+
3. A **section per unit**, each carrying its folder convention as an annotated tree.
|
|
56
|
+
4. **Key files marked `★` inline**, inside those trees.
|
|
57
|
+
|
|
58
|
+
Nothing else. A map that also explains how the system works has become an architecture document,
|
|
59
|
+
and `.how/` already owns that.
|
|
60
|
+
|
|
61
|
+
The form is an **annotated tree**, not prose and not a file table. A tree shows convention and
|
|
62
|
+
location in the same glance, and a `★` next to a filename is read at the moment it matters. Both
|
|
63
|
+
maps MUST close with the one-line legend for `★`.
|
|
64
|
+
|
|
65
|
+
## How units are split
|
|
66
|
+
|
|
67
|
+
Each map splits its sections along the axis its reader is lost on, and the two axes differ:
|
|
68
|
+
|
|
69
|
+
| Map | Sections | Split by |
|
|
70
|
+
|---|---|---|
|
|
71
|
+
| `structure-codebase.md` | Containers · Libraries · the non-unit sections below | **Deployability** |
|
|
72
|
+
| `structure-document.md` | One per layer that carries content | **Layer** |
|
|
73
|
+
|
|
74
|
+
For the codebase map the distinction is exact and MUST NOT be softened:
|
|
75
|
+
|
|
76
|
+
- A **container** runs its own code or stores its own data, and can be replaced without rebuilding
|
|
77
|
+
another one. `architecture-guide.md` owns the two-question test; this map only applies it. The term
|
|
78
|
+
MUST NOT be renamed to "application", "service", or "app" here — a synonym for a term that already
|
|
79
|
+
has a glossary entry is drift, and `wdi-reconcile` hunts for it. It does not mean a Docker image.
|
|
80
|
+
- A **library** is an includable artifact — compiled into or imported by something else, never run
|
|
81
|
+
on its own. A library with an entry point is a container wearing the wrong label, and a library
|
|
82
|
+
MUST NOT appear at C4 L2.
|
|
83
|
+
- Anything that is neither is not a unit. It stays a line in the top-level tree, or in one of the
|
|
84
|
+
non-unit sections below.
|
|
85
|
+
- A unit that stops being separately deployable MUST move sections, not keep its old heading.
|
|
86
|
+
|
|
87
|
+
### The registry match is one-directional
|
|
88
|
+
|
|
89
|
+
**Every container heading MUST be a container registered in `components.yaml`. Not every registered
|
|
90
|
+
container gets a heading.** Reading it both ways makes the rule unsatisfiable: a `built: false` container
|
|
91
|
+
— a database, a web server — MUST be registered, because it runs inside the boundary and carries NFRs,
|
|
92
|
+
and MUST NOT get a heading, because no code of ours lives there. So the check is **heading = exactly the
|
|
93
|
+
`built: true` containers whose code is in this repo** — those without `repo:` — and `container-built`
|
|
94
|
+
runs it. A container whose `repo:` names another repository gets its heading in THAT repository's map;
|
|
95
|
+
`architecture-guide.md` § *`built`* owns the field. `c4-l2-containers.md` still owns the list itself.
|
|
96
|
+
|
|
97
|
+
### Sections that are not units
|
|
98
|
+
|
|
99
|
+
Containers and Libraries are the unit sections. A map MAY also carry sections for what is not a unit at
|
|
100
|
+
all, and these MUST NOT be dressed up as containers to earn a place:
|
|
101
|
+
|
|
102
|
+
| Section | Holds |
|
|
103
|
+
|---|---|
|
|
104
|
+
| **Tooling** | Scripts run by a human or by CI, never deployed |
|
|
105
|
+
| **Generated** | Output, named with its generator — that is what makes a hand edit visible |
|
|
106
|
+
| **Unclaimed** | A folder that exists with no stated purpose. A finding, not a category |
|
|
107
|
+
|
|
108
|
+
The list is open, the test is not: a section that is neither a unit nor one of these MUST say in one line
|
|
109
|
+
why it exists.
|
|
110
|
+
|
|
111
|
+
## Base folders — complete
|
|
112
|
+
|
|
113
|
+
- MUST list every base folder that exists, including the ones that look uninteresting. An unlisted
|
|
114
|
+
folder is the one people misuse, because nothing told them what it was for.
|
|
115
|
+
- MUST descend only until directories stop carrying distinct roles. A shape that repeats MUST be
|
|
116
|
+
described once, generically, rather than enumerated per instance.
|
|
117
|
+
- MUST mark a folder that exists but has no stated purpose as unclaimed instead of inventing one.
|
|
118
|
+
An unclaimed folder is a finding, and `wdi-init` MUST report it.
|
|
119
|
+
- MUST NOT list a folder that the architecture implies but no file has created yet.
|
|
120
|
+
|
|
121
|
+
## Key files — selective
|
|
122
|
+
|
|
123
|
+
A file earns a `★` only if it passes one of these:
|
|
124
|
+
|
|
125
|
+
- It is an entry point, a composition root, or where dependencies get wired.
|
|
126
|
+
- It is the single place a rule is enforced for the whole tree below it.
|
|
127
|
+
- An agent asked to change behaviour in that folder would have to open it first.
|
|
128
|
+
- Removing it would change what the folder *is*, not merely what it does.
|
|
129
|
+
|
|
130
|
+
Everything else MUST be left out. Completeness at file level is what killed every source-tree
|
|
131
|
+
document that came before: it is impossible to keep true, so it stops being read.
|
|
132
|
+
|
|
133
|
+
A folder with no key file MUST still appear in the tree. Folders are complete; files are not.
|
|
134
|
+
|
|
135
|
+
## Freshness — this is a living document
|
|
136
|
+
|
|
137
|
+
- The **Verified** line MUST carry a date and a commit SHA. Without the SHA, staleness cannot be
|
|
138
|
+
measured, only felt.
|
|
139
|
+
- A map MUST be refreshed when a base folder is born or removed, when a key file moves or is
|
|
140
|
+
renamed, when a project or container is added, or when a key file's role changes.
|
|
141
|
+
- **Spec close** carries this hook — it left the ticket-closing checklist along with four other items,
|
|
142
|
+
because a structural change is visible at the end of a spec and guessed at the end of a ticket.
|
|
143
|
+
- A map MUST NOT be edited by hand. `wdi-init` intent `structure` re-derives it from the actual tree;
|
|
144
|
+
a hand edit records what someone remembers, and memory is exactly what the map exists to replace.
|
|
145
|
+
- A map whose **Verified** commit is no longer an ancestor of `HEAD` SHOULD be treated as stale, and
|
|
146
|
+
MUST be refreshed before a gate that reads it.
|
|
147
|
+
|
|
148
|
+
## `structure-codebase.md` — specifics
|
|
149
|
+
|
|
150
|
+
- Born as a skeleton listing only what exists. On an empty repo that is almost nothing, and that is
|
|
151
|
+
correct: writing the tree the spine implies means guessing.
|
|
152
|
+
- Each unit's tree MUST show its **folder convention** — including the shape a feature repeats,
|
|
153
|
+
written once with a placeholder, never enumerated per feature.
|
|
154
|
+
- Each container MUST mark its entry point and its composition root with `★`. A container whose
|
|
155
|
+
tree has neither has not been read properly.
|
|
156
|
+
- Each container SHOULD carry one **Flow** line: the authoritative call direction through its
|
|
157
|
+
folders. A builder who gets that wrong writes code that works and is still wrong. MUST NOT be
|
|
158
|
+
invented where none exists.
|
|
159
|
+
- Each library MUST state who consumes it. A library nobody consumes is a finding.
|
|
160
|
+
- Generated output MUST be named with its generator, even when it looks like ordinary source — that
|
|
161
|
+
is what makes a hand edit visible.
|
|
162
|
+
- MUST NOT carry framework versions, and MUST NOT repeat the suffix list from
|
|
163
|
+
`conventions-guide.md`. Where new code goes is answered by the convention tree itself; how it is
|
|
164
|
+
named is not this file's question.
|
|
165
|
+
|
|
166
|
+
## `structure-document.md` — specifics
|
|
167
|
+
|
|
168
|
+
- The four layers and the workspace are fixed by `corpus-guide.md`. This map records which of them
|
|
169
|
+
actually carry content: which Product Component folders exist, which slots have been split out of
|
|
170
|
+
a kernel, which registries are populated.
|
|
171
|
+
- MUST reference the placement test rather than restating it, and MUST NOT explain slot numbering —
|
|
172
|
+
`corpus-guide.md` owns both.
|
|
173
|
+
- MUST list every Product Component folder that exists in `.what/` or `.how/`, and MUST flag any
|
|
174
|
+
that exists on one side only. A PC with an SRS and no SDD is drift, not layout.
|
|
175
|
+
- Product Component folders MUST live in the table, and MUST NOT also be expanded in the per-layer
|
|
176
|
+
trees. Maintaining the same fact in two places is how one of them starts lying.
|
|
177
|
+
|
|
178
|
+
## File names MUST survive every OS the repo is cloned on
|
|
179
|
+
|
|
180
|
+
This is the one structural rule that is not about where a file sits but about whether it can exist at
|
|
181
|
+
all. It applies to every file any skill in this method creates — corpus documents, generated tables,
|
|
182
|
+
spec folders, and code alike.
|
|
183
|
+
|
|
184
|
+
| Rule | Detail |
|
|
185
|
+
|---|---|
|
|
186
|
+
| Forbidden characters | `\ / : * ? " < > \|` MUST NOT appear in a file or folder name |
|
|
187
|
+
| Substitution | A forbidden character MUST be replaced by `-` or dropped, and the substitution MUST be consistent across the repo |
|
|
188
|
+
| Trailing characters | A name MUST NOT end in a space or a `.` — Windows strips both silently, and the read path then no longer matches the write path |
|
|
189
|
+
| Length | A single path segment SHOULD stay under 255 characters |
|
|
190
|
+
|
|
191
|
+
The failure this prevents is not cosmetic. A repository whose branches carry `:` in a filename
|
|
192
|
+
**cannot be checked out on Windows at all** — `git checkout` fails outright, and recovering the
|
|
193
|
+
content takes per-blob extraction plus a rename map. That has happened in a sibling repo, which is
|
|
194
|
+
why this is stated as a rule rather than left to taste.
|
|
195
|
+
|
|
196
|
+
A name derived from something else — an endpoint path, a URL, a title — MUST be sanitised at the
|
|
197
|
+
moment it becomes a filename, and the mapping SHOULD be recorded when it is not reversible by
|
|
198
|
+
inspection.
|
|
199
|
+
|
|
200
|
+
## Writing rules
|
|
201
|
+
|
|
202
|
+
Inherited from `.constitution/`: normative keyword on every instruction, concise, no duplication,
|
|
203
|
+
English, SHOULD stay under 200 lines. A map that outgrows 200 lines is marking files that never
|
|
204
|
+
earned a `★` — cut those, never the folders.
|