@gotgenes/pi-permission-model-judge 1.0.0 → 1.0.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/CHANGELOG.md +20 -0
- package/README.md +6 -2
- package/config/config.example.json +3 -3
- package/docs/configuration.md +18 -0
- package/package.json +1 -1
- package/src/model-review.ts +19 -1
- package/src/typo-reviewer.ts +18 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.0.2](https://github.com/gotgenes/pi-packages/compare/pi-permission-model-judge-v1.0.1...pi-permission-model-judge-v1.0.2) (2026-07-21)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* **pi-permission-model-judge:** forward resolved auth into the review model call ([9836020](https://github.com/gotgenes/pi-packages/commit/98360207d19a91edcf8e166b59dd1a9262349277)), closes [#625](https://github.com/gotgenes/pi-packages/issues/625)
|
|
9
|
+
* **pi-permission-model-judge:** resolve model auth before the review call ([4c90603](https://github.com/gotgenes/pi-packages/commit/4c906031144e18c7f6b60eac5f8607e271f090f2)), closes [#625](https://github.com/gotgenes/pi-packages/issues/625)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
### Documentation
|
|
13
|
+
|
|
14
|
+
* **pi-permission-model-judge:** feature the corrected dropped-prefix typo pattern ([13553d5](https://github.com/gotgenes/pi-packages/commit/13553d5c4ba8ba50a90688bd26e597a842f5f509)), closes [#625](https://github.com/gotgenes/pi-packages/issues/625)
|
|
15
|
+
|
|
16
|
+
## [1.0.1](https://github.com/gotgenes/pi-packages/compare/pi-permission-model-judge-v1.0.0...pi-permission-model-judge-v1.0.1) (2026-07-20)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
### Documentation
|
|
20
|
+
|
|
21
|
+
* **pi-permission-model-judge:** feature the doubled-package typo pattern ([abcfa23](https://github.com/gotgenes/pi-packages/commit/abcfa23eac678b42b2e031b0bb1092db4b601c55))
|
|
22
|
+
|
|
3
23
|
## 1.0.0 (2026-07-20)
|
|
4
24
|
|
|
5
25
|
|
package/README.md
CHANGED
|
@@ -49,8 +49,12 @@ Two independent config files are involved — the safety policy lives in pi-perm
|
|
|
49
49
|
{
|
|
50
50
|
"provider": "anthropic",
|
|
51
51
|
"model": "claude-haiku-4-5",
|
|
52
|
-
"instructions": "Deny a path that repeats a
|
|
53
|
-
|
|
52
|
+
"instructions": "Deny a path that repeats a package name around `packages/`, or drops the repo's `pi-packages/packages/` prefix…",
|
|
53
|
+
// Catches a doubled package segment and a dropped repository prefix.
|
|
54
|
+
"typoPatterns": [
|
|
55
|
+
"([^/]+)/packages/\\1(/|$)",
|
|
56
|
+
"development/pi/(?!pi-packages/)pi-[^/]+(/|$)"
|
|
57
|
+
]
|
|
54
58
|
}
|
|
55
59
|
```
|
|
56
60
|
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
"$schema": "https://raw.githubusercontent.com/gotgenes/pi-packages/main/packages/pi-permission-model-judge/schemas/model-judge.schema.json",
|
|
3
3
|
"provider": "anthropic",
|
|
4
4
|
"model": "claude-haiku-4-5",
|
|
5
|
-
"instructions": "You review a filesystem path a tool is about to access outside the working directory.
|
|
5
|
+
"instructions": "You review a filesystem path a tool is about to access outside the working directory. Two common typos both point at the wrong location. (1) A doubled package segment — a package name repeated around `packages/`, for example `pi-permission-system/packages/pi-permission-system/…`, where the correct path names the package only once under the repository's `packages/` directory. (2) A dropped repository prefix — a path that jumps straight to a package directory such as `development/pi/pi-permission-system/…`, where the correct path routes through the repository's `pi-packages/packages/` directory (for example `development/pi/pi-packages/packages/pi-permission-system/…`). When the path shows either typo, deny it and give the single corrected absolute path in the reason so the caller can retry against the right location. If the path looks intentional or you are unsure, defer. Reply with strict JSON: {\"verdict\":\"deny\",\"reason\":\"…\"} to reject, or {\"verdict\":\"defer\"} otherwise.",
|
|
6
6
|
"typoPatterns": [
|
|
7
|
-
"
|
|
8
|
-
"pi-packages/
|
|
7
|
+
"([^/]+)/packages/\\1(/|$)",
|
|
8
|
+
"development/pi/(?!pi-packages/)pi-[^/]+(/|$)"
|
|
9
9
|
],
|
|
10
10
|
"timeoutMs": 5000
|
|
11
11
|
}
|
package/docs/configuration.md
CHANGED
|
@@ -59,6 +59,24 @@ Only a path that matches at least one pattern is sent to the model — this is t
|
|
|
59
59
|
An invalid regular expression is skipped with a warning.
|
|
60
60
|
An empty list (the default) matches nothing, so the reviewer defers everything.
|
|
61
61
|
|
|
62
|
+
Two typo shapes are worth featuring, each as its own pattern:
|
|
63
|
+
|
|
64
|
+
```json
|
|
65
|
+
"typoPatterns": [
|
|
66
|
+
"([^/]+)/packages/\\1(/|$)",
|
|
67
|
+
"development/pi/(?!pi-packages/)pi-[^/]+(/|$)"
|
|
68
|
+
]
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
The first catches a **doubled package segment** — a package name repeated around `packages/`, e.g. `pi-permission-system/packages/pi-permission-system/…`.
|
|
72
|
+
The `\1` backreference requires the segment before and after `packages/` to be identical, so it catches `<name>/packages/<name>` for every `<name>` while leaving a correct `packages/<name>/…` path untouched. (In JSON the backslash is doubled — `\\1` — so the parsed string is the regex `\1`.)
|
|
73
|
+
|
|
74
|
+
The second catches a **dropped repository prefix** — a path that jumps straight to a package directory (`development/pi/pi-permission-system/…`) instead of routing through the repo's `pi-packages/packages/` directory.
|
|
75
|
+
The negative lookahead `(?!pi-packages/)` exempts the correct `pi-packages` path, and `pi-[^/]+` requires a package segment after `pi-` so the sibling monorepo at `~/development/pi/pi` is left alone.
|
|
76
|
+
|
|
77
|
+
Both patterns anchor the segment with `(/|$)`, not a bare trailing `/`, so a path that *ends* at the offending segment (`…/pi-permission-system`) still matches.
|
|
78
|
+
Adjust the `development/pi/…` prefix to wherever your checkouts live.
|
|
79
|
+
|
|
62
80
|
### `timeoutMs`
|
|
63
81
|
|
|
64
82
|
The model call is aborted after this many milliseconds, and an aborted call defers.
|
package/package.json
CHANGED
package/src/model-review.ts
CHANGED
|
@@ -28,12 +28,26 @@ export const GENERIC_TEACHING_REASON =
|
|
|
28
28
|
export type CompleteFn = (
|
|
29
29
|
model: Model<any>,
|
|
30
30
|
context: Context,
|
|
31
|
-
options?: {
|
|
31
|
+
options?: {
|
|
32
|
+
signal?: AbortSignal;
|
|
33
|
+
apiKey?: string;
|
|
34
|
+
headers?: Record<string, string>;
|
|
35
|
+
},
|
|
32
36
|
) => Promise<AssistantMessage>;
|
|
33
37
|
|
|
38
|
+
/**
|
|
39
|
+
* The auth resolved for a model call — structurally the `ResolvedRequestAuth`
|
|
40
|
+
* of the core `ModelRegistry`, redeclared here because that type is not
|
|
41
|
+
* re-exported from `@earendil-works/pi-coding-agent`.
|
|
42
|
+
*/
|
|
43
|
+
export type ResolvedRequestAuth =
|
|
44
|
+
| { ok: true; apiKey?: string; headers?: Record<string, string> }
|
|
45
|
+
| { ok: false; error: string };
|
|
46
|
+
|
|
34
47
|
/** The narrow model-registry projection the reviewer needs (ISP). */
|
|
35
48
|
export interface ModelRegistryLike {
|
|
36
49
|
find(provider: string, modelId: string): Model<any> | undefined;
|
|
50
|
+
getApiKeyAndHeaders(model: Model<any>): Promise<ResolvedRequestAuth>;
|
|
37
51
|
}
|
|
38
52
|
|
|
39
53
|
/** Inputs for a single path review. */
|
|
@@ -42,6 +56,8 @@ export interface ReviewPathInputs {
|
|
|
42
56
|
config: ModelJudgeConfig;
|
|
43
57
|
model: Model<any>;
|
|
44
58
|
complete: CompleteFn;
|
|
59
|
+
apiKey?: string;
|
|
60
|
+
headers?: Record<string, string>;
|
|
45
61
|
}
|
|
46
62
|
|
|
47
63
|
/**
|
|
@@ -70,6 +86,8 @@ export async function reviewPath(
|
|
|
70
86
|
};
|
|
71
87
|
const reply = await inputs.complete(inputs.model, context, {
|
|
72
88
|
signal: controller.signal,
|
|
89
|
+
apiKey: inputs.apiKey,
|
|
90
|
+
headers: inputs.headers,
|
|
73
91
|
});
|
|
74
92
|
return parseVerdict(reply);
|
|
75
93
|
} catch {
|
package/src/typo-reviewer.ts
CHANGED
|
@@ -69,14 +69,29 @@ export function createTypoReviewer(
|
|
|
69
69
|
if (!matchesAnyTypoPattern(path, compiledFor(config))) {
|
|
70
70
|
return { kind: "defer" };
|
|
71
71
|
}
|
|
72
|
-
const
|
|
73
|
-
|
|
72
|
+
const registry = deps.getRegistry();
|
|
73
|
+
const model = registry?.find(config.provider, config.model);
|
|
74
|
+
if (!registry || !model) {
|
|
74
75
|
deps.warn?.(
|
|
75
76
|
`model "${config.provider}/${config.model}" did not resolve; deferring`,
|
|
76
77
|
);
|
|
77
78
|
return { kind: "defer" };
|
|
78
79
|
}
|
|
79
|
-
|
|
80
|
+
const auth = await registry.getApiKeyAndHeaders(model);
|
|
81
|
+
if (!auth.ok) {
|
|
82
|
+
deps.warn?.(
|
|
83
|
+
`auth for "${config.provider}/${config.model}" did not resolve (${auth.error}); deferring`,
|
|
84
|
+
);
|
|
85
|
+
return { kind: "defer" };
|
|
86
|
+
}
|
|
87
|
+
return reviewPath({
|
|
88
|
+
path,
|
|
89
|
+
config,
|
|
90
|
+
model,
|
|
91
|
+
complete: deps.complete,
|
|
92
|
+
apiKey: auth.apiKey,
|
|
93
|
+
headers: auth.headers,
|
|
94
|
+
});
|
|
80
95
|
};
|
|
81
96
|
}
|
|
82
97
|
|