@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 +8 -0
- package/package.json +1 -1
- package/src/cli.mjs +90 -7
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
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
|
|
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 =
|
|
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 === '
|
|
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;
|