Expand description
P5-1 (COMPOSABLE-HARNESS-DESIGN.md §2.2 conflict C5, §5.3 risk 1, §4.4 oc-parity): oc/cx import translators. When importing/emulating a last-match-wins rule set (opencode’s native algebra — oc§4:239-241), this module translates it into the engine’s first-match deny→ask→allow form and EMITS A WARNING on every pattern whose translated fixed point differs from the source’s — the risk-1 mitigation verbatim (“import-time translators emit warnings on any rule whose translated fixed point differs”).
Algorithm. Last-match-wins over an ordered list [r1, r2, …, rn]
means: for a given probe, the LAST rule in the list whose pattern matches
it determines the outcome. The target engine has no notion of “position”
at all — it has three FIXED-PRIORITY tiers (deny, then ask, then allow).
There is no general position-preserving translation between the two
algebras (§4.4’s own gap ledger: “adversarial user rule sets exploiting
last-match order … have no first-match equivalent”), so this module does
the next best thing, and does it HONESTLY:
- Resolve each DISTINCT pattern to its own last-match answer (identical patterns repeated: the last occurrence wins; this is just last-match applied to the degenerate single-pattern case).
- Bucket every resolved pattern into the target’s deny/ask/allow tier by
that answer — a first, “naive”
RuleSet. - For every DISTINCT pattern, simulate what the ORIGINAL source list
would decide for a probe equal to that pattern (a true last-match
walk, so cross-pattern glob overlap — e.g. a
"*"rule interacting with a more specific one — is honored, not just same-literal-pattern repeats) and what the naive targetRuleSetfrom step 2 decides for the SAME probe (a true first-match deny→ask→allow evaluation). - Where they agree: no warning, nothing to fix.
- Where they disagree: ALWAYS warn (recording the divergence — the
risk-1 mitigation’s actual requirement). If the target’s answer is
STRICTER (or equal) than the source’s, the divergence is safe-direction
(exactly oc-parity’s named
.env.examplecase, §4.4) and the target’s stricter reading is KEPT. If the target’s answer is MORE PERMISSIVE than the source’s — an unsafe divergence — the pattern is forcibly reassigned to the source’s (stricter) tier before returning, sotranslate_last_match_to_first_matchcan never silently hand back a ruleset more permissive than the one it was asked to translate.
Structs§
- Source
Rule - One rule in the SOURCE (last-match-wins) ordering.
- Translated
- The result of a translation: the target
RuleSet(safe by construction — see the module doc’s step 5) plus one warning string per pattern whose fixed point differed from the source, safe or not.
Functions§
- opencode_
default_ policy - opencode’s documented DEFAULT policy (oc§4 “Default policy”:
{"*": allow}with carve-outsdoom_loop: ask,external_directory: ask,question: deny,plan_enter/plan_exit: deny,read {*.env: ask, *.env.*: ask, *.env.example: allow}), rendered into this engine’s pattern syntax and run throughtranslate_last_match_to_first_match— the worked example design §4.4 specifies and this build reproduces. - translate_
last_ match_ to_ first_ match - Translate
source(last-match-wins order, first rule = lowest priority) into a first-match deny→ask→allowRuleSet— see the module doc for the algorithm and its safety guarantee.