scope = "public-target" is the one predicate that asks somebody else. A forge
that cannot be asked answers nothing, and that answer is currently spelled the
same way as "the policy decided these checks do not apply here".
Repro
A shim scoped public-target and a prevent-unowned-target rule behind it, in a
tree with no remote (or with gh unauthenticated, or offline):
faux issue create --repo other-owner/their-repo -b "An ordinary sentence."
# stderr: uphold shim: no target could be resolved, ... This is not a pass.
# exit 0, the command runs, the issue is opened on somebody else's repository
REFERENCE.md line 1085 and the doc comment on guard::target_refusal
(src/guard/mod.rs:298) both promise exit 2 for a destination that could not be
resolved. Neither is reached: the caller never gets that far.
Cause
Scope::PublicTarget in Shim::scope_holds (src/shim.rs:822) returns
Ok(false) twice: for "no target resolvable" (src/shim.rs:838) and for "the
forge would not say" (src/shim.rs:848). false is "out of scope", so the caller
at src/shim.rs:1953 skips the rule, and guard::target_refusal (which does hold
the exit-2 answer) is never called. The stand-down happens exactly where the
lookup failed, which is the invocation that most needs asking about.
Fix
Three answers rather than two: Holds / DoesNotHold / CouldNotTell. On
CouldNotTell, refuse before exec with exit 2, naming what could not be asked.
A new per-[[shim]] field unresolved = "run" opts back into the old
behaviour, for a workspace whose forge is routinely unreachable; the default is
"refuse". Under "run" the stderr line stays and says the command ran with
nothing checked.
Document it in REFERENCE.md beside the refuse_unknown table, which draws the
same distinction for the same forge lookup, and in the shim's own section. Add
it to the config validation as well: public-target is the only scope that can
answer "could not tell", so the field beside any other scope is read by nothing,
which is the shape [[shim.verbs]] for an unmatched verb is already refused for.
scope = "public-target"is the one predicate that asks somebody else. A forgethat cannot be asked answers nothing, and that answer is currently spelled the
same way as "the policy decided these checks do not apply here".
Repro
A shim scoped
public-targetand aprevent-unowned-targetrule behind it, in atree with no remote (or with
ghunauthenticated, or offline):REFERENCE.md line 1085 and the doc comment on
guard::target_refusal(src/guard/mod.rs:298) both promise exit 2 for a destination that could not be
resolved. Neither is reached: the caller never gets that far.
Cause
Scope::PublicTargetinShim::scope_holds(src/shim.rs:822) returnsOk(false)twice: for "no target resolvable" (src/shim.rs:838) and for "theforge would not say" (src/shim.rs:848).
falseis "out of scope", so the callerat src/shim.rs:1953 skips the rule, and
guard::target_refusal(which does holdthe exit-2 answer) is never called. The stand-down happens exactly where the
lookup failed, which is the invocation that most needs asking about.
Fix
Three answers rather than two: Holds / DoesNotHold / CouldNotTell. On
CouldNotTell, refuse before exec with exit 2, naming what could not be asked.
A new per-
[[shim]]fieldunresolved = "run"opts back into the oldbehaviour, for a workspace whose forge is routinely unreachable; the default is
"refuse". Under"run"the stderr line stays and says the command ran withnothing checked.
Document it in REFERENCE.md beside the
refuse_unknowntable, which draws thesame distinction for the same forge lookup, and in the shim's own section. Add
it to the config validation as well:
public-targetis the only scope that cananswer "could not tell", so the field beside any other scope is read by nothing,
which is the shape
[[shim.verbs]]for an unmatched verb is already refused for.