Skip to content

feat(parser): optional pj.parser_runtime.v1 diagnostics service - #165

Merged
facontidavide merged 6 commits into
mainfrom
feat/parser-runtime-diagnostics
Aug 6, 2026
Merged

feat(parser): optional pj.parser_runtime.v1 diagnostics service#165
facontidavide merged 6 commits into
mainfrom
feat/parser-runtime-diagnostics

Conversation

@facontidavide

Copy link
Copy Markdown
Contributor

Companion G1 of the dialog-tree / SDK-compatibility plan (SDK 0.21.0 train). Independent of #164; trivial CHANGELOG conflict expected with sibling PRs.

What

Message parsers previously had no non-fatal diagnostics channel — a parser could fail a whole parse() via Status but had no way to report recoverable/aggregated conditions (field overflow in N of M messages, invalid optional fields, partial schema mismatch).

  • New optional named service pj.parser_runtime.v1 following the established optional-service pattern: ABI-APPENDABLE PJ_parser_runtime_host_vtable_t (one slot: report_diagnostic(level, stable_code, message, occurrences)), width-pinned level enum, frozen fat pointer, service trait. No existing C struct, vtable, protocol version, or min-vtable size changed.
  • ParserRuntimeHostView::reportDiagnostic(...)noexcept; unbound view is a safe no-op. MessageParserPluginBase::bind() acquires it optionally; parserRuntimeHost() / parserRuntimeHostBound() accessors.
  • Contract (documented): stable_code is a machine-stable dedup key, never localized prose; the host aggregates by (parser ID, bound schema/type, level, code); fatal parse failure still uses Status; classifySchema() stays side-effect free. Host-side aggregation/rate-limiting lands with the PJ4 change.
  • Host adapter + testing recorder so embedders and plugin authors can assert diagnostics in unit tests.

ABI hardening (found by review)

MessageParserPluginBase's member layout is cross-DSO ABI: PJ4 casts the context pointer and calls the final classifySchema/parseScalars/parseObject directly. The new member is therefore appended LAST (all pre-0.21 offsets DWARF-verified unchanged), the class documents the append-only contract, and a new compile-time sentinel test pins every pre-0.21 member offset (numeric pins gated to libstdc++; sizeof deliberately unpinned — the host never allocates or copies the object).

Verification

56/56 ctest, warnings-as-errors, pre-commit clean; independent adversarial review passed after the layout fix; rebind-reset covered by test.

🤖 Generated with Claude Code

facontidavide and others added 4 commits August 5, 2026 10:25
The pinned offsets encode libstdc++'s 32-byte std::string; libc++ (macOS)
uses 24 bytes, shifting every subsequent member and failing the asserts.
One pinned platform is a sufficient insertion tripwire.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@facontidavide
facontidavide merged commit 7166dae into main Aug 6, 2026
4 checks passed
@facontidavide
facontidavide deleted the feat/parser-runtime-diagnostics branch August 6, 2026 10:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant