Skip to content

pj_source batch: provider-contract promotions, packaged test fixtures, provider guide (0.31.0) - #194

Merged
facontidavide merged 4 commits into
mainfrom
feat/pj-source-0.31
Sep 6, 2026
Merged

pj_source batch: provider-contract promotions, packaged test fixtures, provider guide (0.31.0)#194
facontidavide merged 4 commits into
mainfrom
feat/pj-source-0.31

Conversation

@facontidavide

@facontidavide facontidavide commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

SDK 0.31.0 — the ratified pj_source batch (spec: docs/BACKLOG.md). Everything the two cloud provider plugins were each hand-rolling for the M3 source-capture contract, promoted once. No C-ABI changes: protocol headers, vtable sizes and ABI sentinels untouched.

The rename

descriptor_import_support grows into pj_source (PJ::sdk::source, plotjuggler_sdk::source) with a full one-release compatibility layer: forwarding headers, namespace descriptor_import = source, an INTERFACE target under the old export name, and a Conan compatibility component. pj_cloud stays reserved for real connection code.

Promoted

  • limitsenvLimit()/minNonzero() fail-safe env ceilings (byte-identical copies existed in both plugins).
  • parseDecimalNs — int64-safe decimal-ns wire parse; validateSchemelessOrigin — strict host:port charset validator.
  • presentation — the host Load-Layout contract (base64url settings group, bidi/zero-width/control stripping, UTF-16 cap).
  • IngestOutcomeLedger — per-topic outcomes → truthful whole-request terminal + ATTESTS_EMPTY_TOPICS; pure logic, three review rounds of hardening inherited from the Mosaico implementation.
  • record_envelope — the attach_source_record acceptance envelope as a public versioned contract, replacing PJ4's private convention; credential denylist folded into SourceDescriptorPolicy::denied_keys (opt-in) inside the existing single recursive walk; refusal messages byte-compatible with the PJ4 host; the flat pre-envelope shape is a pinned REJECTED vector (mcap_cloud migrates via an explicit reshape-or-adapter decision, never silent re-wrapping).
  • stop_bridgeStopPoller + the documented cancel-before-join contract (both plugins had independently built both halves).
  • time_format + slider_window (pj_base proper) — the shared time formatter and overflow-safe slider↔time conversion. Refactored on review: the copied civil-calendar algorithms are replaced by portable C++20 core chrono (year_month_day/sys_days/hh_mm_ss — verified on GCC 11 and Emscripten; chrono format/parse deliberately NOT used, unavailable across the toolchain matrix), padded output goes through the SDK's existing private fmt from extracted fields (avoids fmt's Windows pre-1970 gmtime path and the global-locale grouping hazard), the ISO offset grammar rejects +05:, and the widget time-span readers use strict PJ::parseNumber instead of unchecked stoll.
  • delegated_ingest_fixture (pj_plugins/testing) — merged fake host pair: attachment/completion/Stop/discard evidence through the SDK's own copyIngestCompletion, double-fetch + anchor lifetime, truncated vtables, cancel during blocked ingest.
  • Packaged test-fixture sources (share/plotjuggler_sdk/test_fixtures/ + exported pj_add_sdk_test_fixture()) — PJ4 can delete its second FetchContent of the release tarball, the last acquire-outside-Conan path.
  • docs/provider-guide.md — the full provider-contract walkthrough, linked from the docs table.

Deliberately not here

  • The metadata query language lives in pj-official-plugins common/query (maintainer decision: its syntax should evolve without SDK compatibility events).
  • RollingTransferRate moved to pj-official-plugins common/transfer_rate by the same rule — a pure dialog readout with no host contract is not SDK surface.
  • Lua evaluation, stable table-row identity and pj_cloud remain outside per the ratified scope.
  • No new dependencies: a time-library audit (candidates: HowardHinnant date, fmt) concluded core chrono + the already-shipped private fmt cover everything; date's Conan default even drags libcurl via its tz half.

Pipeline

Codex implementation → independent session review → 4-angle /simplify pass (query-lexer/API dedup, internal consumers de-aliased off the deprecated names, credential check moved to the right altitude) → Codex time-helper audit applied.

Verification

./build.sh --debug && ./test.sh: 95/95 suites. test_sdk_install.sh (real Conan package + consumer build + per-component find_package smoke): PASSED. Pre-commit clean. fmt verified absent from installed exports.

🤖 Generated with Claude Code

https://claude.ai/code/session_01TTJvEsHX26rG4cHmqppvQg

facontidavide and others added 4 commits September 6, 2026 12:49
…, provider guide (0.31.0)

The descriptor_import_support component grows and renames to pj_source
(PJ::sdk::source, plotjuggler_sdk::source) with a one-release deprecated
alias (forwarding headers + namespace alias + INTERFACE target + Conan
component). No C-ABI surface changes: protocol headers, vtable sizes and
ABI sentinels are untouched.

Promoted from the two cloud provider plugins (write once, review once):

- limits: envLimit()/minNonzero() fail-safe env ceilings (strict
  full-string parse via PJ::parseNumber; unparsable = safe default,
  never off).
- parseDecimalNs: int64-safe decimal-nanosecond wire parse.
- validateSchemelessOrigin: strict lowercase host:port charset validator
  (schemes/userinfo/path/query/fragment/IPv6 rejected by construction).
- presentation: the host Load-Layout contract — unpadded
  base64url(identity) settings group; C0/C1, zero-width, bidi, ALM,
  word-joiner stripping; 200 UTF-16-unit cap without splitting pairs.
- IngestOutcomeLedger: per-topic outcomes -> truthful whole-request
  terminal (+ATTESTS_EMPTY_TOPICS), pure logic, caller-owned locking.
- record_envelope: the attach_source_record acceptance envelope as a
  public versioned contract ({kind, v, request, label?}) with the
  credential-key denylist folded into SourceDescriptorPolicy::denied_keys
  (opt-in, default empty) inside the existing single recursive walk;
  refusal messages byte-compatible with the PJ4 host implementation;
  the flat pre-envelope shape is a pinned REJECTED vector.
- stop_bridge: StopPoller (observe a live ingest context's stop flag,
  cancel once, join before context release) + the documented
  cancel-before-join contract.
- time_format + slider_window (pj_base proper): the byte-identical
  286-line time formatter hardened through combineSecondsAndNanos, and
  overflow-safe slider<->time conversion with its regression tests.
- RollingTransferRate: monotonic 5-second byte-rate window.
- pj_plugins/testing/delegated_ingest_fixture.hpp: merged fake host pair
  (attachment/completion/Stop/discard evidence through the SDK's own
  copyIngestCompletion; double-fetch + anchor lifetime; truncated
  vtables; cancel during blocked ingest).
- Packaged example/mock plugin fixture sources under
  share/plotjuggler_sdk/test_fixtures/ with the exported
  pj_add_sdk_test_fixture() helper (single PJ_SDK_TEST_FIXTURES list
  feeds both the helper and the install rule) — PJ4 can drop its second
  FetchContent of the release tarball.
- docs/provider-guide.md: the full provider-contract walkthrough.

The metadata query language deliberately does NOT ship here: it moved to
pj-official-plugins common/ (maintainer decision 2026-09-06) so its
syntax can evolve without SDK compatibility events; docs/BACKLOG.md
records the decision.

Pipeline: Codex implementation, independent session review, and a
4-angle simplify pass (lexer/API/dedup cleanups; internal consumers
de-aliased off the deprecated names).

Tests: 95/95 (115 cases added); test_sdk_install.sh (real Conan
package + consumer + per-component find_package smoke) PASSED.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TTJvEsHX26rG4cHmqppvQg
…parsing

Codex time-helper audit applied: the copied Hinnant civil-calendar
algorithms are replaced by portable C++20 core chrono (year_month_day /
sys_days / hh_mm_ss — supported on every toolchain in the matrix incl.
GCC 11 and Emscripten, unlike chrono format/parse which stay hand-rolled);
padded output goes through the SDK's existing private fmt from the
extracted fields (never fmt's time-point formatter, whose gmtime path
rejects pre-1970 on Windows) which also removes the global-locale
grouping hazard; the ISO offset grammar now rejects a colon without
minutes ('+05:'); and the two widget time-span readers drop unchecked
stoll for the strict PJ::parseNumber ('123junk' now refused, signed
values preserved). Regression tests: -1 ns, INT64_MIN, grouping locale,
offset grammar, junk-suffix readers. fmt stays out of installed headers.

Production -44 lines, tests +81. 95/95 suites, pre-commit clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TTJvEsHX26rG4cHmqppvQg
Moved to pj-official-plugins common/transfer_rate with its test — same
placement rule that kept the query language out of the SDK: pure UI
helpers with no host contract stay with the dialogs that show them.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TTJvEsHX26rG4cHmqppvQg
…watchdog test

Full-tree documentation audit applied (agent lens: find the existing
symbol before reimplementing it, at minimal token cost):

- docs/sdk-utilities.md: the task->symbol->header lookup table (incl.
  pointers to the query language and RollingTransferRate in
  pj-official-plugins common/, so neither is reimplemented here);
  linked from root CLAUDE.md, README, both module CLAUDE.md files, the
  plugin skill and the top of the provider guide; shipped with the Conan
  package together with the provider guide (docs/ exported; installed
  under share/plotjuggler_sdk/docs/).
- Root CLAUDE.md: conditional reading order ('before implementing a
  helper, consult sdk-utilities.md'), trimmed to navigation (1,357 -> 624
  words); agent entry path to the utilities index is now ~1,340 words.
- Fixed guide examples that taught duplication: message-parser guide's
  strtod -> PJ::parseNumber; data-source guide's manual handoff ->
  DrainQueue; dialog guide's invented formatDate -> a real SDK formatter.
- Provider guide front-loaded (required machinery named up top; host
  capture-cache identity disambiguated); header doc-comment gaps closed
  (time_format contracts incl. no-fraction/no-Z output and floor
  semantics; outcome_ledger outcome semantics; StopPoller throw
  conditions; provider_job gate wording; parseDecimalNs 'overflow'
  grep keyword).
- Staleness sweep across ~12 documents: wrong namespaces (PJ::sdk::getEnv,
  PJ::okStatus), nonexistent paths/symbols, the ARCHITECTURE claim that
  empty-topic attestation does not exist, plot-marker docs contradicting
  the shipped codec, V4_STORE's missing toolbox object-write surface,
  parser-module counts, BACKLOG scope brought current.
- Prose-clarity pass over 17 documents (-492 words; code blocks and
  tables byte-identical; meaning-critical sentences left verbatim).

Deflake: ProviderJobTest.WatchdogFiresOnceWhenTheBodyOverruns widens the
body overrun 120ms -> 400ms — the recurring loaded-macOS-runner flake
where the 20ms watchdog thread starts too late; fire-once semantics
unchanged.

95/95 suites; test_sdk_install.sh (incl. installed-docs comparison)
PASSED; pre-commit clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TTJvEsHX26rG4cHmqppvQg
@facontidavide
facontidavide merged commit 7737f5a into main Sep 6, 2026
7 checks passed
@facontidavide
facontidavide deleted the feat/pj-source-0.31 branch September 6, 2026 12:21
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