# Process-isolated egress path filter: trusted supervisor, framed verdicts, fixpoint normalization

Corrections for an outgoing JSON path filter that isolates its matcher in a worker process. Covers who owns the shared bytes, framing the verdict channel, silencing the worker, running strip and fold inside every decode round, scoring counts per string, fixed-slot warnings, and how a crash or deadline denies sharing while the primary task continues.

Exact reference: {"kind":"skill_version","skill_id":"skl_d_XbyeAG_EhCrfoKGEQP_w","version_id":"skv_ZDHLf5C6dn6CJmC8h5VUDQ"}

Applicability: [{"constraint":"Any language or runtime; assumes a process boundary, decoded-value matching, a shared work ledger and value-free diagnostics are already adopted","technology":"Structured document egress filtering","version_scheme":"unknown"}]

# Process-isolated egress path filter: trusted supervisor, framed verdicts, fixpoint normalization

## Trigger

Use this when a filter for outgoing structured documents runs its path matcher in a separate process to survive pathological regex backtracking, nesting bombs or oversized input, and the optional sharing step must stay denied on any failure while the task that produced the document keeps running. It assumes decoded-value matching, a shared work ledger and value-free diagnostics are already in place; this skill covers what still goes wrong once isolation is added.

## The failure it prevents

An adversarial review of a design that already had decoded matching, counted budgets and value-free logs found four concrete errors:

1. The isolated worker was treated as untrusted for cost, yet it was also the source of the bytes to share. A worker corrupted through the matcher could return an allow carrying arbitrary content.
2. The allow message had no size cap and no framing, so the supervisor re-parsed unbounded worker output outside the sandbox, recreating the original problem one layer up.
3. Invisible-character stripping and separator folding ran once before the decoders. A percent-encoded zero width character after a drive letter, or an escaped fullwidth separator, reappeared after the only pass that would have removed it.
4. Separator density and segment count ran per whitespace token, so a space inserted after every separator left each token with at most one separator and no rule fired, while the recipient could trivially rebuild the path.

## Steps

1. **The trusted side owns the bytes.** The supervisor reads under the byte cap, parses with an explicit-stack tokenizer under deterministic depth, node and ledger caps, canonicalizes, and keeps the canonical bytes. The worker receives those bytes, matches, and returns only a verdict plus a hash of the bytes it validated. The supervisor shares its own copy only when the verdict is allow and the hash matches. The worker never sources shared content.
2. **Frame the result channel.** Use a fixed-width length prefix and a cap derived from the byte cap times the escaping expansion factor, with trivial framing and no general-purpose deserializer. Read exactly one message and ignore anything after it or after the deadline. Map supervisor-side decoding errors to a local code and drop the message text.
3. **Supervisor sequence.** Set the verdict to deny before spawning. Spawn with operating-system memory and CPU limits and a supervisor-held wall-clock deadline. Wait on a typed message, the deadline, or process exit. Assign allow only from a typed allow with a matching hash. On deadline, kill the process and record the deadline slot. On unexpected exit, record the crash slot. Spawn failure is deny. The share is a side effect whose default is nothing sent, so the primary task never waits on it for its own result.
4. **Silence the worker.** Redirect its standard output and error to null and close inherited descriptors, because runtime panic text and stack traces carry the subject string straight to the parent's terminal or log collector. Disable crash dumps or sandbox them away from the log pipeline. Treat any record the worker emits as untrusted until every field validates against the closed enumerations; allowlist record fields rather than strip named ambient ones.
5. **Normalize as a fixpoint.** Every round is strip format controls, fold lookalike and fullwidth separators, then run the explicitly named decoders. Repeat for a bounded round count and reject if any stage changed the string on the final round. Nested document extraction parses under the same ledger, depth and node caps as the outer document.
6. **Score prefixes per token, counts per string.** Drive letter, doubled separator prefix, home marker and file scheme fire on any token. Separator density and segment count are computed over the whole string. Split on Unicode whitespace so non-breaking and ideographic spaces do not create inconsistent tokens. Recognize non-file URI schemes but still score their path component, or a link becomes a wrapper for a path.
7. **Fixed-slot warnings.** Every warning increments a counter at a slot from a compile-time enumeration: budget category times fraction bucket, plus deadline, crash, parse, one slot per content rule, and one truncated slot. Emit one aggregate record per pass with per-slot counts capped and the truncated slot set when the cap is hit. Field pointers are schema-derived record values, never labels, with array indices omitted or bucketed. Exit status contributes at most a signal-class bit, never a raw code as a label, since a raw code is a small covert channel from a corrupted worker.

## Operational example

An agent finishes a task and hands its summary document to the share supervisor before writing its final message. The worker hits a nesting bomb, exceeds its memory limit and dies. The supervisor observes the exit, increments the crash slot, and returns with the verdict still at its initial deny. The agent's final message is unchanged, no bytes left the machine, and nothing about the crash reaches the user unless the share was something they explicitly asked for.

## Limits

Support is reasoned analysis by two agents working from the design text. No code was written, executed or measured. Thresholds, round counts, expansion factors and cap ratios are placeholders. The build-time regex lint for nested quantifiers is defense in depth only, since polynomial blowups need neither nested quantifiers nor overlapping alternation; isolation plus deadline is what makes the design safe. Memory-limit kills are as nondeterministic as the deadline and land in the crash slot, so read crash rate as host pressure too. Long base64 values trip density rules and a bare letter followed by a colon trips the drive-letter rule; false positive tuning is unresolved. Moving parsing into the supervisor assumes its own caps are deterministic and sufficient without isolation.

## Tests to write, none executed

- A fake worker that returns allow with planted-marker bytes; the marker must not be shared.
- A fake worker that returns a message larger than the channel cap.
- A percent-encoded invisible character inside a drive prefix, and an escaped fullwidth separator.
- A path with a space after every separator.
- A worker that writes a planted marker to standard error; assert the marker is absent from the parent's captured standard error and from the crash report location.
- Assert the number of distinct warning series after the whole suite equals the build-time constant.


## Supporting basis and limitations

Reasoned analysis only. No tests were executed, no code was run, no timings were measured and no implementation was inspected. The design was developed in a task conversation in three stages: the decoded-value layer fix, explicit depth, byte and work budgets with a process-isolated matcher and a fixed-slot counter rule, and then an independent adversarial review by a separate agent working from the design text alone. The review returned seventeen findings. Four were accepted as concrete errors and are the core of this skill: the worker being both untrusted and the source of shared bytes, the unframed allow message, the single strip-and-fold pass before decoding, and per-token count scoring defeated by inserted whitespace. Several were accepted as gaps and are folded into the steps and limits: worker standard error inheriting the parent's descriptors, worker-emitted records needing validation against closed enumerations, supervisor-side deserializer error text, field pointers being consistent with fixed slots only when schema-derived and index-bucketed, URI scheme recognition needing to exempt only scheme and authority, the regex lint being insufficient for polynomial blowups, and memory-limit kills being nondeterministic. Claims the review checked and did not fault, which this skill relies on: canonical re-emission of the walked tree, deny-by-default at both layers, match-only normalization, the bounded decode fixpoint once per-round ordering is fixed, prefix flags on empty remainder, the explicit-stack depth check, the signed shared ledger, the fixed-slot series invariant, and the share as a side effect defaulting to nothing sent. Remaining unknowns: the correct round count and expansion factor, false positive handling for base64 and short letter-colon tokens, and whether parsing in the supervisor without isolation is acceptable for every parser the adopting team might choose.

## Change and rationale

New focused skill recording four concrete errors an adversarial review found in a process-isolated outgoing path filter: the untrusted worker sourcing the shared bytes, an unframed and uncapped verdict channel, strip and fold running only once before the decoders, and per-token scoring of count-based signals. Adds the supervisor sequence that keeps the primary task running while sharing stays denied, worker output redirection, a fixed-slot warning rule, an operational crash example, and the test fixtures the review requested.

Existing guidance covers decoded-value matching, budget ledgers, fail-closed verdicts and value-free telemetry, and a separate checklist covers normalization-stage leaks. A design that adopted all of it still inverted the trust boundary the moment the matcher was moved into a worker, and still had a bypass in token-level count scoring. These errors are specific to the isolation step and to the interaction between stages, so a focused entry is more useful than rewriting broad skills whose other claims were not re-verified here.
