@xqyz/xq-cli 0.3.1 → 0.3.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.
package/CHANGELOG.md CHANGED
@@ -10,6 +10,14 @@
10
10
 
11
11
  ## [Unreleased]
12
12
 
13
+ ## [0.3.2] - 2026-08-17
14
+
15
+ ### xq-cli / WorkBuddy 规划模式
16
+
17
+ - 规划模式首次 `outline --plan-mode 1` 在解析完成后明确返回“智能解读待审核”,不再误报大纲已完成或提前进入正文。
18
+ - WorkBuddy 新增智能解读审核、补充/修正暂存和确认续跑流程;确认时才调用喜鹊 `generateDirectoryByCid` 生成大纲。
19
+ - 新增 CLI 与 WorkBuddy 回归测试,验证同一 `cid` / `runId` 不重复提交。
20
+
13
21
  ### xq-cli `0.3.1` / WorkBuddy `0.10.1`
14
22
 
15
23
  - 修复普通项目在后端 `task_status=6`(文件解析中)时被误判为多标包/EPC,导致没有调用正常大纲生成接口、任务长时间停留在解析状态的问题。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xqyz/xq-cli",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "description": "CLI for xique bid-book task workflows",
5
5
  "type": "module",
6
6
  "scripts": {
package/src/cli.mjs CHANGED
@@ -1278,7 +1278,10 @@ async function handleOutline(args, state) {
1278
1278
  }
1279
1279
  const params = buildOutlineParams(outlineSnapshot, effectiveArgs);
1280
1280
 
1281
- const triggerMode = await triggerOutlineGeneration(client, outlineSnapshot, params);
1281
+ const planningMode = Number(params.planMode) === 1;
1282
+ const triggerMode = planningMode
1283
+ ? await preparePlanningAnalysis(client, params)
1284
+ : await triggerOutlineGeneration(client, outlineSnapshot, params);
1282
1285
  saveTaskSnapshot(state, cid, {
1283
1286
  ...outlineSnapshot,
1284
1287
  ...pickTaskSnapshot(params),
@@ -1288,7 +1291,9 @@ async function handleOutline(args, state) {
1288
1291
 
1289
1292
  let waitResult = null;
1290
1293
  if (booleanOption(effectiveArgs, 'wait')) {
1291
- waitResult = await waitForOutlineReady(client, state, cid, outlineSnapshot.uuid, effectiveArgs);
1294
+ waitResult = planningMode
1295
+ ? await waitForPlanningAnalysisReady(client, state, cid, outlineSnapshot.uuid, effectiveArgs)
1296
+ : await waitForOutlineReady(client, state, cid, outlineSnapshot.uuid, effectiveArgs);
1292
1297
  }
1293
1298
 
1294
1299
  const summaryLines = [
@@ -1299,7 +1304,9 @@ async function handleOutline(args, state) {
1299
1304
  `triggerMode: ${triggerMode}`,
1300
1305
  ];
1301
1306
 
1302
- if (waitResult?.phase === 'ready') {
1307
+ if (waitResult?.phase === 'analysis_ready') {
1308
+ summaryLines.push('planning analysis ready: review it, optionally add feedback, then run plan confirm-outline to generate the outline.');
1309
+ } else if (waitResult?.phase === 'ready') {
1303
1310
  summaryLines.push(`outline ready: rootChapters=${countOutlineRoots(waitResult)}`);
1304
1311
  } else if (waitResult?.phase === 'supplement_required') {
1305
1312
  summaryLines.push(`outline blocked: supplement required (${waitResult.issues.join(', ')})`);
@@ -1849,10 +1856,6 @@ function buildOutlineParams(snapshot, args) {
1849
1856
  async function triggerOutlineGeneration(client, snapshot, params) {
1850
1857
  await postJson(client, '/task/preSet', params);
1851
1858
 
1852
- if (Number(params.planMode) === 1) {
1853
- await setPlanModePhase(client, params.cid, 1);
1854
- }
1855
-
1856
1859
  // task_status=6 means "file parsing" in the Xique backend. It is not a
1857
1860
  // signal that this is a multi-bid/EPC task. Only route through the
1858
1861
  // special-selection endpoint when the caller actually supplied a
@@ -1875,6 +1878,13 @@ async function triggerOutlineGeneration(client, snapshot, params) {
1875
1878
  return 'generateByRequirement';
1876
1879
  }
1877
1880
 
1881
+ async function preparePlanningAnalysis(client, params) {
1882
+ // The backend intentionally pauses plan-mode tasks after parsing. The user
1883
+ // must review that analysis before generateDirectoryByCid starts the outline.
1884
+ await postJson(client, '/task/preSet', params);
1885
+ return 'planningAnalysisPrepared';
1886
+ }
1887
+
1878
1888
  async function setPlanModePhase(client, cid, planModePhase) {
1879
1889
  const response = await postJson(client, '/task/setPlanModePhase', { cid, planModePhase });
1880
1890
  const returned = normalizePlanModePhase(response?.data?.planModePhase);
@@ -2369,6 +2379,79 @@ async function waitForOutlineReady(client, state, cid, uuid, args) {
2369
2379
  });
2370
2380
  }
2371
2381
 
2382
+ async function waitForPlanningAnalysisReady(client, state, cid, uuid, args) {
2383
+ const handledIssues = new Set();
2384
+
2385
+ return pollUntil(async () => {
2386
+ const taskResponse = await getJson(client, `/task/getTaskDetail/${encodeURIComponent(cid)}`);
2387
+ const taskDetail = taskResponse?.data || {};
2388
+ saveTaskSnapshot(state, cid, pickTaskSnapshot(taskDetail));
2389
+
2390
+ if (Number(taskDetail.task_status) === 7) {
2391
+ return {
2392
+ done: true,
2393
+ data: { phase: 'failed', taskDetail },
2394
+ progressLabel: 'task_status=7',
2395
+ };
2396
+ }
2397
+
2398
+ const parseStatus = uuid
2399
+ ? await fetchParseStatus(client, state, cid, uuid)
2400
+ : { success: 1 };
2401
+ const parseSuccess = Number(parseStatus.success);
2402
+ const issues = collectParseIssues(parseStatus);
2403
+ if (parseSuccess === 4 && issues.length > 0) {
2404
+ const autoIgnore = resolveAutoIgnoreIssue(issues, args, uuid, handledIssues);
2405
+ if (autoIgnore) {
2406
+ await submitIntermediateChoice(client, autoIgnore.payload);
2407
+ handledIssues.add(autoIgnore.issue);
2408
+ return {
2409
+ done: false,
2410
+ data: null,
2411
+ progressLabel: `ignored ${autoIgnore.issue}, waiting planning analysis`,
2412
+ };
2413
+ }
2414
+ return {
2415
+ done: true,
2416
+ data: {
2417
+ phase: 'supplement_required',
2418
+ issues,
2419
+ parseStatus,
2420
+ taskDetail,
2421
+ },
2422
+ progressLabel: `supplement_required=${issues.join(',')}`,
2423
+ };
2424
+ }
2425
+
2426
+ if (parseSuccess === 1 || (
2427
+ parseSuccess > 0
2428
+ && String(taskDetail.requirement || '').trim()
2429
+ && String(taskDetail.rating || '').trim()
2430
+ )) {
2431
+ return {
2432
+ done: true,
2433
+ data: {
2434
+ phase: 'analysis_ready',
2435
+ taskDetail,
2436
+ parseStatus,
2437
+ },
2438
+ progressLabel: 'planning analysis ready; waiting for outline confirmation',
2439
+ };
2440
+ }
2441
+
2442
+ return {
2443
+ done: false,
2444
+ data: null,
2445
+ progressLabel: `success=${parseSuccess}, task_status=${taskDetail.task_status ?? '-'}, planning analysis pending`,
2446
+ };
2447
+ }, {
2448
+ intervalMs: secondsToMs(numberOption(args, 'intervalSec', DEFAULT_TASK_INTERVAL_MS / 1000)),
2449
+ timeoutMs: secondsToMs(numberOption(args, 'timeoutSec', DEFAULT_TIMEOUT_MS / 1000)),
2450
+ quiet: booleanOption(args, 'json'),
2451
+ waitingText: 'waiting planning analysis',
2452
+ });
2453
+ }
2454
+
2372
2455
  async function pollContentUntilReady(client, state, cid, args) {
2373
2456
  let unfinishedTriggered = false;
2374
2457
  let lastUnfinishedTriggerAt = 0;