Name which body settles data_coding in resolveBody #40
+45
-55
@@ -71,78 +71,68 @@ type ResolvedBody = {
|
|||||||
tlvs: TlvInputs | undefined;
|
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 = 'message_payload' | 'short_message';
|
||||||
|
|
||||||
function codingOf(params: Record<string, ParamValue | undefined>): number | undefined {
|
function codingOf(params: Record<string, ParamValue | undefined>): number | undefined {
|
||||||
return typeof params.data_coding === 'number' ? params.data_coding : 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 resolveShortMessage(
|
||||||
function carriesOctets(value: ParamValue | undefined): boolean {
|
params: Record<string, ParamValue | undefined>,
|
||||||
return Buffer.isBuffer(value) && value.length > 0;
|
definition: CommandDefinition,
|
||||||
|
): Result<{ params: Record<string, ParamValue | undefined>; 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 ? 'short_message' : '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(
|
function resolveBody(
|
||||||
params: Record<string, ParamValue | undefined>,
|
params: Record<string, ParamValue | undefined>,
|
||||||
tlvs: TlvInputs | undefined,
|
tlvs: TlvInputs | undefined,
|
||||||
definition: CommandDefinition,
|
definition: CommandDefinition,
|
||||||
): Result<ResolvedBody> {
|
): Result<ResolvedBody> {
|
||||||
const message = writtenBody(definition, params.short_message);
|
const shortMessage = resolveShortMessage(params, definition);
|
||||||
const resolved: ResolvedBody = { params: { ...params }, tlvs };
|
|
||||||
|
|
||||||
if (Buffer.isBuffer(message) && params.sm_length === undefined) {
|
if (shortMessage.err) return { err: shortMessage.err };
|
||||||
resolved.params.sm_length = message.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof message === 'string') {
|
const text = tlvs?.message_payload?.tagValue;
|
||||||
const encoded = encodeBody(message, codingOf(params));
|
|
||||||
|
|
||||||
if (encoded.err) {
|
if (typeof text !== 'string') return { params: shortMessage.params, tlvs };
|
||||||
return { err: new Error(`Parameter "short_message" of "${definition.command}": ${encoded.err.message}`) };
|
|
||||||
}
|
|
||||||
|
|
||||||
if (carriesOctets(encoded.buffer)) resolved.params.data_coding = encoded.dataCoding;
|
const encoded = encodeBody(text, codingOf(shortMessage.params));
|
||||||
|
|
||||||
resolved.params.short_message = encoded.buffer;
|
if (encoded.err) return { err: new Error(`TLV "message_payload": ${encoded.err.message}`) };
|
||||||
resolved.params.sm_length = encoded.buffer.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only octets the command's own table will write can settle the alphabet the PDU declares.
|
return {
|
||||||
const settles = !carriesOctets(writtenBody(definition, resolved.params.short_message));
|
params: shortMessage.source === 'message_payload'
|
||||||
const carried = resolveCarried(
|
? { ...shortMessage.params, data_coding: encoded.dataCoding }
|
||||||
resolved,
|
: shortMessage.params,
|
||||||
tlvs,
|
tlvs: { ...tlvs, message_payload: { tagValue: encoded.buffer } },
|
||||||
settles ? codingOf(params) : codingOf(resolved.params),
|
};
|
||||||
settles,
|
|
||||||
);
|
|
||||||
|
|
||||||
return carried.err ? { err: carried.err } : resolved;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function writeParams(
|
function writeParams(
|
||||||
|
|||||||
@@ -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
|
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
|
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
|
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
|
same day returned ALIGN with one blocking-severity finding, `resolveBody`'s `settles` boolean, which
|
||||||
and is also what the panel ranked hardest — two methods, one answer.
|
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
|
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
|
the held-message and shutdown code; #30 merged under the floor on condition that Locality is the
|
||||||
@@ -199,12 +199,9 @@ next work ([decision](docs/decisions.md#internals-and-tests)).
|
|||||||
|
|
||||||
### Locality — next, ahead of everything below; 5–6 today, and the gate is 7
|
### 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
|
- [ ] **Lift the held-message and shutdown code to Locality 7, and confirm it with a scoring run.**
|
||||||
chooses both whether to overwrite `data_coding` and which params to read it from, across four
|
The 2026-09-27 run capped every seat there; a run reading 7.0 or above also retires the #30
|
||||||
helpers all named some abstraction of "body". Return a named source — `'short_message' |
|
decision.
|
||||||
'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
|
### Correctness
|
||||||
|
|
||||||
@@ -299,11 +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
|
- [ ] **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,
|
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),
|
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
|
that a receipt's body is read as octets whatever its `data_coding` says, and the `<base>-<n>`
|
||||||
`data_coding` says, and the `<base>-<n>` id notation. The reasoning stays in the log; the
|
id notation. The reasoning stays in the log; the definition belongs at the code.
|
||||||
definition belongs at the code.
|
|
||||||
|
|
||||||
- [ ] **Document the two delivery-receipt merge bounds.** `maxDlrMerges` (1000) and
|
- [ ] **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 —
|
`dlrMergeTimeout` (24 h) are hardcoded, are not options, and appear in no README and no test —
|
||||||
|
|||||||
Reference in New Issue
Block a user