@f-o-h/cli 0.1.59 → 0.1.60

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 CHANGED
@@ -181,16 +181,19 @@ failure packet, and convert it with `foh bug improve`.
181
181
  For guarded programmable-runner planning:
182
182
 
183
183
  ```bash
184
- foh eval external-agent execute \
185
- --runner codex \
186
- --batch test-results/external-agent-runs/<batch>/batch.json \
187
- --dry-run \
188
- --json
189
- ```
190
-
191
- This writes `executor-plan.json`, creates intentionally empty clean workspaces
192
- outside the private repo, validates the local Codex binary/help flags, and
193
- prints exact `codex exec` commands without executing them.
184
+ foh eval external-agent execute \
185
+ --runner codex \
186
+ --batch test-results/external-agent-runs/<batch>/batch.json \
187
+ --codex-model gpt-5.4-mini \
188
+ --dry-run \
189
+ --json
190
+ ```
191
+
192
+ This writes `executor-plan.json`, creates intentionally empty clean workspaces
193
+ outside the private repo, validates the local Codex binary/help flags, and
194
+ prints exact `codex exec` commands without executing them. Use `--codex-model`
195
+ to compare the same prompt across explicit Codex models; the selected runner
196
+ model is recorded in `executor-plan.json` and controlled-run `run.json`.
194
197
 
195
198
  Before promoting run artifacts, scan and redact them:
196
199
 
package/dist/foh.js CHANGED
@@ -32853,7 +32853,7 @@ var StdioServerTransport = class {
32853
32853
  };
32854
32854
 
32855
32855
  // src/lib/cli-version.ts
32856
- var CLI_VERSION = "0.1.59";
32856
+ var CLI_VERSION = "0.1.60";
32857
32857
 
32858
32858
  // src/commands/mcp-serve.ts
32859
32859
  var DEFAULT_TIMEOUT_MS = 12e4;
@@ -39526,6 +39526,9 @@ ${yoloHelp.stderr}`;
39526
39526
  "--output-last-message"
39527
39527
  ];
39528
39528
  const missing = commonExecFlags.filter((flag) => !execHelpText.includes(flag));
39529
+ if (String(options.codexModel || "").trim() && !execHelpText.includes("--model")) {
39530
+ missing.push("--model");
39531
+ }
39529
39532
  const supportsLegacyFullAuto = execHelpText.includes("--full-auto");
39530
39533
  const supportsModernApprovalMode = rootHelp.status === 0 && rootHelpText.includes("--ask-for-approval");
39531
39534
  if (!supportsLegacyFullAuto && !supportsModernApprovalMode) {
@@ -39696,6 +39699,17 @@ function normalizeCodexSandboxMode(value) {
39696
39699
  `Unsupported Codex sandbox mode: ${value}. Use workspace-write or danger-full-access.`
39697
39700
  );
39698
39701
  }
39702
+ function normalizeCodexModel(value) {
39703
+ const normalized = String(value || "").trim();
39704
+ if (!normalized) return null;
39705
+ if (!/^[A-Za-z0-9._:@/-]+$/.test(normalized)) {
39706
+ throw new ExternalAgentExecutorError(
39707
+ "invalid_codex_model",
39708
+ "Unsupported Codex model value. Use a plain model id such as gpt-5.4-mini."
39709
+ );
39710
+ }
39711
+ return normalized;
39712
+ }
39699
39713
  function normalizeGeminiSandboxMode(value) {
39700
39714
  const normalized = (value || "required").trim().toLowerCase();
39701
39715
  if (normalized === "required" || normalized === "disabled") return normalized;
@@ -39704,6 +39718,9 @@ function normalizeGeminiSandboxMode(value) {
39704
39718
  `Unsupported Gemini sandbox mode: ${value}. Use required or disabled.`
39705
39719
  );
39706
39720
  }
39721
+ function codexModelArgs(model) {
39722
+ return model ? ["--model", model] : [];
39723
+ }
39707
39724
  function codexConfigArgs(input) {
39708
39725
  const args = [];
39709
39726
  if (input.backend === "legacy-landlock") {
@@ -39743,6 +39760,7 @@ function createExternalAgentExecutorPlan(options) {
39743
39760
  const runnerProbe = validateRunner(options, runner);
39744
39761
  const codexSandboxBackend = normalizeCodexSandboxBackend(options.codexSandboxBackend);
39745
39762
  const codexSandboxMode = normalizeCodexSandboxMode(options.codexSandboxMode);
39763
+ const codexModel = runner === "codex" ? normalizeCodexModel(options.codexModel) : null;
39746
39764
  const codexNetworkAccess = options.codexNetworkAccess === true;
39747
39765
  const privateRepoRoot = (0, import_path13.resolve)(options.privateRepoRoot || options.cwd || process.cwd());
39748
39766
  const workspaceRoot = resolveWorkspaceRoot({ batchPath, workspaceRoot: options.workspaceRoot, privateRepoRoot });
@@ -39791,6 +39809,7 @@ function createExternalAgentExecutorPlan(options) {
39791
39809
  ] : [
39792
39810
  ...runnerProbe.globalArgs,
39793
39811
  "exec",
39812
+ ...codexModelArgs(codexModel),
39794
39813
  ...codexConfigArgs({ backend: codexSandboxBackend, networkAccess: codexNetworkAccess }),
39795
39814
  "--cd",
39796
39815
  workspaceDir,
@@ -39809,6 +39828,7 @@ function createExternalAgentExecutorPlan(options) {
39809
39828
  run_id: runId,
39810
39829
  model_provider: String(run.model_provider || "unknown"),
39811
39830
  model_name: String(run.model_name || "unknown-model"),
39831
+ runner_model: runner === "codex" ? codexModel : null,
39812
39832
  prompt_version: promptVersion,
39813
39833
  run_dir: runDir,
39814
39834
  prompt_path: promptPath,
@@ -39863,6 +39883,7 @@ function createExternalAgentExecutorPlan(options) {
39863
39883
  },
39864
39884
  runner_automation_mode: runnerProbe.automationMode,
39865
39885
  codex_automation_mode: runner === "codex" ? runnerProbe.automationMode : null,
39886
+ codex_model: runner === "codex" ? codexModel : null,
39866
39887
  codex_sandbox_mode: codexSandboxMode,
39867
39888
  codex_sandbox_backend: codexSandboxBackend,
39868
39889
  codex_network_access: codexNetworkAccess
@@ -40024,6 +40045,7 @@ function buildExecutedRunArtifact(input) {
40024
40045
  failure_reason_code: input.reasonCode,
40025
40046
  model_provider: input.run.model_provider,
40026
40047
  model_name: input.run.model_name,
40048
+ runner_model: input.run.runner_model,
40027
40049
  agent_shell: `${input.run.command}-exec`,
40028
40050
  workspace_type: "clean-no-repo-programmatic",
40029
40051
  prompt_version: input.run.prompt_version,
@@ -40675,7 +40697,7 @@ Exit the shell to finalize run.json.
40675
40697
  }), { json: Boolean(opts.json) });
40676
40698
  if (!report.ok) process.exitCode = 1;
40677
40699
  });
40678
- external.command("execute").description("Create a guarded dry-run executor plan for programmable external-agent runners").requiredOption("--batch <path>", "Path to external_agent_batch_plan.v1 batch.json").option("--runner <runner>", "Runner implementation", "codex").option("--workspace-root <path>", "Clean executor workspace root; must be outside the private repo").option("--private-repo-root <path>", "Private repository root to guard against").option("--timeout-minutes <minutes>", "Per-run timeout planned for future execution", "30").option("--codex-sandbox-backend <backend>", "Codex sandbox backend override: default|legacy-landlock", "default").option("--codex-sandbox-mode <mode>", "Codex sandbox mode: workspace-write|danger-full-access", "workspace-write").option("--codex-network-access", "Allow Codex workspace-write sandbox network access for public docs/npm probes").option("--gemini-sandbox-mode <mode>", "Gemini sandbox mode: required|disabled", "required").option("--skip-runner-probe", "Skip local runner binary/help probing").option("--dry-run", "Write the executor plan without launching the runner", true).option("--live", "Launch one controlled external-agent run after writing the guarded plan").option("--json", "Output as JSON").action(async (opts) => {
40700
+ external.command("execute").description("Create a guarded dry-run executor plan for programmable external-agent runners").requiredOption("--batch <path>", "Path to external_agent_batch_plan.v1 batch.json").option("--runner <runner>", "Runner implementation", "codex").option("--workspace-root <path>", "Clean executor workspace root; must be outside the private repo").option("--private-repo-root <path>", "Private repository root to guard against").option("--timeout-minutes <minutes>", "Per-run timeout planned for future execution", "30").option("--codex-model <model>", "Codex model override for controlled evals; recorded in executor-plan.json and run.json").option("--codex-sandbox-backend <backend>", "Codex sandbox backend override: default|legacy-landlock", "default").option("--codex-sandbox-mode <mode>", "Codex sandbox mode: workspace-write|danger-full-access", "workspace-write").option("--codex-network-access", "Allow Codex workspace-write sandbox network access for public docs/npm probes").option("--gemini-sandbox-mode <mode>", "Gemini sandbox mode: required|disabled", "required").option("--skip-runner-probe", "Skip local runner binary/help probing").option("--dry-run", "Write the executor plan without launching the runner", true).option("--live", "Launch one controlled external-agent run after writing the guarded plan").option("--json", "Output as JSON").action(async (opts) => {
40679
40701
  try {
40680
40702
  const plan = createExternalAgentExecutorPlan({
40681
40703
  batchPath: String(opts.batch),
@@ -40683,6 +40705,7 @@ Exit the shell to finalize run.json.
40683
40705
  workspaceRoot: opts.workspaceRoot ? String(opts.workspaceRoot) : void 0,
40684
40706
  privateRepoRoot: opts.privateRepoRoot ? String(opts.privateRepoRoot) : void 0,
40685
40707
  timeoutMinutes: Number(opts.timeoutMinutes || 30),
40708
+ codexModel: opts.codexModel ? String(opts.codexModel) : void 0,
40686
40709
  codexSandboxBackend: String(opts.codexSandboxBackend || "default"),
40687
40710
  codexSandboxMode: String(opts.codexSandboxMode || "workspace-write"),
40688
40711
  codexNetworkAccess: Boolean(opts.codexNetworkAccess),
@@ -5,6 +5,7 @@
5
5
  "failure_reason_code": "docs_widget_proof_path_unclear",
6
6
  "model_provider": "openai",
7
7
  "model_name": "codex",
8
+ "runner_model": "gpt-5.4-mini",
8
9
  "agent_shell": "vscode-terminal",
9
10
  "workspace_type": "clean-no-repo",
10
11
  "prompt_version": "blank-setup.v1",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@f-o-h/cli",
3
- "version": "0.1.59",
3
+ "version": "0.1.60",
4
4
  "description": "FOH CLI - AI-operator provisioning tool for Front Of House",
5
5
  "license": "UNLICENSED",
6
6
  "bin": {
@@ -25,6 +25,7 @@
25
25
  "failure_reason_code": { "type": ["string", "null"] },
26
26
  "model_provider": { "type": "string", "minLength": 1 },
27
27
  "model_name": { "type": "string", "minLength": 1 },
28
+ "runner_model": { "type": ["string", "null"] },
28
29
  "agent_shell": { "type": "string" },
29
30
  "workspace_type": { "type": "string" },
30
31
  "prompt_version": { "type": "string", "minLength": 1 },