Skip to content

EBP-3106: Add Python direct leaves and the Solace Suggested and Custom overlays - #12

Merged
aelsammak merged 4 commits into
devfrom
EBP-3106
Oct 14, 2026
Merged

aelsammak merged 4 commits into
devfrom
EBP-3106

Conversation

@aelsammak

@aelsammak aelsammak commented Oct 13, 2026 •

Copy link
Copy Markdown

What is the purpose of this change?

Second slice of Python API support in solace-application-development. Implement mode now generates every Python leaf (Direct Pub/Sub and Request-Reply (Direct) join the three Guaranteed Pub/Sub leaves) on all three doors (Quickstart, Solace Suggested, Custom), consistent with the JCSMP section.

How is this accomplished?

  1. Added python/implement-direct-pubsub.md and python/implement-request-reply.md, dispatched from implement mode Step 4. They use the same VERIFY: marker strings as the JCSMP leaves. The blocking requestor sample is the default (matching the JCSMP direct requestor); the non-blocking sample is a variant for many requests in flight.
  2. Added python/solace-suggested-mode.md: tcps:// with CERT_VALIDATED, CERT_REJECT_EXPIRED, and CERT_VALIDATE_SERVERNAME set to True in code after the config loads; the trust store directory from config.json; the HA question mapped to with_connection_retry_strategy(parametrized_retry(1, 3000)), with_reconnection_retry_strategy(parametrized_retry(20, 3000)), and CONNECTION_RETRIES_PER_HOST 5; PERSISTENT_DMQ_ELIGIBLE on the persistent publisher; one independent Python project per role; topic handoff to the topics skill.
  3. Added python/custom-mode.md: the same five knobs as JCSMP, leaf-aware (DMQ and admin-provisioned queue only on Guaranteed Pub/Sub). The admin-queue knob drops CREATE_ON_START and with_subscriptions(...) from the subscriber.
  4. python/design-mode.md: a prompt that needs a persisted request routes to Guaranteed Pub/Sub with an application correlation id, never to Request-Reply (Direct). The direct leaves are now GENERATED.
  5. python/implement-mode.md: removed the "not yet available" stops; Step 0 routes to the overlays; run commands, the manual-run rule, and the interim checklist cover every leaf and door. Quickstart now asks "plaintext (tcp://) or secure (tcps://)?" and gives the trust store guidance on a secure host.
  6. jcsmp.md and python.md design-contract gate: a request to skip the design or all questions does not waive the gate or the door question. The model takes the shortest allowed path instead (derive the summary, present it, wait for one confirm) and writes no file before the confirm.
  7. output-evals.json: the appdev-quickstart-implement-full grader that forbids a verify.sh run now ignores verify.sh text inside a heredoc file write (new exclude_pattern).

Anything reviews should focus on/be aware of?

  • Trust store (differs from JCSMP by necessity). The Python API documents no default trust store, and a validated tcps:// session fails at build() with "Failed to load trust store" without one (confirmed live). JCSMP uses the JVM cacerts. The skill now explains this to the developer and reads solace.messaging.tls.trust-store-path from config.json, on Solace Suggested, the Custom secure-session knob, and secure Quickstart.
  • Other deliberate differences from JCSMP: no parent-pom option for a single deliverable (launcher script or consented drop only); no reapply-subscriptions property (the API re-applies direct subscriptions on reconnect, per the Messaging Service page); DMQ only on the guaranteed publisher (no Python guaranteed request-reply); the short-lived Python scripts keep the samples' SIGINT/SIGTERM handler.
  • Verification is still the compile-only fallback. No Python verify.sh until EBP-3107; each project ends in py_compile, the import smoke, the conformance checks, and handed-back commands.
  • Live round trips (Solace Cloud broker, solace-pubsubplus 1.11.0), generated per the wiring files:
    • Direct Pub/Sub, Quickstart over tcps://: pass (5 of 5 messages, all markers, clean SIGINT).
    • Request-Reply (Direct), blocking requestor, Quickstart over tcps://: pass (all four markers, requestor exit 0, replier exit 0 on SIGINT).
    • Solace Suggested, Guaranteed Pub/Sub, two projects over tcps:// with HA values: pass (3 of 3 PUBLISH_ACKED and MESSAGE_RECEIVED, both exit 0).

…m overlays

- Add implement-direct-pubsub.md and implement-request-reply.md leaf wiring files for the Python API, mirroring the JCSMP leaf files and their VERIFY: marker strings; the blocking requestor is the default and the non-blocking requestor is a variant
- Add solace-suggested-mode.md (TLS with explicit certificate checks and the developer's trust store directory, the HA question mapped to the RetryStrategy values, DMQ eligibility on the persistent publisher, separate Python projects) and custom-mode.md (the same five a la carte knobs as JCSMP)
- Remove the "not yet available" stops for the direct leaves and the hardened doors from implement-mode.md and design-mode.md, and extend the run commands, the manual-run rule, and the interim checklist to every leaf and door
- Route a prompt that needs a persisted request to Guaranteed Pub/Sub with an application correlation id, never to Request-Reply (Direct)
- Explain the trust store to the developer: the Python API has no default trust store, so a tcps:// host fails at build() without one; Quickstart now asks plaintext or secure and gives the same guidance on a secure host
- Note that the Python API re-applies direct subscriptions on reconnect, so the JCSMP reapply-subscriptions property has no Python equivalent
- State in the jcsmp.md and python.md design-contract gate that a request to skip the design or all questions does not waive the gate or the door question
- Direct the shortest allowed path instead: derive the summary, present it, and wait for one confirm before writing any file
- Sonnet failed appdev-code-before-confirm-negative in 2 of 2 runs before the change and passed 3 of 3 after it
- Add an exclude_pattern to the appdev-quickstart-implement-full verify.sh grader so verify.sh text inside a heredoc file write is not counted as a run
- Ask the scheme question on Custom when the secure-session knob is unticked, and give a tcps:// host the Quickstart trust store guidance, example config, next steps, and checklist items
- Split the DMQ checklist item into the API eligibility flag and the broker-side DMQ, which always stays the developer's responsibility
- Move the HA reconnect values to Delivered only when the HA-failover question is answered yes, matching the JCSMP checklist
@aelsammak
aelsammak requested a review from mtite-sol October 13, 2026 19:29
@aelsammak
aelsammak marked this pull request as ready for review October 13, 2026 19:29
@mtite-sol

mtite-sol commented Oct 14, 2026 •

Copy link
Copy Markdown

Ran the no-broker paths headless (claude -p --plugin-dir on claude-sonnet-5, one run per case, at 61c9d20).

Passed

  • Skip-the-questions gate, Python and JCSMP: derived the summary, took one confirm, wrote no file before it, saved solace-design.md after it, then asked the door question.
  • Persisted-request routing: landed on Guaranteed Pub/Sub (single service, exclusive) with the application correlation id in Consumption endpoint. It never offered Request-Reply (Direct).
  • Both direct leaves went through Implement with no leftover "not yet available" stop.
  • Quickstart and unticked-Custom asked the tcp:// or tcps:// question even with Solace Cloud already in the design. On tcps://, config.example.json carried the trust store key and the close-out gave the Download PEM steps.
  • Custom checklist: 3 knobs on Direct Pub/Sub, 5 on Guaranteed, one multi-select each time.
  • Custom with no knobs kept the 20 × 3000 ms reconnect baseline in code. The admin-provisioned-queue knob dropped CREATE_ON_START and with_subscriptions(...), kept QUEUE_BOUND and MESSAGE_RECEIVED, and left the access-type comment.
  • Per-leaf checklists: Direct Pub/Sub has no queue, respect-ttl, or PUBLISH_ACKED items; Request-Reply has REQUEST_RECEIVED and REPLY_RECEIVED.
  • Request-Reply code: positive REQUEST_TIMEOUT_MS, REQUEST_ATTEMPTS = 2, replier.reply().

Findings

1. The persisted-request route produces a reply leg with no wiring, and new markers
design-mode.md L50 asks the model to record "the answer path" in Consumption endpoint, but no Implement file says how to generate one on a Guaranteed leaf. On Quickstart the model wrote its own:

  • guaranteed_publisher.py subscribes to a per-order direct reply topic.
  • guaranteed_subscriber.py publishes a direct reply after ack().
  • It added three marker strings outside the contract: VERIFY: REPLY_SUBSCRIBED, VERIFY: REPLY_RECEIVED and VERIFY: REPLY_SENT.

Two possible fixes: Implement generates only the request leg (plus the correlation id on the message) and lists the answer path under Developer-owned items, or the answer path gets its own wiring and markers. As written, the design step promises something Implement can't deliver within the contract.

2. Custom describes the unticked HA knob as "fail-fast API defaults"
On both the Direct and the Guaranteed checklists, the knob was described as "tuned reconnect … instead of leaving it at the fail-fast API defaults". The generated code was correct (it kept 20 × 3000 ms), so only the description the developer reads is wrong. The Quickstart-shaped floor paragraph puts the reconnect exception after "Quickstart-shaped", and the knob entry doesn't mention the baseline. Suggest naming it on knob 2: "unticked keeps the samples' 20 × 3000 ms baseline; ticked applies the HA values".

3. Minor: the plaintext Quickstart close-out leaves out the future-tcps:// line
The "if the host later changes to tcps://, set a trust store" line landed in the checklist but not in the chat close-out that implement-mode.md L198 asks for. It was one run, so it may be noise.

- Record only the application correlation id in the design summary, and tell the developer the answer path is theirs to build
- Add a persisted-request variant to the Guaranteed Pub/Sub leaf: the publisher sets CORRELATION_ID, no reply wiring or extra VERIFY markers, and the answer path is listed as developer-owned
- Name the reconnect baseline on the unticked HA knob in the Python and JCSMP Custom modes, so the checklist no longer calls it the fail-fast API defaults
@aelsammak

Copy link
Copy Markdown
Author

PR has been updated @mtite-sol!

@mtite-sol mtite-sol left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@aelsammak
aelsammak merged commit 772d8a7 into dev Oct 14, 2026
4 checks passed
@aelsammak
aelsammak deleted the EBP-3106 branch October 14, 2026 17:29
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.

2 participants