sethjuarez/web - #89
Merged
Merged
Conversation
Seth Juarez (sethjuarez)
added a commit
that referenced
this pull request
Aug 6, 2026
Upstream fix: typra #89 — the Rust backend honoured @entryShorthand on load but never on save, writing a name-keyed collection entry in expanded form where the other six backends wrote the shorthand scalar. Generated delta is small and Rust-only: 3 source files plus the export surface manifest, +30 lines. The new code is a guarded save-side branch: if ctx.use_shorthand && item_data.len() == 1 { ... } Measured — every runtime matches the 0.4.28 baseline exactly, zero delta: Rust cd runtime/rust && cargo test --workspace --no-fail-fast 1147 passed / 0 failed C# cd runtime/csharp && dotnet test prompty.sln --nologo 1356 passed / 0 failed (46 skipped) TypeScript cd runtime/typescript && npm test 1734 passed / 0 failed (17 skipped) Python cd runtime/python/prompty && uv run pytest tests/ -q 1484 passed / 0 failed (17 skipped) Go cd runtime/go/prompty && go test -count=1 ./... ok Pin and regeneration travel together in one commit, as with 0.4.28. The schema-repro-check workflow regenerates from the pinned emitter and fails on a dirty tree, so a bump without regeneration is not a valid intermediate state. This is a deliberate deviation from the separate-commits rule. Verified but NOT fixed here — recorded so it is not rediscovered: The new save-side shorthand is unreachable in prompty, and its target field disagrees with the load side. 1. Reachability. The gate requires item_data.len() == 1. Property always serialises `kind` and `enumValues` (as "" and [] when unset), so the length is never 1. A probe over four input shapes produced no shorthand save in either Rust or Python; both emit byte-identical expanded form: {"city": "Seattle"} -> {"kind":"string","default":"Seattle","enumValues":[]} {"city": {"example": "..."}} -> {"kind":"","example":"Seattle","enumValues":[]} So prompty cannot serve as the regression lock for typra #89. 2. Target mismatch. schema/model/core/properties.tsp:15 declares @entryShorthand("default"), and loading a shorthand scalar does place the value in `default` — asserted by the string_scalar_in_name_keyed_inputs_infers_property vector. But every backend's save-side shorthand reads `example`, which is the @Coerce target from properties.tsp:18/24/31/37, not the @entryShorthand target: Rust model/core/property.rs item_data.get("example") Go model/property.go copy["example"] TS core/property.ts:8 shorthandProperty = "example" C# core/Property.cs:29 ShorthandProperty => "example" Uniform across backends, so this is not a cross-runtime divergence — but load and save name different fields. Were the length gate ever satisfied, a Property carrying only `example` would save as a bare scalar and reload with that value in `default`. Reported upstream; not actionable here while unreachable. Also verified: regeneration is idempotent at this pin (a second `npm run generate` leaves the tree clean), and the pin is exact rather than a caret so `npm ci` cannot silently absorb a future publish. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Seth Juarez (sethjuarez)
added a commit
that referenced
this pull request
Aug 6, 2026
The Python package could not be installed from a clean environment. This
was not a CI flake; `uv pip install -e .` failed outright, and every green
Python number this branch has reported was measured in a virtualenv that
predated the generated pipeline ports.
Reproduced before changing anything, in a fresh venv:
uv venv <tmp> && uv pip install --python <tmp>/Scripts/python -e .
-> File ".../prompty/model/pipeline/_EnginePermissionPort.py", line 10
from prompty.core.cancellation import CancellationToken
ModuleNotFoundError: No module named 'prompty'
Mechanism: pyproject declares `dynamic = ["version"]`, so flit resolves
__version__ by loading prompty/__init__.py through spec_from_file_location.
That executes the package without putting its parent directory on sys.path,
so relative imports resolve and absolute self-imports do not. The four
generated runtime-cancellable ports were the only absolute self-imports in
the package:
model/pipeline/_EnginePermissionPort.py
model/pipeline/_EnginePostCommitPort.py
model/pipeline/_EngineToolPort.py
model/pipeline/_Executor.py
Each already imported its generated siblings relatively (`from ..agent._Prompty
import Prompty`) and only the cancellation token absolutely, so the file was
internally inconsistent — the same two-halves-disagreeing shape as typra #78,
#87 and #89.
Fix is configuration, not an emitter change. `cancellationTokenPath` is an
existing emit-target option; the emitter only splits it on the last dot
(python/emitter.js:107-118), so a relative dotted path passes through intact.
Generated ports live at prompty/model/pipeline/, so `...` is the package root.
Not escalated to typra, because the cheap experiment settled it: one config
line and a regeneration, versus an emitter release. Worth recording for them
anyway that the default is absolute and that the adjacent context import in
the same function is already depth-aware (`group ? ".." : "."`) while the
cancellation import is not — so the default will keep breaking any consumer
whose packaging imports the module. That is an upstream defect; it is simply
not one we need a release for.
Verified in a clean venv, which is the environment that previously failed:
uv pip install -e ".[dev,all]" ok
python -c "import prompty" ok (2.0.0b3)
ruff check . All checks passed
python -m pytest tests/ -q 1484 passed, 17 skipped, 0 failed
Same 1484 as before, but now reproducible from the manifest rather than from
a pre-existing local virtualenv.
Regeneration remains idempotent: a second `npm run generate` leaves the tree
clean, so the reproducibility gate still holds. Schema config and its
regeneration travel together for that reason.
Not verified: Rust, C#, TypeScript and Go were not re-run. This change is
scoped to the Python emit target and touches no other runtime's output.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.