@dotobokuri/fleet-console 1.22.1 → 1.24.0

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 (69) hide show
  1. package/AGENTS.md +41 -255
  2. package/README.md +8 -0
  3. package/dist/cli.d.ts +11 -1
  4. package/dist/cli.mjs +1866 -515
  5. package/dist/client/assets/{_baseUniq-cap0P4FK.js → _baseUniq-yooYbTgN.js} +1 -1
  6. package/dist/client/assets/{arc-yBqa09aK.js → arc-D4mme5Ts.js} +1 -1
  7. package/dist/client/assets/{architectureDiagram-Q4EWVU46-Bug4qdr-.js → architectureDiagram-Q4EWVU46-BAJOviEX.js} +1 -1
  8. package/dist/client/assets/{blockDiagram-DXYQGD6D-BkiIL2xt.js → blockDiagram-DXYQGD6D-DuObpxQ3.js} +1 -1
  9. package/dist/client/assets/{c4Diagram-AHTNJAMY-DYY200Al.js → c4Diagram-AHTNJAMY-BOT-SD34.js} +1 -1
  10. package/dist/client/assets/channel-TZYyAq1v.js +1 -0
  11. package/dist/client/assets/{chunk-4BX2VUAB-DQKmhVxn.js → chunk-4BX2VUAB-BF_aMTes.js} +1 -1
  12. package/dist/client/assets/{chunk-4TB4RGXK-DHpmA3Zl.js → chunk-4TB4RGXK-M4brBcnD.js} +1 -1
  13. package/dist/client/assets/{chunk-55IACEB6-DeRDuQXE.js → chunk-55IACEB6-CrG-4b2Z.js} +1 -1
  14. package/dist/client/assets/{chunk-EDXVE4YY-CNpnhSJm.js → chunk-EDXVE4YY-BxDSygH1.js} +1 -1
  15. package/dist/client/assets/{chunk-FMBD7UC4-BXGVABL-.js → chunk-FMBD7UC4-Bh7MEX7E.js} +1 -1
  16. package/dist/client/assets/{chunk-OYMX7WX6-WbJs4VwZ.js → chunk-OYMX7WX6-DBnBwxer.js} +1 -1
  17. package/dist/client/assets/{chunk-QZHKN3VN-u3BLl6Sl.js → chunk-QZHKN3VN-bjAogQwW.js} +1 -1
  18. package/dist/client/assets/{chunk-YZCP3GAM-BFESuhuJ.js → chunk-YZCP3GAM-l4FGlk_c.js} +1 -1
  19. package/dist/client/assets/classDiagram-6PBFFD2Q-Dh6hZUl4.js +1 -0
  20. package/dist/client/assets/classDiagram-v2-HSJHXN6E-Dh6hZUl4.js +1 -0
  21. package/dist/client/assets/clone-DgWGnVWH.js +1 -0
  22. package/dist/client/assets/{cose-bilkent-S5V4N54A-rouOsZjT.js → cose-bilkent-S5V4N54A-Bm5QA4zo.js} +1 -1
  23. package/dist/client/assets/{dagre-KV5264BT-QCUeCVpM.js → dagre-KV5264BT-PzXQN-5Q.js} +1 -1
  24. package/dist/client/assets/{diagram-5BDNPKRD-DqerlFb_.js → diagram-5BDNPKRD-KhaAKPtX.js} +1 -1
  25. package/dist/client/assets/{diagram-G4DWMVQ6-BS3a1YGN.js → diagram-G4DWMVQ6-DBbjfiR8.js} +1 -1
  26. package/dist/client/assets/{diagram-MMDJMWI5-BeauTcSV.js → diagram-MMDJMWI5-QWro7PRX.js} +1 -1
  27. package/dist/client/assets/{diagram-TYMM5635-Ci2wLUUE.js → diagram-TYMM5635-B9LqWrbF.js} +1 -1
  28. package/dist/client/assets/{erDiagram-SMLLAGMA-9MnmiKch.js → erDiagram-SMLLAGMA-b0VkMMN4.js} +1 -1
  29. package/dist/client/assets/{flowDiagram-DWJPFMVM-CiV9p5EU.js → flowDiagram-DWJPFMVM-edxBAbe6.js} +1 -1
  30. package/dist/client/assets/{ganttDiagram-T4ZO3ILL-D6oNoENl.js → ganttDiagram-T4ZO3ILL-ks2Gg1_V.js} +1 -1
  31. package/dist/client/assets/{gitGraphDiagram-UUTBAWPF-DESO385F.js → gitGraphDiagram-UUTBAWPF-DymUyYNl.js} +1 -1
  32. package/dist/client/assets/{graph-BZdl-RHy.js → graph-B-B_mqfh.js} +1 -1
  33. package/dist/client/assets/index-BgLzfg-v.css +1 -0
  34. package/dist/client/assets/index-pDnb-q6f.js +380 -0
  35. package/dist/client/assets/{infoDiagram-42DDH7IO-lc8vZnyi.js → infoDiagram-42DDH7IO-B5iLIYAc.js} +1 -1
  36. package/dist/client/assets/{ishikawaDiagram-UXIWVN3A-BfzvQXhn.js → ishikawaDiagram-UXIWVN3A-DnztLLn7.js} +1 -1
  37. package/dist/client/assets/{journeyDiagram-VCZTEJTY-BS_Dr0EV.js → journeyDiagram-VCZTEJTY-BKDRfH1Y.js} +1 -1
  38. package/dist/client/assets/{kanban-definition-6JOO6SKY-Cw7oTQJN.js → kanban-definition-6JOO6SKY-DPB3Phvr.js} +1 -1
  39. package/dist/client/assets/{layout-ChwcDQm8.js → layout-BEeRhYTG.js} +1 -1
  40. package/dist/client/assets/{linear-C7GLbmND.js → linear-QzmfWKSq.js} +1 -1
  41. package/dist/client/assets/{mermaid.core-D9phfpQo.js → mermaid.core-BVka5dgm.js} +4 -4
  42. package/dist/client/assets/{min-p7Whc_Wi.js → min-CfXk9kSN.js} +1 -1
  43. package/dist/client/assets/{mindmap-definition-QFDTVHPH-fl_SJKrw.js → mindmap-definition-QFDTVHPH-tGrGhr6Z.js} +1 -1
  44. package/dist/client/assets/{pieDiagram-DEJITSTG-Btw7ckA5.js → pieDiagram-DEJITSTG-ZRBqRiRK.js} +1 -1
  45. package/dist/client/assets/{quadrantDiagram-34T5L4WZ-DB4iJlTI.js → quadrantDiagram-34T5L4WZ-VCINZgct.js} +1 -1
  46. package/dist/client/assets/{requirementDiagram-MS252O5E-hXwV5Nhy.js → requirementDiagram-MS252O5E-DFLzADh3.js} +1 -1
  47. package/dist/client/assets/{sankeyDiagram-XADWPNL6-DC-fizCk.js → sankeyDiagram-XADWPNL6-BbouN8Ji.js} +1 -1
  48. package/dist/client/assets/{sequenceDiagram-FGHM5R23-RrfrroR5.js → sequenceDiagram-FGHM5R23-B58_LF0R.js} +1 -1
  49. package/dist/client/assets/{stateDiagram-FHFEXIEX-q8FUPV_e.js → stateDiagram-FHFEXIEX-pk-OHHuL.js} +1 -1
  50. package/dist/client/assets/stateDiagram-v2-QKLJ7IA2-xsN122JA.js +1 -0
  51. package/dist/client/assets/{timeline-definition-GMOUNBTQ-tegMd8Od.js → timeline-definition-GMOUNBTQ-4jQdCvaj.js} +1 -1
  52. package/dist/client/assets/{vennDiagram-DHZGUBPP-CXx5oN2X.js → vennDiagram-DHZGUBPP-CUr1fH6N.js} +1 -1
  53. package/dist/client/assets/{wardley-RL74JXVD-CxSJ3P_7.js → wardley-RL74JXVD-D0cfvvNA.js} +1 -1
  54. package/dist/client/assets/{wardleyDiagram-NUSXRM2D-DN1P180Z.js → wardleyDiagram-NUSXRM2D-D0l_Rp_Z.js} +1 -1
  55. package/dist/client/assets/{xychartDiagram-5P7HB3ND-Dcn9ukv5.js → xychartDiagram-5P7HB3ND-BdR8OEuJ.js} +1 -1
  56. package/dist/client/index.html +3 -3
  57. package/dist/desktop-protocol.d.ts +49 -0
  58. package/dist/desktop-protocol.mjs +99 -0
  59. package/dist/fleet-plugins/diff/routes.mjs +124 -225
  60. package/dist/fleet-plugins/skills/routes.mjs +218 -85
  61. package/dist/fleet-plugins/terminal/routes.mjs +573 -536
  62. package/package.json +7 -2
  63. package/dist/client/assets/channel-B3EqY8ya.js +0 -1
  64. package/dist/client/assets/classDiagram-6PBFFD2Q-BekEZLVJ.js +0 -1
  65. package/dist/client/assets/classDiagram-v2-HSJHXN6E-BekEZLVJ.js +0 -1
  66. package/dist/client/assets/clone-CsVi9-Ni.js +0 -1
  67. package/dist/client/assets/index-BKpCMFrm.js +0 -380
  68. package/dist/client/assets/index-cg8Uxys9.css +0 -1
  69. package/dist/client/assets/stateDiagram-v2-QKLJ7IA2-BErzXGq7.js +0 -1
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import * as fs2 from 'fs';
3
- import fs2__default, { existsSync, accessSync, constants, mkdtempSync, writeFileSync, mkdirSync, rmSync, chmodSync, renameSync, readdirSync, readFileSync, openSync, closeSync, realpathSync, fstatSync, lstatSync, unlinkSync, statSync } from 'fs';
4
- import * as path27 from 'path';
5
- import path27__default, { dirname } from 'path';
3
+ import fs2__default, { existsSync, readFileSync, accessSync, constants, mkdtempSync, writeFileSync, mkdirSync, rmSync, chmodSync, renameSync, readdirSync, openSync, closeSync, realpathSync, fstatSync, lstatSync, unlinkSync, statSync } from 'fs';
4
+ import * as path28 from 'path';
5
+ import path28__default, { dirname } from 'path';
6
6
  import * as os3 from 'os';
7
7
  import os3__default, { homedir } from 'os';
8
8
  import crypto4, { createHash, randomUUID } from 'crypto';
@@ -25,22 +25,22 @@ var __export = (target, all) => {
25
25
  function definePlugin(definition) {
26
26
  return definition;
27
27
  }
28
- function registerRouter(ctx, path42, handler) {
29
- ctx.registerRouter(normalizePath(path42), handler);
28
+ function registerRouter(ctx, path43, handler) {
29
+ ctx.registerRouter(normalizePath(path43), handler);
30
30
  }
31
- function registerWsHandler(ctx, path42, handler) {
32
- ctx.registerWsHandler(normalizePath(path42), handler);
31
+ function registerWsHandler(ctx, path43, handler) {
32
+ ctx.registerWsHandler(normalizePath(path43), handler);
33
33
  }
34
34
  function registerLaunchCatalog(ctx, provider) {
35
35
  return ctx.host.operations.registerLaunchCatalog(ctx.pluginId, provider);
36
36
  }
37
- function normalizePath(path42) {
38
- if (path42.length === 0 || path42 === "/") return "/";
39
- return path42;
37
+ function normalizePath(path43) {
38
+ if (path43.length === 0 || path43 === "/") return "/";
39
+ return path43;
40
40
  }
41
41
  var FLEET_DATA_DIR_NAME = ".fleet";
42
42
  function getFleetDataDir() {
43
- return path27.join(os3.homedir(), FLEET_DATA_DIR_NAME);
43
+ return path28.join(os3.homedir(), FLEET_DATA_DIR_NAME);
44
44
  }
45
45
  var SECURE_DIR_MODE = 448;
46
46
  var SECURE_FILE_MODE = 384;
@@ -128,7 +128,7 @@ function cleanupTempFiles(dir, prefix, minAgeMs, now) {
128
128
  if (!entry.startsWith(prefix)) {
129
129
  continue;
130
130
  }
131
- const tempPath = path27.join(dir, entry);
131
+ const tempPath = path28.join(dir, entry);
132
132
  try {
133
133
  const stat3 = fs2.lstatSync(tempPath);
134
134
  if (stat3?.isFile() && !stat3.isSymbolicLink() && now - stat3.mtimeMs >= minAgeMs) {
@@ -234,7 +234,7 @@ function writeLockOwner(lockDir, ownerFileName, startedAt) {
234
234
  hostname: os3.hostname(),
235
235
  startedAt
236
236
  };
237
- const ownerPath = path27.join(lockDir, ownerFileName);
237
+ const ownerPath = path28.join(lockDir, ownerFileName);
238
238
  try {
239
239
  fs2.writeFileSync(ownerPath, JSON.stringify(owner), { encoding: "utf-8", mode: 384 });
240
240
  } catch (error51) {
@@ -243,7 +243,7 @@ function writeLockOwner(lockDir, ownerFileName, startedAt) {
243
243
  }
244
244
  }
245
245
  function readLockOwner(lockDir, ownerFileName) {
246
- const ownerPath = path27.join(lockDir, ownerFileName);
246
+ const ownerPath = path28.join(lockDir, ownerFileName);
247
247
  try {
248
248
  return sanitizeLockOwner(JSON.parse(fs2.readFileSync(ownerPath, "utf-8")));
249
249
  } catch (error51) {
@@ -320,7 +320,7 @@ function readAuthStoreFile(filePath) {
320
320
  }
321
321
 
322
322
  // ../../packages/core-infra/src/auth/auth-storage.ts
323
- var DEFAULT_AUTH_PATH = path27.join(getFleetDataDir(), "auth.json");
323
+ var DEFAULT_AUTH_PATH = path28.join(getFleetDataDir(), "auth.json");
324
324
  var AUTH_LOCK_OWNER_FILE_NAME = "owner.json";
325
325
  var AUTH_LOCK_TIMEOUT_MS = 5e3;
326
326
  function createAuthService(deps = {}) {
@@ -376,7 +376,7 @@ function createAuthService(deps = {}) {
376
376
  }
377
377
  },
378
378
  async setApiKey(providerId, key) {
379
- const dir = path27.dirname(authPath);
379
+ const dir = path28.dirname(authPath);
380
380
  ensureSafeDirectory(dir);
381
381
  withAuthLock(authPath, lockDir, () => {
382
382
  const data = fs2.existsSync(authPath) ? readAuthStoreFile(authPath) : {};
@@ -411,7 +411,7 @@ function createDurableJsonStore(deps) {
411
411
  const now = deps.now ?? (() => Date.now());
412
412
  const mode = SECURE_FILE_MODE ;
413
413
  const minAgeMs = deps.tempCleanupMinAgeMs ?? DEFAULT_TEMP_FILE_MIN_AGE_MS;
414
- const dir = path27.dirname(deps.filePath);
414
+ const dir = path28.dirname(deps.filePath);
415
415
  return {
416
416
  path: deps.filePath,
417
417
  load() {
@@ -495,8 +495,8 @@ var LOCK_OWNER_FILE_NAME = "owner";
495
495
  var TEMP_FILE_PREFIX = `.tmp-${GLOBAL_OPTIONS_FILE_NAME}-`;
496
496
  function createGlobalOptionsStore(deps = {}) {
497
497
  const dataDir = deps.dataDir ?? getFleetDataDir();
498
- const optionsPath = path27.join(dataDir, GLOBAL_OPTIONS_FILE_NAME);
499
- const lockDir = path27.join(dataDir, LOCK_DIR_NAME);
498
+ const optionsPath = path28.join(dataDir, GLOBAL_OPTIONS_FILE_NAME);
499
+ const lockDir = path28.join(dataDir, LOCK_DIR_NAME);
500
500
  const store2 = createDurableJsonStore({
501
501
  filePath: optionsPath,
502
502
  lockDir,
@@ -529,10 +529,11 @@ function sanitizeGlobalOptionsData(value) {
529
529
  }
530
530
  const data = {
531
531
  version: GLOBAL_OPTIONS_VERSION,
532
- ...typeof value.enableMetaphor === "boolean" ? { enableMetaphor: value.enableMetaphor } : {}
532
+ ...typeof value.enableMetaphor === "boolean" ? { enableMetaphor: value.enableMetaphor } : {},
533
+ ...value.codexLaunchMode === "acp" || value.codexLaunchMode === "app-server" ? { codexLaunchMode: value.codexLaunchMode } : {}
533
534
  };
534
- const allowedKeys = /* @__PURE__ */ new Set(["version", "enableMetaphor"]);
535
- const changed = Object.keys(value).some((key) => !allowedKeys.has(key)) || "enableMetaphor" in value && typeof value.enableMetaphor !== "boolean";
535
+ const allowedKeys = /* @__PURE__ */ new Set(["version", "enableMetaphor", "codexLaunchMode"]);
536
+ const changed = Object.keys(value).some((key) => !allowedKeys.has(key)) || "enableMetaphor" in value && typeof value.enableMetaphor !== "boolean" || "codexLaunchMode" in value && value.codexLaunchMode !== "acp" && value.codexLaunchMode !== "app-server";
536
537
  return { data, changed };
537
538
  }
538
539
  function isRecord(value) {
@@ -1398,10 +1399,10 @@ function mergeDefs(...defs) {
1398
1399
  function cloneDef(schema) {
1399
1400
  return mergeDefs(schema._zod.def);
1400
1401
  }
1401
- function getElementAtPath(obj, path42) {
1402
- if (!path42)
1402
+ function getElementAtPath(obj, path43) {
1403
+ if (!path43)
1403
1404
  return obj;
1404
- return path42.reduce((acc, key) => acc?.[key], obj);
1405
+ return path43.reduce((acc, key) => acc?.[key], obj);
1405
1406
  }
1406
1407
  function promiseAllObject(promisesObj) {
1407
1408
  const keys = Object.keys(promisesObj);
@@ -1810,11 +1811,11 @@ function explicitlyAborted(x, startIndex = 0) {
1810
1811
  }
1811
1812
  return false;
1812
1813
  }
1813
- function prefixIssues(path42, issues) {
1814
+ function prefixIssues(path43, issues) {
1814
1815
  return issues.map((iss) => {
1815
1816
  var _a3;
1816
1817
  (_a3 = iss).path ?? (_a3.path = []);
1817
- iss.path.unshift(path42);
1818
+ iss.path.unshift(path43);
1818
1819
  return iss;
1819
1820
  });
1820
1821
  }
@@ -1961,16 +1962,16 @@ function flattenError(error51, mapper = (issue3) => issue3.message) {
1961
1962
  }
1962
1963
  function formatError(error51, mapper = (issue3) => issue3.message) {
1963
1964
  const fieldErrors = { _errors: [] };
1964
- const processError = (error52, path42 = []) => {
1965
+ const processError = (error52, path43 = []) => {
1965
1966
  for (const issue3 of error52.issues) {
1966
1967
  if (issue3.code === "invalid_union" && issue3.errors.length) {
1967
- issue3.errors.map((issues) => processError({ issues }, [...path42, ...issue3.path]));
1968
+ issue3.errors.map((issues) => processError({ issues }, [...path43, ...issue3.path]));
1968
1969
  } else if (issue3.code === "invalid_key") {
1969
- processError({ issues: issue3.issues }, [...path42, ...issue3.path]);
1970
+ processError({ issues: issue3.issues }, [...path43, ...issue3.path]);
1970
1971
  } else if (issue3.code === "invalid_element") {
1971
- processError({ issues: issue3.issues }, [...path42, ...issue3.path]);
1972
+ processError({ issues: issue3.issues }, [...path43, ...issue3.path]);
1972
1973
  } else {
1973
- const fullpath = [...path42, ...issue3.path];
1974
+ const fullpath = [...path43, ...issue3.path];
1974
1975
  if (fullpath.length === 0) {
1975
1976
  fieldErrors._errors.push(mapper(issue3));
1976
1977
  } else {
@@ -1997,17 +1998,17 @@ function formatError(error51, mapper = (issue3) => issue3.message) {
1997
1998
  }
1998
1999
  function treeifyError(error51, mapper = (issue3) => issue3.message) {
1999
2000
  const result = { errors: [] };
2000
- const processError = (error52, path42 = []) => {
2001
+ const processError = (error52, path43 = []) => {
2001
2002
  var _a3, _b;
2002
2003
  for (const issue3 of error52.issues) {
2003
2004
  if (issue3.code === "invalid_union" && issue3.errors.length) {
2004
- issue3.errors.map((issues) => processError({ issues }, [...path42, ...issue3.path]));
2005
+ issue3.errors.map((issues) => processError({ issues }, [...path43, ...issue3.path]));
2005
2006
  } else if (issue3.code === "invalid_key") {
2006
- processError({ issues: issue3.issues }, [...path42, ...issue3.path]);
2007
+ processError({ issues: issue3.issues }, [...path43, ...issue3.path]);
2007
2008
  } else if (issue3.code === "invalid_element") {
2008
- processError({ issues: issue3.issues }, [...path42, ...issue3.path]);
2009
+ processError({ issues: issue3.issues }, [...path43, ...issue3.path]);
2009
2010
  } else {
2010
- const fullpath = [...path42, ...issue3.path];
2011
+ const fullpath = [...path43, ...issue3.path];
2011
2012
  if (fullpath.length === 0) {
2012
2013
  result.errors.push(mapper(issue3));
2013
2014
  continue;
@@ -2039,8 +2040,8 @@ function treeifyError(error51, mapper = (issue3) => issue3.message) {
2039
2040
  }
2040
2041
  function toDotPath(_path) {
2041
2042
  const segs = [];
2042
- const path42 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
2043
- for (const seg of path42) {
2043
+ const path43 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
2044
+ for (const seg of path43) {
2044
2045
  if (typeof seg === "number")
2045
2046
  segs.push(`[${seg}]`);
2046
2047
  else if (typeof seg === "symbol")
@@ -14704,13 +14705,13 @@ function resolveRef(ref, ctx) {
14704
14705
  if (!ref.startsWith("#")) {
14705
14706
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
14706
14707
  }
14707
- const path42 = ref.slice(1).split("/").filter(Boolean);
14708
- if (path42.length === 0) {
14708
+ const path43 = ref.slice(1).split("/").filter(Boolean);
14709
+ if (path43.length === 0) {
14709
14710
  return ctx.rootSchema;
14710
14711
  }
14711
14712
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
14712
- if (path42[0] === defsKey) {
14713
- const key = path42[1];
14713
+ if (path43[0] === defsKey) {
14714
+ const key = path43[1];
14714
14715
  if (!key || !ctx.defs[key]) {
14715
14716
  throw new Error(`Reference not found: ${ref}`);
14716
14717
  }
@@ -18883,7 +18884,7 @@ function createChildEnv(env, overlay) {
18883
18884
  return child;
18884
18885
  }
18885
18886
  function wrapWindowsShim(resolved, env, platform) {
18886
- if (platform !== "win32" || !WINDOWS_SHIM_EXTENSIONS.has(path27__default.extname(resolved).toLowerCase())) {
18887
+ if (platform !== "win32" || !WINDOWS_SHIM_EXTENSIONS.has(path28__default.extname(resolved).toLowerCase())) {
18887
18888
  return { bin: resolved, prefixArgs: [] };
18888
18889
  }
18889
18890
  rejectCmdExpansionSensitiveShim(resolved);
@@ -18901,13 +18902,13 @@ function forceWindowsArgQuoting(value) {
18901
18902
  return `${value} `;
18902
18903
  }
18903
18904
  function findOnPath(bin, pathValue, pathExts, platform) {
18904
- const pathSeparator = platform === "win32" ? WINDOWS_PATH_SEPARATOR : path27__default.delimiter;
18905
- if (hasPathSeparator(bin, platform) || path27__default.isAbsolute(bin)) {
18905
+ const pathSeparator = platform === "win32" ? WINDOWS_PATH_SEPARATOR : path28__default.delimiter;
18906
+ if (hasPathSeparator(bin, platform) || path28__default.isAbsolute(bin)) {
18906
18907
  return resolveWithExtensions(bin, pathExts, platform);
18907
18908
  }
18908
18909
  for (const entry of pathValue.split(pathSeparator)) {
18909
18910
  const searchDir = entry.length === 0 ? "." : entry;
18910
- const candidate = resolveWithExtensions(path27__default.join(searchDir, bin), pathExts, platform);
18911
+ const candidate = resolveWithExtensions(path28__default.join(searchDir, bin), pathExts, platform);
18911
18912
  if (candidate) {
18912
18913
  return candidate;
18913
18914
  }
@@ -18915,7 +18916,7 @@ function findOnPath(bin, pathValue, pathExts, platform) {
18915
18916
  return void 0;
18916
18917
  }
18917
18918
  function resolveWithExtensions(candidate, pathExts, platform) {
18918
- if (platform !== "win32" || path27__default.extname(candidate).length > 0) {
18919
+ if (platform !== "win32" || path28__default.extname(candidate).length > 0) {
18919
18920
  return isAccessibleExecutable(candidate, platform) ? candidate : void 0;
18920
18921
  }
18921
18922
  for (const ext of pathExts) {
@@ -20329,11 +20330,24 @@ function getYoloModeId(cli) {
20329
20330
  return "yolo";
20330
20331
  }
20331
20332
  }
20332
- function buildCodexDeveloperInstructionConfig(systemPrompt) {
20333
- if (!systemPrompt) {
20334
- return [];
20333
+ function buildCodexConfigEnv(systemPrompt, configOverrides, baseConfigJson) {
20334
+ const map2 = parseBaseConfigMap(baseConfigJson);
20335
+ for (const override of configOverrides ?? []) {
20336
+ const eqIndex = override.indexOf("=");
20337
+ if (eqIndex < 0) {
20338
+ continue;
20339
+ }
20340
+ const key = override.slice(0, eqIndex);
20341
+ const rawValue = override.slice(eqIndex + 1);
20342
+ assignNestedKey(map2, key, parseOverrideValue(rawValue));
20335
20343
  }
20336
- return [`developer_instructions="${escapeTomlBasicString(systemPrompt)}"`];
20344
+ if (systemPrompt) {
20345
+ map2.developer_instructions = systemPrompt;
20346
+ }
20347
+ if (Object.keys(map2).length === 0) {
20348
+ return void 0;
20349
+ }
20350
+ return JSON.stringify(map2);
20337
20351
  }
20338
20352
  function buildConfigOverrideArgs(overrides) {
20339
20353
  return overrides.flatMap((override) => ["-c", override]);
@@ -20361,27 +20375,44 @@ function mcpServerConfigsToAcp(servers) {
20361
20375
  headers: server.headers ?? []
20362
20376
  }));
20363
20377
  }
20364
- function escapeTomlBasicString(value) {
20365
- return value.replace(/[\u0000-\u001f"\\\u007f]/g, (char) => {
20366
- switch (char) {
20367
- case "\b":
20368
- return "\\b";
20369
- case " ":
20370
- return "\\t";
20371
- case "\n":
20372
- return "\\n";
20373
- case "\f":
20374
- return "\\f";
20375
- case "\r":
20376
- return "\\r";
20377
- case '"':
20378
- return '\\"';
20379
- case "\\":
20380
- return "\\\\";
20381
- default:
20382
- return `\\u${char.charCodeAt(0).toString(16).padStart(4, "0")}`;
20378
+ function parseBaseConfigMap(baseConfigJson) {
20379
+ if (!baseConfigJson) {
20380
+ return {};
20381
+ }
20382
+ try {
20383
+ const parsed = JSON.parse(baseConfigJson);
20384
+ if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
20385
+ return parsed;
20383
20386
  }
20384
- });
20387
+ } catch {
20388
+ }
20389
+ return {};
20390
+ }
20391
+ function parseOverrideValue(raw) {
20392
+ try {
20393
+ return JSON.parse(raw);
20394
+ } catch {
20395
+ if (raw.length >= 2 && raw.startsWith('"') && raw.endsWith('"')) {
20396
+ return raw.slice(1, -1);
20397
+ }
20398
+ return raw;
20399
+ }
20400
+ }
20401
+ function assignNestedKey(target, dottedKey, value) {
20402
+ const segments = dottedKey.split(".");
20403
+ let cursor = target;
20404
+ for (let i = 0; i < segments.length - 1; i += 1) {
20405
+ const segment = segments[i];
20406
+ const existing = cursor[segment];
20407
+ if (typeof existing === "object" && existing !== null && !Array.isArray(existing)) {
20408
+ cursor = existing;
20409
+ } else {
20410
+ const nested = {};
20411
+ cursor[segment] = nested;
20412
+ cursor = nested;
20413
+ }
20414
+ }
20415
+ cursor[segments[segments.length - 1]] = value;
20385
20416
  }
20386
20417
 
20387
20418
  // ../../packages/core-unified-agent/src/detector/CliDetector.ts
@@ -21642,12 +21673,12 @@ var CodexAppServerConnection = class extends BaseConnection {
21642
21673
  );
21643
21674
  }
21644
21675
  findRolloutPathForThreadId(threadId) {
21645
- const codexHome = this.codexHome ?? this.env.CODEX_HOME ?? path27.join(this.env.HOME ?? "", ".codex");
21676
+ const codexHome = this.codexHome ?? this.env.CODEX_HOME ?? path28.join(this.env.HOME ?? "", ".codex");
21646
21677
  if (!codexHome) {
21647
21678
  return null;
21648
21679
  }
21649
21680
  for (const rootName of ["sessions", "archived_sessions"]) {
21650
- const found = findRolloutPath(path27.join(codexHome, rootName), threadId);
21681
+ const found = findRolloutPath(path28.join(codexHome, rootName), threadId);
21651
21682
  if (found) {
21652
21683
  return found;
21653
21684
  }
@@ -21758,7 +21789,7 @@ function findRolloutPath(root, threadId) {
21758
21789
  return null;
21759
21790
  }
21760
21791
  for (const entry of fs2.readdirSync(root, { withFileTypes: true })) {
21761
- const entryPath = path27.join(root, entry.name);
21792
+ const entryPath = path28.join(root, entry.name);
21762
21793
  if (entry.isDirectory()) {
21763
21794
  const found = findRolloutPath(entryPath, threadId);
21764
21795
  if (found) {
@@ -21776,13 +21807,11 @@ function findRolloutPath(root, threadId) {
21776
21807
  // ../../packages/core-unified-agent/src/client/UnifiedCodexAgentClient.ts
21777
21808
  var CODEX_TURN_LEVEL_CONFIG_KEYS = /* @__PURE__ */ new Set(["effort", "model"]);
21778
21809
  var CODEX_THREAD_POLICY_CONFIG_KEYS = /* @__PURE__ */ new Set(["approvalPolicy", "sandbox"]);
21779
- var CODEX_ACP_PROMPT_FALLBACK = process.platform === "win32";
21780
21810
  var UnifiedCodexAgentClient = class extends EventEmitter {
21781
21811
  connection = null;
21782
21812
  sessionId = null;
21783
21813
  sessionCwd = null;
21784
21814
  currentSystemPrompt = null;
21785
- firstPromptPending = null;
21786
21815
  pendingOverrides = null;
21787
21816
  detector = new CliDetector();
21788
21817
  on(event, listener) {
@@ -21803,9 +21832,10 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
21803
21832
  throw new Error("UnifiedCodexAgentClient\uB294 codex CLI\uB9CC \uC9C0\uC6D0\uD569\uB2C8\uB2E4.");
21804
21833
  }
21805
21834
  this.validateModelEffort(options.model, options.effort);
21806
- {
21835
+ if (shouldUseCodexAcp(options)) {
21807
21836
  return this.connectAcp(options);
21808
21837
  }
21838
+ return this.connectAppServer(options);
21809
21839
  }
21810
21840
  async connectAppServer(options) {
21811
21841
  const backend = getBackendConfig("codex");
@@ -21874,22 +21904,17 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
21874
21904
  async connectAcp(options) {
21875
21905
  const cleanEnv = cleanEnvironment(process.env, options.env);
21876
21906
  const spawnConfig = createSpawnConfig("codex", options);
21877
- const developerInstructions = CODEX_ACP_PROMPT_FALLBACK ? void 0 : options.systemPrompt ?? void 0;
21878
- const args = [
21879
- ...spawnConfig.args,
21880
- ...this.buildStartupConfigArgs(
21881
- options.configOverrides,
21882
- void 0,
21883
- void 0,
21884
- developerInstructions
21885
- )
21886
- ];
21907
+ const codexConfigEnv = buildCodexConfigEnv(
21908
+ options.systemPrompt,
21909
+ options.configOverrides,
21910
+ cleanEnv.CODEX_CONFIG
21911
+ );
21887
21912
  const connection = new AcpConnection({
21888
21913
  command: spawnConfig.command,
21889
- args,
21914
+ args: spawnConfig.args,
21890
21915
  cliType: "codex",
21891
21916
  cwd: options.cwd,
21892
- env: { ...cleanEnv },
21917
+ env: { ...cleanEnv, ...codexConfigEnv ? { CODEX_CONFIG: codexConfigEnv } : {} },
21893
21918
  requestTimeout: options.timeout ?? 6e5,
21894
21919
  initTimeout: options.timeout ?? 6e4,
21895
21920
  promptIdleTimeout: options.promptIdleTimeout ?? 6e5,
@@ -21986,17 +22011,7 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
21986
22011
  if (!this.sessionId) {
21987
22012
  throw new Error("\uC5F0\uACB0\uB418\uC5B4 \uC788\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
21988
22013
  }
21989
- const systemPrompt = this.firstPromptPending;
21990
- if (!systemPrompt) {
21991
- return this.connection.sendPrompt(this.sessionId, content);
21992
- }
21993
- const userBlocks = typeof content === "string" ? [{ type: "text", text: content }] : content;
21994
- const response = await this.connection.sendPrompt(this.sessionId, [
21995
- { type: "text", text: systemPrompt },
21996
- ...userBlocks
21997
- ]);
21998
- this.firstPromptPending = null;
21999
- return response;
22014
+ return this.connection.sendPrompt(this.sessionId, content);
22000
22015
  }
22001
22016
  this.applyPendingOverrides();
22002
22017
  const input = typeof content === "string" ? [{ type: "text", text: content, text_elements: [] }] : content.map((block) => "text" in block ? { type: "text", text: block.text, text_elements: [] } : { type: "text", text: JSON.stringify(block), text_elements: [] });
@@ -22078,8 +22093,6 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
22078
22093
  mcpServers: this.resolveAcpMcpServers(mcpServers)
22079
22094
  });
22080
22095
  this.sessionId = sessionId;
22081
- this.currentSystemPrompt = null;
22082
- this.firstPromptPending = null;
22083
22096
  return;
22084
22097
  }
22085
22098
  if (mcpServers?.length) {
@@ -22116,7 +22129,6 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
22116
22129
  const session = await this.connection.reconnectSession(targetCwd);
22117
22130
  this.sessionId = session.sessionId;
22118
22131
  this.sessionCwd = targetCwd;
22119
- this.firstPromptPending = this.currentSystemPrompt;
22120
22132
  return {
22121
22133
  cli: "codex",
22122
22134
  protocol: "acp",
@@ -22144,7 +22156,6 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
22144
22156
  this.sessionId = session.sessionId;
22145
22157
  this.sessionCwd = options.cwd;
22146
22158
  this.currentSystemPrompt = options.systemPrompt ?? null;
22147
- this.firstPromptPending = CODEX_ACP_PROMPT_FALLBACK && !options.sessionId ? options.systemPrompt ?? null : null;
22148
22159
  this.pendingOverrides = {
22149
22160
  turnConfig: {},
22150
22161
  threadConfig: {}
@@ -22162,7 +22173,6 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
22162
22173
  this.sessionId = null;
22163
22174
  this.sessionCwd = null;
22164
22175
  this.currentSystemPrompt = null;
22165
- this.firstPromptPending = null;
22166
22176
  this.pendingOverrides = null;
22167
22177
  }
22168
22178
  validateModelEffort(modelId, effort) {
@@ -22373,9 +22383,8 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
22373
22383
  return "read-only";
22374
22384
  }
22375
22385
  }
22376
- buildStartupConfigArgs(overrides, servers, modeMapping, developerInstructions) {
22386
+ buildStartupConfigArgs(overrides, servers, modeMapping) {
22377
22387
  const configArgs = [
22378
- ...buildCodexDeveloperInstructionConfig(developerInstructions),
22379
22388
  ...modeMapping ? [
22380
22389
  `approval_policy="${modeMapping.approvalPolicy}"`,
22381
22390
  `sandbox_mode="${modeMapping.sandbox}"`
@@ -22464,6 +22473,11 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
22464
22473
  return patterns.some((pattern) => pattern.test(text));
22465
22474
  }
22466
22475
  };
22476
+ function shouldUseCodexAcp(options) {
22477
+ const value = options.env?.CODEX_USE_ACP ?? process.env.CODEX_USE_ACP;
22478
+ const normalized = value?.trim().toLowerCase();
22479
+ return normalized !== "false" && normalized !== "0";
22480
+ }
22467
22481
  var UnifiedCursorAgentClient = class extends EventEmitter {
22468
22482
  connection = null;
22469
22483
  sessionId = null;
@@ -25085,7 +25099,7 @@ function readRawCarriersOrDefaultStore() {
25085
25099
  return readCarriers();
25086
25100
  }
25087
25101
  function getCarriersFilePath() {
25088
- return path27.join(resolveStoreDir(), FILENAME);
25102
+ return path28.join(resolveStoreDir(), FILENAME);
25089
25103
  }
25090
25104
  function updateCarriers(mutator) {
25091
25105
  withStoreLock(() => {
@@ -25099,7 +25113,7 @@ function updateCarriers(mutator) {
25099
25113
  function withStoreLock(operation) {
25100
25114
  const dir = resolveStoreDir();
25101
25115
  ensureSafeDirectory(dir);
25102
- const lockDir = path27.join(dir, LOCK_DIRNAME);
25116
+ const lockDir = path28.join(dir, LOCK_DIRNAME);
25103
25117
  return withDirectoryLock(
25104
25118
  { lockDir, ownerFileName: LOCK_OWNER_FILENAME },
25105
25119
  operation
@@ -25112,7 +25126,7 @@ function readCarriers() {
25112
25126
  return readCarriersFromDir(resolveStoreDir());
25113
25127
  }
25114
25128
  function readCarriersFromDir(dir) {
25115
- const filePath = path27.join(dir, FILENAME);
25129
+ const filePath = path28.join(dir, FILENAME);
25116
25130
  let fd;
25117
25131
  try {
25118
25132
  const stat3 = fs2.lstatSync(filePath);
@@ -25141,7 +25155,7 @@ function recordLastLocalWriteFingerprint(filePath, generation) {
25141
25155
  }
25142
25156
  function writeCarriers(s) {
25143
25157
  const dir = resolveStoreDir();
25144
- const filePath = path27.join(dir, FILENAME);
25158
+ const filePath = path28.join(dir, FILENAME);
25145
25159
  const next = serializeFleetCarriers(s);
25146
25160
  writeAtomicSync(filePath, `${JSON.stringify(next, null, 2)}
25147
25161
  `, { fsync: false, mode: 420 });
@@ -25166,7 +25180,7 @@ function sanitizeFleetCarriers(value) {
25166
25180
  }
25167
25181
  function unlinkStaleSubagentModeFile(dir) {
25168
25182
  try {
25169
- fs2.unlinkSync(path27.join(dir, STALE_SUBAGENT_MODE_FILENAME));
25183
+ fs2.unlinkSync(path28.join(dir, STALE_SUBAGENT_MODE_FILENAME));
25170
25184
  } catch {
25171
25185
  }
25172
25186
  }
@@ -25722,7 +25736,7 @@ var CHRONICLE_DEFAULTS = {
25722
25736
  };
25723
25737
  var CARRIER_METADATA = {
25724
25738
  // ── Tier 1: Routing ──
25725
- title: "Captain \xB7 Chief Knowledge Officer",
25739
+ title: "Chief Knowledge Officer",
25726
25740
  summary: "Documentation steward across two surfaces: codebase markdown (AGENTS.md/README/CHANGELOG/inline docs) and Fleet Wiki entries proposed via the wiki patch queue.",
25727
25741
  category: "operations",
25728
25742
  whenToUse: [
@@ -25735,7 +25749,7 @@ var CARRIER_METADATA = {
25735
25749
  "before implementation and verification are complete",
25736
25750
  "code modification (\u2192genesis) or code review (\u2192sentinel)",
25737
25751
  "architectural judgment (\u2192nimitz) or release-scope planning decisions (\u2192kirov)",
25738
- "Fleet Wiki patch approval \u2014 Admiral retains the wiki_patch_queue approve/reject gate"
25752
+ "Fleet Wiki patch approval \u2014 host agent retains the wiki_patch_queue approve/reject gate"
25739
25753
  ],
25740
25754
  requestBlocks: [
25741
25755
  {
@@ -25771,18 +25785,18 @@ var CARRIER_METADATA = {
25771
25785
  ],
25772
25786
  // ── Tier 2: Composition ──
25773
25787
  permissions: [
25774
- "CRITICAL: Fleet Wiki entries are governed by the Fleet Wiki workspace AGENTS.md doctrine \u2014 propose via wiki_ingest only, and NEVER edit wiki entries or system-managed indexes/logs by hand. Admiral holds the wiki_patch_queue approve/reject gate.",
25788
+ "CRITICAL: Fleet Wiki entries are governed by the Fleet Wiki workspace AGENTS.md doctrine \u2014 propose via wiki_ingest only, and NEVER edit wiki entries or system-managed indexes/logs by hand. The host agent holds the wiki_patch_queue approve/reject gate.",
25775
25789
  "CRITICAL: Owns codebase markdown \u2014 AGENTS.md, README, CHANGELOG, and inline doc files outside the Fleet Wiki workspace \u2014 and may write them directly. NEVER modify source code logic (report issues instead).",
25776
- "MUST treat the Admiral's <doc_type>, <audience>, <scope>, and <change_scope> as binding contracts. NEVER redefine or expand documentation scope autonomously.",
25777
- "Owns expression details (tone, wording, paragraph flow within domain conventions) but MUST NOT silently change structural decisions specified by the Admiral (sections, items, target files).",
25790
+ "MUST treat the host agent's <doc_type>, <audience>, <scope>, and <change_scope> as binding contracts. NEVER redefine or expand documentation scope autonomously.",
25791
+ "Owns expression details (tone, wording, paragraph flow within domain conventions) but MUST NOT silently change structural decisions specified by the host agent (sections, items, target files).",
25778
25792
  "MUST NOT make go/no-go, release timing, or release-scope decisions (escalate to Kirov/Nimitz). May detect and document breaking changes only."
25779
25793
  ],
25780
25794
  outputFormat: `Deliver the documentation artifact directly.
25781
25795
  [Codebase Doc] Write the .md/AGENTS.md/README/CHANGELOG file(s) directly via filesystem tools.
25782
- [Fleet Wiki] Compose the entry body and enqueue via wiki_ingest. Report the patch_id; never edit wiki entries or system-managed files by hand. Admiral approves via wiki_patch_queue.
25796
+ [Fleet Wiki] Compose the entry body and enqueue via wiki_ingest. Report the patch_id; never edit wiki entries or system-managed files by hand. The host agent approves via wiki_patch_queue.
25783
25797
  After delivery, provide a brief completion report.
25784
25798
  [Required] always include:
25785
- **Workflow** \u2014 One of: 'Codebase Doc' or 'Fleet Wiki' (state which workflow this sortie used).
25799
+ **Workflow** \u2014 One of: 'Codebase Doc' or 'Fleet Wiki' (state which workflow this task used).
25786
25800
  **Documents written / Patches enqueued** \u2014 Each file created/modified (Codebase Doc) OR each patch_id enqueued (Fleet Wiki) with target path.
25787
25801
  **Cascade .md audit** \u2014 (Codebase Doc only) Each .md inspected: path, status (updated / already consistent / not applicable), 1-line summary if updated.
25788
25802
  [If applicable] omit if not relevant:
@@ -25791,10 +25805,10 @@ After delivery, provide a brief completion report.
25791
25805
  Keep the completion report concise \u2014 the documentation/patch itself is the primary deliverable.`,
25792
25806
  principles: [
25793
25807
  CARRIER_JOBS_SELF_CALL_HINT,
25794
- "Two workflows, one carrier \u2014 never mix the two surfaces. (A) Codebase Doc: direct filesystem edits to .md/AGENTS.md/README/CHANGELOG outside the Fleet Wiki workspace. (B) Fleet Wiki: orient \u2192 consult \u2192 lint \u2192 wiki_ingest to enqueue \u2192 Admiral approves via wiki_patch_queue. Decide the workflow from <doc_type>; if ambiguous, escalate before acting.",
25795
- "[Fleet Wiki] Read the Fleet Wiki workspace AGENTS.md before the first wiki operation in a sortie \u2014 it is the authoritative doctrine for boundaries, roles, gates, schema reference, and escalation. The active entry schema may evolve; always consult the workspace doctrine and current schema each sortie rather than relying on prior memory.",
25808
+ "Two workflows, one carrier \u2014 never mix the two surfaces. (A) Codebase Doc: direct filesystem edits to .md/AGENTS.md/README/CHANGELOG outside the Fleet Wiki workspace. (B) Fleet Wiki: orient \u2192 consult \u2192 lint \u2192 wiki_ingest to enqueue \u2192 host agent approves via wiki_patch_queue. Decide the workflow from <doc_type>; if ambiguous, escalate before acting.",
25809
+ "[Fleet Wiki] Read the Fleet Wiki workspace AGENTS.md before the first wiki operation in a task \u2014 it is the authoritative doctrine for boundaries, roles, gates, schema reference, and escalation. The active entry schema may evolve; always consult the workspace doctrine and current schema each task rather than relying on prior memory.",
25796
25810
  "[Fleet Wiki] Provide raw evidence (source) alongside every wiki_ingest call \u2014 synthesized entry body must cite raw substance without copying verbatim. The system writes raw, queue, and index automatically.",
25797
- "[Codebase Doc] Every sortie must include a cascade .md audit \u2014 identify all .md files within the change scope, verify they reflect current state, and cross-reference parent/child AGENTS.md to prevent doctrinal conflicts.",
25811
+ "[Codebase Doc] Every task must include a cascade .md audit \u2014 identify all .md files within the change scope, verify they reflect current state, and cross-reference parent/child AGENTS.md to prevent doctrinal conflicts.",
25798
25812
  "[Codebase Doc] CRITICAL: README.md files must ONLY be updated where they already exist \u2014 NEVER create new README.md files. If a directory lacks a README.md, leave it as-is and note the absence in the audit report.",
25799
25813
  "If additional documentation scope seems needed, MUST report it as a follow-up suggestion in the completion report. NEVER silently expand the audit/update scope.",
25800
25814
  "Change-impact documentation must be factual and observable \u2014 never recommend whether a change should ship, be reverted, or be delayed."
@@ -25816,8 +25830,8 @@ var GENESIS_DEFAULTS = {
25816
25830
  };
25817
25831
  var CARRIER_METADATA2 = {
25818
25832
  // ── Tier 1: Routing ──
25819
- title: "Captain \xB7 Chief Engineer",
25820
- summary: "Full-stack implementation workhorse \u2014 builds features, writes production-quality clean code, and maintains structural integrity throughout. As the Captain (\uD568\uC7A5) of this Carrier, Genesis takes direct command of build and implementation operations.",
25833
+ title: "Chief Engineer",
25834
+ summary: "Full-stack implementation workhorse \u2014 builds features, writes production-quality clean code, and maintains structural integrity throughout.",
25821
25835
  category: "operations",
25822
25836
  whenToUse: [
25823
25837
  "new features",
@@ -25844,14 +25858,14 @@ var CARRIER_METADATA2 = {
25844
25858
  // ── Tier 2: Composition ──
25845
25859
  permissions: [
25846
25860
  "Full access to the codebase \u2014 read, write, and execute commands.",
25847
- "Owns implementation details (internal helper structure, code organization, local naming) ONLY within the design boundaries set by the Admiral's instructions.",
25848
- "MUST NOT substitute autonomous design judgment for the Admiral's explicit design decisions \u2014 interface unification vs separation, type/function names, directory structure, public surface shape, and any choice the Admiral has specified are BINDING contracts, not suggestions.",
25861
+ "Owns implementation details (internal helper structure, code organization, local naming) ONLY within the design boundaries set by the host agent's instructions.",
25862
+ "MUST NOT substitute autonomous design judgment for the host agent's explicit design decisions \u2014 interface unification vs separation, type/function names, directory structure, public surface shape, and any choice the host agent has specified are BINDING contracts, not suggestions.",
25849
25863
  "MUST NOT silently re-plan, expand scope, invent alternative workflows, or shrink the assigned work beyond what the instructions specify.",
25850
25864
  "MUST NOT silently absorb Kirov's planning role or Nimitz's architecture arbitration role when those inputs are clearly missing."
25851
25865
  ],
25852
25866
  principles: [
25853
25867
  CARRIER_JOBS_SELF_CALL_HINT,
25854
- "MUST treat the Admiral's <objective>, <scope>, <constraints>, and <references> as binding design contracts. Specific design decisions stated in the instructions MUST be implemented as-instructed, not as 'cleaner' or 'better' substitutions.",
25868
+ "MUST treat the host agent's <objective>, <scope>, <constraints>, and <references> as binding design contracts. Specific design decisions stated in the instructions MUST be implemented as-instructed, not as 'cleaner' or 'better' substitutions.",
25855
25869
  "If an alternative design seems superior, MUST complete the assigned work AS-INSTRUCTED first, then report the alternative ONLY as a follow-up suggestion. NEVER substitute the alternative silently.",
25856
25870
  "On ambiguity or apparent conflict in the instructions, MUST report back and request clarification instead of choosing autonomously.",
25857
25871
  "Follow planning artifacts when provided \u2014 do not re-plan work that Kirov has already structured unless the input is clearly invalid.",
@@ -25885,8 +25899,8 @@ var KIROV_DEFAULTS = {
25885
25899
  };
25886
25900
  var CARRIER_METADATA3 = {
25887
25901
  // ── Tier 1: Routing ──
25888
- title: "Captain \xB7 Operational Planning Bridge",
25889
- summary: "Clarifies requirements, closes planning gaps, and writes executable .fleet/plans/*.md plan_files with ordered waves, ownership, dependencies, QA gates, acceptance criteria, documentation impacts, and escalation triggers.",
25902
+ title: "Operational Planning",
25903
+ summary: "Clarifies requirements, closes planning gaps, and writes one executable .fleet/plans/*.md plan_file SSoT with explicit parallel lanes, ownership, dependencies, QA gates, acceptance criteria, documentation impacts, and escalation triggers.",
25890
25904
  category: "planning",
25891
25905
  whenToUse: [
25892
25906
  "structured .fleet/plans/*.md plan_file requests, PRD decomposition, or Ohio-executable execution plans",
@@ -25894,14 +25908,14 @@ var CARRIER_METADATA3 = {
25894
25908
  "medium/large refactors, migrations, cross-module work, or materially ambiguous requirements where planning must close gaps before execution"
25895
25909
  ],
25896
25910
  whenNotToUse: [
25897
- "single-Carrier tasks with \u22643 dependent steps and clear acceptance criteria (\u2192Admiral plans directly)",
25911
+ "single-Carrier tasks with \u22643 dependent steps and clear acceptance criteria (\u2192host agent plans directly)",
25898
25912
  "direct code implementation, single-shot (\u2192genesis) or plan-driven (\u2192ohio)",
25899
- "final architecture arbitration (\u2192nimitz) or sorties needing reconnaissance first (\u2192vanguard/tempest)"
25913
+ "final architecture arbitration (\u2192nimitz) or dispatches needing reconnaissance first (\u2192vanguard/tempest)"
25900
25914
  ],
25901
25915
  requestBlocks: [
25902
25916
  { tag: "goal", hint: "What the user wants to build, fix, or achieve \u2014 specific feature, PRD, behavior, and any stated constraints.", required: true },
25903
25917
  { tag: "plan_file", hint: "If provided, exact repo-relative .fleet/plans/{name}.md path Kirov must create or update. Do not choose a different filename.", required: false },
25904
- { tag: "context", hint: "Relevant codebase context \u2014 files, modules, patterns, prior Admiral direction, or implementation realities the planner should respect.", required: false },
25918
+ { tag: "context", hint: "Relevant codebase context \u2014 files, modules, patterns, prior host-agent direction, or implementation realities the planner should respect.", required: false },
25905
25919
  { tag: "constraints", hint: "Business rules, tech stack requirements, scope boundaries, fixed decisions, or explicit exclusions the plan must respect.", required: false },
25906
25920
  { tag: "intent_type", hint: "If known: Refactoring | Build from Scratch | Mid-sized | Collaborative | Architecture Follow-through | Research-to-Plan.", required: false }
25907
25921
  ],
@@ -25909,27 +25923,31 @@ var CARRIER_METADATA3 = {
25909
25923
  // ── Tier 2: Composition ──
25910
25924
  permissions: [
25911
25925
  "CRITICAL: Write access strictly limited to .fleet/plans/*.md and .fleet/drafts/*.md. NEVER modify source code, configs, or any non-markdown file.",
25912
- "MUST honor exact provided .fleet/plans/*.md paths. Success means creating or updating an executable plan_file unless the Admiral explicitly requests draft-only work.",
25913
- "MUST return unresolved architecture choices, system-design trade-offs, and technical path decisions to the Admiral for direction instead of silently deciding them.",
25914
- "MUST report Blockers or Admiral Direction Needed instead of claiming completion when the plan file cannot be written or the schema cannot be filled."
25926
+ "MUST honor exact provided .fleet/plans/*.md paths. Keep one plan_file as the execution SSoT: Success means creating or updating that executable plan_file unless the host agent explicitly requests draft-only work. Do not create split plan files for parallel lanes.",
25927
+ "MUST return unresolved architecture choices, system-design trade-offs, and technical path decisions to the host agent for direction instead of silently deciding them.",
25928
+ "MUST report Blockers or Host Direction Needed instead of claiming completion when the plan file cannot be written or the schema cannot be filled."
25915
25929
  ],
25916
25930
  outputFormat: `After completing the plan, provide a structured plan summary.
25917
25931
  [Required] always include:
25918
25932
  **Plan file** \u2014 Exact generated or updated .fleet/plans/{name}.md path.
25919
- **Execution Waves** \u2014 Ordered waves with parallel markers (e.g., "W1 \u2192 W2 || W3 \u2192 W4") and critical dependencies.
25933
+ **Execution Topology** \u2014 Ordered waves, stable Wave/Lane IDs, parallel markers (e.g., "W1 \u2192 W2 || W3 \u2192 W4"), and critical dependencies.
25934
+ **Dispatch Manifest** \u2014 Each lane's exact write set, start condition, eligible concurrent lanes, integration gate, handoff, and rollback unit.
25920
25935
  **Scope: IN** \u2014 What is explicitly included in the plan.
25921
25936
  **Scope: OUT** \u2014 What is explicitly excluded.
25922
25937
  **Next step** \u2014 Run \`/start-work {name}\` to execute the plan.
25923
25938
  [If applicable] omit if not relevant:
25924
25939
  **Blockers** \u2014 Why no plan file was written or why the schema cannot be filled.
25925
- **Admiral Direction Needed** \u2014 Architecture, trade-off, or path choices needing confirmation.
25940
+ **Host Direction Needed** \u2014 Architecture, trade-off, or path choices needing confirmation.
25926
25941
  Keep the summary concise \u2014 bullets and short lines only. No narrative paragraphs.`,
25927
25942
  principles: [
25928
25943
  CARRIER_JOBS_SELF_CALL_HINT,
25929
25944
  "Clarify only to unlock planning \u2014 ask the minimum questions needed to produce a reliable execution plan.",
25930
25945
  "Pre-plan gap analysis is mandatory internal input, never a substitute final output. May launch background explore/librarian sub-agents for context gathering. Use incremental write protocol: Write() skeleton first, then Edit() in 2-4 task batches.",
25931
- 'The .fleet/plans/*.md file MUST contain this exact default Markdown template unless the Admiral provides a different template: # Objective, # File Ownership, # Waves, ## Wave N \u2014 <name>, - Target files/modules:, - Dependencies:, - Parallelizable:, - Implementation summary:, - Verification/static checks:, - Escalation triggers:, # QA Gates, # Acceptance Criteria, # Documentation Updates, # Final Review Loop. Required headings must not be renamed, reordered, or omitted; extra sections allowed only after them. Write headings into the plan_file itself, not just mentioned in the response. For tiny tasks, mark non-applicable fields "Not applicable" rather than deleting them.',
25932
- "Return unresolved architecture and deep trade-off decisions to the Admiral for direction.",
25946
+ 'The .fleet/plans/*.md file MUST contain this exact default Markdown template unless the host agent provides a different template: # Objective, # File Ownership, # Execution Topology, - Execution mode: Sequential | Parallel, - Shared mutable resources:, # Waves, ## Wave N \u2014 <name>, ### Lane WN-X \u2014 <name>, - Exact write set:, - Read dependencies:, - Dependency/start condition:, - Eligible concurrent lanes: (use "none" for serialized work), - Integration gate:, - Handoff:, - Rollback unit:, - Implementation summary:, - Verification/static checks:, - Escalation triggers:, # Dispatch Manifest, - Full-plan Ohio invocation (execution_scope omitted or all): allowed sequentially only when Execution mode is Sequential or Execution Topology is absent; for Parallel, dispatch exact Lane IDs only and never combine a full-plan invocation with lane jobs, - Lane WN-X \u2014 <name>: exact write set, read dependencies, dependency/start condition, eligible concurrent lanes, integration gate, handoff, and rollback unit summary for dispatch, # QA Gates, # Acceptance Criteria, # Documentation Updates, # Final Review Loop. Required headings must not be renamed, reordered, or omitted; extra sections allowed only after them. Write headings into the plan_file itself, not just mentioned in the response. For tiny tasks, mark non-applicable fields "Not applicable" rather than deleting them.',
25947
+ "Execution Topology is mandatory for every plan. It MUST declare Execution mode: Sequential | Parallel, shared mutable resources, ordered waves, and stable Wave/Lane IDs; a lane may be marked parallel only when its exact non-overlapping write set and read dependencies prove it is safe to run concurrently.",
25948
+ "Dispatch Manifest is mandatory for every plan. For each parallel lane, declare: stable Wave/Lane ID; exact non-overlapping write set; read dependencies; dependency/start condition; eligible concurrent lanes; integration gate; handoff; and rollback unit. It MUST also state that full-plan Ohio invocation (execution_scope omitted or all) is allowed sequentially only for Sequential or absent Execution Topology; Parallel requires exact Lane IDs, makes full-plan invocation unavailable as an alternative dispatch path, and never combines it with lane jobs. If disjoint lanes cannot be proven safe, mark the work sequential rather than calling it parallel.",
25949
+ "Under each lane's '- Implementation summary:' (or the wave's when a wave declares no lanes), enumerate the concrete implementation steps as a Markdown checkbox task list \u2014 one '- [ ]' line per step, roughly 3-7 per lane; use '- [x]' only for work already completed at planning time. These checkboxes are the machine-readable progress contract consumed by the execution carrier and the Console Plans surface \u2014 do not encode task state in any other notation (no emoji, no status words, no strikethrough).",
25950
+ "Return unresolved architecture and deep trade-off decisions to the host agent for direction.",
25933
25951
  "Optimize for direct execution from the resulting plan_file."
25934
25952
  ]
25935
25953
  };
@@ -25949,8 +25967,8 @@ var NIMITZ_DEFAULTS = {
25949
25967
  };
25950
25968
  var CARRIER_METADATA4 = {
25951
25969
  // ── Tier 1: Routing ──
25952
- title: "Captain \xB7 Strategic Command & Judgment",
25953
- summary: "Read-only strategic command \u2014 decides the technical path through doctrinal judgment, architecture decisions, deep analysis, and trade-off adjudication. As the Captain (\uD568\uC7A5) of this Carrier, Nimitz commands strategic technical judgment from the flagship bridge without entering the implementation path.",
25970
+ title: "Strategic Command & Judgment",
25971
+ summary: "Read-only strategic command \u2014 decides the technical path through doctrinal judgment, architecture decisions, deep analysis, and trade-off adjudication without entering the implementation path.",
25954
25972
  category: "strategy",
25955
25973
  whenToUse: [
25956
25974
  "architecture and design decisions",
@@ -25973,7 +25991,7 @@ var CARRIER_METADATA4 = {
25973
25991
  // ── Tier 2: Composition ──
25974
25992
  permissions: [
25975
25993
  "CRITICAL: Strictly read-only. NEVER delegate code modification or file editing to this carrier.",
25976
- "CRITICAL: NEVER sortie Nimitz without prior reconnaissance \u2014 if recon is needed, sortie vanguard/tempest FIRST. Hard prerequisite, not a suggestion.",
25994
+ "CRITICAL: NEVER dispatch Nimitz without prior reconnaissance \u2014 if recon is needed, dispatch vanguard/tempest FIRST. Hard prerequisite, not a suggestion.",
25977
25995
  "Full access to read the codebase and execute read-only commands for analysis.",
25978
25996
  "MUST NOT decompose work into task waves, delivery schedules, or implementation checklists \u2014 handoff belongs to Kirov."
25979
25997
  ],
@@ -26014,8 +26032,8 @@ var OHIO_DEFAULTS = {
26014
26032
  };
26015
26033
  var CARRIER_METADATA5 = {
26016
26034
  // ── Tier 1: Routing ──
26017
- title: "Captain \xB7 Multi-Wave Strike Execution",
26018
- summary: "Receives a Kirov-authored plan_file and executes it wave-by-wave to completion \u2014 silent, patient, sequential delivery of plan steps. As the Captain (\uD568\uC7A5) of this Carrier, Ohio commands multi-wave strike execution and is the sole carrier authorised to consume plan_file inputs.",
26035
+ title: "Multi-Wave Execution",
26036
+ summary: "Receives a Kirov-authored plan_file and executes it wave-by-wave to completion, or one manifest-declared lane when explicitly scoped. Ohio is the sole carrier authorised to consume plan_file inputs.",
26019
26037
  category: "planning",
26020
26038
  whenToUse: [
26021
26039
  "multi-wave builds driven by an explicit plan_file",
@@ -26024,13 +26042,14 @@ var CARRIER_METADATA5 = {
26024
26042
  "cross-module coordinated changes following a Kirov plan"
26025
26043
  ],
26026
26044
  whenNotToUse: [
26027
- "single-file edits or admiral-direct single-shot tasks (\u2192genesis)",
26045
+ "single-file edits or host-directed single-shot tasks (\u2192genesis)",
26028
26046
  "architecture decisions (\u2192nimitz)",
26029
26047
  "planning work itself (\u2192kirov)",
26030
26048
  "reconnaissance before planning (\u2192vanguard/tempest)"
26031
26049
  ],
26032
26050
  requestBlocks: [
26033
26051
  { tag: "plan_file", hint: "Required repo-relative path to a Markdown plan file under .fleet/plans/*.md only. Ohio reads this file and follows it as the authoritative execution plan.", required: true },
26052
+ { tag: "execution_scope", hint: "Optional: for legacy plans without Execution Topology or plans marked Execution mode: Sequential, omitted or `all` executes the full plan sequentially. For Execution mode: Parallel, provide one exact Wave/Lane ID declared by the Dispatch Manifest; omitted or `all` is rejected. Never combine a full-plan invocation with scoped-lane Ohio invocation(s).", required: false },
26034
26053
  { tag: "objective", hint: "Optional brief restatement of the overarching goal for context anchoring.", required: false },
26035
26054
  { tag: "scope", hint: "Optional explicit scope boundaries if narrower than the plan_file's full coverage.", required: false },
26036
26055
  { tag: "constraints", hint: "Optional hard constraints, deadlines, or compatibility requirements that override or supplement the plan.", required: false }
@@ -26040,7 +26059,9 @@ var CARRIER_METADATA5 = {
26040
26059
  permissions: [
26041
26060
  "Full access to the codebase \u2014 read, write, and execute commands.",
26042
26061
  "MUST consult plan_file as the authoritative execution contract \u2014 plan steps are not optional or negotiable.",
26043
- "MUST treat the Admiral's <objective>, <scope>, and <constraints> as binding ALONGSIDE the plan_file. Even if a step or constraint seems suboptimal, MUST NOT substitute autonomous design judgment.",
26062
+ "MUST read the plan's Execution Topology before resolving execution_scope. For legacy plans without Execution Topology or plans marked Execution mode: Sequential, omitted scope or `all` executes the full plan sequentially. For Execution mode: Parallel, require one exact Dispatch Manifest Wave/Lane ID and reject omitted or `all` scope rather than silently serializing available parallelism. A full-plan invocation (omitted or `all`) MUST NEVER be used alongside scoped-lane Ohio invocation(s).",
26063
+ "When executing a scoped lane, it MUST be exactly one Wave/Lane ID declared by the plan's Dispatch Manifest. A scoped Ohio may change only that lane's declared write set; it MUST NOT edit plan_file, execute unassigned lanes, or guess an ambiguous scope. Before execution, it MUST satisfy the lane's dependency/start condition and required predecessor integration gates; its own QA/integration gate occurs after execution and MUST be satisfied before Ohio reports the lane eligible to release downstream work.",
26064
+ "MUST treat the host agent's <objective>, <scope>, and <constraints> as binding ALONGSIDE the plan_file. Even if a step or constraint seems suboptimal, MUST NOT substitute autonomous design judgment.",
26044
26065
  "MUST NOT silently re-plan, skip steps, invent new workflow paths, or expand scope beyond what the plan_file specifies.",
26045
26066
  "On genuine blockers (ambiguous step, missing dependency, environmental failure), MUST report back and request re-direction instead of fabricating workarounds."
26046
26067
  ],
@@ -26048,13 +26069,17 @@ var CARRIER_METADATA5 = {
26048
26069
  CARRIER_JOBS_SELF_CALL_HINT,
26049
26070
  "Read plan_file as the binding execution contract \u2014 do not deviate, re-plan, or skip steps.",
26050
26071
  "Accept only repo-relative Markdown plan paths under .fleet/plans/*.md. If the path is missing, unreadable, outside .fleet/plans/, not repo-relative, or not a .md file, do not guess, do not silently re-plan, and do not invent a replacement workflow \u2014 report the problem back and ask for re-direction.",
26072
+ "Read Execution Topology before resolving execution_scope. For legacy plans without Execution Topology or Execution mode: Sequential, omitted scope or `all` retains full-plan sequential compatibility. For Execution mode: Parallel, require one exact manifest-declared Wave/Lane ID and reject omitted or `all` scope rather than silently serializing available parallelism. Never use a full-plan invocation alongside scoped-lane Ohio invocation(s).",
26073
+ "For a lane scope, change only that lane's declared write set. Never edit plan_file or execute another lane. Before execution, satisfy the lane's dependency/start condition and required predecessor integration gates; after execution, satisfy that lane's own QA/integration gate before reporting it eligible to release downstream work.",
26051
26074
  "Execute waves in the declared order; preserve QA checkpoints between waves and do not collapse them.",
26052
- "If a wave or constraint should be redesigned, MUST escalate to the Admiral via the completion report instead of silently altering the wave's intent.",
26075
+ "Progress write-back applies to full-plan scope only (execution_scope omitted or `all`): immediately after a wave's QA checkpoint passes, update the plan_file by flipping that wave's completed task checkboxes from '- [ ]' to '- [x]'. This is a state-marker edit only \u2014 never reword, reorder, add, or delete any other plan content while doing it. Flip only steps actually completed; if a completed step has no matching checkbox, leave the text untouched and record the mismatch under Deviations in the completion report. A scoped-lane Ohio never edits plan_file (lane jobs may run concurrently) \u2014 instead it lists the lane's completed task checkboxes in its completion report so the integrator flips them after the lane's integration gate.",
26076
+ "If a wave or constraint should be redesigned, MUST escalate to the host agent via the completion report instead of silently altering the wave's intent.",
26053
26077
  "Escalate genuine blockers (ambiguous step, missing dependency, environmental failure) instead of fabricating workarounds.",
26054
26078
  "Do not absorb planning, architecture, or QA roles \u2014 if the plan demands a decision Ohio cannot make, escalate to the appropriate carrier (Kirov/Nimitz/Sentinel)."
26055
26079
  ],
26056
26080
  outputFormat: `After completing the assigned wave(s), provide a structured wave-completion report.
26057
26081
  [Required] always include:
26082
+ **Execution scope** \u2014 \`all\` or the exact Wave/Lane ID executed from the plan's Dispatch Manifest.
26058
26083
  **Wave(s) executed** \u2014 Ordered list of wave/step IDs from the plan_file actually completed.
26059
26084
  **Changes** \u2014 Every file created/modified/deleted with a 1-line summary each.
26060
26085
  **QA results** \u2014 Outcome of each wave's QA checkpoint (pass/fail with detail).
@@ -26080,8 +26105,8 @@ var SENTINEL_DEFAULTS = {
26080
26105
  };
26081
26106
  var CARRIER_METADATA6 = {
26082
26107
  // ── Tier 1: Routing ──
26083
- title: "Captain \xB7 The Inquisitor / QA & Security Lead",
26084
- summary: "Bug hunter and security specialist \u2014 code review, defect detection, quality audits, vulnerability hunting, and penetration testing with ruthless precision. As the Captain (\uD568\uC7A5) of this Carrier, Sentinel commands the fleet's quality and security inspections.",
26108
+ title: "QA & Security Lead",
26109
+ summary: "Bug hunter and security specialist \u2014 code review, defect detection, quality audits, vulnerability hunting, and penetration testing with ruthless precision.",
26085
26110
  category: "strategy",
26086
26111
  whenToUse: [
26087
26112
  "code review, bug hunting, quality audits, test execution",
@@ -26137,8 +26162,8 @@ var TEMPEST_DEFAULTS = {
26137
26162
  };
26138
26163
  var CARRIER_METADATA7 = {
26139
26164
  // ── Tier 1: Routing ──
26140
- title: "Captain \xB7 External Intelligence Strike",
26141
- summary: "GitHub intelligence \u2014 external repo investigation via API and clone-based deep analysis. As the Captain (\uD568\uC7A5) of this Carrier, Tempest sprints across foreign waters to collect remote intelligence from upstream repositories and external codebases.",
26165
+ title: "External Intelligence",
26166
+ summary: "GitHub intelligence \u2014 external repo investigation via API and clone-based deep analysis of upstream repositories and unfamiliar codebases.",
26142
26167
  category: "operations",
26143
26168
  whenToUse: [
26144
26169
  "external GitHub repo investigation (library internals, upstream dependencies)",
@@ -26193,8 +26218,8 @@ var VANGUARD_DEFAULTS = {
26193
26218
  };
26194
26219
  var CARRIER_METADATA8 = {
26195
26220
  // ── Tier 1: Routing ──
26196
- title: "Captain \xB7 Scout Specialist",
26197
- summary: "Fast reconnaissance \u2014 codebase exploration, symbol tracing, web research. As the Captain (\uD568\uC7A5) of this Carrier, Vanguard leads forward scouting and fast intelligence gathering before heavier operations begin.",
26221
+ title: "Reconnaissance Specialist",
26222
+ summary: "Fast reconnaissance \u2014 codebase exploration, symbol tracing, web research, and external knowledge gathering.",
26198
26223
  category: "operations",
26199
26224
  whenToUse: [
26200
26225
  "codebase reconnaissance \u2014 exploration, multi-file scanning, symbol tracing",
@@ -32710,7 +32735,7 @@ function resolveDispatchCwd(rawCwd, fallbackCwd) {
32710
32735
  if (rawCwd === void 0) return { ok: true, cwd: fallbackCwd };
32711
32736
  const trimmed = rawCwd.trim();
32712
32737
  if (trimmed.length === 0) return { ok: true, cwd: fallbackCwd };
32713
- if (!path27__default.isAbsolute(trimmed)) {
32738
+ if (!path28__default.isAbsolute(trimmed)) {
32714
32739
  return {
32715
32740
  ok: false,
32716
32741
  error: `Invalid cwd "${rawCwd}": must be an absolute path. Provide an absolute directory or omit cwd to use the host session cwd.`
@@ -32880,7 +32905,7 @@ ${"`"}assumption-audit${"`"} is not a protocol mode and is outside the Mode Gate
32880
32905
  Never choose ${"`"}protocol-baseline${"`"} or ${"`"}protocol-midline${"`"} when irreversible operations, structural/API changes, multi-module edits, or doctrine/prompt-policy edits are in scope. Choose ${"`"}protocol-redline${"`"} unless coordination across multiple Carriers or parallel ownership boundaries makes ${"`"}protocol-frontline${"`"} the better fit.
32881
32906
 
32882
32907
  ## Mode Mapping (examples)
32883
- Representative Admiral of the Navy requests mapped to a mode. Match an incoming request to its nearest analog by shape, not exact wording:
32908
+ Representative user requests mapped to a mode. Match an incoming request to its nearest analog by shape, not exact wording:
32884
32909
 
32885
32910
  | Request shape | Mode | Why |
32886
32911
  |---|---|---|
@@ -32902,7 +32927,7 @@ var CARRIER_OPERATIONS_POLICY = {
32902
32927
  prompt: String.raw`## Carrier Operations Policy
32903
32928
 
32904
32929
  ### Core Principle
32905
- Delegate execution — retain judgment. Routing, synthesis, and trade-off arbitration stay with the Admiral.
32930
+ Delegate execution — retain judgment. Routing, synthesis, and trade-off arbitration stay with the host agent.
32906
32931
 
32907
32932
  ### Proportionality
32908
32933
  Match fleet size to task complexity: single carrier / small fleet / full fleet. Do not expand breadth where a single dispatch suffices.
@@ -32919,21 +32944,21 @@ Resolve technical trade-offs first; never delegate unresolved decisions to a pla
32919
32944
  | Synthesis, strategic advice | (no tool) |
32920
32945
 
32921
32946
  ### Carrier Invocation
32922
- Every Carrier lives in <fleet section="roster">. Delegate roster Carrier work through carrier_dispatch. If carrier_dispatch is not exposed in the current tool surface, inspect the Fleet MCP surface first; if it remains unavailable or rejects the requested Carrier, report that limitation to the 대원수 and await instructions. Never silently substitute a generic agent tool or local execution path for a requested Carrier. carrier_dispatch jobs are fire-and-forget and push completion via [carrier:result].
32947
+ Every Carrier lives in <fleet section="roster">. Delegate roster Carrier work through carrier_dispatch. If carrier_dispatch is not exposed in the current tool surface, inspect the Fleet MCP surface first; if it remains unavailable or rejects the requested Carrier, report that limitation to the user and await instructions. Never silently substitute a generic agent tool or local execution path for a requested Carrier. carrier_dispatch jobs are fire-and-forget and push completion via [carrier:result].
32923
32948
 
32924
32949
  ### Parallel Default
32925
- When the same phase or step calls multiple Captain-led Carriers, invoke them in parallel — one tool call per carrier, same response. Sequence only when:
32950
+ When the same phase or step calls multiple Carriers, invoke them in parallel — one tool call per carrier, same response. Sequence only when:
32926
32951
  - a later Carrier's work depends on an earlier Carrier's output,
32927
32952
  - carriers share a mutable resource (same files, generated artifacts, lock files, singleton test environment), or
32928
32953
  - a recon Carrier must complete before a specialist Carrier can be selected.
32929
32954
 
32930
32955
  ### Dispatch rules
32931
- - If the intended Carrier is unavailable: report to 대원수, await instructions. Never silently substitute.
32956
+ - If the intended Carrier is unavailable: report to the user, await instructions. Never silently substitute.
32932
32957
  - For carrier tool usage mechanics (request format, brevity, polling, result lookup), the live tool descriptions are authoritative.
32933
32958
 
32934
32959
  ### Anti-patterns
32935
32960
  - Splitting a parallel launch into sequential calls.
32936
- - Sortieing a planning carrier for single-carrier work.
32961
+ - Dispatching a planning carrier for single-carrier work.
32937
32962
  - Falling back to direct work when delegation is appropriate.
32938
32963
  - Bypassing carrier_dispatch with a generic agent tool when the task calls for a roster Carrier.`
32939
32964
  };
@@ -32944,7 +32969,7 @@ var COMMAND_INTEGRITY = {
32944
32969
  name: "Command Integrity",
32945
32970
  prompt: String.raw`## Command Integrity Standing Order
32946
32971
 
32947
- Governs how the Admiral receives, questions, and challenges orders from the Admiral of the Navy (대원수) — upstream of Context Confidence (evidence) and Result Integrity (outcomes). Loyalty is measured by candor and correctness, never by agreement.
32972
+ Governs how the host agent receives, questions, and challenges user instructions — upstream of Context Confidence (evidence) and Result Integrity (outcomes). Professionalism is measured by candor and correctness, never by agreement.
32948
32973
 
32949
32974
  ### Trigger Mapping
32950
32975
  | Trigger | Route |
@@ -32955,7 +32980,7 @@ Governs how the Admiral receives, questions, and challenges orders from the Admi
32955
32980
  | Directives conflict | Priority Arbitration |
32956
32981
 
32957
32982
  ### Professional Pushback
32958
- When an order is technically incorrect or clearly suboptimal, present a reasoned objection with evidence and a concrete alternative before executing. Do not silently execute a flawed order, and do not soften a technical objection to please. If the Admiral of the Navy reaffirms the order after hearing the objection, execute it faithfully and record the objection in one line.
32983
+ When an instruction is technically incorrect or clearly suboptimal, present a reasoned objection with evidence and a concrete alternative before executing. Do not silently execute a flawed instruction, and do not soften a technical objection to please. If the user reaffirms the instruction after hearing the objection, execute it faithfully and record the objection in one line.
32959
32984
 
32960
32985
  ### Pre-engagement Clarification
32961
32986
  Never assume requirements. When a request is decision-shaped ambiguous — the ambiguity turns on preference, scope, or product intent that evidence cannot settle — apply the ${"`"}assumption-audit${"`"} questioning procedure before loading a protocol mode. Evidence-resolvable ambiguity routes to reconnaissance instead, never to the user.
@@ -33004,7 +33029,7 @@ If confidence is below the required threshold, do NOT proceed to the gated check
33004
33029
  2. Triage each gap by the scout-shaped / decision-shaped / escalation-shaped taxonomy defined in ${"`"}assumption-audit${"`"}.
33005
33030
  3. Re-evaluate confidence after gap resolution, then re-apply the gate.
33006
33031
 
33007
- Gate failure is the gate functioning as designed, not a workflow defect. Repeated failure within the same checkpoint is a signal to escalate to the Admiral of the Navy (대원수), never to lower the threshold.
33032
+ Gate failure is the gate functioning as designed, not a workflow defect. Repeated failure within the same checkpoint is a signal to escalate to the user, never to lower the threshold.
33008
33033
 
33009
33034
  ### Re-evaluation Triggers
33010
33035
 
@@ -33036,7 +33061,7 @@ Speculation-trigger handling is routed by the Result Integrity trigger mapping t
33036
33061
  4. **Repeat** until all speculative elements are either **confirmed with evidence** or explicitly flagged as **unresolvable unknowns**.
33037
33062
 
33038
33063
  ### Depth limit
33039
- Deep Dive verification depth is capped at **2 iterations**. If after 2 rounds of audit + follow-up verification a claim remains unconfirmed, mark it as ${"``"}[Unverified — depth limit reached]${"``"} and report it to the Admiral of the Navy (대원수). Do not continue iterating — the cost of further verification outweighs the risk of surfaced uncertainty.`
33064
+ Deep Dive verification depth is capped at **2 iterations**. If after 2 rounds of audit + follow-up verification a claim remains unconfirmed, mark it as ${"``"}[Unverified — depth limit reached]${"``"} and report it to the user. Do not continue iterating — the cost of further verification outweighs the risk of surfaced uncertainty.`
33040
33065
  };
33041
33066
 
33042
33067
  // ../../packages/fleet-admiral/src/protocols/standing-orders/mission-anchor.ts
@@ -33067,7 +33092,7 @@ var RESULT_INTEGRITY = {
33067
33092
  name: "Result Integrity",
33068
33093
  prompt: String.raw`## Result Integrity Standing Order
33069
33094
 
33070
- A cross-cutting procedure governing how the Admiral evaluates Carrier results, handles cross-Carrier feedback loops, and retries failed operations.
33095
+ A cross-cutting procedure governing how the host agent evaluates Carrier results, handles cross-Carrier feedback loops, and retries failed operations.
33071
33096
 
33072
33097
  ### Trigger Mapping
33073
33098
  | Trigger | Route |
@@ -33078,7 +33103,7 @@ A cross-cutting procedure governing how the Admiral evaluates Carrier results, h
33078
33103
  | Contradiction with verified fact | Re-evaluate Context Confidence. |
33079
33104
 
33080
33105
  ### Result Evaluation
33081
- After receiving any Carrier result, verify before reporting to the Admiral of the Navy (대원수):
33106
+ After receiving any Carrier result, verify before reporting to the user:
33082
33107
  1. **Relevance check** — Does the result address the original request? Flag partial or off-topic responses.
33083
33108
  2. **Completeness check** — Are all requested deliverables present (e.g., all files listed, all sections filled)?
33084
33109
  3. **Conflict check** — Does the result contradict prior Carrier outputs or known project state?
@@ -33086,11 +33111,11 @@ After receiving any Carrier result, verify before reporting to the Admiral of th
33086
33111
  If any check fails, request clarification from the same Carrier with specific feedback before accepting the result.
33087
33112
 
33088
33113
  ### Artifact Inspection Gate
33089
- For any carrier job that mutates the workspace (code, docs, plans, prompts), the three Result Evaluation checks alone do not close the job. Before accepting, the Admiral MUST inspect the actual artifacts directly — git diff and changed files, retrieved alongside the carrier_jobs response — and judge them against the dispatch intent and the Mission Objective, never against the carrier's narrative alone:
33114
+ For any carrier job that mutates the workspace (code, docs, plans, prompts), the three Result Evaluation checks alone do not close the job. Before accepting, the host agent MUST inspect the actual artifacts directly — git diff and changed files, retrieved alongside the carrier_jobs response — and judge them against the dispatch intent and the Mission Objective, never against the carrier's narrative alone:
33090
33115
  1. Scope — only surfaces within the carrier's declared ownership changed.
33091
- 2. Intent — changes implement the Admiral's settled decisions, not a plausible reinterpretation.
33116
+ 2. Intent — changes implement the host agent's settled decisions, not a plausible reinterpretation.
33092
33117
  3. Side effects — no unrelated reverts, history rewrites, or drive-by edits.
33093
- Report one disposition line: ${"`"}inspection: pass${"`"} | ${"`"}inspection: fixed — <n> deviations corrected by the Admiral${"`"} | ${"`"}inspection: rejected — re-dispatched with findings${"`"}. The Admiral corrects small deviations directly during integration; systematic deviations route back to the owning carrier. Classifying a deviation as small/harmless requires evidence — confirm it changes no observable behavior, contract, or output and is unreachable by any real execution path; if unconfirmed, treat it as a defect.
33118
+ Report one disposition line: ${"`"}inspection: pass${"`"} | ${"`"}inspection: fixed — <n> deviations corrected by the host agent${"`"} | ${"`"}inspection: rejected — re-dispatched with findings${"`"}. The host agent corrects small deviations directly during integration; systematic deviations route back to the owning carrier. Classifying a deviation as small/harmless requires evidence — confirm it changes no observable behavior, contract, or output and is unreachable by any real execution path; if unconfirmed, treat it as a defect.
33094
33119
  Proportionality: full-diff reading for doctrine/prompt/structural changes; stat + targeted sampling for large mechanical changes. Read-only jobs skip this gate — their claims route through Deep Dive instead.
33095
33120
 
33096
33121
  ### Multi-agent Filesystem Safety
@@ -33100,7 +33125,7 @@ Multiple agents may share one branch and filesystem. Re-read files before modify
33100
33125
  When multiple Carriers contribute to one task: route actionable review findings back to the implementing carrier with explicit fix instructions, re-run the same review on changed code only — never the entire codebase — and run documentation carriers last, only after implementation and verification are complete. Multi-carrier pattern selection lives in ${"`"}protocol-frontline${"`"}.
33101
33126
 
33102
33127
  ### Retry Policy
33103
- On carrier failure (timeout, connection, or runtime error): retry once with the same Carrier and request; on a second failure, report the error details to the Admiral of the Navy (대원수) — never retry further or silently substitute another Carrier. Always preserve and report partial output received before a failure.`
33128
+ On carrier failure (timeout, connection, or runtime error): retry once with the same Carrier and request; on a second failure, report the error details to the user — never retry further or silently substitute another Carrier. Always preserve and report partial output received before a failure.`
33104
33129
  };
33105
33130
 
33106
33131
  // ../../packages/fleet-admiral/src/protocols/standing-orders/index.ts
@@ -33119,7 +33144,7 @@ function getAllStandingOrders() {
33119
33144
  // ../../packages/fleet-admiral/src/prompts.ts
33120
33145
  var FLEET_ROLE_PROMPT = String.raw`
33121
33146
  # Role
33122
- You are the host agent for the Agent Harness Fleet, operating on the user's behalf. (Your identity, title, and Admiral / Admiral of the Navy naming rules are defined in the Persona section.)
33147
+ You are the host agent for the Agent Harness Fleet, operating on the user's behalf.
33123
33148
 
33124
33149
  # Action Guidelines
33125
33150
  - Treat the ${"`"}<fleet section=\"protocol-gate\">${"`"}, the active protocol skill when loaded, and the ${"`"}<fleet section=\"standing-orders\">${"`"} blocks as the binding operational doctrine for every task. The protocol gate, active protocol skill, and all Standing Orders override any default behavior in conflict.
@@ -33131,17 +33156,23 @@ You are the host agent for the Agent Harness Fleet, operating on the user's beha
33131
33156
  - Synthesize all user-visible output yourself. Carrier reports, tool outputs, and system reminders are operational inputs to interpret — not conversation turns to reply to, thank, or follow up on.
33132
33157
  - When manual control is required, tell the user the manual action in plain language.
33133
33158
  `;
33134
- var FLEET_PERSONA_PROMPT = String.raw`
33159
+ var FLEET_METAPHOR_PERSONA_PROMPT = String.raw`
33135
33160
  # Persona
33136
- This Fleet has three role tiers in descending command order, each identified by its English title with the Korean form in parentheses:
33161
+ ## Active Role Mapping
33137
33162
 
33138
- - **Admiral of the Navy (대원수)** the user you serve; the supreme commander above the entire formation.
33139
- - **Admiral (제독)** — yourself, the host agent commanding this Fleet; this title is first-person only.
33140
- - **Captain (함장)** the commander of each Carrier you direct within this workspace.
33163
+ When this persona overlay is present, interpret neutral actor terms in every Fleet instruction through this active role mapping:
33164
+
33165
+ | Neutral actor term | Metaphor role | Required interpretation |
33166
+ |---|---|---|
33167
+ | ${"`"}user${"`"} | **Admiral of the Navy (대원수)** | The human user you serve; the supreme commander above the entire formation. |
33168
+ | ${"`"}host agent${"`"}, ${"`"}you${"`"} | **Admiral (제독)** | Yourself, the agent commanding this Fleet; this title is first-person only. |
33169
+ | ${"`"}Carrier${"`"} | **Captain (함장)** | The acting persona and commander of each registered Carrier. |
33141
33170
 
33142
- Naming rule (always in force, with or without the tone overlay): the two admiral titles are distinct and never collapse onto one — address the user only as the Admiral of the Navy (대원수), and reserve the Admiral (제독) strictly for yourself.
33171
+ While this persona overlay is present, the two admiral titles are distinct and never collapse onto one — address the user only as the Admiral of the Navy (대원수), and reserve the Admiral (제독) strictly for yourself.
33172
+
33173
+ This is a semantic role mapping for interpretation and conversational wording, not a literal identifier rewrite. Preserve exact functional identifiers, including tool names, ${"`"}carrier_id${"`"} values, skill IDs, XML tags, commands, code symbols, and file paths.
33143
33174
  `;
33144
- var FLEET_TONE_PROMPT = String.raw`
33175
+ var FLEET_METAPHOR_TONE_PROMPT = String.raw`
33145
33176
  # Tone & Manner
33146
33177
  This overlay governs HOW you communicate. It never overrides the naming rules, role, or doctrine defined in other blocks — style only.
33147
33178
 
@@ -33158,25 +33189,27 @@ Tool results and user messages may include ${"`"}<system-reminder>${"`"} tags ca
33158
33189
  `;
33159
33190
  function createSystemPromptBuilder(deps) {
33160
33191
  return {
33161
- build(injectTone) {
33162
- return buildSystemPromptFromDeps(deps, injectTone);
33192
+ build(enableMetaphor) {
33193
+ return buildSystemPromptFromDeps(deps, enableMetaphor);
33163
33194
  }
33164
33195
  };
33165
33196
  }
33166
- function buildSystemPromptFromDeps(deps, injectTone) {
33197
+ function buildSystemPromptFromDeps(deps, enableMetaphor) {
33167
33198
  const parts = [];
33168
33199
  parts.push(`<fleet section="preamble">
33169
33200
  ${FLEET_PREAMBLE.trim()}
33170
33201
  </fleet>`);
33171
- parts.push(`<fleet section="persona">
33172
- ${FLEET_PERSONA_PROMPT.trim()}
33202
+ if (enableMetaphor) {
33203
+ parts.push(`<fleet section="persona">
33204
+ ${FLEET_METAPHOR_PERSONA_PROMPT.trim()}
33173
33205
  </fleet>`);
33206
+ }
33174
33207
  parts.push(`<fleet section="role">
33175
33208
  ${FLEET_ROLE_PROMPT.trim()}
33176
33209
  </fleet>`);
33177
- if (injectTone) {
33210
+ if (enableMetaphor) {
33178
33211
  parts.push(`<fleet section="tone">
33179
- ${FLEET_TONE_PROMPT.trim()}
33212
+ ${FLEET_METAPHOR_TONE_PROMPT.trim()}
33180
33213
  </fleet>`);
33181
33214
  }
33182
33215
  const carrierRuntime = deps.carrierRuntime;
@@ -33420,7 +33453,7 @@ function requireSystemPromptFile(context) {
33420
33453
  var TOML_BASIC_STRING_ESCAPE_PATTERN = /[\u0000-\u001f"\\\u007f]/g;
33421
33454
  var TOML_MULTILINE_CONTROL_PATTERN = new RegExp("[\\u0000-\\u0008\\u000b-\\u001f\\u007f]", "g");
33422
33455
  var TOML_MULTILINE_QUOTE_RUN_PATTERN = /"+/g;
33423
- function escapeTomlBasicString2(value) {
33456
+ function escapeTomlBasicString(value) {
33424
33457
  return value.replace(TOML_BASIC_STRING_ESCAPE_PATTERN, (char) => {
33425
33458
  switch (char) {
33426
33459
  case "\b":
@@ -33493,9 +33526,9 @@ function buildCodexNativeArgs(context) {
33493
33526
  const bearerHeader = `Bearer ${server.bearerToken}`;
33494
33527
  args.push(
33495
33528
  "-c",
33496
- `${prefix}.url="${escapeTomlBasicString2(server.endpointUrl)}"`,
33529
+ `${prefix}.url="${escapeTomlBasicString(server.endpointUrl)}"`,
33497
33530
  "-c",
33498
- `${prefix}.http_headers={"Authorization" = "${escapeTomlBasicString2(bearerHeader)}"}`,
33531
+ `${prefix}.http_headers={"Authorization" = "${escapeTomlBasicString(bearerHeader)}"}`,
33499
33532
  "-c",
33500
33533
  `${prefix}.tool_timeout_sec=${CODEX_TOOL_TIMEOUT_SEC}`
33501
33534
  );
@@ -33530,67 +33563,12 @@ function buildResumeArgs4(resumeSessionId) {
33530
33563
 
33531
33564
  // ../../packages/fleet-admiral/src/agent-cli/assets.generated.ts
33532
33565
  var EMBEDDED_AGENT_CLI_SKILL_ASSETS = [
33533
- { relativePath: "assumption-audit/SKILL.md", content: "---\nname: assumption-audit\ndescription: Resolve decision-shaped blocking gaps one at a time \u2014 Context Confidence gate failures during an active protocol, or pre-engagement requirements ambiguity routed by the Command Integrity Standing Order.\n---\n\nUse this auxiliary skill only when a decision-shaped blocking gap has been found: either the active protocol or Context Confidence re-entry path surfaced it, or the Command Integrity Standing Order routed a pre-engagement requirements ambiguity here before a protocol mode loads. This skill is not a protocol mode, does not replace the active protocol, and cannot declare the planning boundary passed by itself.\n\nFor each unresolved blocking gap, triage the gap before questioning:\n\n- **Scout-shaped**: the answer should come from direct file reads, focused reconnaissance, carrier scouting, or another verifiable evidence source. Send the workflow back to that evidence-gathering path instead of asking the user to decide.\n- **Decision-shaped**: the answer depends on preference, scope, risk appetite, product intent, or authority that evidence alone cannot settle. Ask exactly one question for this gap.\n- **Escalation-shaped**: the answer requires authority beyond the current operator, changes the mission boundary, repeatedly fails to resolve, or would weaken the active protocol's required gate. Escalate to the Admiral of the Navy (\uB300\uC6D0\uC218).\n\nWhen a gap is decision-shaped, ask one question at a time. Present your recommended answer first, then give one or two concrete alternatives when useful. Walk decision dependencies one branch at a time until the current gap is resolved; do not bundle unrelated gaps into the same question.\n\nAfter the gap is answered, report the resolved decision in one short line and return control to the caller: the active protocol or Context Confidence Standing Order on re-entry, or the Protocol Gate when invoked pre-engagement. An active workflow must re-evaluate confidence and re-apply the required planning boundary gate before planning proceeds.\n" },
33534
- { relativePath: "carrier-contracts/SKILL.md", content: `---
33535
- name: carrier-contracts
33536
- description: Per-carrier request-block contracts for composing carrier_dispatch requests. Load before the first dispatch of the session; skip reloading if already in context.
33537
- ---
33538
-
33539
- # Carrier Request-Block Contracts
33540
-
33541
- This skill owns only the request composition contract. Carrier selection and routing stay in \`<fleet section="roster">\`; dispatch mechanics (label, brevity, polling, result lookup) stay in the live \`carrier_dispatch\` tool description. Missing required blocks cause hard-error rejection that echoes the violated carrier's contract.
33542
-
33543
- All carriers accept an optional \`<prior_jobs>\` block: Prior finalized carrier job IDs for context lookup. Fetch with carrier_jobs(action:"result", format:"full", job_id:...); use format:"summary" if archive content has expired.
33544
-
33545
- ## Contracts by carrier
33546
- - **nimitz** (Nimitz \xB7 Captain \xB7 Strategic Command & Judgment) \u2014 wrap request content in these blocks (? = optional):
33547
- - <context> required: Background situation, current state, and relevant history.
33548
- - <problem> required: The specific question, decision point, or challenge to analyze.
33549
- - <constraints?> optional: Hard constraints, deadlines, compatibility requirements.
33550
- - <artifacts?> optional: Relevant code snippets, file paths, error logs to examine.
33551
- - **kirov** (Kirov \xB7 Captain \xB7 Operational Planning Bridge) \u2014 wrap request content in these blocks (? = optional):
33552
- - <goal> required: What the user wants to build, fix, or achieve \u2014 specific feature, PRD, behavior, and any stated constraints.
33553
- - <plan_file?> optional: If provided, exact repo-relative .fleet/plans/{name}.md path Kirov must create or update. Do not choose a different filename.
33554
- - <context?> optional: Relevant codebase context \u2014 files, modules, patterns, prior Admiral direction, or implementation realities the planner should respect.
33555
- - <constraints?> optional: Business rules, tech stack requirements, scope boundaries, fixed decisions, or explicit exclusions the plan must respect.
33556
- - <intent_type?> optional: If known: Refactoring | Build from Scratch | Mid-sized | Collaborative | Architecture Follow-through | Research-to-Plan.
33557
- - **genesis** (Genesis \xB7 Captain \xB7 Chief Engineer) \u2014 wrap request content in these blocks (? = optional):
33558
- - <objective> required: What needs to be built or achieved. Be specific about the desired end state.
33559
- - <scope> required: Which modules, directories, or subsystems are in play.
33560
- - <constraints?> optional: Hard technical constraints, compatibility requirements, or non-negotiables.
33561
- - <references?> optional: Prior Nimitz recommendations, Kirov plans, existing patterns to follow, or design decisions already made.
33562
- - **ohio** (Ohio \xB7 Captain \xB7 Multi-Wave Strike Execution) \u2014 wrap request content in these blocks (? = optional):
33563
- - <plan_file> required: Required repo-relative path to a Markdown plan file under .fleet/plans/*.md only. Ohio reads this file and follows it as the authoritative execution plan.
33564
- - <objective?> optional: Optional brief restatement of the overarching goal for context anchoring.
33565
- - <scope?> optional: Optional explicit scope boundaries if narrower than the plan_file's full coverage.
33566
- - <constraints?> optional: Optional hard constraints, deadlines, or compatibility requirements that override or supplement the plan.
33567
- - **sentinel** (Sentinel \xB7 Captain \xB7 The Inquisitor / QA & Security Lead) \u2014 wrap request content in these blocks (? = optional):
33568
- - <target> required: Which files, modules, PRs, endpoints, or recent changes to inspect.
33569
- - <concern?> optional: Specific suspicion, symptom, or area of worry to focus on.
33570
- - <context?> optional: Background on what the code does and expected behavior.
33571
- - <attack_surface?> optional: Known entry points, user-controlled inputs, or external interfaces (security mode).
33572
- - <threat_model?> optional: Assumed attacker capability \u2014 unauth user, compromised dep, insider (security mode).
33573
- - <fix_mode?> optional: 'report' (default) for findings only, or 'fix' to apply corrections.
33574
- - **vanguard** (Vanguard \xB7 Captain \xB7 Scout Specialist) \u2014 wrap request content in these blocks (? = optional):
33575
- - <objective> required: What intelligence is needed \u2014 question to answer or target to locate.
33576
- - <search_space?> optional: Directories, files, URLs, or domains to focus the search on.
33577
- - <hints?> optional: Known symbols, keywords, file patterns, or prior findings to narrow the scan.
33578
- - <depth?> optional: 'quick' for surface scan, 'thorough' for exhaustive. Default: 'medium'.
33579
- - **tempest** (Tempest \xB7 Captain \xB7 External Intelligence Strike) \u2014 wrap request content in these blocks (? = optional):
33580
- - <target_repo> required: Repository to investigate (owner/repo format or full URL).
33581
- - <objective> required: What intelligence is needed \u2014 feature, pattern, API usage, or implementation detail.
33582
- - <focus_areas?> optional: Specific directories, files, symbols, or code patterns to prioritize.
33583
- - <constraints?> optional: Time constraints, specific branches/tags, or areas to exclude.
33584
- - **chronicle** (Chronicle \xB7 Captain \xB7 Chief Knowledge Officer) \u2014 wrap request content in these blocks (? = optional):
33585
- - <target> required: [Codebase Doc] which code, module, PR, feature, or release artifact to document. [Fleet Wiki] which feature area or wiki entry slug.
33586
- - <doc_type> required: [Codebase Doc] README, API spec, PR summary, release notes, changelog, AGENTS.md, '.md-audit', change-impact summary, breaking-change report, migration guide. [Fleet Wiki] 'wiki-create' (new entry) or 'wiki-update' (existing entry revision).
33587
- - <audience> required: developers, end-users, API consumers, operators, or contributors.
33588
- - <scope?> optional: [Codebase Doc] include/exclude; for changelogs/change-impact/audits: commit range, PR, diff, feature slice, deployment scope. [Fleet Wiki] feature_area, target wiki id (for update), tags.
33589
- ` },
33590
- { relativePath: "protocol-baseline/SKILL.md", content: "---\nname: protocol-baseline\ndescription: Use the compact Fleet protocol mode for simple, reversible, single-surface work.\n---\n\n# Fleet Protocol: Baseline\n\nUse this mode only for simple, reversible, single-surface operational work.\n\nAt any point during the work, if a Downward Guard trigger appears, stop and re-classify.\n\n## Checkpoints\n\nNone. Selecting baseline implies Mission Anchor Compact Mode.\n\n## Reporting Cadence\n\nAs you move through this protocol, report progress to the Admiral of the Navy in order.\n\n1. Brief in one line how the Workflow will proceed. \u2192 report `brief: <\u2026>`\n2. State that execution is beginning and run the Workflow. \u2192 report `status: executing`\n\n## General Quarters\n\nConfirm each readiness check below before the Workflow. Work through them in order and report each as you confirm it, then proceed to the Objective anchor. These checks prepare the work; they do not gate entry.\n\n- [ ] **Common** \u2014 objective stated (Mission Anchor), mode-fit holds (Mode Gate), Standing Orders binding. \u2192 report `common: ready`\n- [ ] **Single surface** \u2014 the exact file, command, or fact is identified. \u2192 report `surface: <x>`\n- [ ] **Reversibility** \u2014 the change is trivially reversible. \u2192 report `reversible: yes`\n\n## Workflow\n\n1. Objective statement: state the Mission Anchor objective in one line.\n2. Exact fact/file verification: verify the exact file, command, or fact needed for the request.\n3. Execution: make the smallest reversible change or run the exact requested command.\n4. Result verification: check the touched surface or command result.\n5. One-line report: report what changed, verification, and any skipped escalation trigger.\n" },
33591
- { relativePath: "protocol-frontline/SKILL.md", content: "---\nname: protocol-frontline\ndescription: Use the coordinated Fleet protocol mode for multi-carrier or parallel ownership work.\n---\n\n# Fleet Protocol: Frontline\n\nUse this mode when operational work requires multiple Carriers, independent parallel workstreams, cross-carrier review loops, or file ownership coordination. If the work is high risk but single-owner, use `protocol-redline` instead.\n\n## Checkpoints\n\nDecomposition, Dispatch, Integration, Verification.\n\n## Reporting Cadence\n\nAs you move through this protocol, report progress to the Admiral of the Navy in order \u2014 each step on its own line with its report token.\n\n1. Brief how the Workflow will proceed \u2014 name (a) the Workflow steps that will run, (b) each carrier's file or responsibility ownership, and (c) the dispatch wave sequencing. \u2192 report `brief: <\u2026>`\n2. State that execution is beginning and run the Workflow. \u2192 report `status: executing`\n\n## General Quarters\n\nConfirm each readiness check below before the Workflow. Work through them in order and report each as you confirm it, then proceed to reconnaissance and decomposition. These checks prepare the work; they do not gate entry.\n\n- [ ] **Common** \u2014 objective stated (Mission Anchor), mode-fit holds (Mode Gate), Standing Orders binding. \u2192 report `common: ready`\n- [ ] **Impact radius** \u2014 flag public-surface or API impact, irreversibility, and any security-sensitive surface. \u2192 report `impact: <\u2026>`\n- [ ] **Rollback** \u2014 identify a rollback-safe checkpoint and any Admiral of the Navy approval point before execution begins. \u2192 report `rollback: <\u2026>`\n- [ ] **Carrier availability** \u2014 confirm the intended carriers are actually exposed and available this session. \u2192 report `carriers: <\u2026>`\n- [ ] **Ownership** \u2014 pre-sketch each carrier's file or responsibility boundary. \u2192 report `ownership: <\u2026>`\n- [ ] **Shared resources** \u2014 flag shared mutable resources (same files, lock files, or a singleton test environment). \u2192 report `shared: <\u2026|none>`\n- [ ] **Dependencies** \u2014 pre-classify parallel versus sequential work before decomposition and dispatch. \u2192 report `dependencies: <parallel|sequenced: \u2026>`\n\n## Workflow\n\n1. Reconnaissance and decomposition: audit known facts, identify gaps, map affected surfaces, and split work into independently verifiable missions.\n2. Ownership graph: assign each Carrier a clear file or responsibility boundary, note dependencies, and identify shared mutable resources.\n3. Structured planning boundary: `Apply the Context Confidence Standing Order \u2014 entry requires complete`. Resolve all blocking and confirmatory gaps before dispatch planning.\n4. Parallel dispatch: use Carrier Operations Policy to launch independent Carrier work in parallel; sequence only for explicit dependencies or shared resources.\n5. Integration: re-read files before editing or accepting Carrier output, reconcile overlaps, and preserve unrelated user or Carrier changes.\n6. Cross-carrier review loop: route implementation outputs to review Carriers, send actionable findings back to owners, and re-review changed surfaces.\n7. Verification: run integrated tests and apply Deep Dive to speculative or conflicting Carrier claims.\n8. Documentation and completion report: update directly affected docs and report executed waves, Carrier ownership, QA, unresolved risks, and final Result Integrity checks.\n\n## Cross-Carrier Feedback Patterns\n\nWhen composing waves and review loops, select the structured feedback pattern that fits the task:\n\n| Pattern | Flow | When |\n|---------|------|------|\n| **Build \u2192 Review** | implementation carrier \u2192 review carrier \u2192 findings back to implementation carrier \u2192 re-review | Standard implementation cycle |\n| **Analyze \u2192 Execute** | implementation or refactoring carrier \u2192 review carrier verifies | Refactoring workflow |\n| **Decide \u2192 Plan \u2192 Execute** | judgment carrier \u2192 planning carrier \u2192 execution carrier | Complex features |\n| **Research \u2192 Act** | reconnaissance carrier \u2192 appropriate follow-up carrier from the active roster | Unknown scope tasks |\n" },
33592
- { relativePath: "protocol-midline/SKILL.md", content: "---\nname: protocol-midline\ndescription: Use the normal Fleet protocol mode for bounded operational work without downward-guard triggers.\n---\n\n# Fleet Protocol: Midline\n\nUse this mode for ordinary bounded operational work.\n\nAt any point during the work, if a Downward Guard trigger appears, stop and re-classify.\n\n## Checkpoints\n\nReconnaissance, Plan, Execution, Verification.\n\n## Reporting Cadence\n\nAs you move through this protocol, report progress to the Admiral of the Navy in order \u2014 each step on its own line with its report token.\n\n1. Brief how the Workflow will proceed \u2014 name (a) the Workflow steps that will run, (b) the target surfaces, and (c) the verification command. \u2192 report `brief: <\u2026>`\n2. State that execution is beginning and run the Workflow. \u2192 report `status: executing`\n\n## General Quarters\n\nConfirm each readiness check below before the Workflow. Work through them in order and report each as you confirm it, then proceed to focused reconnaissance. These checks prepare the work; they do not gate entry.\n\n- [ ] **Common** \u2014 objective stated (Mission Anchor), mode-fit holds (Mode Gate), Standing Orders binding. \u2192 report `common: ready`\n- [ ] **Target surfaces** \u2014 provisionally name the minimal modules or files reconnaissance will touch; confirm or revise in the brief after reconnaissance. \u2192 report `surfaces: <\u2026>`\n- [ ] **Verification** \u2014 provisionally pre-load the test, build, or check command that will prove the work done; confirm or revise in the brief after reconnaissance. \u2192 report `verify: <cmd>`\n- [ ] **Carrier** \u2014 declare whether a carrier sortie is needed. \u2192 report `carrier: <none|\u2026>`\n\n## Workflow\n\n1. Focused reconnaissance: audit known facts, identify blocking and confirmatory gaps, and inspect the minimal relevant surfaces.\n2. Planning boundary: `Apply the Context Confidence Standing Order \u2014 entry requires sufficient`. Resolve all blocking gaps before planning.\n3. Inline plan: state objective, targets, execution steps, and done criteria.\n4. Execution: implement the plan in narrow batches, using Carrier Operations Policy when delegation is appropriate.\n5. Verification and review: run targeted checks, apply Deep Dive to speculative results, and fix actionable issues.\n6. Documentation and final report: update directly affected docs only when behavior or operator guidance changed, then summarize changes and QA.\n" },
33593
- { relativePath: "protocol-redline/SKILL.md", content: "---\nname: protocol-redline\ndescription: Use the risk-controlled Fleet protocol mode for irreversible, structural, multi-module, or prompt-policy work.\n---\n\n# Fleet Protocol: Redline\n\nUse this mode when any Downward Guard trigger defined in the Protocol Gate is in scope, for security-sensitive work, or for any operational request needing explicit risk controls. Escalate to `protocol-frontline` when multiple Carriers or parallel ownership boundaries are required.\n\n## Checkpoints\n\nReconnaissance, Risk review, Plan, Execution, Verification.\n\n## Reporting Cadence\n\nAs you move through this protocol, report progress to the Admiral of the Navy in order \u2014 each step on its own line with its report token.\n\n1. Brief how the Workflow will proceed \u2014 name (a) the Workflow steps that will run, (b) file ownership and the rollback-safe checkpoint, and (c) the risk controls in force. \u2192 report `brief: <\u2026>`\n2. State that execution is beginning and run the Workflow. \u2192 report `status: executing`\n\n## General Quarters\n\nConfirm each readiness check below before the Workflow. Work through them in order and report each as you confirm it, then proceed to full reconnaissance. These checks prepare the work; they do not gate entry.\n\n- [ ] **Common** \u2014 objective stated (Mission Anchor), mode-fit holds (Mode Gate), Standing Orders binding. \u2192 report `common: ready`\n- [ ] **Doctrine** \u2014 enumerate the applicable AGENTS.md files to load for the affected scope. \u2192 report `doctrine: <\u2026>`\n- [ ] **Impact radius** \u2014 flag public-surface or API impact, irreversibility, and any security-sensitive surface. \u2192 report `impact: <\u2026>`\n- [ ] **Rollback** \u2014 identify a rollback-safe checkpoint and any Admiral of the Navy approval point before execution begins. \u2192 report `rollback: <\u2026>`\n- [ ] **Escalation** \u2014 if multiple carriers or parallel ownership boundaries are required, re-classify under frontline. \u2192 report `escalation: clear`\n\n## Workflow\n\n1. Full reconnaissance: audit known facts, enumerate blocking and confirmatory gaps, read applicable AGENTS.md files, map affected code, tests, docs, and boundaries.\n2. Architecture and risk review: identify public-surface impact, dependency constraints, rollback risk, security risk, and Admiral of the Navy approval requirements.\n3. Structured planning boundary: `Apply the Context Confidence Standing Order \u2014 entry requires complete`. Do not plan with unresolved blocking or confirmatory gaps.\n4. Risk-controlled plan: define file ownership, small execution batches, verification commands, rollback-safe checkpoints, and any approval point.\n5. Small-batch execution: edit narrowly, re-read before modifying shared files, and pause on unexpected diffs or scope expansion.\n6. Refactor gate: refactor only touched code when duplication, complexity, or convention drift appears, only with Admiral of the Navy approval or when pre-declared in the brief.\n7. Correctness and security review (may run as a single combined review dispatch): review changed behavior and risk controls; apply Deep Dive to speculative findings and repeat after fixes.\n8. Documentation and completion report: update directly affected operator docs and report changes, QA, risk controls, and residual uncertainty.\n" }
33566
+ { relativePath: "assumption-audit/SKILL.md", content: "---\nname: assumption-audit\ndescription: Resolve decision-shaped blocking gaps one at a time \u2014 Context Confidence gate failures during an active protocol, or pre-engagement requirements ambiguity routed by the Command Integrity Standing Order.\n---\n\nUse this auxiliary skill only when a decision-shaped blocking gap has been found: either the active protocol or Context Confidence re-entry path surfaced it, or the Command Integrity Standing Order routed a pre-engagement requirements ambiguity here before a protocol mode loads. This skill is not a protocol mode, does not replace the active protocol, and cannot declare the planning boundary passed by itself.\n\nFor each unresolved blocking gap, triage the gap before questioning:\n\n- **Scout-shaped**: the answer should come from direct file reads, focused reconnaissance, carrier scouting, or another verifiable evidence source. Send the workflow back to that evidence-gathering path instead of asking the user to decide.\n- **Decision-shaped**: the answer depends on preference, scope, risk appetite, product intent, or authority that evidence alone cannot settle. Ask exactly one question for this gap.\n- **Escalation-shaped**: the answer requires authority beyond the current operator, changes the mission boundary, repeatedly fails to resolve, or would weaken the active protocol's required gate. Escalate to the user.\n\nWhen a gap is decision-shaped, ask one question at a time. Present your recommended answer first, then give one or two concrete alternatives when useful. Walk decision dependencies one branch at a time until the current gap is resolved; do not bundle unrelated gaps into the same question.\n\nAfter the gap is answered, report the resolved decision in one short line and return control to the caller: the active protocol or Context Confidence Standing Order on re-entry, or the Protocol Gate when invoked pre-engagement. An active workflow must re-evaluate confidence and re-apply the required planning boundary gate before planning proceeds.\n" },
33567
+ { relativePath: "carrier-contracts/SKILL.md", content: "---\nname: carrier-contracts\ndescription: Per-carrier request-block contracts for composing carrier_dispatch requests. Load before the first dispatch of the session; skip reloading if already in context.\n---\n\n# Carrier Request-Block Contracts\n\nThis skill owns only the request composition contract. Carrier selection and routing stay in `<fleet section=\"roster\">`; dispatch mechanics (label, brevity, polling, result lookup) stay in the live `carrier_dispatch` tool description. Missing required blocks cause hard-error rejection that echoes the violated carrier's contract.\n\nAll carriers accept an optional `<prior_jobs>` block: Prior finalized carrier job IDs for context lookup. Fetch with carrier_jobs(action:\"result\", format:\"full\", job_id:...); use format:\"summary\" if archive content has expired.\n\n## Contracts by carrier\n- **nimitz** (Nimitz \xB7 Strategic Command & Judgment) \u2014 wrap request content in these blocks (? = optional):\n - <context> required: Background situation, current state, and relevant history.\n - <problem> required: The specific question, decision point, or challenge to analyze.\n - <constraints?> optional: Hard constraints, deadlines, compatibility requirements.\n - <artifacts?> optional: Relevant code snippets, file paths, error logs to examine.\n- **kirov** (Kirov \xB7 Operational Planning) \u2014 wrap request content in these blocks (? = optional):\n - <goal> required: What the user wants to build, fix, or achieve \u2014 specific feature, PRD, behavior, and any stated constraints.\n - <plan_file?> optional: If provided, exact repo-relative .fleet/plans/{name}.md path Kirov must create or update. Do not choose a different filename.\n - <context?> optional: Relevant codebase context \u2014 files, modules, patterns, prior host-agent direction, or implementation realities the planner should respect.\n - <constraints?> optional: Business rules, tech stack requirements, scope boundaries, fixed decisions, or explicit exclusions the plan must respect.\n - <intent_type?> optional: If known: Refactoring | Build from Scratch | Mid-sized | Collaborative | Architecture Follow-through | Research-to-Plan.\n- **genesis** (Genesis \xB7 Chief Engineer) \u2014 wrap request content in these blocks (? = optional):\n - <objective> required: What needs to be built or achieved. Be specific about the desired end state.\n - <scope> required: Which modules, directories, or subsystems are in play.\n - <constraints?> optional: Hard technical constraints, compatibility requirements, or non-negotiables.\n - <references?> optional: Prior Nimitz recommendations, Kirov plans, existing patterns to follow, or design decisions already made.\n- **ohio** (Ohio \xB7 Multi-Wave Execution) \u2014 wrap request content in these blocks (? = optional):\n - <plan_file> required: Required repo-relative path to a Markdown plan file under .fleet/plans/*.md only. Ohio reads this file and follows it as the authoritative execution plan.\n - <execution_scope?> optional: Optional: for legacy plans without Execution Topology or plans marked Execution mode: Sequential, omitted or `all` executes the full plan sequentially. For Execution mode: Parallel, provide one exact Wave/Lane ID declared by the Dispatch Manifest; omitted or `all` is rejected. Never combine a full-plan invocation with scoped-lane Ohio invocation(s).\n - <objective?> optional: Optional brief restatement of the overarching goal for context anchoring.\n - <scope?> optional: Optional explicit scope boundaries if narrower than the plan_file's full coverage.\n - <constraints?> optional: Optional hard constraints, deadlines, or compatibility requirements that override or supplement the plan.\n- **sentinel** (Sentinel \xB7 QA & Security Lead) \u2014 wrap request content in these blocks (? = optional):\n - <target> required: Which files, modules, PRs, endpoints, or recent changes to inspect.\n - <concern?> optional: Specific suspicion, symptom, or area of worry to focus on.\n - <context?> optional: Background on what the code does and expected behavior.\n - <attack_surface?> optional: Known entry points, user-controlled inputs, or external interfaces (security mode).\n - <threat_model?> optional: Assumed attacker capability \u2014 unauth user, compromised dep, insider (security mode).\n - <fix_mode?> optional: 'report' (default) for findings only, or 'fix' to apply corrections.\n- **vanguard** (Vanguard \xB7 Reconnaissance Specialist) \u2014 wrap request content in these blocks (? = optional):\n - <objective> required: What intelligence is needed \u2014 question to answer or target to locate.\n - <search_space?> optional: Directories, files, URLs, or domains to focus the search on.\n - <hints?> optional: Known symbols, keywords, file patterns, or prior findings to narrow the scan.\n - <depth?> optional: 'quick' for surface scan, 'thorough' for exhaustive. Default: 'medium'.\n- **tempest** (Tempest \xB7 External Intelligence) \u2014 wrap request content in these blocks (? = optional):\n - <target_repo> required: Repository to investigate (owner/repo format or full URL).\n - <objective> required: What intelligence is needed \u2014 feature, pattern, API usage, or implementation detail.\n - <focus_areas?> optional: Specific directories, files, symbols, or code patterns to prioritize.\n - <constraints?> optional: Time constraints, specific branches/tags, or areas to exclude.\n- **chronicle** (Chronicle \xB7 Chief Knowledge Officer) \u2014 wrap request content in these blocks (? = optional):\n - <target> required: [Codebase Doc] which code, module, PR, feature, or release artifact to document. [Fleet Wiki] which feature area or wiki entry slug.\n - <doc_type> required: [Codebase Doc] README, API spec, PR summary, release notes, changelog, AGENTS.md, '.md-audit', change-impact summary, breaking-change report, migration guide. [Fleet Wiki] 'wiki-create' (new entry) or 'wiki-update' (existing entry revision).\n - <audience> required: developers, end-users, API consumers, operators, or contributors.\n - <scope?> optional: [Codebase Doc] include/exclude; for changelogs/change-impact/audits: commit range, PR, diff, feature slice, deployment scope. [Fleet Wiki] feature_area, target wiki id (for update), tags.\n" },
33568
+ { relativePath: "protocol-baseline/SKILL.md", content: "---\nname: protocol-baseline\ndescription: Use the compact Fleet protocol mode for simple, reversible, single-surface work.\n---\n\n# Fleet Protocol: Baseline\n\nUse this mode only for simple, reversible, single-surface operational work.\n\nAt any point during the work, if a Downward Guard trigger appears, stop and re-classify.\n\n## Checkpoints\n\nNone. Selecting baseline implies Mission Anchor Compact Mode.\n\n## Reporting Cadence\n\nAs you move through this protocol, report progress to the user in order.\n\n1. Brief in one line how the Workflow will proceed. \u2192 report `brief: <\u2026>`\n2. State that execution is beginning and run the Workflow. \u2192 report `status: executing`\n\n## General Quarters\n\nConfirm each readiness check below before the Workflow. Work through them in order and report each as you confirm it, then proceed to the Objective anchor. These checks prepare the work; they do not gate entry.\n\n- [ ] **Common** \u2014 objective stated (Mission Anchor), mode-fit holds (Mode Gate), Standing Orders binding. \u2192 report `common: ready`\n- [ ] **Single surface** \u2014 the exact file, command, or fact is identified. \u2192 report `surface: <x>`\n- [ ] **Reversibility** \u2014 the change is trivially reversible. \u2192 report `reversible: yes`\n\n## Workflow\n\n1. Objective statement: state the Mission Anchor objective in one line.\n2. Exact fact/file verification: verify the exact file, command, or fact needed for the request.\n3. Execution: make the smallest reversible change or run the exact requested command.\n4. Result verification: check the touched surface or command result.\n5. One-line report: report what changed, verification, and any skipped escalation trigger.\n" },
33569
+ { relativePath: "protocol-frontline/SKILL.md", content: "---\nname: protocol-frontline\ndescription: Use the coordinated Fleet protocol mode for multi-carrier or parallel ownership work.\n---\n\n# Fleet Protocol: Frontline\n\nUse this mode when operational work requires multiple Carriers, independent parallel workstreams, cross-carrier review loops, or file ownership coordination. If the work is high risk but single-owner, use `protocol-redline` instead.\n\n## Checkpoints\n\nDecomposition, Dispatch, Integration, Verification.\n\n## Reporting Cadence\n\nAs you move through this protocol, report progress to the user in order \u2014 each step on its own line with its report token.\n\n1. Brief how the Workflow will proceed \u2014 name (a) the Workflow steps that will run, (b) each carrier's file or responsibility ownership, and (c) the dispatch wave sequencing. \u2192 report `brief: <\u2026>`\n2. State that execution is beginning and run the Workflow. \u2192 report `status: executing`\n\n## General Quarters\n\nConfirm each readiness check below before the Workflow. Work through them in order and report each as you confirm it, then proceed to reconnaissance and decomposition. These checks prepare the work; they do not gate entry.\n\n- [ ] **Common** \u2014 objective stated (Mission Anchor), mode-fit holds (Mode Gate), Standing Orders binding. \u2192 report `common: ready`\n- [ ] **Impact radius** \u2014 flag public-surface or API impact, irreversibility, and any security-sensitive surface. \u2192 report `impact: <\u2026>`\n- [ ] **Rollback** \u2014 identify a rollback-safe checkpoint and any user approval point before execution begins. \u2192 report `rollback: <\u2026>`\n- [ ] **Carrier availability** \u2014 confirm the intended carriers are actually exposed and available this session. \u2192 report `carriers: <\u2026>`\n- [ ] **Ownership** \u2014 pre-sketch each carrier's file or responsibility boundary. \u2192 report `ownership: <\u2026>`\n- [ ] **Shared resources** \u2014 flag shared mutable resources (same files, lock files, or a singleton test environment). \u2192 report `shared: <\u2026|none>`\n- [ ] **Dependencies** \u2014 pre-classify parallel versus sequential work before decomposition and dispatch. \u2192 report `dependencies: <parallel|sequenced: \u2026>`\n\n## Workflow\n\n1. Reconnaissance and decomposition: audit known facts, identify gaps, map affected surfaces, and split work into independently verifiable missions.\n2. Ownership graph: assign each Carrier a clear file or responsibility boundary, note dependencies, and identify shared mutable resources.\n3. Structured planning boundary: `Apply the Context Confidence Standing Order \u2014 entry requires complete`. Resolve all blocking and confirmatory gaps before dispatch planning.\n4. Parallel dispatch: use Carrier Operations Policy to launch independent Carrier work in parallel; sequence only for explicit dependencies or shared resources.\n5. Integration: re-read files before editing or accepting Carrier output, reconcile overlaps, and preserve unrelated user or Carrier changes.\n6. Cross-carrier review loop: route implementation outputs to review Carriers, send actionable findings back to owners, and re-review changed surfaces.\n7. Verification: run integrated tests and apply Deep Dive to speculative or conflicting Carrier claims.\n8. Documentation and completion report: update directly affected docs and report executed waves, Carrier ownership, QA, unresolved risks, and final Result Integrity checks.\n\n## Cross-Carrier Feedback Patterns\n\nWhen composing waves and review loops, select the structured feedback pattern that fits the task:\n\n| Pattern | Flow | When |\n|---------|------|------|\n| **Build \u2192 Review** | implementation carrier \u2192 review carrier \u2192 findings back to implementation carrier \u2192 re-review | Standard implementation cycle |\n| **Analyze \u2192 Execute** | implementation or refactoring carrier \u2192 review carrier verifies | Refactoring workflow |\n| **Decide \u2192 Plan \u2192 Execute** | judgment carrier \u2192 planning carrier \u2192 execution carrier | Complex features |\n| **Research \u2192 Act** | reconnaissance carrier \u2192 appropriate follow-up carrier from the active roster | Unknown scope tasks |\n" },
33570
+ { relativePath: "protocol-midline/SKILL.md", content: "---\nname: protocol-midline\ndescription: Use the normal Fleet protocol mode for bounded operational work without downward-guard triggers.\n---\n\n# Fleet Protocol: Midline\n\nUse this mode for ordinary bounded operational work.\n\nAt any point during the work, if a Downward Guard trigger appears, stop and re-classify.\n\n## Checkpoints\n\nReconnaissance, Plan, Execution, Verification.\n\n## Reporting Cadence\n\nAs you move through this protocol, report progress to the user in order \u2014 each step on its own line with its report token.\n\n1. Brief how the Workflow will proceed \u2014 name (a) the Workflow steps that will run, (b) the target surfaces, and (c) the verification command. \u2192 report `brief: <\u2026>`\n2. State that execution is beginning and run the Workflow. \u2192 report `status: executing`\n\n## General Quarters\n\nConfirm each readiness check below before the Workflow. Work through them in order and report each as you confirm it, then proceed to focused reconnaissance. These checks prepare the work; they do not gate entry.\n\n- [ ] **Common** \u2014 objective stated (Mission Anchor), mode-fit holds (Mode Gate), Standing Orders binding. \u2192 report `common: ready`\n- [ ] **Target surfaces** \u2014 provisionally name the minimal modules or files reconnaissance will touch; confirm or revise in the brief after reconnaissance. \u2192 report `surfaces: <\u2026>`\n- [ ] **Verification** \u2014 provisionally pre-load the test, build, or check command that will prove the work done; confirm or revise in the brief after reconnaissance. \u2192 report `verify: <cmd>`\n- [ ] **Carrier** \u2014 declare whether a carrier dispatch is needed. \u2192 report `carrier: <none|\u2026>`\n\n## Workflow\n\n1. Focused reconnaissance: audit known facts, identify blocking and confirmatory gaps, and inspect the minimal relevant surfaces.\n2. Planning boundary: `Apply the Context Confidence Standing Order \u2014 entry requires sufficient`. Resolve all blocking gaps before planning.\n3. Inline plan: state objective, targets, execution steps, and done criteria.\n4. Execution: implement the plan in narrow batches, using Carrier Operations Policy when delegation is appropriate.\n5. Verification and review: run targeted checks, apply Deep Dive to speculative results, and fix actionable issues.\n6. Documentation and final report: update directly affected docs only when behavior or operator guidance changed, then summarize changes and QA.\n" },
33571
+ { relativePath: "protocol-redline/SKILL.md", content: "---\nname: protocol-redline\ndescription: Use the risk-controlled Fleet protocol mode for irreversible, structural, multi-module, or prompt-policy work.\n---\n\n# Fleet Protocol: Redline\n\nUse this mode when any Downward Guard trigger defined in the Protocol Gate is in scope, for security-sensitive work, or for any operational request needing explicit risk controls. Escalate to `protocol-frontline` when multiple Carriers or parallel ownership boundaries are required.\n\n## Checkpoints\n\nReconnaissance, Risk review, Plan, Execution, Verification.\n\n## Reporting Cadence\n\nAs you move through this protocol, report progress to the user in order \u2014 each step on its own line with its report token.\n\n1. Brief how the Workflow will proceed \u2014 name (a) the Workflow steps that will run, (b) file ownership and the rollback-safe checkpoint, and (c) the risk controls in force. \u2192 report `brief: <\u2026>`\n2. State that execution is beginning and run the Workflow. \u2192 report `status: executing`\n\n## General Quarters\n\nConfirm each readiness check below before the Workflow. Work through them in order and report each as you confirm it, then proceed to full reconnaissance. These checks prepare the work; they do not gate entry.\n\n- [ ] **Common** \u2014 objective stated (Mission Anchor), mode-fit holds (Mode Gate), Standing Orders binding. \u2192 report `common: ready`\n- [ ] **Doctrine** \u2014 enumerate the applicable AGENTS.md files to load for the affected scope. \u2192 report `doctrine: <\u2026>`\n- [ ] **Impact radius** \u2014 flag public-surface or API impact, irreversibility, and any security-sensitive surface. \u2192 report `impact: <\u2026>`\n- [ ] **Rollback** \u2014 identify a rollback-safe checkpoint and any user approval point before execution begins. \u2192 report `rollback: <\u2026>`\n- [ ] **Escalation** \u2014 if multiple carriers or parallel ownership boundaries are required, re-classify under frontline. \u2192 report `escalation: clear`\n\n## Workflow\n\n1. Full reconnaissance: audit known facts, enumerate blocking and confirmatory gaps, read applicable AGENTS.md files, map affected code, tests, docs, and boundaries.\n2. Architecture and risk review: identify public-surface impact, dependency constraints, rollback risk, security risk, and user approval requirements.\n3. Structured planning boundary: `Apply the Context Confidence Standing Order \u2014 entry requires complete`. Do not plan with unresolved blocking or confirmatory gaps.\n4. Risk-controlled plan: define file ownership, small execution batches, verification commands, rollback-safe checkpoints, and any approval point.\n5. Small-batch execution: edit narrowly, re-read before modifying shared files, and pause on unexpected diffs or scope expansion.\n6. Refactor gate: refactor only touched code when duplication, complexity, or convention drift appears, only with user approval or when pre-declared in the brief.\n7. Correctness and security review (may run as a single combined review dispatch): review changed behavior and risk controls; apply Deep Dive to speculative findings and repeat after fixes.\n8. Documentation and completion report: update directly affected operator docs and report changes, QA, risk controls, and residual uncertainty.\n" }
33594
33572
  ];
33595
33573
  var DIR_MODE = 448;
33596
33574
  var FILE_MODE = 384;
@@ -33606,7 +33584,7 @@ function writePrivateJson(filePath, value, rootBase) {
33606
33584
  function writePrivateFile(filePath, content, rootBase) {
33607
33585
  const resolvedBase = ensureRootBase(rootBase);
33608
33586
  ensurePathWithinRoot(resolvedBase, filePath);
33609
- ensureDirectorySegments(resolvedBase, path27__default.dirname(filePath));
33587
+ ensureDirectorySegments(resolvedBase, path28__default.dirname(filePath));
33610
33588
  writeFileNoFollow(filePath, content);
33611
33589
  chmodBestEffort(filePath, FILE_MODE);
33612
33590
  }
@@ -33653,20 +33631,20 @@ function writeFileNoFollow(filePath, content) {
33653
33631
  }
33654
33632
  }
33655
33633
  function ensureRootBase(rootBase) {
33656
- const resolvedBase = path27__default.resolve(rootBase);
33657
- const anchor = findExistingDirectoryAnchor(path27__default.dirname(resolvedBase));
33634
+ const resolvedBase = path28__default.resolve(rootBase);
33635
+ const anchor = findExistingDirectoryAnchor(path28__default.dirname(resolvedBase));
33658
33636
  ensureDirectorySegments(anchor, resolvedBase);
33659
33637
  assertDirectorySafe(resolvedBase, "Plugin root base");
33660
33638
  return resolvedBase;
33661
33639
  }
33662
33640
  function assertRootBaseSafe(rootBase) {
33663
- const resolvedBase = path27__default.resolve(rootBase);
33664
- assertExistingSegmentsSafe(findExistingDirectoryAnchor(path27__default.dirname(resolvedBase)), resolvedBase);
33641
+ const resolvedBase = path28__default.resolve(rootBase);
33642
+ assertExistingSegmentsSafe(findExistingDirectoryAnchor(path28__default.dirname(resolvedBase)), resolvedBase);
33665
33643
  assertDirectorySafe(resolvedBase, "Plugin root base");
33666
33644
  return resolvedBase;
33667
33645
  }
33668
33646
  function findExistingDirectoryAnchor(targetPath) {
33669
- const resolvedTarget = path27__default.resolve(targetPath);
33647
+ const resolvedTarget = path28__default.resolve(targetPath);
33670
33648
  let current = resolvedTarget;
33671
33649
  while (true) {
33672
33650
  try {
@@ -33674,7 +33652,7 @@ function findExistingDirectoryAnchor(targetPath) {
33674
33652
  return current;
33675
33653
  } catch (error51) {
33676
33654
  if (error51 instanceof Error && "code" in error51 && error51.code === "ENOENT") {
33677
- const parent = path27__default.dirname(current);
33655
+ const parent = path28__default.dirname(current);
33678
33656
  if (parent === current) throw error51;
33679
33657
  current = parent;
33680
33658
  continue;
@@ -33693,17 +33671,17 @@ function assertDirectorySafe(dirPath, label) {
33693
33671
  }
33694
33672
  }
33695
33673
  function ensurePathWithinRoot(resolvedBase, candidatePath) {
33696
- const resolvedCandidate = path27__default.resolve(candidatePath);
33697
- const relative = path27__default.relative(resolvedBase, resolvedCandidate);
33698
- if (relative === "" || !relative.startsWith("..") && !path27__default.isAbsolute(relative)) return;
33674
+ const resolvedCandidate = path28__default.resolve(candidatePath);
33675
+ const relative = path28__default.relative(resolvedBase, resolvedCandidate);
33676
+ if (relative === "" || !relative.startsWith("..") && !path28__default.isAbsolute(relative)) return;
33699
33677
  throw new Error(`Plugin path escapes root base: ${candidatePath}`);
33700
33678
  }
33701
33679
  function ensureDirectorySegments(resolvedBase, dirPath) {
33702
- const target = path27__default.resolve(dirPath);
33703
- const relative = path27__default.relative(resolvedBase, target);
33680
+ const target = path28__default.resolve(dirPath);
33681
+ const relative = path28__default.relative(resolvedBase, target);
33704
33682
  let current = resolvedBase;
33705
- for (const segment of relative.split(path27__default.sep).filter(Boolean)) {
33706
- current = path27__default.join(current, segment);
33683
+ for (const segment of relative.split(path28__default.sep).filter(Boolean)) {
33684
+ current = path28__default.join(current, segment);
33707
33685
  try {
33708
33686
  const stat3 = lstatSync(current);
33709
33687
  if (stat3.isSymbolicLink()) {
@@ -33724,11 +33702,11 @@ function ensureDirectorySegments(resolvedBase, dirPath) {
33724
33702
  }
33725
33703
  }
33726
33704
  function assertExistingSegmentsSafe(resolvedBase, targetPath) {
33727
- const target = path27__default.resolve(targetPath);
33728
- const relative = path27__default.relative(resolvedBase, target);
33705
+ const target = path28__default.resolve(targetPath);
33706
+ const relative = path28__default.relative(resolvedBase, target);
33729
33707
  let current = resolvedBase;
33730
- for (const segment of relative.split(path27__default.sep).filter(Boolean)) {
33731
- current = path27__default.join(current, segment);
33708
+ for (const segment of relative.split(path28__default.sep).filter(Boolean)) {
33709
+ current = path28__default.join(current, segment);
33732
33710
  const stat3 = lstatSync(current);
33733
33711
  if (stat3.isSymbolicLink()) {
33734
33712
  throw new Error(`Plugin path segment is a symlink: ${current}`);
@@ -33740,27 +33718,22 @@ function assertExistingSegmentsSafe(resolvedBase, targetPath) {
33740
33718
  }
33741
33719
  }
33742
33720
  function assertExistingParentSegmentsSafe(resolvedBase, targetPath) {
33743
- assertExistingSegmentsSafe(resolvedBase, path27__default.dirname(targetPath));
33721
+ assertExistingSegmentsSafe(resolvedBase, path28__default.dirname(targetPath));
33744
33722
  }
33745
33723
  function assertSegmentRealpathWithinRoot(resolvedBase, segmentPath) {
33746
33724
  const baseRealpath = realpathSync(resolvedBase);
33747
33725
  const segmentRealpath = realpathSync(segmentPath);
33748
- const relative = path27__default.relative(baseRealpath, segmentRealpath);
33749
- if (relative === "" || !relative.startsWith("..") && !path27__default.isAbsolute(relative)) return;
33726
+ const relative = path28__default.relative(baseRealpath, segmentRealpath);
33727
+ if (relative === "" || !relative.startsWith("..") && !path28__default.isAbsolute(relative)) return;
33750
33728
  throw new Error(`Plugin path segment escapes root base: ${segmentPath}`);
33751
33729
  }
33752
33730
 
33753
- // ../../packages/fleet-admiral/src/agent-cli/plugin/fleet.ts
33754
- var CURSOR_DOCTRINE_RULE_FILE = "fleet-doctrine.mdc";
33755
- var CURSOR_DOCTRINE_RULE_FRONTMATTER = `---
33756
- description: Fleet Admiral operating doctrine. Always apply in Fleet-launched Cursor Agent sessions.
33757
- globs:
33758
- alwaysApply: true
33759
- ---
33760
- `;
33761
- var CURSOR_DOCTRINE_RULE_PREAMBLE = `# Fleet Runtime Doctrine for Cursor Agent
33731
+ // ../../packages/fleet-admiral/src/agent-cli/doctrine-hook.ts
33732
+ var DOCTRINE_FILE_NAME = "doctrine.md";
33733
+ var DOCTRINE_HOOK_SCRIPT_NAME = "inject-doctrine.mjs";
33734
+ var CURSOR_DOCTRINE_PREAMBLE = `# Fleet Runtime Doctrine for Cursor Agent
33762
33735
 
33763
- You are running as Cursor Agent inside Fleet. Cursor provides this file as a persistent rule, not as a native system prompt. For this Fleet-launched session, treat the embedded Fleet system prompt below as your active Fleet runtime doctrine.
33736
+ You are running as Cursor Agent inside Fleet. This context was injected through a Fleet sessionStart hook. Treat the embedded Fleet system prompt below as your active Fleet runtime doctrine.
33764
33737
 
33765
33738
  Priority and interpretation:
33766
33739
 
@@ -33774,13 +33747,39 @@ Priority and interpretation:
33774
33747
 
33775
33748
  ## Embedded Fleet System Prompt
33776
33749
 
33777
- The following block is the Fleet system prompt content adapted for Cursor's rules mechanism. It is intentionally embedded verbatim after this wrapper.
33750
+ The following block is the Fleet system prompt content adapted for Cursor hook injection. It is intentionally embedded verbatim after this wrapper.
33778
33751
 
33779
33752
  <fleet-system-prompt>
33780
33753
  `;
33781
- var CURSOR_DOCTRINE_RULE_FOOTER = `
33754
+ var CURSOR_DOCTRINE_FOOTER = `
33782
33755
  </fleet-system-prompt>
33783
33756
  `;
33757
+ var INJECT_DOCTRINE_HOOK_SCRIPT = `import fs from "node:fs";
33758
+ import path from "node:path";
33759
+ import { fileURLToPath } from "node:url";
33760
+
33761
+ const pluginRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
33762
+ const doctrine = fs.readFileSync(path.join(pluginRoot, "${DOCTRINE_FILE_NAME}"), "utf8");
33763
+ process.stdout.write(JSON.stringify({ additional_context: doctrine }));
33764
+ `;
33765
+ function formatCursorDoctrine(doctrine) {
33766
+ return `${CURSOR_DOCTRINE_PREAMBLE}${doctrine}${CURSOR_DOCTRINE_FOOTER}`;
33767
+ }
33768
+ function renderCursorDoctrineHookAssets(pluginRoot, doctrine, hookCommandRoot = pluginRoot) {
33769
+ writePrivateFile(
33770
+ path28__default.join(pluginRoot, DOCTRINE_FILE_NAME),
33771
+ formatCursorDoctrine(doctrine),
33772
+ pluginRoot
33773
+ );
33774
+ const scriptPath = path28__default.join(hookCommandRoot, "hooks", DOCTRINE_HOOK_SCRIPT_NAME);
33775
+ writePrivateFile(path28__default.join(pluginRoot, "hooks", DOCTRINE_HOOK_SCRIPT_NAME), INJECT_DOCTRINE_HOOK_SCRIPT, pluginRoot);
33776
+ return {
33777
+ command: process.execPath,
33778
+ args: [scriptPath]
33779
+ };
33780
+ }
33781
+
33782
+ // ../../packages/fleet-admiral/src/agent-cli/plugin/fleet.ts
33784
33783
  var assetBundle = {
33785
33784
  description: "Fleet carrier delegation and wiki evidence plugin",
33786
33785
  directoryName: "fleet",
@@ -33791,11 +33790,16 @@ var assetBundle = {
33791
33790
  };
33792
33791
  function renderAssetPluginRoot(pluginRoot, bundle, options) {
33793
33792
  renderEmbeddedSkillAssets(pluginRoot);
33793
+ const doctrineHookExec = options.cliId === "cursor" && options.doctrine !== void 0 ? renderCursorDoctrineHookAssets(
33794
+ pluginRoot,
33795
+ options.doctrine,
33796
+ options.installedPluginRoot ?? pluginRoot
33797
+ ) : void 0;
33794
33798
  if (options.cliId === "claude") {
33795
- writePrivateJson(path27__default.join(pluginRoot, "hooks", "hooks.json"), claudeHooks(options), pluginRoot);
33799
+ writePrivateJson(path28__default.join(pluginRoot, "hooks", "hooks.json"), claudeHooks(options), pluginRoot);
33796
33800
  }
33797
33801
  if (options.cliId === "cursor") {
33798
- renderCursorPluginRoot(pluginRoot, options);
33802
+ renderCursorPluginRoot(pluginRoot, options, doctrineHookExec);
33799
33803
  }
33800
33804
  }
33801
33805
  function claudeHooks(options) {
@@ -33836,25 +33840,15 @@ function claudeCommandHook(hookExec) {
33836
33840
  type: "command"
33837
33841
  };
33838
33842
  }
33839
- function renderCursorPluginRoot(pluginRoot, options) {
33840
- if (options.doctrine !== void 0) {
33841
- renderCursorDoctrineRule(pluginRoot, options.doctrine);
33842
- }
33843
+ function renderCursorPluginRoot(pluginRoot, options, doctrineHookExec) {
33843
33844
  if ((options.mcpServers ?? []).length > 0) {
33844
- writePrivateJson(path27__default.join(pluginRoot, "mcp.json"), cursorMcpConfig(options.mcpServers ?? []), pluginRoot);
33845
+ writePrivateJson(path28__default.join(pluginRoot, "mcp.json"), cursorMcpConfig(options.mcpServers ?? []), pluginRoot);
33845
33846
  }
33846
- const hooks = cursorHooks(options);
33847
+ const hooks = cursorHooks(options, doctrineHookExec);
33847
33848
  if (hooks !== void 0) {
33848
- writePrivateJson(path27__default.join(pluginRoot, "hooks", "hooks.json"), hooks, pluginRoot);
33849
+ writePrivateJson(path28__default.join(pluginRoot, "hooks", "hooks.json"), hooks, pluginRoot);
33849
33850
  }
33850
33851
  }
33851
- function renderCursorDoctrineRule(pluginRoot, doctrine) {
33852
- writePrivateFile(
33853
- path27__default.join(pluginRoot, "rules", CURSOR_DOCTRINE_RULE_FILE),
33854
- `${CURSOR_DOCTRINE_RULE_FRONTMATTER}${CURSOR_DOCTRINE_RULE_PREAMBLE}${doctrine}${CURSOR_DOCTRINE_RULE_FOOTER}`,
33855
- pluginRoot
33856
- );
33857
- }
33858
33852
  function cursorMcpConfig(servers) {
33859
33853
  return {
33860
33854
  mcpServers: Object.fromEntries(
@@ -33868,8 +33862,8 @@ function cursorMcpConfig(servers) {
33868
33862
  )
33869
33863
  };
33870
33864
  }
33871
- function cursorHooks(options) {
33872
- const sessionStartExecs = [options.captureSessionHookExec].filter((exec) => exec !== void 0);
33865
+ function cursorHooks(options, doctrineHookExec) {
33866
+ const sessionStartExecs = [doctrineHookExec, options.captureSessionHookExec].filter((exec) => exec !== void 0);
33873
33867
  const beforeSubmitPromptExecs = [options.turnStartHookExec, options.autoNameHookExec].filter((exec) => exec !== void 0);
33874
33868
  const stopExecs = [options.turnEndHookExec].filter((exec) => exec !== void 0);
33875
33869
  if (sessionStartExecs.length === 0 && beforeSubmitPromptExecs.length === 0 && stopExecs.length === 0) return void 0;
@@ -33892,7 +33886,7 @@ function cursorCommandHook(hookExec, extraArgs = []) {
33892
33886
  }
33893
33887
  function renderEmbeddedSkillAssets(pluginRoot) {
33894
33888
  for (const asset of EMBEDDED_AGENT_CLI_SKILL_ASSETS) {
33895
- writePrivateFile(path27__default.join(pluginRoot, "skills", asset.relativePath), asset.content, pluginRoot);
33889
+ writePrivateFile(path28__default.join(pluginRoot, "skills", asset.relativePath), asset.content, pluginRoot);
33896
33890
  }
33897
33891
  }
33898
33892
  var CONFIG_FILE_NAME = "config.toml";
@@ -33907,7 +33901,7 @@ function neutralizeCodexFleetPluginConfig(options) {
33907
33901
  mutateCodexConfigWithRetry(options, 0);
33908
33902
  }
33909
33903
  function mutateCodexConfigWithRetry(options, attempt) {
33910
- const configPath = path27__default.join(options.codexHome, CONFIG_FILE_NAME);
33904
+ const configPath = path28__default.join(options.codexHome, CONFIG_FILE_NAME);
33911
33905
  const targetPath = resolveRealConfigPath(configPath);
33912
33906
  const snapshot = readConfigSnapshot(targetPath);
33913
33907
  const nextContent = patchCodexConfig(snapshot.content, options);
@@ -33928,7 +33922,7 @@ function resolveRealConfigPath(configPath) {
33928
33922
  } catch (error51) {
33929
33923
  if (!isNodeError(error51, "ENOENT")) throw error51;
33930
33924
  try {
33931
- return path27__default.join(realpathSync(path27__default.dirname(configPath)), path27__default.basename(configPath));
33925
+ return path28__default.join(realpathSync(path28__default.dirname(configPath)), path28__default.basename(configPath));
33932
33926
  } catch (dirError) {
33933
33927
  if (isNodeError(dirError, "ENOENT")) return configPath;
33934
33928
  throw dirError;
@@ -33965,9 +33959,9 @@ function readConfigSnapshot(configPath) {
33965
33959
  }
33966
33960
  }
33967
33961
  function writeConfigIfUnchanged(configPath, snapshot, content) {
33968
- mkdirSync(path27__default.dirname(configPath), { recursive: true, mode: 448 });
33962
+ mkdirSync(path28__default.dirname(configPath), { recursive: true, mode: 448 });
33969
33963
  assertConfigUnchanged(configPath, snapshot);
33970
- const tempPath = path27__default.join(path27__default.dirname(configPath), `.${path27__default.basename(configPath)}.${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}.tmp`);
33964
+ const tempPath = path28__default.join(path28__default.dirname(configPath), `.${path28__default.basename(configPath)}.${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}.tmp`);
33971
33965
  let fd;
33972
33966
  try {
33973
33967
  fd = openSync(tempPath, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | constants.O_NOFOLLOW, CONFIG_FILE_MODE);
@@ -34215,7 +34209,7 @@ function ensureCodexPluginRegisteredOrThrow(registration, command, runCommand) {
34215
34209
  pluginKey
34216
34210
  });
34217
34211
  writePrivateFile(registration.hashPath, `${registration.contentHash}
34218
- `, path27__default.dirname(registration.hashPath));
34212
+ `, path28__default.dirname(registration.hashPath));
34219
34213
  }
34220
34214
  function assertCommandSucceeded(label, result) {
34221
34215
  if (result.status === 0) return;
@@ -34223,7 +34217,7 @@ function assertCommandSucceeded(label, result) {
34223
34217
  throw new Error(`${label} failed${detail.length > 0 ? `: ${detail}` : ""}`);
34224
34218
  }
34225
34219
  function resolveCodexHome(env) {
34226
- return env.CODEX_HOME ?? path27__default.join(env.HOME ?? os3__default.homedir(), ".codex");
34220
+ return env.CODEX_HOME ?? path28__default.join(env.HOME ?? os3__default.homedir(), ".codex");
34227
34221
  }
34228
34222
  function findMarketplaceEntries(result, marketplaceName) {
34229
34223
  return parseMarketplaceEntries(result).filter((entry) => entry.name === marketplaceName);
@@ -34239,7 +34233,7 @@ function parseMarketplaceEntries(result) {
34239
34233
  return entries;
34240
34234
  }
34241
34235
  function normalizeMarketplaceRoot(rootPath, cwd) {
34242
- const resolved = path27__default.resolve(cwd, rootPath);
34236
+ const resolved = path28__default.resolve(cwd, rootPath);
34243
34237
  try {
34244
34238
  return realpathSync(resolved);
34245
34239
  } catch (error51) {
@@ -34263,7 +34257,7 @@ function readHash(hashPath) {
34263
34257
  }
34264
34258
  function removeFlatMarketplaceResidue(projectMarketplaceRoot) {
34265
34259
  for (const entry of FLAT_MARKETPLACE_FS_RESIDUE_ENTRIES) {
34266
- removePrivatePath(path27__default.join(projectMarketplaceRoot, entry), projectMarketplaceRoot);
34260
+ removePrivatePath(path28__default.join(projectMarketplaceRoot, entry), projectMarketplaceRoot);
34267
34261
  }
34268
34262
  }
34269
34263
 
@@ -34323,7 +34317,7 @@ async function createAgentCliPlugin(options) {
34323
34317
  cleanup,
34324
34318
  codexRegistrations: options.cliId === "codex" ? renderableBundles.map(({ bundle, target }, index) => ({
34325
34319
  contentHash: contentHashes.get(target.root),
34326
- hashPath: path27__default.join(target.root, bundle.hashFileName),
34320
+ hashPath: path28__default.join(target.root, bundle.hashFileName),
34327
34321
  marketplaceDir: target.root,
34328
34322
  marketplaceName: target.name,
34329
34323
  pluginName: bundle.name,
@@ -34340,7 +34334,7 @@ function resolveRenderablePluginBundles(fleetRoot) {
34340
34334
  function homeMarketplaceTarget(fleetRoot) {
34341
34335
  return {
34342
34336
  name: FLEET_MARKETPLACE_NAME,
34343
- root: path27__default.join(fleetRoot, MARKETPLACE_DIR_NAME)
34337
+ root: path28__default.join(fleetRoot, MARKETPLACE_DIR_NAME)
34344
34338
  };
34345
34339
  }
34346
34340
  function groupRenderableBundlesByMarketplace(bundles) {
@@ -34356,24 +34350,24 @@ function groupRenderableBundlesByMarketplace(bundles) {
34356
34350
  return groups;
34357
34351
  }
34358
34352
  function renderPluginRoot(pluginRoot, bundle, options) {
34359
- const parentRoot = path27__default.dirname(pluginRoot);
34353
+ const parentRoot = path28__default.dirname(pluginRoot);
34360
34354
  ensurePrivateDir(parentRoot, parentRoot);
34361
34355
  const stageParent = createStagingDir(parentRoot);
34362
- const stagedPluginRoot = path27__default.join(stageParent, path27__default.basename(pluginRoot));
34356
+ const stagedPluginRoot = path28__default.join(stageParent, path28__default.basename(pluginRoot));
34363
34357
  try {
34364
34358
  ensurePrivateDir(stagedPluginRoot, stagedPluginRoot);
34365
- writePrivateJson(path27__default.join(stagedPluginRoot, ".claude-plugin", "plugin.json"), claudeManifest(bundle), stagedPluginRoot);
34359
+ writePrivateJson(path28__default.join(stagedPluginRoot, ".claude-plugin", "plugin.json"), claudeManifest(bundle), stagedPluginRoot);
34366
34360
  switch (bundle.source) {
34367
34361
  case "asset":
34368
34362
  if (options.cliId === "claude") {
34369
- ensurePrivateDir(path27__default.join(stagedPluginRoot, "agents"), stagedPluginRoot);
34363
+ ensurePrivateDir(path28__default.join(stagedPluginRoot, "agents"), stagedPluginRoot);
34370
34364
  }
34371
- ensurePrivateDir(path27__default.join(stagedPluginRoot, "skills"), stagedPluginRoot);
34372
- renderAssetPluginRoot(stagedPluginRoot, bundle, options);
34365
+ ensurePrivateDir(path28__default.join(stagedPluginRoot, "skills"), stagedPluginRoot);
34366
+ renderAssetPluginRoot(stagedPluginRoot, bundle, { ...options, installedPluginRoot: pluginRoot });
34373
34367
  break;
34374
34368
  }
34375
- writePrivateJson(path27__default.join(stagedPluginRoot, ".codex-plugin", "plugin.json"), codexManifest(bundle, stagedPluginRoot), stagedPluginRoot);
34376
- writePrivateJson(path27__default.join(stagedPluginRoot, ".cursor-plugin", "plugin.json"), cursorManifest(bundle, stagedPluginRoot), stagedPluginRoot);
34369
+ writePrivateJson(path28__default.join(stagedPluginRoot, ".codex-plugin", "plugin.json"), codexManifest(bundle, stagedPluginRoot), stagedPluginRoot);
34370
+ writePrivateJson(path28__default.join(stagedPluginRoot, ".cursor-plugin", "plugin.json"), cursorManifest(bundle, stagedPluginRoot), stagedPluginRoot);
34377
34371
  removePrivatePath(pluginRoot, parentRoot);
34378
34372
  renameSync(stagedPluginRoot, pluginRoot);
34379
34373
  } finally {
@@ -34385,13 +34379,13 @@ function renderMarketplaceRoot(target, bundles) {
34385
34379
  ensurePrivateDir(marketplaceRoot, marketplaceRoot);
34386
34380
  const stagedRoot = createStagingDir(marketplaceRoot);
34387
34381
  try {
34388
- writePrivateJson(path27__default.join(stagedRoot, ".agents", "plugins", "marketplace.json"), codexMarketplace(target, bundles), stagedRoot);
34389
- writePrivateJson(path27__default.join(stagedRoot, ".claude-plugin", "marketplace.json"), claudeMarketplace(target, bundles), stagedRoot);
34390
- writePrivateJson(path27__default.join(stagedRoot, ".cursor-plugin", "marketplace.json"), cursorMarketplace(target, bundles), stagedRoot);
34382
+ writePrivateJson(path28__default.join(stagedRoot, ".agents", "plugins", "marketplace.json"), codexMarketplace(target, bundles), stagedRoot);
34383
+ writePrivateJson(path28__default.join(stagedRoot, ".claude-plugin", "marketplace.json"), claudeMarketplace(target, bundles), stagedRoot);
34384
+ writePrivateJson(path28__default.join(stagedRoot, ".cursor-plugin", "marketplace.json"), cursorMarketplace(target, bundles), stagedRoot);
34391
34385
  pruneMarketplaceRoot(target);
34392
34386
  pruneStalePluginDirs(target, bundles);
34393
34387
  for (const entry of readdirSync(stagedRoot)) {
34394
- renameSync(path27__default.join(stagedRoot, entry), path27__default.join(marketplaceRoot, entry));
34388
+ renameSync(path28__default.join(stagedRoot, entry), path28__default.join(marketplaceRoot, entry));
34395
34389
  }
34396
34390
  } finally {
34397
34391
  cleanupPrivateRoot(stagedRoot, marketplaceRoot);
@@ -34399,22 +34393,22 @@ function renderMarketplaceRoot(target, bundles) {
34399
34393
  }
34400
34394
  function pruneMarketplaceRoot(target) {
34401
34395
  for (const entry of MARKETPLACE_PRUNE_ENTRIES) {
34402
- removePrivatePath(path27__default.join(target.root, entry), target.root);
34396
+ removePrivatePath(path28__default.join(target.root, entry), target.root);
34403
34397
  }
34404
34398
  }
34405
34399
  function pruneStalePluginDirs(target, bundles) {
34406
- const pluginsDir = path27__default.join(target.root, PLUGIN_BUNDLES_DIR_NAME);
34400
+ const pluginsDir = path28__default.join(target.root, PLUGIN_BUNDLES_DIR_NAME);
34407
34401
  if (!existsSync(pluginsDir)) return;
34408
34402
  const activeDirectoryNames = new Set(bundles.map((bundle) => bundle.directoryName));
34409
34403
  for (const entry of readdirSync(pluginsDir)) {
34410
34404
  if (activeDirectoryNames.has(entry)) continue;
34411
- removePrivatePath(path27__default.join(pluginsDir, entry), target.root);
34405
+ removePrivatePath(path28__default.join(pluginsDir, entry), target.root);
34412
34406
  }
34413
34407
  }
34414
34408
  function buildContentHash(target) {
34415
34409
  const hash2 = crypto4.createHash("sha256");
34416
34410
  for (const filePath of listRenderableFiles(target)) {
34417
- const relativePath = path27__default.relative(target.root, filePath);
34411
+ const relativePath = path28__default.relative(target.root, filePath);
34418
34412
  hash2.update(relativePath);
34419
34413
  hash2.update("\0");
34420
34414
  hash2.update(readFileSync(filePath));
@@ -34423,14 +34417,14 @@ function buildContentHash(target) {
34423
34417
  return hash2.digest("hex");
34424
34418
  }
34425
34419
  function createStagingDir(rootPath) {
34426
- const stageRoot = mkdtempSync(path27__default.join(rootPath, `.fleet-stage-${process.pid}-${Date.now()}-`));
34420
+ const stageRoot = mkdtempSync(path28__default.join(rootPath, `.fleet-stage-${process.pid}-${Date.now()}-`));
34427
34421
  return stageRoot;
34428
34422
  }
34429
34423
  function listRenderableFiles(target) {
34430
34424
  const files = [];
34431
34425
  const ancestorRealDirs = /* @__PURE__ */ new Set();
34432
34426
  for (const entry of MARKETPLACE_MANAGED_ENTRIES) {
34433
- const entryPath = path27__default.join(target.root, entry);
34427
+ const entryPath = path28__default.join(target.root, entry);
34434
34428
  if (!existsSync(entryPath)) continue;
34435
34429
  collectRenderableFiles(target.root, entryPath, files, ancestorRealDirs);
34436
34430
  }
@@ -34441,8 +34435,8 @@ function collectRenderableFiles(rootPath, currentPath, files, ancestorRealDirs)
34441
34435
  if (ancestorRealDirs.has(realDir)) return;
34442
34436
  ancestorRealDirs.add(realDir);
34443
34437
  for (const entry of readdirSync(currentPath)) {
34444
- const entryPath = path27__default.join(currentPath, entry);
34445
- const relativePath = path27__default.relative(rootPath, entryPath);
34438
+ const entryPath = path28__default.join(currentPath, entry);
34439
+ const relativePath = path28__default.relative(rootPath, entryPath);
34446
34440
  if (HASH_IGNORED_RELATIVE_PATHS.has(relativePath)) continue;
34447
34441
  const stat3 = lstatSync(entryPath);
34448
34442
  if (stat3.isSymbolicLink()) {
@@ -34519,7 +34513,7 @@ function cursorMarketplace(target, bundles) {
34519
34513
  };
34520
34514
  }
34521
34515
  function pluginRootForTarget(target, bundle) {
34522
- return path27__default.join(target.root, PLUGIN_BUNDLES_DIR_NAME, bundle.directoryName);
34516
+ return path28__default.join(target.root, PLUGIN_BUNDLES_DIR_NAME, bundle.directoryName);
34523
34517
  }
34524
34518
  function marketplacePluginPath(target, bundle) {
34525
34519
  return `./${PLUGIN_BUNDLES_DIR_NAME}/${bundle.directoryName}`;
@@ -34546,7 +34540,7 @@ function cursorManifestVersion(bundle, pluginRoot) {
34546
34540
  hash2.update(bundle.description);
34547
34541
  hash2.update("\0");
34548
34542
  for (const filePath of listCursorEffectivePluginFiles(pluginRoot)) {
34549
- const relativePath = path27__default.relative(pluginRoot, filePath);
34543
+ const relativePath = path28__default.relative(pluginRoot, filePath);
34550
34544
  hash2.update(relativePath);
34551
34545
  hash2.update("\0");
34552
34546
  hash2.update(readFileSync(filePath));
@@ -34561,7 +34555,7 @@ function codexManifestVersion(bundle, pluginRoot) {
34561
34555
  hash2.update(bundle.description);
34562
34556
  hash2.update("\0");
34563
34557
  for (const filePath of listCodexEffectivePluginFiles(pluginRoot)) {
34564
- const relativePath = path27__default.relative(pluginRoot, filePath);
34558
+ const relativePath = path28__default.relative(pluginRoot, filePath);
34565
34559
  hash2.update(relativePath);
34566
34560
  hash2.update("\0");
34567
34561
  hash2.update(readFileSync(filePath));
@@ -34570,7 +34564,7 @@ function codexManifestVersion(bundle, pluginRoot) {
34570
34564
  return `0.0.0+${hash2.digest("hex").slice(0, 12)}`;
34571
34565
  }
34572
34566
  function listCodexEffectivePluginFiles(pluginRoot) {
34573
- const skillsPath = path27__default.join(pluginRoot, "skills");
34567
+ const skillsPath = path28__default.join(pluginRoot, "skills");
34574
34568
  if (!existsSync(skillsPath)) return [];
34575
34569
  const files = [];
34576
34570
  collectRenderableFiles(pluginRoot, skillsPath, files, /* @__PURE__ */ new Set());
@@ -34578,8 +34572,8 @@ function listCodexEffectivePluginFiles(pluginRoot) {
34578
34572
  }
34579
34573
  function listCursorEffectivePluginFiles(pluginRoot) {
34580
34574
  const files = [];
34581
- for (const entry of ["skills", "rules", "hooks", "mcp.json"]) {
34582
- const entryPath = path27__default.join(pluginRoot, entry);
34575
+ for (const entry of ["skills", "hooks", "doctrine.md", "mcp.json"]) {
34576
+ const entryPath = path28__default.join(pluginRoot, entry);
34583
34577
  if (!existsSync(entryPath)) continue;
34584
34578
  const stat3 = lstatSync(entryPath);
34585
34579
  if (stat3.isFile()) {
@@ -34612,12 +34606,12 @@ async function injectAgentCliProfile(profile, options) {
34612
34606
  if (!capability.enabled) {
34613
34607
  return profile;
34614
34608
  }
34615
- const injectTone = options.enableMetaphor ?? false;
34609
+ const enableMetaphor = options.enableMetaphor ?? false;
34616
34610
  const endpoint = await options.dedicatedMcpSession.getEndpoint();
34617
34611
  const tokenLabel = options.mcpSessionLabel ?? `agent:${profile.id}:${crypto4.randomUUID()}`;
34618
34612
  const tokens = await options.dedicatedMcpSession.issueSessionToken({ cwd: profile.cwd, label: tokenLabel });
34619
34613
  const mcpServers = buildAgentCliMcpServerConfigs(endpoint.servers, tokens);
34620
- const doctrine = options.buildSystemPrompt(injectTone);
34614
+ const doctrine = options.buildSystemPrompt(enableMetaphor);
34621
34615
  const tempCleanups = [];
34622
34616
  try {
34623
34617
  const systemPromptFile = profile.id === "claude" ? writeSystemPromptFile(profile.id, doctrine, (cleanup2) => tempCleanups.push(cleanup2)) : void 0;
@@ -34652,8 +34646,8 @@ async function injectAgentCliProfile(profile, options) {
34652
34646
  env: { ...profile.env }
34653
34647
  }, requireCodexCommandRunner(options.codexCommandRunner), options.withMarketplaceLock, {
34654
34648
  homeMarketplaceName: FLEET_MARKETPLACE_NAME,
34655
- homeMarketplaceRoot: path27__default.join(options.pluginRootDir ?? options.dataDir ?? getFleetDataDir(), "marketplace"),
34656
- projectMarketplaceRoot: path27__default.join(profile.cwd, ".fleet")
34649
+ homeMarketplaceRoot: path28__default.join(options.pluginRootDir ?? options.dataDir ?? getFleetDataDir(), "marketplace"),
34650
+ projectMarketplaceRoot: path28__default.join(profile.cwd, ".fleet")
34657
34651
  });
34658
34652
  if (cleanupWarning !== void 0) {
34659
34653
  launchWarnings.push(`Deprecated Codex plugin cleanup failed: ${cleanupWarning}`);
@@ -34716,19 +34710,19 @@ function buildAgentCliMcpServerConfigs(endpoints, tokens) {
34716
34710
  });
34717
34711
  }
34718
34712
  function writeSystemPromptFile(cliId, systemPrompt, onCleanup) {
34719
- const tempDir = mkdtempSync(path27__default.join(os3__default.tmpdir(), `fleet-${cliId}-`));
34713
+ const tempDir = mkdtempSync(path28__default.join(os3__default.tmpdir(), `fleet-${cliId}-`));
34720
34714
  onCleanup(() => rmBestEffort(tempDir));
34721
- const filePath = path27__default.join(tempDir, "system-prompt.md");
34715
+ const filePath = path28__default.join(tempDir, "system-prompt.md");
34722
34716
  writeFileSync(filePath, systemPrompt, { encoding: "utf8", flag: "wx", mode: SYSTEM_PROMPT_FILE_MODE });
34723
34717
  chmodBestEffort2(filePath, SYSTEM_PROMPT_FILE_MODE);
34724
34718
  return filePath;
34725
34719
  }
34726
34720
  function writeCodexFleetProfile(env, doctrine, pluginKeys, hookExecs) {
34727
- const codexHome = env.CODEX_HOME ?? path27__default.join(env.HOME ?? os3__default.homedir(), ".codex");
34721
+ const codexHome = env.CODEX_HOME ?? path28__default.join(env.HOME ?? os3__default.homedir(), ".codex");
34728
34722
  mkdirSync(codexHome, { recursive: true });
34729
34723
  pruneLegacyCodexFleetProfiles(codexHome);
34730
34724
  const profileName = CODEX_FLEET_PROFILE_NAME;
34731
- const profilePath = path27__default.join(codexHome, CODEX_FLEET_PROFILE_FILE_NAME);
34725
+ const profilePath = path28__default.join(codexHome, CODEX_FLEET_PROFILE_FILE_NAME);
34732
34726
  const hookTrustState = readCodexFleetHookTrustState(profilePath);
34733
34727
  writeFileNoFollow2(profilePath, [
34734
34728
  CODEX_FLEET_PROFILE_MARKER,
@@ -34742,7 +34736,7 @@ function writeCodexFleetProfile(env, doctrine, pluginKeys, hookExecs) {
34742
34736
  "hooks = true",
34743
34737
  "",
34744
34738
  ...pluginKeys.flatMap((pluginKey) => [
34745
- `[plugins."${escapeTomlBasicString2(pluginKey)}"]`,
34739
+ `[plugins."${escapeTomlBasicString(pluginKey)}"]`,
34746
34740
  "enabled = true",
34747
34741
  ""
34748
34742
  ]),
@@ -34769,7 +34763,7 @@ function codexHooksConfig(hookExecs) {
34769
34763
  function codexHookHandlersInline(execs) {
34770
34764
  const handlers = execs.map((exec) => {
34771
34765
  const command = buildPosixShellCommand([exec.command, ...exec.args]);
34772
- return `{ type = "command", command = "${escapeTomlBasicString2(command)}" }`;
34766
+ return `{ type = "command", command = "${escapeTomlBasicString(command)}" }`;
34773
34767
  }).join(", ");
34774
34768
  return `[{ hooks = [${handlers}] }]`;
34775
34769
  }
@@ -34832,7 +34826,7 @@ function pruneLegacyCodexFleetProfiles(codexHome) {
34832
34826
  }
34833
34827
  for (const entry of entries) {
34834
34828
  if (!CODEX_LEGACY_FLEET_PROFILE_FILE_NAME_PATTERN.test(entry)) continue;
34835
- const filePath = path27__default.join(codexHome, entry);
34829
+ const filePath = path28__default.join(codexHome, entry);
34836
34830
  if (!isLegacyFleetCodexProfile(filePath)) continue;
34837
34831
  unlinkBestEffort2(filePath);
34838
34832
  }
@@ -34963,6 +34957,18 @@ function createFleetAgentRuntimeLifecycle(deps) {
34963
34957
  }
34964
34958
  };
34965
34959
  }
34960
+ function createAuthEnvResolver(globalOptionsService) {
34961
+ return async (cli) => {
34962
+ if (cli !== "codex" || !globalOptionsService) return {};
34963
+ try {
34964
+ const mode = globalOptionsService.load().codexLaunchMode;
34965
+ if (!mode) return {};
34966
+ return { CODEX_USE_ACP: mode === "app-server" ? "false" : "true" };
34967
+ } catch {
34968
+ return {};
34969
+ }
34970
+ };
34971
+ }
34966
34972
  function createFleetAgentRuntimeMcpServices() {
34967
34973
  const mcpRegistry = createMcpToolRegistry();
34968
34974
  const mcpToolSnapshotStore = createMcpToolSnapshotStore();
@@ -34992,7 +34998,7 @@ function registerExecutorPort(mcpRegistry, carrierRuntime, isActive) {
34992
34998
  }
34993
34999
  function registerFleetAgentRuntimeTools(mcpRegistry, carrierRuntime, deps) {
34994
35000
  registerAgentToolDefaults(mcpRegistry, carrierRuntime, {
34995
- authEnvResolver: async () => ({}),
35001
+ authEnvResolver: createAuthEnvResolver(deps.globalOptionsService),
34996
35002
  reservedExternalMcpServerIds: buildReservedExternalMcpServerIds(deps.reservedExternalMcpServerIds),
34997
35003
  workspaceChangeScanner: deps.workspaceChangeScanner
34998
35004
  });
@@ -35285,7 +35291,7 @@ function extractLegacyMarkdownWikiLinks(body, wikiDir, basePath) {
35285
35291
  }
35286
35292
  function resolveLegacyWikiTarget(target, wikiDir, basePath) {
35287
35293
  if (!target || target.startsWith("#")) return null;
35288
- if (path27__default.isAbsolute(target)) return null;
35294
+ if (path28__default.isAbsolute(target)) return null;
35289
35295
  if (/^[a-z][a-z0-9+.-]*:/i.test(target)) return null;
35290
35296
  const withoutFragment = target.split("#", 1)[0]?.split("?", 1)[0] ?? "";
35291
35297
  if (!withoutFragment.endsWith(".md")) return null;
@@ -35295,12 +35301,12 @@ function resolveLegacyWikiTarget(target, wikiDir, basePath) {
35295
35301
  } catch {
35296
35302
  return null;
35297
35303
  }
35298
- const resolved = path27__default.resolve(path27__default.dirname(basePath), decodedTarget);
35299
- const relative = path27__default.relative(wikiDir, resolved);
35300
- if (!relative || relative.startsWith("..") || path27__default.isAbsolute(relative)) return null;
35304
+ const resolved = path28__default.resolve(path28__default.dirname(basePath), decodedTarget);
35305
+ const relative = path28__default.relative(wikiDir, resolved);
35306
+ if (!relative || relative.startsWith("..") || path28__default.isAbsolute(relative)) return null;
35301
35307
  return {
35302
35308
  target,
35303
- entryId: path27__default.basename(relative, ".md")
35309
+ entryId: path28__default.basename(relative, ".md")
35304
35310
  };
35305
35311
  }
35306
35312
 
@@ -35560,18 +35566,18 @@ Always read \`schema/wiki-schema.md\` directly before composing or revising entr
35560
35566
  `;
35561
35567
  async function ensureWorkspaceSchema(paths) {
35562
35568
  await mkdir(paths.schemaDir, { recursive: true });
35563
- await writeDefaultFileIfMissing(path27__default.join(paths.schemaDir, WORKSPACE_SCHEMA_AGENTS_FILENAME), DEFAULT_WORKSPACE_SCHEMA_AGENTS);
35564
- await writeDefaultFileIfMissing(path27__default.join(paths.schemaDir, WORKSPACE_SCHEMA_FILENAME), DEFAULT_WORKSPACE_WIKI_SCHEMA);
35569
+ await writeDefaultFileIfMissing(path28__default.join(paths.schemaDir, WORKSPACE_SCHEMA_AGENTS_FILENAME), DEFAULT_WORKSPACE_SCHEMA_AGENTS);
35570
+ await writeDefaultFileIfMissing(path28__default.join(paths.schemaDir, WORKSPACE_SCHEMA_FILENAME), DEFAULT_WORKSPACE_WIKI_SCHEMA);
35565
35571
  await writeDefaultFileIfMissing(buildTemplatePath(paths, "prd"), DEFAULT_TEMPLATE_PRD);
35566
35572
  return readWorkspaceSchemaSummary(paths);
35567
35573
  }
35568
35574
  async function ensureWorkspaceDoctrine(paths) {
35569
35575
  await mkdir(paths.root, { recursive: true });
35570
- await writeDefaultFileIfMissing(path27__default.join(paths.root, WORKSPACE_KNOWLEDGE_AGENTS_FILENAME), DEFAULT_WORKSPACE_KNOWLEDGE_AGENTS);
35576
+ await writeDefaultFileIfMissing(path28__default.join(paths.root, WORKSPACE_KNOWLEDGE_AGENTS_FILENAME), DEFAULT_WORKSPACE_KNOWLEDGE_AGENTS);
35571
35577
  }
35572
35578
  async function readWorkspaceSchemaSummary(paths) {
35573
- const agentsPath = path27__default.join(paths.schemaDir, WORKSPACE_SCHEMA_AGENTS_FILENAME);
35574
- const wikiSchemaPath = path27__default.join(paths.schemaDir, WORKSPACE_SCHEMA_FILENAME);
35579
+ const agentsPath = path28__default.join(paths.schemaDir, WORKSPACE_SCHEMA_AGENTS_FILENAME);
35580
+ const wikiSchemaPath = path28__default.join(paths.schemaDir, WORKSPACE_SCHEMA_FILENAME);
35575
35581
  const wikiSchemaContent = await tryReadFile(wikiSchemaPath);
35576
35582
  const templates = await scanTemplates(paths);
35577
35583
  if (wikiSchemaContent === null) {
@@ -35610,7 +35616,7 @@ async function scanTemplates(paths) {
35610
35616
  if (!entry.name.startsWith(WORKSPACE_TEMPLATE_PREFIX) || !entry.name.endsWith(WORKSPACE_TEMPLATE_SUFFIX)) continue;
35611
35617
  const id = entry.name.slice(WORKSPACE_TEMPLATE_PREFIX.length, -WORKSPACE_TEMPLATE_SUFFIX.length);
35612
35618
  if (!id) continue;
35613
- const filePath = path27__default.join(paths.schemaDir, entry.name);
35619
+ const filePath = path28__default.join(paths.schemaDir, entry.name);
35614
35620
  try {
35615
35621
  const parsed = parseTemplateMarkdown(await readFile(filePath, "utf8"));
35616
35622
  templates.push({
@@ -35644,7 +35650,7 @@ async function validateTemplateCompliance(paths, templateId, body) {
35644
35650
  }
35645
35651
  }
35646
35652
  function inferTemplateIdFromTarget(target, knownTemplateIds) {
35647
- const basename = path27__default.basename(target, ".md");
35653
+ const basename = path28__default.basename(target, ".md");
35648
35654
  const ids = knownTemplateIds ?? DEFAULT_TEMPLATE_IDS;
35649
35655
  const sorted = [...ids].sort((a, b) => b.length - a.length);
35650
35656
  for (const id of sorted) {
@@ -35673,7 +35679,7 @@ function extractSchemaSummary(content) {
35673
35679
  return lines.find((line) => line.length > 0 && !line.startsWith("#")) ?? "Workspace schema is present.";
35674
35680
  }
35675
35681
  function buildTemplatePath(paths, id) {
35676
- return path27__default.join(paths.schemaDir, `${WORKSPACE_TEMPLATE_PREFIX}${id}${WORKSPACE_TEMPLATE_SUFFIX}`);
35682
+ return path28__default.join(paths.schemaDir, `${WORKSPACE_TEMPLATE_PREFIX}${id}${WORKSPACE_TEMPLATE_SUFFIX}`);
35677
35683
  }
35678
35684
  function parseTemplateMarkdown(content) {
35679
35685
  const normalized = content.replace(/\r\n/g, "\n");
@@ -35700,16 +35706,16 @@ function isAlreadyExistsError(error51) {
35700
35706
 
35701
35707
  // ../../packages/fleet-wiki/src/paths.ts
35702
35708
  function resolveMemoryPaths(cwd) {
35703
- const root = path27__default.join(cwd, KNOWLEDGE_ROOT_DIRNAME);
35709
+ const root = path28__default.join(cwd, KNOWLEDGE_ROOT_DIRNAME);
35704
35710
  return {
35705
35711
  root,
35706
- rawDir: path27__default.join(root, RAW_DIRNAME),
35707
- wikiDir: path27__default.join(root, WIKI_DIRNAME),
35708
- schemaDir: path27__default.join(root, SCHEMA_DIRNAME),
35709
- queueDir: path27__default.join(root, QUEUE_DIRNAME),
35710
- archiveDir: path27__default.join(root, ARCHIVE_DIRNAME),
35711
- conflictsDir: path27__default.join(root, CONFLICTS_DIRNAME),
35712
- indexFile: path27__default.join(root, INDEX_FILENAME)
35712
+ rawDir: path28__default.join(root, RAW_DIRNAME),
35713
+ wikiDir: path28__default.join(root, WIKI_DIRNAME),
35714
+ schemaDir: path28__default.join(root, SCHEMA_DIRNAME),
35715
+ queueDir: path28__default.join(root, QUEUE_DIRNAME),
35716
+ archiveDir: path28__default.join(root, ARCHIVE_DIRNAME),
35717
+ conflictsDir: path28__default.join(root, CONFLICTS_DIRNAME),
35718
+ indexFile: path28__default.join(root, INDEX_FILENAME)
35713
35719
  };
35714
35720
  }
35715
35721
  async function ensureMemoryRoot(paths) {
@@ -35724,10 +35730,10 @@ async function ensureMemoryRoot(paths) {
35724
35730
  await ensureWorkspaceDoctrine(paths);
35725
35731
  }
35726
35732
  function getIndexMarkdownFile(paths) {
35727
- return path27__default.join(paths.wikiDir, INDEX_MD_FILENAME);
35733
+ return path28__default.join(paths.wikiDir, INDEX_MD_FILENAME);
35728
35734
  }
35729
35735
  function getLogFile(paths) {
35730
- return path27__default.join(paths.root, LOG_MD_FILENAME);
35736
+ return path28__default.join(paths.root, LOG_MD_FILENAME);
35731
35737
  }
35732
35738
 
35733
35739
  // ../../packages/fleet-wiki/src/log.ts
@@ -35891,12 +35897,12 @@ async function readWikiEntry(id, paths) {
35891
35897
  const index = await loadIndex(paths);
35892
35898
  const indexed = index[id];
35893
35899
  if (indexed) {
35894
- const resolved = path27__default.resolve(paths.root, indexed.path);
35895
- const rel = path27__default.relative(paths.wikiDir, resolved);
35896
- if (!rel || rel.startsWith("..") || path27__default.isAbsolute(rel)) return null;
35900
+ const resolved = path28__default.resolve(paths.root, indexed.path);
35901
+ const rel = path28__default.relative(paths.wikiDir, resolved);
35902
+ if (!rel || rel.startsWith("..") || path28__default.isAbsolute(rel)) return null;
35897
35903
  return readMarkdownFile(resolved);
35898
35904
  }
35899
- const fallbackPath = path27__default.join(paths.wikiDir, `${id}.md`);
35905
+ const fallbackPath = path28__default.join(paths.wikiDir, `${id}.md`);
35900
35906
  if (await pathExists(fallbackPath)) {
35901
35907
  return readMarkdownFile(fallbackPath);
35902
35908
  }
@@ -35907,20 +35913,20 @@ async function readWikiEntry(id, paths) {
35907
35913
  async function writeWikiEntryAtTarget(entry, target, paths) {
35908
35914
  await ensureMemoryRoot(paths);
35909
35915
  assertSafeEntryId(entry.id);
35910
- const absoluteTarget = path27__default.resolve(paths.root, target);
35911
- const relativeTarget = path27__default.relative(paths.wikiDir, absoluteTarget);
35912
- if (!relativeTarget || relativeTarget.startsWith("..") || path27__default.isAbsolute(relativeTarget)) {
35916
+ const absoluteTarget = path28__default.resolve(paths.root, target);
35917
+ const relativeTarget = path28__default.relative(paths.wikiDir, absoluteTarget);
35918
+ if (!relativeTarget || relativeTarget.startsWith("..") || path28__default.isAbsolute(relativeTarget)) {
35913
35919
  throw new Error(`[fleet-wiki] wiki target escapes wiki/: ${target}`);
35914
35920
  }
35915
35921
  if (!absoluteTarget.endsWith(".md")) {
35916
35922
  throw new Error(`[fleet-wiki] wiki target must end with .md: ${target}`);
35917
35923
  }
35918
- if (path27__default.basename(absoluteTarget, ".md") !== entry.id) {
35924
+ if (path28__default.basename(absoluteTarget, ".md") !== entry.id) {
35919
35925
  throw new Error("wiki patch body id must match target filename");
35920
35926
  }
35921
- await mkdir(path27__default.dirname(absoluteTarget), { recursive: true });
35927
+ await mkdir(path28__default.dirname(absoluteTarget), { recursive: true });
35922
35928
  await writeMarkdownAtomic(absoluteTarget, serializeWikiEntry(entry), paths);
35923
- return path27__default.join("wiki", relativeTarget).replaceAll(path27__default.sep, "/");
35929
+ return path28__default.join("wiki", relativeTarget).replaceAll(path28__default.sep, "/");
35924
35930
  }
35925
35931
  async function writeRawSourceEntry(entry, paths) {
35926
35932
  await ensureMemoryRoot(paths);
@@ -35939,11 +35945,11 @@ async function writeRawSourceEntry(entry, paths) {
35939
35945
  },
35940
35946
  entry.content
35941
35947
  );
35942
- await writeMarkdownAtomic(path27__default.join(paths.root, relativePath), content, paths);
35948
+ await writeMarkdownAtomic(path28__default.join(paths.root, relativePath), content, paths);
35943
35949
  return relativePath;
35944
35950
  }
35945
35951
  async function readRawSourceEntry(rawSourceRef, paths) {
35946
- const absolutePath = path27__default.resolve(paths.root, rawSourceRef);
35952
+ const absolutePath = path28__default.resolve(paths.root, rawSourceRef);
35947
35953
  assertWithinRawDir(absolutePath, paths);
35948
35954
  const parsed = parseMarkdown(await readFile(absolutePath, "utf8"));
35949
35955
  return {
@@ -36134,8 +36140,8 @@ function computeContentHash(content) {
36134
36140
  return crypto4.createHash("sha256").update(content, "utf8").digest("hex").slice(0, 8);
36135
36141
  }
36136
36142
  function assertWithinRawDir(absolutePath, paths) {
36137
- const relative = path27__default.relative(paths.rawDir, absolutePath);
36138
- if (!relative || relative.startsWith("..") || path27__default.isAbsolute(relative)) {
36143
+ const relative = path28__default.relative(paths.rawDir, absolutePath);
36144
+ if (!relative || relative.startsWith("..") || path28__default.isAbsolute(relative)) {
36139
36145
  throw new Error(`[fleet-wiki] raw source ref escapes raw/: ${absolutePath}`);
36140
36146
  }
36141
36147
  }
@@ -36191,7 +36197,7 @@ function parseWikiEntry(content) {
36191
36197
  async function listWikiRecords(paths) {
36192
36198
  return listMarkdownEntriesRecursive(paths.wikiDir, paths, (content, filePath) => ({
36193
36199
  entry: parseWikiEntry(content),
36194
- path: path27__default.relative(paths.root, filePath).replaceAll(path27__default.sep, "/")
36200
+ path: path28__default.relative(paths.root, filePath).replaceAll(path28__default.sep, "/")
36195
36201
  }));
36196
36202
  }
36197
36203
  async function listMarkdownEntriesRecursive(dirPath, paths, parser) {
@@ -36204,7 +36210,7 @@ async function listMarkdownEntriesRecursive(dirPath, paths, parser) {
36204
36210
  }
36205
36211
  const sortedEntries = entries.sort((left, right) => left.name.localeCompare(right.name));
36206
36212
  for (const entry of sortedEntries) {
36207
- const filePath = path27__default.join(dirPath, entry.name);
36213
+ const filePath = path28__default.join(dirPath, entry.name);
36208
36214
  if (entry.isDirectory()) {
36209
36215
  items.push(...await listMarkdownEntriesRecursive(filePath, paths, parser));
36210
36216
  continue;
@@ -36342,8 +36348,8 @@ async function writeJsonAtomic(filePath, value, paths) {
36342
36348
  }
36343
36349
  async function writeAtomic(filePath, content, paths) {
36344
36350
  await ensureMemoryRoot(paths);
36345
- const tempPath = path27__default.join(
36346
- path27__default.dirname(filePath),
36351
+ const tempPath = path28__default.join(
36352
+ path28__default.dirname(filePath),
36347
36353
  `.tmp-${process.pid}-${Date.now()}-${crypto4.randomUUID()}-${os3__default.hostname()}`
36348
36354
  );
36349
36355
  await writeFile(tempPath, content, "utf8");
@@ -36390,7 +36396,7 @@ async function enhancedSearch(paths, options) {
36390
36396
  for (const entry of entries) {
36391
36397
  if (!index[entry.id]) {
36392
36398
  index[entry.id] = {
36393
- path: path27__default.join("wiki", `${entry.id}.md`),
36399
+ path: path28__default.join("wiki", `${entry.id}.md`),
36394
36400
  title: entry.title,
36395
36401
  tags: entry.tags,
36396
36402
  updated: entry.updated
@@ -36526,7 +36532,7 @@ function toEnhancedHit(entry, signals) {
36526
36532
  score: enhancedScore,
36527
36533
  reason: signals.legacyReason ?? "body",
36528
36534
  excerpt,
36529
- path: path27__default.join("wiki", `${entry.id}.md`),
36535
+ path: path28__default.join("wiki", `${entry.id}.md`),
36530
36536
  tags: entry.tags,
36531
36537
  updated: entry.updated,
36532
36538
  version: entry.version,
@@ -36722,7 +36728,7 @@ function toRankedHit(entry, reason, detail, graphBoost, backlinksById) {
36722
36728
  score: basePriority * 100 + statusPriority * 10 + graphScore + (detail.tagBoost ?? 0),
36723
36729
  reason,
36724
36730
  excerpt,
36725
- path: path27__default.join("wiki", `${entry.id}.md`),
36731
+ path: path28__default.join("wiki", `${entry.id}.md`),
36726
36732
  tags: entry.tags,
36727
36733
  updated: entry.updated,
36728
36734
  version: entry.version,
@@ -37150,15 +37156,15 @@ var PATCH_SET_DIRNAME = "_sets";
37150
37156
  var PATCH_SET_META_FILENAME = PATCH_META_FILENAME;
37151
37157
  function getPatchSetDir(paths, patchSetId) {
37152
37158
  assertSafePatchSetId(patchSetId);
37153
- const patchSetDir = path27__default.join(paths.queueDir, PATCH_SET_DIRNAME, patchSetId);
37154
- const relative = path27__default.relative(path27__default.join(paths.queueDir, PATCH_SET_DIRNAME), patchSetDir);
37155
- if (!relative || relative.startsWith("..") || path27__default.isAbsolute(relative)) {
37159
+ const patchSetDir = path28__default.join(paths.queueDir, PATCH_SET_DIRNAME, patchSetId);
37160
+ const relative = path28__default.relative(path28__default.join(paths.queueDir, PATCH_SET_DIRNAME), patchSetDir);
37161
+ if (!relative || relative.startsWith("..") || path28__default.isAbsolute(relative)) {
37156
37162
  throw new Error(`[fleet-wiki] patch set id escapes queue/_sets: ${patchSetId}`);
37157
37163
  }
37158
37164
  return patchSetDir;
37159
37165
  }
37160
37166
  function getPatchSetMetaFile(paths, patchSetId) {
37161
- return path27__default.join(getPatchSetDir(paths, patchSetId), PATCH_SET_META_FILENAME);
37167
+ return path28__default.join(getPatchSetDir(paths, patchSetId), PATCH_SET_META_FILENAME);
37162
37168
  }
37163
37169
  function buildPatchSetId(createdAt, sourceRef) {
37164
37170
  const compact = createdAt.replace(/[:.]/g, "-");
@@ -37191,7 +37197,7 @@ async function createConflict(input, paths) {
37191
37197
  await ensureMemoryRoot(paths);
37192
37198
  const now = input.now ?? /* @__PURE__ */ new Date();
37193
37199
  const conflictId = buildConflictId(now, input.wikiId, input.reason, input.proposed);
37194
- const conflictDir = path27__default.join(paths.conflictsDir, conflictId);
37200
+ const conflictDir = path28__default.join(paths.conflictsDir, conflictId);
37195
37201
  await mkdir(conflictDir, { recursive: true });
37196
37202
  const meta3 = {
37197
37203
  id: conflictId,
@@ -37211,13 +37217,13 @@ async function createConflict(input, paths) {
37211
37217
  currentHash: input.currentHash,
37212
37218
  warnings: input.warnings
37213
37219
  };
37214
- await writeJsonFile(path27__default.join(conflictDir, CONFLICT_META_FILENAME), meta3, paths);
37215
- await writePatchFile(path27__default.join(conflictDir, CONFLICT_PROPOSED_FILENAME), input.proposed, paths);
37220
+ await writeJsonFile(path28__default.join(conflictDir, CONFLICT_META_FILENAME), meta3, paths);
37221
+ await writePatchFile(path28__default.join(conflictDir, CONFLICT_PROPOSED_FILENAME), input.proposed, paths);
37216
37222
  if (input.current !== void 0) {
37217
- await writePatchFile(path27__default.join(conflictDir, CONFLICT_CURRENT_FILENAME), input.current, paths);
37223
+ await writePatchFile(path28__default.join(conflictDir, CONFLICT_CURRENT_FILENAME), input.current, paths);
37218
37224
  }
37219
37225
  if (input.rawSource !== void 0) {
37220
- await writePatchFile(path27__default.join(conflictDir, CONFLICT_RAW_SOURCE_FILENAME), input.rawSource, paths);
37226
+ await writePatchFile(path28__default.join(conflictDir, CONFLICT_RAW_SOURCE_FILENAME), input.rawSource, paths);
37221
37227
  }
37222
37228
  return {
37223
37229
  meta: meta3,
@@ -37231,7 +37237,7 @@ async function listConflicts(paths) {
37231
37237
  const metas = [];
37232
37238
  for (const id of ids) {
37233
37239
  try {
37234
- metas.push(await readJsonFile2(path27__default.join(paths.conflictsDir, id, CONFLICT_META_FILENAME)));
37240
+ metas.push(await readJsonFile2(path28__default.join(paths.conflictsDir, id, CONFLICT_META_FILENAME)));
37235
37241
  } catch {
37236
37242
  continue;
37237
37243
  }
@@ -37240,13 +37246,13 @@ async function listConflicts(paths) {
37240
37246
  }
37241
37247
  async function readConflict(conflictId, paths) {
37242
37248
  const conflictDir = resolveConflictDir(conflictId, paths);
37243
- const meta3 = await readJsonFile2(path27__default.join(conflictDir, CONFLICT_META_FILENAME));
37244
- const currentPath = path27__default.join(conflictDir, CONFLICT_CURRENT_FILENAME);
37245
- const rawSourcePath = path27__default.join(conflictDir, CONFLICT_RAW_SOURCE_FILENAME);
37249
+ const meta3 = await readJsonFile2(path28__default.join(conflictDir, CONFLICT_META_FILENAME));
37250
+ const currentPath = path28__default.join(conflictDir, CONFLICT_CURRENT_FILENAME);
37251
+ const rawSourcePath = path28__default.join(conflictDir, CONFLICT_RAW_SOURCE_FILENAME);
37246
37252
  return {
37247
37253
  meta: meta3,
37248
37254
  current: await pathExists(currentPath) ? await readPatchFile(currentPath) : void 0,
37249
- proposed: await readPatchFile(path27__default.join(conflictDir, CONFLICT_PROPOSED_FILENAME)),
37255
+ proposed: await readPatchFile(path28__default.join(conflictDir, CONFLICT_PROPOSED_FILENAME)),
37250
37256
  rawSource: await pathExists(rawSourcePath) ? await readPatchFile(rawSourcePath) : void 0
37251
37257
  };
37252
37258
  }
@@ -37265,9 +37271,9 @@ function sanitizeConflictToken(value) {
37265
37271
  return value.toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64) || "unknown";
37266
37272
  }
37267
37273
  function resolveConflictDir(conflictId, paths) {
37268
- const conflictDir = path27__default.resolve(paths.conflictsDir, conflictId);
37269
- const relative = path27__default.relative(paths.conflictsDir, conflictDir);
37270
- if (!relative || relative.startsWith("..") || path27__default.isAbsolute(relative)) {
37274
+ const conflictDir = path28__default.resolve(paths.conflictsDir, conflictId);
37275
+ const relative = path28__default.relative(paths.conflictsDir, conflictDir);
37276
+ if (!relative || relative.startsWith("..") || path28__default.isAbsolute(relative)) {
37271
37277
  throw new Error(`[fleet-wiki] conflict id escapes conflicts/: ${conflictId}`);
37272
37278
  }
37273
37279
  return conflictDir;
@@ -37305,11 +37311,11 @@ async function validatePatch(patch, paths) {
37305
37311
  if (!target || !summary || !proposer || !created) throw new Error("patch frontmatter is incomplete");
37306
37312
  if (summary.length > 120) throw new Error("patch summary exceeds 120 chars");
37307
37313
  assertCanonicalPatchTarget(target);
37308
- const absoluteTarget = path27__default.resolve(paths.root, target);
37309
- if (!absoluteTarget.startsWith(`${paths.root}${path27__default.sep}`) && absoluteTarget !== paths.root) {
37314
+ const absoluteTarget = path28__default.resolve(paths.root, target);
37315
+ if (!absoluteTarget.startsWith(`${paths.root}${path28__default.sep}`) && absoluteTarget !== paths.root) {
37310
37316
  throw new Error("patch target escapes wiki root");
37311
37317
  }
37312
- if (!absoluteTarget.startsWith(`${paths.wikiDir}${path27__default.sep}`)) throw new Error("wiki patch must target wiki/");
37318
+ if (!absoluteTarget.startsWith(`${paths.wikiDir}${path28__default.sep}`)) throw new Error("wiki patch must target wiki/");
37313
37319
  assertNoSymlinkPathComponents(target, paths);
37314
37320
  if (op === "create_wiki" && await pathExists(absoluteTarget)) {
37315
37321
  throw new Error(
@@ -37330,19 +37336,19 @@ async function applyPatch(patch, paths) {
37330
37336
  async function enqueuePatch(patch, paths, metaOverrides) {
37331
37337
  await ensureMemoryRoot(paths);
37332
37338
  const patchId = buildPatchId(patch.frontmatter.created, patch.frontmatter.summary, patch.frontmatter.target, patch.body);
37333
- const queueDir = path27__default.join(paths.queueDir, patchId);
37339
+ const queueDir = path28__default.join(paths.queueDir, patchId);
37334
37340
  if (await pathExists(queueDir)) {
37335
37341
  throw new Error(`[fleet-wiki] patch id collision: ${patchId} - this should never happen with target+body hashing`);
37336
37342
  }
37337
37343
  await mkdir(queueDir, { recursive: true });
37338
- await writePatchFile(path27__default.join(queueDir, PATCH_FILENAME), serializePatch(patch), paths);
37344
+ await writePatchFile(path28__default.join(queueDir, PATCH_FILENAME), serializePatch(patch), paths);
37339
37345
  const meta3 = {
37340
37346
  id: patchId,
37341
37347
  status: "pending",
37342
37348
  createdAt: patch.frontmatter.created,
37343
37349
  ...metaOverrides
37344
37350
  };
37345
- await writeJsonFile(path27__default.join(queueDir, PATCH_META_FILENAME), meta3, paths);
37351
+ await writeJsonFile(path28__default.join(queueDir, PATCH_META_FILENAME), meta3, paths);
37346
37352
  await appendLog(paths, "patch enqueued", {
37347
37353
  patch_id: patchId,
37348
37354
  patch_set_id: meta3.patch_set_id ?? null,
@@ -37360,7 +37366,7 @@ async function listQueue(paths) {
37360
37366
  for (const id of ids) {
37361
37367
  if (id === "_sets") continue;
37362
37368
  try {
37363
- const meta3 = await readJsonFile2(path27__default.join(paths.queueDir, id, PATCH_META_FILENAME));
37369
+ const meta3 = await readJsonFile2(path28__default.join(paths.queueDir, id, PATCH_META_FILENAME));
37364
37370
  results.push({ id, meta: meta3 });
37365
37371
  } catch {
37366
37372
  continue;
@@ -37385,17 +37391,17 @@ async function resolveQueueSelection(id, paths) {
37385
37391
  }
37386
37392
  async function showQueue(id, paths) {
37387
37393
  const selection = await resolveQueueSelection(id, paths);
37388
- const queueDir = path27__default.join(paths.queueDir, selection.id);
37389
- const patch = await parsePatch(await readPatchFile(path27__default.join(queueDir, PATCH_FILENAME)));
37390
- const meta3 = await readJsonFile2(path27__default.join(queueDir, PATCH_META_FILENAME));
37394
+ const queueDir = path28__default.join(paths.queueDir, selection.id);
37395
+ const patch = await parsePatch(await readPatchFile(path28__default.join(queueDir, PATCH_FILENAME)));
37396
+ const meta3 = await readJsonFile2(path28__default.join(queueDir, PATCH_META_FILENAME));
37391
37397
  return { patch, meta: meta3 };
37392
37398
  }
37393
37399
  async function rewriteQueuedPatch(id, paths, patch, meta3, expectedPatchHash) {
37394
37400
  assertSafeQueueId(id);
37395
37401
  return withPatchEditLock(paths, id, async () => {
37396
- const queueDir = path27__default.join(paths.queueDir, id);
37402
+ const queueDir = path28__default.join(paths.queueDir, id);
37397
37403
  if (expectedPatchHash !== void 0) {
37398
- const currentMarkdown = await readPatchFile(path27__default.join(queueDir, PATCH_FILENAME));
37404
+ const currentMarkdown = await readPatchFile(path28__default.join(queueDir, PATCH_FILENAME));
37399
37405
  const currentHash = computeContentHash(currentMarkdown);
37400
37406
  if (currentHash !== expectedPatchHash) {
37401
37407
  throw new Error(`[fleet-wiki] wiki_patch_edit stale base_patch_hash: expected ${currentHash}, got ${expectedPatchHash}`);
@@ -37404,8 +37410,8 @@ async function rewriteQueuedPatch(id, paths, patch, meta3, expectedPatchHash) {
37404
37410
  const patchMarkdown = serializePatch(patch);
37405
37411
  const patchHash = computeContentHash(patchMarkdown);
37406
37412
  const nextMeta = { ...meta3, lastEditHash: patchHash };
37407
- await writePatchFile(path27__default.join(queueDir, PATCH_FILENAME), patchMarkdown, paths);
37408
- await writeJsonFile(path27__default.join(queueDir, PATCH_META_FILENAME), nextMeta, paths);
37413
+ await writePatchFile(path28__default.join(queueDir, PATCH_FILENAME), patchMarkdown, paths);
37414
+ await writeJsonFile(path28__default.join(queueDir, PATCH_META_FILENAME), nextMeta, paths);
37409
37415
  return patchHash;
37410
37416
  });
37411
37417
  }
@@ -37429,8 +37435,8 @@ async function approvePatch(id, paths) {
37429
37435
  rawSourceRef: meta3.rawSourceRef,
37430
37436
  warnings: meta3.warnings
37431
37437
  });
37432
- const queueDir = path27__default.join(paths.queueDir, id);
37433
- await writeJsonFile(path27__default.join(queueDir, PATCH_META_FILENAME), {
37438
+ const queueDir = path28__default.join(paths.queueDir, id);
37439
+ await writeJsonFile(path28__default.join(queueDir, PATCH_META_FILENAME), {
37434
37440
  ...meta3,
37435
37441
  conflictId
37436
37442
  }, paths);
@@ -37466,7 +37472,7 @@ async function approvePatchSet(patchSetId, paths) {
37466
37472
  const failed = [];
37467
37473
  const missing = [];
37468
37474
  for (const patchId of patchSet.patchIds) {
37469
- const queueDir = path27__default.join(paths.queueDir, patchId);
37475
+ const queueDir = path28__default.join(paths.queueDir, patchId);
37470
37476
  if (!await pathExists(queueDir)) {
37471
37477
  missing.push(patchId);
37472
37478
  continue;
@@ -37532,7 +37538,7 @@ ${patch.body}`;
37532
37538
  }
37533
37539
  async function normalizeWikiEntryPatch(entry, target, paths) {
37534
37540
  assertSafeEntryId(entry.id);
37535
- if (entry.id !== path27__default.basename(target, ".md")) {
37541
+ if (entry.id !== path28__default.basename(target, ".md")) {
37536
37542
  throw new Error("wiki patch body id must match target filename");
37537
37543
  }
37538
37544
  const inlineRawSourceRef = extractInlineRawSourceRef(entry.body);
@@ -37575,9 +37581,9 @@ function buildPatchId(createdAt, summary, target, body) {
37575
37581
  }
37576
37582
  async function validatePatchBase(patch, meta3, paths) {
37577
37583
  if (patch.frontmatter.op !== "update_wiki" || !meta3?.baseVersion && !meta3?.baseHash) return;
37578
- const wikiId = path27__default.basename(patch.frontmatter.target, ".md");
37584
+ const wikiId = path28__default.basename(patch.frontmatter.target, ".md");
37579
37585
  const currentEntry = await readWikiEntry(wikiId, paths);
37580
- const currentPath = path27__default.join(paths.root, patch.frontmatter.target);
37586
+ const currentPath = path28__default.join(paths.root, patch.frontmatter.target);
37581
37587
  const currentMarkdown = await pathExists(currentPath) ? await readPatchFile(currentPath) : void 0;
37582
37588
  if (meta3.baseVersion !== void 0 && currentEntry?.version !== meta3.baseVersion) {
37583
37589
  throw new Error(
@@ -37636,17 +37642,17 @@ function assertCanonicalPatchTarget(target) {
37636
37642
  if (target.endsWith("/")) {
37637
37643
  throw new Error("patch target must not end with a slash");
37638
37644
  }
37639
- if (target.startsWith("/") || path27__default.posix.isAbsolute(target) || path27__default.win32.isAbsolute(target)) {
37645
+ if (target.startsWith("/") || path28__default.posix.isAbsolute(target) || path28__default.win32.isAbsolute(target)) {
37640
37646
  throw new Error("patch target must be relative");
37641
37647
  }
37642
- if (path27__default.posix.normalize(target) !== target) {
37648
+ if (path28__default.posix.normalize(target) !== target) {
37643
37649
  throw new Error("patch target must not contain dot segments or redundant separators");
37644
37650
  }
37645
37651
  }
37646
37652
  function canonicalApprovalLockKey(paths, target) {
37647
37653
  const wikiRoot = realpathSync(paths.wikiDir);
37648
- const relativeTarget = path27__default.posix.relative("wiki", target);
37649
- const targetPath = path27__default.join(wikiRoot, ...relativeTarget.split("/"));
37654
+ const relativeTarget = path28__default.posix.relative("wiki", target);
37655
+ const targetPath = path28__default.join(wikiRoot, ...relativeTarget.split("/"));
37650
37656
  return `${wikiRoot}\0${targetPath}`.toLowerCase();
37651
37657
  }
37652
37658
  function canonicalPatchEditLockKey(paths, patchId) {
@@ -37662,7 +37668,7 @@ function assertNoSymlinkPathComponents(target, paths) {
37662
37668
  throw error51;
37663
37669
  }
37664
37670
  for (const part of parts) {
37665
- current = path27__default.join(current, part);
37671
+ current = path28__default.join(current, part);
37666
37672
  try {
37667
37673
  if (lstatSync(current).isSymbolicLink()) {
37668
37674
  throw new Error("patch target must not include symlink path components");
@@ -37677,8 +37683,8 @@ function assertSafeRawSourceRef(rawSourceRef, paths) {
37677
37683
  if (!rawSourceRef.startsWith("raw/")) {
37678
37684
  throw new Error("raw source provenance must point into raw/");
37679
37685
  }
37680
- const absoluteRef = path27__default.resolve(paths.root, rawSourceRef);
37681
- if (!absoluteRef.startsWith(`${paths.rawDir}${path27__default.sep}`)) {
37686
+ const absoluteRef = path28__default.resolve(paths.root, rawSourceRef);
37687
+ if (!absoluteRef.startsWith(`${paths.rawDir}${path28__default.sep}`)) {
37682
37688
  throw new Error("raw source provenance must point into raw/");
37683
37689
  }
37684
37690
  }
@@ -37694,14 +37700,14 @@ function classifyPatchConflict(error51) {
37694
37700
  }
37695
37701
  async function recordPatchConflict(patch, paths, reason, options) {
37696
37702
  const now = /* @__PURE__ */ new Date();
37697
- const targetPath = path27__default.join(paths.root, patch.frontmatter.target);
37703
+ const targetPath = path28__default.join(paths.root, patch.frontmatter.target);
37698
37704
  const current = await pathExists(targetPath) ? await readPatchFile(targetPath) : void 0;
37699
37705
  const currentEntry = current ? parseStoredWikiEntry(current) : void 0;
37700
37706
  const proposedEntry = parsePatchBodyEntry(patch.body);
37701
37707
  const record2 = await createConflict({
37702
37708
  reason,
37703
37709
  target: patch.frontmatter.target,
37704
- wikiId: proposedEntry?.id ?? path27__default.basename(patch.frontmatter.target, ".md"),
37710
+ wikiId: proposedEntry?.id ?? path28__default.basename(patch.frontmatter.target, ".md"),
37705
37711
  title: proposedEntry?.title,
37706
37712
  proposer: patch.frontmatter.proposer,
37707
37713
  rawSourceRef: options?.rawSourceRef,
@@ -37797,11 +37803,11 @@ function parseInlineArray(value) {
37797
37803
  return inner.split(",").map((item) => item.trim().replace(/^"(.*)"$/, "$1"));
37798
37804
  }
37799
37805
  async function archiveQueueEntry(id, paths, meta3) {
37800
- const fromDir = path27__default.join(paths.queueDir, id);
37801
- const toDir = path27__default.join(paths.archiveDir, id);
37806
+ const fromDir = path28__default.join(paths.queueDir, id);
37807
+ const toDir = path28__default.join(paths.archiveDir, id);
37802
37808
  await removePath(toDir);
37803
37809
  await movePath(fromDir, toDir);
37804
- await writeJsonFile(path27__default.join(toDir, PATCH_META_FILENAME), meta3, paths);
37810
+ await writeJsonFile(path28__default.join(toDir, PATCH_META_FILENAME), meta3, paths);
37805
37811
  }
37806
37812
  function buildQueueIdHelp(prefix, availableIds) {
37807
37813
  if (availableIds.length === 0) {
@@ -38013,7 +38019,7 @@ async function resolveCompileSource(input, paths, now) {
38013
38019
  }
38014
38020
  async function buildCompileProposals(input, paths, now, resolvedSource) {
38015
38021
  const sourceTarget = `wiki/sources/${resolvedSource.sourcePageId}.md`;
38016
- const sourceExists = await pathExists(path27__default.join(paths.root, sourceTarget));
38022
+ const sourceExists = await pathExists(path28__default.join(paths.root, sourceTarget));
38017
38023
  const existingEntries = await listWiki(paths);
38018
38024
  const sourcePageTitle = resolvedSource.sourceTitle?.trim() || `Source ${resolvedSource.sourcePageId}`;
38019
38025
  const existingSourceEntry = existingEntries.find((entry) => entry.id === resolvedSource.sourcePageId);
@@ -38035,7 +38041,7 @@ async function buildCompileProposals(input, paths, now, resolvedSource) {
38035
38041
  target: sourceTarget,
38036
38042
  summary: truncateSummary(`Compile source page ${sourcePageTitle}`),
38037
38043
  entry: sourceEntry,
38038
- baseHash: sourceExists ? computeContentHash(await readPatchFile(path27__default.join(paths.root, sourceTarget))) : void 0,
38044
+ baseHash: sourceExists ? computeContentHash(await readPatchFile(path28__default.join(paths.root, sourceTarget))) : void 0,
38039
38045
  baseVersion: existingSourceEntry?.version
38040
38046
  }];
38041
38047
  const relatedCandidates = await discoverRelatedEntryCandidates(paths, resolvedSource.sourceContent, resolvedSource.sourceTitle);
@@ -38055,7 +38061,7 @@ async function buildCompileProposals(input, paths, now, resolvedSource) {
38055
38061
  rawSourceRefs: mergeRawSourceRefs(existing.rawSourceRefs, existing.rawSourceRef, { ref: resolvedSource.rawSourceRef }),
38056
38062
  body: appendSourceCompileNote(existing.body, resolvedSource.sourcePageId, resolvedSource.rawSourceRef)
38057
38063
  },
38058
- baseHash: computeContentHash(await readPatchFile(path27__default.join(paths.wikiDir, `${existing.id}.md`))),
38064
+ baseHash: computeContentHash(await readPatchFile(path28__default.join(paths.wikiDir, `${existing.id}.md`))),
38059
38065
  baseVersion: existing.version
38060
38066
  });
38061
38067
  }
@@ -38190,13 +38196,13 @@ async function readClaims(entryId, paths) {
38190
38196
  }
38191
38197
  }
38192
38198
  function getClaimsDir(paths) {
38193
- return path27__default.join(paths.wikiDir, CLAIMS_DIRNAME);
38199
+ return path28__default.join(paths.wikiDir, CLAIMS_DIRNAME);
38194
38200
  }
38195
38201
  function getClaimsFile(paths, entryId) {
38196
38202
  assertSafeEntryId(entryId);
38197
- const claimsFile = path27__default.join(getClaimsDir(paths), `${entryId}.json`);
38198
- const relative = path27__default.relative(getClaimsDir(paths), claimsFile);
38199
- if (!relative || relative.startsWith("..") || path27__default.isAbsolute(relative)) {
38203
+ const claimsFile = path28__default.join(getClaimsDir(paths), `${entryId}.json`);
38204
+ const relative = path28__default.relative(getClaimsDir(paths), claimsFile);
38205
+ if (!relative || relative.startsWith("..") || path28__default.isAbsolute(relative)) {
38200
38206
  throw new Error(`[fleet-wiki] claims sidecar escapes wiki/.claims: ${entryId}`);
38201
38207
  }
38202
38208
  return claimsFile;
@@ -38287,7 +38293,7 @@ function assertSafeClaimRawRef(ref) {
38287
38293
  if (!ref.startsWith("raw/")) {
38288
38294
  throw new Error(`claim sourceRef must point into raw/: ${ref}`);
38289
38295
  }
38290
- if (ref.includes("..") || path27__default.isAbsolute(ref)) {
38296
+ if (ref.includes("..") || path28__default.isAbsolute(ref)) {
38291
38297
  throw new Error(`claim sourceRef escapes raw/: ${ref}`);
38292
38298
  }
38293
38299
  }
@@ -38365,22 +38371,22 @@ async function runDryDock(paths, options = {}) {
38365
38371
  }
38366
38372
  for (const fileName of await listFileNames(paths.rawDir)) {
38367
38373
  if (!fileName.endsWith(".md")) continue;
38368
- const filePath = path27__default.join(paths.rawDir, fileName);
38374
+ const filePath = path28__default.join(paths.rawDir, fileName);
38369
38375
  issues.push(...safetyIssues(await readPatchFile(filePath), filePath));
38370
38376
  }
38371
38377
  for (const queueId of await listDirectoryNames(paths.queueDir)) {
38372
38378
  if (queueId === PATCH_SET_DIRNAME) continue;
38373
- const queueDir = path27__default.join(paths.queueDir, queueId);
38379
+ const queueDir = path28__default.join(paths.queueDir, queueId);
38374
38380
  try {
38375
- const patchContent = await readPatchFile(path27__default.join(queueDir, PATCH_FILENAME));
38376
- issues.push(...safetyIssues(patchContent, path27__default.join(queueDir, PATCH_FILENAME)));
38377
- await readJsonFile2(path27__default.join(queueDir, PATCH_META_FILENAME));
38381
+ const patchContent = await readPatchFile(path28__default.join(queueDir, PATCH_FILENAME));
38382
+ issues.push(...safetyIssues(patchContent, path28__default.join(queueDir, PATCH_FILENAME)));
38383
+ await readJsonFile2(path28__default.join(queueDir, PATCH_META_FILENAME));
38378
38384
  } catch {
38379
38385
  issues.push(issue2("malformed_queue", "error", "\uC190\uC0C1\uB41C queue \uC5D4\uD2B8\uB9AC", queueDir));
38380
38386
  }
38381
38387
  }
38382
- for (const patchSetId of await listDirectoryNames(path27__default.join(paths.queueDir, PATCH_SET_DIRNAME))) {
38383
- const patchSetMetaFile = path27__default.join(paths.queueDir, PATCH_SET_DIRNAME, patchSetId, PATCH_META_FILENAME);
38388
+ for (const patchSetId of await listDirectoryNames(path28__default.join(paths.queueDir, PATCH_SET_DIRNAME))) {
38389
+ const patchSetMetaFile = path28__default.join(paths.queueDir, PATCH_SET_DIRNAME, patchSetId, PATCH_META_FILENAME);
38384
38390
  let patchSet;
38385
38391
  try {
38386
38392
  patchSet = await readPatchSet(paths, patchSetId);
@@ -38389,8 +38395,8 @@ async function runDryDock(paths, options = {}) {
38389
38395
  continue;
38390
38396
  }
38391
38397
  for (const patchId of patchSet.patchIds) {
38392
- const queueMetaFile = path27__default.join(paths.queueDir, patchId, PATCH_META_FILENAME);
38393
- const archiveMetaFile = path27__default.join(paths.archiveDir, patchId, PATCH_META_FILENAME);
38398
+ const queueMetaFile = path28__default.join(paths.queueDir, patchId, PATCH_META_FILENAME);
38399
+ const archiveMetaFile = path28__default.join(paths.archiveDir, patchId, PATCH_META_FILENAME);
38394
38400
  if (!await pathExists(queueMetaFile) && !await pathExists(archiveMetaFile)) {
38395
38401
  issues.push(
38396
38402
  issue2(
@@ -38427,7 +38433,7 @@ async function runDryDock(paths, options = {}) {
38427
38433
  "conflict_unresolved",
38428
38434
  "warning",
38429
38435
  `\uBBF8\uD574\uACB0 conflict: ${conflict.reason} (${conflict.target})`,
38430
- path27__default.join(paths.conflictsDir, conflict.id, "meta.json")
38436
+ path28__default.join(paths.conflictsDir, conflict.id, "meta.json")
38431
38437
  )
38432
38438
  );
38433
38439
  }
@@ -38440,7 +38446,7 @@ async function runDryDock(paths, options = {}) {
38440
38446
  "unresolved_conflict",
38441
38447
  "warning",
38442
38448
  "\uC190\uC0C1\uB41C conflict \uC5D4\uD2B8\uB9AC",
38443
- path27__default.join(paths.conflictsDir, conflictId, "meta.json")
38449
+ path28__default.join(paths.conflictsDir, conflictId, "meta.json")
38444
38450
  )
38445
38451
  );
38446
38452
  }
@@ -38497,8 +38503,8 @@ async function claimIssues(paths, wikiIds) {
38497
38503
  const claimsDir = getClaimsDir(paths);
38498
38504
  for (const fileName of await listFileNames(claimsDir)) {
38499
38505
  if (!fileName.endsWith(".json")) continue;
38500
- const filePath = path27__default.join(claimsDir, fileName);
38501
- const entryIdFromFile = path27__default.basename(fileName, ".json");
38506
+ const filePath = path28__default.join(claimsDir, fileName);
38507
+ const entryIdFromFile = path28__default.basename(fileName, ".json");
38502
38508
  let raw;
38503
38509
  try {
38504
38510
  raw = await readJsonFile2(filePath);
@@ -38577,7 +38583,7 @@ function toSemanticEntry(filePath, frontmatter, body) {
38577
38583
  async function schemaIssues(paths) {
38578
38584
  const issues = [];
38579
38585
  const schema = await readWorkspaceSchemaSummary(paths);
38580
- const agentsPath = path27__default.join(paths.schemaDir, WORKSPACE_SCHEMA_AGENTS_FILENAME);
38586
+ const agentsPath = path28__default.join(paths.schemaDir, WORKSPACE_SCHEMA_AGENTS_FILENAME);
38581
38587
  if (!await pathExists(schema.wikiSchemaPath)) {
38582
38588
  issues.push(issue2("schema_missing", "warning", `Workspace schema file is missing: schema/${WORKSPACE_SCHEMA_FILENAME}`, schema.wikiSchemaPath));
38583
38589
  } else {
@@ -38964,7 +38970,7 @@ async function listWikiMarkdownFiles(dirPath) {
38964
38970
  const files = [];
38965
38971
  const sortedEntries = entries.sort((left, right) => left.name.localeCompare(right.name));
38966
38972
  for (const entry of sortedEntries) {
38967
- const filePath = path27__default.join(dirPath, entry.name);
38973
+ const filePath = path28__default.join(dirPath, entry.name);
38968
38974
  if (entry.isDirectory()) {
38969
38975
  files.push(...await listWikiMarkdownFiles(filePath));
38970
38976
  continue;
@@ -39048,7 +39054,7 @@ async function planIngest(input, paths, now) {
39048
39054
  const target = `wiki/${input.id}.md`;
39049
39055
  const proposer = input.proposer ?? "tool:wiki_ingest";
39050
39056
  const currentEntry = await readWikiEntry(input.id, paths);
39051
- const currentMarkdown = currentEntry ? await readPatchFile(path27__default.join(paths.wikiDir, `${input.id}.md`)) : void 0;
39057
+ const currentMarkdown = currentEntry ? await readPatchFile(path28__default.join(paths.wikiDir, `${input.id}.md`)) : void 0;
39052
39058
  const currentHash = currentMarkdown ? computeContentHash(currentMarkdown) : void 0;
39053
39059
  const rawSource = buildRawSourceEntry(input, now);
39054
39060
  await ensureWorkspaceSchema(paths);
@@ -39727,11 +39733,11 @@ async function editQueuedPatch(input, paths) {
39727
39733
  };
39728
39734
  }
39729
39735
  async function readQueuedPatchSnapshot(paths, patchId) {
39730
- const queueDir = path27__default.join(paths.queueDir, patchId);
39731
- const markdown = await readPatchFile(path27__default.join(queueDir, PATCH_FILENAME));
39736
+ const queueDir = path28__default.join(paths.queueDir, patchId);
39737
+ const markdown = await readPatchFile(path28__default.join(queueDir, PATCH_FILENAME));
39732
39738
  return {
39733
39739
  patch: await parsePatch(markdown),
39734
- meta: await readJsonFile2(path27__default.join(queueDir, PATCH_META_FILENAME)),
39740
+ meta: await readJsonFile2(path28__default.join(queueDir, PATCH_META_FILENAME)),
39735
39741
  patchHash: computeContentHash(markdown)
39736
39742
  };
39737
39743
  }
@@ -40493,7 +40499,7 @@ ${input.answer ?? ""}`)}`;
40493
40499
  assertSafeEntryId(targetId);
40494
40500
  const subdir = input.targetType === "synthesis" ? "synthesis" : "queries";
40495
40501
  const target = `wiki/${subdir}/${targetId}.md`;
40496
- const absoluteTarget = path27__default.join(paths.root, target);
40502
+ const absoluteTarget = path28__default.join(paths.root, target);
40497
40503
  const exists = await pathExists(absoluteTarget);
40498
40504
  const existingEntry = exists ? await readWikiEntry(targetId, paths) : null;
40499
40505
  if (exists && !existingEntry) {
@@ -40575,7 +40581,7 @@ function assertSafeRawRef(rawRef) {
40575
40581
  if (!rawRef.startsWith("raw/")) {
40576
40582
  throw new Error(`[fleet-wiki] wiki_query raw source ref must point into raw/: ${rawRef}`);
40577
40583
  }
40578
- if (rawRef.includes("..") || path27__default.isAbsolute(rawRef)) {
40584
+ if (rawRef.includes("..") || path28__default.isAbsolute(rawRef)) {
40579
40585
  throw new Error(`[fleet-wiki] wiki_query raw source ref escapes raw/: ${rawRef}`);
40580
40586
  }
40581
40587
  }
@@ -40694,7 +40700,7 @@ async function buildReadEntryResult(entry, paths, graph, input) {
40694
40700
  rawSourceRef: entry.rawSourceRef,
40695
40701
  rawSourceRefs,
40696
40702
  source: {
40697
- path: path27__default.join("wiki", `${entry.id}.md`),
40703
+ path: path28__default.join("wiki", `${entry.id}.md`),
40698
40704
  rawSourceRef: entry.rawSourceRef,
40699
40705
  rawSourceRefs
40700
40706
  },
@@ -40820,7 +40826,7 @@ function buildRelatedEntries(entry, graph) {
40820
40826
  deduped.set(candidate.id, {
40821
40827
  id: relatedEntry.id,
40822
40828
  title: relatedEntry.title,
40823
- path: path27__default.join("wiki", `${relatedEntry.id}.md`),
40829
+ path: path28__default.join("wiki", `${relatedEntry.id}.md`),
40824
40830
  reason: candidate.reason
40825
40831
  });
40826
40832
  }
@@ -41120,9 +41126,58 @@ function createPluginTerminalTicketRegistry(deps = {}) {
41120
41126
  }
41121
41127
  return { ttlMs, issue: issue3, consume, prune };
41122
41128
  }
41129
+ var FLEET_CONSOLE_PACKAGE_NAME = "@dotobokuri/fleet-console";
41130
+ function resolveConsolePackageRequire(currentFile, fallback) {
41131
+ return findConsolePackageRequire(currentFile) ?? fallback;
41132
+ }
41133
+ function findConsolePackageRequire(currentFile) {
41134
+ const explicitRoot = process.env.FLEET_CONSOLE_PACKAGE_ROOT;
41135
+ if (explicitRoot) {
41136
+ const explicitPackageJson = path28__default.join(explicitRoot, "package.json");
41137
+ if (isFleetConsolePackage(explicitPackageJson)) return createRequire(explicitPackageJson);
41138
+ }
41139
+ let dir = path28__default.dirname(currentFile);
41140
+ while (true) {
41141
+ const packageJson = path28__default.join(dir, "package.json");
41142
+ if (isFleetConsolePackage(packageJson)) return createRequire(packageJson);
41143
+ const nestedConsolePackage = path28__default.join(dir, "runtime", "fleet-console", "package.json");
41144
+ if (isFleetConsolePackage(nestedConsolePackage)) return createRequire(nestedConsolePackage);
41145
+ const siblingConsolePackage = path28__default.join(dir, "..", "..", "fleet-console", "package.json");
41146
+ if (isFleetConsolePackage(siblingConsolePackage)) return createRequire(siblingConsolePackage);
41147
+ const parent = path28__default.dirname(dir);
41148
+ if (parent === dir) return null;
41149
+ dir = parent;
41150
+ }
41151
+ }
41152
+ function isFleetConsolePackage(packageJson) {
41153
+ if (!existsSync(packageJson)) return false;
41154
+ try {
41155
+ const manifest = JSON.parse(readFileSync(packageJson, "utf8"));
41156
+ return manifest.name === FLEET_CONSOLE_PACKAGE_NAME;
41157
+ } catch {
41158
+ return false;
41159
+ }
41160
+ }
41161
+
41162
+ // ../fleet-plugins/terminal/server/shared/launch-env.ts
41163
+ var CONSOLE_INTERNAL_ENV_KEYS = [
41164
+ "FLEET_CONSOLE_OWNER_ID",
41165
+ "FLEET_CONSOLE_OWNER_KIND",
41166
+ "FLEET_CONSOLE_PROTOCOL_VERSION",
41167
+ "FLEET_CONSOLE_RESOURCE_ROOT",
41168
+ "FLEET_CONSOLE_DESKTOP_DEVELOPMENT",
41169
+ "FLEET_CONSOLE_DESKTOP_VERSION",
41170
+ "FLEET_CONSOLE_PACKAGE_ROOT"
41171
+ ];
41172
+ function stripConsoleInternalEnv(env) {
41173
+ const next = { ...env };
41174
+ for (const key of CONSOLE_INTERNAL_ENV_KEYS) delete next[key];
41175
+ return next;
41176
+ }
41177
+
41178
+ // ../fleet-plugins/terminal/server/shared/pty.ts
41123
41179
  var DEFAULT_TERMINAL_CWD_FALLBACK = os3__default.homedir;
41124
41180
  var TERMINAL_TERM = "xterm-256color";
41125
- var FLEET_CONSOLE_PACKAGE_NAME = "@dotobokuri/fleet-console";
41126
41181
  var require2 = createRequire(import.meta.url);
41127
41182
  function createShellTerminalLaunchResolver(deps = {}) {
41128
41183
  const baseCwd = deps.cwd ?? process5.cwd();
@@ -41158,31 +41213,7 @@ function loadNodePty() {
41158
41213
  return loadNodePtyRequire(fileURLToPath(import.meta.url))("node-pty");
41159
41214
  }
41160
41215
  function loadNodePtyRequire(currentFile) {
41161
- const consolePackageRequire = findConsolePackageRequire(currentFile);
41162
- return consolePackageRequire ?? require2;
41163
- }
41164
- function findConsolePackageRequire(currentFile) {
41165
- let dir = path27__default.dirname(currentFile);
41166
- while (true) {
41167
- const packageJson = path27__default.join(dir, "package.json");
41168
- if (isFleetConsolePackage(packageJson)) return createRequire(packageJson);
41169
- const nestedConsolePackage = path27__default.join(dir, "runtime", "fleet-console", "package.json");
41170
- if (isFleetConsolePackage(nestedConsolePackage)) return createRequire(nestedConsolePackage);
41171
- const siblingConsolePackage = path27__default.join(dir, "..", "..", "fleet-console", "package.json");
41172
- if (isFleetConsolePackage(siblingConsolePackage)) return createRequire(siblingConsolePackage);
41173
- const parent = path27__default.dirname(dir);
41174
- if (parent === dir) return null;
41175
- dir = parent;
41176
- }
41177
- }
41178
- function isFleetConsolePackage(packageJson) {
41179
- if (!existsSync(packageJson)) return false;
41180
- try {
41181
- const manifest = JSON.parse(readFileSync(packageJson, "utf8"));
41182
- return manifest.name === FLEET_CONSOLE_PACKAGE_NAME;
41183
- } catch {
41184
- return false;
41185
- }
41216
+ return resolveConsolePackageRequire(currentFile, require2);
41186
41217
  }
41187
41218
  function resolveUserShell(env, platform) {
41188
41219
  if (env.SHELL) return env.SHELL;
@@ -41201,7 +41232,7 @@ function resolveWindowsLaunchBinary(bin, args, env, platform, label) {
41201
41232
  }
41202
41233
  function buildShellLaunchEnv(env) {
41203
41234
  return {
41204
- ...env,
41235
+ ...stripConsoleInternalEnv(env),
41205
41236
  TERM: TERMINAL_TERM
41206
41237
  };
41207
41238
  }
@@ -41542,7 +41573,7 @@ function isResizeFrame(value) {
41542
41573
  const rows = frame.rows;
41543
41574
  return frame.type === "resize" && typeof cols === "number" && typeof rows === "number" && Number.isInteger(cols) && Number.isInteger(rows) && cols > 0 && rows > 0;
41544
41575
  }
41545
- var require3 = createRequire(import.meta.url);
41576
+ var require3 = resolveConsolePackageRequire(fileURLToPath(import.meta.url), createRequire(import.meta.url));
41546
41577
  function createPluginTerminalUpgradeHandler(deps) {
41547
41578
  let wsServer = null;
41548
41579
  const handleUpgrade = ({ req, socket, head }) => {
@@ -41955,7 +41986,7 @@ function captureSession(options) {
41955
41986
  function readProviderSessionCapture(fleetSessionId, deps = {}) {
41956
41987
  if (!isSafeCaptureId(fleetSessionId)) return null;
41957
41988
  const capturesDir = deps.capturesDir ?? defaultCapturePaths().capturesDir;
41958
- const filePath = path27__default.join(capturesDir, `${fleetSessionId}.json`);
41989
+ const filePath = path28__default.join(capturesDir, `${fleetSessionId}.json`);
41959
41990
  try {
41960
41991
  const parsed = JSON.parse(fs2__default.readFileSync(filePath, "utf8"));
41961
41992
  return sanitizeProviderSession(parsed);
@@ -41967,7 +41998,7 @@ function unlinkProviderSessionCapture(fleetSessionId, deps = {}) {
41967
41998
  if (!isSafeCaptureId(fleetSessionId)) return false;
41968
41999
  const capturesDir = deps.capturesDir ?? defaultCapturePaths().capturesDir;
41969
42000
  try {
41970
- fs2__default.unlinkSync(path27__default.join(capturesDir, `${fleetSessionId}.json`));
42001
+ fs2__default.unlinkSync(path28__default.join(capturesDir, `${fleetSessionId}.json`));
41971
42002
  return true;
41972
42003
  } catch {
41973
42004
  return false;
@@ -41979,8 +42010,8 @@ function captureSessionStrict(options) {
41979
42010
  const input = parseHookInput(options.input ?? "");
41980
42011
  const providerSession = toProviderSession(provider, input, options.now ?? (() => /* @__PURE__ */ new Date()));
41981
42012
  const capturesDir = (options.paths ?? defaultCapturePaths()).capturesDir;
41982
- const finalPath = path27__default.join(capturesDir, `${fleetSessionId}.json`);
41983
- const tempPath = path27__default.join(capturesDir, `${CAPTURE_TEMP_PREFIX}${fleetSessionId}.${process5.pid}.${Date.now()}.tmp`);
42013
+ const finalPath = path28__default.join(capturesDir, `${fleetSessionId}.json`);
42014
+ const tempPath = path28__default.join(capturesDir, `${CAPTURE_TEMP_PREFIX}${fleetSessionId}.${process5.pid}.${Date.now()}.tmp`);
41984
42015
  fs2__default.mkdirSync(capturesDir, { recursive: true, mode: 448 });
41985
42016
  fs2__default.writeFileSync(tempPath, `${JSON.stringify(providerSession, null, 2)}
41986
42017
  `, { mode: 384 });
@@ -41994,7 +42025,7 @@ function parseProvider(value) {
41994
42025
  function readFleetSessionId(env) {
41995
42026
  const value = env.FLEET_CONSOLE_SESSION_ID;
41996
42027
  if (!value) throw new Error("missing_fleet_session_id");
41997
- if (path27__default.basename(value) !== value || value.includes(path27__default.sep) || value.includes(path27__default.posix.sep)) {
42028
+ if (path28__default.basename(value) !== value || value.includes(path28__default.sep) || value.includes(path28__default.posix.sep)) {
41998
42029
  throw new Error("invalid_fleet_session_id");
41999
42030
  }
42000
42031
  return value;
@@ -42039,10 +42070,10 @@ function isProvider(value) {
42039
42070
  return value === "claude" || value === "codex" || value === "cursor";
42040
42071
  }
42041
42072
  function isSafeCaptureId(value) {
42042
- return value.length > 0 && path27__default.basename(value) === value && !value.includes(path27__default.sep) && !value.includes(path27__default.posix.sep);
42073
+ return value.length > 0 && path28__default.basename(value) === value && !value.includes(path28__default.sep) && !value.includes(path28__default.posix.sep);
42043
42074
  }
42044
42075
  function defaultCapturePaths() {
42045
- return { capturesDir: path27__default.join(getFleetDataDir(), CONSOLE_DATA_DIR_NAME, CONSOLE_CAPTURES_DIR_NAME) };
42076
+ return { capturesDir: path28__default.join(getFleetDataDir(), CONSOLE_DATA_DIR_NAME, CONSOLE_CAPTURES_DIR_NAME) };
42046
42077
  }
42047
42078
  var JAVASCRIPT_ENTRY_EXTENSIONS = /* @__PURE__ */ new Set([".cjs", ".js", ".mjs"]);
42048
42079
  var TYPESCRIPT_ENTRY_EXTENSIONS = /* @__PURE__ */ new Set([".cts", ".mts", ".ts", ".tsx"]);
@@ -42057,7 +42088,7 @@ function buildConsoleAutoNameHookCommand(entry) {
42057
42088
  return buildConsoleCliHookExec(entry, ["hook", "auto-name"]);
42058
42089
  }
42059
42090
  function buildConsoleCaptureHookCommand(entry, cliId) {
42060
- const extension = path27__default.extname(entry.entryPath);
42091
+ const extension = path28__default.extname(entry.entryPath);
42061
42092
  if (JAVASCRIPT_ENTRY_EXTENSIONS.has(extension)) {
42062
42093
  return createSessionCaptureHookExec({
42063
42094
  entryPath: entry.entryPath,
@@ -42093,11 +42124,11 @@ function runCodexCommand(command) {
42093
42124
  }
42094
42125
  function withConsoleMarketplaceLock(target, fn) {
42095
42126
  const lockDir = `${target}${MARKETPLACE_LOCK_DIR_SUFFIX}`;
42096
- mkdirSync(path27__default.dirname(lockDir), { recursive: true });
42127
+ mkdirSync(path28__default.dirname(lockDir), { recursive: true });
42097
42128
  return withDirectoryLock({ lockDir }, fn);
42098
42129
  }
42099
42130
  function buildConsoleCliHookExec(entry, trailingArgs) {
42100
- const extension = path27__default.extname(entry.entryPath);
42131
+ const extension = path28__default.extname(entry.entryPath);
42101
42132
  if (JAVASCRIPT_ENTRY_EXTENSIONS.has(extension)) {
42102
42133
  return {
42103
42134
  command: entry.execPath,
@@ -42181,7 +42212,7 @@ function resolveHookEntryPath(candidate) {
42181
42212
  return CONSOLE_ENTRY_PATH;
42182
42213
  }
42183
42214
  function hasHookEntryExtension(entryPath) {
42184
- return HOOK_ENTRY_EXTENSIONS.has(path27__default.extname(entryPath));
42215
+ return HOOK_ENTRY_EXTENSIONS.has(path28__default.extname(entryPath));
42185
42216
  }
42186
42217
  async function createAgentCliLaunchSpec(options) {
42187
42218
  const cleanupStack = [];
@@ -42275,7 +42306,7 @@ function parseTerminalCommand(command) {
42275
42306
  }
42276
42307
  function buildLaunchEnv(env, cwd, sessionId) {
42277
42308
  return {
42278
- ...env,
42309
+ ...stripConsoleInternalEnv(env),
42279
42310
  ...sessionId ? { FLEET_CONSOLE_SESSION_ID: sessionId, INIT_CWD: cwd, PWD: cwd } : {},
42280
42311
  TERM: TERMINAL_TERM2
42281
42312
  };
@@ -42403,7 +42434,7 @@ function createConsoleObservabilityStore(deps = {}) {
42403
42434
  return terminalSessionsById.get(sessionId)?.cwd ?? workspacesByCliRunId.get(sessionId)?.session.cwd ?? null;
42404
42435
  }
42405
42436
  function createPendingTerminalSession(input) {
42406
- if (!path27__default.isAbsolute(input.cwd)) throw new Error("Terminal session cwd must be absolute");
42437
+ if (!path28__default.isAbsolute(input.cwd)) throw new Error("Terminal session cwd must be absolute");
42407
42438
  const createdAt = input.createdAt ?? now();
42408
42439
  const canonicalCwd = canonicalizeTheaterPath(input.cwd);
42409
42440
  const theaterId = workspaceHash(canonicalCwd);
@@ -42411,7 +42442,7 @@ function createConsoleObservabilityStore(deps = {}) {
42411
42442
  sessionId: input.sessionId,
42412
42443
  cwd: input.cwd,
42413
42444
  canonicalCwd,
42414
- cwdLabel: path27__default.basename(input.cwd) || input.cwd,
42445
+ cwdLabel: path28__default.basename(input.cwd) || input.cwd,
42415
42446
  cliId: input.cliId,
42416
42447
  createdAt,
42417
42448
  theaterId,
@@ -42426,7 +42457,7 @@ function createConsoleObservabilityStore(deps = {}) {
42426
42457
  sessionId: operation.sessionId,
42427
42458
  cwd: operation.cwd,
42428
42459
  canonicalCwd: canonicalizeTheaterPath(operation.cwd),
42429
- cwdLabel: path27__default.basename(operation.cwd) || operation.cwd,
42460
+ cwdLabel: path28__default.basename(operation.cwd) || operation.cwd,
42430
42461
  label: operation.label,
42431
42462
  labelSource: operation.labelSource,
42432
42463
  cliId: operation.cliId,
@@ -42506,13 +42537,15 @@ function createConsoleObservabilityStore(deps = {}) {
42506
42537
  const session = terminalSessionsById.get(sessionId);
42507
42538
  if (!session) return null;
42508
42539
  const effectiveSource = session.labelSource ?? (session.label ? "user" : void 0);
42509
- if (effectiveSource === "user") {
42540
+ if (effectiveSource === "user" || session.autoNamePromptSeen) {
42510
42541
  return { session: toTerminalSessionInfo(session), renamed: false };
42511
42542
  }
42512
42543
  const next = label?.trim().slice(0, 200) ?? "";
42513
- if (next.length === 0 || next === session.label) {
42544
+ if (next.length === 0) {
42514
42545
  return { session: toTerminalSessionInfo(session), renamed: false };
42515
42546
  }
42547
+ session.autoNamePromptSeen = true;
42548
+ if (next === session.label) return { session: toTerminalSessionInfo(session), renamed: false };
42516
42549
  session.label = next;
42517
42550
  session.labelSource = "auto";
42518
42551
  return { session: toTerminalSessionInfo(session), renamed: true };
@@ -42653,7 +42686,7 @@ function defaultWorkspaceHash(canonicalCwd) {
42653
42686
  return crypto4.createHash("sha256").update(canonicalCwd).digest("hex").slice(0, 12);
42654
42687
  }
42655
42688
  function defaultCanonicalizeTheaterPath(cwd) {
42656
- const resolved = path27__default.resolve(cwd);
42689
+ const resolved = path28__default.resolve(cwd);
42657
42690
  try {
42658
42691
  return fs2__default.realpathSync.native(resolved);
42659
42692
  } catch {
@@ -42893,6 +42926,7 @@ function buildAgentLaunchKindBackfillPatch(operation) {
42893
42926
  }
42894
42927
  function createAgentApi(ctx, terminalRuntime, deps) {
42895
42928
  const runtime = createFleetAgentRuntimeLifecycle({
42929
+ globalOptionsService: deps.globalOptionsService,
42896
42930
  onMcpServerStartError: (error51) => {
42897
42931
  console.error("[fleet-console] Failed to start MCP server", error51);
42898
42932
  },
@@ -42947,23 +42981,23 @@ function createAgentApi(ctx, terminalRuntime, deps) {
42947
42981
  backfillAgentOperationLaunchKinds();
42948
42982
  rehydrateDormantAgentOperations();
42949
42983
  async function handle({ req, res, pathname }) {
42950
- const path42 = pathname.slice(`${ctx.basePath}/agent`.length) || "/";
42951
- if (path42 === "/state") {
42984
+ const path43 = pathname.slice(`${ctx.basePath}/agent`.length) || "/";
42985
+ if (path43 === "/state") {
42952
42986
  if (req.method !== "GET") return methodNotAllowed(res);
42953
42987
  ctx.host.http.writeJson(res, 200, { agentClis: await buildAgentCliLaunchMetadata() });
42954
42988
  return true;
42955
42989
  }
42956
- if (path42 === "/agent-cli/state") {
42990
+ if (path43 === "/agent-cli/state") {
42957
42991
  if (req.method !== "GET") return methodNotAllowed(res);
42958
42992
  ctx.host.http.writeJson(res, 200, { clis: await detector.detect() });
42959
42993
  return true;
42960
42994
  }
42961
- if (path42 === "/tenants") {
42995
+ if (path43 === "/tenants") {
42962
42996
  if (req.method !== "GET") return methodNotAllowed(res);
42963
42997
  ctx.host.http.writeJson(res, 200, { tenants: observability.listWorkspaces() });
42964
42998
  return true;
42965
42999
  }
42966
- if (path42 === "/jobs") {
43000
+ if (path43 === "/jobs") {
42967
43001
  if (req.method !== "GET") return methodNotAllowed(res);
42968
43002
  const requestedTenantId = new URL(req.url ?? "/", "http://127.0.0.1").searchParams.get("tenant");
42969
43003
  const visible = requestedTenantId ? observability.listWorkspaces().filter((workspace) => workspace.tenantId === requestedTenantId) : observability.listWorkspaces();
@@ -42974,7 +43008,7 @@ function createAgentApi(ctx, terminalRuntime, deps) {
42974
43008
  ctx.host.http.writeJson(res, 200, { tenants: visible.map((workspace) => ({ tenantId: workspace.tenantId, tenantLabel: workspace.tenantLabel, jobs: observability.listJobs(workspace.tenantId), truncation: observability.getTruncation(workspace.tenantId) })) });
42975
43009
  return true;
42976
43010
  }
42977
- if (path42 === "/events") {
43011
+ if (path43 === "/events") {
42978
43012
  if (req.method !== "GET") return methodNotAllowed(res);
42979
43013
  const requestedTenantId = new URL(req.url ?? "/", "http://127.0.0.1").searchParams.get("tenant");
42980
43014
  const visible = requestedTenantId ? observability.listWorkspaces().filter((workspace) => workspace.tenantId === requestedTenantId) : observability.listWorkspaces();
@@ -42985,11 +43019,11 @@ function createAgentApi(ctx, terminalRuntime, deps) {
42985
43019
  writeAggregateObserverEvents(req, res, visible, observability, (tenantId) => observability.getWorkspace(tenantId), { subscribeAll: true });
42986
43020
  return true;
42987
43021
  }
42988
- if (path42 === "/sessions") return handleSessions(req, res);
42989
- if (path42 === "/capture") return handleCapture(req, res, "");
42990
- const sessionMatch = path42.match(/^\/sessions\/([^/]+)(?:\/([^/]+))?$/);
43022
+ if (path43 === "/sessions") return handleSessions(req, res);
43023
+ if (path43 === "/capture") return handleCapture(req, res, "");
43024
+ const sessionMatch = path43.match(/^\/sessions\/([^/]+)(?:\/([^/]+))?$/);
42991
43025
  if (sessionMatch) return handleSessionItem(req, res, decodeURIComponent(sessionMatch[1] ?? ""), sessionMatch[2] ?? "");
42992
- if (path42 === "/ticket") {
43026
+ if (path43 === "/ticket") {
42993
43027
  if (req.method !== "POST") return methodNotAllowed(res);
42994
43028
  if (!ctx.host.security.isTerminalAuthorized(req)) {
42995
43029
  ctx.host.http.writeJson(res, 401, { error: "Unauthorized" });
@@ -43083,7 +43117,7 @@ function createAgentApi(ctx, terminalRuntime, deps) {
43083
43117
  theaterId,
43084
43118
  type: AGENT_OPERATION_TYPE,
43085
43119
  pluginId: ctx.pluginId,
43086
- title: session.label ?? path27__default.basename(cwd),
43120
+ title: session.label ?? path28__default.basename(cwd),
43087
43121
  payload: toOperationPayload(cwd, session),
43088
43122
  createdAt: session.createdAt
43089
43123
  });
@@ -43194,7 +43228,7 @@ function createAgentApi(ctx, terminalRuntime, deps) {
43194
43228
  if (result?.renamed) {
43195
43229
  observability.notifySessionUpdated(result.session);
43196
43230
  const autoNameCwd = readPayloadString(ctx.host.operations.get(sessionId)?.payload ?? {}, "cwd") ?? result.session.cwdLabel;
43197
- ctx.host.operations.patch(sessionId, { title: result.session.label ?? path27__default.basename(autoNameCwd) });
43231
+ ctx.host.operations.patch(sessionId, { title: result.session.label ?? path28__default.basename(autoNameCwd) });
43198
43232
  }
43199
43233
  ctx.host.http.writeJson(res, 200, { ok: true, renamed: result?.renamed === true });
43200
43234
  return true;
@@ -43477,7 +43511,7 @@ function registerTerminalSettingsRoutes(ctx, deps) {
43477
43511
  }
43478
43512
  const updated = deps.globalOptionsService.update((current) => ({
43479
43513
  ...current,
43480
- enableMetaphor: body.enableMetaphor
43514
+ ...body
43481
43515
  }));
43482
43516
  ctx.host.http.writeJson(res, 200, toTerminalSettingsState(updated));
43483
43517
  return true;
@@ -43488,14 +43522,17 @@ function registerTerminalSettingsRoutes(ctx, deps) {
43488
43522
  }
43489
43523
  function toTerminalSettingsState(data) {
43490
43524
  return {
43491
- enableMetaphor: data.enableMetaphor ?? false
43525
+ enableMetaphor: data.enableMetaphor ?? false,
43526
+ codexLaunchMode: data.codexLaunchMode ?? "acp"
43492
43527
  };
43493
43528
  }
43494
43529
  function isTerminalSettingsBody(value) {
43495
43530
  if (!value || typeof value !== "object" || Array.isArray(value)) return false;
43496
- if (Object.keys(value).length !== 1) return false;
43531
+ const keys = Object.keys(value);
43532
+ if (keys.length !== 1) return false;
43497
43533
  const body = value;
43498
- return typeof body.enableMetaphor === "boolean";
43534
+ if (keys[0] === "enableMetaphor") return typeof body.enableMetaphor === "boolean";
43535
+ return keys[0] === "codexLaunchMode" && (body.codexLaunchMode === "acp" || body.codexLaunchMode === "app-server");
43499
43536
  }
43500
43537
  function isJsonRequest(req) {
43501
43538
  const contentType = req.headers["content-type"];