Extend a UI Surface
Extends an existing surface document. Use this when a surface needs new components, revised layout, or updated interactions — not for creating a surface from scratch (use surface.create).
Phase 1 — Load Current State
Fetch the surface and its linked feature:
get_document("surface/{id}")get_document("feature/{id}") ← the id from the ui's `for` attributeInventory the existing:
- Layout structure: what containers and regions exist?
- Interactive elements: which buttons, inputs, links are declared?
- Placeholders: which regions are deferred?
- Feature linkage: which requirements and domain actions back the interactive elements?
Then check what has changed since the surface was last updated:
- New requirements in the linked feature?
- Changed flows that imply different interaction patterns?
- New acceptance criteria that need UI support?
Phase 2 — Scope the Change
Determine what specifically needs to change. Precision matters — do not redesign the entire surface for a local update.
| Change type | Scope | Approach |
|---|---|---|
| New screen region | Additive — new section or card | Add within existing layout, choose placement |
| Revised text/labels | Local — strings only | Update literal strings directly in the DSL |
| New interactive element | Local — button, input, link | Add element and verify it has a backing requirement |
| Layout restructure | Regional — one container | Rewrite the affected container completely |
| Container type change | Regional — type swap | Rewrite the region (e.g. stack → tabs), don’t patch around it |
| Placeholder resolution | Local — replace placeholder | Replace with the concrete design, remove placeholder tag |
| Interaction flow change | Structural — clickable/navigation | Update {% interactions %} block if present |
If the user describes a change that implies new requirements not yet in the feature, flag this — the feature should be extended first.
Phase 3 — DSL Changes
Apply the structural and content changes identified in Phase 2:
- Add or remove components — place new elements in the logical position within the existing layout hierarchy
- Update literal strings — labels, headings, button text directly in the Pug DSL
- Adjust nesting — if a component moves between containers, cut and paste cleanly
- Replace placeholders — swap
placeholdertags with their concrete implementations - Container type changes — rewrite the affected region completely rather than patching. When changing from
stacktotabs, the children need restructuring (each group becomes atabchild), not just a parent tag rename.
Indentation check: After all changes, verify indentation is consistent throughout. Mixed tabs and spaces or inconsistent nesting depth produce broken renders. Check the full file, not just the changed region.
Phase 4 — Linkage Verification
After making DSL changes, verify all connections:
forattribute — still points to the correct and existing feature? If the feature was renamed, update it.- Interactive elements — every button, link, and form submit must correspond to a domain action or requirement in the linked feature. List any orphaned elements (interactive but no backing requirement).
- Placeholders — for
status: review, every remaining placeholder needs a justification note. Forstatus: ready, no placeholders should remain unless explicitly documented as intentionally undesigned. - Interactions block — if the file has
{% interactions %}, verify allfromandtargetreferences still resolve to surfaces and elements in the same file.
Present any linkage issues alongside the diff in Phase 5.
Phase 5 — Draft & Confirm
Present the full updated document (not just the diff) for confirmation. Showing the complete file avoids partial-state confusion for visual documents where layout context matters.
Include a summary of:
- What was added, changed, or removed
- Any linkage issues found in Phase 4
- Any remaining placeholders and their justification
Write the updated file only after explicit confirmation.
Output: content/uis/{id}.ui.mdoc (overwrite)
Do’s and Don’ts
Do:
- Fetch the current surface and its linked feature before making changes
- Check what changed in the feature since the surface was last updated
- Scope the change precisely — do not redesign the entire surface for a local update
- Rewrite affected layout regions completely when changing container types
- Verify the
forattribute still points to the correct document after changes - Check indentation consistency across the full file after changes
- Present the full updated document for confirmation
Don’t:
- Don’t redesign the entire surface if only one region changed
- Don’t patch around a container type change; rewrite the affected region cleanly
- Don’t leave interactive elements that have no backing requirement in the linked feature
- Don’t introduce inconsistent indentation; verify the full file after changes
- Don’t skip the linkage check — orphaned surfaces are useless
- Don’t add elements that imply new requirements without flagging the feature gap first
Definition of Done
- Current surface and linked feature loaded before changes
- Change scope determined and agreed before editing
- DSL changes applied with consistent indentation
-
forattribute verified against existing document - Every interactive element has a backing requirement or domain action
- No orphaned placeholders in
readystatus - Full updated document presented to user for confirmation
- All cross-references resolve to existing documents
-
pnpm compilesucceeds