Skip to content

Commit 59c06df

Browse files
committed
feat(ums-lib)!: simplify ProcessStep structure for UMS v2.1
BREAKING CHANGE: ProcessStep interface simplified from v2.0 to v2.1 Removed fields: - detail (replaced by notes array) - when (use natural language in step text) - do (use natural language in step text) - validate (use criteria array instead) Added fields: - notes: optional string array for sub-bullets Changes: - Updated ProcessStep type to: string | { step: string; notes?: string[] } - Implemented new renderProcessStep() function for simplified rendering - Created UMS v2.1 spec with migration notes from v2.0 - Added ADR 0005 documenting rationale for simplification - Updated tests to use new notes field instead of detail Migration path: v2.0: { step: 'X', detail: 'Y', when: 'Z', validate: {...} } v2.1: { step: 'X when Z', notes: ['Y', 'Verify: ...'] } Rationale: - Reduces authoring friction and cognitive load - Natural language is sufficient for conditionals and validation - Clearer separation: process steps vs. validation criteria - Aligns with machine-first architecture (ADR 0004) See ADR 0005 for complete rationale and alternatives considered. feat(ums-lib): simplify Constraint structure (UMS v2.1) BREAKING CHANGE: Constraint interface simplified from 5 fields to 2 fields Changes: - Convert Constraint from interface to type union (string | { rule, notes }) - Remove fields: severity, when, examples, rationale - Add field: notes (string array for elaboration) - Use RFC 2119 keywords (MUST/SHOULD/MAY) for severity in rule text - Update renderer to handle constraint notes with bold rule + bullets - Add test coverage for constraints with notes Migration: - Use RFC 2119 keywords for severity (MUST/SHOULD/MAY) - Move examples to notes with "Good:" and "Bad:" prefixes - Move rationale to notes with "Rationale:" prefix - Use template literals for multi-line content Documentation: - Created ADR 0006: Simplify Constraint Structure - Created RFC proposal: docs/spec/proposals/rfc-constraint-simplification.md - Updated UMS v2.1 spec with Constraint section and migration guide - Documented authoring guidelines and formatting conventions Follows the same simplification pattern as ProcessStep (ADR 0005). See: - docs/architecture/adr/0006-simplify-constraint-structure.md - docs/spec/proposals/rfc-constraint-simplification.md - docs/spec/unified_module_system_v2.1_spec.md feat(ums-lib)!: simplify Criterion structure (ADR 0007) Remove severity field, keep category, add notes array following the same simplification pattern as ProcessStep and Constraint. BREAKING CHANGE: Criterion.severity field removed - use RFC 2119 keywords (MUST/SHOULD/MAY) in criterion text instead. Changes: - Remove severity field (use RFC 2119 keywords in text) - Keep category field (now rendered as subheadings) - Add notes array for test instructions and elaboration - Implement category grouping in renderer - Add comprehensive tests for category and notes rendering Related: ADR 0005 (ProcessStep), ADR 0006 (Constraint)
1 parent 183a552 commit 59c06df

10 files changed

Lines changed: 4240 additions & 71 deletions
Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
# ADR 0005: Simplify ProcessStep Structure
2+
3+
**Status:** Accepted
4+
**Date:** 2025-01-15
5+
**Context:** Reducing complexity in the ProcessStep interface by removing underutilized structured fields in favor of natural language flexibility.
6+
7+
## Context
8+
9+
The UMS v2.0 specification defines a complex `ProcessStep` interface with five fields:
10+
11+
```typescript
12+
interface ProcessStep {
13+
step: string; // Main step description
14+
detail?: string; // Additional context
15+
when?: string; // Conditional execution
16+
do?: string; // Explicit action
17+
validate?: { // Validation criteria
18+
check: string;
19+
severity?: 'error' | 'warning';
20+
};
21+
}
22+
```
23+
24+
This structure was designed to provide machine-readable structure for complex procedural instructions. However, analysis of the design reveals several issues:
25+
26+
1. **Authoring Friction**: Module authors face ambiguity about which field to use:
27+
- Should conditionals go in `when` or be written naturally in `step`?
28+
- Is `do` for commands or descriptions?
29+
- Does `detail` expand on `step` or provide separate information?
30+
31+
2. **Natural Language Sufficiency**: LLMs excel at parsing natural language structures like:
32+
- *"Run migrations if database is empty"* (conditional)
33+
- *"Execute `npm test` and verify all pass"* (action + validation)
34+
- *"Deploy to staging, then run smoke tests"* (sequence)
35+
36+
3. **Validation Duplication**: The spec already includes a dedicated `criteria` array for verification:
37+
```typescript
38+
instruction: {
39+
process?: ProcessStep[];
40+
criteria?: Criterion[]; // Already exists for validation!
41+
}
42+
```
43+
Having validation in both `process[].validate` and `criteria[]` creates confusion about where validation belongs.
44+
45+
4. **Underutilization**: The structured fields are rarely needed. Most processes are straightforward sequences that don't require machine-parseable conditionals or validation.
46+
47+
## Decision
48+
49+
Simplify the `ProcessStep` type to:
50+
51+
```typescript
52+
type ProcessStep = string | {
53+
step: string;
54+
notes?: string[]; // Optional sub-bullets for clarification
55+
};
56+
```
57+
58+
**Rendering Format:**
59+
```markdown
60+
## Process
61+
62+
1. Install dependencies
63+
64+
2. Run database migrations
65+
- Use `npm run migrate` for development
66+
- Production migrations require admin approval
67+
- Verify migration status with `npm run migrate:status`
68+
69+
3. Start the server
70+
```
71+
72+
**Key Principles:**
73+
- **Default to strings**: Most steps need no additional structure
74+
- **Use notes for elaboration**: When a step needs clarification, provide sub-bullets
75+
- **Write conditionals naturally**: "When X, do Y" is clearer than structured fields
76+
- **Keep validation separate**: Use the `criteria` array for verification steps
77+
78+
## Decision Rationale
79+
80+
### 1. Natural Language is Sufficient
81+
82+
LLMs are excellent at extracting structure from well-written natural language. Explicit fields like `when`, `do`, and `validate` add implementation complexity without proportional benefit.
83+
84+
**Example - Natural Language (Better):**
85+
```typescript
86+
process: [
87+
"Run tests. If tests fail, fix issues before proceeding.",
88+
"Deploy to staging environment",
89+
"Run smoke tests and verify all endpoints return 200 OK"
90+
]
91+
```
92+
93+
**Example - Structured Fields (Unnecessary Complexity):**
94+
```typescript
95+
process: [
96+
{
97+
step: "Run tests",
98+
validate: { check: "All tests pass", severity: "error" },
99+
when: "Ready to deploy"
100+
},
101+
{
102+
step: "Deploy to staging",
103+
do: "Execute deployment script"
104+
},
105+
{
106+
step: "Run smoke tests",
107+
validate: { check: "Endpoints return 200", severity: "error" }
108+
}
109+
]
110+
```
111+
112+
### 2. Reduced Cognitive Load
113+
114+
Authors no longer need to decide:
115+
- Which field should this text go in?
116+
- Is this conditional enough to warrant `when`?
117+
- Should validation be in `validate` or `criteria`?
118+
119+
Instead: Just write clear, concise steps.
120+
121+
### 3. Clear Separation of Concerns
122+
123+
- **Process steps** describe *what* to do
124+
- **Criteria** define *how* to verify success
125+
126+
This is cleaner than having validation in both places.
127+
128+
### 4. Flexibility Through Notes
129+
130+
When steps need elaboration, the `notes` array provides structure without over-engineering:
131+
132+
```typescript
133+
{
134+
step: "Configure production environment",
135+
notes: [
136+
"Copy .env.example to .env.production",
137+
"Set DATABASE_URL to production connection string",
138+
"Generate new SECRET_KEY (do not reuse development key)",
139+
"Verify SSL certificates are valid"
140+
]
141+
}
142+
```
143+
144+
## Consequences
145+
146+
### Positive
147+
148+
-**Lower authoring friction**: Clear, simple model reduces decision paralysis
149+
-**More consistent modules**: Fewer options = more consistent patterns
150+
-**Natural expression**: Authors write steps as they naturally think about them
151+
-**Cleaner separation**: Process vs. validation responsibilities are distinct
152+
-**Easier to parse**: Simpler structure is easier for both humans and machines
153+
-**Backwards compatible**: Existing simple steps (strings) continue to work
154+
155+
### Negative
156+
157+
- ⚠️ **Loss of explicit structure**: No dedicated fields for conditionals/validation
158+
- ⚠️ **Parsing ambiguity**: Machines must parse natural language for structure
159+
- ⚠️ **Migration required**: Existing modules using `when`/`do`/validate` need updates
160+
161+
### Migration Path
162+
163+
For existing modules using structured fields, auto-convert to natural language:
164+
165+
```typescript
166+
// Before (v2.0)
167+
{
168+
step: "Start the service",
169+
when: "Service is not running",
170+
do: "Execute systemctl start myapp",
171+
validate: { check: "Service status shows active", severity: "error" }
172+
}
173+
174+
// After (v2.1 - simplified)
175+
{
176+
step: "Start the service if not running",
177+
notes: [
178+
"Execute: `systemctl start myapp`",
179+
"Verify: Service status shows 'active'"
180+
]
181+
}
182+
```
183+
184+
## Alternatives Considered
185+
186+
### Alternative 1: Keep Current Complex Structure
187+
188+
**Rejected because:**
189+
- Creates unnecessary cognitive overhead for authors
190+
- Most modules don't need structured conditionals
191+
- Validation belongs in `criteria`, not embedded in process steps
192+
- Optimizes for the 1% edge case at expense of the 99% common case
193+
194+
### Alternative 2: Remove All Structure (Just Strings)
195+
196+
**Rejected because:**
197+
- Sometimes steps do need elaboration
198+
- Notes array provides minimal structure for common elaboration needs
199+
- Keeps flexibility without abandoning all structure
200+
201+
### Alternative 3: Add Optional Structured Extension (Hybrid)
202+
203+
Add `processAnnotations` for rare cases needing machine-executable steps:
204+
205+
```typescript
206+
instruction: {
207+
process: string[];
208+
processAnnotations?: {
209+
[stepIndex: number]: {
210+
when?: string;
211+
do?: string;
212+
validate?: { ... };
213+
};
214+
};
215+
}
216+
```
217+
218+
**Rejected because:**
219+
- Adds complexity for unproven use cases
220+
- No evidence of actual need for machine-executable steps
221+
- Can be added later if need emerges (YAGNI principle)
222+
- Violates the "keep it simple" directive
223+
224+
## Notes
225+
226+
- This decision aligns with ADR 0004 (Machine-First Architecture) by eliminating unnecessary prose structure while maintaining clarity
227+
- Module authors are encouraged to write clear, self-explanatory steps rather than relying on structure to convey meaning
228+
- If future use cases emerge requiring machine-executable validation, we can revisit with concrete requirements
229+
230+
## References
231+
232+
- UMS v2.0 Specification: Section 3.1 (ProcessStep)
233+
- Related: ADR 0004 (Machine-First Module Architecture)
234+
- Discussion: Unimplemented Spec Properties Report (Section 5)

0 commit comments

Comments
 (0)