Skip to content

Commit 1f245dd

Browse files
committed
Add blind trial results to plan 73
Ran 5 simulated developer trials with a 15-snippet questionnaire. Key findings: {{.field}} dual meaning is the #1 confusion source, indented directives silently break (avg confidence 2.6), nested directives are undefined (avg 2.0), and ratio parameter name misleads. Updated tasks to address all discovered misconceptions. https://claude.ai/code/session_015XXFMqS3iqmbyMsNJFeCeY
1 parent fa68d18 commit 1f245dd

1 file changed

Lines changed: 132 additions & 70 deletions

File tree

plan/73_unify-template-directives.md

Lines changed: 132 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -65,47 +65,113 @@ examples.
6565

6666
### Pain points
6767

68-
1. **Same syntax, different semantics** --
69-
`{{.field}}` means "insert value" in catalog
68+
1. `{{.field}}` means "insert value" in catalog
7069
but "match any text" in required-structure.
71-
2. **Marker pairs vs single markers** -- no
72-
visual cue tells the user whether a marker
70+
2. No visual cue tells you whether a marker
7371
needs a closing tag.
74-
3. **Parameter count varies wildly** -- from
75-
zero (allow-empty-section) to seven (catalog).
76-
4. **No single reference** -- rules are
77-
documented per-rule; no unified walkthrough
78-
exists.
79-
80-
### What works well
81-
82-
- The `<?name ... ?>` syntax is visually
83-
distinct from Markdown content.
84-
- YAML inside markers is familiar to users who
85-
already write front matter.
86-
- Catalog and include share the same
87-
open/generate/close lifecycle via the
88-
`gensection` archetype.
72+
3. No single reference exists -- rules are
73+
documented per-rule only.
74+
75+
## Blind trial results (5 participants)
76+
77+
Five developers got a two-sentence intro and
78+
15 syntax snippets. They guessed what each
79+
snippet does and rated their confidence.
80+
81+
### Confidence scores (1=guessing, 5=certain)
82+
83+
| Snippet | Topic | Avg | Range |
84+
|---------|-----------------------------|-----|-------|
85+
| 1 | `<?catalog?>` pair | 4.8 | 4-5 |
86+
| 2 | `<?include?>` pair | 4.8 | 4-5 |
87+
| 3 | `<?require?>` single marker | 4.0 | 2-5 |
88+
| 4 | `<?allow-empty-section?>` | 4.8 | 4-5 |
89+
| 5 | `{{.id}}: {{.title}}` heading | 3.8 | 3-4 |
90+
| 6 | catalog `row` table template | 4.4 | 4-5 |
91+
| 7 | `line-length` config | 4.0 | 4-5 |
92+
| 8 | config overrides | 4.8 | 4-5 |
93+
| 9 | CUE front-matter schema | 4.4 | 4-5 |
94+
| 10 | `{{.field}}` heading vs row | 4.0 | 3-5 |
95+
| 11 | 4-space indented directive | 2.6 | 1-4 |
96+
| 12 | nested directives in row | 2.0 | 1-3 |
97+
| 13 | empty section at EOF | 4.6 | 3-5 |
98+
| 14 | `paragraph-readability` | 4.0 | 3-5 |
99+
| 15 | `token-budget` with ratio | 3.8 | 2-5 |
100+
101+
### Key misconceptions found
102+
103+
1. **`{{.field}}` dual meaning (snippet 10):**
104+
All five participants correctly identified
105+
that template headings and catalog rows use
106+
the same syntax for different purposes. All
107+
flagged this as the top source of confusion.
108+
Three called it "genuinely confusing" despite
109+
getting the right answer. The syntax collision
110+
means even correct users feel uncertain.
111+
112+
2. **Indented directives silently break
113+
(snippet 11):** Average confidence 2.6.
114+
Most guessed it would be treated as a code
115+
block, but nobody was sure. Four of five
116+
called this a "footgun" because there is no
117+
diagnostic -- the directive just disappears.
118+
119+
3. **Nested directives undefined (snippet 12):**
120+
Confidence 2.0, the lowest of all snippets.
121+
Guesses ranged from "literal text" to "nested
122+
not allowed" to "recursive include." Nobody
123+
was sure.
124+
125+
4. **`<?require?>` role unclear (snippet 3):**
126+
One participant rated confidence 2. The word
127+
"require" is ambiguous: require a file to
128+
exist? A filename pattern? Front-matter
129+
fields? The snippet alone does not tell you.
130+
131+
5. **`ratio: 0.75` meaning (snippet 15):**
132+
Two participants misread `ratio` as a warning
133+
threshold (warn at 75% of budget). It is
134+
actually a words-to-tokens multiplier. The
135+
parameter name does not signal its unit.
136+
137+
6. **fix behavior unclear for simple rules
138+
(snippet 7):** Three participants were unsure
139+
whether `line-length` is fixable. One rated
140+
fix confidence at 2. Users cannot predict
141+
which rules are fixable without reading each
142+
rule's docs.
143+
144+
### What worked well
145+
146+
- Self-describing names scored highest:
147+
`allow-empty-section` (4.8), `overrides` (4.8).
148+
- Marker pairs are intuitive: catalog and
149+
include both scored 4.8.
150+
- CUE schema readable: `|` union and `?`
151+
optional read naturally (4.4).
152+
153+
### Implications for the user model
154+
155+
Users grasped marker pairs quickly. The real
156+
confusion is elsewhere:
157+
158+
- Same syntax, two meanings (`{{.field}}`).
159+
- Silent failures (indented directives).
160+
- Undefined composition (nesting).
161+
- Ambiguous parameter names (`ratio`).
162+
- Unpredictable fixability.
163+
164+
The guide must address all five.
89165

90166
## Proposed user model
91167

92168
### Principle: two kinds of markers
93169

94-
Collapse all directives into two categories a
95-
user can identify on sight:
170+
Users already grasp this (blind trial 4.8 avg
171+
for pairs). Make it the documented rule:
96172

97-
| Kind | Shape | Rule | User prediction |
98-
|------------|-------------------------------|-----------------------------------------------|-----------------------------------------------------|
99-
| **Generator** | `<?name ...?>` ... `<?/name?>` | Content between markers is managed by mdsmith | "If I see a marker pair, `fix` regenerates the body" |
100-
| **Constraint** | `<?name ...?>` (no closing tag) | The marker asserts a condition | "If I see a lone marker, `check` validates something" |
101-
102-
The core rule: if a marker has a closing tag,
103-
the body is auto-generated; if it does not, it
104-
is a validation constraint.
105-
106-
This is already almost true today. The plan
107-
makes it explicit and documents it as the
108-
governing rule.
173+
- Closing tag present: `fix` regenerates body.
174+
- No closing tag: `check` validates a condition.
109175

110176
### Principle: one template language
111177

@@ -135,49 +201,33 @@ field-name hint.
135201
**Decision required from maintainer:** pick A
136202
or B before implementation.
137203

138-
### Principle: consistent YAML parameters
139-
140-
All directives already use YAML for parameters.
141-
No change needed, but the guide must present
142-
them with a uniform layout:
143-
144-
```markdown
145-
<?directive-name
146-
param1: value
147-
param2: value
148-
?>
149-
```
150-
151204
### What does NOT change
152205

153-
- The `<?...?>` marker syntax itself stays.
154-
- The YAML parameter format stays.
155-
- The `gensection` engine for generators stays.
156-
- The `fix` / `check` CLI commands stay.
157-
- `.mdsmith.yml` configuration stays.
158-
159-
This is intentionally conservative. The goal is
160-
a clearer mental model and a guide, not a
161-
rewrite.
206+
The `<?...?>` syntax, YAML parameters,
207+
`gensection` engine, CLI commands, and
208+
`.mdsmith.yml` all stay. This plan improves
209+
the user model and docs, not the engine.
162210

163211
## Tasks
164212

165-
### Phase 1: central directive reference (#70)
213+
### Phase 1: central directive guide (#70)
166214

167215
1. Write `docs/guides/directives.md` covering:
168216

169-
- The two-kind model (generator vs
170-
constraint)
171-
- Placement constraints: must be at document
172-
root, at most 3-space indent, ignored
173-
inside fenced code blocks and HTML blocks
174-
- Every directive with: purpose, parameters,
175-
one good example, one bad example, what
176-
`check` reports, what `fix` does
177-
- A quick-reference table at the top
178-
- Classification by role: "generated-section
179-
markers" vs "rule modifiers / escape
180-
hatches" (per #70)
217+
- Quick-reference table (name, purpose, has
218+
closing tag, fixable, parameters)
219+
- Placement rules: max 3-space indent, not
220+
inside fenced code or HTML blocks. Call out
221+
the 4-space footgun with an explicit warning
222+
and example (blind trial snippet 11)
223+
- Each directive: purpose, parameters, one
224+
good example, one bad example, what `check`
225+
reports, what `fix` does
226+
- A "which rules auto-fix?" summary (blind
227+
trial snippet 7 confusion)
228+
- Nesting: explicitly state that directives
229+
inside generated content are not processed
230+
(blind trial snippet 12 confusion)
181231

182232
2. Add cross-links from each rule README to the
183233
guide.
@@ -204,17 +254,24 @@ rewrite.
204254
`internal/rules/proto.md`,
205255
`.claude/skills/proto.md`) to the new syntax.
206256

257+
### Phase 2b: fix ambiguous parameter names
258+
259+
9. Rename `token-budget` `ratio` to
260+
`words-per-token` (blind trial showed 2 of 5
261+
misread it as a warning threshold). Keep
262+
`ratio` as a deprecated alias.
263+
207264
### Phase 3: evaluate template engine (stretch)
208265

209-
9. Prototype replacing Go `text/template` with
266+
10. Prototype replacing Go `text/template` with
210267
gonja or pongo2 in catalog rendering.
211268

212269
- Measure: does Jinja syntax reduce user
213270
confusion vs Go templates?
214271
- Measure: does it enable filters/conditionals
215272
that users actually need?
216273

217-
10. If the prototype shows clear benefit, plan a
274+
11. If the prototype shows clear benefit, plan a
218275
migration. If not, keep Go `text/template` and
219276
document its quirks in the guide.
220277

@@ -224,11 +281,16 @@ rewrite.
224281
covers every directive with examples
225282
- [ ] The guide passes `mdsmith check
226283
docs/guides/`
284+
- [ ] The guide documents the 4-space indent
285+
footgun and nesting behavior
286+
- [ ] The guide includes a fixability summary
227287
- [ ] `{{.field}}` in required-structure
228288
templates uses a distinct syntax from
229289
catalog templates (Phase 2)
230290
- [ ] Existing template files are migrated
231291
(Phase 2)
292+
- [ ] `ratio` renamed to `words-per-token` with
293+
backward-compatible alias (Phase 2b)
232294
- [ ] All tests pass: `go test ./...`
233295
- [ ] `go tool golangci-lint run` reports no
234296
issues

0 commit comments

Comments
 (0)