# 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.