@dungle-scrubs/harness-cli-normalizer 0.6.1 → 0.6.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/README.md +15 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +5 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/config.d.ts.map +1 -1
- package/dist/cli/config.js +2 -0
- package/dist/cli/config.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 +4 -0
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/plan-turn.d.ts.map +1 -1
- package/dist/cli/plan-turn.js +3 -1
- package/dist/cli/plan-turn.js.map +1 -1
- package/dist/cli/session.d.ts.map +1 -1
- package/dist/cli/session.js +11 -0
- package/dist/cli/session.js.map +1 -1
- package/dist/interpretation/argv.d.ts +1 -0
- package/dist/interpretation/argv.d.ts.map +1 -1
- package/dist/interpretation/argv.js +2 -0
- package/dist/interpretation/argv.js.map +1 -1
- package/dist/interpretation/isolation.d.ts +10 -0
- package/dist/interpretation/isolation.d.ts.map +1 -0
- package/dist/interpretation/isolation.js +30 -0
- package/dist/interpretation/isolation.js.map +1 -0
- package/dist/interpretation/resolve-options.d.ts.map +1 -1
- package/dist/interpretation/resolve-options.js +15 -1
- package/dist/interpretation/resolve-options.js.map +1 -1
- package/dist/interpretation/support.d.ts.map +1 -1
- package/dist/interpretation/support.js +2 -0
- package/dist/interpretation/support.js.map +1 -1
- package/dist/interpretation/turn-options.d.ts.map +1 -1
- package/dist/interpretation/turn-options.js +2 -0
- package/dist/interpretation/turn-options.js.map +1 -1
- package/dist/knowledge/claude-code.d.ts +3 -1
- package/dist/knowledge/claude-code.d.ts.map +1 -1
- package/dist/knowledge/claude-code.js +14 -1
- package/dist/knowledge/claude-code.js.map +1 -1
- package/dist/knowledge/descriptor.d.ts +1 -1
- package/dist/knowledge/descriptor.d.ts.map +1 -1
- package/dist/knowledge/descriptor.js +1 -0
- package/dist/knowledge/descriptor.js.map +1 -1
- package/dist/knowledge/muse.d.ts.map +1 -1
- package/dist/knowledge/muse.js +6 -1
- package/dist/knowledge/muse.js.map +1 -1
- package/package.json +1 -1
- package/src/cli/args.ts +4 -0
- package/src/cli/config.ts +2 -0
- package/src/cli/help.ts +4 -0
- package/src/cli/plan-turn.ts +5 -1
- package/src/cli/session.ts +17 -0
- package/src/interpretation/argv.ts +3 -0
- package/src/interpretation/isolation.ts +39 -0
- package/src/interpretation/resolve-options.ts +13 -1
- package/src/interpretation/support.ts +2 -0
- package/src/interpretation/turn-options.ts +2 -0
- package/src/knowledge/claude-code.ts +14 -1
- package/src/knowledge/descriptor.ts +1 -0
- package/src/knowledge/muse.ts +6 -1
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { HarnessDescriptor } from "../knowledge/descriptor.js";
|
|
2
|
+
import type { TurnOptions } from "./argv.js";
|
|
3
|
+
import { ArgvRefusalError } from "./refusal.js";
|
|
4
|
+
|
|
5
|
+
/** Isolation owns these dimensions for the whole invocation. Config defaults
|
|
6
|
+
* yield to it; explicit competing selections refuse before registry reads. */
|
|
7
|
+
export const ISOLATION_OVERRIDES = [
|
|
8
|
+
"tools",
|
|
9
|
+
"excludeTools",
|
|
10
|
+
"skills",
|
|
11
|
+
"access",
|
|
12
|
+
"autonomy",
|
|
13
|
+
"discovery",
|
|
14
|
+
] as const;
|
|
15
|
+
export const assertIsolationCombination = (
|
|
16
|
+
h: HarnessDescriptor,
|
|
17
|
+
opts: Partial<TurnOptions> & {
|
|
18
|
+
readonly skillNames?: readonly string[];
|
|
19
|
+
readonly passthrough?: readonly string[];
|
|
20
|
+
},
|
|
21
|
+
): void => {
|
|
22
|
+
if (opts.isolation === undefined) return;
|
|
23
|
+
const conflict =
|
|
24
|
+
ISOLATION_OVERRIDES.find((key) =>
|
|
25
|
+
key === "autonomy" ? opts[key] === true : opts[key] !== undefined,
|
|
26
|
+
) ??
|
|
27
|
+
(opts.skillNames !== undefined ? "skills" : undefined) ??
|
|
28
|
+
(opts.passthrough?.length ? "native passthrough" : undefined);
|
|
29
|
+
if (conflict === undefined) return;
|
|
30
|
+
throw new ArgvRefusalError({
|
|
31
|
+
issue: "mutually-exclusive-options",
|
|
32
|
+
harness: h.name,
|
|
33
|
+
option: "isolation",
|
|
34
|
+
detail: conflict,
|
|
35
|
+
supported: [
|
|
36
|
+
"tool-free without explicit tools, skills, access, autonomy, discovery, or native passthrough",
|
|
37
|
+
],
|
|
38
|
+
});
|
|
39
|
+
};
|
|
@@ -11,6 +11,7 @@ import type { HarnessDescriptor } from "../knowledge/descriptor.js";
|
|
|
11
11
|
import { defaultDescriptors } from "../knowledge/overrides.js";
|
|
12
12
|
import { DEFAULT_TURN_PROFILE, type ProfileKey } from "../knowledge/profile.js";
|
|
13
13
|
import type { TurnOptions } from "./argv.js";
|
|
14
|
+
import { assertIsolationCombination, ISOLATION_OVERRIDES } from "./isolation.js";
|
|
14
15
|
import type { QuestionMode } from "./question.js";
|
|
15
16
|
import { ArgvRefusalError } from "./refusal.js";
|
|
16
17
|
import type { ToolMapConfig } from "./tool-vocabulary.js";
|
|
@@ -152,10 +153,17 @@ export const resolveEffectiveOptions = (
|
|
|
152
153
|
args: TurnOptions,
|
|
153
154
|
tiers: ConfigTiers = {},
|
|
154
155
|
): ResolvedOptions => {
|
|
156
|
+
assertIsolationCombination(h, args);
|
|
155
157
|
const provenance: ProvenanceEntry[] = [];
|
|
158
|
+
if (args.isolation !== undefined)
|
|
159
|
+
provenance.push({ key: "isolation", value: args.isolation, tier: "arg" });
|
|
156
160
|
const unrenderable: string[] = [];
|
|
157
|
-
const config = effectiveConfig(tiers);
|
|
161
|
+
const config = { ...effectiveConfig(tiers) };
|
|
162
|
+
if (args.isolation !== undefined) {
|
|
163
|
+
for (const key of ISOLATION_OVERRIDES) delete config[key];
|
|
164
|
+
}
|
|
158
165
|
const sourceTier = (key: string): ProvenanceTier | undefined => {
|
|
166
|
+
if (config[key as keyof TurnOptions] === undefined) return undefined;
|
|
159
167
|
if (tiers.project?.[key as keyof TurnOptions] !== undefined) return "project-config";
|
|
160
168
|
if (tiers.user?.[key as keyof TurnOptions] !== undefined) return "user-config";
|
|
161
169
|
return undefined;
|
|
@@ -288,6 +296,10 @@ export const resolveEffectiveOptions = (
|
|
|
288
296
|
|
|
289
297
|
// Profile is the floor: apply only where nothing above it set the key.
|
|
290
298
|
for (const [key, value] of Object.entries(DEFAULT_TURN_PROFILE)) {
|
|
299
|
+
if (args.isolation !== undefined && ISOLATION_OVERRIDES.some((owned) => owned === key)) {
|
|
300
|
+
provenance.push({ key, value: "disabled (tool-free isolation)", tier: "arg" });
|
|
301
|
+
continue;
|
|
302
|
+
}
|
|
291
303
|
const argsSet = effectiveArgs[key as keyof TurnOptions] !== undefined;
|
|
292
304
|
const tier = sourceTier(key);
|
|
293
305
|
if (argsSet) {
|
|
@@ -51,6 +51,7 @@ const spellingOf = (h: HarnessDescriptor, option: RefusalOption): string | null
|
|
|
51
51
|
}
|
|
52
52
|
case "autonomy":
|
|
53
53
|
return h.autonomy?.flag ?? null;
|
|
54
|
+
case "isolation":
|
|
54
55
|
case "effort":
|
|
55
56
|
case "sandbox":
|
|
56
57
|
case "contextWindow":
|
|
@@ -124,6 +125,7 @@ export const recognizeNativeSpelling = (
|
|
|
124
125
|
"tools",
|
|
125
126
|
"excludeTools",
|
|
126
127
|
"autonomy",
|
|
128
|
+
"isolation",
|
|
127
129
|
"effort",
|
|
128
130
|
"sandbox",
|
|
129
131
|
"contextWindow",
|
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
import { defaultDescriptors } from "../knowledge/overrides.js";
|
|
25
25
|
import type { DiscoveryOptions, TurnOptions } from "./argv.js";
|
|
26
26
|
import { hintFor } from "./hints.js";
|
|
27
|
+
import { assertIsolationCombination } from "./isolation.js";
|
|
27
28
|
import { ArgvRefusalError } from "./refusal.js";
|
|
28
29
|
import { supportedBy } from "./support.js";
|
|
29
30
|
import { renderToolSelection } from "./tool-selection.js";
|
|
@@ -41,6 +42,7 @@ export const renderTurnOptions = (
|
|
|
41
42
|
opts: TurnOptions,
|
|
42
43
|
phase: "launch" | "resume",
|
|
43
44
|
): string[] => {
|
|
45
|
+
assertIsolationCombination(h, opts);
|
|
44
46
|
const sequences: string[][] = [];
|
|
45
47
|
// The turn option the access preset displaces when set (codex: sandbox),
|
|
46
48
|
// read from the descriptor so no arm below branches on a harness name.
|
|
@@ -9,7 +9,9 @@
|
|
|
9
9
|
* `ANTHROPIC_API_KEY` / `apiKeyHelper` (OAuth never read) - so a caller
|
|
10
10
|
* authenticated via OAuth would break. The descriptor therefore offers no
|
|
11
11
|
* `instructionFiles` facet and a call passing it must refuse. Likewise
|
|
12
|
-
* `tools` has no discovery flag on claude and refuses.
|
|
12
|
+
* `tools` has no discovery flag on claude and refuses. The explicit
|
|
13
|
+
* tool-free isolation composite below accepts the bare-mode auth cost and
|
|
14
|
+
* disables native tools too. It is separate from a granular discovery facet.
|
|
13
15
|
*
|
|
14
16
|
* Effort: A-002 showed `--effort bogus` warns on stderr and runs at DEFAULT
|
|
15
17
|
* effort, exit 0, with nothing echoed in the stream. The library-side
|
|
@@ -161,6 +163,17 @@ export const claudeCode: HarnessDescriptor = deepFreeze({
|
|
|
161
163
|
observedOn: { harness: "claude", model: "", version: "2.1.235", date: "2026-08-19" },
|
|
162
164
|
},
|
|
163
165
|
turnOptions: {
|
|
166
|
+
// Native CLI reference: bare removes discovery; the empty built-in list and
|
|
167
|
+
// MCP deny remove tool access. Resume and native overrides are refused.
|
|
168
|
+
isolation: {
|
|
169
|
+
kind: "enum",
|
|
170
|
+
values: ["tool-free"],
|
|
171
|
+
resumeRender: null,
|
|
172
|
+
render: {
|
|
173
|
+
kind: "flag-list",
|
|
174
|
+
flags: ["--bare", "--tools", "", "--disallowedTools", "mcp__*", "--strict-mcp-config"],
|
|
175
|
+
},
|
|
176
|
+
},
|
|
164
177
|
effort: { kind: "effort", render: { kind: "flag-value", flag: "--effort" } },
|
|
165
178
|
// issue #48, live-verified 2.1.235: --system-prompt replaces the built-in
|
|
166
179
|
// prompt; --exclude-dynamic-system-prompt-sections strips the dynamic
|
|
@@ -146,6 +146,7 @@ export type UnavailableMatcher = PhraseMatcher;
|
|
|
146
146
|
* arm would be dead data that can only drift. Render order is the tuple
|
|
147
147
|
* order, so argv is deterministic regardless of caller field order. */
|
|
148
148
|
export const TURN_OPTION_KEYS = deepFreeze([
|
|
149
|
+
"isolation",
|
|
149
150
|
"effort",
|
|
150
151
|
"sandbox",
|
|
151
152
|
"contextWindow",
|
package/src/knowledge/muse.ts
CHANGED
|
@@ -59,7 +59,12 @@ export const museCode: HarnessDescriptor = deepFreeze({
|
|
|
59
59
|
autonomy: { flag: "--yolo" },
|
|
60
60
|
vocabulary: {
|
|
61
61
|
modelFlag: "--model",
|
|
62
|
-
models: [
|
|
62
|
+
models: [
|
|
63
|
+
"muse-spark-1.3-contributor",
|
|
64
|
+
"muse-spark-1.2-contributor",
|
|
65
|
+
"muse-spark-1.2",
|
|
66
|
+
"muse-spark-1.1",
|
|
67
|
+
],
|
|
63
68
|
aliases: {},
|
|
64
69
|
efforts: ["none", "minimal", "low", "medium", "high", "xhigh"],
|
|
65
70
|
extensible: false,
|