diff --git a/README.md b/README.md index 126f6b3..b660528 100644 --- a/README.md +++ b/README.md @@ -594,13 +594,17 @@ Node-based `PreToolUse.cjs` bridge on Windows), then add this command hook to { "hooks": { "PreToolUse": [{ - "matcher": "^Bash$", + "matcher": "^run_shell_command$", "hooks": [{"type": "command", "command": "/path/to/PreToolUse"}] }] } } ``` +The matcher uses Qwen's runtime shell tool ID. Compatibility aliases such as +`Bash` match exactly; anchoring that alias as `^Bash$` does not select the shell +tool. + Qwen sends the native JSON payload on standard input. The bridge returns its native structured allow or deny decision and preserves the Controller reason. See the official diff --git a/cmd/pitot/wire.go b/cmd/pitot/wire.go index 690686e..63c5b6a 100644 --- a/cmd/pitot/wire.go +++ b/cmd/pitot/wire.go @@ -117,7 +117,7 @@ func printWiringGuidance(host string, stdout io.Writer) error { guidance := map[string]string{ "devin": "no hook configuration is required. Run:\n\n pitot dev --host devin -- devin -p \"\"\n\nFor a separately managed runtime, use:\n\n pitot acp devin --runtime \"$PITOT_RUNTIME\" --prompt \"\"", "kimi": "add to ~/.kimi-code/config.toml (or $KIMI_CODE_HOME/config.toml):\n\n [[hooks]]\n event = \"PreToolUse\"\n matcher = \"Bash\"\n command = \"pitot hook kimi\"", - "qwen": "add to ~/.qwen/settings.json under hooks.PreToolUse:\n\n {\"matcher\": \"^Bash$\", \"hooks\": [{\"type\": \"command\", \"command\": \"\"}]}", + "qwen": "add to ~/.qwen/settings.json under hooks.PreToolUse:\n\n {\"matcher\": \"^run_shell_command$\", \"hooks\": [{\"type\": \"command\", \"command\": \"\"}]}", "copilot": "add to ~/.copilot/settings.json under hooks.PreToolUse:\n\n {\"matcher\": \"Bash\", \"hooks\": [{\"type\": \"command\", \"command\": \"\"}]}", "opencode": "register the OpenCode 2 plugin directory in ~/.config/opencode/opencode.json:\n\n {\"plugins\": [\"file:///\"]}", "pi": "copy integrations/pi/pitot.ts into ~/.pi/agent/extensions/ (or the repo's .pi/extensions/)", diff --git a/cmd/pitot/wire_test.go b/cmd/pitot/wire_test.go index 4abe40e..189127e 100644 --- a/cmd/pitot/wire_test.go +++ b/cmd/pitot/wire_test.go @@ -5,6 +5,7 @@ import ( "encoding/json" "os" "path/filepath" + "regexp" goruntime "runtime" "strings" "testing" @@ -183,6 +184,42 @@ func TestWireHostGuidanceAndFlagRules(t *testing.T) { } } +func TestWireQwenGuidanceSelectsRuntimeShellTool(t *testing.T) { + t.Chdir(t.TempDir()) + out, err := runInitHost(t, "qwen") + if err != nil { + t.Fatal(err) + } + var entry struct { + Matcher string `json:"matcher"` + Hooks []struct { + Type string `json:"type"` + Command string `json:"command"` + } `json:"hooks"` + } + found := false + for _, line := range strings.Split(out, "\n") { + if strings.HasPrefix(strings.TrimSpace(line), "{") { + if err := json.Unmarshal([]byte(line), &entry); err != nil { + t.Fatal(err) + } + found = true + } + } + if !found || entry.Matcher != "^run_shell_command$" || len(entry.Hooks) != 1 || entry.Hooks[0].Type != "command" || !strings.Contains(entry.Hooks[0].Command, "integrations/qwen/PreToolUse") { + t.Fatalf("invalid Qwen shell hook guidance: %s", out) + } + matcher := regexp.MustCompile(entry.Matcher) + for tool, want := range map[string]bool{"run_shell_command": true, "read_file": false, "monitor": false, "run_shell_command_extra": false} { + if got := matcher.MatchString(tool); got != want { + t.Errorf("matcher %q selects %q: got %v, want %v", entry.Matcher, tool, got, want) + } + } + if entries, err := os.ReadDir("."); err != nil || len(entries) != 0 { + t.Fatalf("user-level guidance wrote files: %v (error: %v)", entries, err) + } +} + func TestWireOpenCodeGuidanceUsesAPluginDirectory(t *testing.T) { t.Chdir(t.TempDir()) out, err := runInitHost(t, "opencode") diff --git a/tests/endpoint-provenance.json b/tests/endpoint-provenance.json index 0378393..5f5b5dc 100644 --- a/tests/endpoint-provenance.json +++ b/tests/endpoint-provenance.json @@ -1564,531 +1564,531 @@ "artifacts": [ { "agent": "claude", - "archive_sha256": "7ad0439e08756543d13d56d4290d73d69f4f8417b6d5d574d2565d941c67b195", - "artifact_id": 11789380313, + "archive_sha256": "99078aa5e0efd9ec2823027516915704056157d8f7aac2faba2656ad4b0ea7cc", + "artifact_id": 11792147264, "capture_sha256": "6eb5f870d6d9eec0fd8bdfce34693ce86e057feb07df5aa9a4af3f3bd706ea8c", - "check_run_id": 115126832928, + "check_run_id": 115154313535, "conclusion": "success", - "job_id": 115126832928, + "job_id": 115154313535, "platform": "macos", "runner": "macos-latest", - "runner_id": 1000035485, + "runner_id": 1000035622, "runner_labels": [ "macos-latest" ], - "runner_name": "GitHub Actions 1000035485" + "runner_name": "GitHub Actions 1000035622" }, { "agent": "claude", - "archive_sha256": "1b07ebe545d4897ef10d19a54916c1087be97099f3372ac3997a4b47948da9c1", - "artifact_id": 11789265199, + "archive_sha256": "ae2626154f81705dc335f8d245deb189fe346a0e9a8f531eb5a9b33ffa90de6e", + "artifact_id": 11792501139, "capture_sha256": "21fa65e59854f6623ddc764b14463d23d1bf87527e4a4173501a0dc354a7dce9", - "check_run_id": 115126833127, + "check_run_id": 115154312953, "conclusion": "success", - "job_id": 115126833127, + "job_id": 115154312953, "platform": "ubuntu", "runner": "ubuntu-latest", - "runner_id": 1000035479, + "runner_id": 1000035597, "runner_labels": [ "ubuntu-latest" ], - "runner_name": "GitHub Actions 1000035479" + "runner_name": "GitHub Actions 1000035597" }, { "agent": "claude", - "archive_sha256": "20b0e44e252cc6e9559315b2c00d88faa1a9becdd22ff8f7208f85ec4783f383", - "artifact_id": 11789330077, + "archive_sha256": "77c85d56b9514f00b0c3925d6e8aa3dd83ca23db2c263aab69c36391b07deff4", + "artifact_id": 11791834756, "capture_sha256": "de00faa86bcc17a3858475a91044c6a28b24a1af11650bb7758044643de2aa1f", - "check_run_id": 115126833207, + "check_run_id": 115154313210, "conclusion": "success", - "job_id": 115126833207, + "job_id": 115154313210, "platform": "windows", "runner": "windows-latest", - "runner_id": 1000035478, + "runner_id": 1000035606, "runner_labels": [ "windows-latest" ], - "runner_name": "GitHub Actions 1000035478" + "runner_name": "GitHub Actions 1000035606" }, { "agent": "codex", - "archive_sha256": "675b2fc462c858a444368d4c5bdc938dd25bca6c8185b72cd25eae48361cf0a5", - "artifact_id": 11788950380, + "archive_sha256": "ff29d6cf96195d3ce3a9e81061aedef0d66611420ecd390d0d2ecc0e2d8a32ce", + "artifact_id": 11792436724, "capture_sha256": "5e39c8858cfe781d5febb081b393afd0c385a73c33bf6609ca7d7b5a4749852e", - "check_run_id": 115126832959, + "check_run_id": 115154313328, "conclusion": "success", - "job_id": 115126832959, + "job_id": 115154313328, "platform": "macos", "runner": "macos-latest", - "runner_id": 1000035482, + "runner_id": 1000035616, "runner_labels": [ "macos-latest" ], - "runner_name": "GitHub Actions 1000035482" + "runner_name": "GitHub Actions 1000035616" }, { "agent": "codex", - "archive_sha256": "b91a280b11e0c72368699546c9e926fb7d639577984b6d10fadd2d870a74c960", - "artifact_id": 11788613795, + "archive_sha256": "b49b5d4aeb5b51da8757cbdb2024b8f80880d8660a378bf2968591743045ad6a", + "artifact_id": 11792775343, "capture_sha256": "a45c25b9a94213356abc092f187117258099981423758f74e27cf6398efea157", - "check_run_id": 115126832738, + "check_run_id": 115154313073, "conclusion": "success", - "job_id": 115126832738, + "job_id": 115154313073, "platform": "ubuntu", "runner": "ubuntu-latest", - "runner_id": 1000035470, + "runner_id": 1000035605, "runner_labels": [ "ubuntu-latest" ], - "runner_name": "GitHub Actions 1000035470" + "runner_name": "GitHub Actions 1000035605" }, { "agent": "codex", - "archive_sha256": "aa38a711b6fd47684b80a3947447b1b4aefa9fdda73082629bf99e5b84ba2bf7", - "artifact_id": 11788950195, + "archive_sha256": "39b2b66f9c35ad5bb60323fbbec480b24235f4f0db9df2bdd647b16c01e74531", + "artifact_id": 11791957270, "capture_sha256": "1f90c8f26662b2532208cf6abe8bc263e22cadc0a05fd966dc5cfe13652afb5c", - "check_run_id": 115126832980, + "check_run_id": 115154313309, "conclusion": "success", - "job_id": 115126832980, + "job_id": 115154313309, "platform": "windows", "runner": "windows-latest", - "runner_id": 1000035474, + "runner_id": 1000035602, "runner_labels": [ "windows-latest" ], - "runner_name": "GitHub Actions 1000035474" + "runner_name": "GitHub Actions 1000035602" }, { "agent": "copilot", - "archive_sha256": "981612914a20895f6ae41a7e3e401ba5df092ce9c8909550413bf752f3f10ce1", - "artifact_id": 11788289925, + "archive_sha256": "844083dd8187b667360c41e86b3ed4222cbdfbb7bc41209e5458955486a9450b", + "artifact_id": 11792321923, "capture_sha256": "c922e1edecb25cf7909b1fdb0bf8144a7c05ea841ad2315f5fc7656873571dd8", - "check_run_id": 115126833030, + "check_run_id": 115154313050, "conclusion": "success", - "job_id": 115126833030, + "job_id": 115154313050, "platform": "macos", "runner": "macos-latest", - "runner_id": 1000035483, + "runner_id": 1000035618, "runner_labels": [ "macos-latest" ], - "runner_name": "GitHub Actions 1000035483" + "runner_name": "GitHub Actions 1000035618" }, { "agent": "copilot", - "archive_sha256": "cd927956ba4c4c6f7c6edf8f5155d3a605236fa280e63b73f012105334a1a347", - "artifact_id": 11788825326, + "archive_sha256": "883a7cfc1b2273af5699b0debaf196fc0944be552131cc0bfcb01dcf14e4ca2d", + "artifact_id": 11791794931, "capture_sha256": "d17ae1033aafd6c8c7eb5ee2cf2cb134a661ecc37944169574d60806038fa103", - "check_run_id": 115126832820, + "check_run_id": 115154313533, "conclusion": "success", - "job_id": 115126832820, + "job_id": 115154313533, "platform": "ubuntu", "runner": "ubuntu-latest", - "runner_id": 1000035463, + "runner_id": 1000035617, "runner_labels": [ "ubuntu-latest" ], - "runner_name": "GitHub Actions 1000035463" + "runner_name": "GitHub Actions 1000035617" }, { "agent": "copilot", - "archive_sha256": "35017f5f2146ff97da291fa79838cb4a7e29a8a9c8395423e4bef3550df0c7a6", - "artifact_id": 11788514117, + "archive_sha256": "880b9b7cfbb01f4dedf61156012f70924ddb6d16e5dffb7906162d5af28026a4", + "artifact_id": 11791904023, "capture_sha256": "01594240b7ce34526bf7ccbc15bcf9f2ba4b2fff552d6e949c501720df7a0868", - "check_run_id": 115126832521, + "check_run_id": 115154313227, "conclusion": "success", - "job_id": 115126832521, + "job_id": 115154313227, "platform": "windows", "runner": "windows-latest", - "runner_id": 1000035458, + "runner_id": 1000035607, "runner_labels": [ "windows-latest" ], - "runner_name": "GitHub Actions 1000035458" + "runner_name": "GitHub Actions 1000035607" }, { "agent": "cursor", - "archive_sha256": "92c06003012f277c0b1ba099a46ac4442b84a42133ca013ff2f761f07dbfd827", - "artifact_id": 11789245348, + "archive_sha256": "61a28e8b4cafe56dca6d91410c1b6053623b661aab4bebd17c0de3d23cb234ff", + "artifact_id": 11792925010, "capture_sha256": "45b8810fda9834e0a492a9926dffb9be57ee1338d513286ef17d3abe005751b2", - "check_run_id": 115126832785, + "check_run_id": 115154313127, "conclusion": "success", - "job_id": 115126832785, + "job_id": 115154313127, "platform": "macos", "runner": "macos-latest", - "runner_id": 1000035484, + "runner_id": 1000035604, "runner_labels": [ "macos-latest" ], - "runner_name": "GitHub Actions 1000035484" + "runner_name": "GitHub Actions 1000035604" }, { "agent": "cursor", - "archive_sha256": "fc1287dd8d8d7300b20929566ab95d766aefe7079795b5762be58a23d853bd79", - "artifact_id": 11789205399, + "archive_sha256": "0a54f7495df21747c13569e401ad85ef4ea7bd3161d5182bfa15855879051ccb", + "artifact_id": 11792097041, "capture_sha256": "e10c16ce205909adef763903de2d0ac84eabb2e1b496347992ad3c3360213908", - "check_run_id": 115126833110, + "check_run_id": 115154313343, "conclusion": "success", - "job_id": 115126833110, + "job_id": 115154313343, "platform": "ubuntu", "runner": "ubuntu-latest", - "runner_id": 1000035480, + "runner_id": 1000035615, "runner_labels": [ "ubuntu-latest" ], - "runner_name": "GitHub Actions 1000035480" + "runner_name": "GitHub Actions 1000035615" }, { "agent": "cursor", - "archive_sha256": "16db3158f58dc0f33902fce1cf80cb5efb948abb1a27e0c4956e83ffe1e1772b", - "artifact_id": 11789310061, + "archive_sha256": "75f353f07826a8d810a91998b50283a3ba49f3e94c20f76c4b12d7cfdb3c2d38", + "artifact_id": 11792655871, "capture_sha256": "b8af04ff98e36d1f956dd00742a51aed5325e2fef51e867edca544ae8da00555", - "check_run_id": 115126832470, + "check_run_id": 115154313344, "conclusion": "success", - "job_id": 115126832470, + "job_id": 115154313344, "platform": "windows", "runner": "windows-latest", - "runner_id": 1000035466, + "runner_id": 1000035611, "runner_labels": [ "windows-latest" ], - "runner_name": "GitHub Actions 1000035466" + "runner_name": "GitHub Actions 1000035611" }, { "agent": "deepseek", - "archive_sha256": "d4c76e718ea4bc48f693cdea928408c53f9e5af72f93e5db3f69460b9996521f", - "artifact_id": 11789215801, + "archive_sha256": "8e5e5161dd3da7460de1f156b8de66c9aa087a400feaf1b39131008583e47753", + "artifact_id": 11792072030, "capture_sha256": "9f36db049a9f7ac3a58356a9aa17e1bc3727e1a41badd1e2e3b3af30491f672c", - "check_run_id": 115126833106, + "check_run_id": 115154312914, "conclusion": "success", - "job_id": 115126833106, + "job_id": 115154312914, "platform": "macos", "runner": "macos-latest", - "runner_id": 1000035487, + "runner_id": 1000035591, "runner_labels": [ "macos-latest" ], - "runner_name": "GitHub Actions 1000035487" + "runner_name": "GitHub Actions 1000035591" }, { "agent": "deepseek", - "archive_sha256": "7b4578203df7dd3ea79d1bca3d627efc8ec5ffc93587a53893bb5ba03184beef", - "artifact_id": 11788623724, + "archive_sha256": "b8038ce4ec09814b84f9d35de92209e753abe211c57d4386174eda163d5b48a1", + "artifact_id": 11791724994, "capture_sha256": "5c08fb7a1644f87521c9321c99b6deca046ba0c46993d7d747f51215c587f4b2", - "check_run_id": 115126832674, + "check_run_id": 115154312928, "conclusion": "success", - "job_id": 115126832674, + "job_id": 115154312928, "platform": "ubuntu", "runner": "ubuntu-latest", - "runner_id": 1000035459, + "runner_id": 1000035594, "runner_labels": [ "ubuntu-latest" ], - "runner_name": "GitHub Actions 1000035459" + "runner_name": "GitHub Actions 1000035594" }, { "agent": "deepseek", - "archive_sha256": "6056f5f9dc1d927acf6d308c613d533bfa1f41c4de5448f3bf177a4a67aa51dd", - "artifact_id": 11789030778, + "archive_sha256": "fd3ff0cdcef9f567686f00dfdeb2428201bddd2069cba3fa1cd1e0e6f700362c", + "artifact_id": 11792396723, "capture_sha256": "5b26b5c0c269b5fd0392a298d3e238da8ea197f382698c5e3df71ab81101f4be", - "check_run_id": 115126833078, + "check_run_id": 115154313313, "conclusion": "success", - "job_id": 115126833078, + "job_id": 115154313313, "platform": "windows", "runner": "windows-latest", - "runner_id": 1000035475, + "runner_id": 1000035608, "runner_labels": [ "windows-latest" ], - "runner_name": "GitHub Actions 1000035475" + "runner_name": "GitHub Actions 1000035608" }, { "agent": "devin", - "archive_sha256": "930479e62c79dd7beb20c93e9c65877b000ed188a6979a79c6c8b2992dbe39f8", - "artifact_id": 11789185028, + "archive_sha256": "d4ad1a6c5e29047d8d2f752dee7b66b2b0ef19cfedcd0a659d24218bd6c1bf46", + "artifact_id": 11792770665, "capture_sha256": "b162effcbc4be932b051e18ae73139dbaa9d4611e7cb1bdf795fd79a1ce24fed", - "check_run_id": 115126832531, + "check_run_id": 115154312880, "conclusion": "success", - "job_id": 115126832531, + "job_id": 115154312880, "platform": "macos", "runner": "macos-latest", - "runner_id": 1000035460, + "runner_id": 1000035590, "runner_labels": [ "macos-latest" ], - "runner_name": "GitHub Actions 1000035460" + "runner_name": "GitHub Actions 1000035590" }, { "agent": "devin", - "archive_sha256": "d6a0c17ee7604296776ed31fcec9e20e653cf5dd7ddb3e0645c9bbae1f57ee70", - "artifact_id": 11789090360, + "archive_sha256": "595213ce04c8c92573e950cbbfa677021160c5994da48ff3f4b537ecb8639421", + "artifact_id": 11792491351, "capture_sha256": "a87dc314284a5502d80d34de2b532667198652a256bcf85e22211e4bd502bf8f", - "check_run_id": 115126832766, + "check_run_id": 115154313384, "conclusion": "success", - "job_id": 115126832766, + "job_id": 115154313384, "platform": "ubuntu", "runner": "ubuntu-latest", - "runner_id": 1000035468, + "runner_id": 1000035613, "runner_labels": [ "ubuntu-latest" ], - "runner_name": "GitHub Actions 1000035468" + "runner_name": "GitHub Actions 1000035613" }, { "agent": "devin", - "archive_sha256": "7edff181104c1a2202f4ca7c7613ff27d95e8adf82baa5af5d52b39012f789db", - "artifact_id": 11788623703, + "archive_sha256": "9228ba6c849aa317e7c8c6a9dbd87d1c9086de99829277e2064005754af7a9ab", + "artifact_id": 11792231818, "capture_sha256": "8b1dbc6de5b80be42494d1b0066082b7e6c99bea96043bae9960409c0dc776d2", - "check_run_id": 115126832767, + "check_run_id": 115154313361, "conclusion": "success", - "job_id": 115126832767, + "job_id": 115154313361, "platform": "windows", "runner": "windows-latest", - "runner_id": 1000035473, + "runner_id": 1000035610, "runner_labels": [ "windows-latest" ], - "runner_name": "GitHub Actions 1000035473" + "runner_name": "GitHub Actions 1000035610" }, { "agent": "gemini", - "archive_sha256": "9ae17d586ae45e159e681fe610131289ec8ae1f3e8700ed82a6464ba129a2e8d", - "artifact_id": 11789225158, + "archive_sha256": "c241f4201c6dcadd407a9ca43a855c9b831e2852b467b56ce83d7e1cdf88287f", + "artifact_id": 11792212075, "capture_sha256": "0b9396676f937c13f30aa871d2874b3f438e1c91b801dcd16264529de39d4762", - "check_run_id": 115126832845, + "check_run_id": 115154312987, "conclusion": "success", - "job_id": 115126832845, + "job_id": 115154312987, "platform": "macos", "runner": "macos-latest", - "runner_id": 1000035486, + "runner_id": 1000035619, "runner_labels": [ "macos-latest" ], - "runner_name": "GitHub Actions 1000035486" + "runner_name": "GitHub Actions 1000035619" }, { "agent": "gemini", - "archive_sha256": "dc5e5865019b7faba43a4437f25a9921516ddf7602ae237e666230dcfcb86f49", - "artifact_id": 11788499106, + "archive_sha256": "d39255bd2e6224cd5790bf98a88443dae471b6e4881019b1798d999849912cfa", + "artifact_id": 11792436433, "capture_sha256": "6cd688f58722a757df69a82543f4c988a5930479012e63baf936a887fa93419d", - "check_run_id": 115126832446, + "check_run_id": 115154313006, "conclusion": "success", - "job_id": 115126832446, + "job_id": 115154313006, "platform": "ubuntu", "runner": "ubuntu-latest", - "runner_id": 1000035455, + "runner_id": 1000035595, "runner_labels": [ "ubuntu-latest" ], - "runner_name": "GitHub Actions 1000035455" + "runner_name": "GitHub Actions 1000035595" }, { "agent": "gemini", - "archive_sha256": "53561ead19e9ccbf66d7c7e73149fb582a2362446cc248c85fedd5645fefc478", - "artifact_id": 11789305300, + "archive_sha256": "390da5c4cf1058eebc4cba05efc0c2ce3f1f63cbaa1361863a99b5edc76ce92e", + "artifact_id": 11792171887, "capture_sha256": "1f6d00cc96e00f3cb972f8e1089b13935ffd149e6b8aa67911848068f77d668b", - "check_run_id": 115126832590, + "check_run_id": 115154312995, "conclusion": "success", - "job_id": 115126832590, + "job_id": 115154312995, "platform": "windows", "runner": "windows-latest", - "runner_id": 1000035456, + "runner_id": 1000035600, "runner_labels": [ "windows-latest" ], - "runner_name": "GitHub Actions 1000035456" + "runner_name": "GitHub Actions 1000035600" }, { "agent": "kimi", - "archive_sha256": "4b5968f95395a4c7ac58b32bb3309f18e9f6bde76e06bbfd70ede33ce6ab3c5d", - "artifact_id": 11788633834, + "archive_sha256": "ecd7ce0e51010e6eaac01e6e27b9abcef5c29b5582b91bcec2ed806446282c69", + "artifact_id": 11791887979, "capture_sha256": "4ca011a5faccac9d135d75220d2738d19a9df347a0b975546c560afff1e0915b", - "check_run_id": 115126832734, + "check_run_id": 115154312990, "conclusion": "success", - "job_id": 115126832734, + "job_id": 115154312990, "platform": "macos", "runner": "macos-latest", - "runner_id": 1000035462, + "runner_id": 1000035609, "runner_labels": [ "macos-latest" ], - "runner_name": "GitHub Actions 1000035462" + "runner_name": "GitHub Actions 1000035609" }, { "agent": "kimi", - "archive_sha256": "fdea84644237c1234e92c8ecdfbc8fe41fcdec188fbcef65542525841adc048b", - "artifact_id": 11788359377, + "archive_sha256": "35d3a1057d4ba2c17cce2f7a72dfb77e724461ebc96d0cac5e9646cd0ddf561d", + "artifact_id": 11792111827, "capture_sha256": "a3c2d0a3c96e99de4f74ad40970e3fb082250efab11cbaeb80b8ecca357c7de4", - "check_run_id": 115126832752, + "check_run_id": 115154313296, "conclusion": "success", - "job_id": 115126832752, + "job_id": 115154313296, "platform": "ubuntu", "runner": "ubuntu-latest", - "runner_id": 1000035464, + "runner_id": 1000035599, "runner_labels": [ "ubuntu-latest" ], - "runner_name": "GitHub Actions 1000035464" + "runner_name": "GitHub Actions 1000035599" }, { "agent": "kimi", - "archive_sha256": "4b7beb07069d36936ad380490e9f2a61308ca03c40ffb7998035c1e8e566be60", - "artifact_id": 11788736137, + "archive_sha256": "02f1fa5914b5400495a7dc62594659978b27723941f78d2c1d89e26d248a87ea", + "artifact_id": 11792476422, "capture_sha256": "08c897a74d0946a64a448578de24169eb65736289fd1eb7222274de539c14c24", - "check_run_id": 115126832423, + "check_run_id": 115154313179, "conclusion": "success", - "job_id": 115126832423, + "job_id": 115154313179, "platform": "windows", "runner": "windows-latest", - "runner_id": 1000035457, + "runner_id": 1000035601, "runner_labels": [ "windows-latest" ], - "runner_name": "GitHub Actions 1000035457" + "runner_name": "GitHub Actions 1000035601" }, { "agent": "opencode", - "archive_sha256": "df3a6fff445f30bbdcbd53b9e3b62c41942dd0a18d019b8a25be06ebe7e43cf5", - "artifact_id": 11789380028, + "archive_sha256": "fcc4ee1b4d5444d4b1596d17224bbeedc73d482cb15ace19af53cc32c2bbf07f", + "artifact_id": 11792945193, "capture_sha256": "0197c1c312d6532e4a8d05dce595bc6a86e3a393ba74b3f8c6a0a1459a1aaf5c", - "check_run_id": 115126832839, + "check_run_id": 115154313149, "conclusion": "success", - "job_id": 115126832839, + "job_id": 115154313149, "platform": "macos", "runner": "macos-latest", - "runner_id": 1000035461, + "runner_id": 1000035596, "runner_labels": [ "macos-latest" ], - "runner_name": "GitHub Actions 1000035461" + "runner_name": "GitHub Actions 1000035596" }, { "agent": "opencode", - "archive_sha256": "1e5eb6f96ba90afa9e0a44b8a5e55cc3bf6fec4025700cd77c5a8577ba4f5a8b", - "artifact_id": 11788394267, + "archive_sha256": "6bca3009d2975eeb175cf865e252a2840e0a8a0a491c668a6b68446950bd0497", + "artifact_id": 11792256627, "capture_sha256": "f9a06f9015188a22a73e7d1717185489dca98151e57448533e53ad05e03810bb", - "check_run_id": 115126832651, + "check_run_id": 115154313103, "conclusion": "success", - "job_id": 115126832651, + "job_id": 115154313103, "platform": "ubuntu", "runner": "ubuntu-latest", - "runner_id": 1000035471, + "runner_id": 1000035598, "runner_labels": [ "ubuntu-latest" ], - "runner_name": "GitHub Actions 1000035471" + "runner_name": "GitHub Actions 1000035598" }, { "agent": "opencode", - "archive_sha256": "905e5d000cdeefe9af0978222d2a83223e87ea83d023778614dd8475c8b4460a", - "artifact_id": 11788469264, + "archive_sha256": "8071e6b46bc74f36a9377b8a0ce97f4125a7aab9440818b5e3706cfc87795d01", + "artifact_id": 11792416724, "capture_sha256": "31ce073b2034222781b9a4519bae2ffd62b72ffe167aa70bc136aae29d55cfe6", - "check_run_id": 115126833095, + "check_run_id": 115154313014, "conclusion": "success", - "job_id": 115126833095, + "job_id": 115154313014, "platform": "windows", "runner": "windows-latest", - "runner_id": 1000035476, + "runner_id": 1000035593, "runner_labels": [ "windows-latest" ], - "runner_name": "GitHub Actions 1000035476" + "runner_name": "GitHub Actions 1000035593" }, { "agent": "pi", - "archive_sha256": "74b5a9b2405512d30afacd9fa4dbb0667dd62664b05fad55ee281233fd85b827", - "artifact_id": 11789025209, + "archive_sha256": "d527908d906d82e67afccff8b6ce104863c02fef534a63cab5d53fcd13e79177", + "artifact_id": 11792496890, "capture_sha256": "f90ded0ea820aaf27a2e025956367f2d4f1c1271a4c8c0797f3ad0975e70f55e", - "check_run_id": 115126832817, + "check_run_id": 115154313406, "conclusion": "success", - "job_id": 115126832817, + "job_id": 115154313406, "platform": "macos", "runner": "macos-latest", - "runner_id": 1000035465, + "runner_id": 1000035621, "runner_labels": [ "macos-latest" ], - "runner_name": "GitHub Actions 1000035465" + "runner_name": "GitHub Actions 1000035621" }, { "agent": "pi", - "archive_sha256": "473e4828685def0bdb5a3254c5632f8add34164efc4f793ddc960779d7aa41c3", - "artifact_id": 11788359457, + "archive_sha256": "af07bc6616a6f1350f97f416ddcec45690ed7582d03881c6163786dc1b5487a3", + "artifact_id": 11792416584, "capture_sha256": "e0316503ed761604e429919e7593590bc1b2f329b13b0c604864ae2a88a3ec87", - "check_run_id": 115126832921, + "check_run_id": 115154312885, "conclusion": "success", - "job_id": 115126832921, + "job_id": 115154312885, "platform": "ubuntu", "runner": "ubuntu-latest", - "runner_id": 1000035481, + "runner_id": 1000035592, "runner_labels": [ "ubuntu-latest" ], - "runner_name": "GitHub Actions 1000035481" + "runner_name": "GitHub Actions 1000035592" }, { "agent": "pi", - "archive_sha256": "c5c14da7ee2409392d5ccf2499c95eb76775ec81a41eec228243ec955edbfcae", - "artifact_id": 11787999813, + "archive_sha256": "81a04b9fe18071ac01443fe99355e06f1fcffd3a91988547b1d088be28aa0ef1", + "artifact_id": 11791942579, "capture_sha256": "453d9e32581184d83cb26ba6b529db15f08662fd17fea6b1cc75f8b49a34c7e4", - "check_run_id": 115126833171, + "check_run_id": 115154313261, "conclusion": "success", - "job_id": 115126833171, + "job_id": 115154313261, "platform": "windows", "runner": "windows-latest", - "runner_id": 1000035477, + "runner_id": 1000035603, "runner_labels": [ "windows-latest" ], - "runner_name": "GitHub Actions 1000035477" + "runner_name": "GitHub Actions 1000035603" }, { "agent": "qwen", - "archive_sha256": "ca0f9c91c4c79e204fa9cd40389e4f42867593b5949bc5b59b5d22383e0b9046", - "artifact_id": 11789190014, + "archive_sha256": "4fff40c9f1e0b771abaa9044476d9c659d0babc1d5665431544d200bb22de364", + "artifact_id": 11792840787, "capture_sha256": "bf800127313bc7c5e43bb483ee6d8cfee8ca53c2057a150ac5e1c939bb7d1336", - "check_run_id": 115126832626, + "check_run_id": 115154313379, "conclusion": "success", - "job_id": 115126832626, + "job_id": 115154313379, "platform": "macos", "runner": "macos-latest", - "runner_id": 1000035472, + "runner_id": 1000035620, "runner_labels": [ "macos-latest" ], - "runner_name": "GitHub Actions 1000035472" + "runner_name": "GitHub Actions 1000035620" }, { "agent": "qwen", - "archive_sha256": "a4dd4387bb0f61e28b3acdba6c28c7b7a7aa526417762f2358a581eb285ee939", - "artifact_id": 11787979734, + "archive_sha256": "ddb49477c3281c85a428cff75b8280f1d2cba6e125654083ce4ae5b7bfe27004", + "artifact_id": 11791879347, "capture_sha256": "0a9133db580f0861d1fe583fbb0fd81196581af4d4141ab793015a1e8ac516de", - "check_run_id": 115126832600, + "check_run_id": 115154313331, "conclusion": "success", - "job_id": 115126832600, + "job_id": 115154313331, "platform": "ubuntu", "runner": "ubuntu-latest", - "runner_id": 1000035469, + "runner_id": 1000035612, "runner_labels": [ "ubuntu-latest" ], - "runner_name": "GitHub Actions 1000035469" + "runner_name": "GitHub Actions 1000035612" }, { "agent": "qwen", - "archive_sha256": "e733360ea79919201e6394ee022f21629636a5aa8ce9b136ddb07769f80fe362", - "artifact_id": 11788329486, + "archive_sha256": "10a6974c80cdde83f6e472e784de8772a5e9ad426c87a9bc3b73533559d95d7a", + "artifact_id": 11792481536, "capture_sha256": "71a9c5e9463a5ea1b7050053286f4fa11484c2c30c7b509ddac86c16527a1e13", - "check_run_id": 115126832648, + "check_run_id": 115154313567, "conclusion": "success", - "job_id": 115126832648, + "job_id": 115154313567, "platform": "windows", "runner": "windows-latest", - "runner_id": 1000035467, + "runner_id": 1000035614, "runner_labels": [ "windows-latest" ], - "runner_name": "GitHub Actions 1000035467" + "runner_name": "GitHub Actions 1000035614" } ], "catalog_sha256": "f92926d7a643aed5dfb151ba8af1ff570f1a8e46a3587a91e2ae4498868abe82", @@ -2247,7 +2247,7 @@ }, { "path": "tests/real_agent_driver.py", - "sha256": "7748875c63be3a3eb6fbe7516088f9b00c8e74f51661d241a2c9854d7afb33fe" + "sha256": "7c75f03630f4f84883f014de00921ded8e2be4ad194ff990db335d675cd10c3e" }, { "path": "tests/run_e2e_report.py", @@ -2262,8 +2262,8 @@ "repository": "operatorstack/pitot", "repository_id": 1305805198, "run_attempt": 1, - "run_id": 38345794247, - "source_sha": "87fc7ede73adb092f4d50ebdd9d86ee8976de6a3", + "run_id": 38354544512, + "source_sha": "8f9db79ff096f8890e36dc2b6c227ae04f3baab4", "workflow_id": 381486275, "workflow_path": ".github/workflows/pitot-e2e.yml" } diff --git a/tests/real_agent_driver.py b/tests/real_agent_driver.py index 94f2b41..d071cc8 100644 --- a/tests/real_agent_driver.py +++ b/tests/real_agent_driver.py @@ -691,7 +691,7 @@ def configure( f'"{target}" "{witness_command}" "{pitot_command}" ' f'"{witness_receipt}" "{nonce}" "{runtime_path}"' ) - settings = hook_group("PreToolUse", "^(Bash|run_shell_command)$", hook_command) + settings = hook_group("PreToolUse", "^run_shell_command$", hook_command) settings["modelProviders"] = { "openai": { "protocol": "openai", diff --git a/tests/test_qwen_setup.py b/tests/test_qwen_setup.py new file mode 100644 index 0000000..ddad0a5 --- /dev/null +++ b/tests/test_qwen_setup.py @@ -0,0 +1,51 @@ +"""Keep the real Qwen fixture aligned with the public shell-hook setup.""" + +from pathlib import Path +import json +import re +import tempfile +import unittest +from unittest.mock import patch + +import real_agent_driver as driver + + +class QwenSetupTests(unittest.TestCase): + def test_native_fixture_uses_documented_runtime_shell_matcher(self): + section = ( + (driver.LAB / "README.md") + .read_text(encoding="utf-8") + .split("### Qwen Code\n", 1)[1] + .split("\n### ", 1)[0] + ) + documented = json.loads(section.split("```json\n", 1)[1].split("```", 1)[0]) + expected = documented["hooks"]["PreToolUse"][0]["matcher"] + self.assertEqual(expected, "^run_shell_command$") + for windows in (False, True): + with self.subTest(windows=windows), tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + home, project = root / "home", root / "project" + home.mkdir() + project.mkdir() + with patch.object(driver, "windows_host", return_value=windows): + _, env = driver.configure( + "qwen", + home, + project, + "owned-witness", + "http://127.0.0.1:12345", + pitot_command="owned-pitot", + witness_receipt=str(root / "receipt.json"), + nonce="owned-test-nonce", + runtime_path=str(root / "runtime.json"), + ) + settings = json.loads((home / ".qwen/settings.json").read_text()) + entries = settings["hooks"]["PreToolUse"] + self.assertEqual(len(entries), 1) + self.assertEqual(entries[0]["matcher"], expected) + self.assertEqual(entries[0]["hooks"][0]["type"], "command") + self.assertEqual(env["QWEN_HOME"], str(home / ".qwen")) + matcher = re.compile(entries[0]["matcher"]) + self.assertIsNotNone(matcher.fullmatch("run_shell_command")) + for tool in ("read_file", "monitor", "run_shell_command_extra"): + self.assertIsNone(matcher.search(tool), tool)