@xqyz/xq-cli 0.3.2 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -8,7 +8,59 @@
8
8
 
9
9
  发布日期以 npm 官方仓库记录为准。发布前必须先更新本文件,再执行版本发布。
10
10
 
11
- ## [Unreleased]
11
+ ## [0.3.3 / WorkBuddy Plugin 0.10.9] - 2026-08-19
12
+
13
+ ### WorkBuddy 响应依据阶段化选择
14
+
15
+ - 首次标书配置卡移除“响应依据”,避免在后端候选目录生成前提前提交 `referenceType`。
16
+ - 新增独立依据选择阶段,展示喜鹊返回的三套真实目录预览;选择后只调用依据提交接口并继续同一 `cid` / `runId`。
17
+ - 增加重复提交保护,重复选择不会重新上传、创建任务或提交不同依据。
18
+ - 同步 WorkBuddy MCP App、Skill、Connector 文档与回归测试。
19
+ - xq-cli 新增 `plan reference-select`,依据选择复用原任务且不重复提交篇幅等基础参数。
20
+
21
+ ## [WorkBuddy Plugin 0.10.8] - 2026-08-18
22
+
23
+ ### 规划模式目录修改安全性
24
+
25
+ - `xique_prepare_directory_update` 改为显式递归目录结构,目录名称使用 `text`,同时兼容并自动归一化旧调用中的 `title` / `name`。
26
+ - 保存前读取后台当前完整目录,自动保留已有节点 ID;遗漏根节点或子节点时默认拒绝,避免局部目录请求被后台解释为删除其他章节。
27
+ - 修复目录修改预览始终显示“根节点数=0”,现在从 `requestPreview.directories` 返回准确的根节点数、总节点数和 ID 保留统计。
28
+ - 保存确认绑定预览时的后台目录签名;确认期间目录变化时拒绝写入。后台保存失败会返回真实原因和“重新查看、重新预览、重新确认”动作,禁止自动重复请求。
29
+ - 保存成功后仍停留在 `directory-review`,不会启动正文;新增覆盖字段归一化、完整树校验、ID 保留、失败单次消费和成功保存的回归测试。
30
+
31
+ ## [WorkBuddy Plugin 0.10.7] - 2026-08-17
32
+
33
+ ### 规划模式目录确认卡
34
+
35
+ - 修复 `xique_directory_confirmation` 未声明 MCP App 面板元数据,WorkBuddy 只显示文本而不生成目录确认卡的问题。
36
+ - 目录确认准备结果改为紧凑摘要,始终显式返回真实一次性 `confirmationId`,避免完整目录树截断后被误用 `cid`。
37
+ - 目录确认卡和正文继续动作按 `runId`、目录签名自动恢复错误的 `cid`,并支持“确认目录并生成正文”作为有效确认语句。
38
+ - 增加目录确认卡展示、ID 恢复、单次确认和正文门禁回归测试。
39
+
40
+ ## [WorkBuddy Plugin 0.10.6] - 2026-08-17
41
+
42
+ ### 规划模式目录审阅
43
+
44
+ - 修复 Connector 将目录命令拼成 `xq-cli directory directory view/update`,导致目录已经生成后报 `Unknown directory action: directory` 并停在目录审阅阶段的问题。
45
+ - `xique_directory_view`、目录修改预览和目录修改保存现在分别正确调用 `directory view` / `directory update`,不会重复顶层命令。
46
+ - 增加目录查看、预览修改、确认保存的参数级回归测试,并用真实任务 `a653d3b6e6274a2c91f29bcb28712690` 验证可读回完整 9 章目录。
47
+
48
+ ## [WorkBuddy Plugin 0.10.5] - 2026-08-17
49
+
50
+ ### 规划模式确认调用
51
+
52
+ - 修复 Connector 调用带子命令的 `xq-cli` 时将 `--json` 放在子命令前,导致 `plan confirm-outline` 被解析为 `plan status` 的问题。
53
+ - 确认智能解读后现在会真正执行 `plan confirm-outline`,从而按前端顺序调用 `setPlanModePhase(1)` 和 `/task/generateDirectoryByCid`。
54
+ - 增加真实参数顺序回归测试;当 CLI 返回错误命令时报告协议错误,不再伪装成后端大纲生成阻塞。
55
+
56
+ ## [WorkBuddy Plugin 0.10.4] - 2026-08-17
57
+
58
+ ### 规划模式确认链路
59
+
60
+ - 修复 WorkBuddy 将 cid 错传为 confirmationId 时无法继续生成大纲的问题。
61
+ - 智能解读确认卡按同一 runId 自动恢复真实的一次性确认记录,并继续调用 `/task/generateDirectoryByCid`。
62
+ - 新增回归测试覆盖错误 ID、单次消费和同一 runId 恢复。
63
+
12
64
 
13
65
  ## [0.3.2] - 2026-08-17
14
66
 
@@ -17,6 +69,7 @@
17
69
  - 规划模式首次 `outline --plan-mode 1` 在解析完成后明确返回“智能解读待审核”,不再误报大纲已完成或提前进入正文。
18
70
  - WorkBuddy 新增智能解读审核、补充/修正暂存和确认续跑流程;确认时才调用喜鹊 `generateDirectoryByCid` 生成大纲。
19
71
  - 新增 CLI 与 WorkBuddy 回归测试,验证同一 `cid` / `runId` 不重复提交。
72
+ - WorkBuddy Plugin `0.10.3` 修正 MCP 初始化指令和内置命令,明确规划模式必须先审核智能解读,再确认生成大纲。
20
73
 
21
74
  ### xq-cli `0.3.1` / WorkBuddy `0.10.1`
22
75
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xqyz/xq-cli",
3
- "version": "0.3.2",
3
+ "version": "0.3.3",
4
4
  "description": "CLI for xique bid-book task workflows",
5
5
  "type": "module",
6
6
  "scripts": {
package/src/cli.mjs CHANGED
@@ -473,6 +473,7 @@ Examples
473
473
  xq-cli plan status --cid <cid> --json
474
474
  xq-cli plan feedback --cid <cid> --text "Add the missing service boundary"
475
475
  xq-cli plan confirm-outline --cid <cid> --yes --wait
476
+ xq-cli plan reference-select --cid <cid> --reference-type 0 --yes --wait
476
477
  xq-cli plan outline-ai-adjust --cid <cid> --prompt "Split chapter 2 into implementation and quality control" --out D:\\output\\
477
478
  xq-cli plan outline-ai-apply --cid <cid> --file D:\\output\\outline-ai-<cid>.json --yes
478
479
  xq-cli plan directory-generate --cid <cid> --yes --wait
@@ -926,6 +927,10 @@ async function handlePlan(args, state) {
926
927
  case 'correction':
927
928
  await handlePlanFeedback(args, state);
928
929
  return;
930
+ case 'reference-select':
931
+ case 'select-reference':
932
+ await handlePlanReferenceSelection(args, state);
933
+ return;
929
934
  case 'confirm-outline':
930
935
  case 'outline-confirm':
931
936
  case 'generate-outline':
@@ -973,14 +978,16 @@ async function handlePlan(args, state) {
973
978
  async function handlePlanStatus(args, state) {
974
979
  const client = createAuthorizedClient(args, state);
975
980
  const cid = resolveCid(args, state);
976
- const [taskResponse, outlineResponse, contentResponse] = await Promise.all([
981
+ const [taskResponse, outlineResponse, contentResponse, referenceResponse] = await Promise.all([
977
982
  getJson(client, `/task/getTaskDetail/${encodeURIComponent(cid)}`, {}, { retries: DEFAULT_RETRY_COUNT }),
978
983
  fetchOutlineDetail(client, cid),
979
984
  fetchContentDetail(client, cid),
985
+ fetchReferenceStatusSafe(client, cid),
980
986
  ]);
981
987
  const taskDetail = taskResponse?.data || {};
982
988
  const outlineDetail = outlineResponse?.data || {};
983
989
  const contentDetail = contentResponse?.data || {};
990
+ const referenceDetail = referenceResponse?.data || {};
984
991
  const phase = normalizePlanModePhase(taskDetail.plan_mode_phase);
985
992
  const payload = {
986
993
  command: 'plan-status',
@@ -991,15 +998,23 @@ async function handlePlanStatus(args, state) {
991
998
  taskDetail,
992
999
  outlineDetail,
993
1000
  contentDetail,
1001
+ referenceDetail,
1002
+ referenceStatus: normalizeReferenceStatus(referenceDetail.status),
1003
+ referenceOptions: buildOutlineReferenceChoices(referenceDetail),
994
1004
  pendingFeedback: normalizePlanFeedback(state.tasks?.[cid]?.planFeedback).length,
995
1005
  };
996
1006
  saveTaskSnapshot(state, cid, pickTaskSnapshot({ ...taskDetail, ...contentDetail }));
1007
+ saveTaskSnapshot(state, cid, {
1008
+ referenceStatus: normalizeReferenceStatus(referenceDetail.status),
1009
+ referenceOptions: buildOutlineReferenceChoices(referenceDetail),
1010
+ });
997
1011
  outputResult(args, payload, [
998
1012
  `plan status: cid=${cid}`,
999
1013
  `planMode: ${describeEnumValue(PLAN_MODE_OPTIONS, normalizePlanModeValue(taskDetail.planMode) ?? taskDetail.planMode)}`,
1000
1014
  `phase: ${formatPlanModePhase(phase)}`,
1001
1015
  `outline: ${outlineDetail.outline_status ? 'ready' : 'not-ready'} (${countOutlineRoots({ outlineDetail })} root chapters)`,
1002
1016
  `directory: task_status=${contentDetail.task_status ?? taskDetail.task_status ?? '-'}, directory_status=${contentDetail.directory_portion_status ?? taskDetail.directory_portion_status ?? '-'}`,
1017
+ `reference: status=${normalizeReferenceStatus(referenceDetail.status) ?? '-'}, selected=${state.tasks?.[cid]?.outlineReferenceType ?? '-'}`,
1003
1018
  `pending feedback: ${payload.pendingFeedback}`,
1004
1019
  ]);
1005
1020
  return payload;
@@ -1040,6 +1055,65 @@ async function handlePlanFeedback(args, state) {
1040
1055
  return payload;
1041
1056
  }
1042
1057
 
1058
+ async function handlePlanReferenceSelection(args, state) {
1059
+ const client = createAuthorizedClient(args, state);
1060
+ const cid = resolveCid(args, state);
1061
+ const referenceType = parseOutlineReferenceType(stringOption(args, 'referenceType'));
1062
+ if (referenceType === null) {
1063
+ throw new Error('plan reference-select requires --reference-type 0, 1, 2, merge, format, or score.');
1064
+ }
1065
+
1066
+ const snapshot = await hydrateTaskSnapshot(client, state, cid);
1067
+ const previous = parseOutlineReferenceType(snapshot.outlineReferenceType);
1068
+ if (previous !== null) {
1069
+ if (previous !== referenceType) {
1070
+ throw new Error('该任务已经提交过其他响应依据,不能二次修改;请继续查询同一 cid。');
1071
+ }
1072
+ const payload = {
1073
+ command: 'plan-reference-select',
1074
+ cid,
1075
+ referenceType,
1076
+ alreadyApplied: true,
1077
+ duplicateRequestPrevented: true,
1078
+ };
1079
+ outputResult(args, payload, [
1080
+ `reference selection already applied: cid=${cid}, referenceType=${referenceType}`,
1081
+ 'duplicate request prevented; continue querying the same task.',
1082
+ ]);
1083
+ return payload;
1084
+ }
1085
+
1086
+ const referenceStatus = await fetchReferenceStatusSafe(client, cid);
1087
+ const referencePhase = normalizeReferenceStatus(referenceStatus?.data?.status);
1088
+ if (referencePhase !== null && referencePhase !== 1) {
1089
+ throw new Error('当前任务不在等待响应依据选择阶段(status=' + referencePhase + '),请先查询 plan status。');
1090
+ }
1091
+ await confirmPlanAction(args, 'select outline reference basis', [
1092
+ `referenceType: ${referenceType}`,
1093
+ 'only the backend reference-selection endpoint will be called; the task will not be recreated.',
1094
+ ]);
1095
+ await submitOutlineReferenceType(client, cid, referenceType);
1096
+ saveTaskSnapshot(state, cid, { outlineReferenceType: referenceType, referenceStatus: 1 });
1097
+
1098
+ const waitResult = booleanOption(args, 'wait')
1099
+ ? await waitForOutlineReady(client, state, cid, snapshot.uuid, { ...args, referenceType: undefined }, referenceType)
1100
+ : null;
1101
+ const payload = {
1102
+ command: 'plan-reference-select',
1103
+ cid,
1104
+ referenceType,
1105
+ responseSubmitted: true,
1106
+ waitResult,
1107
+ };
1108
+ outputResult(args, payload, [
1109
+ `reference selection submitted: cid=${cid}, referenceType=${referenceType}`,
1110
+ waitResult?.phase === 'ready'
1111
+ ? `outline ready: rootChapters=${countOutlineRoots(waitResult)}`
1112
+ : 'outline generation is continuing; query plan status for the same task.',
1113
+ ]);
1114
+ return payload;
1115
+ }
1116
+
1043
1117
  async function handlePlanOutlineConfirmation(args, state) {
1044
1118
  const client = createAuthorizedClient(args, state);
1045
1119
  const cid = resolveCid(args, state);
@@ -2226,9 +2300,9 @@ async function pollTaskUntil(client, state, cid, args, isDone, formatProgress) {
2226
2300
  });
2227
2301
  }
2228
2302
 
2229
- async function waitForOutlineReady(client, state, cid, uuid, args) {
2303
+ async function waitForOutlineReady(client, state, cid, uuid, args, initialSubmittedReferenceType = null) {
2230
2304
  const handledIssues = new Set();
2231
- let submittedReferenceType = null;
2305
+ let submittedReferenceType = initialSubmittedReferenceType;
2232
2306
 
2233
2307
  return pollUntil(async () => {
2234
2308
  const [taskDetail, outlineDetail, referenceStatus] = await Promise.all([