From b05a0951eea5b33bdf574ee1e4bec785bddb79c1 Mon Sep 17 00:00:00 2001 From: David Cozens Date: Sat, 9 May 2026 21:00:29 +0000 Subject: [PATCH 1/5] feat: S08.03 slice 6a apply_extra_args helper + facility/severity translation Land the cmdline -> `set` bridge in the BDD target driver and untag prival.feature on the FreeRTOS-on-QEMU runner. - target_driver: spawn no longer raises on FreeRTOS extra_args. New apply_extra_args helper walks --flag/value pairs after the prompt is up and writes `set NAME VALUE` lines to the UART. Unknown flags / odd-length args lists raise ValueError so a misconfigured scenario fails loudly rather than silently no-op'ing. - _run_with_prompt_protocol: invokes apply_extra_args after wait_for_prompt; Linux/Windows is a no-op there. - main.c::OnSet: drop the parsed > 23U / parsed > 7U upper-bound rejections on facility/severity. Mirrors the Linux example's atoi-and-cast so the library is the single authority on what's valid (out-of-range encodes as the internal-error PRIVAL 43). - prival.feature: drop the feature-level @freertoswip; all six scenarios pass against syslog-ng-freertos. Refs #306, #268. Co-Authored-By: Claude Opus 4.7 (1M context) --- Bdd/features/prival.feature | 1 - Bdd/features/steps/syslog_steps.py | 3 +- Bdd/features/steps/target_driver.py | 69 ++++++++++++++++++++++++----- Example/FreeRtos/SingleTask/main.c | 17 ++++--- 4 files changed, 72 insertions(+), 18 deletions(-) diff --git a/Bdd/features/prival.feature b/Bdd/features/prival.feature index b9e61d46..f53d994d 100644 --- a/Bdd/features/prival.feature +++ b/Bdd/features/prival.feature @@ -1,5 +1,4 @@ @udp -@freertoswip Feature: PRIVAL encoding The library calculates RFC 5424 PRIVAL from facility and severity. The example program accepts --facility and --severity flags, diff --git a/Bdd/features/steps/syslog_steps.py b/Bdd/features/steps/syslog_steps.py index 0f60aaba..32f3160d 100644 --- a/Bdd/features/steps/syslog_steps.py +++ b/Bdd/features/steps/syslog_steps.py @@ -22,7 +22,7 @@ otel_kill_oracle, otel_start_oracle, ) -from target_driver import spawn_example_process, stop_example_process +from target_driver import apply_extra_args, spawn_example_process, stop_example_process PER_TRANSPORT_LOG_SYSLOG_NG = { "udp": RECEIVED_UDP_LOG, @@ -405,6 +405,7 @@ def _run_with_prompt_protocol(context, binary, label, extra_args, expected_messa try: wait_for_prompt(process) + apply_extra_args(context, process, extra_args) send_command(process, f"send {expected_messages}") wait_for_messages(context, expected_messages) diff --git a/Bdd/features/steps/target_driver.py b/Bdd/features/steps/target_driver.py index 281a48c0..b4370560 100644 --- a/Bdd/features/steps/target_driver.py +++ b/Bdd/features/steps/target_driver.py @@ -13,13 +13,31 @@ The active target is selected by the BDD_TARGET environment variable, read in environment.before_all and stashed on context.target. Steps call spawn_example_process(context, extra_args=...) instead of -subprocess.Popen directly. +subprocess.Popen directly. After wait_for_prompt, callers also invoke +apply_extra_args so any `--flag value` pairs are delivered to the +target — appended to argv on Linux/Windows (a no-op there because +spawn already did it), or translated into `set NAME VALUE` lines over +the UART on FreeRTOS. """ import os import subprocess +# Mapping from cmdline flag to FreeRTOS interactive `set` name. Only the +# flags features currently pass to run_example are mapped — adding a new +# scenario that needs a new flag should fail loudly via the +# `_FREERTOS_SET_TRANSLATION` lookup so the gap is visible, rather than +# silently no-op'ing or printing a confusing "set: invalid" on the UART. +# `--message` -> `msg` is intentional: the FreeRTOS example global is +# g_msg (Example/FreeRtos/SingleTask/main.c) and renaming the set name +# would churn the example for cosmetic gain. +_FREERTOS_SET_TRANSLATION = { + "--facility": "facility", + "--severity": "severity", +} + + # QEMU machine + UART config matches build-freertos-target's smoke run # in .github/workflows/ci.yml: mps2-an385 / Cortex-M3 / 16 MiB / LAN9118 # NIC / -serial stdio for the polled CMSDK UART. -icount keeps virtual @@ -47,10 +65,8 @@ def spawn_example_process(context, extra_args=None, binary=None): extra_args are appended to the binary's command line on Linux and Windows (where the example-runner parses argv via getopt). FreeRTOS has no getopt port and consumes its config via interactive `set` - commands instead; passing extra_args on FreeRTOS therefore raises — - such scenarios should be tagged @freertoswip until a follow-up - slice teaches the FreeRTOS driver to translate cmdline flags into - the equivalent set commands. + commands instead — they are delivered via apply_extra_args after + the prompt is up. binary defaults to context.example_binary (the standard SingleTask binary or its FreeRTOS .elf equivalent); callers that drive a @@ -64,12 +80,6 @@ def spawn_example_process(context, extra_args=None, binary=None): binary = context.example_binary if target == "freertos": - if extra_args: - raise NotImplementedError( - "FreeRTOS target does not accept argv; tag the scenario " - "@freertoswip until the driver translates flags into " - "interactive `set` commands. Got: " + repr(extra_args) - ) cmd = list(_QEMU_BASE_ARGS) + ["-kernel", os.path.abspath(binary)] else: cmd = [os.path.abspath(binary)] @@ -85,6 +95,43 @@ def spawn_example_process(context, extra_args=None, binary=None): ) +def apply_extra_args(context, process, extra_args): + """Deliver `--flag value` pairs to the example after the prompt is up. + + Linux and Windows are no-ops here — spawn already placed the flags + in argv. FreeRTOS translates each pair via _FREERTOS_SET_TRANSLATION + and writes one newline-terminated `set NAME VALUE` line to the UART + per pair. + + Raises ValueError if extra_args is odd-length or contains a flag + not in the translation table; the BDD scenario surfaces the gap + immediately rather than silently no-op'ing or hitting a confusing + UART-side `set: invalid` reply. + """ + if not extra_args: + return + target = getattr(context, "target", "linux") + if target != "freertos": + return + if len(extra_args) % 2 != 0: + raise ValueError( + "FreeRTOS extra_args must be flag/value pairs; got odd length: " + + repr(extra_args) + ) + for flag, value in zip(extra_args[0::2], extra_args[1::2]): + try: + name = _FREERTOS_SET_TRANSLATION[flag] + except KeyError as exc: + raise ValueError( + f"Unknown cmdline flag for FreeRTOS target: {flag!r}. " + "Add it to _FREERTOS_SET_TRANSLATION in target_driver.py " + "if a corresponding `set` name exists in the FreeRTOS " + "example's OnSet handler." + ) from exc + process.stdin.write(f"set {name} {value}\n") + process.stdin.flush() + + def stop_example_process(process, target, timeout=10): """Tear down the example process for the active target. diff --git a/Example/FreeRtos/SingleTask/main.c b/Example/FreeRtos/SingleTask/main.c index 77f2453f..498937d8 100644 --- a/Example/FreeRtos/SingleTask/main.c +++ b/Example/FreeRtos/SingleTask/main.c @@ -249,8 +249,13 @@ static bool OnSet(const char* name, const char* value) } if (strcmp(name, "facility") == 0) { + /* Mirrors the Linux example's atoi-and-cast (Example/Common/ + * ExampleCommandLine.c): the example forwards the parsed value + * unchanged so the library is the single authority on what's + * valid (out-of-range facility/severity encodes as the + * internal-error PRIVAL 43). */ unsigned long parsed = 0U; - if (!TryParseUInt(value, &parsed) || parsed > 23U) + if (!TryParseUInt(value, &parsed)) { return false; } @@ -260,7 +265,7 @@ static bool OnSet(const char* name, const char* value) if (strcmp(name, "severity") == 0) { unsigned long parsed = 0U; - if (!TryParseUInt(value, &parsed) || parsed > 7U) + if (!TryParseUInt(value, &parsed)) { return false; } @@ -290,9 +295,11 @@ static bool TryParseUInt(const char* value, unsigned long* out) } char* end = NULL; unsigned long parsed = strtoul(value, &end, 10); - /* strtoul accepts a leading '-' and wraps to a huge unsigned, but each - * call site range-checks (port <= UINT16_MAX, facility <= 23, - * severity <= 7) so wrapped values are still rejected upstream. */ + /* strtoul accepts a leading '-' and wraps to a huge unsigned. The port + * call site bounds-checks against UINT16_MAX upstream; facility and + * severity intentionally don't, mirroring the Linux example's + * atoi-and-cast so wrapped values reach the library and encode as + * the internal-error PRIVAL. */ if (*end != '\0') { return false; From 8ec026bf0d22f4608556e139a8a4204e7b0aa605 Mon Sep 17 00:00:00 2001 From: David Cozens Date: Sat, 9 May 2026 21:11:12 +0000 Subject: [PATCH 2/5] feat: S08.03 slice 6b msgid/msg translation, untag message_fields + udp_mtu Full delivery Extend the cmdline -> `set` translation table so msgid/message flags reach the FreeRTOS example, and grow the UART line buffer + g_msg storage so a single `set msg ` line can carry a full path-MTU-class message body. - target_driver: --msgid -> set msgid, --message -> set msg. - ExampleInteractive: MAX_LINE_LENGTH 256 -> SOLIDSYSLOG_MAX_MESSAGE_SIZE so fgets doesn't split a `set msg <372-byte UTF-8 body>` line across reads. The HandleSet name[] inherits the same size; future work may decouple the name buffer (always short) from the line buffer. - main.c: g_msg 256 -> SOLIDSYSLOG_MAX_MESSAGE_SIZE so the storage matches the library's bound and the BDD UTF-8 path-MTU test fits. INTERACTIVE_TASK_STACK_DEPTH *32 -> *40 to absorb the ~4 KB peak added by the larger line + name frames. - message_fields.feature: drop the feature-level @freertoswip; tag the Complete RFC 5424 scenario individually (still asserts system hostname / current timestamp / process PID). - udp_mtu.feature: drop the feature-level @freertoswip; tag the Oversize scenario individually (UDP path-MTU clipping depends on EMSGSIZE semantics that FreeRTOS-Plus-TCP doesn't currently surface). After this slice the FreeRTOS BDD sweep is 4 features / 10 scenarios passing, up from the 1-scenario walking-skeleton baseline. Refs #306, #268. Co-Authored-By: Claude Opus 4.7 (1M context) --- Bdd/features/message_fields.feature | 2 +- Bdd/features/steps/target_driver.py | 2 ++ Bdd/features/udp_mtu.feature | 2 +- Example/Common/ExampleInteractive.c | 8 +++++- Example/FreeRtos/SingleTask/main.c | 38 +++++++++++++++++------------ 5 files changed, 33 insertions(+), 19 deletions(-) diff --git a/Bdd/features/message_fields.feature b/Bdd/features/message_fields.feature index 5d9c22c0..457984a3 100644 --- a/Bdd/features/message_fields.feature +++ b/Bdd/features/message_fields.feature @@ -1,5 +1,4 @@ @udp -@freertoswip Feature: Message ID and message body The library includes message ID and message body in the RFC 5424 message. @@ -13,6 +12,7 @@ Feature: Message ID and message body When the example program sends a message with body "system started" Then the message is "system started" + @freertoswip Scenario: Complete RFC 5424 message with all fields Given the syslog oracle is running When the example program sends a complete message with message ID "CONN" and body "session opened" diff --git a/Bdd/features/steps/target_driver.py b/Bdd/features/steps/target_driver.py index b4370560..56c98705 100644 --- a/Bdd/features/steps/target_driver.py +++ b/Bdd/features/steps/target_driver.py @@ -35,6 +35,8 @@ _FREERTOS_SET_TRANSLATION = { "--facility": "facility", "--severity": "severity", + "--msgid": "msgid", + "--message": "msg", } diff --git a/Bdd/features/udp_mtu.feature b/Bdd/features/udp_mtu.feature index 75454c39..5da6cf01 100644 --- a/Bdd/features/udp_mtu.feature +++ b/Bdd/features/udp_mtu.feature @@ -1,5 +1,4 @@ @udp -@freertoswip Feature: UDP datagram path-MTU clipping When a UDP message exceeds the path MTU the sender clips it to the path-MTU's safe payload, walking back over any partial UTF-8 @@ -19,6 +18,7 @@ Feature: UDP datagram path-MTU clipping Then the received message is byte-identical to the sent message @windows_wip + @freertoswip Scenario: Oversize UTF-8 message is clipped at a codepoint boundary Given the syslog oracle is running When the example program sends an oversize UTF-8 message diff --git a/Example/Common/ExampleInteractive.c b/Example/Common/ExampleInteractive.c index 8121c93f..1ee248fe 100644 --- a/Example/Common/ExampleInteractive.c +++ b/Example/Common/ExampleInteractive.c @@ -11,7 +11,13 @@ static const char* const PROMPT = "SolidSyslog> "; enum { - MAX_LINE_LENGTH = 256 + /* Sized to SOLIDSYSLOG_MAX_MESSAGE_SIZE so a single `set msg ` + * can carry a full path-MTU-class message body without fgets + * splitting it across reads. The HandleSet name[] mirrors this size + * because the parser splits at the first whitespace; future work + * may decouple the name buffer (always short — RFC 5424 maxima are + * ≤ 255 chars) from the line buffer. */ + MAX_LINE_LENGTH = SOLIDSYSLOG_MAX_MESSAGE_SIZE }; static void PrintPrompt(void) diff --git a/Example/FreeRtos/SingleTask/main.c b/Example/FreeRtos/SingleTask/main.c index 498937d8..7f3931db 100644 --- a/Example/FreeRtos/SingleTask/main.c +++ b/Example/FreeRtos/SingleTask/main.c @@ -65,13 +65,18 @@ /* SolidSyslog_Log allocates two char[SOLIDSYSLOG_MAX_MESSAGE_SIZE] frames * (~4 KB) plus formatter storage on its formatter path; ExampleInteractive - * adds a 256-byte fgets line and newlib printf (~1 KB). Empirically the - * task hard-faults at *16 (8 KB) once the SolidSyslog setup runs — newlib - * printf and the formatter path together exceed that budget. *32 (16 KB) - * keeps the smoke run stable; a follow-up will introduce CMake-driven - * memory scaling once the budget is properly characterised. The task only - * exists in this single-task example, so heap_4 (96 KB) absorbs it. */ -#define INTERACTIVE_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE * 32U) + * adds a SOLIDSYSLOG_MAX_MESSAGE_SIZE fgets line buffer (so a `set msg + * ` line carrying a full path-MTU-class message body lands in one + * read) plus a same-size HandleSet name buffer and newlib printf (~1 KB). + * Empirically the task hard-faults at *16 (8 KB) once the SolidSyslog + * setup runs — newlib printf and the formatter path together exceed that + * budget. *32 (16 KB) was stable while the line buffer was 256 B; the + * MAX_LINE_LENGTH bump to 2048 B in slice 6 adds ~4 KB peak (line + name + * frames) so *40 (20 KB) gives ~4 KB headroom. A follow-up will introduce + * CMake-driven memory scaling once the budget is properly characterised. + * The task only exists in this single-task example, so heap_4 (96 KB) + * absorbs it. */ +#define INTERACTIVE_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE * 40U) /* Static IPv4 wiring matching the QEMU slirp default. 10.0.2.15 is the * standard slirp DHCP-allocated guest address; we hardcode it here so no @@ -89,15 +94,16 @@ static const uint8_t TEST_DESTINATION_IPV4[ipIP_ADDRESS_LENGTH_BYTES] = {10U, 0U * interactive `set ` command rewrites these in-place via * OnSet below. Storage sizes match RFC 5424 maxima where applicable * (HOSTNAME 255, APP-NAME 48, PROCID 128, MSGID 32) plus null - * terminator; MSG is bounded by storage rather than the protocol; - * g_host fits an IPv4 dotted-quad. g_message holds facility/severity - * (mutated in place) and the messageId/msg pointers (which target the - * mutable storage so contents are seen on each Log). */ -static char g_hostname[256] = "FreeRtosExample"; -static char g_appName[49] = "SolidSyslogExample"; -static char g_processId[129] = "1"; -static char g_messageId[33] = "example"; -static char g_msg[256] = "Hello from FreeRTOS"; + * terminator; MSG matches SOLIDSYSLOG_MAX_MESSAGE_SIZE so a single + * `set msg ` can carry a full path-MTU-class body; g_host fits + * an IPv4 dotted-quad. g_message holds facility/severity (mutated in + * place) and the messageId/msg pointers (which target the mutable + * storage so contents are seen on each Log). */ +static char g_hostname[256] = "FreeRtosExample"; +static char g_appName[49] = "SolidSyslogExample"; +static char g_processId[129] = "1"; +static char g_messageId[33] = "example"; +static char g_msg[SOLIDSYSLOG_MAX_MESSAGE_SIZE] = "Hello from FreeRTOS"; static char g_host[16] = "10.0.2.2"; static uint16_t g_port = (uint16_t) EXAMPLE_UDP_PORT; static uint32_t g_endpointVersion = 0U; From 6b2259ed942a19e6e344a4ce382f8ae3bd639839 Mon Sep 17 00:00:00 2001 From: David Cozens Date: Sat, 9 May 2026 21:12:08 +0000 Subject: [PATCH 3/5] style: clang-format auto-realign after g_msg size bump The longer SOLIDSYSLOG_MAX_MESSAGE_SIZE bracket pushes clang-format's alignment column for the g_* statics; the surrounding g_host / g_port / g_endpointVersion lines need the same extra padding to stay column-consistent. Co-Authored-By: Claude Opus 4.7 (1M context) --- Example/FreeRtos/SingleTask/main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Example/FreeRtos/SingleTask/main.c b/Example/FreeRtos/SingleTask/main.c index 7f3931db..c5d35774 100644 --- a/Example/FreeRtos/SingleTask/main.c +++ b/Example/FreeRtos/SingleTask/main.c @@ -104,9 +104,9 @@ static char g_appName[49] = "SolidSyslogExample"; static char g_processId[129] = "1"; static char g_messageId[33] = "example"; static char g_msg[SOLIDSYSLOG_MAX_MESSAGE_SIZE] = "Hello from FreeRTOS"; -static char g_host[16] = "10.0.2.2"; -static uint16_t g_port = (uint16_t) EXAMPLE_UDP_PORT; -static uint32_t g_endpointVersion = 0U; +static char g_host[16] = "10.0.2.2"; +static uint16_t g_port = (uint16_t) EXAMPLE_UDP_PORT; +static uint32_t g_endpointVersion = 0U; static struct SolidSyslogMessage g_message = { .facility = SOLIDSYSLOG_FACILITY_LOCAL0, From 2ff4f69701d56b56c1a41c8c3b2e8f18478e75ba Mon Sep 17 00:00:00 2001 From: David Cozens Date: Sat, 9 May 2026 21:15:08 +0000 Subject: [PATCH 4/5] docs: update DEVLOG for S08.03 slice 6 Co-Authored-By: Claude Opus 4.7 (1M context) --- DEVLOG.md | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) diff --git a/DEVLOG.md b/DEVLOG.md index 2ce9962e..44986ce5 100644 --- a/DEVLOG.md +++ b/DEVLOG.md @@ -1,5 +1,135 @@ # Dev Log +## 2026-05-09 — S08.03 slice 6 — cmdline → `set` translation in BDD target driver (#306) + +Slice 5 left eight `@udp` features tagged `@freertoswip` because the +FreeRTOS BDD driver couldn't translate Linux-side cmdline flags into +the FreeRTOS example's `set NAME VALUE` UART command channel. Slice 6 +closes that gap for the four flags `@udp` features actually pass to +`run_example` (`--facility`, `--severity`, `--msgid`, `--message`), +loosens the FreeRTOS example's facility/severity input validation to +mirror Linux's permissive `atoi`-and-cast, and grows the UART line +buffer + `g_msg` storage to `SOLIDSYSLOG_MAX_MESSAGE_SIZE` so a single +`set msg ` can carry a full path-MTU-class UTF-8 message. + +After this slice the FreeRTOS BDD sweep is **4 features / 10 scenarios +passing** (up from the slice-5 walking-skeleton baseline of 1 +scenario): `prival.feature` (all 6 scenarios), `message_fields.feature` +(2 of 3), `udp_mtu.feature` (`Full delivery within path MTU` — +`Oversize` stays tagged), and `header_fields.feature::App name`. + +### Decisions + +- **Translation table is exactly four entries; unknown flags raise.** + The FreeRTOS branch of `target_driver.spawn_example_process` no + longer raises on `extra_args`; instead a new helper + `apply_extra_args` (called from `_run_with_prompt_protocol` after + `wait_for_prompt`) walks `--flag value` pairs, looks each flag up + in `_FREERTOS_SET_TRANSLATION`, and writes `set NAME VALUE\n` lines + to the UART. An unknown flag, or an odd-length args list, raises + `ValueError` so a misconfigured scenario fails loudly with a + Python traceback rather than silently no-op'ing or hitting a + confusing `set: invalid` reply on the UART. No premature + generalisation — adding a new scenario flag is a one-line table + append. +- **`--message` ↔ `set msg` naming gap stays in the table.** The + FreeRTOS example's global is `g_msg` (`Example/FreeRtos/SingleTask/ + main.c`); renaming the `set` name would churn the example for + cosmetic gain. The translation lives in one Python dict. +- **Loosen `OnSet` for facility/severity to match Linux's + atoi-and-cast.** The two `prival.feature::Out-of-range` scenarios + assert that the library encodes invalid facility/severity as the + internal-error PRIVAL 43 — which only happens if the example + forwards the bad value unchanged. The FreeRTOS `OnSet` previously + rejected `parsed > 23U` / `parsed > 7U`; slice 6 drops both + bounds so the example becomes permissive about the value and the + library is the single authority on what's valid. Mirrors the + Linux example's `(enum SolidSyslog_Facility) atoi(optarg)` flow + in `Example/Common/ExampleCommandLine.c`. +- **Expand `MAX_LINE_LENGTH` and `g_msg` to + `SOLIDSYSLOG_MAX_MESSAGE_SIZE` (2048).** The walking-skeleton + values (256 each) couldn't carry `udp_mtu.feature::Full + delivery`'s 372-byte UTF-8 body — fgets would split the `set msg + ` line across reads and the `HandleSet name[]` buffer was + same-size. Bumping both to 2048 unblocks Full delivery and + future-proofs the storage to the library's bound. The `Oversize` + scenario (~1600 bytes) stays tagged because UDP path-MTU + EMSGSIZE semantics on FreeRTOS-Plus-TCP are unverified — that is + its own slice. +- **Bump `INTERACTIVE_TASK_STACK_DEPTH` *32 → *40.** The larger + line buffer and same-size `name[]` in `HandleSet` add ~4 KB peak + to the interactive-task stack frame; *32 (16 KB) was the empirical + ceiling at the previous buffer size. *40 (20 KB) gives ~4 KB + headroom. Bigger picture is captured by the existing memory note + on the CMake-driven memory-scaling follow-up (the `*32` magic + number was already deferred to that work). +- **Per-scenario `@freertoswip` tagging where features are mixed.** + `message_fields.feature` keeps `@freertoswip` only on the + `Complete RFC 5424 message` scenario (it asserts system + hostname / current timestamp / process PID — orthogonal to slice + 6). `udp_mtu.feature` keeps it only on the `Oversize` scenario + (UDP-stack semantics — orthogonal). The other features are + untagged at feature level. + +### Two-commit shape + +Strict TDD at the BDD level: +1. **Commit A** untag prival, watch behave fail with + `NotImplementedError`, write the helper + facility/severity + table entries, loosen `OnSet`, watch all 6 prival scenarios go + green. +2. **Commit B** add `--msgid`/`--message` table entries, expand + `MAX_LINE_LENGTH` + `g_msg` + stack depth, untag message_fields + (scenario-level on `Complete RFC 5424`) and `udp_mtu` + (scenario-level on `Oversize`). + +A trailing format-only commit picked up clang-format's column +realignment after `g_msg`'s longer bracket expression shifted the +`g_*` static block alignment column. The PR squash collapses all +three into one commit on `main`. + +### Local verification + +- `cmake --build --preset freertos-cross --target + SolidSyslogFreeRtosSingleTask` clean. +- `behave --tags='not @wip and not @freertoswip and @udp' Bdd/ + features/` against `syslog-ng-freertos`: 4 features pass, 10 + scenarios pass, 36 skipped (still `@freertoswip`). +- `clang-format --dry-run --Werror` on every changed C file: clean. +- Linux unit tests / cppcheck / tidy / iwyu / sanitize / coverage: + not run locally — the `freertos-target` devcontainer carries the + cross toolchain only. CI's responsibility. + +### Deferred + +- **Removing the remaining `@freertoswip` tags.** What's still + tagged after slice 6: `syslog.feature` (single scenario, + composite system-hostname/timestamp/PID assertion); + `header_fields.feature::Hostname` and `::Process ID` (same + reason); `message_fields.feature::Complete RFC 5424` (same + reason); `timestamp.feature` (hardcoded RFC 5424 publication + date); `structured_data.feature`, `origin.feature`, + `time_quality.feature` (no SD wired in the FreeRTOS example); + `udp_mtu.feature::Oversize` (UDP path-MTU EMSGSIZE on FreeRTOS- + Plus-TCP); `buffered.feature` (no FreeRTOS Threaded example). +- **Real RTC-backed clock callback for the FreeRTOS example.** + Until then `TEST_TIMESTAMP` (RFC 5424 publication date) + prevents the timestamp scenarios passing. +- **CMake-driven memory scaling.** The bump to *40 is empirical; + the real lower bound is unverified. Same as the existing slice-3b.2 + follow-up note. + +### Open questions + +- Is the BDD step layer the right place for the `--message` ↔ `msg` + naming gap, or should the example rename the `set` name? Slice 6 + picked the BDD-side mapping; a future cleanup could push it + either way. +- The translation table currently lives as a module-private dict + in `target_driver.py`. If a fifth flag arrives, no churn — but + if a target needs *different* flag→set mappings, the dict goes + context-aware. Keep an eye on it. + ## 2026-05-09 — S08.03 slice 5 — BDD harness pointed at FreeRTOS-on-QEMU target (#304) Slice 4 made the FreeRTOS example's identity, transport endpoint, and PRIVAL From 5a6d9e58943cf6616aadefdb39eb9bd4ed92c236 Mon Sep 17 00:00:00 2001 From: David Cozens Date: Sun, 10 May 2026 05:12:11 +0100 Subject: [PATCH 5/5] Update DEVLOG.md correct escaping of literal * in emphasis section Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- DEVLOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/DEVLOG.md b/DEVLOG.md index 44986ce5..9d34aa15 100644 --- a/DEVLOG.md +++ b/DEVLOG.md @@ -56,10 +56,10 @@ scenario): `prival.feature` (all 6 scenarios), `message_fields.feature` scenario (~1600 bytes) stays tagged because UDP path-MTU EMSGSIZE semantics on FreeRTOS-Plus-TCP are unverified — that is its own slice. -- **Bump `INTERACTIVE_TASK_STACK_DEPTH` *32 → *40.** The larger +- **Bump `INTERACTIVE_TASK_STACK_DEPTH` `*32` → `*40`.** The larger line buffer and same-size `name[]` in `HandleSet` add ~4 KB peak - to the interactive-task stack frame; *32 (16 KB) was the empirical - ceiling at the previous buffer size. *40 (20 KB) gives ~4 KB + to the interactive-task stack frame; `*32` (16 KB) was the empirical + ceiling at the previous buffer size. `*40` (20 KB) gives ~4 KB headroom. Bigger picture is captured by the existing memory note on the CMake-driven memory-scaling follow-up (the `*32` magic number was already deferred to that work).