e42: enhanced (formatted) process programs S7F23-F26

E42 was an explicit out-of-scope item in the prior COMPLIANCE.md.
This commit closes it.

Wire messages added via the catalog:
  S7F23  Formatted PP Send       (H↔E, W=1)
  S7F24  Formatted PP Ack        (ProcessProgramAck)
  S7F25  Formatted PP Request    (PPID, W=1)
  S7F26  Formatted PP Data       (E→H, no reply)

Body shape: <L,4 PPID MDLN SOFTREV <L,n <L,2 CCODE <L,m <L,2
PNAME PVAL>>>>>.  PVAL is declared ITEM so any SECS-II Item type
round-trips — proven by a test that mixes ASCII, BOOLEAN, U4, F8,
Binary, and nested List values in one step.

RecipeStore extension:
  add_formatted(ppid, FormattedRecipe{mdln, softrev, steps})
  get_formatted(ppid) -> optional<FormattedRecipe>
  has_formatted(ppid) -> bool

Formatted + opaque views live alongside each other: a PPID can carry
both, size() counts unique PPIDs.  remove() kills both views.

Six new tests cover wire round-trip per function, every
ProcessProgramAck code, ITEM passthrough, and the store's dual-view
semantics.

COMPLIANCE.md updated: E30 §6.17 row mentions S7F23-F26, S5 message
table grows two rows, §8 "out of scope" entry for E42 removed.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-06-09 11:58:03 +02:00
parent d4d1a411d7
commit 78fb0c3826
5 changed files with 317 additions and 8 deletions
+88
View File
@@ -1204,6 +1204,94 @@ messages:
builder: s7f18_delete_pp_ack
body: {kind: scalar, item_type: BINARY_BYTE, enum: ProcessProgramAck, param: ack}
# =====================================================================
# E42 — Enhanced (formatted) Process Programs (S7F23F26).
#
# An enhanced PP is a list of (CCODE, params) rows: each row is one
# command + its parameters. Unlike the opaque PPBODY in S7F3/F6
# (which is just a text blob), the formatted form lets the host
# inspect / synthesize a recipe step-by-step.
#
# CCODE is a free-form ASCII command name (e.g. "HEAT", "GAS_FLOW",
# "STEP_END"); each parameter is a (PNAME, PVAL) pair where PVAL is
# any SECS-II Item (carried as ITEM in the schema).
# =====================================================================
- id: S7F23
stream: 7
function: 23
w: true
builder: s7f23_formatted_pp_send
parser: parse_s7f23
body:
kind: list
struct_name: FormattedProcessProgram
fields:
- {name: ppid, shape: {kind: scalar, item_type: ASCII}}
- {name: mdln, shape: {kind: scalar, item_type: ASCII}}
- {name: softrev, shape: {kind: scalar, item_type: ASCII}}
- name: steps
shape:
kind: list_of
element:
kind: list
struct_name: FormattedStep
fields:
- {name: ccode, shape: {kind: scalar, item_type: ASCII}}
- name: params
shape:
kind: list_of
element:
kind: list
struct_name: FormattedParam
fields:
- {name: name, shape: {kind: scalar, item_type: ASCII}}
- {name: value, shape: {kind: scalar, item_type: ITEM}}
- id: S7F24
stream: 7
function: 24
builder: s7f24_formatted_pp_ack
body: {kind: scalar, item_type: BINARY_BYTE, enum: ProcessProgramAck, param: ack}
- id: S7F25
stream: 7
function: 25
w: true
builder: s7f25_formatted_pp_request
parser: parse_s7f25
body: {kind: scalar, item_type: ASCII, param: ppid}
- id: S7F26
stream: 7
function: 26
builder: s7f26_formatted_pp_data
parser: parse_s7f26
body:
kind: list
struct_name: FormattedProcessProgram
fields:
- {name: ppid, shape: {kind: scalar, item_type: ASCII}}
- {name: mdln, shape: {kind: scalar, item_type: ASCII}}
- {name: softrev, shape: {kind: scalar, item_type: ASCII}}
- name: steps
shape:
kind: list_of
element:
kind: list
struct_name: FormattedStep
fields:
- {name: ccode, shape: {kind: scalar, item_type: ASCII}}
- name: params
shape:
kind: list_of
element:
kind: list
struct_name: FormattedParam
fields:
- {name: name, shape: {kind: scalar, item_type: ASCII}}
- {name: value, shape: {kind: scalar, item_type: ITEM}}
# =====================================================================
# S9 — Protocol error notifications (E5). All carry the 10-byte
# offending message header (MHEAD) as a single BINARY item, except