@dungle-scrubs/harness-cli-normalizer 0.6.0 → 0.6.1
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/README.md +18 -6
- package/dist/cli/args.d.ts +9 -1
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +31 -26
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/check.d.ts +14 -0
- package/dist/cli/check.d.ts.map +1 -1
- package/dist/cli/check.js +10 -3
- package/dist/cli/check.js.map +1 -1
- package/dist/cli/config.d.ts +4 -4
- package/dist/cli/config.d.ts.map +1 -1
- package/dist/cli/config.js +6 -6
- package/dist/cli/config.js.map +1 -1
- package/dist/cli/exit-codes.d.ts +0 -1
- package/dist/cli/exit-codes.d.ts.map +1 -1
- package/dist/cli/exit-codes.js +0 -1
- package/dist/cli/exit-codes.js.map +1 -1
- package/dist/cli/help.d.ts +2 -2
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/help.js +6 -2
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +3 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/inspect.d.ts.map +1 -1
- package/dist/cli/inspect.js +84 -265
- package/dist/cli/inspect.js.map +1 -1
- package/dist/cli/plan-turn.d.ts +68 -0
- package/dist/cli/plan-turn.d.ts.map +1 -0
- package/dist/cli/plan-turn.js +266 -0
- package/dist/cli/plan-turn.js.map +1 -0
- package/dist/cli/refuse.d.ts.map +1 -1
- package/dist/cli/refuse.js +2 -1
- package/dist/cli/refuse.js.map +1 -1
- package/dist/cli/resolve-harness.d.ts.map +1 -1
- package/dist/cli/resolve-harness.js +2 -3
- package/dist/cli/resolve-harness.js.map +1 -1
- package/dist/cli/run.d.ts.map +1 -1
- package/dist/cli/run.js +33 -367
- package/dist/cli/run.js.map +1 -1
- package/dist/cli/session-json.d.ts +1 -1
- package/dist/cli/session-json.d.ts.map +1 -1
- package/dist/cli/session-json.js +1 -3
- package/dist/cli/session-json.js.map +1 -1
- package/dist/cli/session.d.ts.map +1 -1
- package/dist/cli/session.js +25 -44
- package/dist/cli/session.js.map +1 -1
- package/dist/cli/skills-root.d.ts +1 -1
- package/dist/cli/skills-root.d.ts.map +1 -1
- package/dist/cli/skills-root.js +1 -1
- package/dist/cli/skills-root.js.map +1 -1
- package/dist/execution/decode.d.ts.map +1 -1
- package/dist/execution/decode.js +11 -36
- package/dist/execution/decode.js.map +1 -1
- package/dist/execution/events.d.ts +4 -1
- package/dist/execution/events.d.ts.map +1 -1
- package/dist/execution/events.js.map +1 -1
- package/dist/execution/failure.d.ts +3 -1
- package/dist/execution/failure.d.ts.map +1 -1
- package/dist/execution/failure.js +14 -11
- package/dist/execution/failure.js.map +1 -1
- package/dist/execution/open-session.d.ts +1 -1
- package/dist/execution/open-session.d.ts.map +1 -1
- package/dist/execution/open-session.js +150 -223
- package/dist/execution/open-session.js.map +1 -1
- package/dist/execution/stream-turn.d.ts +9 -14
- package/dist/execution/stream-turn.d.ts.map +1 -1
- package/dist/execution/stream-turn.js +85 -188
- package/dist/execution/stream-turn.js.map +1 -1
- package/dist/execution/supervisor.d.ts +71 -0
- package/dist/execution/supervisor.d.ts.map +1 -0
- package/dist/execution/supervisor.js +127 -0
- package/dist/execution/supervisor.js.map +1 -0
- package/dist/interpretation/argv.d.ts +38 -12
- package/dist/interpretation/argv.d.ts.map +1 -1
- package/dist/interpretation/argv.js +26 -20
- package/dist/interpretation/argv.js.map +1 -1
- package/dist/interpretation/content.d.ts +10 -1
- package/dist/interpretation/content.d.ts.map +1 -1
- package/dist/interpretation/content.js +20 -11
- package/dist/interpretation/content.js.map +1 -1
- package/dist/interpretation/hints.d.ts +1 -1
- package/dist/interpretation/hints.d.ts.map +1 -1
- package/dist/interpretation/hints.js +10 -11
- package/dist/interpretation/hints.js.map +1 -1
- package/dist/interpretation/index.d.ts +0 -1
- package/dist/interpretation/index.d.ts.map +1 -1
- package/dist/interpretation/index.js +0 -1
- package/dist/interpretation/index.js.map +1 -1
- package/dist/interpretation/limits.d.ts +2 -5
- package/dist/interpretation/limits.d.ts.map +1 -1
- package/dist/interpretation/limits.js +8 -62
- package/dist/interpretation/limits.js.map +1 -1
- package/dist/interpretation/question.d.ts +27 -0
- package/dist/interpretation/question.d.ts.map +1 -1
- package/dist/interpretation/question.js +28 -0
- package/dist/interpretation/question.js.map +1 -1
- package/dist/interpretation/refusal.d.ts +10 -5
- package/dist/interpretation/refusal.d.ts.map +1 -1
- package/dist/interpretation/refusal.js +24 -15
- package/dist/interpretation/refusal.js.map +1 -1
- package/dist/interpretation/resolve-options.d.ts +36 -2
- package/dist/interpretation/resolve-options.d.ts.map +1 -1
- package/dist/interpretation/resolve-options.js +38 -21
- package/dist/interpretation/resolve-options.js.map +1 -1
- package/dist/interpretation/session-input.d.ts +44 -1
- package/dist/interpretation/session-input.d.ts.map +1 -1
- package/dist/interpretation/session-input.js +59 -4
- package/dist/interpretation/session-input.js.map +1 -1
- package/dist/interpretation/shape.d.ts +1 -0
- package/dist/interpretation/shape.d.ts.map +1 -1
- package/dist/interpretation/shape.js +10 -0
- package/dist/interpretation/shape.js.map +1 -1
- package/dist/interpretation/skills-selection.d.ts +25 -33
- package/dist/interpretation/skills-selection.d.ts.map +1 -1
- package/dist/interpretation/skills-selection.js +41 -48
- package/dist/interpretation/skills-selection.js.map +1 -1
- package/dist/interpretation/support.d.ts.map +1 -1
- package/dist/interpretation/support.js +23 -8
- package/dist/interpretation/support.js.map +1 -1
- package/dist/interpretation/tool-selection.d.ts +7 -6
- package/dist/interpretation/tool-selection.d.ts.map +1 -1
- package/dist/interpretation/tool-selection.js +54 -116
- package/dist/interpretation/tool-selection.js.map +1 -1
- package/dist/interpretation/tool-vocabulary.d.ts +31 -12
- package/dist/interpretation/tool-vocabulary.d.ts.map +1 -1
- package/dist/interpretation/tool-vocabulary.js +19 -41
- package/dist/interpretation/tool-vocabulary.js.map +1 -1
- package/dist/interpretation/turn-options.d.ts +4 -0
- package/dist/interpretation/turn-options.d.ts.map +1 -1
- package/dist/interpretation/turn-options.js +105 -241
- package/dist/interpretation/turn-options.js.map +1 -1
- package/dist/interpretation/vocabulary.d.ts +8 -6
- package/dist/interpretation/vocabulary.d.ts.map +1 -1
- package/dist/interpretation/vocabulary.js +22 -9
- package/dist/interpretation/vocabulary.js.map +1 -1
- package/dist/knowledge/claude-code.js +3 -3
- package/dist/knowledge/claude-code.js.map +1 -1
- package/dist/knowledge/codex.d.ts.map +1 -1
- package/dist/knowledge/codex.js +31 -7
- package/dist/knowledge/codex.js.map +1 -1
- package/dist/knowledge/descriptor.d.ts +67 -36
- package/dist/knowledge/descriptor.d.ts.map +1 -1
- package/dist/knowledge/descriptor.js +49 -15
- package/dist/knowledge/descriptor.js.map +1 -1
- package/dist/knowledge/matchers.d.ts +12 -0
- package/dist/knowledge/matchers.d.ts.map +1 -1
- package/dist/knowledge/matchers.js +34 -0
- package/dist/knowledge/matchers.js.map +1 -1
- package/dist/knowledge/muse.d.ts.map +1 -1
- package/dist/knowledge/muse.js +7 -5
- package/dist/knowledge/muse.js.map +1 -1
- package/dist/knowledge/overrides.d.ts.map +1 -1
- package/dist/knowledge/overrides.js +9 -20
- package/dist/knowledge/overrides.js.map +1 -1
- package/dist/knowledge/pi.d.ts.map +1 -1
- package/dist/knowledge/pi.js +8 -6
- package/dist/knowledge/pi.js.map +1 -1
- package/dist/knowledge/profile.d.ts +1 -0
- package/dist/knowledge/profile.d.ts.map +1 -1
- package/dist/knowledge/profile.js +1 -0
- package/dist/knowledge/profile.js.map +1 -1
- package/package.json +1 -1
- package/src/cli/args.ts +35 -27
- package/src/cli/check.ts +10 -3
- package/src/cli/config.ts +12 -11
- package/src/cli/exit-codes.ts +0 -2
- package/src/cli/help.ts +6 -2
- package/src/cli/index.ts +3 -1
- package/src/cli/inspect.ts +88 -269
- package/src/cli/plan-turn.ts +346 -0
- package/src/cli/refuse.ts +2 -1
- package/src/cli/resolve-harness.ts +4 -5
- package/src/cli/run.ts +36 -399
- package/src/cli/session-json.ts +1 -6
- package/src/cli/session.ts +34 -44
- package/src/cli/skills-root.ts +1 -4
- package/src/execution/decode.ts +10 -36
- package/src/execution/events.ts +4 -1
- package/src/execution/failure.ts +18 -11
- package/src/execution/open-session.ts +154 -228
- package/src/execution/stream-turn.ts +90 -193
- package/src/execution/supervisor.ts +199 -0
- package/src/interpretation/argv.ts +62 -34
- package/src/interpretation/content.ts +30 -13
- package/src/interpretation/hints.ts +2 -12
- package/src/interpretation/index.ts +0 -1
- package/src/interpretation/limits.ts +14 -75
- package/src/interpretation/question.ts +46 -0
- package/src/interpretation/refusal.ts +28 -18
- package/src/interpretation/resolve-options.ts +85 -32
- package/src/interpretation/session-input.ts +88 -5
- package/src/interpretation/shape.ts +10 -0
- package/src/interpretation/skills-selection.ts +70 -74
- package/src/interpretation/support.ts +19 -6
- package/src/interpretation/tool-selection.ts +67 -122
- package/src/interpretation/tool-vocabulary.ts +48 -53
- package/src/interpretation/turn-options.ts +123 -220
- package/src/interpretation/vocabulary.ts +15 -10
- package/src/knowledge/claude-code.ts +3 -3
- package/src/knowledge/codex.ts +31 -7
- package/src/knowledge/descriptor.ts +105 -49
- package/src/knowledge/matchers.ts +35 -0
- package/src/knowledge/muse.ts +7 -5
- package/src/knowledge/overrides.ts +17 -32
- package/src/knowledge/pi.ts +8 -6
- package/src/knowledge/profile.ts +1 -0
- package/dist/interpretation/dimensions.d.ts +0 -11
- package/dist/interpretation/dimensions.d.ts.map +0 -1
- package/dist/interpretation/dimensions.js +0 -4
- package/dist/interpretation/dimensions.js.map +0 -1
- package/src/interpretation/dimensions.ts +0 -14
|
@@ -41,9 +41,50 @@ export const CANONICAL_TOOLS = deepFreeze([
|
|
|
41
41
|
] as const);
|
|
42
42
|
export type CanonicalTool = (typeof CANONICAL_TOOLS)[number];
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
/** Every closed string vocabulary on a descriptor is declared once as a
|
|
45
|
+
* runtime array with its type derived (RFC-02 change 9), so a CLI list, an
|
|
46
|
+
* override validator, or a test reads the array instead of restating it. */
|
|
47
|
+
export const STREAMING_GRANULARITIES = deepFreeze(["token", "message", "none"] as const);
|
|
48
|
+
export type StreamingGranularity = (typeof STREAMING_GRANULARITIES)[number];
|
|
45
49
|
|
|
46
|
-
export
|
|
50
|
+
export const HARNESS_MODES = deepFreeze([
|
|
51
|
+
"headless-turn",
|
|
52
|
+
"headless-session",
|
|
53
|
+
"interactive",
|
|
54
|
+
] as const);
|
|
55
|
+
export type HarnessMode = (typeof HARNESS_MODES)[number];
|
|
56
|
+
|
|
57
|
+
export const STDIN_POLICIES = deepFreeze(["inherit", "close-required"] as const);
|
|
58
|
+
export type StdinPolicy = (typeof STDIN_POLICIES)[number];
|
|
59
|
+
|
|
60
|
+
export const CWD_SLUGS = deepFreeze(["dash-separators", "pi-dash-wrapped", "verbatim"] as const);
|
|
61
|
+
export type CwdSlug = (typeof CWD_SLUGS)[number];
|
|
62
|
+
|
|
63
|
+
export const RESUME_STYLES = deepFreeze(["flag", "positional"] as const);
|
|
64
|
+
export type ResumeStyle = (typeof RESUME_STYLES)[number];
|
|
65
|
+
|
|
66
|
+
export const RESUME_ON_MISSING = deepFreeze(["error", "create"] as const);
|
|
67
|
+
export type ResumeOnMissing = (typeof RESUME_ON_MISSING)[number];
|
|
68
|
+
|
|
69
|
+
export const IDENTITY_AUTHORITIES = deepFreeze(["caller-assigned", "harness-minted"] as const);
|
|
70
|
+
export type IdentityAuthority = (typeof IDENTITY_AUTHORITIES)[number];
|
|
71
|
+
|
|
72
|
+
export const DENY_SEMANTICS = deepFreeze(["remove-from-set", "policy-gate", "no-lists"] as const);
|
|
73
|
+
export type DenySemantics = (typeof DENY_SEMANTICS)[number];
|
|
74
|
+
|
|
75
|
+
export const SKILLS_OVERRIDES_VIA = deepFreeze([
|
|
76
|
+
"settings-skilloverrides",
|
|
77
|
+
"config-skills-array",
|
|
78
|
+
] as const);
|
|
79
|
+
export type SkillsOverridesVia = (typeof SKILLS_OVERRIDES_VIA)[number];
|
|
80
|
+
|
|
81
|
+
export const VERSION_SOURCE_KINDS = deepFreeze(["npm", "installed"] as const);
|
|
82
|
+
export type VersionSourceKind = (typeof VERSION_SOURCE_KINDS)[number];
|
|
83
|
+
|
|
84
|
+
/** The access preset's value vocabulary: `read` narrows to the read-only
|
|
85
|
+
* tool subset, `write` is no restriction. */
|
|
86
|
+
export const ACCESS_VALUES = deepFreeze(["read", "write"] as const);
|
|
87
|
+
export type AccessValue = (typeof ACCESS_VALUES)[number];
|
|
47
88
|
|
|
48
89
|
export const SESSION_INPUT_KINDS = ["claude-sdk-user-message", "pi-rpc-prompt"] as const;
|
|
49
90
|
export type SessionInputKind = (typeof SESSION_INPUT_KINDS)[number];
|
|
@@ -107,6 +148,7 @@ export type UnavailableMatcher = PhraseMatcher;
|
|
|
107
148
|
export const TURN_OPTION_KEYS = deepFreeze([
|
|
108
149
|
"effort",
|
|
109
150
|
"sandbox",
|
|
151
|
+
"contextWindow",
|
|
110
152
|
"provider",
|
|
111
153
|
"discovery",
|
|
112
154
|
"write",
|
|
@@ -158,6 +200,12 @@ export interface SpecBase {
|
|
|
158
200
|
readonly resumeRender?: OptionRender | null;
|
|
159
201
|
}
|
|
160
202
|
|
|
203
|
+
/** How one access value renders on one harness (RFC-02 change 3): the
|
|
204
|
+
* marker for "render the read preset through the tool list", null for
|
|
205
|
+
* "emit nothing", or a phase-aware render carrying the harness value it
|
|
206
|
+
* maps to (codex: `read` is `--sandbox read-only`). */
|
|
207
|
+
export type AccessRender = "tool-preset" | null | (SpecBase & { readonly value?: string });
|
|
208
|
+
|
|
161
209
|
export type TurnOptionSpec =
|
|
162
210
|
/** Closed value vocabulary. `default` renders on LAUNCH ONLY. */
|
|
163
211
|
| (SpecBase & {
|
|
@@ -165,17 +213,15 @@ export type TurnOptionSpec =
|
|
|
165
213
|
readonly values: readonly string[];
|
|
166
214
|
readonly default?: string;
|
|
167
215
|
})
|
|
168
|
-
/**
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
readonly
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
readonly flags: Readonly<Record<string, readonly string[]>>;
|
|
178
|
-
})
|
|
216
|
+
/** The access preset: one kind on every harness that expresses it, a
|
|
217
|
+
* render per value, and `claims` naming the turn option the preset
|
|
218
|
+
* displaces when set (codex: sandbox) so exclusivity is data, not a
|
|
219
|
+
* harness name. */
|
|
220
|
+
| {
|
|
221
|
+
readonly kind: "access";
|
|
222
|
+
readonly renders: Readonly<Record<AccessValue, AccessRender>>;
|
|
223
|
+
readonly claims?: TurnOptionKey;
|
|
224
|
+
}
|
|
179
225
|
/** Ladder comes from vocabulary.efforts / effortsByModel, not from here. */
|
|
180
226
|
| (SpecBase & { readonly kind: "effort" })
|
|
181
227
|
/** Open selector, CLEAN_SELECTOR-validated. */
|
|
@@ -208,28 +254,37 @@ export const resolveRender = (spec: SpecBase, phase: "launch" | "resume"): Optio
|
|
|
208
254
|
return spec.resumeRender ?? spec.render;
|
|
209
255
|
};
|
|
210
256
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
*
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
)
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
257
|
+
export type Quoting = "toml" | "verbatim";
|
|
258
|
+
|
|
259
|
+
/** The argv tokens one resolved render produces for one value - the only
|
|
260
|
+
* place a render kind becomes tokens (RFC-02 change 1). `toml` quoting is
|
|
261
|
+
* `JSON.stringify`, sufficient for the closed vocabularies that ride
|
|
262
|
+
* config-kv; `verbatim` passes prose (prompt text) and bare TOML literals
|
|
263
|
+
* through unchanged. A flag-value or config-kv render with no value is a
|
|
264
|
+
* descriptor error, never an empty token. */
|
|
265
|
+
export const tokensFor = (
|
|
266
|
+
render: OptionRender,
|
|
267
|
+
value?: string,
|
|
268
|
+
quoting: Quoting = "toml",
|
|
269
|
+
): readonly string[] => {
|
|
270
|
+
switch (render.kind) {
|
|
271
|
+
case "flag-value":
|
|
272
|
+
if (value === undefined) {
|
|
273
|
+
throw new Error(`render ${render.flag} needs a value and none was given`);
|
|
274
|
+
}
|
|
275
|
+
return [...(render.extraFlags ?? []), render.flag, value];
|
|
276
|
+
case "config-kv":
|
|
277
|
+
if (value === undefined) {
|
|
278
|
+
throw new Error(`render ${render.flag} ${render.key} needs a value and none was given`);
|
|
279
|
+
}
|
|
280
|
+
return [render.flag, `${render.key}=${quoting === "toml" ? JSON.stringify(value) : value}`];
|
|
281
|
+
case "flag-list":
|
|
282
|
+
return [...render.flags];
|
|
283
|
+
default: {
|
|
284
|
+
const exhaustive: never = render;
|
|
285
|
+
return exhaustive;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
233
288
|
};
|
|
234
289
|
|
|
235
290
|
export interface HarnessDescriptor {
|
|
@@ -251,8 +306,8 @@ export interface HarnessDescriptor {
|
|
|
251
306
|
* have no registry to poll, so the check falls back to the locally
|
|
252
307
|
* installed `<bin> --version` and is skipped where the CLI is absent. */
|
|
253
308
|
readonly versionSource:
|
|
254
|
-
| { readonly kind: "npm"
|
|
255
|
-
| { readonly kind: "installed" };
|
|
309
|
+
| { readonly kind: Extract<VersionSourceKind, "npm">; readonly package: string }
|
|
310
|
+
| { readonly kind: Extract<VersionSourceKind, "installed"> };
|
|
256
311
|
/** Headless one-turn launch shape. `promptStyle: "positional"` means the
|
|
257
312
|
* prompt travels as a bare argv entry (ordering constraints apply).
|
|
258
313
|
* `streamFlags` is the output flag set a headless turn launches with so
|
|
@@ -267,7 +322,6 @@ export interface HarnessDescriptor {
|
|
|
267
322
|
* `workspace-write` into subcommands. */
|
|
268
323
|
readonly subcommands: readonly string[];
|
|
269
324
|
readonly promptStyle: "positional";
|
|
270
|
-
readonly toolsFlag: string | null;
|
|
271
325
|
readonly streamFlags: readonly string[];
|
|
272
326
|
/** The flag that pins a caller-assigned id at LAUNCH (spawn-time
|
|
273
327
|
* assignment; the execution layer consumes it), or null when the
|
|
@@ -281,7 +335,7 @@ export interface HarnessDescriptor {
|
|
|
281
335
|
* anywhere else (the v1 first-UUID-wins scar: a UUID inside quoted prompt
|
|
282
336
|
* text was returned as the session id, and resuming it started a stranger). */
|
|
283
337
|
readonly resume: {
|
|
284
|
-
readonly style:
|
|
338
|
+
readonly style: ResumeStyle;
|
|
285
339
|
readonly flag: string;
|
|
286
340
|
readonly aliases: readonly string[];
|
|
287
341
|
readonly idShape: RegExp;
|
|
@@ -299,7 +353,7 @@ export interface HarnessDescriptor {
|
|
|
299
353
|
* The protocol layer must know this: a consumer resuming a session it
|
|
300
354
|
* believes exists gets a blank session, not an error, on a "create"
|
|
301
355
|
* harness. */
|
|
302
|
-
readonly onMissing:
|
|
356
|
+
readonly onMissing: ResumeOnMissing;
|
|
303
357
|
};
|
|
304
358
|
/** Persistent headless session support: the complete flag list that follows
|
|
305
359
|
* the binary to open one lucid-owned process serving many turns, or null
|
|
@@ -327,7 +381,11 @@ export interface HarnessDescriptor {
|
|
|
327
381
|
readonly resumeFlag: SessionResumeFlag;
|
|
328
382
|
readonly input: SessionInputContract;
|
|
329
383
|
readonly turnEnd: Readonly<Record<string, string>>;
|
|
330
|
-
|
|
384
|
+
/** The command the runner writes at spawn to learn the session id, and
|
|
385
|
+
* the dot-path to that id in the response (pi rpc: `get_state`,
|
|
386
|
+
* `data.sessionId`). Encoded and decoded in interpretation
|
|
387
|
+
* (session-input.ts); execution holds no field names (ADR 0005). */
|
|
388
|
+
readonly identityProbe: { readonly command: string; readonly responseIdField: string } | null;
|
|
331
389
|
} | null;
|
|
332
390
|
/** Streaming is a property of the INVOCATION, not the harness: each pin
|
|
333
391
|
* names the flag set that unlocks a granularity, checked in order, first
|
|
@@ -348,7 +406,7 @@ export interface HarnessDescriptor {
|
|
|
348
406
|
* {type: "system", subtype: "init"}, re-emitted at every turn start with
|
|
349
407
|
* the same value (A-001) - consumers dedupe via decodeIdentity. */
|
|
350
408
|
readonly identity: {
|
|
351
|
-
readonly authority:
|
|
409
|
+
readonly authority: IdentityAuthority;
|
|
352
410
|
/** `idField` is a dot-path (muse nests its id at `stream.id`); an empty
|
|
353
411
|
* `match` means "any record carrying the id path". */
|
|
354
412
|
readonly announce: {
|
|
@@ -387,7 +445,7 @@ export interface HarnessDescriptor {
|
|
|
387
445
|
readonly template: string;
|
|
388
446
|
/** claude: '/', '.' -> '-'; pi: '/' -> '-' wrapped in leading/trailing
|
|
389
447
|
* dashes, dots preserved. */
|
|
390
|
-
readonly cwdSlug:
|
|
448
|
+
readonly cwdSlug: CwdSlug;
|
|
391
449
|
};
|
|
392
450
|
/** How the harness exposes context-window usage; the interpretation layer
|
|
393
451
|
* surfaces it as a `context` HarnessEvent. */
|
|
@@ -400,7 +458,7 @@ export interface HarnessDescriptor {
|
|
|
400
458
|
readonly resumeLast: { readonly flag: string } | null;
|
|
401
459
|
/** Whether backgrounded headless calls must have stdin closed (pi hangs
|
|
402
460
|
* without `< /dev/null`). */
|
|
403
|
-
readonly stdin:
|
|
461
|
+
readonly stdin: StdinPolicy;
|
|
404
462
|
/** Presence recognition: how an interactive process for a session id shows
|
|
405
463
|
* up in a process listing. `headlessMarkers` mark a process as headless
|
|
406
464
|
* (not interactive presence). Known blind spot, inherent to argv matching:
|
|
@@ -445,8 +503,7 @@ export interface HarnessDescriptor {
|
|
|
445
503
|
* the claude asymmetry: claude's include flag pre-approves without
|
|
446
504
|
* restricting the visible set, so an exact allowlist must render as a
|
|
447
505
|
* disallow-complement there; pi's include IS strict (over built-ins).
|
|
448
|
-
* `
|
|
449
|
-
* include). `builtins`: curated names + default-enabled state - grep/find/
|
|
506
|
+
* `builtins`: curated names + default-enabled state - grep/find/
|
|
450
507
|
* ls ship off on pi, everything ships on elsewhere. `categories`:
|
|
451
508
|
* non-list switches (muse disable flags, codex config booleans).
|
|
452
509
|
* `denySemantics`: whether a deny removes the tool from the model-visible
|
|
@@ -461,13 +518,12 @@ export interface HarnessDescriptor {
|
|
|
461
518
|
* muse: null (structural gap - trust/config scoped only). */
|
|
462
519
|
readonly skills: {
|
|
463
520
|
readonly loadFlag: string | null;
|
|
464
|
-
readonly overridesVia:
|
|
521
|
+
readonly overridesVia: SkillsOverridesVia | null;
|
|
465
522
|
} | null;
|
|
466
523
|
readonly tools: {
|
|
467
524
|
readonly includeFlag: string | null;
|
|
468
525
|
readonly excludeFlag: string | null;
|
|
469
526
|
readonly includeIsStrictAllowlist: boolean;
|
|
470
|
-
readonly composable: boolean;
|
|
471
527
|
readonly builtins: ReadonlyArray<{
|
|
472
528
|
readonly name: string;
|
|
473
529
|
readonly defaultEnabled: boolean;
|
|
@@ -479,6 +535,6 @@ export interface HarnessDescriptor {
|
|
|
479
535
|
readonly configKey: string | null;
|
|
480
536
|
readonly canonical: readonly CanonicalTool[];
|
|
481
537
|
}>;
|
|
482
|
-
readonly denySemantics:
|
|
538
|
+
readonly denySemantics: DenySemantics;
|
|
483
539
|
};
|
|
484
540
|
}
|
|
@@ -11,6 +11,41 @@ import type {
|
|
|
11
11
|
UnavailableMatcher,
|
|
12
12
|
} from "./descriptor.js";
|
|
13
13
|
|
|
14
|
+
/** Bounds on a matcher, enforced wherever one is compiled - the limits
|
|
15
|
+
* scanner and the override loader alike (RFC-02 change 9). They keep a
|
|
16
|
+
* crafted override file from DoS'ing the compiler or the scanner; the
|
|
17
|
+
* input window, not pattern analysis, is the backtracking bound. */
|
|
18
|
+
export const MAX_PATTERN_LENGTH = 200;
|
|
19
|
+
export const MAX_MATCHERS_PER_KIND = 64;
|
|
20
|
+
/** The only flags a matcher may carry. `g` and `y` are stateful and
|
|
21
|
+
* would make `test()` order-dependent. */
|
|
22
|
+
export const MATCHER_FLAGS = "imsu";
|
|
23
|
+
|
|
24
|
+
/** Compile one matcher under the bounds. Throws a plain Error naming the
|
|
25
|
+
* violated bound; loaders wrap it in their own refusal type. */
|
|
26
|
+
export const compileMatcher = (pattern: string, flags: string | undefined): RegExp => {
|
|
27
|
+
const f = flags ?? "i";
|
|
28
|
+
if (pattern.length > MAX_PATTERN_LENGTH) {
|
|
29
|
+
throw new Error(`pattern over ${MAX_PATTERN_LENGTH} characters`);
|
|
30
|
+
}
|
|
31
|
+
if (pattern.length === 0) {
|
|
32
|
+
throw new Error("pattern must not be empty");
|
|
33
|
+
}
|
|
34
|
+
if (f.includes("g") || f.includes("y")) {
|
|
35
|
+
throw new Error(`flags must not contain g or y (got ${JSON.stringify(f)})`);
|
|
36
|
+
}
|
|
37
|
+
for (const ch of f) {
|
|
38
|
+
if (!MATCHER_FLAGS.includes(ch)) {
|
|
39
|
+
throw new Error(`flag ${JSON.stringify(ch)} outside ${MATCHER_FLAGS}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
try {
|
|
43
|
+
return new RegExp(pattern, f);
|
|
44
|
+
} catch (e) {
|
|
45
|
+
throw new Error(`uncompilable pattern ${JSON.stringify(pattern)}: ${(e as Error).message}`);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
|
|
14
49
|
export const SHARED_LIMIT_MATCHERS: ReadonlyArray<LimitMatcher> = [
|
|
15
50
|
{ pattern: "you'?ve hit your usage limit", flags: "i", code: "usage-limit" },
|
|
16
51
|
{ pattern: "usage limit (?:reached|exceeded)", flags: "i", code: "usage-limit" },
|
package/src/knowledge/muse.ts
CHANGED
|
@@ -24,7 +24,6 @@ export const museCode: HarnessDescriptor = deepFreeze({
|
|
|
24
24
|
baseFlags: ["exec", "--json"],
|
|
25
25
|
subcommands: ["exec"],
|
|
26
26
|
promptStyle: "positional",
|
|
27
|
-
toolsFlag: null,
|
|
28
27
|
streamFlags: [],
|
|
29
28
|
idFlag: "--session-id",
|
|
30
29
|
},
|
|
@@ -116,10 +115,14 @@ export const museCode: HarnessDescriptor = deepFreeze({
|
|
|
116
115
|
max: 10000,
|
|
117
116
|
render: { kind: "flag-value", flag: "--max-model-steps" },
|
|
118
117
|
},
|
|
118
|
+
// read gates the write and shell categories; write is the harness
|
|
119
|
+
// default and emits nothing.
|
|
119
120
|
access: {
|
|
120
|
-
kind: "
|
|
121
|
-
|
|
122
|
-
|
|
121
|
+
kind: "access",
|
|
122
|
+
renders: {
|
|
123
|
+
read: { render: { kind: "flag-list", flags: ["--disable-write", "--disable-shell"] } },
|
|
124
|
+
write: null,
|
|
125
|
+
},
|
|
123
126
|
},
|
|
124
127
|
},
|
|
125
128
|
// Phase 0 fixtures: muse-category-flags.md. No name lists; category
|
|
@@ -133,7 +136,6 @@ export const museCode: HarnessDescriptor = deepFreeze({
|
|
|
133
136
|
includeFlag: null,
|
|
134
137
|
excludeFlag: null,
|
|
135
138
|
includeIsStrictAllowlist: false,
|
|
136
|
-
composable: false,
|
|
137
139
|
builtins: [],
|
|
138
140
|
categories: [
|
|
139
141
|
{
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
type HarnessName,
|
|
21
21
|
SESSION_INPUT_KINDS,
|
|
22
22
|
} from "./descriptor.js";
|
|
23
|
+
import { compileMatcher, MAX_MATCHERS_PER_KIND } from "./matchers.js";
|
|
23
24
|
import { museCode } from "./muse.js";
|
|
24
25
|
import { piCli } from "./pi.js";
|
|
25
26
|
|
|
@@ -159,36 +160,12 @@ const validateMatcherPattern = (
|
|
|
159
160
|
path: string,
|
|
160
161
|
harness: string,
|
|
161
162
|
): void => {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
throw new OverrideRefusalError(
|
|
165
|
-
path,
|
|
166
|
-
`pattern over 200 characters: ${JSON.stringify(pattern.slice(0, 40))}`,
|
|
167
|
-
harness,
|
|
168
|
-
);
|
|
169
|
-
}
|
|
170
|
-
if (pattern.length === 0) {
|
|
171
|
-
throw new OverrideRefusalError(path, `pattern must not be empty`, harness);
|
|
172
|
-
}
|
|
173
|
-
if (f.includes("g") || f.includes("y")) {
|
|
174
|
-
throw new OverrideRefusalError(
|
|
175
|
-
path,
|
|
176
|
-
`flags must not contain g or y (got ${JSON.stringify(f)})`,
|
|
177
|
-
harness,
|
|
178
|
-
);
|
|
179
|
-
}
|
|
180
|
-
for (const ch of f) {
|
|
181
|
-
if (!"imsu".includes(ch))
|
|
182
|
-
throw new OverrideRefusalError(path, `flag ${JSON.stringify(ch)} outside imsu`, harness);
|
|
183
|
-
}
|
|
163
|
+
// One compiler and one set of bounds, shared with the limits scanner
|
|
164
|
+
// (RFC-02 change 9); this loader only wraps the refusal.
|
|
184
165
|
try {
|
|
185
|
-
|
|
166
|
+
compileMatcher(pattern, flags);
|
|
186
167
|
} catch (e) {
|
|
187
|
-
throw new OverrideRefusalError(
|
|
188
|
-
path,
|
|
189
|
-
`uncompilable pattern ${JSON.stringify(pattern)}: ${(e as Error).message}`,
|
|
190
|
-
harness,
|
|
191
|
-
);
|
|
168
|
+
throw new OverrideRefusalError(path, (e as Error).message, harness);
|
|
192
169
|
}
|
|
193
170
|
};
|
|
194
171
|
|
|
@@ -196,8 +173,12 @@ const validateMatchers = (desc: HarnessDescriptor, path: string, harness: string
|
|
|
196
173
|
const limitMatchers = (desc as unknown as { limitMatchers: readonly unknown[] }).limitMatchers;
|
|
197
174
|
const authMatchers = (desc as unknown as { authMatchers: readonly unknown[] }).authMatchers;
|
|
198
175
|
if (Array.isArray(limitMatchers)) {
|
|
199
|
-
if (limitMatchers.length >
|
|
200
|
-
throw new OverrideRefusalError(
|
|
176
|
+
if (limitMatchers.length > MAX_MATCHERS_PER_KIND) {
|
|
177
|
+
throw new OverrideRefusalError(
|
|
178
|
+
path,
|
|
179
|
+
`more than ${MAX_MATCHERS_PER_KIND} limit matchers`,
|
|
180
|
+
harness,
|
|
181
|
+
);
|
|
201
182
|
}
|
|
202
183
|
for (const m of limitMatchers) {
|
|
203
184
|
if (!isPlain(m as unknown as Record<string, unknown>)) {
|
|
@@ -211,8 +192,12 @@ const validateMatchers = (desc: HarnessDescriptor, path: string, harness: string
|
|
|
211
192
|
}
|
|
212
193
|
}
|
|
213
194
|
if (Array.isArray(authMatchers)) {
|
|
214
|
-
if (authMatchers.length >
|
|
215
|
-
throw new OverrideRefusalError(
|
|
195
|
+
if (authMatchers.length > MAX_MATCHERS_PER_KIND) {
|
|
196
|
+
throw new OverrideRefusalError(
|
|
197
|
+
path,
|
|
198
|
+
`more than ${MAX_MATCHERS_PER_KIND} auth matchers`,
|
|
199
|
+
harness,
|
|
200
|
+
);
|
|
216
201
|
}
|
|
217
202
|
for (const m of authMatchers) {
|
|
218
203
|
if (!isPlain(m as unknown as Record<string, unknown>)) {
|
package/src/knowledge/pi.ts
CHANGED
|
@@ -22,7 +22,6 @@ export const piCli: HarnessDescriptor = deepFreeze({
|
|
|
22
22
|
baseFlags: ["-p", "--mode", "json"],
|
|
23
23
|
subcommands: [],
|
|
24
24
|
promptStyle: "positional",
|
|
25
|
-
toolsFlag: null,
|
|
26
25
|
streamFlags: [],
|
|
27
26
|
idFlag: "--session-id",
|
|
28
27
|
},
|
|
@@ -49,8 +48,10 @@ export const piCli: HarnessDescriptor = deepFreeze({
|
|
|
49
48
|
// --mode rpc exists on 0.84.2 and its session semantics are now VERIFIED
|
|
50
49
|
// against a live run (2026-08-19 spike, evidence at
|
|
51
50
|
// test/fixtures/pi-rpc-spike): JSONL both directions, agent_settled
|
|
52
|
-
// delimits turns, steer/follow_up queue mid-run (hcn
|
|
53
|
-
//
|
|
51
|
+
// delimits turns, steer/follow_up queue mid-run (hcn keeps no queue of
|
|
52
|
+
// its own since ADR 0007 and writes a send when it arrives; a bare
|
|
53
|
+
// prompt mid-run is refused with success:false - spike fixture 05, a
|
|
54
|
+
// pending change), identity is silent at startup and readable
|
|
54
55
|
// only via a get_state round trip, stdin EOF exits rc=0. The claude
|
|
55
56
|
// slice remains the proven vertical (D-003); this entry is the second.
|
|
56
57
|
sessionMode: {
|
|
@@ -73,7 +74,7 @@ export const piCli: HarnessDescriptor = deepFreeze({
|
|
|
73
74
|
resumeFlag: "--session-id",
|
|
74
75
|
input: { kind: "pi-rpc-prompt" },
|
|
75
76
|
turnEnd: { type: "agent_settled" },
|
|
76
|
-
identityProbe: { command: "get_state" },
|
|
77
|
+
identityProbe: { command: "get_state", responseIdField: "data.sessionId" },
|
|
77
78
|
},
|
|
78
79
|
output: {
|
|
79
80
|
// pi -p prints plain text; --mode json emits structured v3 records
|
|
@@ -173,7 +174,9 @@ export const piCli: HarnessDescriptor = deepFreeze({
|
|
|
173
174
|
},
|
|
174
175
|
},
|
|
175
176
|
},
|
|
176
|
-
|
|
177
|
+
// read renders the read preset through --tools (strict allowlist);
|
|
178
|
+
// write is the harness default and emits nothing.
|
|
179
|
+
access: { kind: "access", renders: { read: "tool-preset", write: null } },
|
|
177
180
|
},
|
|
178
181
|
// Phase 0 fixtures: pi-both-tool-flags.md. Both list flags legal at once;
|
|
179
182
|
// exclude subtracts from include. --tools is strict over BUILT-INS but
|
|
@@ -184,7 +187,6 @@ export const piCli: HarnessDescriptor = deepFreeze({
|
|
|
184
187
|
includeFlag: "--tools",
|
|
185
188
|
excludeFlag: "--exclude-tools",
|
|
186
189
|
includeIsStrictAllowlist: true,
|
|
187
|
-
composable: true,
|
|
188
190
|
builtins: [
|
|
189
191
|
{ name: "read", defaultEnabled: true, canonical: "read" },
|
|
190
192
|
{ name: "bash", defaultEnabled: true, canonical: "shell" },
|
package/src/knowledge/profile.ts
CHANGED
|
@@ -19,6 +19,7 @@ export const DEFAULT_TURN_PROFILE = deepFreeze({
|
|
|
19
19
|
// profile tier. On the other three the dimension is unrenderable and
|
|
20
20
|
// reports as divergence.
|
|
21
21
|
sandbox: "workspace-write",
|
|
22
|
+
contextWindow: 272000,
|
|
22
23
|
// Ratified: discovery fully ON. The harnesses' bare runs already
|
|
23
24
|
// discover instruction files, skills, and extensions; the profile makes
|
|
24
25
|
// that a stated contract. The off-spellings exist per harness
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Small dimension accessors: one interpretation function per PLAN 3.1
|
|
3
|
-
* dimension whose value is a direct descriptor lookup. They exist so every
|
|
4
|
-
* dimension has a single named owner in the interpretation layer - callers
|
|
5
|
-
* never reach into descriptor internals.
|
|
6
|
-
*/
|
|
7
|
-
import type { HarnessDescriptor } from "../knowledge/descriptor.js";
|
|
8
|
-
export declare const stdinPolicyOf: (h: HarnessDescriptor) => "inherit" | "close-required";
|
|
9
|
-
export declare const toolsFlagOf: (h: HarnessDescriptor) => string | null;
|
|
10
|
-
export declare const autonomyFlagOf: (h: HarnessDescriptor) => string | null;
|
|
11
|
-
//# sourceMappingURL=dimensions.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dimensions.d.ts","sourceRoot":"","sources":["../../src/interpretation/dimensions.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAEpE,eAAO,MAAM,aAAa,MAAO,iBAAiB,KAAG,SAAS,GAAG,gBAA2B,CAAC;AAE7F,eAAO,MAAM,WAAW,MAAO,iBAAiB,KAAG,MAAM,GAAG,IAA0B,CAAC;AAEvF,eAAO,MAAM,cAAc,MAAO,iBAAiB,KAAG,MAAM,GAAG,IACjB,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dimensions.js","sourceRoot":"","sources":["../../src/interpretation/dimensions.ts"],"names":[],"mappings":"AAQA,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAoB,EAAgC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;AAE7F,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAoB,EAAiB,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC;AAEvF,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAoB,EAAiB,EAAE,CACpE,CAAC,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC"}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Small dimension accessors: one interpretation function per PLAN 3.1
|
|
3
|
-
* dimension whose value is a direct descriptor lookup. They exist so every
|
|
4
|
-
* dimension has a single named owner in the interpretation layer - callers
|
|
5
|
-
* never reach into descriptor internals.
|
|
6
|
-
*/
|
|
7
|
-
import type { HarnessDescriptor } from "../knowledge/descriptor.js";
|
|
8
|
-
|
|
9
|
-
export const stdinPolicyOf = (h: HarnessDescriptor): "inherit" | "close-required" => h.stdin;
|
|
10
|
-
|
|
11
|
-
export const toolsFlagOf = (h: HarnessDescriptor): string | null => h.launch.toolsFlag;
|
|
12
|
-
|
|
13
|
-
export const autonomyFlagOf = (h: HarnessDescriptor): string | null =>
|
|
14
|
-
h.autonomy === null ? null : h.autonomy.flag;
|