1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
|
# mojibake — Derived Requirements
Software Level: **DAL-C** (DO-178C)
DO-178C §5.1.1.b: requirements arising from design decisions that are not
traceable to a higher-level requirement must be recorded and **flagged for
review** by the safety assessment process. Each entry below states what forced
it and what the reviewer must judge.
---
## MJB-DR-001 — UTF-8 is strict; declared encodings are transcoded
**Status:** **resolved** — no longer an open conflict
**Relates to:** the originating task statement, which listed a "non-UTF-8
rejection path" as a robustness case.
### How it stood
Full Helix save fidelity transcodes rather than rejects, so the first
implementation decoded every input leniently and replaced bad bytes with U+FFFD.
That appeared to contradict the requested rejection path, and the contradiction
was recorded here for the safety assessment. The flagged risk was concrete:
substitution is invisible to the user, and saving a buffer that contains
substituted characters writes U+FFFD over their data.
### How it was resolved
The requester directed that the UTF-8 rule be made an **exception**. The two
behaviours are not in fact in conflict once split by whether the encoding is
*known*:
| Input | Behaviour | Rationale |
|---|---|---|
| BOM declares a non-UTF-8 encoding | Transcode; invalid sequences become U+FFFD | The encoding is known, so the substitution is reproducible on write and Helix fidelity is preserved |
| UTF-8, declared or assumed | **Reject** with the failing byte offset | Nothing is known that would make a repair reproducible, so refusing is the only non-destructive answer |
**Derived requirements.** MJB-LLR-113 governs the transcoding branch;
**MJB-LLR-118** governs the UTF-8 exception. MJB-LLR-115 continues to require
that a detected encoding and BOM round-trip through load and save.
**Residual item for the reviewer.** A user who genuinely wants to inspect a
binary file now cannot open it at all. No override (`moji --binary`, or a
`:e!`-style force) is provided. This is a deliberate omission rather than an
oversight: an override would reintroduce the lossy-save hazard through a
different door, and should be added only with a corresponding requirement that
makes such a buffer read-only.
---
## MJB-DR-002 — Byte offsets require explicit char-boundary defence
**Status:** open — needs review
**Forced by:** the choice of ropey 2.0 with `metric_chars` disabled.
Under char indexing, an index cannot fall inside a character. Under byte
indexing it can, and `Rope::insert`/`remove` panic when it does. This failure
mode does not exist in the Helix design being ported and so is not covered by
any HLR.
**Derived requirement.** Every externally supplied byte offset shall be clamped
into range and moved to a char boundary at construction (MJB-LLR-011), and
change-set application shall validate operation boundaries and return an error
rather than allow a rope panic (MJB-LLR-044).
**Reviewer must judge:** whether returning an error is the correct response, or
whether a violated boundary indicates a defect that should abort. Current choice
is to return an error, consistent with MJB-HLR-018.
---
## MJB-DR-003 — Soft wrap is not implemented
**Status:** open — needs review
**Forced by:** scope.
Helix's viewport carries a `vertical_offset` to address rows within a
soft-wrapped line. With no soft wrap, one buffer line occupies exactly one
screen row, so `vertical_offset` is always zero and is omitted from
`ViewPosition` (MJB-LLR-090).
**Derived requirement.** Lines wider than the viewport shall scroll horizontally
rather than wrap (MJB-LLR-099).
**Reviewer must judge:** that horizontal scrolling is acceptable for the intended
use, and that reintroducing soft wrap later is understood to require reworking
the viewport anchor.
---
## MJB-DR-004 — Keymap ownership is split between App and Buffer
**Status:** open — needs review
**Forced by:** the template's event routing, which delivers every key both to the
application keymap and to every component.
Leaving that routing intact would let a global binding such as `q` fire while the
user types in insert mode. Ownership is therefore split: `App` owns only the
`Global` mode and consumes matching keys; the buffer owns all other modes.
**Derived requirement.** `App` shall not forward a key to components once the
`Global` keymap has matched it (MJB-LLR-203).
**Reviewer must judge:** that `Global` bindings are intentionally unreachable
from every mode, and that placing `Ctrl-c` there is intended even though Helix
binds `Ctrl-c` to comment-toggle in normal mode.
---
## MJB-DR-005 — Count is accumulated but consumed by few commands
**Status:** open — needs review
**Forced by:** MJB-LLR-155 being cheap to implement but not required by any
command in the mandated binding set.
No command in MJB-HLR-006 through MJB-HLR-013 requires a count. The count is
accumulated and passed to command execution, where motions honour it and other
commands ignore it.
**Reviewer must judge:** whether silently ignoring a count on a command that does
not use it is acceptable, or whether it should be reported as an error.
---
## MJB-DR-007 — UTF-16 must be encoded by hand
**Status:** open — needs review
**Found during:** implementation, by a failing round-trip test.
`encoding_rs::Encoding::encode` is deliberately asymmetric. It decodes UTF-16
but refuses to encode to it, silently substituting UTF-8 and reporting the
substitution only through a return value that is easy to discard. Delegating
the save path to it wrote UTF-8 bytes beneath a UTF-16 byte order mark — a
file that no longer matched its own BOM.
**Derived requirement.** UTF-16LE and UTF-16BE shall be encoded directly from
`str::encode_utf16`, with explicit little- and big-endian byte order, and shall
not be routed through `encoding_rs::Encoding::encode` (MJB-LLR-115).
**Reviewer must judge:** whether the remaining encodings, which *are* delegated
to `encoding_rs`, share any comparable asymmetry. The known set is UTF-16LE and
UTF-16BE; single-byte and UTF-8 encodings round-trip correctly. Note that this
defect was invisible to inspection and was caught only by a round-trip test —
the same test shape should guard any encoding added later.
---
## MJB-DR-006 — Pre-release dependency under DAL-C
**Status:** accepted by the requester — recorded for review
**See:** [../reviews/library-selection.md](../reviews/library-selection.md)
ropey 2.0.0-beta.1 is a pre-release, self-described as not battle-tested. It was
selected over the stable 1.6.1 deliberately, with the trade-off stated.
**Derived requirement.** The dependency shall be pinned to an exact version and
reached only through `src/buffer/document.rs`, so that a replacement is confined
to one module.
**Reviewer must judge:** whether a pre-release dependency is acceptable for the
intended deployment, and whether the confinement is in fact maintained.
|