harness-wingman 0.8.0 → 0.8.1

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.
@@ -7757,11 +7757,11 @@ function isPatchState(value) {
7757
7757
  const patch = value;
7758
7758
  return typeof patch.patchFile === "string" && typeof patch.original === "object" && patch.original !== null && typeof patch.original.existed === "boolean" && (patch.original.bytesBase64 === void 0 || typeof patch.original.bytesBase64 === "string");
7759
7759
  }
7760
- async function readState(paths) {
7761
- const buffer = await readIfExists(paths.stateFile);
7760
+ async function readState(paths3) {
7761
+ const buffer = await readIfExists(paths3.stateFile);
7762
7762
  if (buffer === void 0)
7763
7763
  return void 0;
7764
- const state = JSON.parse(decodeUtf8Strict(buffer, paths.stateFile));
7764
+ const state = JSON.parse(decodeUtf8Strict(buffer, paths3.stateFile));
7765
7765
  if (typeof state !== "object" || state === null || state.version !== 1 && state.version !== 2) {
7766
7766
  throw new Error("\u672A\u77E5\u7684\u63A5\u7EBF\u72B6\u6001\u7248\u672C,\u4E0D\u731C");
7767
7767
  }
@@ -7770,18 +7770,18 @@ async function readState(paths) {
7770
7770
  }
7771
7771
  return state;
7772
7772
  }
7773
- async function writeState(paths, state) {
7774
- await mkdir(dirname(paths.stateFile), { recursive: true });
7775
- await writeFile(paths.stateFile, `${JSON.stringify(state, void 0, 2)}
7773
+ async function writeState(paths3, state) {
7774
+ await mkdir(dirname(paths3.stateFile), { recursive: true });
7775
+ await writeFile(paths3.stateFile, `${JSON.stringify(state, void 0, 2)}
7776
7776
  `, "utf8");
7777
7777
  }
7778
- function backupDirectory(paths) {
7779
- return join(paths.backupsRoot, (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-"));
7778
+ function backupDirectory(paths3) {
7779
+ return join(paths3.backupsRoot, (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-"));
7780
7780
  }
7781
- async function backupPatchFile(paths, backupDir, file, bytes) {
7782
- const fromProfiles = relative(paths.profilesDir, file);
7781
+ async function backupPatchFile(paths3, backupDir, file, bytes) {
7782
+ const fromProfiles = relative(paths3.profilesDir, file);
7783
7783
  let safeRelative;
7784
- if (file === paths.patchFile) {
7784
+ if (file === paths3.patchFile) {
7785
7785
  safeRelative = join("home", "cordis.patch.yml");
7786
7786
  } else if (!fromProfiles.startsWith("..") && !isAbsolute(fromProfiles)) {
7787
7787
  safeRelative = join("profiles", fromProfiles);
@@ -7793,15 +7793,15 @@ async function backupPatchFile(paths, backupDir, file, bytes) {
7793
7793
  await mkdir(dirname(target), { recursive: true });
7794
7794
  await writeFile(target, bytes);
7795
7795
  }
7796
- async function writeOwnedFiles(paths, url) {
7797
- await mkdir(dirname(paths.hooksConfigFile), { recursive: true });
7798
- await writeFile(paths.forwarderFile, FORWARDER_SOURCE, "utf8");
7799
- await writeFile(paths.hooksConfigFile, buildHooksConfig(paths.forwarderFile, url), "utf8");
7796
+ async function writeOwnedFiles(paths3, url) {
7797
+ await mkdir(dirname(paths3.hooksConfigFile), { recursive: true });
7798
+ await writeFile(paths3.forwarderFile, FORWARDER_SOURCE, "utf8");
7799
+ await writeFile(paths3.hooksConfigFile, buildHooksConfig(paths3.forwarderFile, url), "utf8");
7800
7800
  }
7801
- async function listProfiles(paths, environment) {
7801
+ async function listProfiles(paths3, environment) {
7802
7802
  let entries;
7803
7803
  try {
7804
- entries = await readdir(paths.profilesDir, { withFileTypes: true });
7804
+ entries = await readdir(paths3.profilesDir, { withFileTypes: true });
7805
7805
  } catch (error) {
7806
7806
  if (error.code === "ENOENT")
7807
7807
  entries = [];
@@ -7813,12 +7813,12 @@ async function listProfiles(paths, environment) {
7813
7813
  if (entry.name === "node_modules")
7814
7814
  continue;
7815
7815
  try {
7816
- if (!(await stat(join(paths.profilesDir, entry.name))).isDirectory())
7816
+ if (!(await stat(join(paths3.profilesDir, entry.name))).isDirectory())
7817
7817
  continue;
7818
7818
  } catch {
7819
7819
  continue;
7820
7820
  }
7821
- const manifest = join(paths.profilesDir, entry.name, "package.json");
7821
+ const manifest = join(paths3.profilesDir, entry.name, "package.json");
7822
7822
  if (await readIfExists(manifest) !== void 0)
7823
7823
  names.push(entry.name);
7824
7824
  }
@@ -7830,12 +7830,12 @@ async function listProfiles(paths, environment) {
7830
7830
  const selectedNames = selected === void 0 || selected === "" ? names : [selected];
7831
7831
  const inspected = [];
7832
7832
  for (const name of selectedNames) {
7833
- const dir = join(paths.profilesDir, name);
7833
+ const dir = join(paths3.profilesDir, name);
7834
7834
  const missingPackages = [];
7835
7835
  for (const packageName of REQUIRED_PACKAGES) {
7836
7836
  const parts = packageName.split("/");
7837
7837
  const localManifest = join(dir, "node_modules", ...parts, "package.json");
7838
- const parentManifest = join(paths.profilesDir, "node_modules", ...parts, "package.json");
7838
+ const parentManifest = join(paths3.profilesDir, "node_modules", ...parts, "package.json");
7839
7839
  if (await readIfExists(localManifest) === void 0 && await readIfExists(parentManifest) === void 0) {
7840
7840
  missingPackages.push(packageName);
7841
7841
  }
@@ -7852,7 +7852,7 @@ async function listProfiles(paths, environment) {
7852
7852
  function installCommand(profile) {
7853
7853
  return `dsh plugin --profile ${profile} add ${DSH_HOOKS_PACKAGE}@${DSH_PINNED_VERSION} ${DSH_HOOK_PROTOCOL_PACKAGE}@${DSH_PINNED_VERSION}`;
7854
7854
  }
7855
- async function profileIsWired(profile, paths) {
7855
+ async function profileIsWired(profile, paths3) {
7856
7856
  if (profile.missingPackages.length > 0)
7857
7857
  return false;
7858
7858
  const buffer = await readIfExists(profile.patchFile);
@@ -7869,18 +7869,18 @@ async function profileIsWired(profile, paths) {
7869
7869
  const entries = tryParsePatchEntries(text, profile.patchFile);
7870
7870
  if (entries === void 0 || !hasWingmanRow(entries))
7871
7871
  return false;
7872
- return await readIfExists(paths.hooksConfigFile) !== void 0;
7872
+ return await readIfExists(paths3.hooksConfigFile) !== void 0;
7873
7873
  }
7874
7874
  async function dshHookInstallReport(options, environment = process.env) {
7875
- const paths = resolveDshHookPaths(options);
7876
- const profiles = await listProfiles(paths, environment);
7875
+ const paths3 = resolveDshHookPaths(options);
7876
+ const profiles = await listProfiles(paths3, environment);
7877
7877
  const reports = [];
7878
7878
  for (const profile of profiles) {
7879
7879
  const missingPackages = [...profile.missingPackages];
7880
7880
  const blockPresent = hasLiveHooksBlock(await readIfExists(profile.patchFile));
7881
7881
  const report = {
7882
7882
  profile: profile.name,
7883
- wired: await profileIsWired(profile, paths),
7883
+ wired: await profileIsWired(profile, paths3),
7884
7884
  blockPresent,
7885
7885
  missingPackages
7886
7886
  };
@@ -7890,16 +7890,16 @@ async function dshHookInstallReport(options, environment = process.env) {
7890
7890
  }
7891
7891
  return { profiles: reports };
7892
7892
  }
7893
- function prepareInstalledProfile(profile, paths, before, previous) {
7893
+ function prepareInstalledProfile(profile, paths3, before, previous) {
7894
7894
  const currentText = before === void 0 ? void 0 : decodeUtf8Strict(before, profile.patchFile);
7895
7895
  const surgicalText = currentText === void 0 ? void 0 : stripLiveHooksBlocks(currentText, profile.patchFile);
7896
7896
  const entriesBefore = surgicalText === void 0 ? [] : parsePatchEntries(surgicalText, profile.patchFile);
7897
7897
  if (hasWingmanRow(entriesBefore)) {
7898
7898
  throw new Error(`\u62D2\u5199:${profile.patchFile} \u5DF2\u6709\u672A\u5E26 wingman \u6807\u8BB0\u7684 ${DSH_HOOK_ROW_ID} \u6761\u76EE(\u7591\u624B\u5DE5\u6284\u5165),\u8BF7\u5148\u624B\u5DE5\u79FB\u9664`);
7899
7899
  }
7900
- const composed = composeInstalledText(surgicalText, entriesBefore.length, buildPatchBlock(paths.hooksConfigFile));
7900
+ const composed = composeInstalledText(surgicalText, entriesBefore.length, buildPatchBlock(paths3.hooksConfigFile));
7901
7901
  const composedEntries = parsePatchEntries(composed, profile.patchFile);
7902
- const expected = [...entriesBefore, expectedEntry(paths.hooksConfigFile)];
7902
+ const expected = [...entriesBefore, expectedEntry(paths3.hooksConfigFile)];
7903
7903
  if (JSON.stringify(composedEntries) !== JSON.stringify(expected)) {
7904
7904
  throw new Error(`\u62D2\u5199:${profile.patchFile} \u8FFD\u52A0\u540E\u5F62\u72B6\u6821\u9A8C\u5931\u8D25(\u539F\u6587\u4EF6\u5F62\u6001\u65E0\u6CD5\u5B89\u5168\u8FFD\u52A0),\u4E0D\u731C`);
7905
7905
  }
@@ -7951,13 +7951,13 @@ function restoredFromSnapshot(after, state) {
7951
7951
  return false;
7952
7952
  return after.equals(Buffer2.from(state.original.bytesBase64, "base64"));
7953
7953
  }
7954
- async function applyMutations(paths, mutations) {
7954
+ async function applyMutations(paths3, mutations) {
7955
7955
  if (mutations.length === 0)
7956
7956
  return;
7957
- const backupDir = backupDirectory(paths);
7957
+ const backupDir = backupDirectory(paths3);
7958
7958
  for (const mutation of mutations) {
7959
7959
  if (mutation.before !== void 0) {
7960
- await backupPatchFile(paths, backupDir, mutation.file, mutation.before);
7960
+ await backupPatchFile(paths3, backupDir, mutation.file, mutation.before);
7961
7961
  }
7962
7962
  }
7963
7963
  for (const mutation of mutations) {
@@ -7970,22 +7970,22 @@ async function applyMutations(paths, mutations) {
7970
7970
  }
7971
7971
  }
7972
7972
  async function retireLegacyDshHomeHooks(options) {
7973
- const paths = resolveDshHookPaths(options);
7973
+ const paths3 = resolveDshHookPaths(options);
7974
7974
  try {
7975
- const before = await readIfExists(paths.patchFile);
7975
+ const before = await readIfExists(paths3.patchFile);
7976
7976
  if (!hasLiveHooksBlock(before))
7977
7977
  return { removed: false, restored: "none" };
7978
- const state = await readState(paths);
7978
+ const state = await readState(paths3);
7979
7979
  const candidate = state?.version === 1 ? { patchFile: state.patchFile, original: state.original } : state?.legacyHome;
7980
- const legacyState = candidate?.patchFile === paths.patchFile ? candidate : void 0;
7981
- const mutation = prepareRemoval(paths.patchFile, before, legacyState);
7980
+ const legacyState = candidate?.patchFile === paths3.patchFile ? candidate : void 0;
7981
+ const mutation = prepareRemoval(paths3.patchFile, before, legacyState);
7982
7982
  if (mutation === void 0)
7983
7983
  return { removed: false, restored: "none" };
7984
- await applyMutations(paths, [mutation]);
7984
+ await applyMutations(paths3, [mutation]);
7985
7985
  return {
7986
7986
  removed: true,
7987
7987
  restored: restoredFromSnapshot(mutation.after, legacyState) ? "byte-identical" : "surgical",
7988
- path: paths.patchFile
7988
+ path: paths3.patchFile
7989
7989
  };
7990
7990
  } catch {
7991
7991
  return {
@@ -7997,9 +7997,9 @@ async function installDshHooks(port, options, environment = process.env) {
7997
7997
  if (!Number.isInteger(port) || port < 1 || port > 65535) {
7998
7998
  throw new Error(`\u975E\u6CD5\u7AEF\u53E3:${String(port)}`);
7999
7999
  }
8000
- const paths = resolveDshHookPaths(options);
8001
- const profiles = await listProfiles(paths, environment);
8002
- const previousState = await readState(paths);
8000
+ const paths3 = resolveDshHookPaths(options);
8001
+ const profiles = await listProfiles(paths3, environment);
8002
+ const previousState = await readState(paths3);
8003
8003
  const previousProfiles = previousState?.version === 2 ? previousState.profiles : {};
8004
8004
  const nextProfiles = { ...previousProfiles };
8005
8005
  const mutations = [];
@@ -8007,7 +8007,7 @@ async function installDshHooks(port, options, environment = process.env) {
8007
8007
  for (const profile of profiles) {
8008
8008
  const before = await readIfExists(profile.patchFile);
8009
8009
  if (profile.missingPackages.length === 0) {
8010
- const prepared = prepareInstalledProfile(profile, paths, before, previousProfiles[profile.name]);
8010
+ const prepared = prepareInstalledProfile(profile, paths3, before, previousProfiles[profile.name]);
8011
8011
  nextProfiles[profile.name] = prepared.state;
8012
8012
  if (prepared.mutation !== void 0)
8013
8013
  mutations.push(prepared.mutation);
@@ -8021,19 +8021,19 @@ async function installDshHooks(port, options, environment = process.env) {
8021
8021
  }
8022
8022
  }
8023
8023
  let legacyHome = previousState?.version === 2 ? previousState.legacyHome : previousState?.version === 1 ? { patchFile: previousState.patchFile, original: previousState.original } : void 0;
8024
- const legacyBefore = await readIfExists(paths.patchFile);
8024
+ const legacyBefore = await readIfExists(paths3.patchFile);
8025
8025
  let migratedThisRun = false;
8026
8026
  if (hasLiveHooksBlock(legacyBefore)) {
8027
- const legacyText = decodeUtf8Strict(legacyBefore, paths.patchFile);
8028
- parsePatchEntries(legacyText, paths.patchFile);
8029
- const surgical = stripLiveHooksBlocks(legacyText, paths.patchFile);
8030
- const surgicalEntries = parsePatchEntries(surgical, paths.patchFile);
8027
+ const legacyText = decodeUtf8Strict(legacyBefore, paths3.patchFile);
8028
+ parsePatchEntries(legacyText, paths3.patchFile);
8029
+ const surgical = stripLiveHooksBlocks(legacyText, paths3.patchFile);
8030
+ const surgicalEntries = parsePatchEntries(surgical, paths3.patchFile);
8031
8031
  legacyHome ??= {
8032
- patchFile: paths.patchFile,
8032
+ patchFile: paths3.patchFile,
8033
8033
  original: { existed: true }
8034
8034
  };
8035
- const after = resolveRestoredBytes(surgical, surgicalEntries, legacyHome, paths.patchFile);
8036
- mutations.push({ file: paths.patchFile, before: legacyBefore, after });
8035
+ const after = resolveRestoredBytes(surgical, surgicalEntries, legacyHome, paths3.patchFile);
8036
+ mutations.push({ file: paths3.patchFile, before: legacyBefore, after });
8037
8037
  migratedThisRun = true;
8038
8038
  }
8039
8039
  const nextState = {
@@ -8046,38 +8046,38 @@ async function installDshHooks(port, options, environment = process.env) {
8046
8046
  const hasState = hasManagedProfiles || legacyHome !== void 0;
8047
8047
  const url = `http://127.0.0.1:${port}/hook?harness=dsh`;
8048
8048
  if (hasManagedProfiles) {
8049
- await writeOwnedFiles(paths, url);
8049
+ await writeOwnedFiles(paths3, url);
8050
8050
  if (hasState)
8051
- await writeState(paths, nextState);
8051
+ await writeState(paths3, nextState);
8052
8052
  else
8053
- await rm(paths.stateFile, { force: true });
8054
- await applyMutations(paths, mutations);
8053
+ await rm(paths3.stateFile, { force: true });
8054
+ await applyMutations(paths3, mutations);
8055
8055
  } else {
8056
- await applyMutations(paths, mutations);
8057
- await rm(paths.hooksConfigFile, { force: true });
8058
- await rm(paths.forwarderFile, { force: true });
8056
+ await applyMutations(paths3, mutations);
8057
+ await rm(paths3.hooksConfigFile, { force: true });
8058
+ await rm(paths3.forwarderFile, { force: true });
8059
8059
  if (hasState)
8060
- await writeState(paths, nextState);
8060
+ await writeState(paths3, nextState);
8061
8061
  else
8062
- await rm(paths.stateFile, { force: true });
8062
+ await rm(paths3.stateFile, { force: true });
8063
8063
  }
8064
8064
  return { migratedThisRun, removedProfiles };
8065
8065
  }
8066
8066
  async function uninstallDshHooks(options, environment = process.env) {
8067
- const paths = resolveDshHookPaths(options);
8068
- const state = await readState(paths);
8067
+ const paths3 = resolveDshHookPaths(options);
8068
+ const state = await readState(paths3);
8069
8069
  const stateProfiles = state?.version === 2 ? state.profiles : {};
8070
8070
  const selected = environment.WINGMAN_DSH_PROFILE;
8071
8071
  const inspectionEnvironment = { ...environment };
8072
8072
  delete inspectionEnvironment.WINGMAN_DSH_PROFILE;
8073
- const inspected = await listProfiles(paths, inspectionEnvironment);
8073
+ const inspected = await listProfiles(paths3, inspectionEnvironment);
8074
8074
  if (selected !== void 0 && selected !== "" && !inspected.some((profile) => profile.name === selected) && stateProfiles[selected] === void 0) {
8075
8075
  throw new Error(`dsh profile \u4E0D\u5B58\u5728\u6216\u7F3A package.json:${selected}`);
8076
8076
  }
8077
8077
  const targetNames = selected === void 0 || selected === "" ? [.../* @__PURE__ */ new Set([...inspected.map((profile) => profile.name), ...Object.keys(stateProfiles)])] : [selected];
8078
8078
  const remainingProfiles = { ...stateProfiles };
8079
8079
  for (const profile of inspected) {
8080
- if (!targetNames.includes(profile.name) && await profileIsWired(profile, paths)) {
8080
+ if (!targetNames.includes(profile.name) && await profileIsWired(profile, paths3)) {
8081
8081
  remainingProfiles[profile.name] ??= {
8082
8082
  patchFile: profile.patchFile,
8083
8083
  original: { existed: true }
@@ -8088,10 +8088,10 @@ async function uninstallDshHooks(options, environment = process.env) {
8088
8088
  const results = [];
8089
8089
  for (const name of targetNames) {
8090
8090
  const profileState = stateProfiles[name];
8091
- const file = profileState?.patchFile ?? join(paths.profilesDir, name, "cordis.patch.yml");
8091
+ const file = profileState?.patchFile ?? join(paths3.profilesDir, name, "cordis.patch.yml");
8092
8092
  const before = await readIfExists(file);
8093
8093
  const inspectedProfile = inspected.find((profile) => profile.name === name);
8094
- const wired = inspectedProfile === void 0 ? false : await profileIsWired(inspectedProfile, paths);
8094
+ const wired = inspectedProfile === void 0 ? false : await profileIsWired(inspectedProfile, paths3);
8095
8095
  const removal = prepareRemoval(file, before, profileState);
8096
8096
  if (removal !== void 0) {
8097
8097
  mutations.push(removal);
@@ -8105,31 +8105,31 @@ async function uninstallDshHooks(options, environment = process.env) {
8105
8105
  delete remainingProfiles[name];
8106
8106
  }
8107
8107
  const legacyState = state?.version === 1 ? { patchFile: state.patchFile, original: state.original } : state?.legacyHome;
8108
- const legacyFile = legacyState?.patchFile ?? paths.patchFile;
8108
+ const legacyFile = legacyState?.patchFile ?? paths3.patchFile;
8109
8109
  const legacyRemoval = prepareRemoval(legacyFile, await readIfExists(legacyFile), legacyState);
8110
8110
  if (legacyRemoval !== void 0)
8111
8111
  mutations.push(legacyRemoval);
8112
- await applyMutations(paths, mutations);
8112
+ await applyMutations(paths3, mutations);
8113
8113
  if (Object.keys(remainingProfiles).length > 0) {
8114
- await writeState(paths, {
8114
+ await writeState(paths3, {
8115
8115
  version: 2,
8116
8116
  port: state?.port ?? 7333,
8117
8117
  profiles: remainingProfiles
8118
8118
  });
8119
8119
  } else {
8120
- await rm(paths.hooksConfigFile, { force: true });
8121
- await rm(paths.forwarderFile, { force: true });
8122
- await rm(paths.stateFile, { force: true });
8120
+ await rm(paths3.hooksConfigFile, { force: true });
8121
+ await rm(paths3.forwarderFile, { force: true });
8122
+ await rm(paths3.stateFile, { force: true });
8123
8123
  }
8124
8124
  return { profiles: results };
8125
8125
  }
8126
8126
  async function detectDshLiveWiring(options, environment = process.env) {
8127
- const paths = resolveDshHookPaths(options);
8127
+ const paths3 = resolveDshHookPaths(options);
8128
8128
  const inspectionEnvironment = { ...environment };
8129
8129
  delete inspectionEnvironment.WINGMAN_DSH_PROFILE;
8130
- const profiles = await listProfiles(paths, inspectionEnvironment);
8130
+ const profiles = await listProfiles(paths3, inspectionEnvironment);
8131
8131
  for (const profile of profiles) {
8132
- if (await profileIsWired(profile, paths))
8132
+ if (await profileIsWired(profile, paths3))
8133
8133
  return true;
8134
8134
  }
8135
8135
  return false;
@@ -8193,17 +8193,19 @@ var init_feedback_url = __esm({
8193
8193
 
8194
8194
  // packages/core/dist/plan-protocol.js
8195
8195
  import { createHash as createHash2 } from "node:crypto";
8196
- function planProtocolBlockStart(version = PLAN_PROTOCOL_VERSION) {
8197
- return `<!-- >>> wingman plan protocol v${version} >>> -->`;
8196
+ function planProtocolBlockStart(version = PLAN_PROTOCOL_VERSION, scope = "project") {
8197
+ return `<!-- >>> wingman plan protocol ${scope === "user" ? "user " : ""}v${version} >>> -->`;
8198
8198
  }
8199
- function buildPlanProtocolBlock(version = PLAN_PROTOCOL_VERSION, text) {
8200
- let body = normalizeMarkdownLineEndings(text ?? KNOWN_PROTOCOL_TEXT.get(version) ?? "");
8199
+ function buildPlanProtocolBlock(version = PLAN_PROTOCOL_VERSION, text, scope = "project") {
8200
+ const known = scope === "user" ? KNOWN_USER_PROTOCOL_TEXT : KNOWN_PROTOCOL_TEXT;
8201
+ let body = normalizeMarkdownLineEndings(text ?? known.get(version) ?? "");
8201
8202
  if (body === "")
8202
8203
  throw new Error(`\u672A\u77E5 Plan Protocol \u7248\u672C v${version}\uFF0C\u4E14\u672A\u63D0\u4F9B\u6B63\u6587`);
8203
8204
  if (!body.endsWith("\n"))
8204
8205
  body += "\n";
8205
- return `${planProtocolBlockStart(version)}
8206
- ${body}${PLAN_PROTOCOL_BLOCK_END}
8206
+ const end = scope === "user" ? PLAN_PROTOCOL_USER_BLOCK_END : PLAN_PROTOCOL_BLOCK_END;
8207
+ return `${planProtocolBlockStart(version, scope)}
8208
+ ${body}${end}
8207
8209
  `;
8208
8210
  }
8209
8211
  function decodeUtf8Strict2(bytes, sourcePath = "<memory>") {
@@ -8224,9 +8226,17 @@ function preferredMarkdownLineEnding(text) {
8224
8226
  const hasBareLf = text.replaceAll("\r\n", "").includes("\n");
8225
8227
  return hasCrlf && !hasBareLf ? "\r\n" : "\n";
8226
8228
  }
8227
- function splitPlanProtocolBlock(text, sourcePath = "<memory>") {
8228
- const starts = [...text.matchAll(BLOCK_START)];
8229
- const ends = allIndexesOf(text, PLAN_PROTOCOL_BLOCK_END);
8229
+ function splitPlanProtocolBlock(text, sourcePath = "<memory>", scope = "project") {
8230
+ const startPattern = scope === "user" ? USER_BLOCK_START : BLOCK_START;
8231
+ const endMarker = scope === "user" ? PLAN_PROTOCOL_USER_BLOCK_END : PLAN_PROTOCOL_BLOCK_END;
8232
+ const starts = [...text.matchAll(startPattern)];
8233
+ const ends = allIndexesOf(text, endMarker);
8234
+ if (scope === "user") {
8235
+ const unrecognized = text.replace(startPattern, "").replaceAll(endMarker, "");
8236
+ if (/<!--\s*(?:>>>|<<<)\s*wingman plan protocol user\b/u.test(unrecognized)) {
8237
+ throw new Error(`wingman plan protocol user \u672A\u77E5\u6807\u8BB0\u683C\u5F0F(${sourcePath})`);
8238
+ }
8239
+ }
8230
8240
  if (starts.length === 0 && ends.length === 0) {
8231
8241
  return { before: text, after: "", remainder: text };
8232
8242
  }
@@ -8238,7 +8248,7 @@ function splitPlanProtocolBlock(text, sourcePath = "<memory>") {
8238
8248
  if (start === void 0 || endMark === void 0 || endMark < start.index) {
8239
8249
  throw new Error(`wingman plan protocol \u6807\u8BB0\u5757\u6B8B\u7F3A(${sourcePath})`);
8240
8250
  }
8241
- let end = endMark + PLAN_PROTOCOL_BLOCK_END.length;
8251
+ let end = endMark + endMarker.length;
8242
8252
  if (text.startsWith("\r\n", end))
8243
8253
  end += 2;
8244
8254
  else if (text[end] === "\n")
@@ -8253,15 +8263,17 @@ function splitPlanProtocolBlock(text, sourcePath = "<memory>") {
8253
8263
  version: Number(start[1])
8254
8264
  };
8255
8265
  }
8256
- function inspectPlanProtocolBlock(block) {
8266
+ function inspectPlanProtocolBlock(block, scope = "project") {
8257
8267
  const normalized = normalizeMarkdownLineEndings(block);
8258
- const split = splitPlanProtocolBlock(normalized);
8268
+ const split = splitPlanProtocolBlock(normalized, "<memory>", scope);
8259
8269
  const version = split.version;
8260
- const knownText = version === void 0 ? void 0 : KNOWN_PROTOCOL_TEXT.get(version);
8261
- const knownBlock = version === void 0 || knownText === void 0 ? void 0 : buildPlanProtocolBlock(version, knownText);
8270
+ const currentVersion = scope === "user" ? PLAN_PROTOCOL_USER_VERSION : PLAN_PROTOCOL_VERSION;
8271
+ const knownTexts = scope === "user" ? KNOWN_USER_PROTOCOL_TEXT : KNOWN_PROTOCOL_TEXT;
8272
+ const knownText = version === void 0 ? void 0 : knownTexts.get(version);
8273
+ const knownBlock = version === void 0 || knownText === void 0 ? void 0 : buildPlanProtocolBlock(version, knownText, scope);
8262
8274
  const known = split.before === "" && split.after === "" && normalized === knownBlock;
8263
8275
  return {
8264
- kind: known && version === PLAN_PROTOCOL_VERSION ? "current" : known ? "legacy" : "modified",
8276
+ kind: known && version === currentVersion ? "current" : known ? "legacy" : "modified",
8265
8277
  ...version !== void 0 ? { version } : {},
8266
8278
  sha256: sha256Hex(normalized)
8267
8279
  };
@@ -8287,11 +8299,27 @@ function allIndexesOf(text, needle) {
8287
8299
  }
8288
8300
  return indexes;
8289
8301
  }
8290
- var PLAN_PROTOCOL_VERSION, PLAN_PROTOCOL_TEXT, PLAN_PROTOCOL_BLOCK_END, LEGACY_PLAN_PROTOCOL_TEXT, KNOWN_PROTOCOL_TEXT, BLOCK_START;
8302
+ function mergePlanProtocolBlock(text, block, sourcePath = "<memory>", scope = "project") {
8303
+ const split = splitPlanProtocolBlock(text, sourcePath, scope);
8304
+ const lineEnding = preferredMarkdownLineEnding(text);
8305
+ const normalizedBlock = normalizeMarkdownLineEndings(block).replaceAll("\n", lineEnding);
8306
+ if (split.block !== void 0)
8307
+ return split.before + normalizedBlock + split.after;
8308
+ if (text === "")
8309
+ return normalizedBlock;
8310
+ let before = text;
8311
+ if (!before.endsWith("\n"))
8312
+ before += lineEnding;
8313
+ if (!before.endsWith(`${lineEnding}${lineEnding}`))
8314
+ before += lineEnding;
8315
+ return before + normalizedBlock;
8316
+ }
8317
+ var PLAN_PROTOCOL_VERSION, PLAN_PROTOCOL_USER_VERSION, PLAN_PROTOCOL_TEXT, PLAN_PROTOCOL_TEXT_USER, PLAN_PROTOCOL_USER_BLOCK_END, PLAN_PROTOCOL_BLOCK_END, LEGACY_PLAN_PROTOCOL_TEXT, KNOWN_PROTOCOL_TEXT, KNOWN_USER_PROTOCOL_TEXT, BLOCK_START, USER_BLOCK_START;
8291
8318
  var init_plan_protocol = __esm({
8292
8319
  "packages/core/dist/plan-protocol.js"() {
8293
8320
  "use strict";
8294
8321
  PLAN_PROTOCOL_VERSION = 1;
8322
+ PLAN_PROTOCOL_USER_VERSION = 1;
8295
8323
  PLAN_PROTOCOL_TEXT = `Wingman plan protocol v1 \u2014 a behavioral convention, not a gate. Wingman only reads; it never replies to you.
8296
8324
  - The project root is the directory that contains this instruction file (for Claude Code: the parent of \`.claude/\`).
8297
8325
  - Before starting work, read \`<project root>/.wingman/plan.md\`. If it does not exist, create it: a \`# Title\` line, then a nested checkbox tree of steps, each step with an indented \`Verify:\` line describing how it will be checked.
@@ -8300,13 +8328,159 @@ var init_plan_protocol = __esm({
8300
8328
  - Keep your in-session todo list as sub-steps of the \`[/]\` step; do not copy the whole file into it.
8301
8329
  - Never put secrets, credentials, or personal data in the plan.
8302
8330
  `;
8331
+ PLAN_PROTOCOL_TEXT_USER = PLAN_PROTOCOL_TEXT.replace(/^- The project root .*$/mu, "- The project root is the nearest git root containing the current working directory, or the current working directory when there is no git root. If the current working directory is the user\u2019s home directory, you MUST NOT create a plan file. Only multi-step tasks use the plan workflow below; single-turn questions do not create or update a plan file.");
8332
+ PLAN_PROTOCOL_USER_BLOCK_END = "<!-- <<< wingman plan protocol user <<< -->";
8303
8333
  PLAN_PROTOCOL_BLOCK_END = "<!-- <<< wingman plan protocol <<< -->";
8304
8334
  LEGACY_PLAN_PROTOCOL_TEXT = "Wingman plan protocol v0 \u2014 legacy fixture text.\n";
8305
8335
  KNOWN_PROTOCOL_TEXT = /* @__PURE__ */ new Map([
8306
8336
  [0, LEGACY_PLAN_PROTOCOL_TEXT],
8307
8337
  [PLAN_PROTOCOL_VERSION, PLAN_PROTOCOL_TEXT]
8308
8338
  ]);
8339
+ KNOWN_USER_PROTOCOL_TEXT = /* @__PURE__ */ new Map([[PLAN_PROTOCOL_USER_VERSION, PLAN_PROTOCOL_TEXT_USER]]);
8309
8340
  BLOCK_START = /<!-- >>> wingman plan protocol v(\d+) >>> -->/gu;
8341
+ USER_BLOCK_START = /<!-- >>> wingman plan protocol user v(\d+) >>> -->/gu;
8342
+ }
8343
+ });
8344
+
8345
+ // packages/core/dist/plan-protocol-user.js
8346
+ import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
8347
+ import { basename as basename2, dirname as dirname2, join as join2 } from "node:path";
8348
+ function readTarget(targetPath2) {
8349
+ if (!existsSync(targetPath2))
8350
+ return void 0;
8351
+ const bytes = readFileSync(targetPath2);
8352
+ decodeUtf8Strict2(bytes, targetPath2);
8353
+ const text = bytes.toString("utf8");
8354
+ const split = splitPlanProtocolBlock(text, targetPath2, "user");
8355
+ const identity = split.block === void 0 ? void 0 : inspectPlanProtocolBlock(split.block, "user");
8356
+ return { bytes, text, split, identity };
8357
+ }
8358
+ function statusPlanProtocolUser(targetPath2) {
8359
+ try {
8360
+ const identity = readTarget(targetPath2)?.identity;
8361
+ return {
8362
+ targetPath: targetPath2,
8363
+ state: identity === void 0 ? "missing" : identity.kind === "current" ? "installed" : "modified",
8364
+ ...identity?.version !== void 0 ? { version: identity.version } : {},
8365
+ ...identity?.kind === "modified" ? { reason: "\u7528\u6237\u7EA7\u53D7\u7BA1\u5757\u5DF2\u88AB\u4FEE\u6539" } : {}
8366
+ };
8367
+ } catch (error) {
8368
+ return { targetPath: targetPath2, state: "modified", reason: error.message };
8369
+ }
8370
+ }
8371
+ function installPlanProtocolUser(paths3) {
8372
+ const existing = readTarget(paths3.targetPath);
8373
+ assertKnown(existing, paths3.targetPath);
8374
+ const before = existing?.text ?? "";
8375
+ if (existing?.identity !== void 0) {
8376
+ return result(paths3.targetPath, "install", "installed", before, before, true, false);
8377
+ }
8378
+ const statePath2 = snapshotPath(paths3);
8379
+ readSnapshot(statePath2, paths3.targetPath);
8380
+ const block = buildPlanProtocolBlock(PLAN_PROTOCOL_USER_VERSION, void 0, "user");
8381
+ const after = mergePlanProtocolBlock(before, block, paths3.targetPath, "user");
8382
+ const backupDir = nextBackupDir(paths3.homeDir);
8383
+ if (!paths3.dryRun) {
8384
+ backupTarget(backupDir, paths3.targetPath, existing?.bytes);
8385
+ const snapshot = {
8386
+ version: 1,
8387
+ targetPath: paths3.targetPath,
8388
+ installedRemainderSha256: sha256Hex(splitPlanProtocolBlock(after, paths3.targetPath, "user").remainder),
8389
+ original: existing === void 0 ? { existed: false } : { existed: true, base64: existing.bytes.toString("base64") }
8390
+ };
8391
+ mkdirSync(dirname2(statePath2), { recursive: true });
8392
+ writeFileSync(statePath2, `${JSON.stringify(snapshot, null, 2)}
8393
+ `);
8394
+ mkdirSync(dirname2(paths3.targetPath), { recursive: true });
8395
+ writeFileSync(paths3.targetPath, after);
8396
+ }
8397
+ return {
8398
+ ...result(paths3.targetPath, "install", "missing", before, after, true, true),
8399
+ state: "installed",
8400
+ version: PLAN_PROTOCOL_USER_VERSION,
8401
+ backupDir
8402
+ };
8403
+ }
8404
+ function uninstallPlanProtocolUser(paths3) {
8405
+ const existing = readTarget(paths3.targetPath);
8406
+ assertKnown(existing, paths3.targetPath);
8407
+ const before = existing?.text ?? "";
8408
+ if (existing?.identity === void 0) {
8409
+ return result(paths3.targetPath, "uninstall", "missing", before, before, existing !== void 0, false);
8410
+ }
8411
+ const statePath2 = snapshotPath(paths3);
8412
+ const snapshot = readSnapshot(statePath2, paths3.targetPath);
8413
+ const canRestore = snapshot !== void 0 && sha256Hex(existing.split.remainder) === snapshot.installedRemainderSha256;
8414
+ const restored = canRestore && snapshot.original.existed ? Buffer.from(snapshot.original.base64 ?? "", "base64") : void 0;
8415
+ const afterExists = canRestore ? snapshot.original.existed : existing.split.remainder !== "";
8416
+ const after = afterExists ? restored?.toString("utf8") ?? existing.split.remainder : "";
8417
+ const backupDir = nextBackupDir(paths3.homeDir);
8418
+ if (!paths3.dryRun) {
8419
+ backupTarget(backupDir, paths3.targetPath, existing.bytes);
8420
+ if (afterExists)
8421
+ writeFileSync(paths3.targetPath, restored ?? after);
8422
+ else
8423
+ rmSync(paths3.targetPath);
8424
+ rmSync(statePath2, { force: true });
8425
+ }
8426
+ return {
8427
+ ...result(paths3.targetPath, "uninstall", "installed", before, after, afterExists, true),
8428
+ state: "missing",
8429
+ backupDir,
8430
+ restoredOriginal: canRestore
8431
+ };
8432
+ }
8433
+ function assertKnown(existing, targetPath2) {
8434
+ if (existing?.identity !== void 0 && existing.identity.kind !== "current") {
8435
+ throw new Error(`${targetPath2}: \u7528\u6237\u7EA7\u53D7\u7BA1\u5757\u5DF2\u88AB\u4FEE\u6539\u6216\u7248\u672C\u672A\u77E5\uFF0C\u62D2\u5199\u5E76\u4FDD\u7559\u7528\u6237\u5185\u5BB9`);
8436
+ }
8437
+ }
8438
+ function result(targetPath2, operation, previousState, before, after, afterExists, changed) {
8439
+ return {
8440
+ targetPath: targetPath2,
8441
+ operation,
8442
+ previousState,
8443
+ state: previousState,
8444
+ before,
8445
+ after,
8446
+ afterExists,
8447
+ changed,
8448
+ effectiveAt: "next_session",
8449
+ totalBytes: Buffer.byteLength(after)
8450
+ };
8451
+ }
8452
+ function snapshotPath(paths3) {
8453
+ return join2(paths3.homeDir, ".wingman", "state", `plan-protocol-user-${sha256Hex(paths3.targetPath)}.json`);
8454
+ }
8455
+ function readSnapshot(statePath2, targetPath2) {
8456
+ if (!existsSync(statePath2))
8457
+ return void 0;
8458
+ try {
8459
+ const value = JSON.parse(readFileSync(statePath2, "utf8"));
8460
+ if (value.version === 1 && value.targetPath === targetPath2 && typeof value.installedRemainderSha256 === "string" && /^[a-f0-9]{64}$/u.test(value.installedRemainderSha256) && typeof value.original?.existed === "boolean" && (value.original.existed ? typeof value.original.base64 === "string" && Buffer.from(value.original.base64, "base64").toString("base64") === value.original.base64 : value.original.base64 === void 0)) {
8461
+ return value;
8462
+ }
8463
+ } catch {
8464
+ }
8465
+ throw new Error(`\u7528\u6237\u7EA7\u534F\u8BAE\u5FEB\u7167\u683C\u5F0F\u672A\u77E5(${statePath2})\uFF0C\u62D2\u5199\u5E76\u4FDD\u7559\u7528\u6237\u5185\u5BB9`);
8466
+ }
8467
+ function nextBackupDir(homeDir) {
8468
+ const stamp = (/* @__PURE__ */ new Date()).toISOString().replaceAll(":", "-");
8469
+ const root = join2(homeDir, ".wingman", "backups");
8470
+ let dir = join2(root, stamp);
8471
+ for (let n = 2; existsSync(dir); n += 1)
8472
+ dir = join2(root, `${stamp}-${n}`);
8473
+ return dir;
8474
+ }
8475
+ function backupTarget(backupDir, targetPath2, bytes) {
8476
+ mkdirSync(backupDir, { recursive: true });
8477
+ if (bytes !== void 0)
8478
+ writeFileSync(join2(backupDir, basename2(targetPath2)), bytes);
8479
+ }
8480
+ var init_plan_protocol_user = __esm({
8481
+ "packages/core/dist/plan-protocol-user.js"() {
8482
+ "use strict";
8483
+ init_plan_protocol();
8310
8484
  }
8311
8485
  });
8312
8486
 
@@ -8492,6 +8666,7 @@ var init_dist = __esm({
8492
8666
  "use strict";
8493
8667
  init_feedback_url();
8494
8668
  init_plan_protocol();
8669
+ init_plan_protocol_user();
8495
8670
  init_refscan();
8496
8671
  SLOT_IDS = ["base", "rules", "skills", "tools", "gates", "history"];
8497
8672
  HARNESS_IDS = ["cc", "codex", "dsh"];
@@ -8521,7 +8696,7 @@ var init_dist = __esm({
8521
8696
  import { Buffer as Buffer3 } from "node:buffer";
8522
8697
  import { randomBytes } from "node:crypto";
8523
8698
  import { mkdir as mkdir2, rm as rm2, writeFile as writeFile2 } from "node:fs/promises";
8524
- import { dirname as dirname2, isAbsolute as isAbsolute2, join as join2, relative as relative2 } from "node:path";
8699
+ import { dirname as dirname3, isAbsolute as isAbsolute2, join as join3, relative as relative2 } from "node:path";
8525
8700
  function buildToggleBlock(instanceId, flags) {
8526
8701
  const lines2 = [`${TOGGLE_BEGIN_PREFIX}${instanceId}${TOGGLE_BEGIN_SUFFIX}`];
8527
8702
  if (flags.fileCreated)
@@ -8782,15 +8957,15 @@ async function planDshToggle(action, dump, options) {
8782
8957
  if (row.id === DSH_HOOK_ROW_ID && row.name === DSH_HOOKS_PACKAGE) {
8783
8958
  throw new Error(`\u300C${row.name}\u300D(${row.id})\u7531 Wingman \u5B9E\u51B5\u63A5\u7EBF(live hooks \u5757)\u5F15\u5165,\u8BF7\u7528 \`wingman hook uninstall dsh\` \u7BA1\u7406,\u4E0D\u8D70\u5F00\u5173`);
8784
8959
  }
8785
- const paths = resolveDshHookPaths(options);
8786
- const buffer = await readIfExists(paths.patchFile);
8787
- const text = buffer === void 0 ? void 0 : decodeUtf8Strict(buffer, paths.patchFile);
8788
- const blocks = text === void 0 ? [] : findToggleBlocks(text, paths.patchFile);
8960
+ const paths3 = resolveDshHookPaths(options);
8961
+ const buffer = await readIfExists(paths3.patchFile);
8962
+ const text = buffer === void 0 ? void 0 : decodeUtf8Strict(buffer, paths3.patchFile);
8963
+ const blocks = text === void 0 ? [] : findToggleBlocks(text, paths3.patchFile);
8789
8964
  const myBlock = blocks.find((b) => b.instanceId === row.id);
8790
- const entriesAll = text === void 0 ? [] : parsePatchEntries(text, paths.patchFile);
8965
+ const entriesAll = text === void 0 ? [] : parsePatchEntries(text, paths3.patchFile);
8791
8966
  const outsideToggle = text === void 0 ? "" : stripAllToggleBlocks(text, blocks);
8792
- const entriesOutsideToggle = text === void 0 ? [] : parsePatchEntries(outsideToggle, paths.patchFile);
8793
- const entriesUser = text === void 0 ? [] : parsePatchEntries(stripHooksBlocks(outsideToggle), paths.patchFile);
8967
+ const entriesOutsideToggle = text === void 0 ? [] : parsePatchEntries(outsideToggle, paths3.patchFile);
8968
+ const entriesUser = text === void 0 ? [] : parsePatchEntries(stripHooksBlocks(outsideToggle), paths3.patchFile);
8794
8969
  const refInUser = referencesInstanceId(entriesUser, row.id);
8795
8970
  const refInHooks = !refInUser && referencesInstanceId(entriesOutsideToggle, row.id);
8796
8971
  if (refInHooks) {
@@ -8802,36 +8977,36 @@ async function planDshToggle(action, dump, options) {
8802
8977
  throw new Error(`\u300C${row.name}\u300D(${row.id})\u5DF2\u7531 Wingman \u5173\u95ED(dsh \u4E0B\u6B21\u542F\u52A8\u751F\u6548);\u5982\u9700\u6062\u590D\u8BF7 toggle on`);
8803
8978
  }
8804
8979
  if (refInUser) {
8805
- throw new Error(`${paths.patchFile} \u5DF2\u6709\u7528\u6237\u81EA\u5DF1\u7684 ${row.id} \u6761\u76EE,\u4E0D\u731C\u5408\u5E76:\u8BF7\u624B\u5DE5\u5904\u7406\u8BE5\u6761\u76EE\u540E\u518D\u8BD5`);
8980
+ throw new Error(`${paths3.patchFile} \u5DF2\u6709\u7528\u6237\u81EA\u5DF1\u7684 ${row.id} \u6761\u76EE,\u4E0D\u731C\u5408\u5E76:\u8BF7\u624B\u5DE5\u5904\u7406\u8BE5\u6761\u76EE\u540E\u518D\u8BD5`);
8806
8981
  }
8807
8982
  if (row.disabled === true) {
8808
8983
  throw new Error(`\u300C${row.name}\u300D(${row.id})\u5DF2\u5728 ${item.source} \u5C42\u88AB\u7981\u7528(\u539F\u751F\u7981\u7528\u975E Wingman \u6240\u8F96),\u65E0\u9700\u518D\u5173`);
8809
8984
  }
8810
8985
  const composed = composeToggleOff(text, row.id, entriesAll.length);
8811
8986
  const expected = JSON.stringify([...entriesAll, { id: row.id, disabled: true }]);
8812
- if (JSON.stringify(parsePatchEntries(composed.after, paths.patchFile)) !== expected) {
8813
- throw new Error(`\u62D2\u5199:${paths.patchFile} \u8FFD\u52A0\u540E\u5F62\u72B6\u6821\u9A8C\u5931\u8D25(\u539F\u6587\u4EF6\u5F62\u6001\u65E0\u6CD5\u5B89\u5168\u8FFD\u52A0),\u4E0D\u731C`);
8987
+ if (JSON.stringify(parsePatchEntries(composed.after, paths3.patchFile)) !== expected) {
8988
+ throw new Error(`\u62D2\u5199:${paths3.patchFile} \u8FFD\u52A0\u540E\u5F62\u72B6\u6821\u9A8C\u5931\u8D25(\u539F\u6587\u4EF6\u5F62\u6001\u65E0\u6CD5\u5B89\u5168\u8FFD\u52A0),\u4E0D\u731C`);
8814
8989
  }
8815
- change = composed.kind === "create" || text === void 0 ? { file: paths.patchFile, kind: "create", after: composed.after } : { file: paths.patchFile, kind: "modify", before: text, after: composed.after };
8990
+ change = composed.kind === "create" || text === void 0 ? { file: paths3.patchFile, kind: "create", after: composed.after } : { file: paths3.patchFile, kind: "modify", before: text, after: composed.after };
8816
8991
  } else {
8817
8992
  if (myBlock === void 0 || text === void 0) {
8818
8993
  if (refInUser) {
8819
- throw new Error(`${paths.patchFile} \u5DF2\u6709\u7528\u6237\u81EA\u5DF1\u7684 ${row.id} \u6761\u76EE,\u4E0D\u731C\u5408\u5E76:\u8BF7\u624B\u5DE5\u5904\u7406\u8BE5\u6761\u76EE\u540E\u518D\u8BD5`);
8994
+ throw new Error(`${paths3.patchFile} \u5DF2\u6709\u7528\u6237\u81EA\u5DF1\u7684 ${row.id} \u6761\u76EE,\u4E0D\u731C\u5408\u5E76:\u8BF7\u624B\u5DE5\u5904\u7406\u8BE5\u6761\u76EE\u540E\u518D\u8BD5`);
8820
8995
  }
8821
8996
  if (row.disabled === true) {
8822
8997
  throw new Error(`\u300C${row.name}\u300D(${row.id})\u5728 ${item.source} \u5C42\u88AB\u539F\u751F\u7981\u7528,\u975E Wingman \u6240\u8F96:\u8BF7\u5230\u8BE5\u5C42(bundle/profile \u914D\u7F6E)\u4FEE\u6539`);
8823
8998
  }
8824
8999
  throw new Error(`\u300C${row.name}\u300D(${row.id})\u5DF2\u662F\u542F\u7528\u72B6\u6001,\u65E0\u9700 toggle on`);
8825
9000
  }
8826
- const composed = composeToggleOn(text, myBlock, paths.patchFile);
8827
- change = composed.kind === "delete" || composed.after === void 0 ? { file: paths.patchFile, kind: "delete", before: text } : { file: paths.patchFile, kind: "modify", before: text, after: composed.after };
9001
+ const composed = composeToggleOn(text, myBlock, paths3.patchFile);
9002
+ change = composed.kind === "delete" || composed.after === void 0 ? { file: paths3.patchFile, kind: "delete", before: text } : { file: paths3.patchFile, kind: "modify", before: text, after: composed.after };
8828
9003
  }
8829
9004
  return {
8830
9005
  harness: "dsh",
8831
9006
  action: toggle,
8832
9007
  writes: [change],
8833
- backupDir: join2(paths.backupsRoot, backupDirName()),
8834
- references: scanDshReferences(paths.patchFile, text, dump, row),
9008
+ backupDir: join3(paths3.backupsRoot, backupDirName()),
9009
+ references: scanDshReferences(paths3.patchFile, text, dump, row),
8835
9010
  // 生效时机:patch 层在 boot 时组装(composeProfile),保证下次启动生效;钉定版本
8836
9011
  // 还会 watchUserPatches 热重载家目录层,但该监听失败被静默吞掉(suppressShutdownError)
8837
9012
  // 且热拔插行为无兼容承诺 → 按宪法取保守值 next_session,如实不夸大。
@@ -8864,39 +9039,39 @@ function validatePlanShape(plan, patchFile, backupsRoot) {
8864
9039
  }
8865
9040
  async function applyDshToggle(plan, options) {
8866
9041
  try {
8867
- const paths = resolveDshHookPaths(options);
8868
- const { change } = validatePlanShape(plan, paths.patchFile, paths.backupsRoot);
8869
- const buffer = await readIfExists(paths.patchFile);
9042
+ const paths3 = resolveDshHookPaths(options);
9043
+ const { change } = validatePlanShape(plan, paths3.patchFile, paths3.backupsRoot);
9044
+ const buffer = await readIfExists(paths3.patchFile);
8870
9045
  if (change.kind === "create") {
8871
9046
  if (buffer !== void 0) {
8872
9047
  return {
8873
9048
  ok: false,
8874
- error: `${paths.patchFile} \u5728 plan \u4E4B\u540E\u88AB\u521B\u5EFA,\u4E0E plan \u524D\u63D0\u4E0D\u7B26:\u8BF7\u91CD\u65B0 plan`
9049
+ error: `${paths3.patchFile} \u5728 plan \u4E4B\u540E\u88AB\u521B\u5EFA,\u4E0E plan \u524D\u63D0\u4E0D\u7B26:\u8BF7\u91CD\u65B0 plan`
8875
9050
  };
8876
9051
  }
8877
9052
  } else {
8878
9053
  if (buffer === void 0) {
8879
9054
  return {
8880
9055
  ok: false,
8881
- error: `${paths.patchFile} \u5728 plan \u4E4B\u540E\u88AB\u5220\u9664,\u4E0E plan \u524D\u63D0\u4E0D\u7B26:\u8BF7\u91CD\u65B0 plan`
9056
+ error: `${paths3.patchFile} \u5728 plan \u4E4B\u540E\u88AB\u5220\u9664,\u4E0E plan \u524D\u63D0\u4E0D\u7B26:\u8BF7\u91CD\u65B0 plan`
8882
9057
  };
8883
9058
  }
8884
9059
  if (!buffer.equals(Buffer3.from(change.before ?? "", "utf8"))) {
8885
9060
  return {
8886
9061
  ok: false,
8887
- error: `${paths.patchFile} \u5728 plan \u4E4B\u540E\u88AB\u6539\u52A8,\u4E0E plan \u5FEB\u7167\u4E0D\u4E00\u81F4:\u8BF7\u91CD\u65B0 plan`
9062
+ error: `${paths3.patchFile} \u5728 plan \u4E4B\u540E\u88AB\u6539\u52A8,\u4E0E plan \u5FEB\u7167\u4E0D\u4E00\u81F4:\u8BF7\u91CD\u65B0 plan`
8888
9063
  };
8889
9064
  }
8890
9065
  }
8891
9066
  await mkdir2(plan.backupDir, { recursive: true });
8892
9067
  if (buffer !== void 0) {
8893
- await writeFile2(join2(plan.backupDir, "cordis.patch.yml"), buffer);
9068
+ await writeFile2(join3(plan.backupDir, "cordis.patch.yml"), buffer);
8894
9069
  }
8895
9070
  if (change.kind === "delete") {
8896
- await rm2(paths.patchFile);
9071
+ await rm2(paths3.patchFile);
8897
9072
  } else {
8898
- await mkdir2(dirname2(paths.patchFile), { recursive: true });
8899
- await writeFile2(paths.patchFile, change.after ?? "", "utf8");
9073
+ await mkdir2(dirname3(paths3.patchFile), { recursive: true });
9074
+ await writeFile2(paths3.patchFile, change.after ?? "", "utf8");
8900
9075
  }
8901
9076
  return { ok: true, backupDir: plan.backupDir };
8902
9077
  } catch (error) {
@@ -8925,55 +9100,55 @@ var init_toggle = __esm({
8925
9100
 
8926
9101
  // packages/adapter-dsh/dist/protocol.js
8927
9102
  import { execFileSync } from "node:child_process";
8928
- import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
9103
+ import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "node:fs";
8929
9104
  import { homedir as homedir2 } from "node:os";
8930
- import { basename as basename2, dirname as dirname3, join as join3, resolve } from "node:path";
9105
+ import { basename as basename3, dirname as dirname4, join as join4, resolve } from "node:path";
8931
9106
  function protocolStatusDsh(options) {
8932
- const paths = resolveOptions(options);
8933
- if (!existsSync(paths.targetPath))
8934
- return status(paths.targetPath, "not_installed", options);
9107
+ const paths3 = resolveOptions(options);
9108
+ if (!existsSync2(paths3.targetPath))
9109
+ return status(paths3.targetPath, "not_installed", options);
8935
9110
  try {
8936
- const file = readAgents(paths.targetPath);
9111
+ const file = readAgents(paths3.targetPath);
8937
9112
  if (file.identity === void 0)
8938
- return status(paths.targetPath, "not_installed", options);
9113
+ return status(paths3.targetPath, "not_installed", options);
8939
9114
  const state = stateForIdentity(file.identity);
8940
- return status(paths.targetPath, state, options, file.identity);
9115
+ return status(paths3.targetPath, state, options, file.identity);
8941
9116
  } catch (error) {
8942
- return status(paths.targetPath, "invalid", options, void 0, error.message);
9117
+ return status(paths3.targetPath, "invalid", options, void 0, error.message);
8943
9118
  }
8944
9119
  }
8945
9120
  function installProtocolDsh(options) {
8946
- const paths = resolveOptions(options);
8947
- const existing = existsSync(paths.targetPath) ? readAgents(paths.targetPath) : void 0;
9121
+ const paths3 = resolveOptions(options);
9122
+ const existing = existsSync2(paths3.targetPath) ? readAgents(paths3.targetPath) : void 0;
8948
9123
  const previousState = stateForIdentity(existing?.identity);
8949
9124
  if (previousState === "installed") {
8950
- return overlayLoadState(result(paths.targetPath, "install", false, previousState, existing?.text ?? "", true), options);
9125
+ return overlayLoadState(result2(paths3.targetPath, "install", false, previousState, existing?.text ?? "", true), options);
8951
9126
  }
8952
9127
  if (previousState === "modified")
8953
- throw modifiedError(paths.targetPath, "\u5B89\u88C5");
9128
+ throw modifiedError(paths3.targetPath, "\u5B89\u88C5");
8954
9129
  const before = existing?.text ?? "";
8955
9130
  const lineEnding = preferredMarkdownLineEnding(before);
8956
9131
  const block = buildPlanProtocolBlock().replaceAll("\n", lineEnding);
8957
9132
  const after = existing?.split.block ? existing.split.before + block + existing.split.after : appendBlock(before, block, lineEnding);
8958
- const installedRemainder = splitPlanProtocolBlock(after, paths.targetPath).remainder;
8959
- const backupDir = nextBackupDir(paths.homeDir);
8960
- if (!paths.dryRun) {
8961
- const prior = readState2(paths.statePath, paths.targetPath);
8962
- backupTarget(backupDir, paths.targetPath, existing?.bytes);
8963
- writeState2(paths.statePath, {
9133
+ const installedRemainder = splitPlanProtocolBlock(after, paths3.targetPath).remainder;
9134
+ const backupDir = nextBackupDir2(paths3.homeDir);
9135
+ if (!paths3.dryRun) {
9136
+ const prior = readState2(paths3.statePath, paths3.targetPath);
9137
+ backupTarget2(backupDir, paths3.targetPath, existing?.bytes);
9138
+ writeState2(paths3.statePath, {
8964
9139
  version: 1,
8965
- projectDir: paths.projectDir,
8966
- targetPath: paths.targetPath,
9140
+ projectDir: paths3.projectDir,
9141
+ targetPath: paths3.targetPath,
8967
9142
  protocolVersion: PLAN_PROTOCOL_VERSION,
8968
9143
  installedAt: (/* @__PURE__ */ new Date()).toISOString(),
8969
9144
  backupDir,
8970
9145
  installedRemainderSha256: sha256Hex(installedRemainder),
8971
9146
  original: prior?.original ?? (existing === void 0 ? { existed: false } : { existed: true, base64: existing.bytes.toString("base64") })
8972
9147
  });
8973
- writeFileSync(paths.targetPath, after);
9148
+ writeFileSync2(paths3.targetPath, after);
8974
9149
  }
8975
9150
  return overlayLoadState({
8976
- ...result(paths.targetPath, "install", true, previousState, before, true),
9151
+ ...result2(paths3.targetPath, "install", true, previousState, before, true),
8977
9152
  state: "installed",
8978
9153
  version: PLAN_PROTOCOL_VERSION,
8979
9154
  after,
@@ -8982,33 +9157,33 @@ function installProtocolDsh(options) {
8982
9157
  }, options);
8983
9158
  }
8984
9159
  function uninstallProtocolDsh(options) {
8985
- const paths = resolveOptions(options);
8986
- if (!existsSync(paths.targetPath)) {
8987
- return result(paths.targetPath, "uninstall", false, "not_installed", "", false);
9160
+ const paths3 = resolveOptions(options);
9161
+ if (!existsSync2(paths3.targetPath)) {
9162
+ return result2(paths3.targetPath, "uninstall", false, "not_installed", "", false);
8988
9163
  }
8989
- const existing = readAgents(paths.targetPath);
9164
+ const existing = readAgents(paths3.targetPath);
8990
9165
  if (existing.identity === void 0) {
8991
- return result(paths.targetPath, "uninstall", false, "not_installed", existing.text, true);
9166
+ return result2(paths3.targetPath, "uninstall", false, "not_installed", existing.text, true);
8992
9167
  }
8993
9168
  const previousState = stateForIdentity(existing.identity);
8994
9169
  if (previousState === "modified")
8995
- throw modifiedError(paths.targetPath, "\u5378\u8F7D");
8996
- const state = readState2(paths.statePath, paths.targetPath);
9170
+ throw modifiedError(paths3.targetPath, "\u5378\u8F7D");
9171
+ const state = readState2(paths3.statePath, paths3.targetPath);
8997
9172
  const canRestore = state !== void 0 && sha256Hex(existing.split.remainder) === state.installedRemainderSha256;
8998
9173
  const restored = canRestore ? originalBytes(state) : void 0;
8999
9174
  const deleteTarget = canRestore ? state?.original.existed === false : existing.split.remainder.trim() === "";
9000
9175
  const after = deleteTarget ? "" : restored?.toString("utf8") ?? existing.split.remainder;
9001
- const backupDir = nextBackupDir(paths.homeDir);
9002
- if (!paths.dryRun) {
9003
- backupTarget(backupDir, paths.targetPath, existing.bytes);
9176
+ const backupDir = nextBackupDir2(paths3.homeDir);
9177
+ if (!paths3.dryRun) {
9178
+ backupTarget2(backupDir, paths3.targetPath, existing.bytes);
9004
9179
  if (deleteTarget)
9005
- rmSync(paths.targetPath, { force: true });
9180
+ rmSync2(paths3.targetPath, { force: true });
9006
9181
  else
9007
- writeFileSync(paths.targetPath, restored ?? existing.split.remainder);
9008
- rmSync(paths.statePath, { force: true });
9182
+ writeFileSync2(paths3.targetPath, restored ?? existing.split.remainder);
9183
+ rmSync2(paths3.statePath, { force: true });
9009
9184
  }
9010
9185
  return {
9011
- ...result(paths.targetPath, "uninstall", true, previousState, existing.text, !deleteTarget),
9186
+ ...result2(paths3.targetPath, "uninstall", true, previousState, existing.text, !deleteTarget),
9012
9187
  state: "not_installed",
9013
9188
  message: canRestore ? `${SHARED_MESSAGE}\uFF1B\u5378\u8F7D\u540C\u65F6\u5F71\u54CD Codex \u4E0E dsh` : `${SHARED_MESSAGE}\uFF1B\u5378\u8F7D\u540C\u65F6\u5F71\u54CD Codex \u4E0E dsh\uFF1B\u5DF2\u4FDD\u7559\u7528\u6237\u6539\u52A8`,
9014
9189
  after,
@@ -9020,17 +9195,17 @@ function uninstallProtocolDsh(options) {
9020
9195
  function resolveOptions(options) {
9021
9196
  const homeDir = resolve(options?.homeDir ?? homedir2());
9022
9197
  const projectDir = resolve(options?.projectDir ?? process.cwd());
9023
- const targetPath2 = join3(projectDir, "AGENTS.md");
9198
+ const targetPath2 = join4(projectDir, "AGENTS.md");
9024
9199
  return {
9025
9200
  homeDir,
9026
9201
  projectDir,
9027
9202
  targetPath: targetPath2,
9028
- statePath: join3(homeDir, ".wingman", "state", `plan-protocol-agents-${sha256Hex(projectDir)}.json`),
9203
+ statePath: join4(homeDir, ".wingman", "state", `plan-protocol-agents-${sha256Hex(projectDir)}.json`),
9029
9204
  dryRun: options?.dryRun ?? false
9030
9205
  };
9031
9206
  }
9032
9207
  function readAgents(targetPath2) {
9033
- const bytes = readFileSync(targetPath2);
9208
+ const bytes = readFileSync2(targetPath2);
9034
9209
  const text = decodeUtf8Strict2(bytes, targetPath2);
9035
9210
  let split;
9036
9211
  try {
@@ -9078,7 +9253,7 @@ function status(targetPath2, state, options, identity, reason) {
9078
9253
  ...reason !== void 0 ? { reason } : {}
9079
9254
  };
9080
9255
  }
9081
- function result(targetPath2, operation, changed, previousState, before, afterExists) {
9256
+ function result2(targetPath2, operation, changed, previousState, before, afterExists) {
9082
9257
  return {
9083
9258
  harness: "dsh",
9084
9259
  state: previousState,
@@ -9112,7 +9287,7 @@ function agentInstructionsDisabled(options) {
9112
9287
  if (options?.dumpConfigText !== void 0)
9113
9288
  text = options.dumpConfigText;
9114
9289
  else if (options?.dumpConfigPath !== void 0)
9115
- text = readFileSync(options.dumpConfigPath, "utf8");
9290
+ text = readFileSync2(options.dumpConfigPath, "utf8");
9116
9291
  else {
9117
9292
  text = execFileSync("dsh", ["--profile", options?.profile ?? "web", "--dump-config"], {
9118
9293
  encoding: "utf8",
@@ -9129,38 +9304,41 @@ function agentInstructionsDisabled(options) {
9129
9304
  function modifiedError(targetPath2, operation) {
9130
9305
  return new Error(`${targetPath2}: \u53D7\u7BA1\u5757\u5DF2\u88AB\u4FEE\u6539\uFF0C\u62D2\u7EDD${operation}\u5E76\u4FDD\u7559\u7528\u6237\u5185\u5BB9`);
9131
9306
  }
9132
- function nextBackupDir(homeDir) {
9307
+ function nextBackupDir2(homeDir) {
9133
9308
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replaceAll(":", "-");
9134
- const root = join3(homeDir, ".wingman", "backups");
9135
- let dir = join3(root, stamp);
9136
- for (let n = 2; existsSync(dir); n += 1)
9137
- dir = join3(root, `${stamp}-${n}`);
9309
+ const root = join4(homeDir, ".wingman", "backups");
9310
+ let dir = join4(root, stamp);
9311
+ for (let n = 2; existsSync2(dir); n += 1)
9312
+ dir = join4(root, `${stamp}-${n}`);
9138
9313
  return dir;
9139
9314
  }
9140
- function backupTarget(backupDir, targetPath2, bytes) {
9141
- mkdirSync(backupDir, { recursive: true });
9315
+ function backupTarget2(backupDir, targetPath2, bytes) {
9316
+ mkdirSync2(backupDir, { recursive: true });
9142
9317
  if (bytes !== void 0)
9143
- writeFileSync(join3(backupDir, basename2(targetPath2)), bytes);
9318
+ writeFileSync2(join4(backupDir, basename3(targetPath2)), bytes);
9144
9319
  }
9145
9320
  function readState2(statePath2, targetPath2) {
9146
- if (!existsSync(statePath2))
9321
+ if (!existsSync2(statePath2))
9147
9322
  return void 0;
9148
9323
  try {
9149
- const value = JSON.parse(readFileSync(statePath2, "utf8"));
9324
+ const value = JSON.parse(readFileSync2(statePath2, "utf8"));
9150
9325
  return value.version === 1 && value.targetPath === targetPath2 ? value : void 0;
9151
9326
  } catch {
9152
9327
  return void 0;
9153
9328
  }
9154
9329
  }
9155
9330
  function writeState2(statePath2, state) {
9156
- mkdirSync(dirname3(statePath2), { recursive: true });
9157
- writeFileSync(statePath2, `${JSON.stringify(state, null, 2)}
9331
+ mkdirSync2(dirname4(statePath2), { recursive: true });
9332
+ writeFileSync2(statePath2, `${JSON.stringify(state, null, 2)}
9158
9333
  `);
9159
9334
  }
9160
9335
  function originalBytes(state) {
9161
9336
  return state.original.existed ? Buffer.from(state.original.base64 ?? "", "base64") : void 0;
9162
9337
  }
9163
- var SHARED_MESSAGE, DISABLED_MESSAGE;
9338
+ function protocolStatusDshUser(_options) {
9339
+ return { unsupported: "dsh \u6CA1\u6709\u7528\u6237\u7EA7\u6307\u4EE4\u6587\u4EF6,\u8BF7\u6309\u9879\u76EE\u5B89\u88C5" };
9340
+ }
9341
+ var SHARED_MESSAGE, DISABLED_MESSAGE, installProtocolDshUser, uninstallProtocolDshUser;
9164
9342
  var init_protocol = __esm({
9165
9343
  "packages/adapter-dsh/dist/protocol.js"() {
9166
9344
  "use strict";
@@ -9168,6 +9346,8 @@ var init_protocol = __esm({
9168
9346
  init_dump_config();
9169
9347
  SHARED_MESSAGE = "\u6B64 AGENTS.md \u534F\u8BAE\u5757\u7531 Codex \u4E0E dsh \u5171\u7528";
9170
9348
  DISABLED_MESSAGE = "dsh \u6307\u4EE4\u52A0\u8F7D\u63D2\u4EF6\u5DF2\u7981\u7528\uFF0C\u89C1\u63A7\u5236\u9875\u5F00\u5173";
9349
+ installProtocolDshUser = protocolStatusDshUser;
9350
+ uninstallProtocolDshUser = protocolStatusDshUser;
9171
9351
  }
9172
9352
  });
9173
9353
 
@@ -9183,18 +9363,21 @@ __export(dist_exports, {
9183
9363
  hasManagedHooks: () => hasManagedHooks,
9184
9364
  installDshHooks: () => installDshHooks,
9185
9365
  installProtocolDsh: () => installProtocolDsh,
9366
+ installProtocolDshUser: () => installProtocolDshUser,
9186
9367
  parseDumpConfig: () => parseDumpConfig,
9187
9368
  protocolStatusDsh: () => protocolStatusDsh,
9369
+ protocolStatusDshUser: () => protocolStatusDshUser,
9188
9370
  resolveDshHome: () => resolveDshHome,
9189
9371
  resolveDshHookPaths: () => resolveDshHookPaths,
9190
9372
  retireLegacyDshHomeHooks: () => retireLegacyDshHomeHooks,
9191
9373
  uninstallDshHooks: () => uninstallDshHooks,
9192
- uninstallProtocolDsh: () => uninstallProtocolDsh
9374
+ uninstallProtocolDsh: () => uninstallProtocolDsh,
9375
+ uninstallProtocolDshUser: () => uninstallProtocolDshUser
9193
9376
  });
9194
9377
  import { execFile } from "node:child_process";
9195
- import { existsSync as existsSync2 } from "node:fs";
9378
+ import { existsSync as existsSync3 } from "node:fs";
9196
9379
  import { readFile as readFile2 } from "node:fs/promises";
9197
- import { join as join4 } from "node:path";
9380
+ import { join as join5 } from "node:path";
9198
9381
  import { promisify } from "node:util";
9199
9382
  async function execVersionViaPath() {
9200
9383
  const { stdout } = await execFileAsync("dsh", ["-V"], {
@@ -9267,7 +9450,7 @@ function createAdapter(options = {}) {
9267
9450
  // 检测与 CC/Codex 同构:探用户 dsh 家目录(homeDir/.dsh → $DSH_HOME → ~/.dsh)是否存在。
9268
9451
  // 版本尽力:PATH 上 `dsh -V`,3 秒超时;失败不影响 installed 判定。
9269
9452
  async detect(options2) {
9270
- if (!existsSync2(resolveDshHome(options2)))
9453
+ if (!existsSync3(resolveDshHome(options2)))
9271
9454
  return { installed: false };
9272
9455
  const version = await loadVersion();
9273
9456
  return version !== void 0 ? { installed: true, version } : { installed: true };
@@ -9300,7 +9483,7 @@ function createAdapter(options = {}) {
9300
9483
  },
9301
9484
  async planAction(action, options2) {
9302
9485
  const text = await loadDumpText();
9303
- const file = dumpConfigPath ?? join4(resolveDshHookPaths(options2).dshHome, `dump-config(${profile})`);
9486
+ const file = dumpConfigPath ?? join5(resolveDshHookPaths(options2).dshHome, `dump-config(${profile})`);
9304
9487
  return await planDshToggle(action, { text, file }, options2);
9305
9488
  },
9306
9489
  async applyAction(plan, options2) {
@@ -9331,7 +9514,7 @@ var init_dist2 = __esm({
9331
9514
 
9332
9515
  // packages/adapter-cc/dist/walk.js
9333
9516
  import { readdirSync } from "node:fs";
9334
- import { join as join8, parse as parse2, resolve as resolve2 } from "node:path";
9517
+ import { join as join9, parse as parse2, resolve as resolve2 } from "node:path";
9335
9518
  function newWalkStats(entryBudget = MAX_WALK_ENTRIES) {
9336
9519
  return { unknownErrors: 0, truncated: false, entriesLeft: entryBudget };
9337
9520
  }
@@ -9358,7 +9541,7 @@ function walkFiles(dir, fileName, stats = newWalkStats()) {
9358
9541
  return;
9359
9542
  }
9360
9543
  stats.entriesLeft -= 1;
9361
- const p = join8(d, entry.name);
9544
+ const p = join9(d, entry.name);
9362
9545
  if (entry.isDirectory()) {
9363
9546
  if (entry.name.startsWith(".") || SKIP_DIR_NAMES.has(entry.name))
9364
9547
  continue;
@@ -9375,7 +9558,7 @@ function walkFiles(dir, fileName, stats = newWalkStats()) {
9375
9558
  return found;
9376
9559
  }
9377
9560
  function listMdFiles(dir, stats) {
9378
- return safeReaddir(dir, stats).map((e) => e.name).filter((n) => n.endsWith(".md")).sort().map((n) => join8(dir, n));
9561
+ return safeReaddir(dir, stats).map((e) => e.name).filter((n) => n.endsWith(".md")).sort().map((n) => join9(dir, n));
9379
9562
  }
9380
9563
  function isBareProjectDir(projectDir, homeDir) {
9381
9564
  const r = resolve2(projectDir);
@@ -9393,21 +9576,21 @@ var init_walk = __esm({
9393
9576
  });
9394
9577
 
9395
9578
  // packages/adapter-cc/dist/detect.js
9396
- import { existsSync as existsSync4, readFileSync as readFileSync4, statSync } from "node:fs";
9579
+ import { existsSync as existsSync5, readFileSync as readFileSync5, statSync } from "node:fs";
9397
9580
  import { homedir as homedir5 } from "node:os";
9398
- import { join as join9 } from "node:path";
9581
+ import { join as join10 } from "node:path";
9399
9582
  function probeVersion(homeDir, stats = newWalkStats()) {
9400
- const root = join9(homeDir, ".claude", "projects");
9583
+ const root = join10(homeDir, ".claude", "projects");
9401
9584
  let latest;
9402
9585
  for (const entry of safeReaddir(root, stats)) {
9403
9586
  if (!entry.isDirectory())
9404
9587
  continue;
9405
- const dir = join9(root, entry.name);
9588
+ const dir = join10(root, entry.name);
9406
9589
  for (const sub of safeReaddir(dir, stats)) {
9407
9590
  const name = sub.name;
9408
9591
  if (!name.endsWith(".jsonl"))
9409
9592
  continue;
9410
- const file = join9(dir, name);
9593
+ const file = join10(dir, name);
9411
9594
  let mtimeMs;
9412
9595
  try {
9413
9596
  mtimeMs = statSync(file).mtimeMs;
@@ -9423,7 +9606,7 @@ function probeVersion(homeDir, stats = newWalkStats()) {
9423
9606
  return void 0;
9424
9607
  let lines2;
9425
9608
  try {
9426
- lines2 = readFileSync4(latest.file, "utf8").split("\n");
9609
+ lines2 = readFileSync5(latest.file, "utf8").split("\n");
9427
9610
  } catch (error) {
9428
9611
  recordWalkError(error, stats);
9429
9612
  return void 0;
@@ -9443,7 +9626,7 @@ function probeVersion(homeDir, stats = newWalkStats()) {
9443
9626
  }
9444
9627
  async function detectCc(options) {
9445
9628
  const homeDir = options?.homeDir ?? homedir5();
9446
- const installed = existsSync4(join9(homeDir, ".claude")) || existsSync4(join9(homeDir, ".claude.json"));
9629
+ const installed = existsSync5(join10(homeDir, ".claude")) || existsSync5(join10(homeDir, ".claude.json"));
9447
9630
  if (!installed)
9448
9631
  return { installed: false };
9449
9632
  const version = probeVersion(homeDir);
@@ -9458,11 +9641,11 @@ var init_detect = __esm({
9458
9641
 
9459
9642
  // packages/adapter-cc/dist/scan.js
9460
9643
  import { Buffer as Buffer4 } from "node:buffer";
9461
- import { existsSync as existsSync5, readFileSync as readFileSync5, statSync as statSync2 } from "node:fs";
9644
+ import { existsSync as existsSync6, readFileSync as readFileSync6, statSync as statSync2 } from "node:fs";
9462
9645
  import { homedir as homedir6 } from "node:os";
9463
- import { basename as basename3, dirname as dirname6, join as join10, resolve as resolve3, sep } from "node:path";
9646
+ import { basename as basename4, dirname as dirname7, join as join11, resolve as resolve3, sep } from "node:path";
9464
9647
  function readJsonFile(file) {
9465
- const text = readFileSync5(file, "utf8");
9648
+ const text = readFileSync6(file, "utf8");
9466
9649
  try {
9467
9650
  return JSON.parse(text);
9468
9651
  } catch (e) {
@@ -9478,13 +9661,13 @@ function recordField(v, key) {
9478
9661
  }
9479
9662
  function readSettingsChain(homeDir, projectDir) {
9480
9663
  const chain = [
9481
- { file: join10(homeDir, ".claude", "settings.json"), source: "user" },
9482
- { file: join10(projectDir, ".claude", "settings.json"), source: "project" },
9483
- { file: join10(projectDir, ".claude", "settings.local.json"), source: "local" }
9664
+ { file: join11(homeDir, ".claude", "settings.json"), source: "user" },
9665
+ { file: join11(projectDir, ".claude", "settings.json"), source: "project" },
9666
+ { file: join11(projectDir, ".claude", "settings.local.json"), source: "local" }
9484
9667
  ];
9485
9668
  const out = [];
9486
9669
  for (const { file, source } of chain) {
9487
- if (!existsSync5(file))
9670
+ if (!existsSync6(file))
9488
9671
  continue;
9489
9672
  const data = asRecord(readJsonFile(file));
9490
9673
  if (!data)
@@ -9527,7 +9710,7 @@ function ruleItem(file, source, stats) {
9527
9710
  return {
9528
9711
  id: "",
9529
9712
  slot: "rules",
9530
- nativeName: basename3(file),
9713
+ nativeName: basename4(file),
9531
9714
  nativePath: file,
9532
9715
  tokens: estimateTokens(statSync2(file).size),
9533
9716
  residency: "resident",
@@ -9547,20 +9730,20 @@ function buildRules(homeDir, projectDir, stats) {
9547
9730
  if (item !== void 0)
9548
9731
  items.push(item);
9549
9732
  };
9550
- const userClaudeMd = join10(homeDir, ".claude", "CLAUDE.md");
9551
- if (existsSync5(userClaudeMd))
9733
+ const userClaudeMd = join11(homeDir, ".claude", "CLAUDE.md");
9734
+ if (existsSync6(userClaudeMd))
9552
9735
  append(userClaudeMd, "user");
9553
- for (const f of listMdFiles(join10(homeDir, ".claude", "rules"), stats))
9736
+ for (const f of listMdFiles(join11(homeDir, ".claude", "rules"), stats))
9554
9737
  append(f, "user");
9555
9738
  if (isBareProjectDir(projectDir, homeDir)) {
9556
- const direct = join10(projectDir, "CLAUDE.md");
9557
- if (existsSync5(direct))
9739
+ const direct = join11(projectDir, "CLAUDE.md");
9740
+ if (existsSync6(direct))
9558
9741
  append(direct, "project");
9559
9742
  } else {
9560
9743
  for (const f of walkFiles(projectDir, "CLAUDE.md", stats))
9561
9744
  append(f, "project");
9562
9745
  }
9563
- for (const f of listMdFiles(join10(projectDir, ".claude", "rules"), stats)) {
9746
+ for (const f of listMdFiles(join11(projectDir, ".claude", "rules"), stats)) {
9564
9747
  append(f, "project");
9565
9748
  }
9566
9749
  return items;
@@ -9583,14 +9766,14 @@ function parseSkillFrontmatter(content) {
9583
9766
  return out;
9584
9767
  }
9585
9768
  function buildSkills(homeDir, projectDir, overrides, stats) {
9586
- const userRoot = join10(homeDir, ".claude", "skills");
9587
- const syncedRoot = join10(userRoot, "synced");
9769
+ const userRoot = join11(homeDir, ".claude", "skills");
9770
+ const syncedRoot = join11(userRoot, "synced");
9588
9771
  const roots = [
9589
9772
  { root: userRoot, source: "user", exclude: syncedRoot },
9590
9773
  // projectDir 为家目录时,项目 skills 根与 user 根是同一目录,再走一遍会把每个
9591
9774
  // skill 重复列为 project 层;bare root 无项目上下文 → 不设项目 skills 根
9592
- ...isBareProjectDir(projectDir, homeDir) ? [] : [{ root: join10(projectDir, ".claude", "skills"), source: "project" }],
9593
- { root: join10(homeDir, ".claude", "plugins"), source: "plugin" },
9775
+ ...isBareProjectDir(projectDir, homeDir) ? [] : [{ root: join11(projectDir, ".claude", "skills"), source: "project" }],
9776
+ { root: join11(homeDir, ".claude", "plugins"), source: "plugin" },
9594
9777
  { root: syncedRoot, source: "synced" }
9595
9778
  ];
9596
9779
  const items = [];
@@ -9599,8 +9782,8 @@ function buildSkills(homeDir, projectDir, overrides, stats) {
9599
9782
  if (exclude && (skillFile === exclude || skillFile.startsWith(exclude + sep)))
9600
9783
  continue;
9601
9784
  try {
9602
- const fm = parseSkillFrontmatter(readFileSync5(skillFile, "utf8"));
9603
- const name = fm.name ?? basename3(dirname6(skillFile));
9785
+ const fm = parseSkillFrontmatter(readFileSync6(skillFile, "utf8"));
9786
+ const name = fm.name ?? basename4(dirname7(skillFile));
9604
9787
  const size = statSync2(skillFile).size;
9605
9788
  items.push({
9606
9789
  id: "",
@@ -9624,9 +9807,9 @@ function buildSkills(homeDir, projectDir, overrides, stats) {
9624
9807
  }
9625
9808
  function buildTools(homeDir, projectDir) {
9626
9809
  const items = [];
9627
- const claudeJsonPath = join10(homeDir, ".claude.json");
9810
+ const claudeJsonPath = join11(homeDir, ".claude.json");
9628
9811
  let claudeJson;
9629
- if (existsSync5(claudeJsonPath))
9812
+ if (existsSync6(claudeJsonPath))
9630
9813
  claudeJson = asRecord(readJsonFile(claudeJsonPath));
9631
9814
  const projectEntry = recordField(claudeJson?.projects, resolve3(projectDir));
9632
9815
  const disabledRaw = projectEntry?.disabledMcpServers;
@@ -9650,8 +9833,8 @@ function buildTools(homeDir, projectDir) {
9650
9833
  for (const name of Object.keys(localServers).sort()) {
9651
9834
  items.push(mcpItem(name, "local", claudeJsonPath));
9652
9835
  }
9653
- const mcpJsonPath = join10(projectDir, ".mcp.json");
9654
- if (existsSync5(mcpJsonPath)) {
9836
+ const mcpJsonPath = join11(projectDir, ".mcp.json");
9837
+ if (existsSync6(mcpJsonPath)) {
9655
9838
  const projectServers = recordField(readJsonFile(mcpJsonPath), "mcpServers") ?? {};
9656
9839
  for (const name of Object.keys(projectServers).sort()) {
9657
9840
  items.push(mcpItem(name, "project", mcpJsonPath));
@@ -9697,7 +9880,7 @@ function lastContextTotal(file, stats) {
9697
9880
  let total;
9698
9881
  let text;
9699
9882
  try {
9700
- text = readFileSync5(file, "utf8");
9883
+ text = readFileSync6(file, "utf8");
9701
9884
  } catch (error) {
9702
9885
  recordWalkError(error, stats);
9703
9886
  return void 0;
@@ -9725,10 +9908,10 @@ function lastContextTotal(file, stats) {
9725
9908
  return total;
9726
9909
  }
9727
9910
  function buildHistory(homeDir, projectDir, stats) {
9728
- const dir = join10(homeDir, ".claude", "projects", projectSlug(projectDir));
9911
+ const dir = join11(homeDir, ".claude", "projects", projectSlug(projectDir));
9729
9912
  const items = [];
9730
9913
  for (const name of safeReaddir(dir, stats).map((e) => e.name).filter((n) => n.endsWith(".jsonl")).sort()) {
9731
- const file = join10(dir, name);
9914
+ const file = join11(dir, name);
9732
9915
  const total = lastContextTotal(file, stats);
9733
9916
  if (total === void 0)
9734
9917
  continue;
@@ -9839,9 +10022,9 @@ var init_scan = __esm({
9839
10022
  });
9840
10023
 
9841
10024
  // packages/adapter-cc/dist/actions.js
9842
- import { existsSync as existsSync6, mkdirSync as mkdirSync3, readFileSync as readFileSync6, rmSync as rmSync2, writeFileSync as writeFileSync4 } from "node:fs";
10025
+ import { existsSync as existsSync7, mkdirSync as mkdirSync4, readFileSync as readFileSync7, rmSync as rmSync3, writeFileSync as writeFileSync5 } from "node:fs";
9843
10026
  import { homedir as homedir7 } from "node:os";
9844
- import { basename as basename4, dirname as dirname7, join as join11, resolve as resolve4 } from "node:path";
10027
+ import { basename as basename5, dirname as dirname8, join as join12, resolve as resolve4 } from "node:path";
9845
10028
  function asRecord2(v) {
9846
10029
  return typeof v === "object" && v !== null && !Array.isArray(v) ? v : void 0;
9847
10030
  }
@@ -9865,10 +10048,10 @@ function deepEqual(a, b) {
9865
10048
  }
9866
10049
  function backupDirPath(homeDir) {
9867
10050
  const ts = (/* @__PURE__ */ new Date()).toISOString().replaceAll(":", "-");
9868
- const root = join11(homeDir, ".wingman", "backups");
9869
- let dir = join11(root, ts);
9870
- for (let n = 2; existsSync6(dir); n++)
9871
- dir = join11(root, `${ts}-${n}`);
10051
+ const root = join12(homeDir, ".wingman", "backups");
10052
+ let dir = join12(root, ts);
10053
+ for (let n = 2; existsSync7(dir); n++)
10054
+ dir = join12(root, `${ts}-${n}`);
9872
10055
  return dir;
9873
10056
  }
9874
10057
  function decodeUtf8Strict3(buffer, file) {
@@ -9880,15 +10063,15 @@ function decodeUtf8Strict3(buffer, file) {
9880
10063
  }
9881
10064
  function readSettingsSnapshots(homeDir, projectDir) {
9882
10065
  const files = [
9883
- join11(homeDir, ".claude", "settings.json"),
9884
- join11(projectDir, ".claude", "settings.json"),
9885
- join11(projectDir, ".claude", "settings.local.json")
10066
+ join12(homeDir, ".claude", "settings.json"),
10067
+ join12(projectDir, ".claude", "settings.json"),
10068
+ join12(projectDir, ".claude", "settings.local.json")
9886
10069
  ];
9887
10070
  const out = [];
9888
10071
  for (const file of files) {
9889
- if (!existsSync6(file))
10072
+ if (!existsSync7(file))
9890
10073
  continue;
9891
- const raw = decodeUtf8Strict3(readFileSync6(file), file);
10074
+ const raw = decodeUtf8Strict3(readFileSync7(file), file);
9892
10075
  let parsed;
9893
10076
  try {
9894
10077
  parsed = JSON.parse(raw);
@@ -9911,7 +10094,7 @@ function overridesRecord(s) {
9911
10094
  return rec;
9912
10095
  }
9913
10096
  function skillTargetFile(item, homeDir, projectDir) {
9914
- return item.source === "project" ? join11(projectDir, ".claude", "settings.json") : join11(homeDir, ".claude", "settings.json");
10097
+ return item.source === "project" ? join12(projectDir, ".claude", "settings.json") : join12(homeDir, ".claude", "settings.json");
9915
10098
  }
9916
10099
  function planSkillToggle(item, enable, homeDir, projectDir) {
9917
10100
  const name = item.nativeName;
@@ -9964,11 +10147,11 @@ function planSkillToggle(item, enable, homeDir, projectDir) {
9964
10147
  });
9965
10148
  }
9966
10149
  function planMcpToggle(name, enable, homeDir, projectDir) {
9967
- const file = join11(homeDir, ".claude.json");
9968
- if (!existsSync6(file)) {
10150
+ const file = join12(homeDir, ".claude.json");
10151
+ if (!existsSync7(file)) {
9969
10152
  throw new Error(`\u62D2\u7EDD:\u627E\u4E0D\u5230 ${file}(MCP \u8FDE\u63A5\u5F00\u5173\u6309\u9879\u76EE\u5B58\u653E\u4E8E\u8BE5\u6587\u4EF6)`);
9970
10153
  }
9971
- const raw = readFileSync6(file, "utf8");
10154
+ const raw = readFileSync7(file, "utf8");
9972
10155
  let parsed;
9973
10156
  try {
9974
10157
  parsed = JSON.parse(raw);
@@ -10042,24 +10225,24 @@ function collectRefSources(homeDir, projectDir, exclude) {
10042
10225
  sources.push({ file, text });
10043
10226
  };
10044
10227
  const pushFile = (file) => {
10045
- if (!seen.has(file) && existsSync6(file))
10046
- push(file, readFileSync6(file, "utf8"));
10228
+ if (!seen.has(file) && existsSync7(file))
10229
+ push(file, readFileSync7(file, "utf8"));
10047
10230
  };
10048
10231
  const bareRoot = isBareProjectDir(projectDir, homeDir);
10049
- pushFile(join11(homeDir, ".claude", "CLAUDE.md"));
10050
- for (const f of listMdFiles(join11(homeDir, ".claude", "rules")))
10232
+ pushFile(join12(homeDir, ".claude", "CLAUDE.md"));
10233
+ for (const f of listMdFiles(join12(homeDir, ".claude", "rules")))
10051
10234
  pushFile(f);
10052
10235
  if (bareRoot)
10053
- pushFile(join11(projectDir, "CLAUDE.md"));
10236
+ pushFile(join12(projectDir, "CLAUDE.md"));
10054
10237
  else
10055
10238
  for (const f of walkFiles(projectDir, "CLAUDE.md"))
10056
10239
  pushFile(f);
10057
- for (const f of listMdFiles(join11(projectDir, ".claude", "rules")))
10240
+ for (const f of listMdFiles(join12(projectDir, ".claude", "rules")))
10058
10241
  pushFile(f);
10059
10242
  const skillRoots = [
10060
- join11(homeDir, ".claude", "skills"),
10061
- ...bareRoot ? [] : [join11(projectDir, ".claude", "skills")],
10062
- join11(homeDir, ".claude", "plugins")
10243
+ join12(homeDir, ".claude", "skills"),
10244
+ ...bareRoot ? [] : [join12(projectDir, ".claude", "skills")],
10245
+ join12(homeDir, ".claude", "plugins")
10063
10246
  ];
10064
10247
  for (const root of skillRoots) {
10065
10248
  for (const f of walkFiles(root, "SKILL.md")) {
@@ -10068,20 +10251,20 @@ function collectRefSources(homeDir, projectDir, exclude) {
10068
10251
  }
10069
10252
  }
10070
10253
  for (const dir of [
10071
- join11(homeDir, ".claude", "agents"),
10072
- join11(projectDir, ".claude", "agents"),
10073
- join11(homeDir, ".claude", "commands"),
10074
- join11(projectDir, ".claude", "commands")
10254
+ join12(homeDir, ".claude", "agents"),
10255
+ join12(projectDir, ".claude", "agents"),
10256
+ join12(homeDir, ".claude", "commands"),
10257
+ join12(projectDir, ".claude", "commands")
10075
10258
  ]) {
10076
10259
  for (const f of listMdFiles(dir))
10077
10260
  pushFile(f);
10078
10261
  }
10079
10262
  for (const s of readSettingsSnapshots(homeDir, projectDir))
10080
10263
  push(s.file, s.raw);
10081
- for (const file of [join11(projectDir, ".mcp.json"), join11(homeDir, ".claude.json")]) {
10082
- if (seen.has(file) || !existsSync6(file))
10264
+ for (const file of [join12(projectDir, ".mcp.json"), join12(homeDir, ".claude.json")]) {
10265
+ if (seen.has(file) || !existsSync7(file))
10083
10266
  continue;
10084
- const raw = readFileSync6(file, "utf8");
10267
+ const raw = readFileSync7(file, "utf8");
10085
10268
  let parsed;
10086
10269
  try {
10087
10270
  parsed = JSON.parse(raw);
@@ -10188,14 +10371,14 @@ async function applyActionCc(plan, _options) {
10188
10371
  const currentByFile = /* @__PURE__ */ new Map();
10189
10372
  for (const w of plan.writes) {
10190
10373
  if (w.kind === "create") {
10191
- if (existsSync6(w.file)) {
10374
+ if (existsSync7(w.file)) {
10192
10375
  return { ok: false, error: `\u62D2\u7EDD\u6267\u884C:${w.file} \u5728 plan \u540E\u88AB\u521B\u5EFA,\u8BF7\u91CD\u65B0 plan` };
10193
10376
  }
10194
10377
  } else {
10195
- if (!existsSync6(w.file)) {
10378
+ if (!existsSync7(w.file)) {
10196
10379
  return { ok: false, error: `\u62D2\u7EDD\u6267\u884C:${w.file} \u5DF2\u4E0D\u5B58\u5728(plan \u540E\u88AB\u6539\u52A8),\u8BF7\u91CD\u65B0 plan` };
10197
10380
  }
10198
- const currentRaw = readFileSync6(w.file);
10381
+ const currentRaw = readFileSync7(w.file);
10199
10382
  if (!currentRaw.equals(Buffer.from(w.before, "utf8"))) {
10200
10383
  return { ok: false, error: `\u62D2\u7EDD\u6267\u884C:${w.file} \u5728 plan \u540E\u88AB\u6539\u8FC7,\u8BF7\u91CD\u65B0 plan` };
10201
10384
  }
@@ -10203,15 +10386,15 @@ async function applyActionCc(plan, _options) {
10203
10386
  }
10204
10387
  }
10205
10388
  const toBackup = plan.writes.filter((w) => w.kind !== "create");
10206
- mkdirSync3(plan.backupDir, { recursive: true });
10389
+ mkdirSync4(plan.backupDir, { recursive: true });
10207
10390
  const manifestFiles = toBackup.map((w, i) => ({
10208
- backup: `${i}-${basename4(w.file)}`,
10391
+ backup: `${i}-${basename5(w.file)}`,
10209
10392
  target: w.file
10210
10393
  }));
10211
10394
  toBackup.forEach((w, i) => {
10212
- writeFileSync4(join11(plan.backupDir, `${i}-${basename4(w.file)}`), currentByFile.get(w.file));
10395
+ writeFileSync5(join12(plan.backupDir, `${i}-${basename5(w.file)}`), currentByFile.get(w.file));
10213
10396
  });
10214
- writeFileSync4(join11(plan.backupDir, "manifest.json"), serialize({
10397
+ writeFileSync5(join12(plan.backupDir, "manifest.json"), serialize({
10215
10398
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
10216
10399
  harness: "cc",
10217
10400
  action: plan.action,
@@ -10221,10 +10404,10 @@ async function applyActionCc(plan, _options) {
10221
10404
  try {
10222
10405
  for (const w of plan.writes) {
10223
10406
  if (w.kind === "delete") {
10224
- rmSync2(w.file);
10407
+ rmSync3(w.file);
10225
10408
  } else {
10226
- mkdirSync3(dirname7(w.file), { recursive: true });
10227
- writeFileSync4(w.file, w.after ?? "");
10409
+ mkdirSync4(dirname8(w.file), { recursive: true });
10410
+ writeFileSync5(w.file, w.after ?? "");
10228
10411
  }
10229
10412
  written.push(w);
10230
10413
  }
@@ -10233,9 +10416,9 @@ async function applyActionCc(plan, _options) {
10233
10416
  for (const w of written) {
10234
10417
  try {
10235
10418
  if (w.kind === "create")
10236
- rmSync2(w.file, { force: true });
10419
+ rmSync3(w.file, { force: true });
10237
10420
  else
10238
- writeFileSync4(w.file, w.before ?? "");
10421
+ writeFileSync5(w.file, w.before ?? "");
10239
10422
  } catch {
10240
10423
  failures.push(w.file);
10241
10424
  }
@@ -10244,12 +10427,12 @@ async function applyActionCc(plan, _options) {
10244
10427
  return { ok: false, error: `\u5199\u5165\u5931\u8D25:${e.message};${rollbackNote}` };
10245
10428
  }
10246
10429
  for (const w of plan.writes) {
10247
- if (basename4(w.file) !== ".claude.json" || w.kind !== "modify" || w.after === void 0) {
10430
+ if (basename5(w.file) !== ".claude.json" || w.kind !== "modify" || w.after === void 0) {
10248
10431
  continue;
10249
10432
  }
10250
10433
  let verified = false;
10251
10434
  try {
10252
- verified = deepEqual(JSON.parse(readFileSync6(w.file, "utf8")), JSON.parse(w.after));
10435
+ verified = deepEqual(JSON.parse(readFileSync7(w.file, "utf8")), JSON.parse(w.after));
10253
10436
  } catch {
10254
10437
  verified = false;
10255
10438
  }
@@ -10275,9 +10458,9 @@ var init_actions = __esm({
10275
10458
  });
10276
10459
 
10277
10460
  // packages/adapter-cc/dist/hooks.js
10278
- import { existsSync as existsSync7, mkdirSync as mkdirSync4, readFileSync as readFileSync7, rmSync as rmSync3, writeFileSync as writeFileSync5 } from "node:fs";
10461
+ import { existsSync as existsSync8, mkdirSync as mkdirSync5, readFileSync as readFileSync8, rmSync as rmSync4, writeFileSync as writeFileSync6 } from "node:fs";
10279
10462
  import { homedir as homedir8 } from "node:os";
10280
- import { dirname as dirname8, join as join12 } from "node:path";
10463
+ import { dirname as dirname9, join as join13 } from "node:path";
10281
10464
  function wingmanUrl(port) {
10282
10465
  return `http://127.0.0.1:${port}${SIGNATURE}`;
10283
10466
  }
@@ -10289,18 +10472,18 @@ function isWingmanHandler(h) {
10289
10472
  return rec?.type === "http" && typeof rec.url === "string" && rec.url.includes(SIGNATURE);
10290
10473
  }
10291
10474
  function wingmanRoot(homeDir) {
10292
- return join12(homeDir, ".wingman");
10475
+ return join13(homeDir, ".wingman");
10293
10476
  }
10294
10477
  function statePath(homeDir) {
10295
- return join12(wingmanRoot(homeDir), "state", "cc-hooks.json");
10478
+ return join13(wingmanRoot(homeDir), "state", "cc-hooks.json");
10296
10479
  }
10297
10480
  function readState3(homeDir) {
10298
10481
  const file = statePath(homeDir);
10299
- if (!existsSync7(file))
10482
+ if (!existsSync8(file))
10300
10483
  return void 0;
10301
10484
  let parsed;
10302
10485
  try {
10303
- parsed = JSON.parse(readFileSync7(file, "utf8"));
10486
+ parsed = JSON.parse(readFileSync8(file, "utf8"));
10304
10487
  } catch {
10305
10488
  return void 0;
10306
10489
  }
@@ -10321,23 +10504,23 @@ function readState3(homeDir) {
10321
10504
  }
10322
10505
  function writeState3(homeDir, state) {
10323
10506
  const file = statePath(homeDir);
10324
- mkdirSync4(dirname8(file), { recursive: true });
10325
- writeFileSync5(file, `${JSON.stringify(state, null, 2)}
10507
+ mkdirSync5(dirname9(file), { recursive: true });
10508
+ writeFileSync6(file, `${JSON.stringify(state, null, 2)}
10326
10509
  `);
10327
10510
  }
10328
10511
  function makeBackupDir(homeDir) {
10329
10512
  const ts = (/* @__PURE__ */ new Date()).toISOString().replaceAll(":", "-");
10330
- const root = join12(wingmanRoot(homeDir), "backups");
10331
- let dir = join12(root, ts);
10332
- for (let n = 2; existsSync7(dir); n++)
10333
- dir = join12(root, `${ts}-${n}`);
10334
- mkdirSync4(dir, { recursive: true });
10513
+ const root = join13(wingmanRoot(homeDir), "backups");
10514
+ let dir = join13(root, ts);
10515
+ for (let n = 2; existsSync8(dir); n++)
10516
+ dir = join13(root, `${ts}-${n}`);
10517
+ mkdirSync5(dir, { recursive: true });
10335
10518
  return dir;
10336
10519
  }
10337
- function readTarget(target) {
10338
- if (!existsSync7(target))
10520
+ function readTarget2(target) {
10521
+ if (!existsSync8(target))
10339
10522
  return { bytes: null, settings: {} };
10340
- const bytes = readFileSync7(target, "utf8");
10523
+ const bytes = readFileSync8(target, "utf8");
10341
10524
  let parsed;
10342
10525
  try {
10343
10526
  parsed = JSON.parse(bytes);
@@ -10440,13 +10623,13 @@ function deepEqual2(a, b) {
10440
10623
  return false;
10441
10624
  }
10442
10625
  function targetPath(homeDir) {
10443
- return join12(homeDir, ".claude", "settings.json");
10626
+ return join13(homeDir, ".claude", "settings.json");
10444
10627
  }
10445
10628
  async function installHooksCc(port, options) {
10446
10629
  const homeDir = options?.homeDir ?? homedir8();
10447
10630
  const target = targetPath(homeDir);
10448
10631
  const url = wingmanUrl(port);
10449
- const { bytes, settings } = readTarget(target);
10632
+ const { bytes, settings } = readTarget2(target);
10450
10633
  if (isFullyWired(settings, url))
10451
10634
  return;
10452
10635
  if (settings.hooks !== void 0 && !asRecord3(settings.hooks)) {
@@ -10462,7 +10645,7 @@ async function installHooksCc(port, options) {
10462
10645
  }
10463
10646
  const backupDir = makeBackupDir(homeDir);
10464
10647
  if (bytes !== null)
10465
- writeFileSync5(join12(backupDir, "settings.json"), bytes);
10648
+ writeFileSync6(join13(backupDir, "settings.json"), bytes);
10466
10649
  const prev = readState3(homeDir);
10467
10650
  const now = (/* @__PURE__ */ new Date()).toISOString();
10468
10651
  writeState3(homeDir, prev ? { ...prev, port, installedAt: now } : { target, original: bytes, backupDir, port, installedAt: now });
@@ -10474,44 +10657,44 @@ async function installHooksCc(port, options) {
10474
10657
  groups.push({ hooks: [{ type: "http", url }] });
10475
10658
  hooks[event] = groups;
10476
10659
  }
10477
- mkdirSync4(dirname8(target), { recursive: true });
10478
- writeFileSync5(target, `${JSON.stringify(settings, null, 2)}
10660
+ mkdirSync5(dirname9(target), { recursive: true });
10661
+ writeFileSync6(target, `${JSON.stringify(settings, null, 2)}
10479
10662
  `);
10480
10663
  }
10481
10664
  async function uninstallHooksCc(options) {
10482
10665
  const homeDir = options?.homeDir ?? homedir8();
10483
10666
  const target = targetPath(homeDir);
10484
10667
  const state = readState3(homeDir);
10485
- if (!existsSync7(target)) {
10486
- rmSync3(statePath(homeDir), { force: true });
10668
+ if (!existsSync8(target)) {
10669
+ rmSync4(statePath(homeDir), { force: true });
10487
10670
  return;
10488
10671
  }
10489
- const { bytes, settings } = readTarget(target);
10672
+ const { bytes, settings } = readTarget2(target);
10490
10673
  const changed = removeWingmanEntries(settings);
10491
10674
  if (!changed) {
10492
- rmSync3(statePath(homeDir), { force: true });
10675
+ rmSync4(statePath(homeDir), { force: true });
10493
10676
  return;
10494
10677
  }
10495
10678
  const backupDir = makeBackupDir(homeDir);
10496
10679
  if (bytes !== null)
10497
- writeFileSync5(join12(backupDir, "settings.json"), bytes);
10680
+ writeFileSync6(join13(backupDir, "settings.json"), bytes);
10498
10681
  if (state && state.original !== null) {
10499
10682
  const originalParsed = asRecord3(JSON.parse(state.original));
10500
10683
  if (originalParsed && deepEqual2(normalizeForCompare(settings), normalizeForCompare(originalParsed))) {
10501
- writeFileSync5(target, state.original);
10502
- rmSync3(statePath(homeDir), { force: true });
10684
+ writeFileSync6(target, state.original);
10685
+ rmSync4(statePath(homeDir), { force: true });
10503
10686
  return;
10504
10687
  }
10505
10688
  } else if (state && state.original === null) {
10506
10689
  if (deepEqual2(normalizeForCompare(settings), {})) {
10507
- rmSync3(target, { force: true });
10508
- rmSync3(statePath(homeDir), { force: true });
10690
+ rmSync4(target, { force: true });
10691
+ rmSync4(statePath(homeDir), { force: true });
10509
10692
  return;
10510
10693
  }
10511
10694
  }
10512
- writeFileSync5(target, `${JSON.stringify(settings, null, 2)}
10695
+ writeFileSync6(target, `${JSON.stringify(settings, null, 2)}
10513
10696
  `);
10514
- rmSync3(statePath(homeDir), { force: true });
10697
+ rmSync4(statePath(homeDir), { force: true });
10515
10698
  }
10516
10699
  var WIRED_EVENTS, SIGNATURE;
10517
10700
  var init_hooks2 = __esm({
@@ -10532,60 +10715,60 @@ var init_hooks2 = __esm({
10532
10715
  });
10533
10716
 
10534
10717
  // packages/adapter-cc/dist/protocol.js
10535
- import { existsSync as existsSync8, mkdirSync as mkdirSync5, readdirSync as readdirSync2, readFileSync as readFileSync8, rmdirSync, rmSync as rmSync4, writeFileSync as writeFileSync6 } from "node:fs";
10718
+ import { existsSync as existsSync9, mkdirSync as mkdirSync6, readdirSync as readdirSync2, readFileSync as readFileSync9, rmdirSync, rmSync as rmSync5, writeFileSync as writeFileSync7 } from "node:fs";
10536
10719
  import { homedir as homedir9 } from "node:os";
10537
- import { basename as basename5, dirname as dirname9, join as join13, resolve as resolve5 } from "node:path";
10720
+ import { basename as basename6, dirname as dirname10, join as join14, resolve as resolve5 } from "node:path";
10538
10721
  function protocolStatusCc(options) {
10539
- const paths = resolveOptions2(options);
10540
- if (!existsSync8(paths.targetPath)) {
10541
- return { harness: "cc", state: "not_installed", targetPath: paths.targetPath };
10722
+ const paths3 = resolveOptions2(options);
10723
+ if (!existsSync9(paths3.targetPath)) {
10724
+ return { harness: "cc", state: "not_installed", targetPath: paths3.targetPath };
10542
10725
  }
10543
10726
  try {
10544
- return statusFromIdentity(paths.targetPath, inspectPlanProtocolFile(readFileSync8(paths.targetPath), paths.targetPath));
10727
+ return statusFromIdentity(paths3.targetPath, inspectPlanProtocolFile(readFileSync9(paths3.targetPath), paths3.targetPath));
10545
10728
  } catch (error) {
10546
10729
  return {
10547
10730
  harness: "cc",
10548
10731
  state: "invalid",
10549
- targetPath: paths.targetPath,
10732
+ targetPath: paths3.targetPath,
10550
10733
  reason: error.message
10551
10734
  };
10552
10735
  }
10553
10736
  }
10554
10737
  function installProtocolCc(options) {
10555
- const paths = resolveOptions2(options);
10556
- const existing = readExisting(paths.targetPath);
10738
+ const paths3 = resolveOptions2(options);
10739
+ const existing = readExisting(paths3.targetPath);
10557
10740
  const previousState = stateForIdentity2(existing?.identity);
10558
10741
  if (previousState === "installed") {
10559
- return result2(paths.targetPath, "install", false, previousState, existing?.text ?? "", true);
10742
+ return result3(paths3.targetPath, "install", false, previousState, existing?.text ?? "", true);
10560
10743
  }
10561
10744
  if (previousState === "modified")
10562
- throw modifiedError2(paths.targetPath, "\u5B89\u88C5");
10745
+ throw modifiedError2(paths3.targetPath, "\u5B89\u88C5");
10563
10746
  const before = existing?.text ?? "";
10564
- const backupDir = nextBackupDir2(paths.homeDir);
10747
+ const backupDir = nextBackupDir3(paths3.homeDir);
10565
10748
  const installedSha256 = sha256Hex(PLAN_PROTOCOL_TEXT);
10566
- if (!paths.dryRun) {
10567
- const claudeDir = join13(paths.projectDir, ".claude");
10568
- const rulesDir = dirname9(paths.targetPath);
10569
- const prior = readState4(paths.statePath);
10570
- backupTarget2(backupDir, paths.targetPath, existing?.bytes);
10571
- writeState4(paths.statePath, {
10749
+ if (!paths3.dryRun) {
10750
+ const claudeDir = join14(paths3.projectDir, ".claude");
10751
+ const rulesDir = dirname10(paths3.targetPath);
10752
+ const prior = readState4(paths3.statePath);
10753
+ backupTarget3(backupDir, paths3.targetPath, existing?.bytes);
10754
+ writeState4(paths3.statePath, {
10572
10755
  version: 1,
10573
10756
  harness: "cc",
10574
- projectDir: paths.projectDir,
10575
- targetPath: paths.targetPath,
10757
+ projectDir: paths3.projectDir,
10758
+ targetPath: paths3.targetPath,
10576
10759
  protocolVersion: PLAN_PROTOCOL_VERSION,
10577
10760
  installedSha256,
10578
10761
  installedAt: (/* @__PURE__ */ new Date()).toISOString(),
10579
10762
  backupDir,
10580
10763
  original: prior?.original ?? (existing === void 0 ? { existed: false } : { existed: true, base64: existing.bytes.toString("base64") }),
10581
- createdClaudeDir: prior?.createdClaudeDir ?? !existsSync8(claudeDir),
10582
- createdRulesDir: prior?.createdRulesDir ?? !existsSync8(rulesDir)
10764
+ createdClaudeDir: prior?.createdClaudeDir ?? !existsSync9(claudeDir),
10765
+ createdRulesDir: prior?.createdRulesDir ?? !existsSync9(rulesDir)
10583
10766
  });
10584
- mkdirSync5(rulesDir, { recursive: true });
10585
- writeFileSync6(paths.targetPath, PLAN_PROTOCOL_TEXT);
10767
+ mkdirSync6(rulesDir, { recursive: true });
10768
+ writeFileSync7(paths3.targetPath, PLAN_PROTOCOL_TEXT);
10586
10769
  }
10587
10770
  return {
10588
- ...result2(paths.targetPath, "install", true, previousState, before, true),
10771
+ ...result3(paths3.targetPath, "install", true, previousState, before, true),
10589
10772
  state: "installed",
10590
10773
  version: PLAN_PROTOCOL_VERSION,
10591
10774
  sha256: installedSha256,
@@ -10595,31 +10778,31 @@ function installProtocolCc(options) {
10595
10778
  };
10596
10779
  }
10597
10780
  function uninstallProtocolCc(options) {
10598
- const paths = resolveOptions2(options);
10599
- const existing = readExisting(paths.targetPath);
10781
+ const paths3 = resolveOptions2(options);
10782
+ const existing = readExisting(paths3.targetPath);
10600
10783
  if (existing === void 0) {
10601
- return result2(paths.targetPath, "uninstall", false, "not_installed", "", false);
10784
+ return result3(paths3.targetPath, "uninstall", false, "not_installed", "", false);
10602
10785
  }
10603
10786
  const previousState = stateForIdentity2(existing.identity);
10604
10787
  if (previousState === "modified")
10605
- throw modifiedError2(paths.targetPath, "\u5378\u8F7D");
10606
- const state = readState4(paths.statePath);
10788
+ throw modifiedError2(paths3.targetPath, "\u5378\u8F7D");
10789
+ const state = readState4(paths3.statePath);
10607
10790
  const restored = restoredOriginal(state);
10608
10791
  const after = restored?.toString("utf8") ?? "";
10609
10792
  const afterExists = restored !== void 0;
10610
- const backupDir = nextBackupDir2(paths.homeDir);
10611
- if (!paths.dryRun) {
10612
- backupTarget2(backupDir, paths.targetPath, existing.bytes);
10793
+ const backupDir = nextBackupDir3(paths3.homeDir);
10794
+ if (!paths3.dryRun) {
10795
+ backupTarget3(backupDir, paths3.targetPath, existing.bytes);
10613
10796
  if (restored === void 0)
10614
- rmSync4(paths.targetPath, { force: true });
10797
+ rmSync5(paths3.targetPath, { force: true });
10615
10798
  else
10616
- writeFileSync6(paths.targetPath, restored);
10799
+ writeFileSync7(paths3.targetPath, restored);
10617
10800
  if (restored === void 0)
10618
- removeCreatedEmptyDirs(paths, state);
10619
- rmSync4(paths.statePath, { force: true });
10801
+ removeCreatedEmptyDirs(paths3, state);
10802
+ rmSync5(paths3.statePath, { force: true });
10620
10803
  }
10621
10804
  return {
10622
- ...result2(paths.targetPath, "uninstall", true, previousState, existing.text, afterExists),
10805
+ ...result3(paths3.targetPath, "uninstall", true, previousState, existing.text, afterExists),
10623
10806
  state: "not_installed",
10624
10807
  after,
10625
10808
  backupDir,
@@ -10629,20 +10812,20 @@ function uninstallProtocolCc(options) {
10629
10812
  function resolveOptions2(options) {
10630
10813
  const homeDir = resolve5(options?.homeDir ?? homedir9());
10631
10814
  const projectDir = resolve5(options?.projectDir ?? process.cwd());
10632
- const targetPath2 = join13(projectDir, ".claude", "rules", "wingman-plan-protocol.md");
10815
+ const targetPath2 = join14(projectDir, ".claude", "rules", "wingman-plan-protocol.md");
10633
10816
  const projectHash = sha256Hex(projectDir);
10634
10817
  return {
10635
10818
  homeDir,
10636
10819
  projectDir,
10637
10820
  dryRun: options?.dryRun ?? false,
10638
10821
  targetPath: targetPath2,
10639
- statePath: join13(homeDir, ".wingman", "state", `plan-protocol-cc-${projectHash}.json`)
10822
+ statePath: join14(homeDir, ".wingman", "state", `plan-protocol-cc-${projectHash}.json`)
10640
10823
  };
10641
10824
  }
10642
10825
  function readExisting(targetPath2) {
10643
- if (!existsSync8(targetPath2))
10826
+ if (!existsSync9(targetPath2))
10644
10827
  return void 0;
10645
- const bytes = readFileSync8(targetPath2);
10828
+ const bytes = readFileSync9(targetPath2);
10646
10829
  const identity = inspectPlanProtocolFile(bytes, targetPath2);
10647
10830
  return { bytes, text: bytes.toString("utf8"), identity };
10648
10831
  }
@@ -10665,7 +10848,7 @@ function statusFromIdentity(targetPath2, identity) {
10665
10848
  ...identity.kind === "modified" ? { reason: "\u53D7\u7BA1\u534F\u8BAE\u6587\u4EF6\u5DF2\u88AB\u4FEE\u6539" } : {}
10666
10849
  };
10667
10850
  }
10668
- function result2(targetPath2, operation, changed, previousState, before, afterExists) {
10851
+ function result3(targetPath2, operation, changed, previousState, before, afterExists) {
10669
10852
  return {
10670
10853
  harness: "cc",
10671
10854
  operation,
@@ -10683,32 +10866,32 @@ function result2(targetPath2, operation, changed, previousState, before, afterEx
10683
10866
  function modifiedError2(targetPath2, operation) {
10684
10867
  return new Error(`\u53D7\u7BA1\u534F\u8BAE\u6587\u4EF6\u5DF2\u88AB\u4FEE\u6539(${targetPath2})\uFF0C\u62D2\u7EDD${operation}\u5E76\u4FDD\u7559\u7528\u6237\u5185\u5BB9`);
10685
10868
  }
10686
- function nextBackupDir2(homeDir) {
10869
+ function nextBackupDir3(homeDir) {
10687
10870
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replaceAll(":", "-");
10688
- const root = join13(homeDir, ".wingman", "backups");
10689
- let dir = join13(root, stamp);
10690
- for (let n = 2; existsSync8(dir); n += 1)
10691
- dir = join13(root, `${stamp}-${n}`);
10871
+ const root = join14(homeDir, ".wingman", "backups");
10872
+ let dir = join14(root, stamp);
10873
+ for (let n = 2; existsSync9(dir); n += 1)
10874
+ dir = join14(root, `${stamp}-${n}`);
10692
10875
  return dir;
10693
10876
  }
10694
- function backupTarget2(backupDir, targetPath2, bytes) {
10695
- mkdirSync5(backupDir, { recursive: true });
10877
+ function backupTarget3(backupDir, targetPath2, bytes) {
10878
+ mkdirSync6(backupDir, { recursive: true });
10696
10879
  if (bytes !== void 0)
10697
- writeFileSync6(join13(backupDir, basename5(targetPath2)), bytes);
10880
+ writeFileSync7(join14(backupDir, basename6(targetPath2)), bytes);
10698
10881
  }
10699
10882
  function readState4(statePath2) {
10700
- if (!existsSync8(statePath2))
10883
+ if (!existsSync9(statePath2))
10701
10884
  return void 0;
10702
10885
  try {
10703
- const state = JSON.parse(readFileSync8(statePath2, "utf8"));
10886
+ const state = JSON.parse(readFileSync9(statePath2, "utf8"));
10704
10887
  return state.version === 1 && state.harness === "cc" && typeof state.targetPath === "string" ? state : void 0;
10705
10888
  } catch {
10706
10889
  return void 0;
10707
10890
  }
10708
10891
  }
10709
10892
  function writeState4(statePath2, state) {
10710
- mkdirSync5(dirname9(statePath2), { recursive: true });
10711
- writeFileSync6(statePath2, `${JSON.stringify(state, null, 2)}
10893
+ mkdirSync6(dirname10(statePath2), { recursive: true });
10894
+ writeFileSync7(statePath2, `${JSON.stringify(state, null, 2)}
10712
10895
  `);
10713
10896
  }
10714
10897
  function restoredOriginal(state) {
@@ -10716,13 +10899,13 @@ function restoredOriginal(state) {
10716
10899
  return void 0;
10717
10900
  return Buffer.from(state.original.base64 ?? "", "base64");
10718
10901
  }
10719
- function removeCreatedEmptyDirs(paths, state) {
10720
- const rulesDir = dirname9(paths.targetPath);
10721
- const claudeDir = dirname9(rulesDir);
10722
- if (state?.createdRulesDir && existsSync8(rulesDir) && readdirSync2(rulesDir).length === 0) {
10902
+ function removeCreatedEmptyDirs(paths3, state) {
10903
+ const rulesDir = dirname10(paths3.targetPath);
10904
+ const claudeDir = dirname10(rulesDir);
10905
+ if (state?.createdRulesDir && existsSync9(rulesDir) && readdirSync2(rulesDir).length === 0) {
10723
10906
  rmdirSync(rulesDir);
10724
10907
  }
10725
- if (state?.createdClaudeDir && existsSync8(claudeDir) && readdirSync2(claudeDir).length === 0) {
10908
+ if (state?.createdClaudeDir && existsSync9(claudeDir) && readdirSync2(claudeDir).length === 0) {
10726
10909
  rmdirSync(claudeDir);
10727
10910
  }
10728
10911
  }
@@ -10733,6 +10916,33 @@ var init_protocol2 = __esm({
10733
10916
  }
10734
10917
  });
10735
10918
 
10919
+ // packages/adapter-cc/dist/protocol-user.js
10920
+ import { homedir as homedir10 } from "node:os";
10921
+ import { join as join15, resolve as resolve6 } from "node:path";
10922
+ function paths(options) {
10923
+ const homeDir = resolve6(options?.homeDir ?? homedir10());
10924
+ return {
10925
+ homeDir,
10926
+ targetPath: join15(homeDir, ".claude", "CLAUDE.md"),
10927
+ dryRun: options?.dryRun ?? false
10928
+ };
10929
+ }
10930
+ function protocolStatusCcUser(options) {
10931
+ return { harness: "cc", ...statusPlanProtocolUser(paths(options).targetPath) };
10932
+ }
10933
+ function installProtocolCcUser(options) {
10934
+ return { harness: "cc", ...installPlanProtocolUser(paths(options)) };
10935
+ }
10936
+ function uninstallProtocolCcUser(options) {
10937
+ return { harness: "cc", ...uninstallPlanProtocolUser(paths(options)) };
10938
+ }
10939
+ var init_protocol_user = __esm({
10940
+ "packages/adapter-cc/dist/protocol-user.js"() {
10941
+ "use strict";
10942
+ init_dist();
10943
+ }
10944
+ });
10945
+
10736
10946
  // packages/adapter-cc/dist/index.js
10737
10947
  var dist_exports2 = {};
10738
10948
  __export(dist_exports2, {
@@ -10740,8 +10950,11 @@ __export(dist_exports2, {
10740
10950
  createAdapter: () => createAdapter2,
10741
10951
  feedbackSignals: () => feedbackSignalsCc,
10742
10952
  installProtocolCc: () => installProtocolCc,
10953
+ installProtocolCcUser: () => installProtocolCcUser,
10743
10954
  protocolStatusCc: () => protocolStatusCc,
10744
- uninstallProtocolCc: () => uninstallProtocolCc
10955
+ protocolStatusCcUser: () => protocolStatusCcUser,
10956
+ uninstallProtocolCc: () => uninstallProtocolCc,
10957
+ uninstallProtocolCcUser: () => uninstallProtocolCcUser
10745
10958
  });
10746
10959
  function createAdapter2(_options) {
10747
10960
  return {
@@ -10764,6 +10977,7 @@ var init_dist3 = __esm({
10764
10977
  init_hooks2();
10765
10978
  init_protocol2();
10766
10979
  init_scan();
10980
+ init_protocol_user();
10767
10981
  }
10768
10982
  });
10769
10983
 
@@ -11476,15 +11690,15 @@ var init_dist4 = __esm({
11476
11690
  });
11477
11691
 
11478
11692
  // packages/adapter-codex/dist/shared.js
11479
- import { homedir as homedir10 } from "node:os";
11480
- import { join as join14 } from "node:path";
11693
+ import { homedir as homedir11 } from "node:os";
11694
+ import { join as join16 } from "node:path";
11481
11695
  function resolvePaths(options) {
11482
- const homeDir = options?.homeDir ?? homedir10();
11696
+ const homeDir = options?.homeDir ?? homedir11();
11483
11697
  const projectDir = options?.projectDir ?? process.cwd();
11484
- return { homeDir, projectDir, codexHome: join14(homeDir, ".codex") };
11698
+ return { homeDir, projectDir, codexHome: join16(homeDir, ".codex") };
11485
11699
  }
11486
- function wingmanStateRoot(paths) {
11487
- return join14(paths.homeDir, ".wingman");
11700
+ function wingmanStateRoot(paths3) {
11701
+ return join16(paths3.homeDir, ".wingman");
11488
11702
  }
11489
11703
  function isTable(value) {
11490
11704
  return typeof value === "object" && value !== null && !Array.isArray(value) && !(value instanceof Date);
@@ -11793,26 +12007,26 @@ var init_toml_edit = __esm({
11793
12007
  });
11794
12008
 
11795
12009
  // packages/adapter-codex/dist/actions.js
11796
- import { existsSync as existsSync9, mkdirSync as mkdirSync6, readdirSync as readdirSync3, readFileSync as readFileSync9, statSync as statSync3, writeFileSync as writeFileSync7 } from "node:fs";
11797
- import { basename as basename6, dirname as dirname10, join as join15 } from "node:path";
12010
+ import { existsSync as existsSync10, mkdirSync as mkdirSync7, readdirSync as readdirSync3, readFileSync as readFileSync10, statSync as statSync3, writeFileSync as writeFileSync8 } from "node:fs";
12011
+ import { basename as basename7, dirname as dirname11, join as join17 } from "node:path";
11798
12012
  async function planAction(action, options) {
11799
- const paths = resolvePaths(options);
11800
- const resolved = resolveToggle(action, paths);
12013
+ const paths3 = resolvePaths(options);
12014
+ const resolved = resolveToggle(action, paths3);
11801
12015
  return {
11802
12016
  harness: "codex",
11803
12017
  action,
11804
12018
  writes: [
11805
12019
  { file: resolved.file, kind: "modify", before: resolved.before, after: resolved.after }
11806
12020
  ],
11807
- backupDir: nextBackupDir3(paths),
11808
- references: scanReferences(collectCorpus(paths), resolved.bareName),
12021
+ backupDir: nextBackupDir4(paths3),
12022
+ references: scanReferences(collectCorpus(paths3), resolved.bareName),
11809
12023
  // §4b 地面真值:config.toml 启动时读,外改对运行中会话不生效 → 如实报 next_session
11810
12024
  effectiveAt: "next_session"
11811
12025
  };
11812
12026
  }
11813
12027
  async function applyAction(plan, options) {
11814
12028
  try {
11815
- const paths = resolvePaths(options);
12029
+ const paths3 = resolvePaths(options);
11816
12030
  if (plan.harness !== "codex") {
11817
12031
  return { ok: false, error: `plan.harness=${String(plan.harness)} \u4E0D\u662F codex,\u62D2\u7EDD\u6267\u884C` };
11818
12032
  }
@@ -11823,38 +12037,38 @@ async function applyAction(plan, options) {
11823
12037
  error: "plan.writes \u4E0D\u662F\u672C adapter \u4EA7\u51FA\u7684\u5F62\u72B6(\u5E94\u6070\u4E3A\u4E00\u5904 modify),\u62D2\u7EDD\u6267\u884C"
11824
12038
  };
11825
12039
  }
11826
- const backupsRoot = join15(wingmanStateRoot(paths), "backups");
11827
- if (dirname10(plan.backupDir) !== backupsRoot) {
12040
+ const backupsRoot = join17(wingmanStateRoot(paths3), "backups");
12041
+ if (dirname11(plan.backupDir) !== backupsRoot) {
11828
12042
  return { ok: false, error: `backupDir \u4E0D\u5728 wingman \u5907\u4EFD\u6839(${backupsRoot})\u4E0B,\u62D2\u7EDD\u6267\u884C` };
11829
12043
  }
11830
- const currentRaw = readFileSync9(write.file);
12044
+ const currentRaw = readFileSync10(write.file);
11831
12045
  if (!currentRaw.equals(Buffer.from(write.before, "utf8"))) {
11832
12046
  return { ok: false, error: `\u6587\u4EF6\u5728 plan \u4E4B\u540E\u88AB\u4FEE\u6539(${write.file}),\u62D2\u7EDD\u6267\u884C;\u8BF7\u91CD\u65B0 plan` };
11833
12047
  }
11834
- const resolved = resolveToggle(plan.action, paths);
12048
+ const resolved = resolveToggle(plan.action, paths3);
11835
12049
  if (resolved.file !== write.file) {
11836
12050
  return { ok: false, error: "plan.writes \u7684\u76EE\u6807\u6587\u4EF6\u4E0E itemId \u5BF9\u4E0D\u4E0A,\u62D2\u7EDD\u6267\u884C" };
11837
12051
  }
11838
12052
  if (resolved.after !== write.after) {
11839
12053
  return { ok: false, error: "plan \u4E0E\u672C adapter \u7684\u63A8\u6F14\u4E0D\u4E00\u81F4,\u62D2\u7EDD\u6267\u884C;\u8BF7\u91CD\u65B0 plan" };
11840
12054
  }
11841
- mkdirSync6(plan.backupDir, { recursive: true });
11842
- writeFileSync7(join15(plan.backupDir, basename6(write.file)), currentRaw);
11843
- writeFileSync7(write.file, write.after);
12055
+ mkdirSync7(plan.backupDir, { recursive: true });
12056
+ writeFileSync8(join17(plan.backupDir, basename7(write.file)), currentRaw);
12057
+ writeFileSync8(write.file, write.after);
11844
12058
  return { ok: true, backupDir: plan.backupDir };
11845
12059
  } catch (error) {
11846
12060
  return { ok: false, error: error.message };
11847
12061
  }
11848
12062
  }
11849
- function nextBackupDir3(paths) {
12063
+ function nextBackupDir4(paths3) {
11850
12064
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replaceAll(":", "-");
11851
- const base = join15(wingmanStateRoot(paths), "backups");
11852
- let dir = join15(base, stamp);
11853
- for (let n = 1; existsSync9(dir); n += 1)
11854
- dir = join15(base, `${stamp}-${n}`);
12065
+ const base = join17(wingmanStateRoot(paths3), "backups");
12066
+ let dir = join17(base, stamp);
12067
+ for (let n = 1; existsSync10(dir); n += 1)
12068
+ dir = join17(base, `${stamp}-${n}`);
11855
12069
  return dir;
11856
12070
  }
11857
- function resolveToggle(action, paths) {
12071
+ function resolveToggle(action, paths3) {
11858
12072
  if (action.kind !== "toggle") {
11859
12073
  throw new Error(`\u672A\u77E5\u52A8\u4F5C\u79CD\u7C7B:${String(action.kind)}(v1 \u4EC5 toggle \u8D70 plan\u2192apply)`);
11860
12074
  }
@@ -11865,10 +12079,10 @@ function resolveToggle(action, paths) {
11865
12079
  const slot = m[1];
11866
12080
  const source = m[2];
11867
12081
  const nativeName = m[3];
11868
- const file = source === "user" ? join15(paths.codexHome, "config.toml") : join15(paths.projectDir, ".codex", "config.toml");
11869
- if (!existsSync9(file))
12082
+ const file = source === "user" ? join17(paths3.codexHome, "config.toml") : join17(paths3.projectDir, ".codex", "config.toml");
12083
+ if (!existsSync10(file))
11870
12084
  throw new Error(`itemId \u627E\u4E0D\u5230:\u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728(${file})`);
11871
- const before = readFileSync9(file, "utf8");
12085
+ const before = readFileSync10(file, "utf8");
11872
12086
  let table;
11873
12087
  try {
11874
12088
  table = parse3(before);
@@ -12089,15 +12303,15 @@ function verifyEdit(table, edit, file) {
12089
12303
  throw new Error(`\u7F16\u8F91\u7ED3\u679C\u4E0E\u671F\u671B\u7684\u6700\u5C0F\u53D8\u66F4\u4E0D\u4E00\u81F4,\u62D2\u7EDD\u5199\u5165(${file})`);
12090
12304
  }
12091
12305
  }
12092
- function collectCorpus(paths) {
12306
+ function collectCorpus(paths3) {
12093
12307
  const candidates = [
12094
- join15(paths.codexHome, "AGENTS.md"),
12095
- join15(paths.projectDir, "AGENTS.md"),
12096
- join15(paths.codexHome, "config.toml"),
12097
- join15(paths.projectDir, ".codex", "config.toml"),
12098
- join15(paths.codexHome, "hooks.json"),
12099
- join15(paths.projectDir, ".codex", "hooks.json"),
12100
- ...listFilesRecursive(join15(paths.codexHome, "prompts"))
12308
+ join17(paths3.codexHome, "AGENTS.md"),
12309
+ join17(paths3.projectDir, "AGENTS.md"),
12310
+ join17(paths3.codexHome, "config.toml"),
12311
+ join17(paths3.projectDir, ".codex", "config.toml"),
12312
+ join17(paths3.codexHome, "hooks.json"),
12313
+ join17(paths3.projectDir, ".codex", "hooks.json"),
12314
+ ...listFilesRecursive(join17(paths3.codexHome, "prompts"))
12101
12315
  ];
12102
12316
  const sources = [];
12103
12317
  for (const file of candidates) {
@@ -12107,7 +12321,7 @@ function collectCorpus(paths) {
12107
12321
  } catch {
12108
12322
  continue;
12109
12323
  }
12110
- sources.push({ file, text: readFileSync9(file, "utf8") });
12324
+ sources.push({ file, text: readFileSync10(file, "utf8") });
12111
12325
  }
12112
12326
  return sources;
12113
12327
  }
@@ -12120,7 +12334,7 @@ function listFilesRecursive(dir) {
12120
12334
  }
12121
12335
  const files = [];
12122
12336
  for (const entry of [...entries].sort((a, b) => a.name.localeCompare(b.name))) {
12123
- const path = join15(dir, entry.name);
12337
+ const path = join17(dir, entry.name);
12124
12338
  if (entry.isDirectory())
12125
12339
  files.push(...listFilesRecursive(path));
12126
12340
  else if (entry.isFile())
@@ -12187,17 +12401,17 @@ var init_actions2 = __esm({
12187
12401
 
12188
12402
  // packages/adapter-codex/dist/hooks.js
12189
12403
  import { spawnSync } from "node:child_process";
12190
- import { existsSync as existsSync10, mkdirSync as mkdirSync7, readFileSync as readFileSync10, realpathSync, rmSync as rmSync5, writeFileSync as writeFileSync8 } from "node:fs";
12191
- import { basename as basename7, dirname as dirname11, join as join16 } from "node:path";
12404
+ import { existsSync as existsSync11, mkdirSync as mkdirSync8, readFileSync as readFileSync11, realpathSync, rmSync as rmSync6, writeFileSync as writeFileSync9 } from "node:fs";
12405
+ import { basename as basename8, dirname as dirname12, join as join18 } from "node:path";
12192
12406
  async function installHooks(port, options) {
12193
12407
  if (!Number.isInteger(port) || port <= 0 || port > 65535) {
12194
12408
  throw new Error(`\u975E\u6CD5\u7AEF\u53E3:${port}`);
12195
12409
  }
12196
- const paths = resolvePaths(options);
12197
- const root = wingmanStateRoot(paths);
12198
- const scriptPath = join16(root, FORWARD_SCRIPT_NAME);
12199
- const configPath = join16(paths.codexHome, "config.toml");
12200
- const raw = existsSync10(configPath) ? readFileSync10(configPath) : void 0;
12410
+ const paths3 = resolvePaths(options);
12411
+ const root = wingmanStateRoot(paths3);
12412
+ const scriptPath = join18(root, FORWARD_SCRIPT_NAME);
12413
+ const configPath = join18(paths3.codexHome, "config.toml");
12414
+ const raw = existsSync11(configPath) ? readFileSync11(configPath) : void 0;
12201
12415
  const text = raw?.toString("utf8") ?? "";
12202
12416
  const { before, after, remainder, block } = splitManagedBlock(text, configPath);
12203
12417
  const lineEnding = preferredLineEnding(text);
@@ -12206,8 +12420,8 @@ async function installHooks(port, options) {
12206
12420
  if (block !== void 0 && knownBlock === void 0) {
12207
12421
  throw new Error(`Wingman Codex hook \u53D7\u7BA1\u5757\u5DF2\u88AB\u4FEE\u6539\u6216\u6B8B\u7F3A(${configPath}),\u62D2\u7EDD\u8C0E\u62A5\u63A5\u7EBF\u6210\u529F;\u8BF7\u5148\u4ECE <wingman\u6839>/backups/ \u6062\u590D\u5B8C\u6574\u5757,\u6216\u4EBA\u5DE5\u6838\u5BF9\u540E\u79FB\u9664\u8BE5\u53D7\u7BA1\u5757\u518D\u91CD\u65B0\u5B89\u88C5\u5E76\u4FE1\u4EFB`);
12208
12422
  }
12209
- mkdirSync7(root, { recursive: true });
12210
- writeFileSync8(scriptPath, FORWARD_SCRIPT);
12423
+ mkdirSync8(root, { recursive: true });
12424
+ writeFileSync9(scriptPath, FORWARD_SCRIPT);
12211
12425
  const statePath2 = hooksStatePath(root);
12212
12426
  const prior = readState5(statePath2);
12213
12427
  if (knownBlock !== void 0 && knownBlock.state === void 0) {
@@ -12236,7 +12450,7 @@ async function installHooks(port, options) {
12236
12450
  ...backupDir !== void 0 ? { backupDir } : {}
12237
12451
  });
12238
12452
  const state = hasStateOutsideBlock ? "" : knownBlock.state;
12239
- writeFileSync8(configPath, before + knownBlock.managedBlock + state + after);
12453
+ writeFileSync9(configPath, before + knownBlock.managedBlock + state + after);
12240
12454
  return;
12241
12455
  }
12242
12456
  const original = prior?.original ?? (raw === void 0 ? { existed: false } : { existed: true, base64: raw.toString("base64") });
@@ -12252,17 +12466,17 @@ async function installHooks(port, options) {
12252
12466
  let base = remainder;
12253
12467
  if (base !== "" && !base.endsWith("\n"))
12254
12468
  base += lineEnding;
12255
- mkdirSync7(paths.codexHome, { recursive: true });
12256
- writeFileSync8(configPath, base + newBlock);
12469
+ mkdirSync8(paths3.codexHome, { recursive: true });
12470
+ writeFileSync9(configPath, base + newBlock);
12257
12471
  }
12258
12472
  async function uninstallHooks(options) {
12259
- const paths = resolvePaths(options);
12260
- const root = wingmanStateRoot(paths);
12261
- const scriptPath = join16(root, FORWARD_SCRIPT_NAME);
12473
+ const paths3 = resolvePaths(options);
12474
+ const root = wingmanStateRoot(paths3);
12475
+ const scriptPath = join18(root, FORWARD_SCRIPT_NAME);
12262
12476
  const statePath2 = hooksStatePath(root);
12263
- const configPath = join16(paths.codexHome, "config.toml");
12477
+ const configPath = join18(paths3.codexHome, "config.toml");
12264
12478
  const state = readState5(statePath2);
12265
- const raw = existsSync10(configPath) ? readFileSync10(configPath) : void 0;
12479
+ const raw = existsSync11(configPath) ? readFileSync11(configPath) : void 0;
12266
12480
  if (raw !== void 0) {
12267
12481
  const text = raw.toString("utf8");
12268
12482
  const { before, after, remainder, block } = splitManagedBlock(text, configPath);
@@ -12275,34 +12489,34 @@ async function uninstallHooks(options) {
12275
12489
  const preservedState = hasHooksState(remainder) ? "" : knownBlock.state ?? "";
12276
12490
  const restored = restoreTarget(before + preservedState + after, state);
12277
12491
  if (restored === null)
12278
- rmSync5(configPath);
12492
+ rmSync6(configPath);
12279
12493
  else
12280
- writeFileSync8(configPath, restored);
12494
+ writeFileSync9(configPath, restored);
12281
12495
  }
12282
12496
  }
12283
- rmSync5(scriptPath, { force: true });
12284
- rmSync5(statePath2, { force: true });
12497
+ rmSync6(scriptPath, { force: true });
12498
+ rmSync6(statePath2, { force: true });
12285
12499
  }
12286
- function hasManagedHooks2(paths) {
12287
- const configPath = join16(paths.codexHome, "config.toml");
12288
- if (!existsSync10(configPath))
12500
+ function hasManagedHooks2(paths3) {
12501
+ const configPath = join18(paths3.codexHome, "config.toml");
12502
+ if (!existsSync11(configPath))
12289
12503
  return false;
12290
12504
  try {
12291
- const { block } = splitManagedBlock(readFileSync10(configPath, "utf8"), configPath);
12292
- return block !== void 0 && inspectManagedBlock(block, join16(wingmanStateRoot(paths), FORWARD_SCRIPT_NAME)) !== void 0;
12505
+ const { block } = splitManagedBlock(readFileSync11(configPath, "utf8"), configPath);
12506
+ return block !== void 0 && inspectManagedBlock(block, join18(wingmanStateRoot(paths3), FORWARD_SCRIPT_NAME)) !== void 0;
12293
12507
  } catch {
12294
12508
  return false;
12295
12509
  }
12296
12510
  }
12297
12511
  function feedbackSignalsCodex(options) {
12298
- const paths = resolvePaths(options);
12299
- const configPath = join16(paths.codexHome, "config.toml");
12512
+ const paths3 = resolvePaths(options);
12513
+ const configPath = join18(paths3.codexHome, "config.toml");
12300
12514
  const wiredEvents = [];
12301
- if (existsSync10(configPath)) {
12515
+ if (existsSync11(configPath)) {
12302
12516
  try {
12303
- const { block } = splitManagedBlock(readFileSync10(configPath, "utf8"), configPath);
12517
+ const { block } = splitManagedBlock(readFileSync11(configPath, "utf8"), configPath);
12304
12518
  if (block !== void 0) {
12305
- const knownBlock = inspectManagedBlock(block, join16(wingmanStateRoot(paths), FORWARD_SCRIPT_NAME));
12519
+ const knownBlock = inspectManagedBlock(block, join18(wingmanStateRoot(paths3), FORWARD_SCRIPT_NAME));
12306
12520
  const hooks = knownBlock === void 0 ? void 0 : parse3(normalizeLineEndings(knownBlock.managedBlock)).hooks;
12307
12521
  if (isTable(hooks)) {
12308
12522
  for (const [event, groups] of Object.entries(hooks)) {
@@ -12343,7 +12557,7 @@ function restoreTarget(remainder, state) {
12343
12557
  }
12344
12558
  function resolveNodeExecutable(probe = {}) {
12345
12559
  const execPath = probe.execPath ?? process.execPath;
12346
- const exists = probe.exists ?? existsSync10;
12560
+ const exists = probe.exists ?? existsSync11;
12347
12561
  let executable = isNodeExecutable(execPath) ? execPath : void 0;
12348
12562
  if (executable === void 0) {
12349
12563
  const loginShellWhich = probe.loginShellWhich ?? defaultLoginShellWhich;
@@ -12390,13 +12604,13 @@ function defaultRealpath(path) {
12390
12604
  }
12391
12605
  }
12392
12606
  function defaultLoginShellWhich(shell) {
12393
- const result4 = spawnSync(shell, ["-lc", "command -v node"], {
12607
+ const result5 = spawnSync(shell, ["-lc", "command -v node"], {
12394
12608
  encoding: "utf8",
12395
12609
  timeout: 3e3
12396
12610
  });
12397
- if (result4.error !== void 0)
12611
+ if (result5.error !== void 0)
12398
12612
  return void 0;
12399
- return result4.stdout.trim() || void 0;
12613
+ return result5.stdout.trim() || void 0;
12400
12614
  }
12401
12615
  function buildManagedBlock(scriptPath, nodeExecutable = "node") {
12402
12616
  return buildManagedBlockForCommand(`${nodeExecutable} "${scriptPath}"`);
@@ -12548,28 +12762,28 @@ function hasHooksState(text) {
12548
12762
  }
12549
12763
  function backupFile(root, filePath, contents) {
12550
12764
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replaceAll(":", "-");
12551
- let dir = join16(root, "backups", stamp);
12552
- for (let n = 1; existsSync10(dir); n += 1)
12553
- dir = join16(root, "backups", `${stamp}-${n}`);
12554
- mkdirSync7(dir, { recursive: true });
12555
- writeFileSync8(join16(dir, basename7(filePath)), contents);
12765
+ let dir = join18(root, "backups", stamp);
12766
+ for (let n = 1; existsSync11(dir); n += 1)
12767
+ dir = join18(root, "backups", `${stamp}-${n}`);
12768
+ mkdirSync8(dir, { recursive: true });
12769
+ writeFileSync9(join18(dir, basename8(filePath)), contents);
12556
12770
  return dir;
12557
12771
  }
12558
12772
  function hooksStatePath(root) {
12559
- return join16(root, "state", "codex-hooks.json");
12773
+ return join18(root, "state", "codex-hooks.json");
12560
12774
  }
12561
12775
  function readState5(statePath2) {
12562
- if (!existsSync10(statePath2))
12776
+ if (!existsSync11(statePath2))
12563
12777
  return void 0;
12564
12778
  try {
12565
- return JSON.parse(readFileSync10(statePath2, "utf8"));
12779
+ return JSON.parse(readFileSync11(statePath2, "utf8"));
12566
12780
  } catch {
12567
12781
  return void 0;
12568
12782
  }
12569
12783
  }
12570
12784
  function writeState5(statePath2, state) {
12571
- mkdirSync7(dirname11(statePath2), { recursive: true });
12572
- writeFileSync8(statePath2, `${JSON.stringify(state, null, 2)}
12785
+ mkdirSync8(dirname12(statePath2), { recursive: true });
12786
+ writeFileSync9(statePath2, `${JSON.stringify(state, null, 2)}
12573
12787
  `);
12574
12788
  }
12575
12789
  function deepEqual3(a, b) {
@@ -12725,15 +12939,15 @@ process.stdin.on('end', async () => {
12725
12939
  });
12726
12940
 
12727
12941
  // packages/adapter-codex/dist/scan.js
12728
- import { existsSync as existsSync11, readdirSync as readdirSync4, readFileSync as readFileSync11, statSync as statSync4 } from "node:fs";
12729
- import { dirname as dirname12, isAbsolute as isAbsolute3, join as join17, resolve as resolve6 } from "node:path";
12942
+ import { existsSync as existsSync12, readdirSync as readdirSync4, readFileSync as readFileSync12, statSync as statSync4 } from "node:fs";
12943
+ import { dirname as dirname13, isAbsolute as isAbsolute3, join as join19, resolve as resolve7 } from "node:path";
12730
12944
  async function detect(options) {
12731
12945
  const { codexHome } = resolvePaths(options);
12732
- return { installed: existsSync11(codexHome) };
12946
+ return { installed: existsSync12(codexHome) };
12733
12947
  }
12734
12948
  async function scan(options) {
12735
- const paths = resolvePaths(options);
12736
- const layers = loadConfigLayers(paths);
12949
+ const paths3 = resolvePaths(options);
12950
+ const layers = loadConfigLayers(paths3);
12737
12951
  const slots = {
12738
12952
  base: [],
12739
12953
  rules: [],
@@ -12742,14 +12956,14 @@ async function scan(options) {
12742
12956
  gates: [],
12743
12957
  history: []
12744
12958
  };
12745
- collectRules(slots.rules, paths, layers);
12959
+ collectRules(slots.rules, paths3, layers);
12746
12960
  for (const layer of layers) {
12747
12961
  collectBase(slots.base, layer);
12748
12962
  collectSkills(slots.skills, layer);
12749
12963
  collectTools(slots.tools, layer);
12750
12964
  collectGates(slots.gates, layer);
12751
12965
  }
12752
- collectHistory(slots.history, paths, layers);
12966
+ collectHistory(slots.history, paths3, layers);
12753
12967
  assertUniqueIds(slots);
12754
12968
  return {
12755
12969
  harness: "codex",
@@ -12759,21 +12973,21 @@ async function scan(options) {
12759
12973
  // actions:M3 起 toggle(plan→apply)/scan_references(命中随 plan)已落地;
12760
12974
  // open_editor 是面板用 nativePath 跳转的即时动作,无需 adapter 方法
12761
12975
  capabilities: {
12762
- live: hasManagedHooks2(paths) ? "push" : "none",
12976
+ live: hasManagedHooks2(paths3) ? "push" : "none",
12763
12977
  actions: ["toggle", "open_editor", "scan_references"]
12764
12978
  }
12765
12979
  };
12766
12980
  }
12767
- function loadConfigLayers(paths) {
12981
+ function loadConfigLayers(paths3) {
12768
12982
  const candidates = [
12769
- ["user", join17(paths.codexHome, "config.toml")],
12770
- ["project", join17(paths.projectDir, ".codex", "config.toml")]
12983
+ ["user", join19(paths3.codexHome, "config.toml")],
12984
+ ["project", join19(paths3.projectDir, ".codex", "config.toml")]
12771
12985
  ];
12772
12986
  const layers = [];
12773
12987
  for (const [source, path] of candidates) {
12774
12988
  if (fileSize(path) === void 0)
12775
12989
  continue;
12776
- const text = readFileSync11(path, "utf8");
12990
+ const text = readFileSync12(path, "utf8");
12777
12991
  try {
12778
12992
  layers.push({ source, path, table: parse3(text) });
12779
12993
  } catch (error) {
@@ -12782,10 +12996,10 @@ function loadConfigLayers(paths) {
12782
12996
  }
12783
12997
  return layers;
12784
12998
  }
12785
- function collectRules(out, paths, layers) {
12999
+ function collectRules(out, paths3, layers) {
12786
13000
  const agentsChain = [
12787
- ["user", join17(paths.codexHome, "AGENTS.md")],
12788
- ["project", join17(paths.projectDir, "AGENTS.md")]
13001
+ ["user", join19(paths3.codexHome, "AGENTS.md")],
13002
+ ["project", join19(paths3.projectDir, "AGENTS.md")]
12789
13003
  ];
12790
13004
  for (const [source, file] of agentsChain) {
12791
13005
  const size = fileSize(file);
@@ -12820,7 +13034,7 @@ function collectRules(out, paths, layers) {
12820
13034
  }
12821
13035
  const instructionsFile = layer.table.model_instructions_file;
12822
13036
  if (typeof instructionsFile === "string") {
12823
- const filePath = isAbsolute3(instructionsFile) ? instructionsFile : resolve6(dirname12(layer.path), instructionsFile);
13037
+ const filePath = isAbsolute3(instructionsFile) ? instructionsFile : resolve7(dirname13(layer.path), instructionsFile);
12824
13038
  const item = {
12825
13039
  id: `codex:rules:${layer.source}:model_instructions_file`,
12826
13040
  slot: "rules",
@@ -12919,8 +13133,8 @@ function collectGates(out, layer) {
12919
13133
  });
12920
13134
  }
12921
13135
  }
12922
- function collectHistory(out, paths, layers) {
12923
- const historyFile = join17(paths.codexHome, "history.jsonl");
13136
+ function collectHistory(out, paths3, layers) {
13137
+ const historyFile = join19(paths3.codexHome, "history.jsonl");
12924
13138
  const historyBytes = fileSize(historyFile);
12925
13139
  if (historyBytes !== void 0) {
12926
13140
  out.push({
@@ -12935,7 +13149,7 @@ function collectHistory(out, paths, layers) {
12935
13149
  });
12936
13150
  }
12937
13151
  const configured = layers.find((layer) => layer.source === "user")?.table.log_dir;
12938
- const logDir = typeof configured === "string" ? expandPath(configured, paths) : join17(paths.codexHome, "log");
13152
+ const logDir = typeof configured === "string" ? expandPath(configured, paths3) : join19(paths3.codexHome, "log");
12939
13153
  if (isDirectory(logDir)) {
12940
13154
  out.push({
12941
13155
  id: "codex:history:user:log_dir",
@@ -12949,10 +13163,10 @@ function collectHistory(out, paths, layers) {
12949
13163
  });
12950
13164
  }
12951
13165
  }
12952
- function expandPath(value, paths) {
13166
+ function expandPath(value, paths3) {
12953
13167
  if (value === "~" || value.startsWith("~/"))
12954
- return join17(paths.homeDir, value.slice(2));
12955
- return isAbsolute3(value) ? value : resolve6(paths.codexHome, value);
13168
+ return join19(paths3.homeDir, value.slice(2));
13169
+ return isAbsolute3(value) ? value : resolve7(paths3.codexHome, value);
12956
13170
  }
12957
13171
  function assertUniqueIds(slots) {
12958
13172
  const seen = /* @__PURE__ */ new Set();
@@ -12983,7 +13197,7 @@ function isDirectory(path) {
12983
13197
  function directoryBytes(dir) {
12984
13198
  let total = 0;
12985
13199
  for (const entry of readdirSync4(dir, { withFileTypes: true })) {
12986
- const entryPath = join17(dir, entry.name);
13200
+ const entryPath = join19(dir, entry.name);
12987
13201
  if (entry.isDirectory())
12988
13202
  total += directoryBytes(entryPath);
12989
13203
  else if (entry.isFile())
@@ -13005,54 +13219,54 @@ var init_scan2 = __esm({
13005
13219
  });
13006
13220
 
13007
13221
  // packages/adapter-codex/dist/protocol.js
13008
- import { existsSync as existsSync12, mkdirSync as mkdirSync8, readFileSync as readFileSync12, rmSync as rmSync6, writeFileSync as writeFileSync9 } from "node:fs";
13009
- import { basename as basename8, dirname as dirname13, join as join18, resolve as resolve7 } from "node:path";
13222
+ import { existsSync as existsSync13, mkdirSync as mkdirSync9, readFileSync as readFileSync13, rmSync as rmSync7, writeFileSync as writeFileSync10 } from "node:fs";
13223
+ import { basename as basename9, dirname as dirname14, join as join20, resolve as resolve8 } from "node:path";
13010
13224
  function protocolStatusCodex(options) {
13011
- const paths = resolveOptions3(options);
13012
- if (!existsSync12(paths.targetPath))
13013
- return status2(paths.targetPath, "not_installed");
13225
+ const paths3 = resolveOptions3(options);
13226
+ if (!existsSync13(paths3.targetPath))
13227
+ return status2(paths3.targetPath, "not_installed");
13014
13228
  try {
13015
- const file = readAgents2(paths.targetPath);
13229
+ const file = readAgents2(paths3.targetPath);
13016
13230
  if (file.identity === void 0)
13017
- return status2(paths.targetPath, "not_installed");
13231
+ return status2(paths3.targetPath, "not_installed");
13018
13232
  const state = stateForIdentity3(file.identity);
13019
- return status2(paths.targetPath, state, file.identity);
13233
+ return status2(paths3.targetPath, state, file.identity);
13020
13234
  } catch (error) {
13021
- return status2(paths.targetPath, "invalid", void 0, error.message);
13235
+ return status2(paths3.targetPath, "invalid", void 0, error.message);
13022
13236
  }
13023
13237
  }
13024
13238
  function installProtocolCodex(options) {
13025
- const paths = resolveOptions3(options);
13026
- const existing = existsSync12(paths.targetPath) ? readAgents2(paths.targetPath) : void 0;
13239
+ const paths3 = resolveOptions3(options);
13240
+ const existing = existsSync13(paths3.targetPath) ? readAgents2(paths3.targetPath) : void 0;
13027
13241
  const previousState = stateForIdentity3(existing?.identity);
13028
13242
  if (previousState === "installed") {
13029
- return result3(paths.targetPath, "install", false, previousState, existing?.text ?? "", true);
13243
+ return result4(paths3.targetPath, "install", false, previousState, existing?.text ?? "", true);
13030
13244
  }
13031
13245
  if (previousState === "modified")
13032
- throw modifiedError3(paths.targetPath, "\u5B89\u88C5");
13246
+ throw modifiedError3(paths3.targetPath, "\u5B89\u88C5");
13033
13247
  const before = existing?.text ?? "";
13034
13248
  const lineEnding = preferredMarkdownLineEnding(before);
13035
13249
  const block = buildPlanProtocolBlock().replaceAll("\n", lineEnding);
13036
13250
  const after = existing?.split.block ? existing.split.before + block + existing.split.after : appendBlock2(before, block, lineEnding);
13037
- const installedRemainder = splitPlanProtocolBlock(after, paths.targetPath).remainder;
13038
- const backupDir = nextBackupDir4(paths.homeDir);
13039
- if (!paths.dryRun) {
13040
- const prior = readState6(paths.statePath, paths.targetPath);
13041
- backupTarget3(backupDir, paths.targetPath, existing?.bytes);
13042
- writeState6(paths.statePath, {
13251
+ const installedRemainder = splitPlanProtocolBlock(after, paths3.targetPath).remainder;
13252
+ const backupDir = nextBackupDir5(paths3.homeDir);
13253
+ if (!paths3.dryRun) {
13254
+ const prior = readState6(paths3.statePath, paths3.targetPath);
13255
+ backupTarget4(backupDir, paths3.targetPath, existing?.bytes);
13256
+ writeState6(paths3.statePath, {
13043
13257
  version: 1,
13044
- projectDir: paths.projectDir,
13045
- targetPath: paths.targetPath,
13258
+ projectDir: paths3.projectDir,
13259
+ targetPath: paths3.targetPath,
13046
13260
  protocolVersion: PLAN_PROTOCOL_VERSION,
13047
13261
  installedAt: (/* @__PURE__ */ new Date()).toISOString(),
13048
13262
  backupDir,
13049
13263
  installedRemainderSha256: sha256Hex(installedRemainder),
13050
13264
  original: prior?.original ?? (existing === void 0 ? { existed: false } : { existed: true, base64: existing.bytes.toString("base64") })
13051
13265
  });
13052
- writeFileSync9(paths.targetPath, after);
13266
+ writeFileSync10(paths3.targetPath, after);
13053
13267
  }
13054
13268
  return {
13055
- ...result3(paths.targetPath, "install", true, previousState, before, true),
13269
+ ...result4(paths3.targetPath, "install", true, previousState, before, true),
13056
13270
  state: "installed",
13057
13271
  version: PLAN_PROTOCOL_VERSION,
13058
13272
  after,
@@ -13061,33 +13275,33 @@ function installProtocolCodex(options) {
13061
13275
  };
13062
13276
  }
13063
13277
  function uninstallProtocolCodex(options) {
13064
- const paths = resolveOptions3(options);
13065
- if (!existsSync12(paths.targetPath)) {
13066
- return result3(paths.targetPath, "uninstall", false, "not_installed", "", false);
13278
+ const paths3 = resolveOptions3(options);
13279
+ if (!existsSync13(paths3.targetPath)) {
13280
+ return result4(paths3.targetPath, "uninstall", false, "not_installed", "", false);
13067
13281
  }
13068
- const existing = readAgents2(paths.targetPath);
13282
+ const existing = readAgents2(paths3.targetPath);
13069
13283
  if (existing.identity === void 0) {
13070
- return result3(paths.targetPath, "uninstall", false, "not_installed", existing.text, true);
13284
+ return result4(paths3.targetPath, "uninstall", false, "not_installed", existing.text, true);
13071
13285
  }
13072
13286
  const previousState = stateForIdentity3(existing.identity);
13073
13287
  if (previousState === "modified")
13074
- throw modifiedError3(paths.targetPath, "\u5378\u8F7D");
13075
- const state = readState6(paths.statePath, paths.targetPath);
13288
+ throw modifiedError3(paths3.targetPath, "\u5378\u8F7D");
13289
+ const state = readState6(paths3.statePath, paths3.targetPath);
13076
13290
  const canRestore = state !== void 0 && sha256Hex(existing.split.remainder) === state.installedRemainderSha256;
13077
13291
  const restored = canRestore ? originalBytes2(state) : void 0;
13078
13292
  const deleteTarget = canRestore ? state?.original.existed === false : existing.split.remainder.trim() === "";
13079
13293
  const after = deleteTarget ? "" : restored?.toString("utf8") ?? existing.split.remainder;
13080
- const backupDir = nextBackupDir4(paths.homeDir);
13081
- if (!paths.dryRun) {
13082
- backupTarget3(backupDir, paths.targetPath, existing.bytes);
13294
+ const backupDir = nextBackupDir5(paths3.homeDir);
13295
+ if (!paths3.dryRun) {
13296
+ backupTarget4(backupDir, paths3.targetPath, existing.bytes);
13083
13297
  if (deleteTarget)
13084
- rmSync6(paths.targetPath, { force: true });
13298
+ rmSync7(paths3.targetPath, { force: true });
13085
13299
  else
13086
- writeFileSync9(paths.targetPath, restored ?? existing.split.remainder);
13087
- rmSync6(paths.statePath, { force: true });
13300
+ writeFileSync10(paths3.targetPath, restored ?? existing.split.remainder);
13301
+ rmSync7(paths3.statePath, { force: true });
13088
13302
  }
13089
13303
  return {
13090
- ...result3(paths.targetPath, "uninstall", true, previousState, existing.text, !deleteTarget),
13304
+ ...result4(paths3.targetPath, "uninstall", true, previousState, existing.text, !deleteTarget),
13091
13305
  state: "not_installed",
13092
13306
  message: canRestore ? SHARED_MESSAGE2 : `${SHARED_MESSAGE2}\uFF1B\u5DF2\u79FB\u9664\u5757\u5E76\u4FDD\u7559\u7528\u6237\u6539\u52A8`,
13093
13307
  after,
@@ -13098,14 +13312,14 @@ function uninstallProtocolCodex(options) {
13098
13312
  }
13099
13313
  function resolveOptions3(options) {
13100
13314
  const base = resolvePaths(options);
13101
- const homeDir = resolve7(base.homeDir);
13102
- const projectDir = resolve7(base.projectDir);
13103
- const targetPath2 = join18(projectDir, "AGENTS.md");
13104
- const statePath2 = join18(wingmanStateRoot({ ...base, homeDir, projectDir }), "state", `plan-protocol-agents-${sha256Hex(projectDir)}.json`);
13315
+ const homeDir = resolve8(base.homeDir);
13316
+ const projectDir = resolve8(base.projectDir);
13317
+ const targetPath2 = join20(projectDir, "AGENTS.md");
13318
+ const statePath2 = join20(wingmanStateRoot({ ...base, homeDir, projectDir }), "state", `plan-protocol-agents-${sha256Hex(projectDir)}.json`);
13105
13319
  return { homeDir, projectDir, targetPath: targetPath2, statePath: statePath2, dryRun: options?.dryRun ?? false };
13106
13320
  }
13107
13321
  function readAgents2(targetPath2) {
13108
- const bytes = readFileSync12(targetPath2);
13322
+ const bytes = readFileSync13(targetPath2);
13109
13323
  const text = decodeUtf8Strict2(bytes, targetPath2);
13110
13324
  let split;
13111
13325
  try {
@@ -13150,7 +13364,7 @@ function status2(targetPath2, state, identity, reason) {
13150
13364
  ...reason !== void 0 ? { reason } : {}
13151
13365
  };
13152
13366
  }
13153
- function result3(targetPath2, operation, changed, previousState, before, afterExists) {
13367
+ function result4(targetPath2, operation, changed, previousState, before, afterExists) {
13154
13368
  return {
13155
13369
  ...status2(targetPath2, previousState),
13156
13370
  operation,
@@ -13166,32 +13380,32 @@ function result3(targetPath2, operation, changed, previousState, before, afterEx
13166
13380
  function modifiedError3(targetPath2, operation) {
13167
13381
  return new Error(`${targetPath2}: \u53D7\u7BA1\u5757\u5DF2\u88AB\u4FEE\u6539\uFF0C\u62D2\u7EDD${operation}\u5E76\u4FDD\u7559\u7528\u6237\u5185\u5BB9`);
13168
13382
  }
13169
- function nextBackupDir4(homeDir) {
13383
+ function nextBackupDir5(homeDir) {
13170
13384
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replaceAll(":", "-");
13171
- const root = join18(homeDir, ".wingman", "backups");
13172
- let dir = join18(root, stamp);
13173
- for (let n = 2; existsSync12(dir); n += 1)
13174
- dir = join18(root, `${stamp}-${n}`);
13385
+ const root = join20(homeDir, ".wingman", "backups");
13386
+ let dir = join20(root, stamp);
13387
+ for (let n = 2; existsSync13(dir); n += 1)
13388
+ dir = join20(root, `${stamp}-${n}`);
13175
13389
  return dir;
13176
13390
  }
13177
- function backupTarget3(backupDir, targetPath2, bytes) {
13178
- mkdirSync8(backupDir, { recursive: true });
13391
+ function backupTarget4(backupDir, targetPath2, bytes) {
13392
+ mkdirSync9(backupDir, { recursive: true });
13179
13393
  if (bytes !== void 0)
13180
- writeFileSync9(join18(backupDir, basename8(targetPath2)), bytes);
13394
+ writeFileSync10(join20(backupDir, basename9(targetPath2)), bytes);
13181
13395
  }
13182
13396
  function readState6(statePath2, targetPath2) {
13183
- if (!existsSync12(statePath2))
13397
+ if (!existsSync13(statePath2))
13184
13398
  return void 0;
13185
13399
  try {
13186
- const value = JSON.parse(readFileSync12(statePath2, "utf8"));
13400
+ const value = JSON.parse(readFileSync13(statePath2, "utf8"));
13187
13401
  return value.version === 1 && value.targetPath === targetPath2 ? value : void 0;
13188
13402
  } catch {
13189
13403
  return void 0;
13190
13404
  }
13191
13405
  }
13192
13406
  function writeState6(statePath2, state) {
13193
- mkdirSync8(dirname13(statePath2), { recursive: true });
13194
- writeFileSync9(statePath2, `${JSON.stringify(state, null, 2)}
13407
+ mkdirSync9(dirname14(statePath2), { recursive: true });
13408
+ writeFileSync10(statePath2, `${JSON.stringify(state, null, 2)}
13195
13409
  `);
13196
13410
  }
13197
13411
  function originalBytes2(state) {
@@ -13207,6 +13421,33 @@ var init_protocol3 = __esm({
13207
13421
  }
13208
13422
  });
13209
13423
 
13424
+ // packages/adapter-codex/dist/protocol-user.js
13425
+ import { homedir as homedir12 } from "node:os";
13426
+ import { join as join21, resolve as resolve9 } from "node:path";
13427
+ function paths2(options) {
13428
+ const homeDir = resolve9(options?.homeDir ?? homedir12());
13429
+ return {
13430
+ homeDir,
13431
+ targetPath: join21(homeDir, ".codex", "AGENTS.md"),
13432
+ dryRun: options?.dryRun ?? false
13433
+ };
13434
+ }
13435
+ function protocolStatusCodexUser(options) {
13436
+ return { harness: "codex", ...statusPlanProtocolUser(paths2(options).targetPath) };
13437
+ }
13438
+ function installProtocolCodexUser(options) {
13439
+ return { harness: "codex", ...installPlanProtocolUser(paths2(options)) };
13440
+ }
13441
+ function uninstallProtocolCodexUser(options) {
13442
+ return { harness: "codex", ...uninstallPlanProtocolUser(paths2(options)) };
13443
+ }
13444
+ var init_protocol_user2 = __esm({
13445
+ "packages/adapter-codex/dist/protocol-user.js"() {
13446
+ "use strict";
13447
+ init_dist();
13448
+ }
13449
+ });
13450
+
13210
13451
  // packages/adapter-codex/dist/index.js
13211
13452
  var dist_exports3 = {};
13212
13453
  __export(dist_exports3, {
@@ -13214,9 +13455,12 @@ __export(dist_exports3, {
13214
13455
  createAdapter: () => createAdapter3,
13215
13456
  feedbackSignals: () => feedbackSignalsCodex,
13216
13457
  installProtocolCodex: () => installProtocolCodex,
13458
+ installProtocolCodexUser: () => installProtocolCodexUser,
13217
13459
  protocolStatusCodex: () => protocolStatusCodex,
13460
+ protocolStatusCodexUser: () => protocolStatusCodexUser,
13218
13461
  resolveNodeExecutable: () => resolveNodeExecutable,
13219
- uninstallProtocolCodex: () => uninstallProtocolCodex
13462
+ uninstallProtocolCodex: () => uninstallProtocolCodex,
13463
+ uninstallProtocolCodexUser: () => uninstallProtocolCodexUser
13220
13464
  });
13221
13465
  function createAdapter3(_options) {
13222
13466
  return {
@@ -13237,23 +13481,24 @@ var init_dist5 = __esm({
13237
13481
  init_scan2();
13238
13482
  init_hooks3();
13239
13483
  init_protocol3();
13484
+ init_protocol_user2();
13240
13485
  }
13241
13486
  });
13242
13487
 
13243
13488
  // apps/cli/dist/main.js
13244
13489
  init_dist2();
13245
13490
  init_dist();
13246
- import { readFileSync as readFileSync18 } from "node:fs";
13247
- import { homedir as homedir13 } from "node:os";
13248
- import { dirname as dirname19, resolve as resolve12 } from "node:path";
13491
+ import { readFileSync as readFileSync19 } from "node:fs";
13492
+ import { homedir as homedir16 } from "node:os";
13493
+ import { dirname as dirname20, resolve as resolve14 } from "node:path";
13249
13494
  import { fileURLToPath as fileURLToPath2 } from "node:url";
13250
13495
 
13251
13496
  // packages/fixtures/dist/index.js
13252
- import { dirname as dirname4, join as join5 } from "node:path";
13497
+ import { dirname as dirname5, join as join6 } from "node:path";
13253
13498
  import { fileURLToPath } from "node:url";
13254
- var fixturesRoot = join5(dirname4(dirname4(fileURLToPath(import.meta.url))), "data");
13499
+ var fixturesRoot = join6(dirname5(dirname5(fileURLToPath(import.meta.url))), "data");
13255
13500
  function fixturePath(...segments) {
13256
- return join5(fixturesRoot, ...segments);
13501
+ return join6(fixturesRoot, ...segments);
13257
13502
  }
13258
13503
 
13259
13504
  // packages/live/dist/receiver.js
@@ -13373,7 +13618,7 @@ function isHookPayload(value) {
13373
13618
  }
13374
13619
  var HOOK_BODY_LIMIT = 1024 * 1024;
13375
13620
  function readBody(req) {
13376
- return new Promise((resolve13, reject) => {
13621
+ return new Promise((resolve15, reject) => {
13377
13622
  const chunks = [];
13378
13623
  let size = 0;
13379
13624
  req.on("data", (chunk) => {
@@ -13385,7 +13630,7 @@ function readBody(req) {
13385
13630
  }
13386
13631
  chunks.push(chunk);
13387
13632
  });
13388
- req.on("end", () => resolve13(Buffer.concat(chunks).toString("utf8")));
13633
+ req.on("end", () => resolve15(Buffer.concat(chunks).toString("utf8")));
13389
13634
  req.on("error", reject);
13390
13635
  });
13391
13636
  }
@@ -13400,9 +13645,9 @@ function sendText(res, status3, body) {
13400
13645
 
13401
13646
  // apps/cli/dist/license.js
13402
13647
  import { verify } from "node:crypto";
13403
- import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync2, renameSync, writeFileSync as writeFileSync2 } from "node:fs";
13648
+ import { existsSync as existsSync4, mkdirSync as mkdirSync3, readFileSync as readFileSync3, renameSync, writeFileSync as writeFileSync3 } from "node:fs";
13404
13649
  import { homedir as homedir3 } from "node:os";
13405
- import { join as join6 } from "node:path";
13650
+ import { join as join7 } from "node:path";
13406
13651
  var OFFLINE_GRACE_DAYS = 14;
13407
13652
  var PROD_PUBLIC_KEY_PEM = "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAyU4yO0SJcflt/CV77wqVxIwCkM52CYGC6qrPGP8dMME=\n-----END PUBLIC KEY-----\n";
13408
13653
  function checkLicense(options = {}) {
@@ -13416,7 +13661,7 @@ function licenseStatus(options = {}) {
13416
13661
  const home = options.homeDir ?? homedir3();
13417
13662
  let raw;
13418
13663
  try {
13419
- raw = readFileSync2(join6(home, ".wingman", "license.json"), "utf8");
13664
+ raw = readFileSync3(join7(home, ".wingman", "license.json"), "utf8");
13420
13665
  } catch {
13421
13666
  return { state: "none", detail: "\u672A\u5B89\u88C5 license(anatomy \u4E0E\u5B9E\u51B5\u514D\u8D39\u53EF\u7528;\u5199\u52A8\u4F5C\u9700\u8BA2\u9605)" };
13422
13667
  }
@@ -13483,7 +13728,7 @@ function verifyEntitlement(raw, now, publicKeyPem) {
13483
13728
  function nextLicenseBackupPath(licensePath, now) {
13484
13729
  const base = `${licensePath}.bak-${now.toISOString().replaceAll(":", "-")}`;
13485
13730
  let candidate = base;
13486
- for (let index = 2; existsSync3(candidate); index++)
13731
+ for (let index = 2; existsSync4(candidate); index++)
13487
13732
  candidate = `${base}-${index}`;
13488
13733
  return candidate;
13489
13734
  }
@@ -13504,13 +13749,13 @@ function installLicense(raw, options = {}) {
13504
13749
  return { ok: false, error: status3.detail };
13505
13750
  }
13506
13751
  }
13507
- const dir = join6(options.homeDir ?? homedir3(), ".wingman");
13508
- const licensePath = join6(dir, "license.json");
13509
- const tmpPath = join6(dir, `.license.json.tmp-${process.pid}`);
13752
+ const dir = join7(options.homeDir ?? homedir3(), ".wingman");
13753
+ const licensePath = join7(dir, "license.json");
13754
+ const tmpPath = join7(dir, `.license.json.tmp-${process.pid}`);
13510
13755
  try {
13511
- mkdirSync2(dir, { recursive: true });
13512
- writeFileSync2(tmpPath, raw);
13513
- if (existsSync3(licensePath)) {
13756
+ mkdirSync3(dir, { recursive: true });
13757
+ writeFileSync3(tmpPath, raw);
13758
+ if (existsSync4(licensePath)) {
13514
13759
  renameSync(licensePath, nextLicenseBackupPath(licensePath, options.now ?? /* @__PURE__ */ new Date()));
13515
13760
  }
13516
13761
  renameSync(tmpPath, licensePath);
@@ -13522,17 +13767,17 @@ function installLicense(raw, options = {}) {
13522
13767
  }
13523
13768
 
13524
13769
  // apps/cli/dist/license-refresh.js
13525
- import { copyFileSync, readFileSync as readFileSync3, renameSync as renameSync2, writeFileSync as writeFileSync3 } from "node:fs";
13770
+ import { copyFileSync, readFileSync as readFileSync4, renameSync as renameSync2, writeFileSync as writeFileSync4 } from "node:fs";
13526
13771
  import { homedir as homedir4 } from "node:os";
13527
- import { dirname as dirname5, join as join7 } from "node:path";
13772
+ import { dirname as dirname6, join as join8 } from "node:path";
13528
13773
  var DEFAULT_LICENSE_SERVER = "https://api.getwingman.dev";
13529
13774
  async function refreshLicense(options = {}) {
13530
13775
  const home = options.homeDir ?? homedir4();
13531
13776
  const baseUrl = options.baseUrl ?? process.env.WINGMAN_LICENSE_SERVER ?? DEFAULT_LICENSE_SERVER;
13532
- const licensePath = join7(home, ".wingman", "license.json");
13777
+ const licensePath = join8(home, ".wingman", "license.json");
13533
13778
  let raw;
13534
13779
  try {
13535
- raw = readFileSync3(licensePath, "utf8");
13780
+ raw = readFileSync4(licensePath, "utf8");
13536
13781
  } catch {
13537
13782
  return {
13538
13783
  ok: false,
@@ -13602,7 +13847,7 @@ async function refreshLicense(options = {}) {
13602
13847
  }
13603
13848
  }
13604
13849
  try {
13605
- if (readFileSync3(licensePath, "utf8") !== raw) {
13850
+ if (readFileSync4(licensePath, "utf8") !== raw) {
13606
13851
  return {
13607
13852
  ok: false,
13608
13853
  message: "\u5237\u65B0\u671F\u95F4\u672C\u673A\u6388\u6743\u5DF2\u88AB\u66F4\u6362;\u5DF2\u4FDD\u7559\u8F83\u65B0\u7684\u6587\u4EF6,\u8BF7\u518D\u70B9\u4E00\u6B21\u5237\u65B0",
@@ -13616,9 +13861,9 @@ async function refreshLicense(options = {}) {
13616
13861
  reason: "changed"
13617
13862
  };
13618
13863
  }
13619
- const tmpPath = join7(dirname5(licensePath), `.license.json.tmp-${process.pid}`);
13864
+ const tmpPath = join8(dirname6(licensePath), `.license.json.tmp-${process.pid}`);
13620
13865
  try {
13621
- writeFileSync3(tmpPath, next);
13866
+ writeFileSync4(tmpPath, next);
13622
13867
  copyFileSync(licensePath, nextLicenseBackupPath(licensePath, options.now ?? /* @__PURE__ */ new Date()));
13623
13868
  renameSync2(tmpPath, licensePath);
13624
13869
  } catch (error) {
@@ -13646,7 +13891,7 @@ init_dist5();
13646
13891
  init_dist2();
13647
13892
  init_dist();
13648
13893
  import { readdir as readdir2 } from "node:fs/promises";
13649
- import { isAbsolute as isAbsolute6, join as join22, resolve as resolve9 } from "node:path";
13894
+ import { isAbsolute as isAbsolute6, join as join25, resolve as resolve11 } from "node:path";
13650
13895
 
13651
13896
  // packages/narrative/dist/attribute.js
13652
13897
  function extractSteps(lines2) {
@@ -13671,13 +13916,13 @@ function extractSteps(lines2) {
13671
13916
  byToolUseId.set(block.id, step);
13672
13917
  }
13673
13918
  } else if (line.kind === "user") {
13674
- for (const result4 of line.toolResults) {
13675
- const step = byToolUseId.get(result4.toolUseId);
13919
+ for (const result5 of line.toolResults) {
13920
+ const step = byToolUseId.get(result5.toolUseId);
13676
13921
  if (step === void 0)
13677
13922
  continue;
13678
13923
  if (line.timestamp !== void 0)
13679
13924
  step.endTs = line.timestamp;
13680
- if (result4.isError)
13925
+ if (result5.isError)
13681
13926
  step.isError = true;
13682
13927
  }
13683
13928
  }
@@ -13849,17 +14094,17 @@ function parseResponseItem(payload, timestamp) {
13849
14094
  return call;
13850
14095
  }
13851
14096
  if (payload !== void 0 && (payloadType === "function_call_output" || payloadType === "custom_tool_call_output")) {
13852
- const result4 = { kind: "tool_result", resultType: payloadType };
13853
- assignString(result4, "timestamp", timestamp);
13854
- assignString(result4, "callId", optionalString(payload.call_id));
13855
- assignString(result4, "itemId", optionalString(payload.id));
13856
- assignString(result4, "turnId", extractTurnId(payload));
14097
+ const result5 = { kind: "tool_result", resultType: payloadType };
14098
+ assignString(result5, "timestamp", timestamp);
14099
+ assignString(result5, "callId", optionalString(payload.call_id));
14100
+ assignString(result5, "itemId", optionalString(payload.id));
14101
+ assignString(result5, "turnId", extractTurnId(payload));
13857
14102
  if (payload.output !== void 0) {
13858
- result4.output = payload.output;
14103
+ result5.output = payload.output;
13859
14104
  if (codexToolResultIsError(payload.output))
13860
- result4.isError = true;
14105
+ result5.isError = true;
13861
14106
  }
13862
- return result4;
14107
+ return result5;
13863
14108
  }
13864
14109
  return otherLine("response_item", payload, timestamp);
13865
14110
  }
@@ -14041,13 +14286,13 @@ function parseUser(raw, common) {
14041
14286
  if (!isRecord3(block))
14042
14287
  continue;
14043
14288
  if (block.type === "tool_result" && typeof block.tool_use_id === "string") {
14044
- const result4 = {
14289
+ const result5 = {
14045
14290
  toolUseId: block.tool_use_id,
14046
14291
  // 实测:成功结果常无 is_error 字段;仅显式 true 视为失败
14047
14292
  isError: block.is_error === true,
14048
14293
  content: block.content
14049
14294
  };
14050
- line.toolResults.push(result4);
14295
+ line.toolResults.push(result5);
14051
14296
  } else if (block.type === "text" && typeof block.text === "string") {
14052
14297
  texts.push(block.text);
14053
14298
  }
@@ -14570,11 +14815,11 @@ function buildTaskCreateResultIndex(lines2) {
14570
14815
  for (const line of lines2) {
14571
14816
  if (line.kind !== "user")
14572
14817
  continue;
14573
- const result4 = line.toolUseResult;
14574
- if (!isRecord3(result4) || !isRecord3(result4.task) || typeof result4.task.id !== "string")
14818
+ const result5 = line.toolUseResult;
14819
+ if (!isRecord3(result5) || !isRecord3(result5.task) || typeof result5.task.id !== "string")
14575
14820
  continue;
14576
14821
  for (const toolResult of line.toolResults)
14577
- index.set(toolResult.toolUseId, result4.task.id);
14822
+ index.set(toolResult.toolUseId, result5.task.id);
14578
14823
  }
14579
14824
  return index;
14580
14825
  }
@@ -14708,7 +14953,7 @@ function turnUsage(line) {
14708
14953
  if (inputTokens === void 0 || cacheCreationInputTokens === void 0 || cacheReadInputTokens === void 0 || outputTokens === void 0) {
14709
14954
  return void 0;
14710
14955
  }
14711
- const result4 = {
14956
+ const result5 = {
14712
14957
  inputTokens,
14713
14958
  cacheCreationInputTokens,
14714
14959
  cacheReadInputTokens,
@@ -14723,11 +14968,11 @@ function turnUsage(line) {
14723
14968
  const fiveMinute = finiteNumber(breakdown.ephemeral_5m_input_tokens);
14724
14969
  const oneHour = finiteNumber(breakdown.ephemeral_1h_input_tokens);
14725
14970
  if (fiveMinute !== void 0)
14726
- result4.cacheCreation5mTokens = fiveMinute;
14971
+ result5.cacheCreation5mTokens = fiveMinute;
14727
14972
  if (oneHour !== void 0)
14728
- result4.cacheCreation1hTokens = oneHour;
14973
+ result5.cacheCreation1hTokens = oneHour;
14729
14974
  }
14730
- return result4;
14975
+ return result5;
14731
14976
  }
14732
14977
  function finiteNumber(value) {
14733
14978
  return typeof value === "number" && Number.isFinite(value) ? value : void 0;
@@ -15101,9 +15346,9 @@ function fromTool(harness, name, input, source, at) {
15101
15346
  return [];
15102
15347
  if (harness === "codex" && name === "exec") {
15103
15348
  const inputText = toolText(input, ["input"]);
15104
- const paths = codexExecPatchPaths(inputText);
15105
- if (paths.length > 0) {
15106
- return paths.map((path) => fileObservation(path, "codex apply_patch via exec", source, false, at));
15349
+ const paths3 = codexExecPatchPaths(inputText);
15350
+ if (paths3.length > 0) {
15351
+ return paths3.map((path) => fileObservation(path, "codex apply_patch via exec", source, false, at));
15107
15352
  }
15108
15353
  }
15109
15354
  if (name === "Bash" || name === "exec") {
@@ -15145,13 +15390,13 @@ function fileObservation(path, method, source, wholeFile, at) {
15145
15390
  function patchPaths(patch) {
15146
15391
  if (patch === void 0)
15147
15392
  return [];
15148
- const paths = [];
15393
+ const paths3 = [];
15149
15394
  for (const line of patch.split("\n")) {
15150
15395
  const match = /^\*\*\* (?:Update|Add) File: (.+?)\s*$/u.exec(line);
15151
15396
  if (match?.[1] !== void 0 && isPlanPath(match[1]))
15152
- paths.push(match[1]);
15397
+ paths3.push(match[1]);
15153
15398
  }
15154
- return paths;
15399
+ return paths3;
15155
15400
  }
15156
15401
  function codexExecPatchPaths(input) {
15157
15402
  if (input === void 0 || !input.includes("*** Begin Patch"))
@@ -15212,22 +15457,29 @@ function isRecord5(value) {
15212
15457
 
15213
15458
  // apps/cli/dist/project-index.js
15214
15459
  import { lstat, readFile as readFile3, realpath, stat as stat3 } from "node:fs/promises";
15215
- import { dirname as dirname14, isAbsolute as isAbsolute4, join as join19, relative as relative3, resolve as resolve8 } from "node:path";
15460
+ import { dirname as dirname15, isAbsolute as isAbsolute4, join as join22, relative as relative3, resolve as resolve10 } from "node:path";
15216
15461
  var PROJECT_ROOT_MAX_DIRECTORIES = 8;
15217
15462
  var PROJECT_PLAN_POLL_MS = 2e3;
15218
15463
  async function resolveProjectRoot(cwd, options) {
15219
- const root = resolve8(cwd);
15220
- const homeDir = resolve8(options.homeDir);
15221
- const boundaryDir = options.boundaryDir === void 0 ? void 0 : resolve8(options.boundaryDir);
15464
+ const root = resolve10(cwd);
15465
+ const homeDir = resolve10(options.homeDir);
15466
+ const boundaryDir = options.boundaryDir === void 0 ? void 0 : resolve10(options.boundaryDir);
15222
15467
  const [rootIdentity, homeIdentity, boundaryIdentity] = await Promise.all([
15223
15468
  pathIdentity(root),
15224
15469
  pathIdentity(homeDir),
15225
15470
  boundaryDir === void 0 ? void 0 : pathIdentity(boundaryDir)
15226
15471
  ]);
15227
- const wingmanHomeIdentity = await pathIdentity(join19(homeIdentity, ".wingman"));
15228
- const planPathIdentity = await pathIdentity(join19(rootIdentity, ".wingman", "plan.md"));
15472
+ const wingmanHomeIdentity = await pathIdentity(join22(homeIdentity, ".wingman"));
15473
+ const planPathIdentity = await pathIdentity(join22(rootIdentity, ".wingman", "plan.md"));
15229
15474
  if (rootIdentity === homeIdentity || rootIdentity === wingmanHomeIdentity || boundaryIdentity !== void 0 && !isWithin(boundaryIdentity, rootIdentity)) {
15230
- return { root, rootIdentity, planPathIdentity, lookedUp: [], higherPlanPaths: [] };
15475
+ return {
15476
+ root,
15477
+ rootIdentity,
15478
+ planPathIdentity,
15479
+ lookedUp: [],
15480
+ higherPlanPaths: [],
15481
+ ...rootIdentity === homeIdentity ? { isHome: true } : {}
15482
+ };
15231
15483
  }
15232
15484
  const lookedUp = [];
15233
15485
  const found = [];
@@ -15239,7 +15491,7 @@ async function resolveProjectRoot(cwd, options) {
15239
15491
  break;
15240
15492
  if (boundaryIdentity !== void 0 && !isWithin(boundaryIdentity, currentIdentity))
15241
15493
  break;
15242
- const planPath = join19(current, ".wingman", "plan.md");
15494
+ const planPath = join22(current, ".wingman", "plan.md");
15243
15495
  lookedUp.push(planPath);
15244
15496
  try {
15245
15497
  await lstat(planPath);
@@ -15251,7 +15503,7 @@ async function resolveProjectRoot(cwd, options) {
15251
15503
  });
15252
15504
  } catch {
15253
15505
  }
15254
- const parent = dirname14(current);
15506
+ const parent = dirname15(current);
15255
15507
  if (parent === current)
15256
15508
  break;
15257
15509
  current = parent;
@@ -15329,7 +15581,7 @@ function watchProjectPlan(planPath, options) {
15329
15581
  };
15330
15582
  }
15331
15583
  async function pathIdentity(path) {
15332
- const resolved = resolve8(path);
15584
+ const resolved = resolve10(path);
15333
15585
  try {
15334
15586
  return normalizedPath(await realpath(resolved));
15335
15587
  } catch {
@@ -15344,7 +15596,7 @@ async function pathsReferToSameLocation(left, right) {
15344
15596
  return relative3(leftIdentity, rightIdentity) === "";
15345
15597
  }
15346
15598
  function normalizedPath(path) {
15347
- const resolved = resolve8(path);
15599
+ const resolved = resolve10(path);
15348
15600
  return process.platform === "win32" ? resolved.toLowerCase() : resolved;
15349
15601
  }
15350
15602
  function isWithin(parent, child) {
@@ -15354,17 +15606,17 @@ function isWithin(parent, child) {
15354
15606
 
15355
15607
  // apps/cli/dist/project-roots.js
15356
15608
  import { randomBytes as randomBytes2 } from "node:crypto";
15357
- import { closeSync, mkdirSync as mkdirSync9, openSync, readFileSync as readFileSync13, renameSync as renameSync3, rmSync as rmSync7, statSync as statSync5, writeFileSync as writeFileSync10 } from "node:fs";
15358
- import { dirname as dirname15, isAbsolute as isAbsolute5, join as join20 } from "node:path";
15609
+ import { closeSync, mkdirSync as mkdirSync10, openSync, readFileSync as readFileSync14, renameSync as renameSync3, rmSync as rmSync8, statSync as statSync5, writeFileSync as writeFileSync11 } from "node:fs";
15610
+ import { dirname as dirname16, isAbsolute as isAbsolute5, join as join23 } from "node:path";
15359
15611
  var PROJECT_ROOTS_MAX_ENTRIES = 200;
15360
15612
  function projectRootsPath(homeDir) {
15361
- return join20(homeDir, ".wingman", "state", "projects.json");
15613
+ return join23(homeDir, ".wingman", "state", "projects.json");
15362
15614
  }
15363
15615
  function readProjectRoots(homeDir) {
15364
15616
  const path = projectRootsPath(homeDir);
15365
15617
  let raw;
15366
15618
  try {
15367
- raw = readFileSync13(path, "utf8");
15619
+ raw = readFileSync14(path, "utf8");
15368
15620
  } catch (error) {
15369
15621
  if (isErrno(error, "ENOENT"))
15370
15622
  return { version: 1, roots: {} };
@@ -15404,7 +15656,7 @@ function pruneProjectRoots(homeDir) {
15404
15656
  return current;
15405
15657
  const roots = Object.fromEntries(Object.entries(current.roots).filter(([, entry]) => {
15406
15658
  try {
15407
- statSync5(join20(entry.root, ".wingman", "plan.md"));
15659
+ statSync5(join23(entry.root, ".wingman", "plan.md"));
15408
15660
  return true;
15409
15661
  } catch (error) {
15410
15662
  return !isErrno(error, "ENOENT") && !isErrno(error, "ENOTDIR");
@@ -15428,12 +15680,12 @@ function limitRoots(roots) {
15428
15680
  }
15429
15681
  function writeProjectRoots(homeDir, state) {
15430
15682
  const path = projectRootsPath(homeDir);
15431
- const tempPath = join20(dirname15(path), `.projects-${randomBytes2(8).toString("hex")}.tmp`);
15683
+ const tempPath = join23(dirname16(path), `.projects-${randomBytes2(8).toString("hex")}.tmp`);
15432
15684
  let fd;
15433
15685
  try {
15434
- mkdirSync9(dirname15(path), { recursive: true, mode: 448 });
15686
+ mkdirSync10(dirname16(path), { recursive: true, mode: 448 });
15435
15687
  fd = openSync(tempPath, "wx", 384);
15436
- writeFileSync10(fd, `${JSON.stringify(state)}
15688
+ writeFileSync11(fd, `${JSON.stringify(state)}
15437
15689
  `, "utf8");
15438
15690
  closeSync(fd);
15439
15691
  fd = void 0;
@@ -15446,7 +15698,7 @@ function writeProjectRoots(homeDir, state) {
15446
15698
  }
15447
15699
  }
15448
15700
  try {
15449
- rmSync7(tempPath, { force: true });
15701
+ rmSync8(tempPath, { force: true });
15450
15702
  } catch {
15451
15703
  }
15452
15704
  throw error;
@@ -15475,16 +15727,16 @@ function isErrno(error, code) {
15475
15727
 
15476
15728
  // apps/cli/dist/task-overlay.js
15477
15729
  import { randomBytes as randomBytes3 } from "node:crypto";
15478
- import { closeSync as closeSync2, mkdirSync as mkdirSync10, openSync as openSync2, readFileSync as readFileSync14, renameSync as renameSync4, rmSync as rmSync8, writeFileSync as writeFileSync11 } from "node:fs";
15479
- import { dirname as dirname16, join as join21 } from "node:path";
15730
+ import { closeSync as closeSync2, mkdirSync as mkdirSync11, openSync as openSync2, readFileSync as readFileSync15, renameSync as renameSync4, rmSync as rmSync9, writeFileSync as writeFileSync12 } from "node:fs";
15731
+ import { dirname as dirname17, join as join24 } from "node:path";
15480
15732
  function taskOverlayPath(homeDir) {
15481
- return join21(homeDir, ".wingman", "state", "task-overlay.json");
15733
+ return join24(homeDir, ".wingman", "state", "task-overlay.json");
15482
15734
  }
15483
15735
  function readTaskOverlay(homeDir) {
15484
15736
  const path = taskOverlayPath(homeDir);
15485
15737
  let raw;
15486
15738
  try {
15487
- raw = readFileSync14(path, "utf8");
15739
+ raw = readFileSync15(path, "utf8");
15488
15740
  } catch (error) {
15489
15741
  if (isErrno2(error, "ENOENT"))
15490
15742
  return { version: 1, entries: {} };
@@ -15536,12 +15788,12 @@ function patchTaskOverlay(homeDir, key, patch, now) {
15536
15788
  }
15537
15789
  function writeTaskOverlay(homeDir, overlay) {
15538
15790
  const path = taskOverlayPath(homeDir);
15539
- const tempPath = join21(dirname16(path), `.task-overlay-${randomBytes3(8).toString("hex")}.tmp`);
15791
+ const tempPath = join24(dirname17(path), `.task-overlay-${randomBytes3(8).toString("hex")}.tmp`);
15540
15792
  let fd;
15541
15793
  try {
15542
- mkdirSync10(dirname16(path), { recursive: true, mode: 448 });
15794
+ mkdirSync11(dirname17(path), { recursive: true, mode: 448 });
15543
15795
  fd = openSync2(tempPath, "wx", 384);
15544
- writeFileSync11(fd, `${JSON.stringify(overlay)}
15796
+ writeFileSync12(fd, `${JSON.stringify(overlay)}
15545
15797
  `, "utf8");
15546
15798
  closeSync2(fd);
15547
15799
  fd = void 0;
@@ -15554,7 +15806,7 @@ function writeTaskOverlay(homeDir, overlay) {
15554
15806
  }
15555
15807
  }
15556
15808
  try {
15557
- rmSync8(tempPath, { force: true });
15809
+ rmSync9(tempPath, { force: true });
15558
15810
  } catch {
15559
15811
  }
15560
15812
  throw error;
@@ -15587,7 +15839,7 @@ function errorMessage(error) {
15587
15839
  }
15588
15840
 
15589
15841
  // apps/cli/dist/version.js
15590
- import { readFileSync as readFileSync15 } from "node:fs";
15842
+ import { readFileSync as readFileSync16 } from "node:fs";
15591
15843
  function resolveWingmanVersion({ defined, moduleUrl = import.meta.url, readPackage }) {
15592
15844
  if (typeof defined === "string" && defined.trim() !== "")
15593
15845
  return defined;
@@ -15606,10 +15858,10 @@ function resolveWingmanVersion({ defined, moduleUrl = import.meta.url, readPacka
15606
15858
  return void 0;
15607
15859
  }
15608
15860
  function wingmanVersion() {
15609
- const defined = false ? void 0 : "0.8.0";
15861
+ const defined = false ? void 0 : "0.8.1";
15610
15862
  return resolveWingmanVersion({
15611
15863
  defined,
15612
- readPackage: (url) => JSON.parse(readFileSync15(url, "utf8"))
15864
+ readPackage: (url) => JSON.parse(readFileSync16(url, "utf8"))
15613
15865
  });
15614
15866
  }
15615
15867
 
@@ -15692,6 +15944,9 @@ function createNarrativeService(options = {}) {
15692
15944
  generation: 0,
15693
15945
  lines: [],
15694
15946
  codexLines: [],
15947
+ instructionSeq: 0,
15948
+ sessionPlanSeq: 0,
15949
+ hookInstructions: [],
15695
15950
  pendingPlanWrites: [],
15696
15951
  confirmedPlanWrites: [],
15697
15952
  nonPlanToolSteps: 0,
@@ -15725,6 +15980,8 @@ function createNarrativeService(options = {}) {
15725
15980
  if (closed || session.cwd !== cwd)
15726
15981
  return;
15727
15982
  session.projectResolution = resolution;
15983
+ if (resolution.isHome)
15984
+ session.label = "\u65E0\u9879\u76EE\u76EE\u5F55(\u5BB6\u76EE\u5F55)";
15728
15985
  seenProjectRoots.add(resolution.rootIdentity);
15729
15986
  rememberResolution(resolution);
15730
15987
  watchResolution(resolution);
@@ -15778,7 +16035,7 @@ function createNarrativeService(options = {}) {
15778
16035
  function watchResolution(resolution) {
15779
16036
  if (resolution.lookedUp.length === 0)
15780
16037
  return;
15781
- const planPath = resolution.planPath ?? join22(resolution.root, ".wingman", "plan.md");
16038
+ const planPath = resolution.planPath ?? join25(resolution.root, ".wingman", "plan.md");
15782
16039
  const planPathIdentity = resolution.planPathIdentity;
15783
16040
  if (projectWatchers.has(planPathIdentity))
15784
16041
  return;
@@ -15867,7 +16124,7 @@ function createNarrativeService(options = {}) {
15867
16124
  for (const session of sessions.values()) {
15868
16125
  const resolution = session.projectResolution;
15869
16126
  if (resolution?.planPathIdentity === planPathIdentity) {
15870
- const planPath = resolution.planPath ?? join22(resolution.root, ".wingman", "plan.md");
16127
+ const planPath = resolution.planPath ?? join25(resolution.root, ".wingman", "plan.md");
15871
16128
  void applyPendingPlanWrites(session, planPath, planPathIdentity).then(() => {
15872
16129
  session.dirty = true;
15873
16130
  notify(harness);
@@ -15912,7 +16169,7 @@ function createNarrativeService(options = {}) {
15912
16169
  }
15913
16170
  const resolution = session.projectResolution;
15914
16171
  if (resolution !== void 0) {
15915
- const planPath = resolution.planPath ?? join22(resolution.root, ".wingman", "plan.md");
16172
+ const planPath = resolution.planPath ?? join25(resolution.root, ".wingman", "plan.md");
15916
16173
  void applyPendingPlanWrites(session, planPath, resolution.planPathIdentity).then(() => {
15917
16174
  session.dirty = true;
15918
16175
  notify(harness);
@@ -15942,12 +16199,12 @@ function createNarrativeService(options = {}) {
15942
16199
  at: observation.at ?? versions.current.info.mtime,
15943
16200
  nonPlanStepsBefore: pending.nonPlanStepsBefore
15944
16201
  });
15945
- const result4 = attributePlanWrite(before, after, observation);
15946
- if ("attachedTo" in result4) {
15947
- session.planAttachment = result4;
16202
+ const result5 = attributePlanWrite(before, after, observation);
16203
+ if ("attachedTo" in result5) {
16204
+ session.planAttachment = result5;
15948
16205
  session.planUnattachedReason = void 0;
15949
16206
  } else {
15950
- session.planUnattachedReason = result4.reason;
16207
+ session.planUnattachedReason = result5.reason;
15951
16208
  }
15952
16209
  }
15953
16210
  session.pendingPlanWrites = remaining;
@@ -16002,8 +16259,13 @@ function createNarrativeService(options = {}) {
16002
16259
  session.lines = [];
16003
16260
  session.codexLines = [];
16004
16261
  session.hookIntervals = [];
16005
- session.hookPrompt = void 0;
16006
- session.hookPromptAt = void 0;
16262
+ if (session.transcriptPath !== void 0) {
16263
+ session.hookPrompt = void 0;
16264
+ session.hookPromptAt = void 0;
16265
+ session.hookInstructions = [];
16266
+ }
16267
+ session.instructionSeq = 0;
16268
+ session.sessionPlanSeq = 0;
16007
16269
  session.mockNote = void 0;
16008
16270
  session.transcriptPath = path;
16009
16271
  session.dirty = true;
@@ -16040,7 +16302,7 @@ function createNarrativeService(options = {}) {
16040
16302
  const sessionDir = transcriptPath.replace(/\.jsonl$/, "");
16041
16303
  if (sessionDir === transcriptPath)
16042
16304
  return;
16043
- const subagentsDir = join22(sessionDir, "subagents");
16305
+ const subagentsDir = join25(sessionDir, "subagents");
16044
16306
  const generation = session.generation;
16045
16307
  const poll = async () => {
16046
16308
  try {
@@ -16050,7 +16312,7 @@ function createNarrativeService(options = {}) {
16050
16312
  }
16051
16313
  for (const entry of entries) {
16052
16314
  if (/^agent-.*\.jsonl$/.test(entry)) {
16053
- startFollowing(harness, session, join22(subagentsDir, entry), generation);
16315
+ startFollowing(harness, session, join25(subagentsDir, entry), generation);
16054
16316
  }
16055
16317
  }
16056
16318
  } catch {
@@ -16073,7 +16335,7 @@ function createNarrativeService(options = {}) {
16073
16335
  if (cwd !== void 0) {
16074
16336
  anchorCwd(event.harness, session, cwd);
16075
16337
  const base = pathBasename(cwd);
16076
- if (base !== "")
16338
+ if (base !== "" && !session.projectResolution?.isHome)
16077
16339
  session.label = base;
16078
16340
  }
16079
16341
  recordToolObservations(event.harness, session, extractToolObservations(event.harness, [{ ...payload, received_at: event.received_at }]));
@@ -16086,11 +16348,17 @@ function createNarrativeService(options = {}) {
16086
16348
  }
16087
16349
  }
16088
16350
  }
16089
- if (name === "UserPromptSubmit" && typeof payload.prompt === "string") {
16090
- const prompt = payload.prompt.trim();
16091
- if (prompt !== "" && !isHarnessSystemNotice(prompt)) {
16092
- session.hookPrompt = truncate(prompt, DETAIL_LIMIT);
16093
- session.hookPromptAt = event.received_at;
16351
+ if (name === "UserPromptSubmit") {
16352
+ const prompt = typeof payload.prompt === "string" ? payload.prompt.trim() : void 0;
16353
+ if (prompt === void 0 || prompt !== "" && !isHarnessSystemNotice(prompt)) {
16354
+ session.hookInstructions.push({
16355
+ at: event.received_at,
16356
+ ...prompt === void 0 ? {} : { text: prompt }
16357
+ });
16358
+ if (prompt !== void 0) {
16359
+ session.hookPrompt = truncate(prompt, DETAIL_LIMIT);
16360
+ session.hookPromptAt = event.received_at;
16361
+ }
16094
16362
  }
16095
16363
  }
16096
16364
  if (name === "SubagentStart") {
@@ -16176,7 +16444,7 @@ function createNarrativeService(options = {}) {
16176
16444
  if (cwd !== void 0) {
16177
16445
  anchorCwd(harness, session2, cwd);
16178
16446
  const base = pathBasename(cwd);
16179
- if (base !== "")
16447
+ if (base !== "" && !session2.projectResolution?.isHome)
16180
16448
  session2.label = base;
16181
16449
  }
16182
16450
  session2.dirty = true;
@@ -16203,7 +16471,7 @@ function createNarrativeService(options = {}) {
16203
16471
  if (typeof cwd === "string") {
16204
16472
  anchorCwd(harness, session, cwd);
16205
16473
  const base = pathBasename(cwd);
16206
- if (base !== "")
16474
+ if (base !== "" && !session.projectResolution?.isHome)
16207
16475
  session.label = base;
16208
16476
  break;
16209
16477
  }
@@ -16345,7 +16613,7 @@ function createNarrativeService(options = {}) {
16345
16613
  for (const session of sessions.values()) {
16346
16614
  if (session.cwd === void 0)
16347
16615
  continue;
16348
- const rootIdentity = session.projectResolution?.rootIdentity ?? resolve9(session.cwd);
16616
+ const rootIdentity = session.projectResolution?.rootIdentity ?? resolve11(session.cwd);
16349
16617
  const group = grouped.get(rootIdentity);
16350
16618
  if (group === void 0) {
16351
16619
  grouped.set(rootIdentity, {
@@ -16365,8 +16633,8 @@ function createNarrativeService(options = {}) {
16365
16633
  for (const [rootIdentity, group] of grouped) {
16366
16634
  const { members } = group;
16367
16635
  const resolution = members.find((member) => member.session.projectResolution !== void 0)?.session.projectResolution ?? group.resolution;
16368
- const root = resolution?.root ?? resolve9(members[0]?.session.cwd ?? "");
16369
- const planPath = resolution?.planPath ?? join22(root, ".wingman", "plan.md");
16636
+ const root = resolution?.root ?? resolve11(members[0]?.session.cwd ?? "");
16637
+ const planPath = resolution?.planPath ?? join25(root, ".wingman", "plan.md");
16370
16638
  const runtime = projectFiles.get(resolution?.planPathIdentity ?? planPath);
16371
16639
  const parsed = runtime?.missing === true ? void 0 : runtime?.parsed;
16372
16640
  const planMtime = parsed?.availability === "available" ? runtime?.current?.info.mtime : void 0;
@@ -16384,12 +16652,13 @@ function createNarrativeService(options = {}) {
16384
16652
  const verification = state?.taskWorkflow?.verification;
16385
16653
  const attachedTitle = session.planAttachment?.attachedTo.split(" > ").at(-1);
16386
16654
  const instructionTitle = state?.taskWorkflow?.latestInstruction?.text;
16655
+ const planInstruction = state?.taskWorkflow?.plan.availability === "available" ? session.sessionPlanInstruction : void 0;
16387
16656
  return {
16388
16657
  harness,
16389
16658
  id: session.id,
16390
16659
  label,
16391
16660
  ended: info?.ended ?? false,
16392
- title: attachedTitle !== void 0 ? { text: attachedTitle, source: "plan.md \u6B65\u9AA4" } : instructionTitle !== void 0 ? { text: truncate(instructionTitle, DETAIL_LIMIT), source: "\u6700\u65B0\u6307\u4EE4" } : { text: label, source: "\u5DE5\u4F5C\u76EE\u5F55" },
16661
+ title: attachedTitle !== void 0 ? { text: attachedTitle, source: "plan.md \u6B65\u9AA4" } : planInstruction !== void 0 ? { text: truncate(planInstruction, DETAIL_LIMIT), source: "\u8BA1\u5212\u6240\u5C5E\u6307\u4EE4" } : instructionTitle !== void 0 ? { text: truncate(instructionTitle, DETAIL_LIMIT), source: "\u6700\u65B0\u6307\u4EE4" } : { text: label, source: "\u5DE5\u4F5C\u76EE\u5F55" },
16393
16662
  user: {
16394
16663
  ...userEntry?.title === void 0 ? {} : { title: userEntry.title },
16395
16664
  pinned: userEntry?.pinned ?? false,
@@ -16434,14 +16703,14 @@ function createNarrativeService(options = {}) {
16434
16703
  id: `${session.harness}:${session.id}`,
16435
16704
  ...session.attachedTo === void 0 ? {} : { attachedTo: session.attachedTo },
16436
16705
  ended: session.ended,
16437
- ...session.sessionPlan?.availability === "available" && session.sessionPlan.steps.length > 0 ? {
16706
+ ...session.sessionPlan?.availability === "available" && session.sessionPlan.forInstruction === "current" && session.sessionPlan.steps.length > 0 ? {
16438
16707
  sessionPlanAllCompleted: session.sessionPlan.steps.every((step) => step.status === "completed")
16439
16708
  } : {},
16440
16709
  ...session.attachedBy?.at === void 0 ? {} : { wrotePlanAt: session.attachedBy.at }
16441
16710
  })), now().toISOString());
16442
16711
  const lastWriter = [...sessionViews].filter((session) => typeof session.attachedBy?.at === "string").sort((left, right) => right.attachedBy.at.localeCompare(left.attachedBy.at))[0];
16443
- const titleText = parsed?.availability === "available" && parsed.title !== void 0 ? parsed.title : pathBasename(root) || root;
16444
- const titleSource = parsed?.availability === "available" && parsed.title !== void 0 ? ".wingman/plan.md H1" : "\u5DE5\u4F5C\u76EE\u5F55";
16712
+ const titleText = resolution?.isHome ? "\u65E0\u9879\u76EE\u76EE\u5F55(\u5BB6\u76EE\u5F55)" : parsed?.availability === "available" && parsed.title !== void 0 ? parsed.title : pathBasename(root) || root;
16713
+ const titleSource = resolution?.isHome ? "\u5DE5\u4F5C\u76EE\u5F55 = \u5BB6\u76EE\u5F55" : parsed?.availability === "available" && parsed.title !== void 0 ? ".wingman/plan.md H1" : "\u5DE5\u4F5C\u76EE\u5F55";
16445
16714
  let plan;
16446
16715
  if (parsed?.availability === "available") {
16447
16716
  plan = {
@@ -16680,8 +16949,8 @@ function extractRawToolObservations(harness, rawLine) {
16680
16949
  }
16681
16950
  function resolveObservedPath(path, cwd) {
16682
16951
  if (isAbsolute6(path))
16683
- return resolve9(path);
16684
- return cwd === void 0 ? void 0 : resolve9(cwd, path);
16952
+ return resolve11(path);
16953
+ return cwd === void 0 ? void 0 : resolve11(cwd, path);
16685
16954
  }
16686
16955
  function agentIdOf(payload) {
16687
16956
  const id = payload.agent_id ?? payload.agentId;
@@ -16745,9 +17014,9 @@ function derive(harness, session, nowIso) {
16745
17014
  const attributed = attributeSteps(steps, timeline, intervals);
16746
17015
  const results = collectResults(lines2);
16747
17016
  const resultBriefs = /* @__PURE__ */ new Map();
16748
- for (const [toolUseId, result4] of results) {
16749
- if (result4.brief !== void 0)
16750
- resultBriefs.set(toolUseId, result4.brief);
17017
+ for (const [toolUseId, result5] of results) {
17018
+ if (result5.brief !== void 0)
17019
+ resultBriefs.set(toolUseId, result5.brief);
16751
17020
  }
16752
17021
  const checks = deriveCheckStats(allSteps, resultBriefs);
16753
17022
  const todoChecks = deriveTodoCheckStats(attributed);
@@ -16856,11 +17125,16 @@ function derive(harness, session, nowIso) {
16856
17125
  const activeTodos = todos.filter((todo) => todo.status === "in_progress");
16857
17126
  const activeTodo = activeTodos.length === 1 ? activeTodos[0] : void 0;
16858
17127
  const activeChecks = activeTodo === void 0 ? void 0 : todoChecks.get(activeTodo.id);
16859
- const plan = workflowBase.plan;
17128
+ scopeSessionPlan(harness, session, lines2);
17129
+ const plan = workflowBase.plan.availability === "available" ? {
17130
+ ...workflowBase.plan,
17131
+ forInstruction: session.sessionPlanSeq === session.instructionSeq ? "current" : "previous"
17132
+ } : workflowBase.plan;
16860
17133
  const taskWorkflow = {
16861
17134
  ...workflowBase,
17135
+ plan,
16862
17136
  verification: {
16863
- agentMarkedComplete: plan.availability === "available" && plan.steps.length > 0 && plan.steps.every((step) => step.status === "completed"),
17137
+ agentMarkedComplete: plan.availability === "available" && plan.forInstruction === "current" && plan.steps.length > 0 && plan.steps.every((step) => step.status === "completed"),
16864
17138
  checks: { ...checks, source: CHECK_STATS_SOURCE },
16865
17139
  ...activeTodo === void 0 ? {} : {
16866
17140
  currentStep: {
@@ -16880,7 +17154,7 @@ function derive(harness, session, nowIso) {
16880
17154
  ...session.cwd === void 0 ? {} : { cwd: session.cwd },
16881
17155
  ...session.cwd === void 0 ? {} : {
16882
17156
  project: {
16883
- root: session.projectResolution?.root ?? resolve9(session.cwd),
17157
+ root: session.projectResolution?.root ?? resolve11(session.cwd),
16884
17158
  ...session.planAttachment === void 0 ? {} : { attachedTo: session.planAttachment.attachedTo }
16885
17159
  }
16886
17160
  },
@@ -16898,6 +17172,92 @@ function derive(harness, session, nowIso) {
16898
17172
  updatedAt: nowIso
16899
17173
  };
16900
17174
  }
17175
+ function scopeSessionPlan(harness, session, lines2) {
17176
+ const observations = [];
17177
+ const seenUsers = /* @__PURE__ */ new Set();
17178
+ const taskIds = /* @__PURE__ */ new Set();
17179
+ const resultLines = /* @__PURE__ */ new Map();
17180
+ for (const line of lines2) {
17181
+ if (line.kind === "user") {
17182
+ for (const result5 of line.toolResults)
17183
+ resultLines.set(result5.toolUseId, line);
17184
+ }
17185
+ }
17186
+ let at;
17187
+ for (const line of lines2) {
17188
+ if (line.kind === "unknown" || line.agentId !== void 0 || line.isSidechain === true) {
17189
+ continue;
17190
+ }
17191
+ at = line.timestamp ?? at;
17192
+ const timestamp = at === void 0 ? {} : { at };
17193
+ if (line.kind === "user" && line.toolResults.length === 0) {
17194
+ const text = line.text?.trim();
17195
+ if (text === void 0 || text === "" || isHarnessSystemNotice(text))
17196
+ continue;
17197
+ if (line.uuid !== void 0) {
17198
+ if (seenUsers.has(line.uuid))
17199
+ continue;
17200
+ seenUsers.add(line.uuid);
17201
+ }
17202
+ observations.push({ kind: "instruction", source: "transcript", text, ...timestamp });
17203
+ } else if (line.kind === "assistant") {
17204
+ for (const block of line.blocks) {
17205
+ if (block.kind !== "tool_use")
17206
+ continue;
17207
+ if (harness === "codex" && block.name === "update_plan") {
17208
+ observations.push({ kind: "plan", ...timestamp });
17209
+ } else if (harness === "cc") {
17210
+ if (block.name === "TaskCreate" || block.name === "TodoWrite") {
17211
+ const result5 = resultLines.get(block.id);
17212
+ const snapshot = extractTodoSnapshots([
17213
+ { ...line, blocks: [block] },
17214
+ ...result5 === void 0 ? [] : [result5]
17215
+ ]).at(-1);
17216
+ if (snapshot === void 0)
17217
+ continue;
17218
+ if (block.name === "TodoWrite")
17219
+ taskIds.clear();
17220
+ for (const todo of snapshot.todos)
17221
+ taskIds.add(todo.id);
17222
+ } else if (block.name === "TaskUpdate") {
17223
+ const taskId = block.input.taskId;
17224
+ if (typeof taskId !== "string" || !taskIds.has(taskId))
17225
+ continue;
17226
+ if (block.input.status === "deleted")
17227
+ taskIds.delete(taskId);
17228
+ } else {
17229
+ continue;
17230
+ }
17231
+ observations.push({ kind: "plan", ...timestamp });
17232
+ }
17233
+ }
17234
+ }
17235
+ }
17236
+ for (const hook of session.hookInstructions) {
17237
+ observations.push({ kind: "instruction", source: "hook", ...hook });
17238
+ }
17239
+ observations.sort((a, b) => (a.at ?? "").localeCompare(b.at ?? ""));
17240
+ session.instructionSeq = 0;
17241
+ session.sessionPlanSeq = 0;
17242
+ const instructions = /* @__PURE__ */ new Map();
17243
+ let unpaired;
17244
+ for (const observation of observations) {
17245
+ if (observation.kind === "plan") {
17246
+ session.sessionPlanSeq = session.instructionSeq;
17247
+ unpaired = void 0;
17248
+ } else if (unpaired !== void 0 && unpaired.source !== observation.source && (unpaired.text === void 0 || observation.text === void 0 || unpaired.text === observation.text)) {
17249
+ if (observation.text !== void 0)
17250
+ instructions.set(session.instructionSeq, observation.text);
17251
+ unpaired = void 0;
17252
+ } else {
17253
+ session.instructionSeq += 1;
17254
+ if (observation.text !== void 0)
17255
+ instructions.set(session.instructionSeq, observation.text);
17256
+ unpaired = observation;
17257
+ }
17258
+ }
17259
+ session.sessionPlanInstruction = instructions.get(session.sessionPlanSeq);
17260
+ }
16901
17261
  function todoInProgressAt(timeline, ts) {
16902
17262
  const active = timeline.filter((entry) => entry.spans.some((span) => span.status === "in_progress" && span.from !== void 0 && span.from <= ts && (span.to === void 0 || ts < span.to)));
16903
17263
  const only = active[0];
@@ -17053,18 +17413,18 @@ function collectResults(lines2) {
17053
17413
  for (const line of lines2) {
17054
17414
  if (line.kind !== "user")
17055
17415
  continue;
17056
- for (const result4 of line.toolResults) {
17057
- if (result4.content === void 0)
17416
+ for (const result5 of line.toolResults) {
17417
+ if (result5.content === void 0)
17058
17418
  continue;
17059
17419
  const info = {};
17060
17420
  try {
17061
- info.bytes = Buffer.byteLength(JSON.stringify(result4.content), "utf8");
17421
+ info.bytes = Buffer.byteLength(JSON.stringify(result5.content), "utf8");
17062
17422
  } catch {
17063
17423
  }
17064
- const brief = errorBrief(result4.content);
17424
+ const brief = errorBrief(result5.content);
17065
17425
  if (brief !== void 0)
17066
17426
  info.brief = brief;
17067
- results.set(result4.toolUseId, info);
17427
+ results.set(result5.toolUseId, info);
17068
17428
  }
17069
17429
  }
17070
17430
  return results;
@@ -17370,16 +17730,22 @@ function errorBrief(content) {
17370
17730
  init_dist3();
17371
17731
  init_dist5();
17372
17732
  init_dist2();
17733
+ import { homedir as homedir13 } from "node:os";
17373
17734
  import { createInterface } from "node:readline/promises";
17374
17735
  var ProtocolUsageError = class extends Error {
17375
17736
  };
17376
- async function runProtocolCli(args) {
17737
+ async function runProtocolCli(args, options = { homeDir: homedir13() }) {
17377
17738
  const parsed = parseProtocolArgs(args);
17739
+ if (parsed.user && parsed.harness === "dsh") {
17740
+ throw new ProtocolUsageError(protocolStatusDshUser(options).unsupported);
17741
+ }
17378
17742
  if (parsed.action === "status") {
17379
- printStatus(getStatus(parsed.harness, parsed.projectDir));
17743
+ const user = getUserStatus(parsed.harness, options.homeDir);
17744
+ printStatus(user, "\u7528\u6237\u7EA7");
17745
+ printStatus(getStatus(parsed.harness, parsed.projectDir, options.homeDir), "\u9879\u76EE\u7EA7");
17380
17746
  return 0;
17381
17747
  }
17382
- const preview = mutate(parsed.action, parsed.harness, parsed.projectDir, true);
17748
+ const preview = mutate(parsed, options.homeDir, true);
17383
17749
  printPreview(preview);
17384
17750
  if (!preview.changed)
17385
17751
  return 0;
@@ -17389,7 +17755,7 @@ async function runProtocolCli(args) {
17389
17755
  process.stdout.write("wingman:\u5DF2\u53D6\u6D88\uFF0C\u672A\u5199\u5165\u4EFB\u4F55\u6587\u4EF6\u3002\n");
17390
17756
  return 0;
17391
17757
  }
17392
- const applied = mutate(parsed.action, parsed.harness, parsed.projectDir, false);
17758
+ const applied = mutate(parsed, options.homeDir, false);
17393
17759
  process.stdout.write(`wingman:${parsed.harness} protocol ${parsed.action} \u5B8C\u6210
17394
17760
  state: ${applied.state}
17395
17761
  backupDir: ${applied.backupDir ?? "(no backup)"}
@@ -17401,12 +17767,15 @@ ${applied.message ?? ""}${applied.message === void 0 ? "" : "\n"}`);
17401
17767
  function parseProtocolArgs(args) {
17402
17768
  const [actionText, harnessText, ...tail] = args;
17403
17769
  if (actionText !== "install" && actionText !== "uninstall" && actionText !== "status") {
17404
- throw new ProtocolUsageError("protocol \u7528\u6CD5:wingman protocol install|uninstall|status <cc|codex|dsh> [--project <dir>] [--dry-run] [--yes]");
17770
+ throw new ProtocolUsageError("protocol \u7528\u6CD5:wingman protocol install|uninstall|status <cc|codex|dsh> [--project <dir> | --user] [--dry-run] [--yes]");
17405
17771
  }
17406
17772
  if (harnessText !== "cc" && harnessText !== "codex" && harnessText !== "dsh") {
17407
17773
  throw new ProtocolUsageError(`protocol \u9700\u8981 harness \u2208 cc|codex|dsh,\u5F97\u5230 ${harnessText ?? "(\u7F3A\u53C2)"}`);
17408
17774
  }
17409
17775
  let projectDir = process.cwd();
17776
+ let user = false;
17777
+ let project = false;
17778
+ let fixtures = false;
17410
17779
  let dryRun = false;
17411
17780
  let yes = false;
17412
17781
  const rest = [...tail];
@@ -17414,9 +17783,14 @@ function parseProtocolArgs(args) {
17414
17783
  const arg = rest.shift();
17415
17784
  if (arg === "--project") {
17416
17785
  const value = rest.shift();
17417
- if (value === void 0)
17786
+ if (value === void 0 || value.startsWith("--"))
17418
17787
  throw new ProtocolUsageError("--project \u9700\u8981\u76EE\u5F55\u8DEF\u5F84,\u5F97\u5230(\u7F3A\u53C2)");
17788
+ project = true;
17419
17789
  projectDir = value;
17790
+ } else if (arg === "--user") {
17791
+ user = true;
17792
+ } else if (arg === "--fixtures") {
17793
+ fixtures = true;
17420
17794
  } else if (arg === "--dry-run") {
17421
17795
  dryRun = true;
17422
17796
  } else if (arg === "--yes") {
@@ -17425,36 +17799,57 @@ function parseProtocolArgs(args) {
17425
17799
  throw new ProtocolUsageError(`protocol \u4E0D\u8BA4\u8BC6\u53C2\u6570:${arg}`);
17426
17800
  }
17427
17801
  }
17428
- return { action: actionText, harness: harnessText, projectDir, dryRun, yes };
17802
+ if (user && project)
17803
+ throw new ProtocolUsageError("--user \u4E0E --project \u4E92\u65A5");
17804
+ if (fixtures && user)
17805
+ throw new ProtocolUsageError("fixtures \u6A21\u5F0F\u62D2\u7EDD --user\uFF0C\u4E0D\u80FD\u8BBF\u95EE\u7528\u6237\u7EA7\u6307\u4EE4\u6587\u4EF6");
17806
+ if (fixtures)
17807
+ throw new ProtocolUsageError("protocol \u4E0D\u652F\u6301 --fixtures");
17808
+ return { action: actionText, harness: harnessText, projectDir, user, dryRun, yes };
17429
17809
  }
17430
- function getStatus(harness, projectDir) {
17810
+ function getStatus(harness, projectDir, homeDir) {
17431
17811
  switch (harness) {
17432
17812
  case "cc":
17433
- return protocolStatusCc({ projectDir });
17813
+ return protocolStatusCc({ projectDir, homeDir });
17434
17814
  case "codex":
17435
- return protocolStatusCodex({ projectDir });
17815
+ return protocolStatusCodex({ projectDir, homeDir });
17436
17816
  case "dsh":
17437
- return protocolStatusDsh({ projectDir });
17817
+ return protocolStatusDsh({ projectDir, homeDir });
17438
17818
  }
17439
17819
  }
17440
- function mutate(action, harness, projectDir, dryRun) {
17820
+ function getUserStatus(harness, homeDir) {
17441
17821
  switch (harness) {
17442
17822
  case "cc":
17443
- return action === "install" ? installProtocolCc({ projectDir, dryRun }) : uninstallProtocolCc({ projectDir, dryRun });
17823
+ return protocolStatusCcUser({ homeDir });
17444
17824
  case "codex":
17445
- return action === "install" ? installProtocolCodex({ projectDir, dryRun }) : uninstallProtocolCodex({ projectDir, dryRun });
17825
+ return protocolStatusCodexUser({ homeDir });
17446
17826
  case "dsh":
17447
- return action === "install" ? installProtocolDsh({ projectDir, dryRun }) : uninstallProtocolDsh({ projectDir, dryRun });
17827
+ return protocolStatusDshUser({ homeDir });
17448
17828
  }
17449
17829
  }
17450
- function printStatus(value) {
17451
- process.stdout.write(`harness: ${value.harness}
17452
- target: ${value.targetPath}
17453
- state: ${value.state}
17454
- ${value.version === void 0 ? "" : `version: ${value.version}
17455
- `}${value.message === void 0 ? "" : `${value.message}
17456
- `}${value.reason === void 0 ? "" : `reason: ${value.reason}
17457
- `}`);
17830
+ function mutate(parsed, homeDir, dryRun) {
17831
+ const { action, harness, projectDir, user } = parsed;
17832
+ switch (harness) {
17833
+ case "cc":
17834
+ return action === "install" ? (user ? installProtocolCcUser : installProtocolCc)({ projectDir, homeDir, dryRun }) : (user ? uninstallProtocolCcUser : uninstallProtocolCc)({ projectDir, homeDir, dryRun });
17835
+ case "codex":
17836
+ return action === "install" ? (user ? installProtocolCodexUser : installProtocolCodex)({ projectDir, homeDir, dryRun }) : (user ? uninstallProtocolCodexUser : uninstallProtocolCodex)({
17837
+ projectDir,
17838
+ homeDir,
17839
+ dryRun
17840
+ });
17841
+ case "dsh":
17842
+ return action === "install" ? installProtocolDsh({ projectDir, homeDir, dryRun }) : uninstallProtocolDsh({ projectDir, homeDir, dryRun });
17843
+ }
17844
+ }
17845
+ function printStatus(value, scope) {
17846
+ if ("unsupported" in value) {
17847
+ process.stdout.write(`${scope}: unsupported \u2014 ${value.unsupported}
17848
+ `);
17849
+ return;
17850
+ }
17851
+ process.stdout.write(`${scope}: ${value.state} | target: ${value.targetPath} | state: ${value.state}${value.version === void 0 ? "" : ` | version: ${value.version}`}${value.message === void 0 ? "" : ` | ${value.message}`}${value.reason === void 0 ? "" : ` | reason: ${value.reason}`}
17852
+ `);
17458
17853
  }
17459
17854
  function printPreview(value) {
17460
17855
  process.stdout.write(`${unifiedDiff(value.targetPath, value.before, value.after)}
@@ -17504,8 +17899,8 @@ async function confirmWrite() {
17504
17899
  }
17505
17900
 
17506
17901
  // apps/cli/dist/registry.js
17507
- import { existsSync as existsSync13 } from "node:fs";
17508
- import { homedir as homedir11 } from "node:os";
17902
+ import { existsSync as existsSync14 } from "node:fs";
17903
+ import { homedir as homedir14 } from "node:os";
17509
17904
  async function importHarnessModule(harness) {
17510
17905
  const mod = await importAdapterModule(harness);
17511
17906
  if (typeof mod.createAdapter !== "function") {
@@ -17527,7 +17922,7 @@ function importAdapterModule(harness) {
17527
17922
  }
17528
17923
  }
17529
17924
  function fixtureScanOptions(harness) {
17530
- if (!existsSync13(fixturePath())) {
17925
+ if (!existsSync14(fixturePath())) {
17531
17926
  throw new Error("--fixtures \u9700\u8981\u4ED3\u5E93\u5185\u7684 packages/fixtures \u6570\u636E;\u53D1\u5E03\u5B89\u88C5\u5305/npx \u4EA7\u7269\u4E0D\u5305\u542B\u6837\u4F8B");
17532
17927
  }
17533
17928
  switch (harness) {
@@ -17548,16 +17943,16 @@ async function loadHarness(harness, mode) {
17548
17943
  return {
17549
17944
  harness,
17550
17945
  adapter,
17551
- scanOptions: mode.fixtures ? fixtureScanOptions(harness) : { homeDir: homedir11() },
17946
+ scanOptions: mode.fixtures ? fixtureScanOptions(harness) : { homeDir: homedir14() },
17552
17947
  feedbackSignals
17553
17948
  };
17554
17949
  }
17555
17950
 
17556
17951
  // apps/cli/dist/runtime-state.js
17557
17952
  import { randomBytes as randomBytes4 } from "node:crypto";
17558
- import { closeSync as closeSync3, mkdirSync as mkdirSync11, openSync as openSync3, readFileSync as readFileSync16, renameSync as renameSync5, rmSync as rmSync9, writeFileSync as writeFileSync12 } from "node:fs";
17559
- import { homedir as homedir12 } from "node:os";
17560
- import { dirname as dirname17, join as join23 } from "node:path";
17953
+ import { closeSync as closeSync3, mkdirSync as mkdirSync12, openSync as openSync3, readFileSync as readFileSync17, renameSync as renameSync5, rmSync as rmSync10, writeFileSync as writeFileSync13 } from "node:fs";
17954
+ import { homedir as homedir15 } from "node:os";
17955
+ import { dirname as dirname18, join as join26 } from "node:path";
17561
17956
  function createHookToken() {
17562
17957
  return randomBytes4(32).toString("base64url");
17563
17958
  }
@@ -17568,15 +17963,15 @@ function writeServeRuntimeState(port, token, options = {}) {
17568
17963
  const pid = options.pid ?? process.pid;
17569
17964
  const suffix = randomBytes4(8).toString("base64url");
17570
17965
  const owner = `serve-${startedAtMs}-${pid}-${suffix}`;
17571
- const path = join23(options.homeDir ?? homedir12(), ".wingman", "state", "serve", `${owner}.json`);
17572
- const tempPath = join23(dirname17(path), `.${owner}.tmp`);
17966
+ const path = join26(options.homeDir ?? homedir15(), ".wingman", "state", "serve", `${owner}.json`);
17967
+ const tempPath = join26(dirname18(path), `.${owner}.tmp`);
17573
17968
  const contents = Buffer.from(`${JSON.stringify({ version: 2, owner, pid, port, startedAtMs, token })}
17574
17969
  `, "utf8");
17575
17970
  let fd;
17576
17971
  try {
17577
- mkdirSync11(dirname17(path), { recursive: true, mode: 448 });
17972
+ mkdirSync12(dirname18(path), { recursive: true, mode: 448 });
17578
17973
  fd = openSync3(tempPath, "wx", 384);
17579
- writeFileSync12(fd, contents);
17974
+ writeFileSync13(fd, contents);
17580
17975
  closeSync3(fd);
17581
17976
  fd = void 0;
17582
17977
  renameSync5(tempPath, path);
@@ -17589,7 +17984,7 @@ function writeServeRuntimeState(port, token, options = {}) {
17589
17984
  }
17590
17985
  }
17591
17986
  try {
17592
- rmSync9(tempPath, { force: true });
17987
+ rmSync10(tempPath, { force: true });
17593
17988
  } catch {
17594
17989
  }
17595
17990
  warn(`Codex hook \u8FD0\u884C\u6001\u5199\u5165\u5931\u8D25,\u9762\u677F\u7EE7\u7EED\u8FD0\u884C:${errorMessage2(error)}`);
@@ -17600,9 +17995,9 @@ function removeServeRuntimeState(registration) {
17600
17995
  if (registration === void 0)
17601
17996
  return;
17602
17997
  try {
17603
- const current = readFileSync16(registration.path);
17998
+ const current = readFileSync17(registration.path);
17604
17999
  if (current.equals(registration.contents))
17605
- rmSync9(registration.path, { force: true });
18000
+ rmSync10(registration.path, { force: true });
17606
18001
  } catch {
17607
18002
  }
17608
18003
  }
@@ -17623,17 +18018,19 @@ async function scanValidated(adapter, options) {
17623
18018
  }
17624
18019
 
17625
18020
  // apps/cli/dist/server.js
18021
+ init_dist3();
18022
+ init_dist5();
17626
18023
  init_dist();
17627
18024
  import { execFile as execFile2 } from "node:child_process";
17628
18025
  import { createHmac, timingSafeEqual } from "node:crypto";
17629
18026
  import { readFile as readFile4 } from "node:fs/promises";
17630
18027
  import { createServer } from "node:http";
17631
- import { extname, resolve as resolve11, sep as sep2 } from "node:path";
18028
+ import { extname, resolve as resolve13, sep as sep2 } from "node:path";
17632
18029
 
17633
18030
  // apps/cli/dist/return-target.js
17634
18031
  import { randomBytes as randomBytes5 } from "node:crypto";
17635
- import { closeSync as closeSync4, copyFileSync as copyFileSync2, mkdirSync as mkdirSync12, openSync as openSync4, readFileSync as readFileSync17, renameSync as renameSync6, rmSync as rmSync10, statSync as statSync6, writeFileSync as writeFileSync13 } from "node:fs";
17636
- import { dirname as dirname18, join as join24, resolve as resolve10 } from "node:path";
18032
+ import { closeSync as closeSync4, copyFileSync as copyFileSync2, mkdirSync as mkdirSync13, openSync as openSync4, readFileSync as readFileSync18, renameSync as renameSync6, rmSync as rmSync11, statSync as statSync6, writeFileSync as writeFileSync14 } from "node:fs";
18033
+ import { dirname as dirname19, join as join27, resolve as resolve12 } from "node:path";
17637
18034
  var BUNDLES = [
17638
18035
  ["Terminal", "Terminal.app"],
17639
18036
  ["iTerm", "iTerm.app"],
@@ -17644,11 +18041,11 @@ var BUNDLES = [
17644
18041
  ["kitty", "kitty.app"],
17645
18042
  ["VS Code", "Visual Studio Code.app"]
17646
18043
  ];
17647
- function detectReturnTargets(homeDir, roots = ["/Applications", join24(homeDir, "Applications")]) {
18044
+ function detectReturnTargets(homeDir, roots = ["/Applications", join27(homeDir, "Applications")]) {
17648
18045
  const available = [];
17649
18046
  for (const [name, bundle] of BUNDLES) {
17650
- for (const root of new Set(roots.map((root2) => resolve10(root2)))) {
17651
- const bundlePath = join24(root, bundle);
18047
+ for (const root of new Set(roots.map((root2) => resolve12(root2)))) {
18048
+ const bundlePath = join27(root, bundle);
17652
18049
  try {
17653
18050
  if (statSync6(bundlePath).isDirectory())
17654
18051
  available.push({ name, bundlePath });
@@ -17659,12 +18056,12 @@ function detectReturnTargets(homeDir, roots = ["/Applications", join24(homeDir,
17659
18056
  return available;
17660
18057
  }
17661
18058
  function settingsPath(homeDir) {
17662
- return join24(homeDir, ".wingman", "state", "settings.json");
18059
+ return join27(homeDir, ".wingman", "state", "settings.json");
17663
18060
  }
17664
18061
  function readReturnTargetSettings(homeDir) {
17665
18062
  let raw;
17666
18063
  try {
17667
- raw = readFileSync17(settingsPath(homeDir), "utf8");
18064
+ raw = readFileSync18(settingsPath(homeDir), "utf8");
17668
18065
  } catch (error) {
17669
18066
  if (isRecord8(error) && error.code === "ENOENT")
17670
18067
  return { version: 1 };
@@ -17685,10 +18082,10 @@ function saveReturnTarget(homeDir, bundlePath) {
17685
18082
  return current;
17686
18083
  const settings = { version: 1, returnTarget: { bundlePath } };
17687
18084
  const path = settingsPath(homeDir);
17688
- const tempPath = join24(dirname18(path), `.settings-${randomBytes5(8).toString("hex")}.tmp`);
18085
+ const tempPath = join27(dirname19(path), `.settings-${randomBytes5(8).toString("hex")}.tmp`);
17689
18086
  let fd;
17690
18087
  try {
17691
- mkdirSync12(dirname18(path), { recursive: true, mode: 448 });
18088
+ mkdirSync13(dirname19(path), { recursive: true, mode: 448 });
17692
18089
  try {
17693
18090
  copyFileSync2(path, `${path}.bak`);
17694
18091
  } catch (error) {
@@ -17696,7 +18093,7 @@ function saveReturnTarget(homeDir, bundlePath) {
17696
18093
  throw error;
17697
18094
  }
17698
18095
  fd = openSync4(tempPath, "wx", 384);
17699
- writeFileSync13(fd, `${JSON.stringify(settings)}
18096
+ writeFileSync14(fd, `${JSON.stringify(settings)}
17700
18097
  `, "utf8");
17701
18098
  closeSync4(fd);
17702
18099
  fd = void 0;
@@ -17712,7 +18109,7 @@ function saveReturnTarget(homeDir, bundlePath) {
17712
18109
  }
17713
18110
  }
17714
18111
  try {
17715
- rmSync10(tempPath, { force: true });
18112
+ rmSync11(tempPath, { force: true });
17716
18113
  } catch {
17717
18114
  }
17718
18115
  }
@@ -18037,8 +18434,15 @@ async function handle(req, res, options, warn, runtime) {
18037
18434
  }
18038
18435
  if (url.pathname === "/api/anatomy") {
18039
18436
  const configs = await scanAll(options.harnesses, warn);
18437
+ const anatomy = configs.map((config) => {
18438
+ const homeDir = options.harnesses.find((entry) => entry.harness === config.harness)?.scanOptions.homeDir ?? options.homeDir;
18439
+ if (homeDir === void 0)
18440
+ throw new Error("anatomy \u9700\u8981\u663E\u5F0F homeDir");
18441
+ const user = config.harness === "cc" ? protocolStatusCcUser({ homeDir }).state : config.harness === "codex" ? protocolStatusCodexUser({ homeDir }).state : "unsupported";
18442
+ return { ...config, planProtocol: { user } };
18443
+ });
18040
18444
  res.writeHead(200, { "content-type": "application/json; charset=utf-8" });
18041
- res.end(JSON.stringify(configs));
18445
+ res.end(JSON.stringify(anatomy));
18042
18446
  return;
18043
18447
  }
18044
18448
  if (url.pathname === "/api/version") {
@@ -18199,11 +18603,11 @@ async function handleActionApply(req, res, options, runtime) {
18199
18603
  return;
18200
18604
  }
18201
18605
  try {
18202
- const result4 = await loaded.adapter.applyAction(plan, loaded.scanOptions);
18203
- if (result4.ok) {
18606
+ const result5 = await loaded.adapter.applyAction(plan, loaded.scanOptions);
18607
+ if (result5.ok) {
18204
18608
  runtime.anatomy = null;
18205
18609
  }
18206
- sendJson2(res, 200, result4);
18610
+ sendJson2(res, 200, result5);
18207
18611
  } catch (error) {
18208
18612
  sendJson2(res, 400, { error: errorMessage3(error) });
18209
18613
  }
@@ -18283,12 +18687,12 @@ async function handleTaskOverlay(req, res, options) {
18283
18687
  return;
18284
18688
  }
18285
18689
  const key = `${body.harness}:${body.sessionId}`;
18286
- const result4 = patchTaskOverlay(options.homeDir, key, body.patch, /* @__PURE__ */ new Date());
18287
- if ("unavailable" in result4) {
18288
- sendJson2(res, 409, { error: result4.unavailable });
18690
+ const result5 = patchTaskOverlay(options.homeDir, key, body.patch, /* @__PURE__ */ new Date());
18691
+ if ("unavailable" in result5) {
18692
+ sendJson2(res, 409, { error: result5.unavailable });
18289
18693
  return;
18290
18694
  }
18291
- sendJson2(res, 200, { key, entry: result4.entry });
18695
+ sendJson2(res, 200, { key, entry: result5.entry });
18292
18696
  }
18293
18697
  var LICENSE_BODY_LIMIT = 64 * 1024;
18294
18698
  async function handleLicenseInstall(req, res, options) {
@@ -18297,12 +18701,12 @@ async function handleLicenseInstall(req, res, options) {
18297
18701
  sendJson2(res, 400, { error: "license \u6587\u4EF6\u8D85\u8FC7 64KB \u4E0A\u9650\u6216\u8BFB\u53D6\u5931\u8D25" });
18298
18702
  return;
18299
18703
  }
18300
- const result4 = installLicense(raw, options.licenseOptions);
18301
- if (!result4.ok) {
18302
- sendJson2(res, 400, { error: result4.error });
18704
+ const result5 = installLicense(raw, options.licenseOptions);
18705
+ if (!result5.ok) {
18706
+ sendJson2(res, 400, { error: result5.error });
18303
18707
  return;
18304
18708
  }
18305
- sendJson2(res, 200, publicLicenseStatus(result4.status));
18709
+ sendJson2(res, 200, publicLicenseStatus(result5.status));
18306
18710
  }
18307
18711
  async function handleLicenseRefresh(res, options) {
18308
18712
  const homeDir = options.licenseRefreshOptions?.homeDir ?? options.licenseOptions?.homeDir;
@@ -18314,11 +18718,11 @@ async function handleLicenseRefresh(res, options) {
18314
18718
  ...publicKeyPem === void 0 ? {} : { publicKeyPem },
18315
18719
  ...now === void 0 ? {} : { now }
18316
18720
  };
18317
- const result4 = await refreshLicense(refreshOptions);
18318
- if (!result4.ok) {
18721
+ const result5 = await refreshLicense(refreshOptions);
18722
+ if (!result5.ok) {
18319
18723
  sendJson2(res, 400, {
18320
- error: result4.message,
18321
- canSubscribe: result4.reason === "inactive"
18724
+ error: result5.message,
18725
+ canSubscribe: result5.reason === "inactive"
18322
18726
  });
18323
18727
  return;
18324
18728
  }
@@ -18330,7 +18734,7 @@ async function handleLicenseRefresh(res, options) {
18330
18734
  };
18331
18735
  sendJson2(res, 200, {
18332
18736
  ...publicLicenseStatus(licenseStatus(statusOptions)),
18333
- message: result4.message
18737
+ message: result5.message
18334
18738
  });
18335
18739
  }
18336
18740
  function publicLicenseStatus(status3) {
@@ -18425,8 +18829,8 @@ async function serveStatic(pathname, res, panelDistDir) {
18425
18829
  return;
18426
18830
  }
18427
18831
  const rel = decoded === "/" ? "/index.html" : decoded;
18428
- const distDir = resolve11(panelDistDir);
18429
- const filePath = resolve11(distDir, `.${rel}`);
18832
+ const distDir = resolve13(panelDistDir);
18833
+ const filePath = resolve13(distDir, `.${rel}`);
18430
18834
  if (filePath !== distDir && !filePath.startsWith(distDir + sep2)) {
18431
18835
  sendText2(res, 403, "forbidden");
18432
18836
  return;
@@ -18463,8 +18867,8 @@ var HELP = `wingman \u2014 Not your copilot. Your wingman.
18463
18867
  wingman hook install <harness> [--port 7333] \u5B9E\u51B5\u63A5\u7EBF(\u5199\u524D\u5907\u4EFD,\u5E42\u7B49)
18464
18868
  [--profile <p>] dsh:\u53EA\u5904\u7406\u6307\u5B9A profile
18465
18869
  wingman hook uninstall <harness> [--profile <p>] \u89E3\u7EBF(\u914D\u7F6E\u6062\u590D,\u5E42\u7B49)
18466
- wingman protocol install|uninstall|status <harness> \u6309\u9879\u76EE\u7BA1\u7406 Plan Protocol
18467
- [--project <dir>] [--dry-run] [--yes]
18870
+ wingman protocol install|uninstall|status <harness> \u7BA1\u7406\u7528\u6237\u7EA7 / \u9879\u76EE\u7EA7 Plan Protocol
18871
+ [--project <dir> | --user] [--dry-run] [--yes]
18468
18872
  wingman license status \u67E5\u770B\u8BA2\u9605\u72B6\u6001(\u5199\u52A8\u4F5C\u7684\u95F8)
18469
18873
  wingman license refresh \u8054\u7F51\u5411\u7B7E\u53D1\u7AEF\u6362\u65B0 license(\u7EED\u671F)
18470
18874
  wingman --version | -v | version \u663E\u793A\u7248\u672C
@@ -18493,7 +18897,7 @@ async function main(argv) {
18493
18897
  case "hook":
18494
18898
  return runHook(rest);
18495
18899
  case "protocol":
18496
- return runProtocolCli(rest);
18900
+ return runProtocolCli(rest, { homeDir: homedir16() });
18497
18901
  case "license": {
18498
18902
  if (rest[0] === "status") {
18499
18903
  const status3 = licenseStatus();
@@ -18502,10 +18906,10 @@ async function main(argv) {
18502
18906
  return 0;
18503
18907
  }
18504
18908
  if (rest[0] === "refresh") {
18505
- const result4 = await refreshLicense();
18506
- process.stdout.write(`${result4.message}
18909
+ const result5 = await refreshLicense();
18910
+ process.stdout.write(`${result5.message}
18507
18911
  `);
18508
- if (!result4.ok)
18912
+ if (!result5.ok)
18509
18913
  return 1;
18510
18914
  const status3 = licenseStatus();
18511
18915
  process.stdout.write(`${status3.state}:${status3.detail}
@@ -18544,7 +18948,7 @@ ${counts}
18544
18948
  }
18545
18949
  async function runServe(args) {
18546
18950
  const { port, fixtures, panelDist } = parseServeArgs(args);
18547
- const homeDir = fixtures ? fixturesRoot : homedir13();
18951
+ const homeDir = fixtures ? fixturesRoot : homedir16();
18548
18952
  const hookToken = createHookToken();
18549
18953
  let dshRetirementNotice;
18550
18954
  if (!fixtures) {
@@ -18579,7 +18983,7 @@ async function runServe(args) {
18579
18983
  `);
18580
18984
  }
18581
18985
  }
18582
- const panelDistDir = panelDist === void 0 ? resolve12(dirname19(fileURLToPath2(import.meta.url)), "../../panel/dist") : resolve12(panelDist);
18986
+ const panelDistDir = panelDist === void 0 ? resolve14(dirname20(fileURLToPath2(import.meta.url)), "../../panel/dist") : resolve14(panelDist);
18583
18987
  const narrative = createNarrativeService({
18584
18988
  followTranscripts: !fixtures,
18585
18989
  homeDir,
@@ -18592,7 +18996,7 @@ async function runServe(args) {
18592
18996
  });
18593
18997
  if (fixtures) {
18594
18998
  try {
18595
- const raw = readFileSync18(fixturePath("cc", "sessions", "session-todos.jsonl"), "utf8");
18999
+ const raw = readFileSync19(fixturePath("cc", "sessions", "session-todos.jsonl"), "utf8");
18596
19000
  narrative.seedFixture("cc", raw.split("\n"), "MOCK \u2014 fixtures \u6F14\u793A:\u53D9\u4E8B\u6570\u636E\u6765\u81EA packages/fixtures \u7684 session-todos.jsonl \u6837\u4F8B\u4F1A\u8BDD,\u975E\u672C\u673A\u771F\u5B9E transcript\u3002");
18597
19001
  } catch (error) {
18598
19002
  const message = error instanceof Error ? error.message : String(error);
@@ -18666,8 +19070,8 @@ async function runHook(args) {
18666
19070
  const { adapter, scanOptions } = await loadHarness(harness, { fixtures: false });
18667
19071
  if (action === "install") {
18668
19072
  if (harness === "dsh") {
18669
- const result4 = await installDshHooks(port, scanOptions);
18670
- writeDshInstallReport(await dshHookInstallReport(scanOptions), result4);
19073
+ const result5 = await installDshHooks(port, scanOptions);
19074
+ writeDshInstallReport(await dshHookInstallReport(scanOptions), result5);
18671
19075
  process.stdout.write(`wingman:dsh profile \u63A5\u7EBF\u5904\u7406\u5B8C\u6210(POST http://127.0.0.1:${port}/hook?harness=dsh)\u3002
18672
19076
  \u5199\u524D\u5DF2\u5907\u4EFD;\u91CD\u590D\u6267\u884C\u5E42\u7B49;\u89E3\u7EBF:wingman hook uninstall dsh
18673
19077
  `);
@@ -18681,14 +19085,14 @@ async function runHook(args) {
18681
19085
  `);
18682
19086
  }
18683
19087
  } else if (harness === "dsh") {
18684
- const result4 = await uninstallDshHooks(scanOptions);
19088
+ const result5 = await uninstallDshHooks(scanOptions);
18685
19089
  const messages = {
18686
19090
  unwired: "\u5DF2\u89E3\u7EBF",
18687
19091
  state: "\u5DF2\u6062\u590D",
18688
19092
  removed: "\u5DF2\u79FB\u9664\u6B8B\u7559\u5757",
18689
19093
  cleared: "\u5DF2\u6E05\u7406\u8BB0\u5F55"
18690
19094
  };
18691
- for (const profile2 of result4.profiles) {
19095
+ for (const profile2 of result5.profiles) {
18692
19096
  process.stdout.write(`${profile2.profile}:${messages[profile2.restored]}
18693
19097
  `);
18694
19098
  }
@@ -18709,16 +19113,16 @@ function writeDshInstallReport(report, installResult) {
18709
19113
  process.stdout.write("\u672A\u53D1\u73B0\u542B package.json \u7684 dsh profile\u3002\n");
18710
19114
  return;
18711
19115
  }
18712
- for (const result4 of report.profiles) {
18713
- if (result4.wired) {
18714
- process.stdout.write(`${result4.profile}:\u5DF2\u63A5\u7EBF
19116
+ for (const result5 of report.profiles) {
19117
+ if (result5.wired) {
19118
+ process.stdout.write(`${result5.profile}:\u5DF2\u63A5\u7EBF
18715
19119
  `);
18716
- } else if (result4.missingPackages.length > 0) {
18717
- const removed = installResult.removedProfiles.includes(result4.profile) ? "\u5DF2\u79FB\u9664\u65E7\u63A5\u7EBF\u5757," : "";
18718
- process.stdout.write(`${result4.profile}:\u672A\u63A5\u7EBF,${removed}\u7F3A ${result4.missingPackages.join("\u3001")} \u2192 ${result4.installCommand ?? ""}
19120
+ } else if (result5.missingPackages.length > 0) {
19121
+ const removed = installResult.removedProfiles.includes(result5.profile) ? "\u5DF2\u79FB\u9664\u65E7\u63A5\u7EBF\u5757," : "";
19122
+ process.stdout.write(`${result5.profile}:\u672A\u63A5\u7EBF,${removed}\u7F3A ${result5.missingPackages.join("\u3001")} \u2192 ${result5.installCommand ?? ""}
18719
19123
  `);
18720
19124
  } else {
18721
- process.stdout.write(`${result4.profile}:\u672A\u63A5\u7EBF
19125
+ process.stdout.write(`${result5.profile}:\u672A\u63A5\u7EBF
18722
19126
  `);
18723
19127
  }
18724
19128
  }
@@ -18798,7 +19202,7 @@ main(process.argv.slice(2)).then((code) => {
18798
19202
  process.stderr.write(`
18799
19203
  ${HELP}`);
18800
19204
  }
18801
- process.exitCode = 1;
19205
+ process.exitCode = error instanceof ProtocolUsageError ? 2 : 1;
18802
19206
  });
18803
19207
  /*! Bundled license information:
18804
19208