holycodex 0.11.0 → 0.11.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 (2) hide show
  1. package/dist/cli.js +389 -457
  2. package/package.json +4 -4
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import process$1 from "node:process";
2
- import { access, copyFile, cp, lstat, mkdir, readFile, readdir, readlink, rename, rm, stat, writeFile } from "node:fs/promises";
2
+ import { access, copyFile, cp, lstat, mkdir, mkdtemp, readFile, readdir, readlink, rename, rm, stat, writeFile } from "node:fs/promises";
3
3
  import { homedir, tmpdir } from "node:os";
4
- import { dirname, join } from "node:path";
4
+ import { delimiter, dirname, join } from "node:path";
5
5
  import { execFileSync, spawn, spawnSync } from "node:child_process";
6
6
  import { existsSync } from "node:fs";
7
7
  import { Buffer } from "node:buffer";
@@ -81,7 +81,6 @@ function cached(getter) {
81
81
  Object.defineProperty(this, "value", { value });
82
82
  return value;
83
83
  }
84
- throw new Error("cached value already set");
85
84
  } };
86
85
  }
87
86
  function nullish(input) {
@@ -1907,115 +1906,6 @@ function handleIntersectionResults(result, left, right) {
1907
1906
  result.value = merged.data;
1908
1907
  return result;
1909
1908
  }
1910
- var $ZodRecord = /*@__PURE__*/ $constructor("$ZodRecord", (inst, def) => {
1911
- $ZodType.init(inst, def);
1912
- inst._zod.parse = (payload, ctx) => {
1913
- const input = payload.value;
1914
- if (!isPlainObject(input)) {
1915
- payload.issues.push({
1916
- expected: "record",
1917
- code: "invalid_type",
1918
- input,
1919
- inst
1920
- });
1921
- return payload;
1922
- }
1923
- const proms = [];
1924
- const values = def.keyType._zod.values;
1925
- if (values) {
1926
- payload.value = {};
1927
- const recordKeys = /* @__PURE__ */ new Set();
1928
- for (const key of values) if (typeof key === "string" || typeof key === "number" || typeof key === "symbol") {
1929
- recordKeys.add(typeof key === "number" ? key.toString() : key);
1930
- const keyResult = def.keyType._zod.run({
1931
- value: key,
1932
- issues: []
1933
- }, ctx);
1934
- if (keyResult instanceof Promise) throw new Error("Async schemas not supported in object keys currently");
1935
- if (keyResult.issues.length) {
1936
- payload.issues.push({
1937
- code: "invalid_key",
1938
- origin: "record",
1939
- issues: keyResult.issues.map((iss) => finalizeIssue(iss, ctx, config())),
1940
- input: key,
1941
- path: [key],
1942
- inst
1943
- });
1944
- continue;
1945
- }
1946
- const outKey = keyResult.value;
1947
- const result = def.valueType._zod.run({
1948
- value: input[key],
1949
- issues: []
1950
- }, ctx);
1951
- if (result instanceof Promise) proms.push(result.then((result) => {
1952
- if (result.issues.length) payload.issues.push(...prefixIssues(key, result.issues));
1953
- payload.value[outKey] = result.value;
1954
- }));
1955
- else {
1956
- if (result.issues.length) payload.issues.push(...prefixIssues(key, result.issues));
1957
- payload.value[outKey] = result.value;
1958
- }
1959
- }
1960
- let unrecognized;
1961
- for (const key in input) if (!recordKeys.has(key)) {
1962
- unrecognized = unrecognized ?? [];
1963
- unrecognized.push(key);
1964
- }
1965
- if (unrecognized && unrecognized.length > 0) payload.issues.push({
1966
- code: "unrecognized_keys",
1967
- input,
1968
- inst,
1969
- keys: unrecognized
1970
- });
1971
- } else {
1972
- payload.value = {};
1973
- for (const key of Reflect.ownKeys(input)) {
1974
- if (key === "__proto__") continue;
1975
- if (!Object.prototype.propertyIsEnumerable.call(input, key)) continue;
1976
- let keyResult = def.keyType._zod.run({
1977
- value: key,
1978
- issues: []
1979
- }, ctx);
1980
- if (keyResult instanceof Promise) throw new Error("Async schemas not supported in object keys currently");
1981
- if (typeof key === "string" && number$1.test(key) && keyResult.issues.length) {
1982
- const retryResult = def.keyType._zod.run({
1983
- value: Number(key),
1984
- issues: []
1985
- }, ctx);
1986
- if (retryResult instanceof Promise) throw new Error("Async schemas not supported in object keys currently");
1987
- if (retryResult.issues.length === 0) keyResult = retryResult;
1988
- }
1989
- if (keyResult.issues.length) {
1990
- if (def.mode === "loose") payload.value[key] = input[key];
1991
- else payload.issues.push({
1992
- code: "invalid_key",
1993
- origin: "record",
1994
- issues: keyResult.issues.map((iss) => finalizeIssue(iss, ctx, config())),
1995
- input: key,
1996
- path: [key],
1997
- inst
1998
- });
1999
- continue;
2000
- }
2001
- const result = def.valueType._zod.run({
2002
- value: input[key],
2003
- issues: []
2004
- }, ctx);
2005
- if (result instanceof Promise) proms.push(result.then((result) => {
2006
- if (result.issues.length) payload.issues.push(...prefixIssues(key, result.issues));
2007
- payload.value[keyResult.value] = result.value;
2008
- }));
2009
- else {
2010
- if (result.issues.length) payload.issues.push(...prefixIssues(key, result.issues));
2011
- payload.value[keyResult.value] = result.value;
2012
- }
2013
- }
2014
- }
2015
- if (proms.length) return Promise.all(proms).then(() => payload);
2016
- return payload;
2017
- };
2018
- });
2019
1909
  var $ZodEnum = /*@__PURE__*/ $constructor("$ZodEnum", (inst, def) => {
2020
1910
  $ZodType.init(inst, def);
2021
1911
  const values = getEnumValues(def.entries);
@@ -3281,39 +3171,6 @@ var intersectionProcessor = (schema, ctx, json, params) => {
3281
3171
  const isSimpleIntersection = (val) => "allOf" in val && Object.keys(val).length === 1;
3282
3172
  json.allOf = [...isSimpleIntersection(a) ? a.allOf : [a], ...isSimpleIntersection(b) ? b.allOf : [b]];
3283
3173
  };
3284
- var recordProcessor = (schema, ctx, _json, params) => {
3285
- const json = _json;
3286
- const def = schema._zod.def;
3287
- json.type = "object";
3288
- const keyType = def.keyType;
3289
- const patterns = keyType._zod.bag?.patterns;
3290
- if (def.mode === "loose" && patterns && patterns.size > 0) {
3291
- const valueSchema = process$2(def.valueType, ctx, {
3292
- ...params,
3293
- path: [
3294
- ...params.path,
3295
- "patternProperties",
3296
- "*"
3297
- ]
3298
- });
3299
- json.patternProperties = {};
3300
- for (const pattern of patterns) json.patternProperties[pattern.source] = valueSchema;
3301
- } else {
3302
- if (ctx.target === "draft-07" || ctx.target === "draft-2020-12") json.propertyNames = process$2(def.keyType, ctx, {
3303
- ...params,
3304
- path: [...params.path, "propertyNames"]
3305
- });
3306
- json.additionalProperties = process$2(def.valueType, ctx, {
3307
- ...params,
3308
- path: [...params.path, "additionalProperties"]
3309
- });
3310
- }
3311
- const keyValues = keyType._zod.values;
3312
- if (keyValues) {
3313
- const validKeyValues = [...keyValues].filter((v) => typeof v === "string" || typeof v === "number");
3314
- if (validKeyValues.length > 0) json.required = validKeyValues;
3315
- }
3316
- };
3317
3174
  var nullableProcessor = (schema, ctx, json, params) => {
3318
3175
  const def = schema._zod.def;
3319
3176
  const inner = process$2(def.innerType, ctx, params);
@@ -3965,14 +3822,6 @@ function strictObject(shape, params) {
3965
3822
  ...normalizeParams(params)
3966
3823
  });
3967
3824
  }
3968
- function looseObject(shape, params) {
3969
- return new ZodObject({
3970
- type: "object",
3971
- shape,
3972
- catchall: unknown(),
3973
- ...normalizeParams(params)
3974
- });
3975
- }
3976
3825
  var ZodUnion = /*@__PURE__*/ $constructor("ZodUnion", (inst, def) => {
3977
3826
  $ZodUnion.init(inst, def);
3978
3827
  ZodType.init(inst, def);
@@ -4010,27 +3859,6 @@ function intersection(left, right) {
4010
3859
  right
4011
3860
  });
4012
3861
  }
4013
- var ZodRecord = /*@__PURE__*/ $constructor("ZodRecord", (inst, def) => {
4014
- $ZodRecord.init(inst, def);
4015
- ZodType.init(inst, def);
4016
- inst._zod.processJSONSchema = (ctx, json, params) => recordProcessor(inst, ctx, json, params);
4017
- inst.keyType = def.keyType;
4018
- inst.valueType = def.valueType;
4019
- });
4020
- function record(keyType, valueType, params) {
4021
- if (!valueType || !valueType._zod) return new ZodRecord({
4022
- type: "record",
4023
- keyType: string(),
4024
- valueType: keyType,
4025
- ...normalizeParams(valueType)
4026
- });
4027
- return new ZodRecord({
4028
- type: "record",
4029
- keyType,
4030
- valueType,
4031
- ...normalizeParams(params)
4032
- });
4033
- }
4034
3862
  var ZodEnum = /*@__PURE__*/ $constructor("ZodEnum", (inst, def) => {
4035
3863
  $ZodEnum.init(inst, def);
4036
3864
  ZodType.init(inst, def);
@@ -4252,13 +4080,13 @@ function superRefine(fn, params) {
4252
4080
  }
4253
4081
  //#endregion
4254
4082
  //#region packages/cli/src/catalog.ts
4255
- var VERSION = "0.11.0";
4083
+ var VERSION = "0.11.2";
4256
4084
  var SKILLS = [
4257
4085
  "ast-grep",
4258
4086
  "babysit-ci",
4259
- "caveman",
4260
4087
  "code-review",
4261
4088
  "compress",
4089
+ "context7-cli",
4262
4090
  "debugging",
4263
4091
  "handoff",
4264
4092
  "lsp",
@@ -4740,36 +4568,112 @@ var GENERATED_RUNTIMES = [
4740
4568
  "git-bash-resolver.js",
4741
4569
  "LICENSE-LSP-MIT.txt",
4742
4570
  "lsp.js",
4743
- "mcp-stdio-core.js",
4744
4571
  "rules.js"
4745
4572
  ];
4746
- var WINDOWS_SHELL_POLICY = "On native Windows, before the first shell action, inspect callable and deferred tools until `mcp__git_bash__run` is resolved. Use it for every shell command, including Git, Bash, POSIX, package, build, test, and script commands. If unavailable, stop and report the blocker. Never fall back to PowerShell or cmd.";
4747
- /** Provides effective mcp servers. */
4748
- function effectiveMcpServers(platform) {
4749
- return {
4750
- ...platform === "win32" ? { git_bash: {
4751
- command: "node",
4752
- args: ["runtime/git-bash.js", "mcp"],
4753
- cwd: ".",
4754
- enabled_tools: ["run"]
4755
- } } : {},
4756
- lsp: {
4757
- command: "node",
4758
- args: ["runtime/lsp.js", "mcp"],
4759
- cwd: "."
4760
- },
4761
- context7: {
4762
- command: "bunx",
4763
- args: ["@upstash/context7-mcp"]
4764
- }
4765
- };
4766
- }
4573
+ var WINDOWS_SHELL_POLICY = "On native Windows, run every shell command through the bundled Git Bash launcher, including Git, package, build, test, script and POSIX commands. Never execute task commands through PowerShell or cmd. If Git Bash cannot be resolved, stop and report the blocker. On non-Windows, use the native shell normally.";
4574
+ var LITE_WRITING_POLICY = "Communicate grammatically and concisely. Omit filler, hedging, repetition, decoration, self-reference, style announcements and tool narration. Preserve exact technical terms, APIs, commands, paths, errors and commit keywords. Use fuller grammar for safety, ambiguity, clarification and ordered instructions. Apply this policy only to agent communication, never to literal authored or transformed content, UI or accessibility labels, help text, errors, logs, tests, fixtures, documentation, comments, commit or PR text, authored prompts, translations, quotations, generated content, public APIs, or existing repository and product voice.";
4575
+ var CONTEXT7_POLICY = "Within assigned scope, use the Context7 CLI skill first for current library, framework, SDK and API documentation. Use live web search for releases, dates, broader research, missing Context7 coverage and corroboration. Context7 does not authorize scope expansion.";
4767
4576
  /** Returns packaged runtime files required on a platform. */
4768
4577
  function requiredPackageRuntimes(platform) {
4769
4578
  return platform === "win32" ? GENERATED_RUNTIMES : GENERATED_RUNTIMES.filter((file) => file !== "git-bash.js");
4770
4579
  }
4771
4580
  //#endregion
4772
- //#region packages/git-bash-mcp/src/git-bash-resolver.ts
4581
+ //#region packages/cli/src/arguments.ts
4582
+ var INSTALL_FLAGS = /* @__PURE__ */ new Set([
4583
+ "--plan",
4584
+ "--max-subagents",
4585
+ "--codex-autonomous",
4586
+ "--no-codex-autonomous",
4587
+ "--dangerous-codex-autonomous",
4588
+ "--fast",
4589
+ "--fast-all",
4590
+ "--no-fast",
4591
+ "--json"
4592
+ ]);
4593
+ var SHARED_FLAGS = /* @__PURE__ */ new Set(["--json"]);
4594
+ /** Strictly parses command-specific HolyCodex CLI arguments. */
4595
+ function parseCliArguments(args) {
4596
+ if (args.length === 0 || args[0] === "--help" || args[0] === "-h") return base("help");
4597
+ if (args[0] === "--version" || args[0] === "-v") {
4598
+ if (args.length !== 1) throw new Error("--version does not accept other arguments.");
4599
+ return base("version");
4600
+ }
4601
+ const command = args[0];
4602
+ if (command !== "install" && command !== "doctor" && command !== "cleanup") throw new Error(`Unknown command: ${command ?? ""}`);
4603
+ if (args[1] === "--help" || args[1] === "-h") {
4604
+ if (args.length !== 2) throw new Error("--help does not accept other arguments.");
4605
+ return {
4606
+ ...base("help"),
4607
+ command
4608
+ };
4609
+ }
4610
+ const allowed = command === "install" ? INSTALL_FLAGS : SHARED_FLAGS;
4611
+ const values = /* @__PURE__ */ new Map();
4612
+ for (let index = 1; index < args.length; index += 1) {
4613
+ const token = args[index];
4614
+ if (token === void 0 || !token.startsWith("--")) throw new Error(`Unexpected positional argument: ${token ?? ""}`);
4615
+ const separator = token.indexOf("=");
4616
+ const name = separator < 0 ? token : token.slice(0, separator);
4617
+ if (!allowed.has(name)) throw new Error(`Option ${name} is not valid for ${command}.`);
4618
+ if (values.has(name)) throw new Error(`Repeated option: ${name}`);
4619
+ if (name !== "--plan" && name !== "--max-subagents") {
4620
+ if (separator >= 0) throw new Error(`${name} does not accept a value.`);
4621
+ values.set(name, true);
4622
+ continue;
4623
+ }
4624
+ const value = separator < 0 ? args[++index] : token.slice(separator + 1);
4625
+ if (value === void 0 || value === "" || separator < 0 && value.startsWith("--")) throw new Error(`Missing value for ${name}.`);
4626
+ values.set(name, value);
4627
+ }
4628
+ const autonomyFlags = [
4629
+ "--codex-autonomous",
4630
+ "--no-codex-autonomous",
4631
+ "--dangerous-codex-autonomous"
4632
+ ].filter((flag) => values.has(flag));
4633
+ if (autonomyFlags.length > 1) throw new Error(`Conflicting autonomy flags: ${autonomyFlags.join(", ")}`);
4634
+ const fastFlags = [
4635
+ "--fast",
4636
+ "--fast-all",
4637
+ "--no-fast"
4638
+ ].filter((flag) => values.has(flag));
4639
+ if (fastFlags.length > 1) throw new Error(`Conflicting Fast flags: ${fastFlags.join(", ")}`);
4640
+ const planValue = values.get("--plan") ?? "plus";
4641
+ const plan = PlanNameSchema.safeParse(planValue);
4642
+ if (!plan.success) throw new Error(`Unknown plan: ${String(planValue)}. Valid plans: ${PLAN_NAMES.join(", ")}.`);
4643
+ const maxValue = values.get("--max-subagents");
4644
+ if (maxValue !== void 0 && (typeof maxValue !== "string" || !/^\d+$/.test(maxValue) || Number(maxValue) > 3)) throw new Error(`Invalid --max-subagents value: ${String(maxValue)}. Expected an integer from 0 through 3.`);
4645
+ const autonomy = values.has("--dangerous-codex-autonomous") ? {
4646
+ requested: true,
4647
+ mode: "dangerous"
4648
+ } : values.has("--codex-autonomous") ? {
4649
+ requested: true,
4650
+ mode: "autonomous"
4651
+ } : values.has("--no-codex-autonomous") ? {
4652
+ requested: true,
4653
+ mode: "default"
4654
+ } : { requested: false };
4655
+ const fast = FastModeSchema.parse(values.has("--fast-all") ? "fast-all" : values.has("--fast") ? "fast" : "standard");
4656
+ return {
4657
+ action: "run",
4658
+ command,
4659
+ json: values.has("--json"),
4660
+ plan: plan.data,
4661
+ ...maxValue === void 0 ? {} : { maxSubagents: Number(maxValue) },
4662
+ autonomy,
4663
+ fast
4664
+ };
4665
+ }
4666
+ function base(action) {
4667
+ return {
4668
+ action,
4669
+ json: false,
4670
+ plan: DEFAULT_PLAN,
4671
+ autonomy: { requested: false },
4672
+ fast: "standard"
4673
+ };
4674
+ }
4675
+ //#endregion
4676
+ //#region packages/git-bash/src/git-bash-resolver.ts
4773
4677
  var GIT_BASH_ENV_KEY = "HOLYCODEX_GIT_BASH_PATH";
4774
4678
  var PROGRAM_FILES = "C:\\Program Files\\Git\\bin\\bash.exe";
4775
4679
  var PROGRAM_FILES_X86 = "C:\\Program Files (x86)\\Git\\bin\\bash.exe";
@@ -4850,7 +4754,7 @@ function missing(checkedPaths) {
4850
4754
  };
4851
4755
  }
4852
4756
  //#endregion
4853
- //#region packages/mcp-stdio-core/src/process.ts
4757
+ //#region packages/runtime-core/src/process.ts
4854
4758
  var TRUNCATED_MARKER = "\n... diagnostic output truncated ...\n";
4855
4759
  var defaultManagedProcessRuntime = {
4856
4760
  terminationGraceMs: 2e3,
@@ -4915,11 +4819,13 @@ async function runManagedProcess(input, runtime = defaultManagedProcessRuntime)
4915
4819
  let matched = false;
4916
4820
  let settled = false;
4917
4821
  let forceKillTimeout;
4822
+ let finalResolutionTimeout;
4918
4823
  const finish = (exitCode, error, errorCode) => {
4919
4824
  if (settled) return;
4920
4825
  settled = true;
4921
4826
  clearTimeout(timeout);
4922
4827
  if (forceKillTimeout !== void 0) clearTimeout(forceKillTimeout);
4828
+ if (finalResolutionTimeout !== void 0) clearTimeout(finalResolutionTimeout);
4923
4829
  resolve({
4924
4830
  exitCode,
4925
4831
  stdout: outputText(stdout),
@@ -4938,6 +4844,8 @@ async function runManagedProcess(input, runtime = defaultManagedProcessRuntime)
4938
4844
  runtime.kill(child, input.platform, "SIGKILL");
4939
4845
  }, runtime.terminationGraceMs);
4940
4846
  forceKillTimeout.unref();
4847
+ finalResolutionTimeout = setTimeout(() => finish(child.exitCode, "Managed process did not emit close after termination."), input.finalResolutionMs ?? runtime.terminationGraceMs * 2);
4848
+ finalResolutionTimeout.unref();
4941
4849
  };
4942
4850
  const inspectMatch = () => {
4943
4851
  if (matched || input.matchOutput === void 0) return;
@@ -4968,7 +4876,9 @@ async function runManagedProcess(input, runtime = defaultManagedProcessRuntime)
4968
4876
  /** Terminates process tree. */
4969
4877
  function killProcessTree(child, platform, signal = "SIGTERM", runTaskkill = (command, args) => spawnSync(command, [...args], {
4970
4878
  stdio: "ignore",
4971
- windowsHide: true
4879
+ windowsHide: true,
4880
+ timeout: 2e3,
4881
+ killSignal: "SIGKILL"
4972
4882
  })) {
4973
4883
  if (platform === "win32" && child.pid !== void 0) {
4974
4884
  const result = runTaskkill("taskkill", [
@@ -5311,6 +5221,13 @@ function nextTableBoundary(input) {
5311
5221
  if (managedHeader < 0) return header;
5312
5222
  return Math.min(header, managedHeader);
5313
5223
  }
5224
+ function tableSource(input, table) {
5225
+ const match = new RegExp(`^\\s*\\[${table.replaceAll(".", "\\.")}]\\s*(?:#.*)?$`, "m").exec(input);
5226
+ if (match === null) return void 0;
5227
+ const tail = input.slice(match.index + match[0].length);
5228
+ const end = nextTableBoundary(tail);
5229
+ return end < 0 ? tail : tail.slice(0, end);
5230
+ }
5314
5231
  function rootValue(input, key) {
5315
5232
  if (key === "status_line") return rootTomlStringArraySource(input, key);
5316
5233
  return new RegExp(`^\\s*${key}\\s*=.*$`, "m").exec(input)?.[0];
@@ -5351,23 +5268,27 @@ function readPreservedRootOverrides(input) {
5351
5268
  const managedRoot = new RegExp(`^${START}\\r?\\n([\\s\\S]*?)^${END}\\r?$`, "m").exec(input)?.[1];
5352
5269
  if (managedRoot === void 0) return {
5353
5270
  model: false,
5354
- reasoningEffort: false
5271
+ reasoningEffort: false,
5272
+ webSearch: false
5355
5273
  };
5356
5274
  const plan = readManagedPlan(managedRoot);
5357
5275
  const model = rootTomlString(input, "model");
5358
5276
  const reasoningEffort = rootTomlString(input, "model_reasoning_effort");
5359
5277
  if (plan === void 0 || model === void 0 || reasoningEffort === void 0) return {
5360
5278
  model: false,
5361
- reasoningEffort: false
5279
+ reasoningEffort: false,
5280
+ webSearch: false
5362
5281
  };
5363
5282
  if (MANAGED_ROOT_MODEL_HISTORY_BY_PLAN[plan].some((route) => route.model === model && route.reasoningEffort === reasoningEffort)) return {
5364
5283
  model: false,
5365
- reasoningEffort: false
5284
+ reasoningEffort: false,
5285
+ webSearch: rootTomlString(managedRoot, "web_search") !== "live"
5366
5286
  };
5367
5287
  const preset = MODEL_ROUTING_PLANS[plan].root;
5368
5288
  return {
5369
5289
  model: model !== preset.model,
5370
- reasoningEffort: reasoningEffort !== preset.reasoningEffort
5290
+ reasoningEffort: reasoningEffort !== preset.reasoningEffort,
5291
+ webSearch: rootTomlString(managedRoot, "web_search") !== "live"
5371
5292
  };
5372
5293
  }
5373
5294
  function preserveManagedRootPreferences(input, base) {
@@ -5378,7 +5299,11 @@ function preserveManagedRootPreferences(input, base) {
5378
5299
  const tables = firstTable < 0 ? "" : base.slice(firstTable);
5379
5300
  let updatedRoot = root.trim();
5380
5301
  const overrides = readPreservedRootOverrides(input);
5381
- for (const [key, preserve] of [["model", overrides.model], ["model_reasoning_effort", overrides.reasoningEffort]]) {
5302
+ for (const [key, preserve] of [
5303
+ ["model", overrides.model],
5304
+ ["model_reasoning_effort", overrides.reasoningEffort],
5305
+ ["web_search", overrides.webSearch]
5306
+ ]) {
5382
5307
  const live = rootValue(managedRoot, key)?.trim();
5383
5308
  if (!preserve || live === void 0) continue;
5384
5309
  if (rootValue(root, key)?.trim() === live) continue;
@@ -5416,6 +5341,7 @@ function installConfig(input, mode, _platform, plan = DEFAULT_PLAN, maxSubagents
5416
5341
  const hadOriginalRoot = /^# holycodex original root:/m.test(input);
5417
5342
  const permissionLines = originalPermissionLines ?? (legacyGeneratedRoot !== void 0 && previousOriginalRoot === void 0 ? [] : previousOriginalRoot === void 0 ? hadManagedAutonomy && !hadOriginalRoot ? [] : readPermissionLines(root) : readPermissionLines(previousOriginalRoot));
5418
5343
  const controlled = [
5344
+ "web_search",
5419
5345
  "approval_policy",
5420
5346
  "approvals_reviewer",
5421
5347
  "sandbox_mode",
@@ -5426,6 +5352,7 @@ function installConfig(input, mode, _platform, plan = DEFAULT_PLAN, maxSubagents
5426
5352
  ...request.requested ? ["default_permissions"] : []
5427
5353
  ].map((key) => rootValue(root, key));
5428
5354
  const preservedRoot = [
5355
+ "web_search",
5429
5356
  "approval_policy",
5430
5357
  "approvals_reviewer",
5431
5358
  "sandbox_mode",
@@ -5446,72 +5373,131 @@ function installConfig(input, mode, _platform, plan = DEFAULT_PLAN, maxSubagents
5446
5373
  const original = originalSource ? `${ORIGINAL_ROOT}${Buffer.from(originalSource).toString("base64")}\n` : "";
5447
5374
  const maxSubagentsMetadata = maxSubagents === void 0 ? "" : `${MAX_SUBAGENTS_PREFIX}${maxSubagents}\n`;
5448
5375
  const rootServiceTier = fastMode === "fast-all" ? "fast" : "default";
5449
- const rootBlock = `${START}\n${PLAN_PREFIX}${plan}\n${FAST_MODE_PREFIX}${fastMode}\n${AUTONOMY_METADATA_PREFIX}${effectiveAutonomy}\n${maxSubagentsMetadata}${original}${originalPermissionMetadata(permissionLines)}${model}${effort}model_verbosity = "low"\nservice_tier = "${rootServiceTier}"\n${rootPermissionLines.join("\n")}\nstatus_line = ${mergedStatusLine(rootValue(root, "status_line"))}\n${END}`;
5376
+ const priorManagedRoot = new RegExp(`^${START}\\r?\\n([\\s\\S]*?)^${END}\\r?$`, "m").exec(input)?.[1];
5377
+ const webSearch = readPreservedRootOverrides(input).webSearch ? rootTomlString(priorManagedRoot ?? "", "web_search") ?? "live" : "live";
5378
+ const statusLine = mergedStatusLine(rootValue(root, "status_line") ?? rootTomlStringArraySource(tableSource(base, "tui") ?? "", "status_line"));
5379
+ const rootBlock = `${START}\n${PLAN_PREFIX}${plan}\n${FAST_MODE_PREFIX}${fastMode}\n${AUTONOMY_METADATA_PREFIX}${effectiveAutonomy}\n${maxSubagentsMetadata}${original}${originalPermissionMetadata(permissionLines)}${model}${effort}web_search = ${JSON.stringify(webSearch)}\nmodel_verbosity = "low"\nservice_tier = "${rootServiceTier}"\n${rootPermissionLines.join("\n")}\n${END}`;
5450
5380
  let configured = `${preservedRoot ? `${preservedRoot}\n` : ""}${rootBlock}${tables ? `\n\n${tables}` : ""}`;
5381
+ const legacyMultiAgentV2 = /\bmulti_agent_v2\s*=\s*(true|false)/.exec(configured)?.[1];
5451
5382
  configured = injectTableKeys(configured, "features", [
5452
5383
  ["default_mode_request_user_input", "true"],
5453
5384
  ["multi_agent", "true"],
5454
- ["multi_agent_v2", "true"]
5385
+ ...legacyMultiAgentV2 === void 0 ? [] : [["multi_agent_v2", legacyMultiAgentV2]]
5455
5386
  ]);
5456
5387
  const usage = MODEL_ROUTING_PLANS[plan].usage;
5457
- configured = injectTableKeys(configured, "agents", [["max_threads", String(effectiveMaxSubagents + 1)], ["max_depth", String(usage.maxDepth)]]);
5388
+ configured = injectTableKeys(configured, "agents", [["max_concurrent_threads_per_session", String(effectiveMaxSubagents + 1)], ["max_depth", String(usage.maxDepth)]]);
5389
+ configured = injectTableKeys(configured, "tui", [["status_line", statusLine]]);
5458
5390
  if (effectiveAutonomy !== "dangerous") configured = injectTableKeys(configured, "sandbox_workspace_write", [["network_access", "true"]]);
5459
- configured = injectTableKeys(configured, "desktop", [["enabled-reasoning-efforts", "[\"low\", \"medium\", \"high\", \"xhigh\", \"max\"]"], ["show-context-window-usage", "true"]]);
5391
+ configured = injectTableKeys(configured, "desktop", [["show-context-window-usage", "true"]]);
5460
5392
  if (_platform === "win32") configured = injectTableKeys(configured, "windows", [["sandbox", "\"unelevated\""]]);
5461
5393
  for (const agent of AGENTS) configured = injectTableKeys(configured, `agents.${agent}`, [["config_file", `"holycodex/agents/${agent}.toml"`]]);
5462
5394
  const plugin = `${START}\n[plugins."holycodex@holycodex"]\nenabled = true\n${END}`;
5463
5395
  return `${configured.trim()}\n\n${plugin}\n`;
5464
5396
  }
5465
5397
  //#endregion
5398
+ //#region packages/cli/src/context7.ts
5399
+ var RUNNERS = [
5400
+ {
5401
+ executable: "nubx",
5402
+ command: "nubx",
5403
+ prefix: ["-y"]
5404
+ },
5405
+ {
5406
+ executable: "nub",
5407
+ command: "nub",
5408
+ prefix: ["dlx"]
5409
+ },
5410
+ {
5411
+ executable: "bunx",
5412
+ command: "bunx",
5413
+ prefix: []
5414
+ },
5415
+ {
5416
+ executable: "bun",
5417
+ command: "bun",
5418
+ prefix: ["x"]
5419
+ },
5420
+ {
5421
+ executable: "pnpmx",
5422
+ command: "pnpmx",
5423
+ prefix: []
5424
+ },
5425
+ {
5426
+ executable: "pnpm",
5427
+ command: "pnpm",
5428
+ prefix: ["dlx"]
5429
+ },
5430
+ {
5431
+ executable: "npmx",
5432
+ command: "npmx",
5433
+ prefix: ["--yes"]
5434
+ },
5435
+ {
5436
+ executable: "npm",
5437
+ command: "npx",
5438
+ prefix: ["--yes"]
5439
+ },
5440
+ {
5441
+ executable: "yarn",
5442
+ command: "yarn",
5443
+ prefix: ["dlx"]
5444
+ }
5445
+ ];
5446
+ /** Constructs the supported direct Context7 invocation for the first available runner. */
5447
+ function context7Command(args, executableExists = executableOnPath, env = process.env) {
5448
+ const runner = RUNNERS.find((candidate) => executableExists(candidate.executable));
5449
+ if (runner === void 0) return void 0;
5450
+ return {
5451
+ command: runner.command,
5452
+ args: [
5453
+ ...runner.prefix,
5454
+ "ctx7@latest",
5455
+ ...args
5456
+ ],
5457
+ env: {
5458
+ ...env,
5459
+ CI: env.CI ?? "1"
5460
+ }
5461
+ };
5462
+ }
5463
+ /** Reports whether an executable can be resolved from PATH. */
5464
+ function executableOnPath(name) {
5465
+ const path = process.env.PATH;
5466
+ if (path === void 0) return false;
5467
+ const extensions = process.platform === "win32" ? [
5468
+ ".exe",
5469
+ ".cmd",
5470
+ ".bat",
5471
+ ""
5472
+ ] : [""];
5473
+ for (const directory of path.split(delimiter)) for (const extension of extensions) try {
5474
+ if (process.getBuiltinModule("node:fs").existsSync(`${directory}/${name}${extension}`)) return true;
5475
+ } catch {
5476
+ continue;
5477
+ }
5478
+ return false;
5479
+ }
5480
+ //#endregion
5466
5481
  //#region packages/cli/src/doctor.ts
5467
- var McpManifestSchema = looseObject({ mcpServers: record(string(), record(string(), unknown())) });
5468
- async function runCommand(name, args, platform) {
5482
+ var COMPATIBILITY_KEYS = ["desktop.show-context-window-usage"];
5483
+ async function runCommand(name, args, env) {
5469
5484
  const result = await runManagedProcess({
5470
5485
  command: name,
5471
5486
  args,
5472
- platform,
5473
- timeoutMs: 1e4,
5474
- maxOutputChars: 64 * 1024
5487
+ platform: process.platform,
5488
+ timeoutMs: 15e3,
5489
+ maxOutputChars: 64 * 1024,
5490
+ ...env === void 0 ? {} : { env }
5475
5491
  });
5476
5492
  return {
5477
5493
  ok: result.exitCode === 0 && !result.timedOut && result.error === void 0,
5478
5494
  output: `${result.stdout}\n${result.stderr}`.trim() || result.error || ""
5479
5495
  };
5480
5496
  }
5481
- async function startContext7(platform) {
5482
- const result = await runManagedProcess({
5483
- command: "bunx",
5484
- args: ["@upstash/context7-mcp"],
5485
- platform,
5486
- timeoutMs: 15e3,
5487
- maxOutputChars: 128 * 1024,
5488
- stdin: `${JSON.stringify({
5489
- jsonrpc: "2.0",
5490
- id: 1,
5491
- method: "initialize",
5492
- params: {
5493
- protocolVersion: "2025-03-26",
5494
- capabilities: {},
5495
- clientInfo: {
5496
- name: "holycodex-doctor",
5497
- version: VERSION
5498
- }
5499
- }
5500
- })}\n`,
5501
- matchOutput: (output) => output.includes("\"serverInfo\"") || output.includes("\"capabilities\"")
5502
- });
5503
- const diagnostic = `${result.stdout}\n${result.stderr}`.trim() || result.error || "";
5504
- return {
5505
- ok: result.matched && !result.timedOut,
5506
- timedOut: result.timedOut,
5507
- packageFailure: /(?:404|failed to resolve|package.*not found|error: GET)/i.test(diagnostic),
5508
- detail: diagnostic
5509
- };
5510
- }
5511
5497
  var defaultRuntime$1 = {
5512
5498
  platform: process.platform,
5513
- command: (name, args) => runCommand(name, args, process.platform),
5514
- context7: () => startContext7(process.platform),
5499
+ command: runCommand,
5500
+ executable: executableOnPath,
5515
5501
  gitBash: resolveGitBashForCurrentProcess
5516
5502
  };
5517
5503
  function check(id, status, code, detail, fix) {
@@ -5523,14 +5509,6 @@ function check(id, status, code, detail, fix) {
5523
5509
  ...fix === void 0 ? {} : { fix }
5524
5510
  };
5525
5511
  }
5526
- function mcpConfigMatches(actual, expected) {
5527
- const expectedEntries = Object.entries(expected);
5528
- if (Object.keys(actual).length !== expectedEntries.length) return false;
5529
- return expectedEntries.every(([key, expectedValue]) => {
5530
- const actualValue = actual[key];
5531
- return Array.isArray(expectedValue) ? Array.isArray(actualValue) && actualValue.length === expectedValue.length && actualValue.every((value, index) => value === expectedValue[index]) : actualValue === expectedValue;
5532
- });
5533
- }
5534
5512
  async function missingFiles(root, paths) {
5535
5513
  const missing = [];
5536
5514
  for (const path of paths) try {
@@ -5540,138 +5518,82 @@ async function missingFiles(root, paths) {
5540
5518
  }
5541
5519
  return missing;
5542
5520
  }
5543
- function tableBoolean(config, table, key) {
5544
- const body = new RegExp(`^\\s*\\[${table.replaceAll(".", "\\.")}]\\s*$([\\s\\S]*?)(?=^\\s*\\[|(?![\\s\\S]))`, "m").exec(config)?.[1];
5545
- const value = body === void 0 ? void 0 : new RegExp(`^\\s*${key}\\s*=\\s*(true|false)`, "m").exec(body)?.[1];
5546
- return value === void 0 ? void 0 : value === "true";
5547
- }
5548
- function tableString(config, table, key) {
5549
- const body = new RegExp(`^\\s*\\[${table.replaceAll(".", "\\.")}]\\s*$([\\s\\S]*?)(?=^\\s*\\[|(?![\\s\\S]))`, "m").exec(config)?.[1];
5550
- return body === void 0 ? void 0 : rootTomlString(body, key);
5521
+ function tableBody(config, table) {
5522
+ return new RegExp(`^\\s*\\[${table.replaceAll(".", "\\.")}]\\s*$([\\s\\S]*?)(?=^\\s*\\[|(?![\\s\\S]))`, "m").exec(config)?.[1];
5551
5523
  }
5552
- function tableStringArray(config, table, key) {
5553
- const body = new RegExp(`^\\s*\\[${table.replaceAll(".", "\\.")}]\\s*$([\\s\\S]*?)(?=^\\s*\\[|(?![\\s\\S]))`, "m").exec(config)?.[1];
5554
- return body === void 0 ? void 0 : rootTomlStringArray(body, key);
5555
- }
5556
- function tableInteger(config, table, key) {
5557
- const body = new RegExp(`^\\s*\\[${table.replaceAll(".", "\\.")}]\\s*$([\\s\\S]*?)(?=^\\s*\\[|(?![\\s\\S]))`, "m").exec(config)?.[1];
5558
- const value = body === void 0 ? void 0 : new RegExp(`^\\s*${key}\\s*=\\s*(\\d+)`, "m").exec(body)?.[1];
5559
- return value === void 0 ? void 0 : Number(value);
5524
+ function tableValue(config, table, key) {
5525
+ const body = tableBody(config, table);
5526
+ return body === void 0 ? void 0 : new RegExp(`^\\s*${key.replaceAll("-", "\\-")}\\s*=\\s*(.+?)\\s*$`, "m").exec(body)?.[1];
5560
5527
  }
5561
5528
  function autonomy(config) {
5562
5529
  const approval = rootTomlString(config, "approval_policy");
5563
- const approvalsReviewer = rootTomlString(config, "approvals_reviewer");
5530
+ const reviewer = rootTomlString(config, "approvals_reviewer");
5564
5531
  const sandbox = rootTomlString(config, "sandbox_mode");
5565
- const network = tableBoolean(config, "sandbox_workspace_write", "network_access");
5566
- if (approval === "on-request" && approvalsReviewer === "auto_review" && sandbox === "workspace-write" && network === true) return "safe-workspace";
5567
- if (approval === "never" && approvalsReviewer === void 0 && sandbox === "workspace-write" && network === true) return "autonomous-workspace";
5568
- if (approval === "never" && approvalsReviewer === void 0 && sandbox === "danger-full-access") return "dangerous";
5532
+ const network = tableValue(config, "sandbox_workspace_write", "network_access");
5533
+ if (approval === "on-request" && reviewer === "auto_review" && sandbox === "workspace-write" && network === "true") return "safe-workspace";
5534
+ if (approval === "never" && reviewer === void 0 && sandbox === "workspace-write" && network === "true") return "autonomous-workspace";
5535
+ if (approval === "never" && reviewer === void 0 && sandbox === "danger-full-access") return "dangerous";
5569
5536
  return "unknown";
5570
5537
  }
5571
- /** Runs HolyCodex installation and environment health checks. */
5538
+ /** Runs installation, configuration, runtime, and override health checks. */
5572
5539
  async function doctor(home = process.env.CODEX_HOME ?? join(homedir(), ".codex"), runtime = defaultRuntime$1) {
5573
5540
  const checks = [];
5574
5541
  const pluginRoot = join(home, "plugins", "cache", "holycodex", "holycodex", VERSION);
5575
5542
  const agentRoot = join(home, "holycodex", "agents");
5576
5543
  const configPath = join(home, "config.toml");
5577
5544
  let config = "";
5578
- let configAvailable = true;
5579
5545
  try {
5580
5546
  config = await readFile(configPath, "utf8");
5581
5547
  } catch {
5582
- configAvailable = false;
5548
+ checks.push(check("config", "error", "config-missing", `Missing ${configPath}.`, "Run holycodex install."));
5583
5549
  }
5584
5550
  const missing = await missingFiles(pluginRoot, [
5585
5551
  ".codex-plugin/plugin.json",
5586
- ".mcp.json",
5587
- "LICENSE-OH-MY-OPENCODE-SLIM-MIT.txt",
5588
5552
  "hooks/hooks.json",
5589
5553
  ...requiredPackageRuntimes(runtime.platform).map((file) => `runtime/${file}`),
5590
5554
  ...AGENTS.map((name) => `agents/${name}.toml`),
5591
5555
  ...SKILLS.map((name) => `skills/${name}/SKILL.md`)
5592
5556
  ]);
5593
- checks.push(missing.length === 0 ? check("package", "ok", "package-ready", `Plugin ${VERSION}, generated runtime, hooks, three agents, and ${SKILLS.length} skills are present.`) : check("package", "error", "package-incomplete", `Missing ${missing.join(", ")}.`, "Reinstall HolyCodex."));
5594
- let mcp;
5595
- try {
5596
- mcp = McpManifestSchema.parse(JSON.parse(await readFile(join(pluginRoot, ".mcp.json"), "utf8")));
5597
- } catch (error) {
5598
- checks.push(check("mcp-config", "error", "malformed-mcp-config", error instanceof ZodError ? "Invalid MCP JSON structure." : error instanceof Error ? error.message : "Invalid MCP JSON.", "Reinstall HolyCodex."));
5599
- }
5600
- const servers = mcp?.mcpServers;
5601
- const requiredMcps = runtime.platform === "win32" ? ["git_bash", "lsp"] : ["lsp"];
5602
- const expectedMcps = effectiveMcpServers(runtime.platform);
5603
- for (const name of requiredMcps) {
5604
- const configured = servers?.[name];
5605
- const expected = expectedMcps[name];
5606
- checks.push(configured === void 0 || expected === void 0 ? check(`mcp-${name}`, "error", "missing-required-mcp", `${name} is not configured.`, "Reinstall HolyCodex.") : !mcpConfigMatches(configured, expected) ? check(`mcp-${name}`, "error", "invalid-required-mcp-config", `${name} configuration is stale or contains unsupported settings.`, "Reinstall HolyCodex.") : check(`mcp-${name}`, "ok", "required-mcp-ready", `${name} is configured locally.`));
5607
- }
5608
- const gitBashConfig = servers?.git_bash;
5609
- if (runtime.platform === "win32" && gitBashConfig !== void 0) {
5610
- const expected = effectiveMcpServers("win32").git_bash;
5611
- checks.push(expected !== void 0 && mcpConfigMatches(gitBashConfig, expected) ? check("mcp-git_bash-config", "ok", "git-bash-mcp-config-ready", "Git Bash MCP exposes only run through the supported allowlist.") : check("mcp-git_bash-config", "error", "invalid-git-bash-mcp-config", "Git Bash MCP command or enabled_tools configuration is stale.", "Reinstall HolyCodex."));
5612
- } else if (runtime.platform !== "win32" && gitBashConfig !== void 0) checks.push(check("mcp-git_bash-config", "error", "unexpected-git-bash-mcp", "Git Bash MCP must not be installed on non-Windows platforms.", "Reinstall HolyCodex for this platform."));
5613
- const context7 = servers?.context7;
5614
- const expectedContext7 = effectiveMcpServers(runtime.platform).context7;
5615
- const obsoleteAuth = context7 !== void 0 && [
5616
- "headers",
5617
- "env",
5618
- "authorization",
5619
- "apiKey"
5620
- ].some((key) => key in context7);
5621
- if (context7 === void 0) checks.push(check("context7-config", "error", "missing-context7", "Context7 is not configured.", "Reinstall HolyCodex."));
5622
- else if (string().safeParse(context7.url).success) checks.push(check("context7-config", "error", "obsolete-context7-remote", "Context7 still uses a hosted URL.", "Reinstall to use local bunx Context7."));
5623
- else if (obsoleteAuth) checks.push(check("context7-config", "error", "obsolete-context7-auth", "Context7 contains obsolete authentication settings.", "Remove auth settings and reinstall."));
5624
- else if (expectedContext7 === void 0 || !mcpConfigMatches(context7, expectedContext7)) checks.push(check("context7-config", "error", "invalid-context7-config", "Context7 launch configuration is stale or contains unsupported settings.", "Repair .mcp.json or reinstall."));
5625
- else checks.push(check("context7-config", "ok", "local-context7-config", "Local no-auth Context7 is configured."));
5626
- const bun = await runtime.command("bun", ["--version"]);
5627
- const bunx = await runtime.command("bunx", ["--version"]);
5628
- checks.push(bun.ok ? check("bun", "ok", "bun-ready", `Bun ${bun.output || "available"}.`) : check("bun", "error", "missing-bun", "Bun is unavailable.", "Install or repair Bun."));
5629
- checks.push(bunx.ok ? check("bunx", "ok", "bunx-ready", `bunx ${bunx.output || "available"}.`) : check("bunx", "error", "missing-bunx", "bunx is unavailable.", "Repair the Bun installation."));
5630
- if (bun.ok && bunx.ok && checks.some((item) => item.code === "local-context7-config")) {
5631
- const started = await runtime.context7();
5632
- checks.push(started.ok && !started.timedOut ? check("context7-startup", "ok", "context7-healthy", "Context7 completed a bounded MCP handshake.") : started.packageFailure ? check("context7-startup", "error", "context7-package-resolution-failed", started.detail || "Context7 package resolution failed.", "Check network/package availability.") : check("context7-startup", "error", "context7-startup-failed", started.detail || "Context7 did not complete an MCP handshake within 15 seconds.", runtime.platform === "win32" ? "Run bunx @upstash/context7-mcp in Git Bash." : "Run bunx @upstash/context7-mcp in the native shell."));
5633
- }
5557
+ checks.push(missing.length === 0 ? check("package", "ok", "package-ready", `Plugin ${VERSION}, runtimes, agents, and ${SKILLS.length} skills are present.`) : check("package", "error", "package-incomplete", `Missing ${missing.join(", ")}.`, "Reinstall HolyCodex."));
5558
+ const webSearchOverride = readPreservedRootOverrides(config).webSearch;
5559
+ checks.push(rootTomlString(config, "web_search") === "live" ? check("web-search", "ok", "live-web-search", "Managed web search defaults to live.") : webSearchOverride ? check("web-search", "ok", "web-search-override", "An intentional user web-search override is preserved.") : check("web-search", "error", "web-search-not-live", "Managed web search is not live.", "Reinstall HolyCodex."));
5560
+ const status = rootTomlStringArray(config, "status_line") ?? rootTomlStringArray(tableBody(config, "tui") ?? "", "status_line");
5561
+ checks.push(status?.includes("context-remaining") ? check("context-visibility", "ok", "context-visible", "Context-window usage remains visible.") : check("context-visibility", "error", "context-hidden", "The status line does not show context remaining.", "Reinstall HolyCodex."));
5562
+ checks.push(check("screenshot", "ok", "screenshot-default-preserved", "HolyCodex does not override the enabled Codex screenshot default."));
5563
+ const context7 = context7Command(["--version"], runtime.executable);
5564
+ if (context7 === void 0) checks.push(check("context7", "error", "context7-runner-missing", "No supported direct Context7 runner is available.", "Install nub, Bun, pnpm, npm, or Yarn."));
5565
+ else checks.push(check("context7", "ok", "context7-cli-ready", `${context7.command} constructs a valid direct ctx7@latest command.`));
5566
+ const lsp = await runtime.command(process.execPath, [
5567
+ join(pluginRoot, "runtime", "lsp.js"),
5568
+ "status",
5569
+ "--json"
5570
+ ], {
5571
+ ...process.env,
5572
+ HOLYCODEX_LSP_IDLE_SHUTDOWN_MS: "0",
5573
+ HOLYCODEX_LSP_IDLE_CHECK_INTERVAL_MS: "50"
5574
+ });
5575
+ checks.push(lsp.ok ? check("lsp", "ok", "lsp-cli-ready", "The LSP CLI and daemon are reachable.") : check("lsp", "error", "lsp-cli-failed", lsp.output || "LSP CLI failed.", "Reinstall HolyCodex and inspect the reported daemon log."));
5634
5576
  if (runtime.platform === "win32") {
5635
- const gitBash = runtime.gitBash();
5636
- checks.push(gitBash.found ? check("git-bash", "ok", "git-bash-ready", `Git Bash: ${gitBash.path ?? "configured"}.`) : check("git-bash", "error", "missing-git-bash", "Git Bash is required on Windows but unavailable.", gitBash.installHint));
5637
- } else checks.push(check("git-bash", "ok", "git-bash-not-applicable", "Git Bash is not applicable on this platform."));
5638
- if (!configAvailable) checks.push(check("codex-config", "error", "missing-codex-config", `Missing ${configPath}.`, "Run holycodex install."));
5639
- const mode = autonomy(config);
5577
+ const resolution = runtime.gitBash();
5578
+ checks.push(resolution.found ? check("git-bash", "ok", "git-bash-launcher-ready", `Git Bash resolves at ${resolution.path}; the bundled launcher is present.`) : check("git-bash", "error", "git-bash-unavailable", resolution.installHint, resolution.installHint));
5579
+ }
5640
5580
  const plan = readManagedPlan(config);
5641
- checks.push(plan === void 0 ? check("routing-plan", "error", "routing-plan-missing", "No managed model routing plan is recorded.", "Rerun holycodex install.") : check("routing-plan", "ok", "routing-plan-ready", `Model routing plan ${plan} is active.`));
5642
- const preset = plan === void 0 ? void 0 : MODEL_ROUTING_PLANS[plan];
5643
- const managedFastMode = readManagedFastMode(config);
5644
- const managedMaxSubagents = readManagedMaxSubagents(config);
5645
- const expectedMaxSubagents = managedMaxSubagents.configured ? managedMaxSubagents.value : preset?.usage.maxSubagents;
5646
- const rootOverrides = readPreservedRootOverrides(config);
5647
- checks.push(preset !== void 0 && rootTomlString(config, "model") === preset.root.model && rootTomlString(config, "model_reasoning_effort") === preset.root.reasoningEffort ? check("root-model", "ok", "root-model-ready", "Root model matches the selected routing plan.") : rootOverrides.model || rootOverrides.reasoningEffort ? check("root-model", "ok", "root-model-override", "Root model uses an intentionally preserved explicit override.") : check("root-model", "error", "root-model-stale", "Root model configuration does not match the selected routing plan.", "Reinstall HolyCodex."));
5648
- checks.push(["default", "fast"].includes(rootTomlString(config, "service_tier") ?? "") && (managedFastMode === void 0 || rootTomlString(config, "service_tier") === (managedFastMode === "fast-all" ? "fast" : "default")) ? check("service-tier", "ok", "service-tier-ready", "Codex service tier is explicitly managed.") : check("service-tier", "error", "service-tier-stale", "service_tier does not match the managed Fast mode.", "Reinstall HolyCodex with --fast, --fast-all, or --no-fast."));
5649
- checks.push(rootTomlString(config, "model_verbosity") === "low" ? check("root-verbosity", "ok", "root-verbosity-ready", "Root model verbosity is forced to low.") : check("root-verbosity", "error", "root-verbosity-stale", "Root model verbosity must be low.", "Reinstall HolyCodex."));
5650
- checks.push(preset === void 0 || expectedMaxSubagents === void 0 || tableInteger(config, "agents", "max_threads") !== expectedMaxSubagents + 1 || tableInteger(config, "agents", "max_depth") !== preset.usage.maxDepth ? check("agent-usage", "error", "agent-usage-stale", "Agent concurrency configuration does not match the selected routing plan or explicit override.", "Reinstall HolyCodex.") : check("agent-usage", "ok", "agent-usage-ready", `Agent concurrency allows ${expectedMaxSubagents} direct subagent${expectedMaxSubagents === 1 ? "" : "s"}.`));
5651
- checks.push(mode === "unknown" ? check("autonomy", "error", "invalid-autonomy-config", "Approval policy, approval reviewer, sandbox, and network settings do not match a supported mode.", "Rerun install with the intended autonomy flag.") : mode === "dangerous" ? check("autonomy", "warning", "dangerous-autonomy", "Explicit dangerous autonomy is active; workspace containment is removed.") : check("autonomy", "ok", `${mode}-ready`, mode === "safe-workspace" ? "Safe workspace autonomy is active." : "Approval-free workspace autonomy is active."));
5652
- checks.push(tableBoolean(config, "features", "default_mode_request_user_input") === true ? check("user-input", "ok", "user-input-ready", "default_mode_request_user_input is enabled.") : check("user-input", "error", "user-input-disabled", "default_mode_request_user_input is not enabled.", "Rerun holycodex install."));
5653
- checks.push(tableStringArray(config, "desktop", "enabled-reasoning-efforts")?.join(",") === "low,medium,high,xhigh,max" ? check("desktop-reasoning", "ok", "desktop-reasoning-ready", "Desktop exposes low through max reasoning efforts.") : check("desktop-reasoning", "error", "desktop-reasoning-stale", "Desktop reasoning choices must include low through max.", "Reinstall HolyCodex."));
5654
- checks.push(tableBoolean(config, "desktop", "show-context-window-usage") === true ? check("desktop-context-usage", "ok", "desktop-context-usage-ready", "Desktop context-window usage is visible.") : check("desktop-context-usage", "error", "desktop-context-usage-hidden", "Desktop context-window usage is not enabled.", "Reinstall HolyCodex."));
5655
- checks.push(rootTomlStringArray(config, "status_line")?.includes("context-remaining") === true ? check("context-visibility", "warning", "context-visible-support-unverified", "status_line includes context-remaining. Current official Codex config documents this item, but publishes no minimum compatible Codex version.") : check("context-visibility", "error", "context-hidden", "status_line does not include context-remaining.", "Rerun holycodex install."));
5656
- const codex = await runtime.command("codex", ["--version"]);
5657
- checks.push(codex.ok ? check("codex", "ok", "codex-version", codex.output || "Codex is available.") : check("codex", "warning", "codex-version-unavailable", "Codex version could not be read; status-line compatibility cannot be independently confirmed."));
5658
- if (runtime.platform === "win32") checks.push(tableString(config, "windows", "sandbox") === "unelevated" ? check("windows-sandbox", "ok", "windows-sandbox-ready", "Windows sandbox runs unelevated.") : check("windows-sandbox", "error", "windows-sandbox-stale", "Windows sandbox must run unelevated.", "Reinstall HolyCodex on Windows."));
5659
- const agentModelFailures = [];
5660
- const agentTierValues = [];
5661
- for (const agent of AGENTS) try {
5662
- const text = await readFile(join(agentRoot, `${agent}.toml`), "utf8");
5663
- const expected = plan === void 0 ? void 0 : MODEL_ROUTING_PLANS[plan].agents[agent];
5664
- if (expected === void 0 || rootTomlString(text, "model") !== expected.model || rootTomlString(text, "model_reasoning_effort") !== expected.reasoningEffort) agentModelFailures.push(agent);
5665
- agentTierValues.push(rootTomlString(text, "service_tier"));
5666
- } catch {
5667
- agentModelFailures.push(agent);
5581
+ const overrides = readPreservedRootOverrides(config);
5582
+ const fast = readManagedFastMode(config);
5583
+ const max = readManagedMaxSubagents(config);
5584
+ checks.push(plan === void 0 ? check("routes", "error", "route-plan-missing", "Managed route plan metadata is missing.", "Reinstall HolyCodex.") : check("routes", "ok", "routes-ready", `${plan} routes are active${max.configured ? ` with max-subagents=${max.value ?? "invalid"}` : ""}.`));
5585
+ checks.push(overrides.model || overrides.reasoningEffort ? check("root-overrides", "ok", "root-overrides-preserved", "Intentional Root model or reasoning overrides are preserved and healthy.") : check("root-overrides", "ok", "root-managed-defaults", "Root uses managed route defaults."));
5586
+ if (plan !== void 0 && fast === void 0) checks.push(check("fast", "warning", "fast-metadata-missing", "Fast metadata is missing; doctor will not guess a service tier.", "Reinstall with an explicit Fast mode."));
5587
+ if (plan !== void 0) for (const agent of AGENTS) {
5588
+ const source = await readFile(join(agentRoot, `${agent}.toml`), "utf8").catch(() => "");
5589
+ const expected = MODEL_ROUTING_PLANS[plan].agents[agent];
5590
+ const overridden = rootTomlString(source, "model") !== expected.model || rootTomlString(source, "model_reasoning_effort") !== expected.reasoningEffort;
5591
+ checks.push(check(`agent-${agent}`, "ok", overridden ? "agent-override-preserved" : "agent-managed-default", overridden ? `${agent} has an intentional healthy route override.` : `${agent} uses managed route defaults.`));
5668
5592
  }
5669
- checks.push(agentModelFailures.length === 0 ? check("agent-models", "ok", "agent-models-ready", `Specialist models match the ${plan ?? "unknown"} routing plan.`) : check("agent-models", "error", "agent-models-stale", `Agent model configuration is stale for ${agentModelFailures.join(", ")}.`, "Reinstall HolyCodex."));
5670
- const expectedAgentTier = managedFastMode === "standard" ? "default" : "fast";
5671
- if (agentTierValues.some((value) => value !== void 0)) checks.push(agentTierValues.every((value) => value === expectedAgentTier) ? check("agent-service-tiers", "ok", "agent-service-tiers-ready", `Specialist service tiers use ${expectedAgentTier}.`) : check("agent-service-tiers", "error", "agent-service-tiers-stale", `Specialist service tiers must use ${expectedAgentTier}.`, "Reinstall HolyCodex."));
5593
+ for (const key of COMPATIBILITY_KEYS) if (config.includes(key.split(".")[1] ?? key)) checks.push(check(`compat-${key}`, "warning", "compatibility-sensitive-key", `${key} is compatibility-sensitive and isolated from supported managed Codex keys.`));
5672
5594
  return {
5673
- healthy: !checks.some((item) => item.status === "error"),
5674
- autonomy: mode,
5595
+ healthy: checks.every((item) => item.status !== "error"),
5596
+ autonomy: autonomy(config),
5675
5597
  checks
5676
5598
  };
5677
5599
  }
@@ -6363,6 +6285,7 @@ var defaultRuntime = {
6363
6285
  gitBash: resolveGitBashForCurrentProcess,
6364
6286
  runProcess: runManagedProcess
6365
6287
  };
6288
+ var BACKUP_RETENTION = 5;
6366
6289
  function paths(home = process.env.CODEX_HOME ?? join(homedir(), ".codex")) {
6367
6290
  const marketplaceCache = join(home, "plugins", "cache", "holycodex");
6368
6291
  const cacheRoot = join(marketplaceCache, "holycodex");
@@ -6394,39 +6317,63 @@ async function install(options, runtime = defaultRuntime) {
6394
6317
  const plan = options.plan ?? "plus";
6395
6318
  const target = paths();
6396
6319
  const root = backupRoot();
6320
+ const configBackup = await backup(target.config, root);
6321
+ const cacheBackup = await backup(target.marketplaceCache, root);
6322
+ const agentsBackup = await backup(target.agents, root);
6397
6323
  const backups = [
6398
- await backup(target.config, root),
6399
- await backup(target.marketplaceCache, root),
6400
- await backup(target.agents, root),
6324
+ configBackup,
6325
+ cacheBackup,
6326
+ agentsBackup,
6401
6327
  ...await Promise.all(target.legacy.map((path) => backup(path, root)))
6402
6328
  ].filter((path) => path !== void 0);
6403
6329
  const existingConfig = await readText(target.config);
6404
6330
  const previousPlan = readManagedPlan(existingConfig);
6405
6331
  const fastMode = options.fast ?? "standard";
6406
6332
  const config = installConfig(existingConfig, options.autonomy, runtime.platform, plan, options.maxSubagents, fastMode);
6407
- await atomicWrite(target.config, config);
6408
- await rm(target.cache, {
6409
- recursive: true,
6410
- force: true
6411
- });
6412
- await mkdir(dirname(target.cache), { recursive: true });
6413
- await cp(pluginRoot, target.cache, { recursive: true });
6414
- await writePlatformPlugin(target.cache, runtime.platform, plan, fastMode);
6415
6333
  const existingAgentPreferences = await readAgentPreferences(target.agents, previousPlan);
6416
- await rm(target.agents, {
6417
- recursive: true,
6418
- force: true
6419
- });
6420
- await cp(join(pluginRoot, "agents"), target.agents, { recursive: true });
6421
- await writeInstalledAgents(target.agents, runtime.platform, plan, fastMode);
6422
- await preserveAgentPreferences(target.agents, existingAgentPreferences, plan, fastMode);
6334
+ const staging = await mkdtemp(join(tmpdir(), "holycodex-stage-"));
6335
+ const stagedCache = join(staging, "cache");
6336
+ const stagedAgents = join(staging, "agents");
6337
+ await cp(pluginRoot, stagedCache, { recursive: true });
6338
+ await writeInstalledAgents(join(stagedCache, "agents"), runtime.platform, plan, fastMode);
6339
+ await cp(join(pluginRoot, "agents"), stagedAgents, { recursive: true });
6340
+ await writeInstalledAgents(stagedAgents, runtime.platform, plan, fastMode);
6341
+ await preserveAgentPreferences(stagedAgents, existingAgentPreferences, plan, fastMode);
6342
+ await validateStaging(stagedCache, stagedAgents);
6423
6343
  const removedLegacy = [];
6424
- for (const path of target.legacy) {
6425
- if (!await exists(path)) continue;
6426
- await rm(path, { recursive: true });
6427
- removedLegacy.push(path);
6344
+ let codexSecurity;
6345
+ try {
6346
+ await atomicWrite(target.config, config);
6347
+ await rm(target.cache, {
6348
+ recursive: true,
6349
+ force: true
6350
+ });
6351
+ await mkdir(dirname(target.cache), { recursive: true });
6352
+ await cp(stagedCache, target.cache, { recursive: true });
6353
+ await rm(target.agents, {
6354
+ recursive: true,
6355
+ force: true
6356
+ });
6357
+ await cp(stagedAgents, target.agents, { recursive: true });
6358
+ for (const path of target.legacy) {
6359
+ if (!await exists(path)) continue;
6360
+ await rm(path, { recursive: true });
6361
+ removedLegacy.push(path);
6362
+ }
6363
+ codexSecurity = await installCodexSecurity(runtime.runProcess, runtime.platform, process.env);
6364
+ await removeObsoleteVersionCaches(target.cacheRoot);
6365
+ } catch (error) {
6366
+ await restoreTarget(target.config, configBackup);
6367
+ await restoreTarget(target.marketplaceCache, cacheBackup);
6368
+ await restoreTarget(target.agents, agentsBackup);
6369
+ throw error;
6370
+ } finally {
6371
+ await rm(staging, {
6372
+ recursive: true,
6373
+ force: true
6374
+ });
6428
6375
  }
6429
- const codexSecurity = await installCodexSecurity(runtime.runProcess, runtime.platform, process.env);
6376
+ await pruneBackupHistory();
6430
6377
  return {
6431
6378
  action: "install",
6432
6379
  changed: [
@@ -6441,6 +6388,40 @@ async function install(options, runtime = defaultRuntime) {
6441
6388
  ...options.maxSubagents === void 0 ? {} : { maxSubagents: options.maxSubagents }
6442
6389
  };
6443
6390
  }
6391
+ async function validateStaging(cache, agents) {
6392
+ const required = [
6393
+ join(cache, ".codex-plugin", "plugin.json"),
6394
+ join(cache, "skills", "context7-cli", "SKILL.md"),
6395
+ join(cache, "runtime", "lsp.js"),
6396
+ ...AGENTS.map((agent) => join(agents, `${agent}.toml`))
6397
+ ];
6398
+ const missing = [];
6399
+ for (const path of required) if (!await exists(path)) missing.push(path);
6400
+ if (missing.length > 0) throw new Error(`Staged HolyCodex installation is incomplete: ${missing.join(", ")}`);
6401
+ }
6402
+ async function restoreTarget(target, source) {
6403
+ await rm(target, {
6404
+ recursive: true,
6405
+ force: true
6406
+ });
6407
+ if (source !== void 0) await cp(source, target, { recursive: true });
6408
+ }
6409
+ async function removeObsoleteVersionCaches(cacheRoot) {
6410
+ if (!await exists(cacheRoot)) return;
6411
+ for (const entry of await readdir(cacheRoot)) if (entry !== "0.11.2") await rm(join(cacheRoot, entry), {
6412
+ recursive: true,
6413
+ force: true
6414
+ });
6415
+ }
6416
+ async function pruneBackupHistory() {
6417
+ const root = join(tmpdir(), "holycodex-backups");
6418
+ if (!await exists(root)) return;
6419
+ const entries = (await readdir(root)).sort().reverse();
6420
+ await Promise.allSettled(entries.slice(BACKUP_RETENTION, 6).map((entry) => rm(join(root, entry), {
6421
+ recursive: true,
6422
+ force: true
6423
+ })));
6424
+ }
6444
6425
  var AGENT_MANAGED_KEYS = /* @__PURE__ */ new Set([
6445
6426
  "model",
6446
6427
  "model_reasoning_effort",
@@ -6448,7 +6429,6 @@ var AGENT_MANAGED_KEYS = /* @__PURE__ */ new Set([
6448
6429
  "service_tier"
6449
6430
  ]);
6450
6431
  var AGENT_BUNDLED_KEYS = /* @__PURE__ */ new Set(["description", "developer_instructions"]);
6451
- var COMPACT_WINDOWS_SHELL_POLICY = /^On native Windows, resolve `mcp__git_bash__run` before shell use;[^\r\n]*never use PowerShell\/cmd\.\r?\n\r?\n/m;
6452
6432
  async function readAgentPreferences(root, previousPlan) {
6453
6433
  const preferences = {};
6454
6434
  await Promise.all(AGENTS.map(async (agent) => {
@@ -6513,26 +6493,27 @@ function mergeCustomAgentSettings(input, custom) {
6513
6493
  if (custom.tables !== void 0 && !output.includes(custom.tables)) output = `${output.trimEnd()}\n\n${custom.tables}`;
6514
6494
  return `${output.trimEnd()}\n`;
6515
6495
  }
6516
- async function writePlatformPlugin(root, platform, plan, fastMode) {
6517
- await atomicWrite(join(root, ".mcp.json"), `${JSON.stringify({ mcpServers: effectiveMcpServers(platform) }, null, 2)}\n`);
6518
- await writeInstalledAgents(join(root, "agents"), platform, plan, fastMode);
6519
- }
6520
6496
  async function writeInstalledAgents(root, platform, plan, fastMode) {
6521
6497
  await Promise.all(AGENTS.map(async (agent) => {
6522
6498
  const path = join(root, `${agent}.toml`);
6523
6499
  const route = MODEL_ROUTING_PLANS[plan].agents[agent];
6524
6500
  let source = await readText(path);
6501
+ source = composeAgentPolicies(source, platform);
6525
6502
  source = replaceTomlString(source, "model", route.model);
6526
6503
  source = replaceTomlString(source, "model_reasoning_effort", route.reasoningEffort);
6527
6504
  source = replaceTomlString(source, "model_verbosity", "low");
6528
6505
  source = replaceOrAppendTomlString(source, "service_tier", fastMode === "standard" ? "default" : "fast");
6529
- if (platform === "win32") {
6530
- await atomicWrite(path, source);
6531
- return;
6532
- }
6533
- await atomicWrite(path, source.replace(`${WINDOWS_SHELL_POLICY}\r\n\r\n`, "").replace(`${WINDOWS_SHELL_POLICY}\n\n`, "").replace(COMPACT_WINDOWS_SHELL_POLICY, ""));
6506
+ await atomicWrite(path, source);
6534
6507
  }));
6535
6508
  }
6509
+ function composeAgentPolicies(input, platform) {
6510
+ const policy = [
6511
+ LITE_WRITING_POLICY,
6512
+ CONTEXT7_POLICY,
6513
+ ...platform === "win32" ? [WINDOWS_SHELL_POLICY] : []
6514
+ ].join("\n\n");
6515
+ return input.replace(/(developer_instructions\s*=\s*"""\r?\n)/, `$1${policy}\n\n`);
6516
+ }
6536
6517
  /** Provides cleanup. */
6537
6518
  async function cleanup(_options) {
6538
6519
  const target = paths();
@@ -6652,88 +6633,39 @@ function renderNotice(kind, message, color) {
6652
6633
  //#endregion
6653
6634
  //#region packages/cli/src/cli.ts
6654
6635
  async function main() {
6655
- const args = process$1.argv.slice(2);
6636
+ const parsed = parseCliArguments(process$1.argv.slice(2));
6656
6637
  const stdoutColor = supportsColor(process$1.stdout.isTTY, process$1.env.NO_COLOR);
6657
6638
  const stderrColor = supportsColor(process$1.stderr.isTTY, process$1.env.NO_COLOR);
6658
- const command = args.find((arg, index) => !arg.startsWith("-") && args[index - 1] !== "--plan" && args[index - 1] !== "--max-subagents");
6659
- if (args.includes("--help") || args.includes("-h") || args.length === 0) {
6660
- process$1.stdout.write(command === "install" ? renderInstallHelp(VERSION, stdoutColor) : renderHelp(VERSION, stdoutColor));
6639
+ if (parsed.action === "help") {
6640
+ process$1.stdout.write(parsed.command === "install" ? renderInstallHelp(VERSION, stdoutColor) : renderHelp(VERSION, stdoutColor));
6661
6641
  return;
6662
6642
  }
6663
- if (args.includes("--version") || args.includes("-v")) {
6643
+ if (parsed.action === "version") {
6664
6644
  process$1.stdout.write(`${VERSION}\n`);
6665
6645
  return;
6666
6646
  }
6667
- if (args.flatMap((arg, index) => arg === "--plan" ? [index] : []).length > 1) throw new Error("--plan may be specified only once.");
6668
- const planFlagIndex = args.indexOf("--plan");
6669
- const planValue = planFlagIndex < 0 ? DEFAULT_PLAN : args[planFlagIndex + 1];
6670
- if (planValue === void 0 || planValue.startsWith("-") || planValue === command) throw new Error(`Missing --plan value. Valid plans: ${PLAN_NAMES.join(", ")}.`);
6671
- const parsedPlan = PlanNameSchema.safeParse(planValue);
6672
- if (!parsedPlan.success) throw new Error(`Unknown plan: ${planValue}. Valid plans: ${PLAN_NAMES.join(", ")}.`);
6673
- const plan = parsedPlan.data;
6674
- if (args.flatMap((arg, index) => arg === "--max-subagents" ? [index] : []).length > 1) throw new Error("--max-subagents may be specified only once.");
6675
- const maxSubagentsIndex = args.indexOf("--max-subagents");
6676
- const maxSubagentsValue = maxSubagentsIndex < 0 ? void 0 : args[maxSubagentsIndex + 1];
6677
- if (maxSubagentsIndex >= 0 && (maxSubagentsValue === void 0 || maxSubagentsValue.startsWith("--") || maxSubagentsValue === command)) throw new Error("Missing --max-subagents value. Expected a nonnegative integer.");
6678
- if (maxSubagentsValue !== void 0 && !/^\d+$/.test(maxSubagentsValue)) throw new Error(`Invalid --max-subagents value: ${maxSubagentsValue}. Expected a nonnegative integer.`);
6679
- const maxSubagents = maxSubagentsValue === void 0 ? void 0 : Number(maxSubagentsValue);
6680
- const autonomyFlags = args.filter((arg) => [
6681
- "--codex-autonomous",
6682
- "--no-codex-autonomous",
6683
- "--dangerous-codex-autonomous"
6684
- ].includes(arg));
6685
- if (autonomyFlags.length > 1) {
6686
- process$1.stderr.write(renderError(`Conflicting autonomy flags: ${autonomyFlags.join(", ")}`, stderrColor));
6687
- process$1.exitCode = 1;
6688
- return;
6689
- }
6690
- const fastFlags = args.filter((arg) => [
6691
- "--fast",
6692
- "--fast-all",
6693
- "--no-fast"
6694
- ].includes(arg));
6695
- if (fastFlags.length > 1) {
6696
- process$1.stderr.write(renderError(`Conflicting fast flags: ${fastFlags.join(", ")}`, stderrColor));
6697
- process$1.exitCode = 1;
6698
- return;
6699
- }
6700
- const autonomy = args.includes("--dangerous-codex-autonomous") ? {
6701
- requested: true,
6702
- mode: "dangerous"
6703
- } : args.includes("--codex-autonomous") ? {
6704
- requested: true,
6705
- mode: "autonomous"
6706
- } : args.includes("--no-codex-autonomous") ? {
6707
- requested: true,
6708
- mode: "default"
6709
- } : { requested: false };
6710
6647
  const options = {
6711
- autonomy,
6712
- json: args.includes("--json"),
6713
- fast: args.includes("--fast-all") ? "fast-all" : args.includes("--fast") ? "fast" : "standard",
6714
- plan,
6715
- ...maxSubagents === void 0 ? {} : { maxSubagents }
6648
+ autonomy: parsed.autonomy,
6649
+ fast: parsed.fast,
6650
+ json: parsed.json,
6651
+ plan: parsed.plan,
6652
+ ...parsed.maxSubagents === void 0 ? {} : { maxSubagents: parsed.maxSubagents }
6716
6653
  };
6717
- if (command === "doctor") {
6654
+ if (parsed.command === "doctor") {
6718
6655
  const result = await doctor();
6719
- process$1.stdout.write(options.json ? `${JSON.stringify(result)}\n` : renderDoctor(result, stdoutColor));
6656
+ process$1.stdout.write(parsed.json ? `${JSON.stringify(result)}\n` : renderDoctor(result, stdoutColor));
6720
6657
  if (!result.healthy) process$1.exitCode = 1;
6721
6658
  return;
6722
6659
  }
6723
- if (autonomy.requested && autonomy.mode === "dangerous") process$1.stderr.write(renderNotice("warning", "Dangerous autonomy disables approvals and filesystem sandboxing.", stderrColor));
6724
- const result = command === "install" ? await install(options) : command === "cleanup" ? await cleanup(options) : void 0;
6725
- if (result === void 0) {
6726
- process$1.stderr.write(renderError(`Unknown command: ${command ?? args[0] ?? ""}`, stderrColor));
6727
- process$1.exitCode = 1;
6728
- return;
6729
- }
6730
- process$1.stdout.write(options.json ? `${JSON.stringify(result)}\n` : renderRunResult(result, stdoutColor));
6660
+ if (parsed.autonomy.requested && parsed.autonomy.mode === "dangerous") process$1.stderr.write(renderNotice("warning", "Dangerous autonomy disables approvals and filesystem sandboxing.", stderrColor));
6661
+ const result = parsed.command === "install" ? await install(options) : await cleanup(options);
6662
+ process$1.stdout.write(parsed.json ? `${JSON.stringify(result)}\n` : renderRunResult(result, stdoutColor));
6731
6663
  }
6732
6664
  try {
6733
6665
  await main();
6734
6666
  } catch (error) {
6735
- const stderrColor = supportsColor(process$1.stderr.isTTY, process$1.env.NO_COLOR);
6736
- process$1.stderr.write(renderError(formatCliError(error), stderrColor));
6667
+ const color = supportsColor(process$1.stderr.isTTY, process$1.env.NO_COLOR);
6668
+ process$1.stderr.write(renderError(formatCliError(error), color));
6737
6669
  process$1.exitCode = 1;
6738
6670
  }
6739
6671
  //#endregion
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "holycodex",
3
- "version": "0.11.0",
3
+ "version": "0.11.2",
4
4
  "description": "Lean Codex-only agent toolkit installer and doctor",
5
5
  "keywords": [
6
6
  "agents",
7
7
  "chatgpt",
8
8
  "codex",
9
- "mcp"
9
+ "developer-tools"
10
10
  ],
11
11
  "homepage": "https://github.com/davidbasilefilho/holycodex#readme",
12
12
  "bugs": {
@@ -39,10 +39,10 @@
39
39
  "prepack": "vp run --workspace-root build"
40
40
  },
41
41
  "dependencies": {
42
- "@holycodex/plugin": "0.11.0",
42
+ "@holycodex/plugin": "0.11.2",
43
43
  "zod": "^4.4.3"
44
44
  },
45
45
  "engines": {
46
- "node": ">=20"
46
+ "node": ">=26 <27"
47
47
  }
48
48
  }