harness-wingman 0.8.1 → 0.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8273,7 +8273,7 @@ function inspectPlanProtocolBlock(block, scope = "project") {
8273
8273
  const knownBlock = version === void 0 || knownText === void 0 ? void 0 : buildPlanProtocolBlock(version, knownText, scope);
8274
8274
  const known = split.before === "" && split.after === "" && normalized === knownBlock;
8275
8275
  return {
8276
- kind: known && version === currentVersion ? "current" : known ? "legacy" : "modified",
8276
+ kind: known && version === currentVersion ? "current" : known ? "outdated" : "modified",
8277
8277
  ...version !== void 0 ? { version } : {},
8278
8278
  sha256: sha256Hex(normalized)
8279
8279
  };
@@ -8284,7 +8284,7 @@ function inspectPlanProtocolFile(bytes, sourcePath = "<memory>") {
8284
8284
  for (const [version, text] of KNOWN_PROTOCOL_TEXT) {
8285
8285
  if (sha256 === sha256Hex(text)) {
8286
8286
  return {
8287
- kind: version === PLAN_PROTOCOL_VERSION ? "current" : "legacy",
8287
+ kind: version === PLAN_PROTOCOL_VERSION ? "current" : "outdated",
8288
8288
  version,
8289
8289
  sha256
8290
8290
  };
@@ -8314,13 +8314,22 @@ function mergePlanProtocolBlock(text, block, sourcePath = "<memory>", scope = "p
8314
8314
  before += lineEnding;
8315
8315
  return before + normalizedBlock;
8316
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;
8317
+ var PLAN_PROTOCOL_VERSION, PLAN_PROTOCOL_USER_VERSION, PLAN_PROTOCOL_TEXT, PLAN_PROTOCOL_TEXT_USER, PLAN_PROTOCOL_TEXT_V1, PLAN_PROTOCOL_TEXT_USER_V1, 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;
8318
8318
  var init_plan_protocol = __esm({
8319
8319
  "packages/core/dist/plan-protocol.js"() {
8320
8320
  "use strict";
8321
- PLAN_PROTOCOL_VERSION = 1;
8322
- PLAN_PROTOCOL_USER_VERSION = 1;
8323
- PLAN_PROTOCOL_TEXT = `Wingman plan protocol v1 \u2014 a behavioral convention, not a gate. Wingman only reads; it never replies to you.
8321
+ PLAN_PROTOCOL_VERSION = 2;
8322
+ PLAN_PROTOCOL_USER_VERSION = 2;
8323
+ PLAN_PROTOCOL_TEXT = `Wingman plan protocol v2 \u2014 a behavioral convention, not a gate. Wingman only reads; it never replies to you.
8324
+ - The project root is the directory that contains this instruction file (for Claude Code: the parent of \`.claude/\`).
8325
+ - Before starting work, read \`<project root>/.wingman/plan.md\`. If it does not exist, create it: a \`# Title\` line, immediately followed by \`\u76EE\u6807: <one sentence, what done looks like>\` (or \`Goal:\`), then a nested checkbox tree of steps; add an indented \`Verify:\` line to the steps whose completion a person would want to check; not every step needs one.
8326
+ - As soon as the scope is clear (after any clarifying questions), create the plan file before doing the first step. Mark a step \`[/]\` right before you start it and \`[x]\` right after it is done; do not write the whole plan as finished afterwards. Add sub-steps under your current step as you learn more. Mark abandoned steps \`[-]\` and steps that need the user's decision \`[?]\`.
8327
+ - Re-read the file before every write; change only your own lines; never reorder or rewrite other entries. Use your file-editing tool, not shell redirection.
8328
+ - Keep your in-session todo list as sub-steps of the \`[/]\` step; do not copy the whole file into it.
8329
+ - Never put secrets, credentials, or personal data in the plan.
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_TEXT_V1 = `Wingman plan protocol v1 \u2014 a behavioral convention, not a gate. Wingman only reads; it never replies to you.
8324
8333
  - The project root is the directory that contains this instruction file (for Claude Code: the parent of \`.claude/\`).
8325
8334
  - 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.
8326
8335
  - Mark the step you are working on \`[/]\` and add sub-steps under it as you learn more. Mark finished steps \`[x]\`, abandoned steps \`[-]\`, and steps that need the user's decision \`[?]\`.
@@ -8328,15 +8337,19 @@ var init_plan_protocol = __esm({
8328
8337
  - Keep your in-session todo list as sub-steps of the \`[/]\` step; do not copy the whole file into it.
8329
8338
  - Never put secrets, credentials, or personal data in the plan.
8330
8339
  `;
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.");
8340
+ PLAN_PROTOCOL_TEXT_USER_V1 = PLAN_PROTOCOL_TEXT_V1.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
8341
  PLAN_PROTOCOL_USER_BLOCK_END = "<!-- <<< wingman plan protocol user <<< -->";
8333
8342
  PLAN_PROTOCOL_BLOCK_END = "<!-- <<< wingman plan protocol <<< -->";
8334
8343
  LEGACY_PLAN_PROTOCOL_TEXT = "Wingman plan protocol v0 \u2014 legacy fixture text.\n";
8335
8344
  KNOWN_PROTOCOL_TEXT = /* @__PURE__ */ new Map([
8336
8345
  [0, LEGACY_PLAN_PROTOCOL_TEXT],
8346
+ [1, PLAN_PROTOCOL_TEXT_V1],
8337
8347
  [PLAN_PROTOCOL_VERSION, PLAN_PROTOCOL_TEXT]
8338
8348
  ]);
8339
- KNOWN_USER_PROTOCOL_TEXT = /* @__PURE__ */ new Map([[PLAN_PROTOCOL_USER_VERSION, PLAN_PROTOCOL_TEXT_USER]]);
8349
+ KNOWN_USER_PROTOCOL_TEXT = /* @__PURE__ */ new Map([
8350
+ [1, PLAN_PROTOCOL_TEXT_USER_V1],
8351
+ [PLAN_PROTOCOL_USER_VERSION, PLAN_PROTOCOL_TEXT_USER]
8352
+ ]);
8340
8353
  BLOCK_START = /<!-- >>> wingman plan protocol v(\d+) >>> -->/gu;
8341
8354
  USER_BLOCK_START = /<!-- >>> wingman plan protocol user v(\d+) >>> -->/gu;
8342
8355
  }
@@ -8360,7 +8373,7 @@ function statusPlanProtocolUser(targetPath2) {
8360
8373
  const identity = readTarget(targetPath2)?.identity;
8361
8374
  return {
8362
8375
  targetPath: targetPath2,
8363
- state: identity === void 0 ? "missing" : identity.kind === "current" ? "installed" : "modified",
8376
+ state: identity === void 0 ? "missing" : identity.kind === "current" ? "installed" : identity.kind,
8364
8377
  ...identity?.version !== void 0 ? { version: identity.version } : {},
8365
8378
  ...identity?.kind === "modified" ? { reason: "\u7528\u6237\u7EA7\u53D7\u7BA1\u5757\u5DF2\u88AB\u4FEE\u6539" } : {}
8366
8379
  };
@@ -8372,11 +8385,12 @@ function installPlanProtocolUser(paths3) {
8372
8385
  const existing = readTarget(paths3.targetPath);
8373
8386
  assertKnown(existing, paths3.targetPath);
8374
8387
  const before = existing?.text ?? "";
8375
- if (existing?.identity !== void 0) {
8388
+ if (existing?.identity?.kind === "current") {
8376
8389
  return result(paths3.targetPath, "install", "installed", before, before, true, false);
8377
8390
  }
8378
8391
  const statePath2 = snapshotPath(paths3);
8379
- readSnapshot(statePath2, paths3.targetPath);
8392
+ const prior = readSnapshot(statePath2, paths3.targetPath);
8393
+ const outdated = existing?.identity?.kind === "outdated";
8380
8394
  const block = buildPlanProtocolBlock(PLAN_PROTOCOL_USER_VERSION, void 0, "user");
8381
8395
  const after = mergePlanProtocolBlock(before, block, paths3.targetPath, "user");
8382
8396
  const backupDir = nextBackupDir(paths3.homeDir);
@@ -8386,16 +8400,21 @@ function installPlanProtocolUser(paths3) {
8386
8400
  version: 1,
8387
8401
  targetPath: paths3.targetPath,
8388
8402
  installedRemainderSha256: sha256Hex(splitPlanProtocolBlock(after, paths3.targetPath, "user").remainder),
8389
- original: existing === void 0 ? { existed: false } : { existed: true, base64: existing.bytes.toString("base64") }
8403
+ original: existing === void 0 || outdated && existing.split.remainder === "" ? { existed: false } : {
8404
+ existed: true,
8405
+ base64: (outdated ? Buffer.from(existing.split.remainder) : existing.bytes).toString("base64")
8406
+ }
8390
8407
  };
8391
- mkdirSync(dirname2(statePath2), { recursive: true });
8392
- writeFileSync(statePath2, `${JSON.stringify(snapshot, null, 2)}
8408
+ if (!outdated || prior === void 0) {
8409
+ mkdirSync(dirname2(statePath2), { recursive: true });
8410
+ writeFileSync(statePath2, `${JSON.stringify(snapshot, null, 2)}
8393
8411
  `);
8412
+ }
8394
8413
  mkdirSync(dirname2(paths3.targetPath), { recursive: true });
8395
8414
  writeFileSync(paths3.targetPath, after);
8396
8415
  }
8397
8416
  return {
8398
- ...result(paths3.targetPath, "install", "missing", before, after, true, true),
8417
+ ...result(paths3.targetPath, "install", outdated ? "outdated" : "missing", before, after, true, true),
8399
8418
  state: "installed",
8400
8419
  version: PLAN_PROTOCOL_USER_VERSION,
8401
8420
  backupDir
@@ -8424,14 +8443,14 @@ function uninstallPlanProtocolUser(paths3) {
8424
8443
  rmSync(statePath2, { force: true });
8425
8444
  }
8426
8445
  return {
8427
- ...result(paths3.targetPath, "uninstall", "installed", before, after, afterExists, true),
8446
+ ...result(paths3.targetPath, "uninstall", existing.identity.kind === "outdated" ? "outdated" : "installed", before, after, afterExists, true),
8428
8447
  state: "missing",
8429
8448
  backupDir,
8430
8449
  restoredOriginal: canRestore
8431
8450
  };
8432
8451
  }
8433
8452
  function assertKnown(existing, targetPath2) {
8434
- if (existing?.identity !== void 0 && existing.identity.kind !== "current") {
8453
+ if (existing?.identity?.kind === "modified") {
8435
8454
  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
8455
  }
8437
8456
  }
@@ -9142,7 +9161,7 @@ function installProtocolDsh(options) {
9142
9161
  protocolVersion: PLAN_PROTOCOL_VERSION,
9143
9162
  installedAt: (/* @__PURE__ */ new Date()).toISOString(),
9144
9163
  backupDir,
9145
- installedRemainderSha256: sha256Hex(installedRemainder),
9164
+ installedRemainderSha256: previousState === "outdated" && prior !== void 0 ? prior.installedRemainderSha256 : sha256Hex(installedRemainder),
9146
9165
  original: prior?.original ?? (existing === void 0 ? { existed: false } : { existed: true, base64: existing.bytes.toString("base64") })
9147
9166
  });
9148
9167
  writeFileSync2(paths3.targetPath, after);
@@ -9206,7 +9225,8 @@ function resolveOptions(options) {
9206
9225
  }
9207
9226
  function readAgents(targetPath2) {
9208
9227
  const bytes = readFileSync2(targetPath2);
9209
- const text = decodeUtf8Strict2(bytes, targetPath2);
9228
+ decodeUtf8Strict2(bytes, targetPath2);
9229
+ const text = bytes.toString("utf8");
9210
9230
  let split;
9211
9231
  try {
9212
9232
  split = splitPlanProtocolBlock(text, targetPath2);
@@ -9235,7 +9255,7 @@ function stateForIdentity(identity) {
9235
9255
  return "not_installed";
9236
9256
  if (identity.kind === "current")
9237
9257
  return "installed";
9238
- if (identity.kind === "legacy")
9258
+ if (identity.kind === "outdated")
9239
9259
  return "outdated";
9240
9260
  return "modified";
9241
9261
  }
@@ -10834,7 +10854,7 @@ function stateForIdentity2(identity) {
10834
10854
  return "not_installed";
10835
10855
  if (identity.kind === "current")
10836
10856
  return "installed";
10837
- if (identity.kind === "legacy")
10857
+ if (identity.kind === "outdated")
10838
10858
  return "outdated";
10839
10859
  return "modified";
10840
10860
  }
@@ -13260,7 +13280,7 @@ function installProtocolCodex(options) {
13260
13280
  protocolVersion: PLAN_PROTOCOL_VERSION,
13261
13281
  installedAt: (/* @__PURE__ */ new Date()).toISOString(),
13262
13282
  backupDir,
13263
- installedRemainderSha256: sha256Hex(installedRemainder),
13283
+ installedRemainderSha256: previousState === "outdated" && prior !== void 0 ? prior.installedRemainderSha256 : sha256Hex(installedRemainder),
13264
13284
  original: prior?.original ?? (existing === void 0 ? { existed: false } : { existed: true, base64: existing.bytes.toString("base64") })
13265
13285
  });
13266
13286
  writeFileSync10(paths3.targetPath, after);
@@ -13320,7 +13340,8 @@ function resolveOptions3(options) {
13320
13340
  }
13321
13341
  function readAgents2(targetPath2) {
13322
13342
  const bytes = readFileSync13(targetPath2);
13323
- const text = decodeUtf8Strict2(bytes, targetPath2);
13343
+ decodeUtf8Strict2(bytes, targetPath2);
13344
+ const text = bytes.toString("utf8");
13324
13345
  let split;
13325
13346
  try {
13326
13347
  split = splitPlanProtocolBlock(text, targetPath2);
@@ -13349,7 +13370,7 @@ function stateForIdentity3(identity) {
13349
13370
  return "not_installed";
13350
13371
  if (identity.kind === "current")
13351
13372
  return "installed";
13352
- if (identity.kind === "legacy")
13373
+ if (identity.kind === "outdated")
13353
13374
  return "outdated";
13354
13375
  return "modified";
13355
13376
  }
@@ -15858,7 +15879,7 @@ function resolveWingmanVersion({ defined, moduleUrl = import.meta.url, readPacka
15858
15879
  return void 0;
15859
15880
  }
15860
15881
  function wingmanVersion() {
15861
- const defined = false ? void 0 : "0.8.1";
15882
+ const defined = false ? void 0 : "0.8.2";
15862
15883
  return resolveWingmanVersion({
15863
15884
  defined,
15864
15885
  readPackage: (url) => JSON.parse(readFileSync16(url, "utf8"))
@@ -16559,7 +16580,7 @@ function createNarrativeService(options = {}) {
16559
16580
  let state;
16560
16581
  if (observed.state === "installed_not_loaded")
16561
16582
  state = "installed_not_loaded";
16562
- else if (observed.state === "installed") {
16583
+ else if (observed.state === "installed" || observed.state === "outdated") {
16563
16584
  state = planMtime === void 0 ? "installed" : "plan_present";
16564
16585
  } else
16565
16586
  state = "not_installed";
@@ -18025,7 +18046,8 @@ import { execFile as execFile2 } from "node:child_process";
18025
18046
  import { createHmac, timingSafeEqual } from "node:crypto";
18026
18047
  import { readFile as readFile4 } from "node:fs/promises";
18027
18048
  import { createServer } from "node:http";
18028
- import { extname, resolve as resolve13, sep as sep2 } from "node:path";
18049
+ import { hostname } from "node:os";
18050
+ import { extname, relative as relative4, resolve as resolve13, sep as sep2 } from "node:path";
18029
18051
 
18030
18052
  // apps/cli/dist/return-target.js
18031
18053
  import { randomBytes as randomBytes5 } from "node:crypto";
@@ -18435,11 +18457,14 @@ async function handle(req, res, options, warn, runtime) {
18435
18457
  if (url.pathname === "/api/anatomy") {
18436
18458
  const configs = await scanAll(options.harnesses, warn);
18437
18459
  const anatomy = configs.map((config) => {
18438
- const homeDir = options.harnesses.find((entry) => entry.harness === config.harness)?.scanOptions.homeDir ?? options.homeDir;
18460
+ const scanOptions = options.harnesses.find((entry) => entry.harness === config.harness)?.scanOptions;
18461
+ const homeDir = scanOptions?.homeDir ?? options.homeDir;
18439
18462
  if (homeDir === void 0)
18440
18463
  throw new Error("anatomy \u9700\u8981\u663E\u5F0F homeDir");
18441
18464
  const user = config.harness === "cc" ? protocolStatusCcUser({ homeDir }).state : config.harness === "codex" ? protocolStatusCodexUser({ homeDir }).state : "unsupported";
18442
- return { ...config, planProtocol: { user } };
18465
+ const projectDir = scanOptions?.projectDir;
18466
+ const project = projectDir === void 0 ? "not_installed" : config.harness === "cc" ? protocolStatusCc({ homeDir, projectDir }).state : protocolStatusCodex({ homeDir, projectDir }).state;
18467
+ return { ...config, planProtocol: { user, project } };
18443
18468
  });
18444
18469
  res.writeHead(200, { "content-type": "application/json; charset=utf-8" });
18445
18470
  res.end(JSON.stringify(anatomy));
@@ -18561,6 +18586,10 @@ async function handleActionPlan(req, res, options) {
18561
18586
  sendJson2(res, 400, { error: "\u8BF7\u6C42\u4F53\u5FC5\u987B\u662F\u5408\u6CD5 JSON" });
18562
18587
  return;
18563
18588
  }
18589
+ if (isProtocolUserRequest(body)) {
18590
+ handleProtocolUserAction(body, res, options);
18591
+ return;
18592
+ }
18564
18593
  const { harness, action } = body;
18565
18594
  const loaded = pickHarness(options, harness);
18566
18595
  if (!loaded) {
@@ -18592,6 +18621,10 @@ async function handleActionApply(req, res, options, runtime) {
18592
18621
  sendJson2(res, 400, { error: "\u8BF7\u6C42\u4F53\u5FC5\u987B\u662F\u5408\u6CD5 JSON" });
18593
18622
  return;
18594
18623
  }
18624
+ if (isProtocolUserRequest(body)) {
18625
+ handleProtocolUserAction(body, res, options, runtime);
18626
+ return;
18627
+ }
18595
18628
  const { harness, plan } = body;
18596
18629
  const loaded = pickHarness(options, harness);
18597
18630
  if (!loaded) {
@@ -18612,6 +18645,59 @@ async function handleActionApply(req, res, options, runtime) {
18612
18645
  sendJson2(res, 400, { error: errorMessage3(error) });
18613
18646
  }
18614
18647
  }
18648
+ function isProtocolUserRequest(body) {
18649
+ return isRecord9(body) && (body.kind === "protocol_user_install" || body.kind === "protocol_user_uninstall");
18650
+ }
18651
+ function handleProtocolUserAction(body, res, options, runtime) {
18652
+ if (options.readonlyActions) {
18653
+ sendJson2(res, 403, { error: "fixtures \u6A21\u5F0F\u53EA\u8BFB:\u4E0D\u9884\u89C8\u6216\u5199\u5165\u7528\u6237\u7EA7\u534F\u8BAE" });
18654
+ return;
18655
+ }
18656
+ if (body.harness === "dsh") {
18657
+ sendJson2(res, 400, { error: "unsupported: dsh \u65E0\u7528\u6237\u7EA7\u6307\u4EE4\u6587\u4EF6\uFF0C\u8BF7\u6309\u9879\u76EE\u5B89\u88C5\u8BA1\u5212\u534F\u8BAE" });
18658
+ return;
18659
+ }
18660
+ const loaded = pickHarness(options, body.harness);
18661
+ if (!loaded || body.harness !== "cc" && body.harness !== "codex") {
18662
+ sendJson2(res, 400, { error: "\u7528\u6237\u7EA7\u8BA1\u5212\u534F\u8BAE harness \u9700\u8981 cc|codex" });
18663
+ return;
18664
+ }
18665
+ const homeDir = loaded.scanOptions.homeDir ?? options.homeDir;
18666
+ if (homeDir === void 0) {
18667
+ sendJson2(res, 500, { error: "\u7528\u6237\u7EA7\u8BA1\u5212\u534F\u8BAE\u9700\u8981\u663E\u5F0F homeDir" });
18668
+ return;
18669
+ }
18670
+ const install = body.kind === "protocol_user_install";
18671
+ const operation = body.harness === "cc" ? install ? installProtocolCcUser : uninstallProtocolCcUser : install ? installProtocolCodexUser : uninstallProtocolCodexUser;
18672
+ try {
18673
+ const result5 = operation({ homeDir, dryRun: runtime === void 0 });
18674
+ if (runtime === void 0) {
18675
+ const before = splitPlanProtocolBlock(result5.before, result5.targetPath, "user");
18676
+ const after = splitPlanProtocolBlock(result5.after, result5.targetPath, "user");
18677
+ const block = install ? after.block : before.block;
18678
+ sendJson2(res, 200, {
18679
+ kind: body.kind,
18680
+ harness: body.harness,
18681
+ targetPath: body.harness === "cc" ? "~/.claude/CLAUDE.md" : "~/.codex/AGENTS.md",
18682
+ hasBlock: before.block !== void 0,
18683
+ ...install && before.version !== void 0 && after.version !== void 0 && before.version < after.version ? { fromVersion: before.version, toVersion: after.version } : {},
18684
+ blockBytes: Buffer.byteLength(block ?? ""),
18685
+ backupDir: "~/.wingman/backups/<ISO \u65F6\u95F4\u6233>\uFF08\u91CD\u540D\u8FFD\u52A0 -N\uFF09",
18686
+ hostname: hostname()
18687
+ });
18688
+ } else {
18689
+ runtime.anatomy = null;
18690
+ const user = body.harness === "cc" ? protocolStatusCcUser({ homeDir }).state : protocolStatusCodexUser({ homeDir }).state;
18691
+ sendJson2(res, 200, {
18692
+ ok: true,
18693
+ planProtocol: { user },
18694
+ ...result5.backupDir === void 0 ? {} : { backupDir: `~/${relative4(homeDir, result5.backupDir).split(sep2).join("/")}` }
18695
+ });
18696
+ }
18697
+ } catch (error) {
18698
+ sendJson2(res, 400, { error: errorSummary(error) });
18699
+ }
18700
+ }
18615
18701
  async function handleReturn(req, res, options, activate) {
18616
18702
  if (req.method !== "POST" && (activate || req.method !== "GET")) {
18617
18703
  sendText2(res, 405, "method not allowed");
@@ -0,0 +1 @@
1
+ :root{color-scheme:dark;--page: #0d0d0d;--surface: #1a1a19;--pill: #050505;--ink: #ffffff;--ink2: #c3c2b7;--muted: #898781;--hairline: rgba(255, 255, 255, .1);--grid: #2c2c2a;--s1: #3987e5;--s2: #d95926;--s3: #199e70;--s4: #c98500;--s5: #d55181;--warn: #fab219;--bad: #e5534b;--fs-1: 18px;--fs-2: 14px;--fs-3: 12px}*{box-sizing:border-box;margin:0;padding:0}body{background:var(--page);color:var(--ink);font-family:system-ui,-apple-system,Segoe UI,PingFang SC,Microsoft YaHei,sans-serif;min-height:100vh;display:flex;flex-direction:column;align-items:center;padding:28px 16px 48px}.wrap{display:flex;width:100%;max-width:100%;min-width:0;flex-direction:column;align-items:center}.pill{display:flex;max-width:min(100%,640px);min-width:0;align-items:center;gap:10px;background:var(--pill);border:1px solid var(--hairline);border-radius:999px;padding:10px 18px;cursor:pointer;-webkit-user-select:none;user-select:none;box-shadow:0 8px 30px #0000008c;transition:transform .15s ease}.pill:hover{transform:scale(1.03)}.dot{width:8px;height:8px;border-radius:50%;background:var(--s1);animation:pulse 1.6s infinite;flex:none}@keyframes pulse{0%,to{opacity:1}50%{opacity:.35}}.dot.quiet{animation:none;background:var(--muted);opacity:.6}.dot.live{background:var(--s3);box-shadow:0 0 8px #199e70cc}.pill .t1{font-size:13px;font-weight:600;flex:none}.pill .t2{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:12px;color:var(--ink2)}.pill .chev{color:var(--muted);font-size:11px;flex:none}.dot.wait{background:var(--warn);box-shadow:0 0 8px #fab219cc;animation:pulse 1.2s infinite}.pill.waiting{border-color:#fab2198c}.pill.waiting .t2{color:var(--warn)}.panel{display:none;width:min(700px,94vw);background:var(--surface);border:1px solid var(--hairline);border-radius:20px;padding:20px 22px 16px;box-shadow:0 18px 60px #0009;transform-origin:top center}.open .panel{display:block;animation:drop .22s ease}.open .pill{display:none}.panel-region{display:contents}@keyframes drop{0%{opacity:0;transform:scale(.92) translateY(-8px)}to{opacity:1;transform:none}}.head{display:flex;align-items:center;gap:10px;margin-bottom:12px;flex-wrap:wrap}.head .title{font-size:15px;font-weight:700}.head .meta{font-size:12px;color:var(--muted)}.badge{font-size:10px;letter-spacing:.1em;color:var(--warn);border:1px solid var(--warn);border-radius:4px;padding:2px 6px}.collapse{margin-left:auto;background:none;border:1px solid var(--hairline);color:var(--ink2);border-radius:8px;padding:4px 10px;font-size:12px;cursor:pointer}.collapse:hover{border-color:var(--muted)}.tabs{display:flex;gap:4px;background:var(--pill);border:1px solid var(--hairline);border-radius:10px;padding:3px;width:max-content;margin-bottom:6px}.tab{border:none;background:none;color:var(--muted);font-size:12.5px;padding:5px 14px;border-radius:8px;cursor:pointer;font-family:inherit}.tab.act{background:var(--surface);color:var(--ink);font-weight:600;border:1px solid var(--hairline)}.tabnum{display:inline-block;margin-left:6px;min-width:16px;text-align:center;font-size:10px;color:var(--ink2);background:var(--grid);border-radius:999px;padding:0 4px;font-variant-numeric:tabular-nums}.now{background:var(--pill);border:1px solid var(--hairline);border-radius:12px;padding:10px 14px;margin:8px 0 10px}.now .ntask{font-size:14px;font-weight:700;display:flex;align-items:center;gap:8px}.now .ntask .muted{color:var(--muted);font-weight:400}.now .ndoing{font-size:12px;color:var(--ink2);margin-top:5px}.now .ndoing b{color:var(--ink);font-weight:600}.now .nquote{font-size:11.5px;color:var(--muted);margin-top:5px;line-height:1.6}.now .nwait{font-size:12px;color:var(--warn);border:1px solid rgba(250,178,25,.55);border-radius:8px;padding:5px 9px;margin-bottom:8px;animation:pulse 1.2s infinite}.taskflow{margin:8px 0 10px;font-size:var(--fs-2);line-height:1.55}.box{background:var(--pill);border:1px solid var(--hairline);border-radius:12px;padding:12px}.box+.box,.ask-line+.box,.fold{margin-top:16px}.box>*+*{margin-top:8px}.ask-box.active{border-color:var(--warn);color:var(--warn)}.ask-text{font-size:var(--fs-2);font-weight:650}.ask-meta{display:flex;align-items:center;flex-wrap:wrap;gap:6px 8px;font-size:var(--fs-3)}.ask-meta button{margin-left:auto;border:1px solid currentColor;border-radius:8px;background:transparent;color:inherit;cursor:pointer;font:inherit;padding:4px 8px}.ask-line{display:flex;align-items:baseline;gap:8px;color:var(--muted);font-size:var(--fs-3)}.wftitle{font-size:var(--fs-1);font-weight:650}.wfgoal,.wflead{display:flex;align-items:baseline;gap:8px;color:var(--ink2)}.wfsteps[data-expanded=false]{max-height:3.1em;-webkit-line-clamp:unset}.wfsteps[data-expanded=true]{max-height:none}.wflabel{display:inline-block;margin-right:8px;color:var(--muted);font-size:var(--fs-3);flex:none}.wfsource{color:var(--muted);font-size:var(--fs-3)}.wfsteps{margin-top:5px}.wfstep{display:flex;gap:7px;align-items:baseline}.wfstep.completed{color:var(--muted)}.wfstep.in_progress{font-weight:600}.wfrecent{display:flex;flex-wrap:wrap;gap:4px 8px}.wfrecent-step{color:var(--ink2)}.wfproject,.wfproject-details{display:flex;align-items:baseline;flex-wrap:wrap;gap:4px 6px;color:var(--ink2)}.wfcurrent{display:flex;align-items:baseline;min-width:0;gap:6px}.wfproject-node{padding:1px 7px}.wfproject-link{border:1px solid var(--hairline);border-radius:999px;background:transparent;color:var(--ink2);cursor:pointer;font:inherit;font-size:var(--fs-3);padding:2px 8px}.wfverify{display:flex;align-items:center;flex-wrap:wrap;gap:6px;color:var(--ink2)}.wfverify-sep{color:var(--muted)}.wfverify-action{border:1px solid var(--hairline);border-radius:999px;background:transparent;color:var(--ink2);cursor:pointer;font:inherit;font-size:var(--fs-3);padding:2px 8px}.wfverify-error{margin-top:5px}.fold>summary{display:flex;align-items:baseline;gap:8px;cursor:pointer;list-style:none}.fold>summary::-webkit-details-marker{display:none}.fold>summary:before{content:"▸";color:var(--muted);font-size:var(--fs-3);flex:none}.fold[open]>summary:before{content:"▾"}.fold>summary .wflabel{min-width:5em;margin-right:0}.fold-summary{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--ink2);font-size:var(--fs-2)}.fold-body{margin-top:8px;padding:8px 12px;border-left:1px solid var(--hairline);color:var(--ink2);overflow-wrap:anywhere}.protocol-foot{margin-top:16px;color:var(--muted);font-size:var(--fs-3)}.protocol-foot button{margin-left:8px;border:0;padding:0;background:transparent;color:inherit;font:inherit;text-decoration:underline;cursor:pointer}.evidencegroup+.evidencegroup{margin-top:6px}.vtabs{display:flex;gap:22px;border-bottom:1px solid var(--grid);margin-bottom:4px}.vtab{background:none;border:none;font-family:inherit;font-size:13px;color:var(--muted);padding:8px 2px;cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-1px}.vtab.act{color:var(--ink);font-weight:700;border-bottom-color:var(--s1)}.vtab .vcnt{font-size:11px;color:var(--muted);font-weight:400;font-variant-numeric:tabular-nums}.pane{display:none}.pane.act{display:block}.td{padding:8px 0;border-top:1px dashed var(--grid);font-size:13px}.td:first-child{border-top:none}.tdr{display:flex;align-items:center;gap:9px}.tdr[data-act]{cursor:pointer}.mk{width:16px;flex:none;text-align:center;font-size:12px;color:var(--s3)}.mk.doing{color:var(--s1)}.td .tdc{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.td.done .tdr{color:var(--muted)}.td.done .tdc{text-decoration:line-through}.td.todo .tdr{color:var(--muted)}.td .tdc b{font-weight:700}.ag{font-size:10px;color:var(--s1);border:1px solid rgba(57,135,229,.5);border-radius:999px;padding:0 8px;flex:none}.loc{margin-left:auto;flex:none;font-size:10.5px;font-family:inherit;color:var(--ink2);background:none;border:1px solid var(--grid);border-radius:7px;padding:2px 8px;cursor:pointer}.loc:hover{border-color:var(--muted)}.trace{margin:8px 0 2px 24px;border-left:2px solid var(--grid);padding-left:14px}.tr{display:flex;align-items:center;gap:8px;padding:5px 0;font-size:12px;color:var(--ink2);cursor:pointer}.tr .ic{width:8px;height:8px;border-radius:50%;background:var(--s3);flex:none;margin-left:-19px;border:2px solid var(--surface)}.tr.bad .ic{background:var(--bad)}.tr.run .ic{background:var(--s1)}.tr .trlabel{flex:none}.tr .dur,.trs .dur{margin-left:auto;color:var(--muted);font-size:10.5px;font-variant-numeric:tabular-nums;flex:none;white-space:nowrap}.failchip{font-size:10px;color:var(--bad);border:1px solid var(--bad);border-radius:999px;padding:0 7px;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.steps{margin-left:6px;padding:2px 0 4px}.trs{display:flex;align-items:center;gap:8px;padding:3px 0;font-size:11.5px;color:var(--muted)}.trs .cmd{font-family:ui-monospace,SF Mono,Menlo,Consolas,monospace;font-size:11px;color:var(--ink2);flex:none}.trs .sdetail{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.trs.bad .cmd{color:var(--bad)}.rawsec .rawhead{background:none;border:none;font-family:inherit;font-size:11px;letter-spacing:.14em;color:var(--muted);padding:0;cursor:pointer}.rawsec .rawhead:hover{color:var(--ink2)}.rawsec .rawbody{display:none}.rawsec .rawbody.open{display:block;margin-top:8px}.ubox{max-height:220px;overflow-y:auto;border:1px solid var(--grid);border-radius:8px;padding:2px 10px}.urow{display:flex;align-items:center;gap:8px;padding:5px 0;font-size:11.5px;border-top:1px dashed var(--grid);color:var(--ink2)}.urow:first-child{border-top:none}.urow .utime{color:var(--muted);font-size:10.5px;font-variant-numeric:tabular-nums;flex:none}.urow .unums{color:var(--muted);font-variant-numeric:tabular-nums;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.urow .utot{margin-left:auto;color:var(--ink);font-variant-numeric:tabular-nums;flex:none}.urow .ucost{color:var(--s3);font-variant-numeric:tabular-nums;flex:none}.sessions-empty,.session-notice{margin-top:8px;padding:7px 10px;border:1px solid var(--grid);border-radius:6px;color:var(--ink2);font-size:11px}.session-notice{display:flex;gap:8px;cursor:pointer}.session-notice-close{margin-left:auto;color:var(--ink3)}.schips{display:flex;flex-wrap:wrap;gap:6px;padding:8px 0 2px}.schip{display:inline-flex;align-items:center;gap:5px;background:none;border:1px solid var(--grid);border-radius:999px;padding:2px 10px;font-family:inherit;font-size:11px;color:var(--ink2);cursor:pointer}.schip:hover{border-color:var(--ink2)}.schip.act{color:var(--ink);border-color:var(--ink2);font-weight:600}.schip.ended{opacity:.55}.schip .sdot{width:6px;height:6px;border-radius:50%;background:var(--s1);flex:none}.schip .sdot.wait{background:var(--warn);animation:pulse 1.2s infinite}.schip .snew{padding:0 5px;border:1px solid var(--s1);border-radius:999px;color:var(--s1);font-size:9px;font-weight:700}.feedbacksignal{margin:8px 0 2px;border:1px solid rgba(250,178,25,.4);border-radius:8px;padding:5px 9px;color:var(--warn);font-size:12px}.suggslot:empty{display:none}.suggslot{border-top:1px solid var(--grid);padding:8px 0 2px}.sugg{display:flex;align-items:center;gap:8px;padding:5px 0;font-size:12px;color:var(--ink2)}.sugg .sugtext{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sugg.r-waiting-timeout .sugtext{color:var(--warn)}.sugg .sugbtn,.sugg .sugdismiss{background:none;border:1px solid var(--grid);border-radius:6px;padding:1px 8px;font-family:inherit;font-size:11px;color:var(--ink2);cursor:pointer;flex:none}.sugg .sugbtn{color:var(--ink);border-color:var(--ink2);margin-left:auto}.sugg .sugbtn:hover{background:var(--grid)}.sugg .sugdismiss{color:var(--muted)}.sugg .sugbtn+.sugdismiss{margin-left:0}.sugg .sugdismiss:only-of-type{margin-left:auto}.sugg .sugdismiss:hover{color:var(--ink2)}.tr.waitrow{cursor:default}.tr.waitrow .trlabel{color:var(--warn)}.sec{border-top:1px solid var(--grid);padding:13px 0}.sec.first{border-top:none;padding-top:2px}.sec .label{font-size:11px;letter-spacing:.14em;color:var(--muted);margin-bottom:8px;display:flex;align-items:center;gap:8px}.tier{font-size:10px;letter-spacing:0;color:var(--ink2);border:1px solid var(--grid);border-radius:999px;padding:1px 8px;font-weight:400}.sec .headline{font-size:13px;color:var(--ink2);margin-bottom:10px}.sec .headline b{color:var(--ink);font-weight:700}.stack{display:flex;height:16px;margin-bottom:10px}.seg{margin-right:2px;cursor:default}.seg:last-child{margin-right:0}.seg:first-child{border-radius:4px 0 0 4px}.seg:last-child{border-radius:0 4px 4px 0}.seg:hover{filter:brightness(1.18)}.legend{display:grid;grid-template-columns:1fr 1fr;gap:5px 18px}@media(max-width:560px){.legend{grid-template-columns:1fr}}.lrow{display:flex;align-items:center;gap:7px;font-size:12.5px;color:var(--ink2);min-width:0}.sw{width:10px;height:10px;border-radius:3px;flex:none}.lrow .nat,.gtitle .nat{font-size:10.5px;color:var(--muted);border:1px solid var(--grid);border-radius:4px;padding:0 5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.lrow .v{margin-left:auto;color:var(--ink);font-variant-numeric:tabular-nums;flex:none}.lrow .cnt{color:var(--muted);font-size:10.5px;flex:none}.lrow.na,.lrow.na .v{color:var(--muted)}.grp{margin-bottom:10px}.grp:last-child{margin-bottom:0}.gtitle{font-size:11.5px;color:var(--muted);margin-bottom:4px;display:flex;align-items:center;gap:7px}.gdot{width:8px;height:8px;border-radius:2px;flex:none}.crow{display:flex;align-items:center;gap:10px;padding:6px 0;font-size:12.5px;border-top:1px dashed var(--grid)}.cname{color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.offrow .cname{color:var(--muted)}.chip{font-size:10px;color:var(--muted);border:1px solid var(--grid);border-radius:999px;padding:1px 7px;flex:none}.statechip{font-size:10px;border-radius:999px;padding:1px 7px;flex:none}.statechip.off{color:var(--warn);border:1px solid var(--warn)}.statechip.nofile{color:var(--muted);border:1px dashed var(--grid)}.ctok{margin-left:auto;color:var(--muted);font-size:11.5px;font-variant-numeric:tabular-nums;flex:none}.crow.emptyrow{color:var(--muted);font-size:12px}.livenone{font-size:12.5px;color:var(--muted);border:1px dashed var(--grid);border-radius:8px;padding:10px 12px;margin-bottom:8px;line-height:1.7}.livenone:last-child{margin-bottom:0}.livenone code{color:var(--ink2);background:var(--pill);border:1px solid var(--grid);border-radius:4px;padding:1px 5px}.tier.none{color:var(--muted);border-style:dashed}.conn{font-size:10px;letter-spacing:0;font-weight:400;border-radius:999px;padding:1px 8px;border:1px solid var(--grid);color:var(--muted)}.conn.open{color:var(--s3);border-color:var(--s3)}.conn.retrying{color:var(--warn);border-color:var(--warn)}.conn.replay{color:var(--warn);border-style:dashed}.demobtn{margin-left:auto;background:none;border:1px dashed var(--warn);color:var(--warn);border-radius:6px;padding:2px 8px;font-size:10.5px;letter-spacing:0;cursor:pointer;font-family:inherit}.demobtn:hover:not(:disabled){border-style:solid}.demobtn:disabled{opacity:.5;cursor:default}.feed{max-height:240px;overflow-y:auto;border:1px solid var(--grid);border-radius:8px;padding:2px 10px}.lvrow{display:flex;align-items:center;gap:8px;padding:5px 0;font-size:12px;border-top:1px dashed var(--grid)}.lvrow:first-child{border-top:none}.lvtime{color:var(--muted);font-size:11px;font-variant-numeric:tabular-nums;flex:none}.lvname{color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.lvrow.own .lvname{font-weight:600}.lvrow.other{opacity:.45}.lvharness{margin-left:auto;font-size:10px;color:var(--muted);border:1px solid var(--grid);border-radius:4px;padding:0 5px;flex:none}.lvrow.own .lvharness{color:var(--ink2);border-color:var(--hairline)}.mockchip{font-size:9px;letter-spacing:.08em;color:var(--warn);border:1px solid var(--warn);border-radius:4px;padding:0 4px;flex:none}.labr{margin-left:auto;display:flex;align-items:center;gap:8px}.sharelink{background:none;border:1px solid var(--grid);color:var(--muted);border-radius:6px;padding:2px 8px;font-size:10.5px;letter-spacing:0;cursor:pointer;font-family:inherit}.sharelink:hover{color:var(--ink2);border-color:var(--muted)}.sharebox{max-height:320px;overflow:auto;border:1px solid var(--grid);border-radius:8px;background:var(--pill);padding:6px 8px;font-family:ui-monospace,SF Mono,Menlo,Consolas,monospace;font-size:11px;line-height:1.5}.shline{display:flex;gap:7px;align-items:flex-start;padding:1px 0}.shdel{flex:none;background:none;border:1px solid var(--grid);color:var(--muted);border-radius:4px;font-size:9px;line-height:1.3;padding:0 4px;margin-top:1px;cursor:pointer}.shdel:hover{color:var(--s2);border-color:var(--s2)}.shtext{color:var(--ink2);white-space:pre-wrap;word-break:break-all}.btn:disabled{opacity:.45;cursor:default}.btn:disabled:hover{filter:none}.empty-state{display:flex;flex-direction:column;align-items:center}.empty-card{width:min(460px,94vw);background:var(--surface);border:1px solid var(--hairline);border-radius:16px;padding:28px 26px;text-align:center}.empty-title{font-size:15px;font-weight:700;margin-bottom:8px}.empty-detail{font-size:12px;color:var(--warn);margin-bottom:8px;word-break:break-all}.empty-hint{font-size:12.5px;color:var(--muted);line-height:1.7}.empty-hint code{color:var(--ink2);background:var(--pill);border:1px solid var(--grid);border-radius:4px;padding:1px 5px}#tip{position:fixed;display:none;pointer-events:none;z-index:9;background:#050505;border:1px solid var(--hairline);border-radius:8px;padding:6px 10px;font-size:12px;color:var(--ink);max-width:300px;box-shadow:0 8px 24px #00000080;white-space:pre-line;line-height:1.5}.toggle{width:30px;height:17px;border-radius:999px;background:var(--grid);position:relative;cursor:pointer;flex:none;transition:background .15s;border:none;padding:0}.toggle:after{content:"";position:absolute;top:2px;left:2px;width:13px;height:13px;border-radius:50%;background:var(--ink2);transition:left .15s}.toggle.on{background:var(--s1)}.toggle.on:after{left:15px;background:#fff}.cright{display:flex;align-items:center;gap:8px;flex:none}.cfgnote{font-size:11px;color:var(--muted);padding:5px 0 2px;border-top:1px dashed var(--grid);line-height:1.6}.licbar{display:block;width:100%;text-align:left;font-size:12px;font-family:inherit;color:var(--warn);background:none;border:1px solid var(--warn);border-radius:8px;padding:6px 10px;margin-bottom:10px;cursor:pointer}.licbar.expired{color:var(--s2);border-color:var(--s2)}.licbar:hover{filter:brightness(1.12)}.licrow{display:flex;align-items:stretch;gap:8px;margin-bottom:10px}.licrow .licbar{flex:1;margin-bottom:0}.licimport{flex:none;font-size:11px;font-family:inherit;color:var(--muted);background:none;border:1px solid var(--grid);border-radius:8px;padding:6px 10px;cursor:pointer}.licimport:hover{color:var(--ink2);border-color:var(--muted)}.licfoot{margin-top:12px;text-align:center}.licfootlink{font-size:11px;font-family:inherit;color:var(--muted);background:none;border:none;padding:2px 4px;cursor:pointer;text-decoration:underline;text-decoration-color:var(--grid);text-underline-offset:3px}.licfootlink:hover{color:var(--ink2)}.feedbackfoot{display:flex;align-items:center;justify-content:center;gap:8px;flex-wrap:wrap;padding:0 18px 16px;color:var(--muted);font-size:10.5px;line-height:1.45;text-align:center}.feedbackfoot a{color:var(--ink2);text-underline-offset:2px}.feedbackfoot a:hover{color:var(--ink)}.feedbacklink{font-weight:650}.lictrial{margin:-2px 0 8px;text-align:right}.lictrial .licfootlink{text-decoration:none}#drop{position:fixed;inset:0;z-index:40;display:none;align-items:center;justify-content:center;background:#000000a6;border:2px dashed var(--s1);color:var(--ink);font-size:15px;pointer-events:none}.overlay{position:fixed;inset:0;z-index:20;display:flex;align-items:center;justify-content:center;padding:20px}.scrim{position:absolute;inset:0;background:#0009}.modal{position:relative;width:min(560px,94vw);max-height:86vh;overflow-y:auto;background:var(--surface);border:1px solid var(--hairline);border-radius:16px;padding:16px 18px;box-shadow:0 18px 60px #0009;animation:drop .18s ease}.mhead{display:flex;align-items:center;gap:8px;margin-bottom:10px}.mtitle{font-size:14px;font-weight:700}.mclose{margin-left:auto;background:none;border:1px solid var(--hairline);color:var(--ink2);border-radius:8px;padding:2px 8px;font-size:12px;cursor:pointer}.mclose:hover{border-color:var(--muted)}.mnote{font-size:11px;color:var(--warn);border:1px dashed var(--warn);border-radius:8px;padding:8px 10px;margin-bottom:10px;line-height:1.6}.msec{border-top:1px solid var(--grid);padding:10px 0}.mlabel{font-size:11px;letter-spacing:.1em;color:var(--muted);margin-bottom:6px}.mtext{font-size:12.5px;color:var(--ink2);line-height:1.7;word-break:break-all}.mtext.muted{color:var(--muted)}.mtext code,.mpath{color:var(--ink2);background:var(--pill);border:1px solid var(--grid);border-radius:4px;padding:1px 5px;font-size:11px;word-break:break-all}.mfile{display:flex;align-items:center;gap:8px;padding:4px 0;font-size:12px;flex-wrap:wrap}.mkind{font-size:10px;border-radius:4px;padding:1px 6px;flex:none;border:1px solid var(--grid);color:var(--ink2)}.mkind.create{color:var(--s3);border-color:var(--s3)}.mkind.modify{color:var(--s4);border-color:var(--s4)}.mkind.delete{color:var(--s2);border-color:var(--s2)}.mlines{margin-left:auto;font-size:11px;color:var(--muted);font-variant-numeric:tabular-nums;flex:none}.mref{display:flex;gap:8px;padding:4px 0;font-size:12px;align-items:baseline;flex-wrap:wrap}.mctx{color:var(--muted);font-size:11.5px;line-height:1.5}.merror{font-size:12px;color:var(--warn);border:1px solid var(--warn);border-radius:8px;padding:8px 10px;margin-bottom:8px;white-space:pre-wrap;word-break:break-all}.mact{display:flex;gap:8px;justify-content:flex-end;margin-top:12px}.btn{border-radius:8px;padding:6px 14px;font-size:12.5px;cursor:pointer;font-family:inherit}.btn.ghost{background:none;border:1px solid var(--hairline);color:var(--ink2)}.btn.ghost:hover{border-color:var(--muted)}.btn.primary{background:var(--s1);border:1px solid var(--s1);color:#fff;font-weight:600}.btn.primary:hover{filter:brightness(1.1)}.projects{display:grid;gap:12px;padding:12px 14px 16px}.projects-empty,.project-empty{color:var(--muted);font-size:12px;padding:8px 0}.project-card{border:1px solid var(--hairline);border-radius:12px;padding:12px;background:var(--surface)}.project-progress{display:grid;gap:7px;margin-top:12px;font-size:12px}.project-progress>div{display:flex;align-items:baseline;flex-wrap:wrap;gap:5px}.project-action{margin-top:14px;padding:10px 0;border-block:1px solid var(--hairline);font-size:12px}.project-action[data-kind=decision],.project-action[data-kind=checkpoint]{color:var(--warn)}.project-action-title{font-weight:650}.project-action-title>span{margin-left:6px;font-weight:400}.project-action-item{display:flex;align-items:baseline;flex-wrap:wrap;gap:7px;margin-top:8px}.project-tech{margin-top:14px;color:var(--muted);font-size:11px}.project-tech>summary,.project-plan-help>summary,.project-node-children>summary{cursor:pointer}.project-tech>summary{margin-bottom:7px}.project-node-children>summary{color:var(--muted);font-size:11px}.project-plan-help{margin-top:7px}.project-plan-help pre{white-space:pre-wrap}.project-action button:focus-visible,.project-tech summary:focus-visible,.project-node-children summary:focus-visible{outline:2px solid var(--s1);outline-offset:3px}.project-card.unavailable,.project-last-good{background:color-mix(in srgb,var(--surface) 88%,var(--grid))}.project-card-head{display:flex;justify-content:space-between;gap:12px;align-items:baseline}.project-title{font-size:15px;font-weight:700}.project-source{margin-left:7px;color:var(--muted);font-size:10.5px}.project-presence{color:var(--muted);font-size:11px;margin-top:4px}.project-memory-warning,.anatomy-refresh-warning{color:var(--warn);font-size:11px}.project-memory-warning{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:8px}.project-memory-warning button{color:inherit;background:transparent;border:0;cursor:pointer}.project-root,.project-meta,.project-counts,.project-facts{color:var(--muted);font-size:11px;overflow-wrap:anywhere}.project-meta{margin-top:4px}.project-protocols{display:grid;gap:6px;margin-top:8px}.project-protocol-row{display:flex;align-items:center;flex-wrap:wrap;gap:5px}.project-protocol-chip,.project-protocol-copy{border:1px solid var(--hairline);border-radius:999px;color:var(--ink2);font-family:inherit;font-size:10.5px;padding:2px 7px}.project-protocol-chip.plan_present,.project-protocol-chip.session_wrote_plan{border-color:var(--s3);color:var(--s3)}.project-protocol-chip.installed_not_loaded{border-color:var(--warn);color:var(--warn)}.project-protocol-note{color:var(--muted);font-size:10px;overflow-wrap:anywhere}.project-protocol-copy{background:transparent;cursor:pointer;padding-inline:6px}.project-protocol-copy:hover{border-color:var(--s1)}.project-goal,.project-section,.project-counts,.project-facts,.project-complete,.project-l0,.project-error,.project-last-good{margin-top:10px}.project-label{color:var(--ink2);font-size:11px;font-weight:650;margin-right:8px}.project-l0,.project-error{border:1px solid var(--hairline);border-radius:8px;padding:8px 10px;font-size:12px}.project-error{color:var(--warn);border-color:var(--warn)}.project-complete{color:var(--s3);font-size:12px;font-weight:650}.project-points{display:flex;flex-wrap:wrap;gap:6px;margin-top:5px}.project-checkpoints{margin-top:5px}.project-checkpoint{font-size:12px;font-weight:400}.project-crumb{border:1px solid var(--hairline);border-radius:999px;background:transparent;color:var(--ink2);cursor:pointer;font-family:inherit;font-size:11px;padding:3px 8px}.project-crumb:hover{border-color:var(--s1)}.project-node-text,.project-crumb,.project-checkpoint{display:-webkit-box;min-width:0;max-width:100%;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden;overflow-wrap:anywhere}.project-node-text{flex:1}.project-facts-group+.project-facts-group{margin-top:4px}.project-facts-toggle{border:0;background:transparent;color:inherit;cursor:pointer;font:inherit;padding:0;text-align:left}.project-facts-items{display:grid;gap:3px;margin:4px 0 0 14px}.task-filters{display:grid;gap:7px;padding:12px 14px 0}.task-filter-group{display:flex;align-items:center;flex-wrap:wrap;gap:5px;color:var(--muted);font-size:10.5px}.task-filter-chip,.task-badge,.task-status{border:1px solid var(--hairline);border-radius:999px;background:transparent;color:var(--ink2);font-family:inherit;font-size:10.5px;padding:2px 7px}.task-filter-chip{cursor:pointer}.task-filter-chip:hover,.task-filter-chip.act{border-color:var(--s1);color:var(--s1)}.task-filter-summary,.task-hidden{color:var(--muted);font-size:11px}.task-filter-summary{padding:7px 14px 0}.task-hidden{margin:5px 0 0 19px}.task-card-list{display:grid;grid-template-columns:minmax(0,1fr);gap:7px;margin-top:6px}.task-card{display:block;width:100%;border:1px solid var(--hairline);border-radius:10px;background:color-mix(in srgb,var(--surface) 94%,var(--grid));color:var(--ink);cursor:pointer;font-family:inherit;padding:9px 38px 9px 10px;text-align:left}.task-card:hover{border-color:var(--s1)}.task-card-head,.task-card-meta{display:flex;align-items:center;flex-wrap:wrap;gap:6px}.task-card-meta{margin-top:7px}.task-title{font-size:12px;font-weight:650;overflow-wrap:anywhere}.task-title-source,.task-progress,.task-activity,.task-context,.task-feedback,.task-checks,.task-accept{color:var(--muted);font-size:10.5px}.task-title-source:before{content:"来源:"}.task-status.waiting{border-color:var(--warn);color:var(--warn)}.task-status.active,.task-status.complete{border-color:var(--s3);color:var(--s3)}.task-status.ended{color:var(--muted)}.task-feedback,.task-context{display:block;margin-top:6px}.task-feedback{color:var(--warn)}.task-card-wrap{position:relative}.task-menu-button{position:absolute;top:6px;right:7px;width:28px;height:26px;border:1px solid transparent;border-radius:7px;background:transparent;color:var(--muted);cursor:pointer;font:700 17px / 1 inherit}.task-menu-button:hover,.task-menu-button[aria-expanded=true]{border-color:var(--hairline);color:var(--ink)}.task-menu{display:grid;gap:7px;max-width:100%;margin-top:5px;padding:8px;border:1px solid var(--hairline);border-radius:9px;background:color-mix(in srgb,var(--surface) 92%,var(--grid))}.task-menu label{display:grid;grid-template-columns:auto minmax(0,1fr);gap:7px;align-items:center;color:var(--muted);font-size:10.5px}.task-menu input{min-width:0;border:1px solid var(--hairline);border-radius:6px;background:var(--surface);color:var(--ink);font:inherit;padding:5px 7px}.task-menu-actions{display:flex;flex-wrap:wrap;gap:6px}.return-target-option,.return-settings-dismiss,.task-menu-actions button,.task-resume-command button,.task-unhide,.task-hidden-toggle{border:1px solid var(--hairline);border-radius:999px;background:transparent;color:var(--ink2);cursor:pointer;font:inherit;font-size:10.5px;padding:3px 8px}.task-resume-command{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:6px;align-items:center}.task-resume-command code{min-width:0;overflow-wrap:anywhere;white-space:pre-wrap}.task-return-result,.task-resume-note,.task-resume-unavailable,.task-error{grid-column:1 / -1;color:var(--muted);font-size:10.5px;overflow-wrap:anywhere}.task-error{margin-top:5px;color:var(--warn)}.task-pin-mark{color:var(--s1);font-size:10px;font-weight:700}.task-hidden-group{margin-top:6px}.task-hidden-toggle{color:var(--muted)}.task-card-hidden{opacity:.58}.task-unhide{margin-top:5px}@media(max-width:560px){.task-menu label{grid-template-columns:1fr}}.project-tree,.project-tree ul,.project-session-plan ul{list-style:none;margin:5px 0 0;padding-left:17px}.project-tree{padding-left:0}.project-node{margin:4px 0;font-size:12px}.project-node-line{display:flex;gap:7px;align-items:baseline}.project-node.in_progress>.project-node-line{color:var(--s3)}.project-node.completed,.project-node.cancelled,.project-node.collapsed{color:var(--muted)}.project-mark{width:12px;flex:none;text-align:center}.project-verify{color:var(--muted);font-size:11px;margin:3px 0 0 19px}.project-session-wrap,.task-card-wrap{margin:5px 0 6px 19px}.project-session-plan{border-left:1px solid var(--hairline);margin:5px 0 0 8px;padding-left:8px;font-size:11px}.project-session-plan .project-source{margin-left:0}.project-last-good{opacity:.72;border-radius:8px;padding:8px}html.island,html.island body{background:transparent}html.island body{padding:8px 0 12px;overflow:hidden}html.island .open .panel{height:calc(100vh - 20px);overflow-y:auto}html.island .scrim{border-radius:20px}.return-target-options{display:flex;flex-wrap:wrap;gap:6px}.return-target-option.act{color:var(--s1);border-color:var(--s1);background:var(--surface)}.return-target-option:hover,.return-settings-dismiss:hover{color:var(--ink)}.return-target-option:focus-visible,.return-settings-dismiss:focus-visible{outline:2px solid var(--s1);outline-offset:2px}.return-target-option:disabled{opacity:.6;cursor:default}[data-expand-text]{display:-webkit-box;min-width:0;max-width:100%;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden;overflow-wrap:anywhere}[data-expand-text][data-expanded=true]{-webkit-line-clamp:unset;white-space:normal;overflow:visible}.ask-line>[data-expand-text],.wfgoal>[data-expand-text],.wflead>[data-expand-text]{flex:1}.expand{border:0;background:transparent;color:var(--s1);cursor:pointer;font:inherit;font-size:11px;padding:2px 4px}.expand[hidden]{display:none}.expand:focus-visible{outline:2px solid var(--s1);outline-offset:2px}.protocol-banner{display:flex;align-items:center;flex-wrap:wrap;gap:8px;border-color:var(--hairline);color:var(--ink2);font-size:var(--fs-3)}.protocol-banner small{color:var(--muted);font-size:var(--fs-3)}.protocol-banner.highlighted{outline:2px solid var(--ink2);outline-offset:2px}.panel:has(.taskflow) .head .dot,.panel:has(.taskflow) .schip .sdot{background:var(--muted)}.panel:has(.taskflow) .schip .snew,.panel:has(.taskflow) .head .badge{color:var(--muted);border-color:var(--muted)}.panel:has(.taskflow) .vtab.act{border-bottom-color:var(--muted)}.ask-box .task-return-result{font-size:var(--fs-3)}.taskflow .mk,.taskflow .ag,.taskflow .expand,.taskflow .mockchip,.taskflow .failchip,.taskflow .trs.bad .cmd,.taskflow .tr.waitrow .trlabel,.taskflow .task-error{color:var(--ink2)}.taskflow .box .muted,.taskflow .fold .muted{color:var(--muted)}.taskflow .tr .ic{background:var(--muted)}.taskflow .mockchip,.taskflow .ag,.taskflow .failchip,.taskflow .project-crumb:hover,.taskflow .project-protocol-copy:hover,.protocol-banner .project-protocol-copy:hover{border-color:var(--muted)}.taskflow .cfgnote,.taskflow .ag,.taskflow .mockchip,.taskflow .task-error,.taskflow .statechip,.taskflow .mk,.taskflow .tr,.taskflow .tr .dur,.taskflow .trs,.taskflow .trs .cmd,.taskflow .trs .dur,.taskflow .failchip,.taskflow .expand,.taskflow .livenone,.taskflow .project-crumb,.taskflow .project-protocol-copy,.taskflow .project-protocol-note{font-size:var(--fs-3)}.taskflow button:focus-visible,.taskflow summary:focus-visible,.protocol-banner button:focus-visible,.protocol-foot button:focus-visible{outline:2px solid var(--ink2);outline-offset:3px}