RuleSpoolfor OpenCode 2
RULESPOOL / NOTE 04UPDATED October 25, 2026

One request can carry more than one resource.

A patch that touches a source file and a protected file is still one operation. Inspecting only its first path can hide the reason it stops.

The two-path patch

Choose “A patch touches two paths”. Its agent rules allow edits generally, then deny edits under secrets/*. The selected request contains src/signup.ts and secrets/test.env. Use the resource menu to follow each path through the same tape.

The source path resolves to allow. The secrets path resolves to deny. The whole supplied request therefore denies, and the approval stage is skipped. The separate source-only case remains allow. Keeping both cases prevents a broad change from looking successful just because one troublesome path stopped prompting.

Inspect the trace, not just the stamp

“See every match” lists each rule's action match and resource match. A resource match alone is insufficient when the action does not match. The last rule that matches both controls that resource. The lower stamp summarizes all resources in the request.

When no configured result denies, saved approvals are added and the remaining resource results are combined. Any ask makes the request ask; otherwise the pre-hook aggregate is allow. This describes the pinned source stage, not a guarantee that your installed runtime proceeds.

Empty resources are a real edge case

An empty array is different from a missing or malformed array. The pinned source accepts resources: [] and its aggregation reaches allow before hooks when the relevant runtime state is successfully available. No individual resource was checked. RuleSpool displays that condition explicitly rather than inventing a wildcard resource.

A missing resources field, a string instead of an array, or an array containing non-string entries is rejected. Imported literal empty strings remain literal empty strings. The request editor uses a JSON array so embedded newlines and exact whitespace can be retained.

Use actual scanner output

A compound shell command may yield several native resource strings. This site does not split a raw shell script and pretend the pieces are authoritative. Capture the runtime request, preserve its action and resources, and label it copied. Keep invented edge cases labeled synthetic alongside it.

The permitted neighbour belongs in the same review.

Suppose the goal is to edit documentation while keeping secret files protected. A useful synthetic request set includes docs/start.md, secrets/test.env, and a request containing both paths. Looking only at the denied case can hide a rule that blocks all useful work; looking only at the allowed case can hide a protected-path exception.

Ordered rules for this thought experiment:
1. edit / *              → ask
2. edit / docs/*         → allow
3. edit / secrets/*      → deny

Request A: ["docs/start.md"]                    → allow
Request B: ["secrets/test.env"]                 → deny
Request C: ["docs/start.md", "secrets/test.env"] → deny
Request D: ["src/main.ts"]                      → ask

These are synthetic resource strings, not a claim about a captured runtime request. The four requests test distinct commitments: a narrow grant, a protected path, a mixed operation and work outside the grant. Keep all four when reviewing a change to the tape.

Two edits that look like a fix.

Appending edit / * → allow after these rules makes the earlier secret-path denial lose at the matching stage. It also changes the unrelated source file from ask to allow. That may remove a prompt, but it changes two security decisions beyond the documentation task. Moving the broad ask rule to the end instead makes every matching edit ask, including the protected path; it has not preserved the explicit deny.

A narrower change should be evaluated against the exact new requirement. For example, adding a second documented subdirectory to an allow rule is a different request from allowing all edits. Keep the protected and unrelated cases unchanged while examining the intended new path. Do not rely on the colors of the final stamp without reading which rule supplied each result.

Carry the boundary into native testing.

The official V2 permission description documents ordered matching and aggregation across resources. RuleSpool’s supplied-request trace starts after the runtime has identified those resources. Shell scanning, external-directory checks, plugin hooks and configuration layers can introduce additional boundaries.

For a copied native request, retain its complete resource array, platform and resolved rule layers. Compare it with a deliberately synthetic neighbour that differs in only one path. If native behavior and the local trace differ, investigate the missing boundary before broadening permissions. “Both paths passed separately” is not evidence that the combined operation reached the same approval stage.

Behavior is checked against the pinned aggregation; official action resources describe the runtime inputs.