Skip to content

Commit 3e486f0

Browse files
committed
docs(editor): add cursor rule for HN-10 heading code guardrails
New .cursor/rules/editor-heading-rules.mdc auto-surfaces INPLACE-1 and STACK-ATTACH-1 rules when editing changeHeadingLevel*.ts, hierarchy validation plugin, or heading test files. Links to V-4 history so future developers understand why delete-then-reinsert is forbidden.
1 parent 953c366 commit 3e486f0

1 file changed

Lines changed: 33 additions & 0 deletions

File tree

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
---
2+
description: Heading schema rules (HN-10) — mandatory reading before modifying heading-related editor code
3+
alwaysApply: false
4+
globs:
5+
[
6+
'**/changeHeadingLevel*.ts',
7+
'**/hierarchyValidationPlugin.ts',
8+
'**/validateHeadingHierarchy.ts',
9+
'**/extensions/Heading/**',
10+
'**/cypress/e2e/editor/Heading/**'
11+
]
12+
---
13+
14+
# Editor Heading Rules (HN-10)
15+
16+
Before modifying any heading-related code, you MUST read:
17+
18+
- `Notes/editor/Editor_Schema_Rules_v3.md` — the HN-10 spec (especially **§9 Level-Change Semantics**)
19+
- `Notes/editor/Code_vs_Rules_Audit.md` — compliance audit and violation history
20+
21+
## Non-Negotiable Rules
22+
23+
1. **INPLACE-1**: Level changes MUST use in-place `setNodeMarkup` — NEVER delete+reinsert. Deleting and reinserting destroys positional identity and causes silent re-parenting under wrong siblings.
24+
25+
2. **STACK-ATTACH-1**: After a forward level change (`newLevel > oldLevel`), re-parent into the preceding sibling's `contentWrapper` if `siblingLevel < newLevel`. This happens in the same transaction, after the in-place attribute change.
26+
27+
3. **Single source of truth**: The hierarchy validation plugin (`appendTransaction`) is the ONLY place that fixes structural violations (child extraction, H1-nested extraction). The level-change command itself MUST NOT duplicate this logic.
28+
29+
4. **H1 special case**: Changing FROM H1 is the only case exempt from INPLACE-1 (section root semantics).
30+
31+
## Why This Matters
32+
33+
A previous implementation used delete-then-reinsert, which caused headings to silently move under wrong siblings — a critical data-corruption bug (V-4). The fix required a full rewrite (Phase 9). See `Code_vs_Rules_Audit.md` for the full history.

0 commit comments

Comments
 (0)