Skip to content

fix(extensions): transport the isolated presentation view validator payload as UTF-8 bytes - #6230

Open
JasonBuildAI wants to merge 1 commit into
loopx-project:mainfrom
JasonBuildAI:codex/ext-helper-stdio-utf8-p4w7
Open

JasonBuildAI wants to merge 1 commit into
loopx-project:mainfrom
JasonBuildAI:codex/ext-helper-stdio-utf8-p4w7

Conversation

@JasonBuildAI

Copy link
Copy Markdown
Contributor

Goal And Delivered Outcome

Author Declaration

Implemented against

Criterion (spec clause) Disposition Symbol / path Test or command
The python -I helper must read its request as UTF-8 bytes regardless of host locale (#6228 expected) implemented loopx/extensions/presentation.py::_ISOLATED_VIEW_VALIDATOR tests/extensions/test_isolated_view_validator_utf8.py::test_generated_helper_transports_utf8_bytes_behind_locale_streams
The response bytes handed back to invoke_runtime_validator must be UTF-8, with no mojibake or lone surrogates (#6228 actual) implemented same tests/extensions/test_isolated_view_validator_utf8.py::test_isolated_validator_round_trips_non_ascii_view_in_runtime
Extension authors can see the isolation contract (python -I ignores PYTHONIOENCODING/PYTHONUTF8; payload crosses stdio as UTF-8 bytes) implemented docs/reference/extensions.md (extension runtime boundary section) review
_RESOLVE_DECLARED_MODULE_ORIGIN, the other successor named by #6168, is unaffected implemented (no change needed) loopx/extensions/readiness.py inspection: it serializes with the json.dump default (ensure_ascii=True), so its output is ASCII-only and locale-safe
  • Self-check before submission: ran the new tests on the unmodified base (2 failed) and on head (2 passed); ran the full tests/extensions suite on base and head and compared failure identities; ran the canary premerge catalog on the diff and re-ran every failing check on the clean base; read the transport owner (run_capped_process call, request encode, response decode) and the readiness helper before writing the issue. Left out: non-Windows non-UTF-8 locales (e.g. LANG=C on Linux) and the CI-only workflows.

Scope And Continuation

  • Completed scope and remaining work: the generated isolated view validator now speaks UTF-8 bytes on both directions; no remaining work identified inside this entrypoint.
  • Slice boundary / successor: N/A - complete within this scope. The readiness helper named by the same fix(extensions): pin bundled extension entrypoint stdio to UTF-8 #6168 note is ASCII-safe as shown above, so no follow-up is needed for it.

Validation

Check kind Result Public-safe evidence / limitation
unit passed New tests/extensions/test_isolated_view_validator_utf8.py (2 tests). Before, on unmodified base adb247e5f: 2 failed (UnicodeDecodeError: 'utf-8' codec can't decode bytes ... invalid continuation byte; ValueError: presentation surface view_validator builtins:str returned invalid output). After: 2 passed.
regression_parity passed Full tests/extensions head vs unmodified base adb247e5f: identical failure/error identity sets (268 unique), head 350 failed, 1018 passed, 63 skipped, 80 errors vs base 350 failed, 1016 passed, 63 skipped, 80 errors; the +2 passed are the new tests. The pre-existing failures are Windows-environment issues (shebang fixtures, missing npm dev dependencies) that fail identically on the base.
static passed ruff check tests loopx/canary loopx/control_plane loopx/domain_packs loopx/presentation (CI lint scope) and the canary direct git diff --check checks.
real_entrypoint passed loopx canary premerge --from-git-diff --git-diff-base upstream/main on head: 11 checks selected, public boundary passed; the 7 failing checks (semantic-vocabulary-drift, cli-project-lifecycle-command-modularization, 5 content-ops-* smokes) fail identically when re-run on the unmodified base worktree for environment reasons (repository npm dev dependencies not installed; host Node 22.2.0 < required 22.22.3).
integration passed tests/test_cli_stdio_utf8.py (3 tests) still passes, exercising the adjacent stdio-pinning contract.
  • Coverage and gaps: the first test simulates a locale-coded stdio pair behind the real transport bytes, so it reproduces the cp936 failure on any host; the second runs the real python -I child through load_presentation_view_validator, so it fails on a cp936 host without the fix and passes with it. Not exercised locally: non-Windows non-UTF-8 locales and CI-only workflows. The envelope-hash/projection write path is covered indirectly (the response equality assertion catches surrogate-corrupted views).

Frontend / Visual Evidence

  • UI impact: none
  • Before: N/A
  • After: N/A
  • States and viewports shown: N/A
  • Source data: none
  • Attention review: N/A - no user-visible surface changes.

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Refactoring (no functional changes)
  • Documentation update
  • Test update

LoopX Area

  • Control plane (goals, todos, quota, scheduler, registry, runtime)
  • Benchmark boundary (adapters, runners, verifiers, scoring, evidence)
  • Capability or extension (providers, adapters, skills)
  • Public docs or presentation surface (README, protocols, dashboard)
  • Build, packaging, installer, or CI
  • Host or runtime integration

Technical Direction

Shared-authority RFC fixture impact

  • Production-scale fixture schema: N/A
  • Semantic dimensions changed, or reviewed no-impact rationale: N/A - no RFC progress claimed.
  • Provider conformance arms run: N/A
  • Read-only legacy/file/PostgreSQL three-arm rehearsal (required for promotion, runtime-routing, or compatibility-projection changes): N/A

Boundary Checklist

  • Neither the diff nor this PR body/comments/attachments disclose private state, credentials, raw traces or verifier output, internal links, or local machine paths (including .loopx/, .codex/goals/, and live ACTIVE_GOAL_STATE.md).
  • I did not duplicate maintainer-owned benchmark work unless a maintainer split out a public issue for it.
  • I kept the change scoped to the linked issue/task.
  • I completed the visual evidence section for UI changes, or marked UI impact none.
  • Every commit includes a DCO Signed-off-by trailer (git commit -s).

…-8 bytes

`load_presentation_view_validator` launches the extension-declared helper as
`python -I -c <helper>` inside the extension's runtime interpreter. `-I`
ignores `PYTHONIOENCODING`/`PYTHONUTF8`, so the helper's `sys.stdin` and
`sys.stdout` fall back to the host locale codec while the transport owner
writes the request as UTF-8 bytes and decodes the response as UTF-8. On a
zh-CN Windows host (cp936) a view with non-ASCII text decodes into mojibake
with lone surrogates; the parent then raises `UnicodeDecodeError` when the
surrogates are re-encoded, or `UnicodeEncodeError` in the envelope hash and
persisted projection when the response survives. Decode and encode the JSON
payload explicitly as UTF-8 bytes in the generated helper and document the
isolation contract.

Signed-off-by: JasonBuildAI <jasonbuildai@gmail.com>

@JasonBuildAI JasonBuildAI left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Independent review record (commissioned by the author)

An independent reviewing agent re-verified this PR from the issue, the diff and its own reproduction on a genuinely affected cp936 host, without relying on the author's summary. Reviewed head: 7535bcef8 (unchanged since).

Six-question verdict:

  1. Value — real, reproducible. The pre-fix failure is deterministic and has no user-side workaround (-I drops PYTHONIOENCODING/PYTHONUTF8). The affected path is shipped production code (validate_provider_presentation_projection -> _runtime_presentation_view_validator, used by publish, status readback and doctor/readiness), so any extension view with non-ASCII text fails on any non-UTF-8-locale host (Windows cp936/cp932/cp949/cp125x). Circumscribed to non-UTF-8 hosts; UTF-8 hosts are unaffected before and after.
  2. Single problem — yes. 3 files, +118/-2: the generated helper transport, one documentation paragraph, one test file. No drive-bys; the semantic-vocabulary probe reports no new vocabulary carriers.
  3. Logic and edge cases — no defect found. -I is the actual launch flag; the byte contract is symmetric (request encoded UTF-8 by the parent, response encoded UTF-8 by the helper, decoded UTF-8 by the parent). Empty stdin, non-UTF-8 stdin and lone-surrogate responses behave as before or better; no missing flush (verified end-to-end).
  4. Over-abstraction — none. Two lines in the generated script plus a comment; the in-process stdio pin cannot be used inside the isolated interpreter (no PYTHONPATH), so local byte handling is the right scope.
  5. Tests — genuine. Test 1 executes the real helper source against forced cp936 streams; it fails on the unmodified base even under -X utf8, so it is a portable guard, not a host artifact. Test 2 runs the real python -I child through the production transport and failed on base with the reported error. The limitation that test 2 alone would pass pre-fix on UTF-8 hosts is disclosed in the PR body.
  6. Local checks — reproduced on both heads. New file: 2 passed on head / 2 failed on unmodified base. tests/test_cli_stdio_utf8.py + tests/extensions/test_extension_provider_stdio_utf8.py: 6 passed. CI lint scope ruff: clean. Full tests/extensions head vs base: failure node-id sets identical (350F/1018P/63S/80E vs 350F/1016P/63S/80E; the +2 passes are the new tests). Validator-adjacent files: 69F/82P/5S on both, failure ids identical (Windows entrypoint_missing environment issues).

Must fix: none. Non-blocking notes: the new test file has no trailing newline (ruff/CI do not flag it); the simulated stdout uses errors="strict" where a real cp936 child uses surrogateescape (immaterial, because the fixed helper bypasses the text layer entirely). Out-of-scope observation for future contract work: a validator that itself prints to sys.stdout corrupts the JSON response both before and after this change, unchanged in kind.

This branch has not been deployed

No deployments
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.

[Bug]: isolated presentation view validator encodes its stdio with the host locale, so non-ASCII views fail on a non-UTF-8 host (cp936)

1 participant