From 2a6df3ffe279a83258fd2bdfb44567d1e51b5609 Mon Sep 17 00:00:00 2001 From: Lilleman auf Larv Date: Mon, 28 Sep 2026 02:02:53 +0200 Subject: [PATCH 1/3] Name which body settles data_coding in resolveBody --- src/pdu.ts | 100 ++++++++++++++++++++++++----------------------------- todo.md | 7 ---- 2 files changed, 45 insertions(+), 62 deletions(-) diff --git a/src/pdu.ts b/src/pdu.ts index fd0651a..63c069b 100644 --- a/src/pdu.ts +++ b/src/pdu.ts @@ -71,78 +71,68 @@ type ResolvedBody = { tlvs: TlvInputs | undefined; }; +/** + * What the PDU's data_coding describes, and so what may set it: short_message wherever it holds an + * octet, since messageOctets() reads it there, and message_payload only where it does not. + */ +type CodingSource = 'caller' | 'message_payload' | 'short_message'; + function codingOf(params: Record): number | undefined { return typeof params.data_coding === 'number' ? params.data_coding : undefined; } -/** messageOctets() reads short_message wherever it holds an octet, and the TLV only where it does not. */ -function carriesOctets(value: ParamValue | undefined): boolean { - return Buffer.isBuffer(value) && value.length > 0; +/** Only the short_message the command's own table will write, since writeParams() ignores any other. */ +function resolveShortMessage( + params: Record, + definition: CommandDefinition, +): Result<{ params: Record; source: CodingSource }> { + const message = definition.params?.short_message === undefined ? undefined : params.short_message; + + if (Buffer.isBuffer(message)) { + return { + params: params.sm_length === undefined ? { ...params, sm_length: message.length } : params, + source: message.length > 0 ? 'caller' : 'message_payload', + }; + } + + if (typeof message !== 'string') return { params, source: 'message_payload' }; + + const encoded = encodeBody(message, codingOf(params)); + + if (encoded.err) { + return { err: new Error(`Parameter "short_message" of "${definition.command}": ${encoded.err.message}`) }; + } + + const written = { ...params, short_message: encoded.buffer, sm_length: encoded.buffer.length }; + + if (encoded.buffer.length === 0) return { params: written, source: 'message_payload' }; + + return { params: { ...written, data_coding: encoded.dataCoding }, source: 'short_message' }; } -/** The short_message the command's own table will write, since writeParams() ignores any other. */ -function writtenBody(definition: CommandDefinition, value: ParamValue | undefined): ParamValue | undefined { - return definition.params?.short_message === undefined ? undefined : value; -} - -/** Encoded in place, settling data_coding where `settles` says no mandatory field will carry it. */ -function resolveCarried( - resolved: ResolvedBody, - inputs: TlvInputs | undefined, - dataCoding: number | undefined, - settles: boolean, -): VoidResult { - const text = inputs?.message_payload?.tagValue; - - if (typeof text !== 'string') return {}; - - const encoded = encodeBody(text, dataCoding); - - if (encoded.err) return { err: new Error(`TLV "message_payload": ${encoded.err.message}`) }; - - if (settles) resolved.params.data_coding = encoded.dataCoding; - - resolved.tlvs = { ...resolved.tlvs, message_payload: { tagValue: encoded.buffer } }; - - return {}; -} - -/** data_coding names the alphabet of the body, and short_message settles it where it carries octets. */ function resolveBody( params: Record, tlvs: TlvInputs | undefined, definition: CommandDefinition, ): Result { - const message = writtenBody(definition, params.short_message); - const resolved: ResolvedBody = { params: { ...params }, tlvs }; + const shortMessage = resolveShortMessage(params, definition); - if (Buffer.isBuffer(message) && params.sm_length === undefined) { - resolved.params.sm_length = message.length; - } + if (shortMessage.err) return { err: shortMessage.err }; - if (typeof message === 'string') { - const encoded = encodeBody(message, codingOf(params)); + const text = tlvs?.message_payload?.tagValue; - if (encoded.err) { - return { err: new Error(`Parameter "short_message" of "${definition.command}": ${encoded.err.message}`) }; - } + if (typeof text !== 'string') return { params: shortMessage.params, tlvs }; - if (carriesOctets(encoded.buffer)) resolved.params.data_coding = encoded.dataCoding; + const encoded = encodeBody(text, codingOf(shortMessage.params)); - resolved.params.short_message = encoded.buffer; - resolved.params.sm_length = encoded.buffer.length; - } + if (encoded.err) return { err: new Error(`TLV "message_payload": ${encoded.err.message}`) }; - // Only octets the command's own table will write can settle the alphabet the PDU declares. - const settles = !carriesOctets(writtenBody(definition, resolved.params.short_message)); - const carried = resolveCarried( - resolved, - tlvs, - settles ? codingOf(params) : codingOf(resolved.params), - settles, - ); - - return carried.err ? { err: carried.err } : resolved; + return { + params: shortMessage.source === 'message_payload' + ? { ...shortMessage.params, data_coding: encoded.dataCoding } + : shortMessage.params, + tlvs: { ...tlvs, message_payload: { tagValue: encoded.buffer } }, + }; } function writeParams( diff --git a/todo.md b/todo.md index be7f61f..8791da0 100644 --- a/todo.md +++ b/todo.md @@ -199,13 +199,6 @@ next work ([decision](docs/decisions.md#internals-and-tests)). ### Locality — next, ahead of everything below; 5–6 today, and the gate is 7 -- [ ] **Replace `resolveBody`'s `settles` boolean with the decision it stands for.** One boolean - chooses both whether to overwrite `data_coding` and which params to read it from, across four - helpers all named some abstraction of "body". Return a named source — `'short_message' | - 'payload' | 'caller'` — and branch once. Ranked hardest by three readers and picked by one as - the unit they would least want to touch, because a mistake here does not throw, does not fail - the types, and reaches the peer as somebody's message rendered wrong. - ### Correctness - [ ] **Settle what a repeated tag not marked `multiple` reads as, and pin it in a test.** A vendor -- 2.52.0 From 65fadfc93af19ebc3c30522a106ff544585df8c4 Mon Sep 17 00:00:00 2001 From: Lilleman auf Larv Date: Mon, 28 Sep 2026 02:09:42 +0200 Subject: [PATCH 2/3] Narrow CodingSource to the two bodies, and file Locality's remaining work --- src/pdu.ts | 6 +++--- todo.md | 14 +++++++++----- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/pdu.ts b/src/pdu.ts index 63c069b..743cbed 100644 --- a/src/pdu.ts +++ b/src/pdu.ts @@ -75,23 +75,23 @@ type ResolvedBody = { * What the PDU's data_coding describes, and so what may set it: short_message wherever it holds an * octet, since messageOctets() reads it there, and message_payload only where it does not. */ -type CodingSource = 'caller' | 'message_payload' | 'short_message'; +type CodingSource = 'message_payload' | 'short_message'; function codingOf(params: Record): number | undefined { return typeof params.data_coding === 'number' ? params.data_coding : undefined; } -/** Only the short_message the command's own table will write, since writeParams() ignores any other. */ function resolveShortMessage( params: Record, definition: CommandDefinition, ): Result<{ params: Record; source: CodingSource }> { + // Only the short_message the command's own table will write, since writeParams() ignores any other. const message = definition.params?.short_message === undefined ? undefined : params.short_message; if (Buffer.isBuffer(message)) { return { params: params.sm_length === undefined ? { ...params, sm_length: message.length } : params, - source: message.length > 0 ? 'caller' : 'message_payload', + source: message.length > 0 ? 'short_message' : 'message_payload', }; } diff --git a/todo.md b/todo.md index 8791da0..5190609 100644 --- a/todo.md +++ b/todo.md @@ -190,8 +190,8 @@ A nine-reader comprehension panel read the whole project on 2026-09-20 and score mean 6.8. Navigation (7–8) capped nobody. **Locality capped every unit reader at 5–6 and Shape capped both architects at 6**, and those two are what this release lifts. The gate is 7 on all four dimensions, higher where it is cheap. Maintainer's call, 2026-09-20. A systems-architect review the -same day returned ALIGN with one blocking-severity finding, which is the first item under Locality -and is also what the panel ranked hardest — two methods, one answer. +same day returned ALIGN with one blocking-severity finding, `resolveBody`'s `settles` boolean, which +the panel also ranked hardest; it is now a named `CodingSource`. A four-seat scoring run on 2026-09-27 read #30 at 6, 6, 7 and 6, every seat capped by Locality in the held-message and shutdown code; #30 merged under the floor on condition that Locality is the @@ -199,6 +199,10 @@ next work ([decision](docs/decisions.md#internals-and-tests)). ### Locality — next, ahead of everything below; 5–6 today, and the gate is 7 +- [ ] **Lift the held-message and shutdown code to Locality 7, and confirm it with a scoring run.** + The 2026-09-27 run capped every seat there; a run reading 7.0 or above also retires the #30 + decision. + ### Correctness - [ ] **Settle what a repeated tag not marked `multiple` reads as, and pin it in a test.** A vendor @@ -292,10 +296,10 @@ next work ([decision](docs/decisions.md#internals-and-tests)). - [ ] **Move the one-line facts out of the decision log and back to the code.** Five of nine readers independently reported being sent to `docs/decisions.md` for a question they hit while reading, - with no link from the code; one counted roughly fifty index redirects. The four worth inlining + with no link from the code; one counted roughly fifty index redirects. The three left to inline as one line each: that `segmentUnits`' three numbers are in two units (septets and octets), - which body settles `data_coding`, that a receipt's body is read as octets whatever its - `data_coding` says, and the `-` id notation. The reasoning stays in the log; the + that a receipt's body is read as octets whatever its `data_coding` says, and the `-` + id notation. The reasoning stays in the log; the definition belongs at the code. - [ ] **Document the two delivery-receipt merge bounds.** `maxDlrMerges` (1000) and -- 2.52.0 From af2984654475d2430d5df78b3b43b7553319b5d1 Mon Sep 17 00:00:00 2001 From: Lilleman auf Larv Date: Mon, 28 Sep 2026 02:10:02 +0200 Subject: [PATCH 3/3] Reflow the Self-sufficiency item --- todo.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/todo.md b/todo.md index 5190609..f602931 100644 --- a/todo.md +++ b/todo.md @@ -299,8 +299,7 @@ next work ([decision](docs/decisions.md#internals-and-tests)). with no link from the code; one counted roughly fifty index redirects. The three left to inline as one line each: that `segmentUnits`' three numbers are in two units (septets and octets), that a receipt's body is read as octets whatever its `data_coding` says, and the `-` - id notation. The reasoning stays in the log; the - definition belongs at the code. + id notation. The reasoning stays in the log; the definition belongs at the code. - [ ] **Document the two delivery-receipt merge bounds.** `maxDlrMerges` (1000) and `dlrMergeTimeout` (24 h) are hardcoded, are not options, and appear in no README and no test — -- 2.52.0