@mu-crew/muzzle 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/extension/muzzle.ts +16 -0
- package/package.json +4 -4
- package/skills/muzzle/SKILL.md +2 -2
package/extension/muzzle.ts
CHANGED
|
@@ -7,6 +7,12 @@
|
|
|
7
7
|
// tool_result: read the report, append `muzzle: waited Ws for N slots, ran
|
|
8
8
|
// Rs` and a `muzzle` custom entry with the same numbers (D26).
|
|
9
9
|
//
|
|
10
|
+
// One copy per pi process: the pi package and `-e <path>` can both load this
|
|
11
|
+
// file, and two copies would each wrap the call (the CLI also refuses to wrap
|
|
12
|
+
// a command that already runs muzzle, D22). The first copy to load claims
|
|
13
|
+
// GUARD on globalThis; later copies register nothing. The claim is released
|
|
14
|
+
// on session_shutdown, so /reload and session replacement load it again.
|
|
15
|
+
//
|
|
10
16
|
// Nothing here may block a call: a missing binary or a failing wrap leaves
|
|
11
17
|
// the call as it is. A throwing tool_call handler blocks the tool in pi, so
|
|
12
18
|
// every path is caught.
|
|
@@ -134,6 +140,9 @@ function wrap(bin: string, command: string, cwd: string, timeout?: number): Prom
|
|
|
134
140
|
});
|
|
135
141
|
}
|
|
136
142
|
|
|
143
|
+
/** The process-wide claim; registry-global so separate module copies share it. */
|
|
144
|
+
export const GUARD = Symbol.for("@mu-crew/muzzle/extension");
|
|
145
|
+
|
|
137
146
|
export interface Deps {
|
|
138
147
|
findBinary?: () => string | null;
|
|
139
148
|
tmpRoot?: string;
|
|
@@ -142,6 +151,10 @@ export interface Deps {
|
|
|
142
151
|
export function createExtension(deps: Deps = {}) {
|
|
143
152
|
const findBinary = deps.findBinary ?? (() => findMuzzle());
|
|
144
153
|
return function (pi: ExtensionAPI) {
|
|
154
|
+
const g = globalThis as Record<symbol, unknown>;
|
|
155
|
+
if (g[GUARD] !== undefined) return;
|
|
156
|
+
const claim = {};
|
|
157
|
+
g[GUARD] = claim;
|
|
145
158
|
let bin: string | null | undefined;
|
|
146
159
|
let reportDir: string | undefined;
|
|
147
160
|
const pending = new Map<string, string>();
|
|
@@ -167,6 +180,8 @@ export function createExtension(deps: Deps = {}) {
|
|
|
167
180
|
if (bin === null) warn(ctx, "muzzle not found: bash calls run unwrapped");
|
|
168
181
|
}
|
|
169
182
|
if (bin === null) return;
|
|
183
|
+
// Belt and braces for the guard: our own rewrite is never rewritten.
|
|
184
|
+
if (input.command.startsWith(`${shellQuote(bin)} run `)) return;
|
|
170
185
|
const timeout = typeof input.timeout === "number" ? input.timeout : undefined;
|
|
171
186
|
const wrapped = await wrap(bin, input.command, ctx.cwd, timeout);
|
|
172
187
|
if (wrapWarned) {
|
|
@@ -213,6 +228,7 @@ export function createExtension(deps: Deps = {}) {
|
|
|
213
228
|
});
|
|
214
229
|
|
|
215
230
|
pi.on("session_shutdown", async () => {
|
|
231
|
+
if (g[GUARD] === claim) delete g[GUARD];
|
|
216
232
|
if (reportDir) rmSync(reportDir, { recursive: true, force: true });
|
|
217
233
|
reportDir = undefined;
|
|
218
234
|
pending.clear();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mu-crew/muzzle",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Per-host admission for heavy commands, with a run log that tunes itself",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -42,8 +42,8 @@
|
|
|
42
42
|
}
|
|
43
43
|
},
|
|
44
44
|
"optionalDependencies": {
|
|
45
|
-
"@mu-crew/muzzle-linux-x64": "0.1.
|
|
46
|
-
"@mu-crew/muzzle-linux-arm64": "0.1.
|
|
47
|
-
"@mu-crew/muzzle-darwin-arm64": "0.1.
|
|
45
|
+
"@mu-crew/muzzle-linux-x64": "0.1.2",
|
|
46
|
+
"@mu-crew/muzzle-linux-arm64": "0.1.2",
|
|
47
|
+
"@mu-crew/muzzle-darwin-arm64": "0.1.2"
|
|
48
48
|
}
|
|
49
49
|
}
|
package/skills/muzzle/SKILL.md
CHANGED
|
@@ -53,8 +53,8 @@ muzzle run --rule gate --run-timeout 900 -- contrib/fast-gate
|
|
|
53
53
|
- **`timeout` goes inside `muzzle run`, never outside it.** An outer
|
|
54
54
|
`timeout` counts the queue wait and kills the gate before it starts. Use
|
|
55
55
|
`--run-timeout S`, which counts from admission and exits 124.
|
|
56
|
-
- In pi, a command that
|
|
57
|
-
extension, so pi's own bash `timeout` still counts the wait. Give a
|
|
56
|
+
- In pi, a command that already runs muzzle (`muzzle run …`, by any
|
|
57
|
+
path) is left alone by the extension, so pi's own bash `timeout` still counts the wait. Give a
|
|
58
58
|
hand-wrapped call no pi timeout, and put the limit in `--run-timeout`.
|
|
59
59
|
- muzzle sets `CARGO_BUILD_JOBS`, `RUST_TEST_THREADS`, `MAKEFLAGS` and
|
|
60
60
|
`MUZZLE_SLOTS` from the claim and overwrites any it inherits. Drop
|