Repository navigation
fix: name join in YAML/LTL and ArgValue; host install names its binary and its mode - #197
Merged
Merged
Conversation
…y and its mode Three items left over from the kta1kri round-two review. - A rule written as LTL in YAML (`called(Issue_Refund)`, `Var(count, …)`) and the `ArgValue` term keyed on the exact tool spelling, so they missed `issue_refund` and `mcp__finance__issue_refund` while the pattern factories had been canonicalised in a17. The join now lives in `pred_key` / `predKey` for the tool-keyed predicates (`called`, `count`, `consecutive_count`, `arg_value`); grounding writes `arg_value` under every alias and keys its counters canonically, so a stale spelling no longer overwrites a count. `loop_detection` follows a tool across an MCP prefix. - `host install` resolved the hook binary from PATH when invoked by a relative path, which on a machine with a second install wrote that one into the hook; Claude Code runs the tool when a hook exits non-zero. One `resolve_binary` for both installers, resolving argv[0] against the working directory and using the interpreter for a module invocation. - `--mode` wrote `defaults.mode` into the host library, which the hook never read: a default install printed `observe` and blocked anyway. The hook defaults to `enforce` openly; `--mode observe` rides on the hook command as `env SPONSIO_GUARD_MODE=observe …`, where the agent under guard cannot change it. Tests: pytest 3141 passed; TS 124 passed, parity 40 + 39 scenarios. Co-Authored-By: Claude Fable 5.1 <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Three items left over from the kta1kri round-two review (#196). None was in his report; the first is the class he was probing (#2, the name join) on a surface the earlier fixes did not reach, and the other two came up while re-verifying a18 through the real install path.
The name join reaches YAML/LTL atoms, the
ArgValueterm, and loop detectiona17 canonicalised the tool argument inside the pattern factories, so
must_precede("check_policy", "issue_refund")binds every spelling. A rule written as LTL in YAML did not go through a factory:called(Issue_Refund)andVar(count, Issue_Refund)keyed on that exact spelling and missedissue_refund,mcp__finance__issue_refundandfinance__issue_refund. TheArgValueterm (G(!Gt(ArgValue("issue_refund", "amount"), 10))) readarg_value(<exact tool>, field)while grounding wrote it under the raw event name only, so a cap written as a Term passed the MCP-prefixed call with the value unread.The join now lives in
pred_key/predKey, the one function both sides call: forcalled,count,consecutive_countandarg_valuethe tool position is canonicalised. Grounding writesarg_valueunder every alias and keys its counters canonically; keying them by raw spelling put two entries behind one key and the snapshot loop wrote whichever came last, which admitted a thirdrate_limitcall under a new spelling.loop_detectionnow follows a tool across an MCP prefix (search, thenmcp__web__search, used to reset the run) and still resets on a different tool. Two low-level test files that hand-wrotecalled(X)valuations now use lower-case names.sponsio host installnames its own binary_resolve_binaryaccepted an already-absoluteargv[0]and otherwise took whateversponsiowas first onPATH. A relative invocation (./venv/bin/sponsio host install) on a machine with a second install wrote the other binary intosettings.json; on my machine that was a broken Homebrew install, and Claude Code treats a hook that exits non-zero as a non-blocking error and runs the tool. Oneresolve_binaryinhosts.pyserves both installers:argv[0]resolved against the working directory,python -m sponsio.clifor a module invocation,PATHlast.--modeonhost installdoes what it saysIt wrote
defaults.modeinto the host library, which the hook never reads (the hook takesSPONSIO_GUARD_MODE, thenSPONSIO_MODE, thenenforce), so a default install printedRuntime mode: observeand blocked anyway, and--mode enforcewas a no-op. Rather than have the hook honour a file the agent can reach, the mode rides on the hook command:--mode observewritesenv SPONSIO_GUARD_MODE=observe <binary> host guard …(works whether the host shells out or exec()s),enforcewrites the plain command, and a reinstall switches. The installer's default is nowenforce, which is what it always did;sponsio init/onboardkeepobservefor a projectsponsio.yaml, wheredefaults.modeis honoured. The installer no longer stampsmode:into host buckets; an existing line is left alone and ignored, as it always was.Tests
check-ts-parity.shin sync.HOME), parity 40 + 39 scenarios.tests/test_host_install_mode.py(resolver, prefix on both installers, the hook honouring the prefix, defaults);tests/test_fail_open_layer.py(+8 YAML/LTL andArgValuespellings, loop detection across a prefix, counter not overwritten); matching cases infail-open-layer.test.ts.No version bump; this can ride in a19 with whatever else lands.
🤖 Generated with Claude Code