Skip to content

Release/v0.14.0#64

Merged
lchoquel merged 3 commits into
mainfrom
release/v0.14.0
Jul 15, 2026
Merged

Release/v0.14.0#64
lchoquel merged 3 commits into
mainfrom
release/v0.14.0

Conversation

@lchoquel

@lchoquel lchoquel commented Jul 15, 2026

Copy link
Copy Markdown
Member

[v0.14.0] - 2026-07-15

Added

  • Zero-argument demo fallbacks: every demo now runs with zero arguments, falling back to a built-in sample (e.g. samples/sample-invoice.pdf for summarize-pdf) and printing a notice to stderr, so stdout stays pipeable and a fresh clone shows a working result on the first command. read_text_input() gains a sample parameter and returns a TextInput(text, is_sample).
  • Generated typed clients: output models are now generated from .mthds bundles into piper/generated/ via pipelex codegen, replacing hand-written models (generate-image now parses into the generated Image model, replacing the hand-written GeneratedImage). Added make codegen to regenerate clients and templates, and make codegen-check to verify offline (via hashing against each codegen.lock) that generated clients are up to date. Each codegen.lock ships as package data, so the check also works against an installed (wheel) copy, not just a git checkout.
  • New documentation: added docs/cli-architecture.md, describing the copy-paste CLI layout, and docs/codegen.md, explaining the generated-models workflow.
  • Offline smoke tests: added tests/unit/test_generated_clients.py to verify generated modules import correctly, carry the stamp + lock, round-trip their serialization, and match the committed input templates to the CLI's inputs; and tests/unit/test_mode_symmetry.py to guard against drift between CLI modes.
  • Bootstrap validation: /bootstrap now rejects package names that collide with the template's piper placeholder (e.g. piper_tools, which would corrupt into piper_tools_tools under the pyproject transform).

Changed

  • Execution mode is now the command group, not an option (Breaking): --mode, --detach, and the PIPELEX_EXECUTION_MODE env var are gone — invoke the mode explicitly: piper blocking <demo>, piper attended <demo>, or piper detached <demo>. The top-level runs command moves under detached mode (piper detached status|result|wait <id>). There is no default mode anymore; the mode is explicit in every invocation, which is itself the lesson. The middle mode is named attended, not durable, because detached runs are durable too — the axis the names describe is who waits.
  • Typed Image dimensions (Breaking): the generated Image model now uses optional integer width and height fields instead of an untyped size dict, with native field descriptions sourced from the standard's pinned definitions. Regenerated all committed clients (stamps, locks, and fingerprints updated).
  • CLI architecture: each execution mode is now a self-contained, copy-paste unit (piper/<mode>/cli.py) with its own commands, SDK lifecycle helper (execute_pipe / start_and_wait / start_pipe), and progress rendering; lifecycle code is no longer shared. Only mode-orthogonal code remains shared: piper/inputs.py (text/file inputs and document envelopes — piper/file_input.py is merged into it) and piper/errors.py, whose hints now name the mode groups (a blocking run that hits the ~30s cap points at piper attended; an interrupted attended run points at piper detached wait <id>).
  • Structured HTTP errors: protocol-route HTTP errors now parse and surface the API's RFC 7807 problem+json body (title, detail, machine error_type) instead of httpx's stringification, with hints pointing to the correct CLI mode based on error type (e.g. StartRequiresAsyncOrchestration points at piper blocking).
  • E2E tests: end-to-end tests now call the mode lifecycle helpers directly, with one execution mode per demo (extract-entities → blocking, summarize-pdf → attended, generate-image → detached) for full matrix coverage.
  • piper/generated is excluded from ruff (reformatting generated files would trip the drift check) but remains fully type-checked.

Fixed

  • Bootstrap pyproject.toml transform: /bootstrap now rewrites pyproject.toml using generic, context-aware rules (quoted-exact and dotted/path positions) instead of per-key edits, preventing staleness as the package list changes, and correctly handles the multi-line packages array with the piper.generated.* subpackages, quoted package-data keys, and the piper/generated ruff exclude.

Removed

  • Dispatch layer: removed piper/runner.py, the central _dispatch() chain, and the ExecutionMode enum, in favor of the self-contained mode CLIs; piper/cli.py shrinks to a load_dotenv callback plus three add_typer calls.
  • piper/examples/ layer: removed the per-demo wrapper modules; demo logic and inline model narrowing (Model.model_validate(main_stuff)) now live directly in the mode CLI files. The parse() unit tests went with it (they only exercised pydantic's model_validate).
  • piper/file_input.py: merged into the new shared piper/inputs.py module.

🤖 Generated with Claude Code

https://claude.ai/code/session_01AA5fmhTMLRLTJgVmCsW6da

Review in cubic

lchoquel and others added 3 commits July 15, 2026 09:11
…#62)

* feat: generate the typed clients from the bundles via pipelex codegen

Delete the hand-written output models: pipelex codegen projects each method's
concepts into piper/generated/<method>/models.py (stamped, locked by a sibling
codegen.lock); the examples keep only the bundle path, pipe code, and the
parse() narrower. generate-image now parses into the generated built-in Image
model. New make codegen (regen, write-if-changed) + make codegen-check
(offline drift check) targets — the pipelex CLI is not a dependency, point
the PIPELEX make variable at an install that ships codegen; CI wiring is
release-gated on a published pipelex. Adds inputs.template.json scaffolds
beside each bundle, offline smoke tests for the generated clients, and
docs/codegen.md.

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

* fix(devx): Checkpoint C review — ship codegen.lock in wheel + lockstep comments

Cold-review triage: package each codegen.lock as package data so the offline
drift check also works against an installed copy, and cross-reference the three
places the method list is enumerated (piper/methods/*, pyproject packages, the
Makefile codegen targets).

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

* chore(codegen): regenerate typed clients — pinned native definitions + flattened Image

Regenerated with the codegen engine after the native-materialization change: Image now emits width/height integer fields instead of the interim dict-with-imprecision size, and native field descriptions come from the pinned normative definitions (storage-neutral url wording, described Text). Crate fingerprints and stamps updated accordingly; codegen-check green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: changelog — call out the generated Image shape change (width/height)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* chore(Makefile): update PIPELEX_RUN to streamline codegen invocations

* simplify

* feat(cli): update execution modes to use a single --mode option; remove --detach flag

* feat: remove legacy file input and runner modules; introduce new test suite for document input handling

* feat: introduce detached CLI mode for durable runs

- Added `piper.detached` package with CLI commands for starting and managing durable runs.
- Implemented commands: `extract-entities`, `summarize-pdf`, `generate-image`, `wait`, `status`, and `result`.
- Created shared input handling functions in `piper.inputs` for text and document inputs.
- Enhanced error presentation in `piper.errors` to provide mode-specific hints.
- Updated tests to cover the new detached mode and ensure symmetry across CLI modes.
- Refactored existing tests to align with the new structure and added new unit tests for input handling.

* feat: enhance CLI demos to run with zero arguments using built-in samples

- Updated all demo commands to utilize bundled sample inputs when no arguments are provided, ensuring a working result on the first command execution.
- Introduced a `sample` parameter in `read_text_input()` to facilitate this feature.
- Enhanced error handling to surface detailed API error messages instead of generic httpx errors, improving user feedback.
- Refactored execution modes into self-contained units, removing the previous shared dispatch structure for clarity and maintainability.
- Updated documentation to reflect changes in execution modes and sample usage.
- Added tests to verify that demos correctly fall back to sample inputs when no user input is provided.

---------

Co-authored-by: Louis Choquel <8851983+lchoquel@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* feat: generate the typed clients from the bundles via pipelex codegen

Delete the hand-written output models: pipelex codegen projects each method's
concepts into piper/generated/<method>/models.py (stamped, locked by a sibling
codegen.lock); the examples keep only the bundle path, pipe code, and the
parse() narrower. generate-image now parses into the generated built-in Image
model. New make codegen (regen, write-if-changed) + make codegen-check
(offline drift check) targets — the pipelex CLI is not a dependency, point
the PIPELEX make variable at an install that ships codegen; CI wiring is
release-gated on a published pipelex. Adds inputs.template.json scaffolds
beside each bundle, offline smoke tests for the generated clients, and
docs/codegen.md.

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

* fix(devx): Checkpoint C review — ship codegen.lock in wheel + lockstep comments

Cold-review triage: package each codegen.lock as package data so the offline
drift check also works against an installed copy, and cross-reference the three
places the method list is enumerated (piper/methods/*, pyproject packages, the
Makefile codegen targets).

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

* chore(codegen): regenerate typed clients — pinned native definitions + flattened Image

Regenerated with the codegen engine after the native-materialization change: Image now emits width/height integer fields instead of the interim dict-with-imprecision size, and native field descriptions come from the pinned normative definitions (storage-neutral url wording, described Text). Crate fingerprints and stamps updated accordingly; codegen-check green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: changelog — call out the generated Image shape change (width/height)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* chore(Makefile): update PIPELEX_RUN to streamline codegen invocations

* simplify

* feat(cli): update execution modes to use a single --mode option; remove --detach flag

* feat: remove legacy file input and runner modules; introduce new test suite for document input handling

* feat: introduce detached CLI mode for durable runs

- Added `piper.detached` package with CLI commands for starting and managing durable runs.
- Implemented commands: `extract-entities`, `summarize-pdf`, `generate-image`, `wait`, `status`, and `result`.
- Created shared input handling functions in `piper.inputs` for text and document inputs.
- Enhanced error presentation in `piper.errors` to provide mode-specific hints.
- Updated tests to cover the new detached mode and ensure symmetry across CLI modes.
- Refactored existing tests to align with the new structure and added new unit tests for input handling.

* feat: enhance CLI demos to run with zero arguments using built-in samples

- Updated all demo commands to utilize bundled sample inputs when no arguments are provided, ensuring a working result on the first command execution.
- Introduced a `sample` parameter in `read_text_input()` to facilitate this feature.
- Enhanced error handling to surface detailed API error messages instead of generic httpx errors, improving user feedback.
- Refactored execution modes into self-contained units, removing the previous shared dispatch structure for clarity and maintainability.
- Updated documentation to reflect changes in execution modes and sample usage.
- Added tests to verify that demos correctly fall back to sample inputs when no user input is provided.

* fix: address PR #62 review feedback for zero-argument CLI demos

Guards bootstrap against package names that collide with the piper
placeholder, and refines sample-input/error handling in the attended
CLI mode with corresponding test coverage updates.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AA5fmhTMLRLTJgVmCsW6da

* fix: bootstrap rewrites Makefile codegen paths and docs

The bootstrap script's rewrite set never included the Makefile, so the
codegen targets kept pointing at piper/generated and piper/methods after
a rename, breaking make codegen / make codegen-check on bootstrapped
projects. Same gap for the docs under docs/, which went stale. Both are
now in the rewrite set (the generic context-aware token pass handles
their path/command forms), SKILL.md lists them, and a non-dry-run test
asserts the rewritten paths.

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

---------

Co-authored-by: Louis Choquel <8851983+lchoquel@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…structured CLI modes

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AA5fmhTMLRLTJgVmCsW6da
@greptile-apps

greptile-apps Bot commented Jul 15, 2026

Copy link
Copy Markdown

Greptile Summary

This PR reorganizes the CLI around three explicit execution modes and adds generated clients. The main changes are:

  • Adds blocking, attended, and detached command groups.
  • Adds zero-argument demo samples and shared input handling.
  • Adds generated models and offline code-generation checks.
  • Adds structured HTTP error messages.
  • Updates bootstrap rewriting, packaging, documentation, and tests.

Confidence Score: 4/5

The installed zero-argument PDF demo needs a packaging fix before merging.

Source checkouts contain the default invoice, so local runs work. Built wheels do not ship that file at the path used by SAMPLE_INVOICE. The main mode lifecycle and error-handling changes otherwise appear consistent.

piper/inputs.py and pyproject.toml

T-Rex T-Rex Logs

What T-Rex did

  • The wheel was built in a clean environment and the sample-invoice.pdf was found missing from the bundled samples, causing a FileNotFoundError when building the document input.
  • A Python harness was executed to inspect the wheel and exercise the installed document input path, confirming that SAMPLE_INVOICE cannot be resolved due to the missing sample.
  • A reusable wheel build and isolated-install runner was established to enable repeatable repros in future work.
  • The offline-release smoke test log was captured to document the exact test invocation, results, CLI outputs, and exit codes, including the codegen-check blocker.

View all artifacts

T-Rex Ran code and verified through T-Rex

Important Files Changed

Filename Overview
piper/inputs.py Adds shared input handling, but the default PDF sample is unavailable in installed wheels.
piper/blocking/cli.py Adds blocking commands backed by direct SDK execution and generated-model validation.
piper/attended/cli.py Adds durable start-and-wait commands with run recovery guidance.
piper/detached/cli.py Adds detached starts and commands for status, result, and waiting.
piper/errors.py Adds structured problem-response parsing and mode-specific hints.
pyproject.toml Packages the new modules and generated locks, but not the default invoice sample.
.claude/skills/bootstrap/scripts/bootstrap.py Expands placeholder rewriting and rejects package names that collide with the template token.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
CLI[piper CLI] --> B[blocking]
CLI --> A[attended]
CLI --> D[detached]
B --> E[client.execute]
A --> S[client.start]
S --> W[client.wait_for_result]
D --> DS[client.start]
D --> R[status / result / wait]
E --> O[Generated-model JSON]
W --> O
DS --> ID[Run ID]
R --> O
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
CLI[piper CLI] --> B[blocking]
CLI --> A[attended]
CLI --> D[detached]
B --> E[client.execute]
A --> S[client.start]
S --> W[client.wait_for_result]
D --> DS[client.start]
D --> R[status / result / wait]
E --> O[Generated-model JSON]
W --> O
DS --> ID[Run ID]
R --> O
Loading
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
piper/inputs.py:33
**Bundled Sample Is Missing From Wheels**

When `summarize-pdf` runs without an argument from an installed wheel, this path resolves to `site-packages/samples/sample-invoice.pdf`. The sample remains outside the `piper` package and is not declared as package data, so the new zero-argument path raises `FileNotFoundError` instead of running the demo.

Reviews (1): Last reviewed commit: "Release v0.14.0: zero-arg demo fallbacks..." | Re-trigger Greptile

Comment thread piper/inputs.py
# Sample inputs — the zero-argument fallback for each demo (also the README's examples).
SAMPLE_ENTITIES_TEXT = "Alice from Acme met Bob on May 3rd, 2026."
SAMPLE_IMAGE_PROMPT = "a fox reading under a tree"
SAMPLE_INVOICE = Path(__file__).parent.parent / "samples" / "sample-invoice.pdf"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Bundled Sample Is Missing From Wheels

When summarize-pdf runs without an argument from an installed wheel, this path resolves to site-packages/samples/sample-invoice.pdf. The sample remains outside the piper package and is not declared as package data, so the new zero-argument path raises FileNotFoundError instead of running the demo.

Artifacts

Repro: Python harness that inspects the wheel and executes the installed document input path

  • Contains supporting evidence from the run (text/x-python; charset=utf-8).

Repro: reusable wheel build and isolated-install runner

  • Contains supporting evidence from the run (text/x-shellscript; charset=utf-8).

Stack trace captured during the T-Rex run

  • Keeps the raw stack trace available without making the summary code-heavy.

View artifacts

T-Rex Ran code and verified through T-Rex

Prompt To Fix With AI
This is a comment left during a code review.
Path: piper/inputs.py
Line: 33

Comment:
**Bundled Sample Is Missing From Wheels**

When `summarize-pdf` runs without an argument from an installed wheel, this path resolves to `site-packages/samples/sample-invoice.pdf`. The sample remains outside the `piper` package and is not declared as package data, so the new zero-argument path raises `FileNotFoundError` instead of running the demo.

How can I resolve this? If you propose a fix, please make it concise.

@lchoquel lchoquel merged commit 87decbd into main Jul 15, 2026
18 checks passed
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 15, 2026
@lchoquel lchoquel deleted the release/v0.14.0 branch July 15, 2026 09:41
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant