@dungle-scrubs/harness-cli-normalizer 0.6.0 → 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.
Files changed (219) hide show
  1. package/README.md +33 -6
  2. package/dist/cli/args.d.ts +9 -1
  3. package/dist/cli/args.d.ts.map +1 -1
  4. package/dist/cli/args.js +36 -26
  5. package/dist/cli/args.js.map +1 -1
  6. package/dist/cli/check.d.ts +14 -0
  7. package/dist/cli/check.d.ts.map +1 -1
  8. package/dist/cli/check.js +10 -3
  9. package/dist/cli/check.js.map +1 -1
  10. package/dist/cli/config.d.ts +4 -4
  11. package/dist/cli/config.d.ts.map +1 -1
  12. package/dist/cli/config.js +8 -6
  13. package/dist/cli/config.js.map +1 -1
  14. package/dist/cli/exit-codes.d.ts +0 -1
  15. package/dist/cli/exit-codes.d.ts.map +1 -1
  16. package/dist/cli/exit-codes.js +0 -1
  17. package/dist/cli/exit-codes.js.map +1 -1
  18. package/dist/cli/help.d.ts +2 -2
  19. package/dist/cli/help.d.ts.map +1 -1
  20. package/dist/cli/help.js +10 -2
  21. package/dist/cli/help.js.map +1 -1
  22. package/dist/cli/index.d.ts.map +1 -1
  23. package/dist/cli/index.js +3 -1
  24. package/dist/cli/index.js.map +1 -1
  25. package/dist/cli/inspect.d.ts.map +1 -1
  26. package/dist/cli/inspect.js +84 -265
  27. package/dist/cli/inspect.js.map +1 -1
  28. package/dist/cli/plan-turn.d.ts +68 -0
  29. package/dist/cli/plan-turn.d.ts.map +1 -0
  30. package/dist/cli/plan-turn.js +268 -0
  31. package/dist/cli/plan-turn.js.map +1 -0
  32. package/dist/cli/refuse.d.ts.map +1 -1
  33. package/dist/cli/refuse.js +2 -1
  34. package/dist/cli/refuse.js.map +1 -1
  35. package/dist/cli/resolve-harness.d.ts.map +1 -1
  36. package/dist/cli/resolve-harness.js +2 -3
  37. package/dist/cli/resolve-harness.js.map +1 -1
  38. package/dist/cli/run.d.ts.map +1 -1
  39. package/dist/cli/run.js +33 -367
  40. package/dist/cli/run.js.map +1 -1
  41. package/dist/cli/session-json.d.ts +1 -1
  42. package/dist/cli/session-json.d.ts.map +1 -1
  43. package/dist/cli/session-json.js +1 -3
  44. package/dist/cli/session-json.js.map +1 -1
  45. package/dist/cli/session.d.ts.map +1 -1
  46. package/dist/cli/session.js +35 -43
  47. package/dist/cli/session.js.map +1 -1
  48. package/dist/cli/skills-root.d.ts +1 -1
  49. package/dist/cli/skills-root.d.ts.map +1 -1
  50. package/dist/cli/skills-root.js +1 -1
  51. package/dist/cli/skills-root.js.map +1 -1
  52. package/dist/execution/decode.d.ts.map +1 -1
  53. package/dist/execution/decode.js +11 -36
  54. package/dist/execution/decode.js.map +1 -1
  55. package/dist/execution/events.d.ts +4 -1
  56. package/dist/execution/events.d.ts.map +1 -1
  57. package/dist/execution/events.js.map +1 -1
  58. package/dist/execution/failure.d.ts +3 -1
  59. package/dist/execution/failure.d.ts.map +1 -1
  60. package/dist/execution/failure.js +14 -11
  61. package/dist/execution/failure.js.map +1 -1
  62. package/dist/execution/open-session.d.ts +1 -1
  63. package/dist/execution/open-session.d.ts.map +1 -1
  64. package/dist/execution/open-session.js +150 -223
  65. package/dist/execution/open-session.js.map +1 -1
  66. package/dist/execution/stream-turn.d.ts +9 -14
  67. package/dist/execution/stream-turn.d.ts.map +1 -1
  68. package/dist/execution/stream-turn.js +85 -188
  69. package/dist/execution/stream-turn.js.map +1 -1
  70. package/dist/execution/supervisor.d.ts +71 -0
  71. package/dist/execution/supervisor.d.ts.map +1 -0
  72. package/dist/execution/supervisor.js +127 -0
  73. package/dist/execution/supervisor.js.map +1 -0
  74. package/dist/interpretation/argv.d.ts +39 -12
  75. package/dist/interpretation/argv.d.ts.map +1 -1
  76. package/dist/interpretation/argv.js +28 -20
  77. package/dist/interpretation/argv.js.map +1 -1
  78. package/dist/interpretation/content.d.ts +10 -1
  79. package/dist/interpretation/content.d.ts.map +1 -1
  80. package/dist/interpretation/content.js +20 -11
  81. package/dist/interpretation/content.js.map +1 -1
  82. package/dist/interpretation/hints.d.ts +1 -1
  83. package/dist/interpretation/hints.d.ts.map +1 -1
  84. package/dist/interpretation/hints.js +10 -11
  85. package/dist/interpretation/hints.js.map +1 -1
  86. package/dist/interpretation/index.d.ts +0 -1
  87. package/dist/interpretation/index.d.ts.map +1 -1
  88. package/dist/interpretation/index.js +0 -1
  89. package/dist/interpretation/index.js.map +1 -1
  90. package/dist/interpretation/isolation.d.ts +10 -0
  91. package/dist/interpretation/isolation.d.ts.map +1 -0
  92. package/dist/interpretation/isolation.js +30 -0
  93. package/dist/interpretation/isolation.js.map +1 -0
  94. package/dist/interpretation/limits.d.ts +2 -5
  95. package/dist/interpretation/limits.d.ts.map +1 -1
  96. package/dist/interpretation/limits.js +8 -62
  97. package/dist/interpretation/limits.js.map +1 -1
  98. package/dist/interpretation/question.d.ts +27 -0
  99. package/dist/interpretation/question.d.ts.map +1 -1
  100. package/dist/interpretation/question.js +28 -0
  101. package/dist/interpretation/question.js.map +1 -1
  102. package/dist/interpretation/refusal.d.ts +10 -5
  103. package/dist/interpretation/refusal.d.ts.map +1 -1
  104. package/dist/interpretation/refusal.js +24 -15
  105. package/dist/interpretation/refusal.js.map +1 -1
  106. package/dist/interpretation/resolve-options.d.ts +36 -2
  107. package/dist/interpretation/resolve-options.d.ts.map +1 -1
  108. package/dist/interpretation/resolve-options.js +53 -22
  109. package/dist/interpretation/resolve-options.js.map +1 -1
  110. package/dist/interpretation/session-input.d.ts +44 -1
  111. package/dist/interpretation/session-input.d.ts.map +1 -1
  112. package/dist/interpretation/session-input.js +59 -4
  113. package/dist/interpretation/session-input.js.map +1 -1
  114. package/dist/interpretation/shape.d.ts +1 -0
  115. package/dist/interpretation/shape.d.ts.map +1 -1
  116. package/dist/interpretation/shape.js +10 -0
  117. package/dist/interpretation/shape.js.map +1 -1
  118. package/dist/interpretation/skills-selection.d.ts +25 -33
  119. package/dist/interpretation/skills-selection.d.ts.map +1 -1
  120. package/dist/interpretation/skills-selection.js +41 -48
  121. package/dist/interpretation/skills-selection.js.map +1 -1
  122. package/dist/interpretation/support.d.ts.map +1 -1
  123. package/dist/interpretation/support.js +25 -8
  124. package/dist/interpretation/support.js.map +1 -1
  125. package/dist/interpretation/tool-selection.d.ts +7 -6
  126. package/dist/interpretation/tool-selection.d.ts.map +1 -1
  127. package/dist/interpretation/tool-selection.js +54 -116
  128. package/dist/interpretation/tool-selection.js.map +1 -1
  129. package/dist/interpretation/tool-vocabulary.d.ts +31 -12
  130. package/dist/interpretation/tool-vocabulary.d.ts.map +1 -1
  131. package/dist/interpretation/tool-vocabulary.js +19 -41
  132. package/dist/interpretation/tool-vocabulary.js.map +1 -1
  133. package/dist/interpretation/turn-options.d.ts +4 -0
  134. package/dist/interpretation/turn-options.d.ts.map +1 -1
  135. package/dist/interpretation/turn-options.js +107 -241
  136. package/dist/interpretation/turn-options.js.map +1 -1
  137. package/dist/interpretation/vocabulary.d.ts +8 -6
  138. package/dist/interpretation/vocabulary.d.ts.map +1 -1
  139. package/dist/interpretation/vocabulary.js +22 -9
  140. package/dist/interpretation/vocabulary.js.map +1 -1
  141. package/dist/knowledge/claude-code.d.ts +3 -1
  142. package/dist/knowledge/claude-code.d.ts.map +1 -1
  143. package/dist/knowledge/claude-code.js +17 -4
  144. package/dist/knowledge/claude-code.js.map +1 -1
  145. package/dist/knowledge/codex.d.ts.map +1 -1
  146. package/dist/knowledge/codex.js +31 -7
  147. package/dist/knowledge/codex.js.map +1 -1
  148. package/dist/knowledge/descriptor.d.ts +67 -36
  149. package/dist/knowledge/descriptor.d.ts.map +1 -1
  150. package/dist/knowledge/descriptor.js +50 -15
  151. package/dist/knowledge/descriptor.js.map +1 -1
  152. package/dist/knowledge/matchers.d.ts +12 -0
  153. package/dist/knowledge/matchers.d.ts.map +1 -1
  154. package/dist/knowledge/matchers.js +34 -0
  155. package/dist/knowledge/matchers.js.map +1 -1
  156. package/dist/knowledge/muse.d.ts.map +1 -1
  157. package/dist/knowledge/muse.js +13 -6
  158. package/dist/knowledge/muse.js.map +1 -1
  159. package/dist/knowledge/overrides.d.ts.map +1 -1
  160. package/dist/knowledge/overrides.js +9 -20
  161. package/dist/knowledge/overrides.js.map +1 -1
  162. package/dist/knowledge/pi.d.ts.map +1 -1
  163. package/dist/knowledge/pi.js +8 -6
  164. package/dist/knowledge/pi.js.map +1 -1
  165. package/dist/knowledge/profile.d.ts +1 -0
  166. package/dist/knowledge/profile.d.ts.map +1 -1
  167. package/dist/knowledge/profile.js +1 -0
  168. package/dist/knowledge/profile.js.map +1 -1
  169. package/package.json +1 -1
  170. package/src/cli/args.ts +39 -27
  171. package/src/cli/check.ts +10 -3
  172. package/src/cli/config.ts +14 -11
  173. package/src/cli/exit-codes.ts +0 -2
  174. package/src/cli/help.ts +10 -2
  175. package/src/cli/index.ts +3 -1
  176. package/src/cli/inspect.ts +88 -269
  177. package/src/cli/plan-turn.ts +350 -0
  178. package/src/cli/refuse.ts +2 -1
  179. package/src/cli/resolve-harness.ts +4 -5
  180. package/src/cli/run.ts +36 -399
  181. package/src/cli/session-json.ts +1 -6
  182. package/src/cli/session.ts +51 -44
  183. package/src/cli/skills-root.ts +1 -4
  184. package/src/execution/decode.ts +10 -36
  185. package/src/execution/events.ts +4 -1
  186. package/src/execution/failure.ts +18 -11
  187. package/src/execution/open-session.ts +154 -228
  188. package/src/execution/stream-turn.ts +90 -193
  189. package/src/execution/supervisor.ts +199 -0
  190. package/src/interpretation/argv.ts +65 -34
  191. package/src/interpretation/content.ts +30 -13
  192. package/src/interpretation/hints.ts +2 -12
  193. package/src/interpretation/index.ts +0 -1
  194. package/src/interpretation/isolation.ts +39 -0
  195. package/src/interpretation/limits.ts +14 -75
  196. package/src/interpretation/question.ts +46 -0
  197. package/src/interpretation/refusal.ts +28 -18
  198. package/src/interpretation/resolve-options.ts +98 -33
  199. package/src/interpretation/session-input.ts +88 -5
  200. package/src/interpretation/shape.ts +10 -0
  201. package/src/interpretation/skills-selection.ts +70 -74
  202. package/src/interpretation/support.ts +21 -6
  203. package/src/interpretation/tool-selection.ts +67 -122
  204. package/src/interpretation/tool-vocabulary.ts +48 -53
  205. package/src/interpretation/turn-options.ts +125 -220
  206. package/src/interpretation/vocabulary.ts +15 -10
  207. package/src/knowledge/claude-code.ts +17 -4
  208. package/src/knowledge/codex.ts +31 -7
  209. package/src/knowledge/descriptor.ts +106 -49
  210. package/src/knowledge/matchers.ts +35 -0
  211. package/src/knowledge/muse.ts +13 -6
  212. package/src/knowledge/overrides.ts +17 -32
  213. package/src/knowledge/pi.ts +8 -6
  214. package/src/knowledge/profile.ts +1 -0
  215. package/dist/interpretation/dimensions.d.ts +0 -11
  216. package/dist/interpretation/dimensions.d.ts.map +0 -1
  217. package/dist/interpretation/dimensions.js +0 -4
  218. package/dist/interpretation/dimensions.js.map +0 -1
  219. package/src/interpretation/dimensions.ts +0 -14
@@ -1,69 +1,63 @@
1
- import { redactArgv } from "../execution/stream-turn.js";
2
- import { buildLaunchArgv } from "../interpretation/argv.js";
3
1
  import { capabilitiesOf } from "../interpretation/capabilities.js";
4
- import { ArgvRefusalError } from "../interpretation/refusal.js";
5
- import { FloorExceededError, resolveEffectiveOptions } from "../interpretation/resolve-options.js";
6
2
  import { canonicalTable, mergeToolMaps } from "../interpretation/tool-vocabulary.js";
7
- import type { HarnessMode } from "../knowledge/descriptor.js";
3
+ import { HARNESS_MODES, type HarnessMode } from "../knowledge/descriptor.js";
8
4
  import { defaultDescriptors } from "../knowledge/overrides.js";
9
- import { parseTurnOptions, resolvePromptAsync } from "./args.js";
5
+ import { splitPassthrough } from "./args.js";
10
6
  import { ConfigError, loadProjectConfig, loadUserConfig } from "./config.js";
11
7
  import { EXIT_REFUSAL } from "./exit-codes.js";
12
- import { refusalOf, refuse } from "./refuse.js";
8
+ import { planTurn, writePlanDiagnostics } from "./plan-turn.js";
9
+ import { refuse } from "./refuse.js";
13
10
  import { resolveHarness } from "./resolve-harness.js";
14
11
 
15
- const HARNESS_MODES = ["headless-turn", "headless-session", "interactive"] as const;
16
-
17
12
  export const inspect = async (harnessName: string, rawArgs: string[]): Promise<void> => {
18
13
  const h = resolveHarness(harnessName);
14
+ const { normalized } = splitPassthrough(rawArgs);
19
15
 
20
- // Check for --help
21
- if (rawArgs.includes("--help") || rawArgs.includes("-h")) {
16
+ if (normalized.includes("--help") || normalized.includes("-h")) {
22
17
  const { INSPECT_HELP } = await import("./help.js");
23
18
  process.stdout.write(INSPECT_HELP);
24
19
  return;
25
20
  }
26
21
 
27
- // Check for positional prompt injection before parse (only when --argv and no explicit prompt)
28
- const { parseCommonFlags, detectPositionalPromptInjection } = await import("./args.js");
29
- if (rawArgs.includes("--argv")) {
30
- const injection = detectPositionalPromptInjection(rawArgs.filter((a) => a !== "--argv"));
31
- if (injection) {
32
- const err = new ArgvRefusalError({
33
- issue: "prompt-flag-injection",
34
- harness: h.name,
35
- supported: ["prompt must not start with '-'"],
36
- detail: `it would be parsed as a flag by ${h.bin}`,
37
- });
38
- process.stderr.write(`${err.message}\n`);
39
- process.stderr.write(`supported: prompt must not start with '-'\n`);
40
- process.exitCode = 2;
22
+ // --argv: the preview is the plan the run command would spawn from, so
23
+ // the two agree by construction (RFC-02 change 10). Refusals go through
24
+ // the shared refuse path like every other command's.
25
+ if (normalized.includes("--argv")) {
26
+ if (normalized.includes("--capabilities")) {
27
+ process.stderr.write(`--capabilities and --argv are mutually exclusive; pick one\n`);
28
+ process.exitCode = EXIT_REFUSAL;
29
+ return;
30
+ }
31
+ const outcome = await planTurn(h, rawArgs, { command: "inspect" });
32
+ if (outcome.kind === "refusal") {
33
+ refuse(outcome.refusal, false);
41
34
  return;
42
35
  }
36
+ writePlanDiagnostics(h, outcome.plan, "argv");
37
+ process.stdout.write(`${JSON.stringify(outcome.plan.redactedArgv)}\n`);
38
+ return;
43
39
  }
44
40
 
45
- // Parse flags for inspect
41
+ // --capabilities path: pure capability record, no spawn, no config, no prompt
42
+ const { parseCommonFlags } = await import("./args.js");
46
43
  let parsed: ReturnType<typeof parseCommonFlags>;
47
44
  try {
48
45
  parsed = parseCommonFlags(rawArgs);
49
46
  } catch (err) {
50
47
  const message = err instanceof Error ? err.message : String(err);
51
- process.stderr.write(`unknown flag: ${message}\n`);
52
- process.stderr.write(`Run 'hcn inspect --help' for usage.\n`);
53
- process.exitCode = 2;
48
+ refuse(
49
+ {
50
+ message: `unknown flag: ${message}`,
51
+ issue: "invalid-option-value",
52
+ trailer: ["Run 'hcn inspect --help' for usage."],
53
+ },
54
+ false,
55
+ );
54
56
  return;
55
57
  }
56
-
57
58
  const values = parsed.values as Record<string, unknown>;
58
- const wantArgv = values.argv === true;
59
59
 
60
- // --capabilities path: pure capability record, no spawn, no config, no prompt
61
60
  if (values.capabilities === true) {
62
- if (wantArgv) {
63
- process.stderr.write(`--capabilities and --argv are mutually exclusive; pick one\n`);
64
- process.exitCode = EXIT_REFUSAL;
65
- return;
66
- }
67
61
  const mode = values.mode === undefined ? "headless-turn" : String(values.mode);
68
62
  if (!(HARNESS_MODES as readonly string[]).includes(mode)) {
69
63
  process.stderr.write(
@@ -78,247 +72,72 @@ export const inspect = async (harnessName: string, rawArgs: string[]): Promise<v
78
72
  return;
79
73
  }
80
74
 
81
- // Load config once at top and reuse for both paths
82
- let rawUserMap: Record<string, Record<string, string>> | undefined;
83
- let rawProjectMap: Record<string, Record<string, string>> | undefined;
84
- let loadedTiers: {
85
- user?: import("../interpretation/argv.js").TurnOptions;
86
- project?: import("../interpretation/argv.js").TurnOptions;
87
- } = {};
75
+ // The descriptor dump, with the tool vocabulary slice the config tiers
76
+ // extend.
77
+ let userMap: ReturnType<typeof loadUserConfig> = null;
78
+ let projectMap: ReturnType<typeof loadProjectConfig> = null;
88
79
  try {
89
- const u = loadUserConfig();
90
- rawUserMap = (u?.config as { toolMap?: Record<string, Record<string, string>> } | undefined)
91
- ?.toolMap;
92
- if (u) loadedTiers = { ...loadedTiers, user: u.config as never };
93
- const p = loadProjectConfig();
94
- rawProjectMap = (p?.config as { toolMap?: Record<string, Record<string, string>> } | undefined)
95
- ?.toolMap;
96
- if (p) loadedTiers = { ...loadedTiers, project: p.config as never };
80
+ userMap = loadUserConfig();
81
+ projectMap = loadProjectConfig();
97
82
  } catch (e) {
98
83
  if (e instanceof ConfigError) {
99
- process.stderr.write(`config error: ${(e as Error).message}\n`);
100
- process.exitCode = 2;
84
+ refuse({ message: `config error: ${e.message}`, issue: "invalid-option-value" }, false);
101
85
  return;
102
86
  }
103
87
  throw e;
104
88
  }
105
- const merged = mergeToolMaps({ user: rawUserMap, project: rawProjectMap });
106
-
107
- if (!wantArgv) {
108
- const table = canonicalTable(defaultDescriptors());
109
- const slice: Record<string, unknown> = {};
110
- const allCanonicalForInspect = [
111
- ...new Set([...Object.keys(table), ...Object.keys(merged[h.name] ?? {})]),
112
- ].sort();
113
- for (const canonical of allCanonicalForInspect) {
114
- const perHarness = table[canonical] as Record<string, unknown> | undefined;
115
- const v = perHarness?.[h.name];
116
- const mapped = merged[h.name]?.[canonical];
117
- if (mapped !== undefined) {
118
- slice[canonical] = { native: mapped.native, source: mapped.tier };
119
- } else if (v !== undefined) {
120
- const vv = v as { kind: string; native?: string; key?: string };
121
- const val =
122
- vv.kind === "builtin"
123
- ? { native: vv.native, source: "descriptor" }
124
- : { ...vv, source: "descriptor" };
125
- slice[canonical] = val;
126
- } else {
127
- slice[canonical] = { native: null, source: "none" };
128
- }
89
+ const merged = mergeToolMaps({
90
+ user: userMap?.config.toolMap,
91
+ project: projectMap?.config.toolMap,
92
+ });
93
+ const table = canonicalTable(defaultDescriptors());
94
+ const slice: Record<string, unknown> = {};
95
+ const allCanonicalForInspect = [
96
+ ...new Set([...Object.keys(table), ...Object.keys(merged[h.name] ?? {})]),
97
+ ].sort();
98
+ for (const canonical of allCanonicalForInspect) {
99
+ const v = table[canonical]?.[h.name];
100
+ const mapped = merged[h.name]?.[canonical];
101
+ if (mapped !== undefined) {
102
+ slice[canonical] = { native: mapped.native, source: mapped.tier };
103
+ } else if (v !== undefined) {
104
+ slice[canonical] =
105
+ v.kind === "builtin"
106
+ ? { native: v.native, source: "descriptor" }
107
+ : { ...v, source: "descriptor" };
108
+ } else {
109
+ slice[canonical] = { native: null, source: "none" };
129
110
  }
130
- const out = {
131
- name: h.name,
132
- bin: h.bin,
133
- verifiedAgainst: h.verifiedAgainst,
134
- versionSource: h.versionSource,
135
- launch: {
136
- baseFlags: h.launch.baseFlags,
137
- subcommands: h.launch.subcommands,
138
- streamFlags: h.launch.streamFlags,
139
- promptStyle: h.launch.promptStyle,
140
- toolsFlag: h.launch.toolsFlag,
141
- idFlag: h.launch.idFlag,
142
- },
143
- resume: h.resume,
144
- sessionMode: h.sessionMode,
145
- vocabulary: {
146
- models: h.vocabulary.models,
147
- aliases: h.vocabulary.aliases,
148
- efforts: h.vocabulary.efforts,
149
- effortsByModel: (h.vocabulary as { effortsByModel?: unknown }).effortsByModel,
150
- extensible: h.vocabulary.extensible,
151
- modelFlag: h.vocabulary.modelFlag,
152
- },
153
- turnOptions: h.turnOptions,
154
- limitMatchers: h.limitMatchers,
155
- authMatchers: h.authMatchers,
156
- toolVocabulary: slice,
157
- };
158
- process.stdout.write(`${JSON.stringify(out, null, 2)}\n`);
159
- return;
160
- }
161
-
162
- // --argv preview path: need prompt + turn options
163
- const positional = parsed.positionals as string[];
164
- // positional[0] would be harness already consumed, but we passed rawArgs without harness - check: caller passes remaining after harness
165
- // So positionals are potential prompt positional if not using --prompt
166
- const positionalPrompt = positional.length > 0 ? positional[0] : undefined;
167
- if (positional.length > 1) {
168
- process.stderr.write(`too many positionals for inspect --argv\n`);
169
- process.exitCode = 2;
170
- return;
171
- }
172
-
173
- let prompt: string;
174
- let promptSource: string;
175
- try {
176
- const resolved = await resolvePromptAsync({
177
- positionalPrompt,
178
- promptFlag: values.prompt as string | undefined,
179
- promptFile: values["prompt-file"] as string | undefined,
180
- });
181
- prompt = resolved.prompt;
182
- promptSource = resolved.source;
183
- } catch (err) {
184
- if (err instanceof ArgvRefusalError) {
185
- process.stderr.write(`${err.message}\n`);
186
- if (err.supported.length) process.stderr.write(`supported: ${err.supported.join(", ")}\n`);
187
- process.exitCode = 2;
188
- return;
189
- }
190
- throw err;
191
111
  }
192
-
193
- // Build TurnOptions from flags
194
- let turnOpts: ReturnType<typeof parseTurnOptions>;
195
- try {
196
- turnOpts = parseTurnOptions(values);
197
- } catch (err) {
198
- if (err instanceof ArgvRefusalError) {
199
- process.stderr.write(`${err.message}\n`);
200
- if (err.supported.length) process.stderr.write(`supported: ${err.supported.join(", ")}\n`);
201
- process.exitCode = 2;
202
- return;
203
- }
204
- throw err;
205
- }
206
-
207
- // Mirror run.ts skills resolution (F-16): resolve names and build claude tokens
208
- const rawSkills = (turnOpts as unknown as { skills?: string[] }).skills;
209
- if (rawSkills !== undefined && rawSkills.length > 0) {
210
- try {
211
- const { resolveSkillNames, listKnownSkills } = await import("./skills-root.js");
212
- const resolvedSkills = resolveSkillNames(rawSkills, h.name);
213
- const skillTokens: string[] = [];
214
- if (h.name === "claude") {
215
- const { claudeSkillOverridesArg } = await import("../interpretation/skills-selection.js");
216
- skillTokens.push(...claudeSkillOverridesArg(listKnownSkills(), resolvedSkills));
217
- } else if (h.name === "codex") {
218
- const { codexSkillConfigArg } = await import("../interpretation/skills-selection.js");
219
- skillTokens.push(...codexSkillConfigArg(listKnownSkills(), resolvedSkills));
220
- }
221
- (turnOpts as unknown as Record<string, unknown>).skills = resolvedSkills;
222
- (turnOpts as unknown as Record<string, unknown>).__skillTokens = skillTokens;
223
- } catch (err) {
224
- if (err instanceof ArgvRefusalError) {
225
- process.stderr.write(`${err.message}\n`);
226
- if (err.supported.length) process.stderr.write(`supported: ${err.supported.join(", ")}\n`);
227
- process.exitCode = 2;
228
- return;
229
- }
230
- throw err;
231
- }
232
- }
233
-
234
- // Resume previews from unresolved options, mirroring run.ts launch-only rule (F-15)
235
- if (values.resume !== undefined || values["session-id"] !== undefined) {
236
- if (values.resume !== undefined && values["session-id"] !== undefined) {
237
- const err = new ArgvRefusalError({
238
- issue: "mutually-exclusive-options",
239
- harness: h.name,
240
- supported: ["--resume or --session-id, not both (--session-id is an alias for --resume)"],
241
- detail: "both --resume and --session-id given",
242
- });
243
- process.stderr.write(`${err.message}\n`);
244
- if (err.supported.length) process.stderr.write(`supported: ${err.supported.join(", ")}\n`);
245
- process.exitCode = 2;
246
- return;
247
- }
248
- const { buildResumeArgv } = await import("../interpretation/argv.js");
249
- const resumeId = String(values.resume ?? values["session-id"]);
250
- try {
251
- const resumeOpts = {
252
- ...(turnOpts as object),
253
- prompt,
254
- sessionId: resumeId,
255
- ...(promptSource !== "positional" ? { __explicitPrompt: true as const } : {}),
256
- } as Parameters<typeof buildResumeArgv>[1];
257
- const resumeArgv = buildResumeArgv(h, resumeOpts);
258
- const redactedResume = redactArgv(resumeArgv, prompt);
259
- process.stdout.write(`${JSON.stringify(redactedResume)}\n`);
260
- process.stderr.write(`argv: ${redactedResume.join(" ")}\n`);
261
- return;
262
- } catch (err) {
263
- if (err instanceof ArgvRefusalError) {
264
- process.stderr.write(`${err.message}\n`);
265
- if (err.supported.length) process.stderr.write(`supported: ${err.supported.join(", ")}\n`);
266
- process.exitCode = 2;
267
- return;
268
- }
269
- throw err;
270
- }
271
- }
272
-
273
- // Reuse already-loaded config for argv preview
274
- const tiers: {
275
- user?: Partial<ReturnType<typeof parseTurnOptions>>;
276
- project?: Partial<ReturnType<typeof parseTurnOptions>>;
277
- } = {};
278
- if (loadedTiers.user) tiers.user = loadedTiers.user as never;
279
- if (loadedTiers.project) tiers.project = loadedTiers.project as never;
280
- let resolved: ReturnType<typeof resolveEffectiveOptions>;
281
- try {
282
- resolved = resolveEffectiveOptions(h, { ...turnOpts, prompt } as never, tiers);
283
- } catch (resErr) {
284
- if (resErr instanceof FloorExceededError) {
285
- process.stderr.write(`${(resErr as Error).message}\n`);
286
- process.exitCode = 2;
287
- return;
288
- }
289
- if (resErr instanceof ArgvRefusalError) {
290
- refuse(refusalOf(resErr as ArgvRefusalError), false);
291
- return;
292
- }
293
- throw resErr;
294
- }
295
- const { writeProvenance } = await import("./provenance.js");
296
- writeProvenance(h.name, resolved.provenance, resolved.unrenderable);
297
- const { prompt: _p, ...effectiveRest } = resolved.options as { prompt: string };
298
- const fullOpts = {
299
- ...(effectiveRest as object),
300
- prompt,
301
- ...(promptSource !== "positional" ? { __explicitPrompt: true as const } : {}),
302
- } as Parameters<typeof buildLaunchArgv>[1];
303
-
304
- let argv: string[];
305
- try {
306
- argv = buildLaunchArgv(h, fullOpts);
307
- const skillTokens = (effectiveRest as unknown as { __skillTokens?: string[] }).__skillTokens;
308
- if (skillTokens !== undefined && skillTokens.length > 0) argv.push(...skillTokens);
309
- } catch (err) {
310
- if (err instanceof ArgvRefusalError) {
311
- refuse(refusalOf(err as ArgvRefusalError), false);
312
- return;
313
- }
314
- throw err;
315
- }
316
-
317
- // Redact prompt for display, but keep structure
318
- const redacted = redactArgv(argv, prompt);
319
-
320
- process.stdout.write(`${JSON.stringify(redacted)}\n`);
321
- process.stderr.write(`argv: ${redacted.join(" ")}\n`);
112
+ const out = {
113
+ name: h.name,
114
+ bin: h.bin,
115
+ verifiedAgainst: h.verifiedAgainst,
116
+ versionSource: h.versionSource,
117
+ launch: {
118
+ baseFlags: h.launch.baseFlags,
119
+ subcommands: h.launch.subcommands,
120
+ streamFlags: h.launch.streamFlags,
121
+ promptStyle: h.launch.promptStyle,
122
+ toolsFlag: h.tools.includeFlag,
123
+ idFlag: h.launch.idFlag,
124
+ },
125
+ resume: h.resume,
126
+ sessionMode: h.sessionMode,
127
+ vocabulary: {
128
+ models: h.vocabulary.models,
129
+ aliases: h.vocabulary.aliases,
130
+ efforts: h.vocabulary.efforts,
131
+ effortsByModel: h.vocabulary.effortsByModel,
132
+ extensible: h.vocabulary.extensible,
133
+ modelFlag: h.vocabulary.modelFlag,
134
+ },
135
+ turnOptions: h.turnOptions,
136
+ limitMatchers: h.limitMatchers,
137
+ authMatchers: h.authMatchers,
138
+ toolVocabulary: slice,
139
+ };
140
+ process.stdout.write(`${JSON.stringify(out, null, 2)}\n`);
322
141
  };
323
142
 
324
143
  export const inspectCommand = inspect;