@lmzhen/dsh-evolution-merge 0.30.14 → 0.30.16
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/lib/index.js +32 -7
- package/lib/types/domain/ledger.js +3 -0
- package/lib/types/read-commands.js +10 -4
- package/lib/types/resume-command.js +4 -0
- package/lib/types/runtime.js +11 -3
- package/lib/types/state.js +1 -1
- package/package.json +3 -3
package/lib/index.js
CHANGED
|
@@ -246,6 +246,14 @@ function parseLedger(raw) {
|
|
|
246
246
|
};
|
|
247
247
|
}
|
|
248
248
|
const body = parsed;
|
|
249
|
+
if (typeof body.schemaVersion === "number" && body.schemaVersion > 2) return {
|
|
250
|
+
ok: false,
|
|
251
|
+
ledger: {
|
|
252
|
+
schemaVersion: 2,
|
|
253
|
+
rows: []
|
|
254
|
+
},
|
|
255
|
+
note: "merge-state-forward-only"
|
|
256
|
+
};
|
|
249
257
|
if (!Array.isArray(body.rows)) return {
|
|
250
258
|
ok: false,
|
|
251
259
|
ledger: {
|
|
@@ -300,7 +308,8 @@ function parseState(raw) {
|
|
|
300
308
|
const parsed = parseLedger(raw);
|
|
301
309
|
if (!parsed.ok) return {
|
|
302
310
|
ok: false,
|
|
303
|
-
rows: []
|
|
311
|
+
rows: [],
|
|
312
|
+
...parsed.note === void 0 ? {} : { note: parsed.note }
|
|
304
313
|
};
|
|
305
314
|
return {
|
|
306
315
|
ok: true,
|
|
@@ -1551,8 +1560,13 @@ function mergeUsage() {
|
|
|
1551
1560
|
//#region lib/types/read-commands.js
|
|
1552
1561
|
async function handleReadOnlyMergeCommand(command, io, home, cards) {
|
|
1553
1562
|
const withNote = (text, note) => note === void 0 ? text : "note: " + note + "\n" + text;
|
|
1563
|
+
const load = async () => {
|
|
1564
|
+
const result = await loadMergeState(io, home);
|
|
1565
|
+
if (result.note === "merge-state-forward-only") throw new Error("merge-state-forward-only");
|
|
1566
|
+
return result;
|
|
1567
|
+
};
|
|
1554
1568
|
if (command.verb === "status") {
|
|
1555
|
-
const loaded = await
|
|
1569
|
+
const loaded = await load();
|
|
1556
1570
|
if (command.id !== void 0) {
|
|
1557
1571
|
const row = loaded.state.rows.find((item) => item.id === command.id);
|
|
1558
1572
|
return withNote(row === void 0 ? "merge row not found: " + command.id : formatStatus([row]), loaded.note);
|
|
@@ -1560,17 +1574,17 @@ async function handleReadOnlyMergeCommand(command, io, home, cards) {
|
|
|
1560
1574
|
return withNote(formatStatus(loaded.state.rows), loaded.note);
|
|
1561
1575
|
}
|
|
1562
1576
|
if (command.verb === "pending") {
|
|
1563
|
-
const loaded = await
|
|
1577
|
+
const loaded = await load();
|
|
1564
1578
|
const rows = command.expired === true ? loaded.state.rows.filter((row) => row.expired !== void 0) : loaded.state.rows;
|
|
1565
1579
|
const live = cards === void 0 ? rows : rows.filter((row) => cards.some((card) => card.name === row.a) && cards.some((card) => card.name === row.b));
|
|
1566
1580
|
return withNote(command.expired === true ? formatStatus(live) : formatQueue(live, "pending"), loaded.note);
|
|
1567
1581
|
}
|
|
1568
1582
|
if (command.verb === "candidates") {
|
|
1569
|
-
const loaded = await
|
|
1583
|
+
const loaded = await load();
|
|
1570
1584
|
return withNote(formatQueue(command.retry === true ? loaded.state.rows.filter((row) => row.state === "approved") : loaded.state.rows, command.retry === true ? "fuse" : "verify"), loaded.note);
|
|
1571
1585
|
}
|
|
1572
1586
|
if (command.verb === "skipped") {
|
|
1573
|
-
const loaded = await
|
|
1587
|
+
const loaded = await load();
|
|
1574
1588
|
return withNote(formatQueue(loaded.state.rows, "skipped"), loaded.note);
|
|
1575
1589
|
}
|
|
1576
1590
|
return null;
|
|
@@ -2498,13 +2512,18 @@ async function runResumeCommand(options) {
|
|
|
2498
2512
|
}])
|
|
2499
2513
|
};
|
|
2500
2514
|
} },
|
|
2501
|
-
...options.timeoutMinutes === void 0 ? {} : { timeoutMinutes: options.timeoutMinutes }
|
|
2515
|
+
...options.timeoutMinutes === void 0 ? {} : { timeoutMinutes: options.timeoutMinutes },
|
|
2516
|
+
...options.isOwnerActive === void 0 ? {} : { isOwnerActive: options.isOwnerActive }
|
|
2502
2517
|
});
|
|
2503
2518
|
}
|
|
2504
2519
|
if (row.state !== "fuse" && row.state !== "approved") return {
|
|
2505
2520
|
ok: false,
|
|
2506
2521
|
message: "row is not resumable from state " + row.state
|
|
2507
2522
|
};
|
|
2523
|
+
if (row.runId !== void 0 && await options.isOwnerActive?.(row.runId) === true) return {
|
|
2524
|
+
ok: false,
|
|
2525
|
+
message: "merge run still owns this fuse row: " + row.runId
|
|
2526
|
+
};
|
|
2508
2527
|
const decision = row.decision;
|
|
2509
2528
|
if (decision === void 0) return {
|
|
2510
2529
|
ok: false,
|
|
@@ -4071,7 +4090,13 @@ function createMergeRuntime(deps) {
|
|
|
4071
4090
|
};
|
|
4072
4091
|
}
|
|
4073
4092
|
const loaded = await loadMergeState(deps.io, deps.home);
|
|
4074
|
-
|
|
4093
|
+
let row = command.id === void 0 ? void 0 : loaded.state.rows.find((item) => item.id === command.id);
|
|
4094
|
+
if (command.id === void 0) for (const item of loaded.state.rows) {
|
|
4095
|
+
if (item.state !== "fuse" && item.state !== "verify" && !(command.retry === true && item.state === "approved")) continue;
|
|
4096
|
+
if (item.runId !== void 0 && await deps.isOwnerActive?.(item.runId) === true) continue;
|
|
4097
|
+
row = item;
|
|
4098
|
+
break;
|
|
4099
|
+
}
|
|
4075
4100
|
if (row === void 0) return {
|
|
4076
4101
|
ok: false,
|
|
4077
4102
|
text: "merge row not found: " + (command.id ?? "(auto)")
|
|
@@ -17,6 +17,9 @@ export function parseLedger(raw) {
|
|
|
17
17
|
return { ok: false, ledger: { schemaVersion: 2, rows: [] }, note: 'invalid json' };
|
|
18
18
|
}
|
|
19
19
|
const body = parsed;
|
|
20
|
+
if (typeof body.schemaVersion === 'number' && body.schemaVersion > 2) {
|
|
21
|
+
return { ok: false, ledger: { schemaVersion: 2, rows: [] }, note: 'merge-state-forward-only' };
|
|
22
|
+
}
|
|
20
23
|
if (!Array.isArray(body.rows))
|
|
21
24
|
return { ok: false, ledger: { schemaVersion: 2, rows: [] }, note: 'rows missing' };
|
|
22
25
|
const rows = [];
|
|
@@ -3,8 +3,14 @@ import { formatQueue, formatStatus } from "./status.js";
|
|
|
3
3
|
import { mergeUsage } from "./commands.js";
|
|
4
4
|
export async function handleReadOnlyMergeCommand(command, io, home, cards) {
|
|
5
5
|
const withNote = (text, note) => note === undefined ? text : 'note: ' + note + '\n' + text;
|
|
6
|
+
const load = async () => {
|
|
7
|
+
const result = await loadMergeState(io, home);
|
|
8
|
+
if (result.note === 'merge-state-forward-only')
|
|
9
|
+
throw new Error('merge-state-forward-only');
|
|
10
|
+
return result;
|
|
11
|
+
};
|
|
6
12
|
if (command.verb === 'status') {
|
|
7
|
-
const loaded = await
|
|
13
|
+
const loaded = await load();
|
|
8
14
|
if (command.id !== undefined) {
|
|
9
15
|
const row = loaded.state.rows.find(item => item.id === command.id);
|
|
10
16
|
return withNote(row === undefined ? 'merge row not found: ' + command.id : formatStatus([row]), loaded.note);
|
|
@@ -12,18 +18,18 @@ export async function handleReadOnlyMergeCommand(command, io, home, cards) {
|
|
|
12
18
|
return withNote(formatStatus(loaded.state.rows), loaded.note);
|
|
13
19
|
}
|
|
14
20
|
if (command.verb === 'pending') {
|
|
15
|
-
const loaded = await
|
|
21
|
+
const loaded = await load();
|
|
16
22
|
const rows = command.expired === true ? loaded.state.rows.filter(row => row.expired !== undefined) : loaded.state.rows;
|
|
17
23
|
const live = cards === undefined ? rows : rows.filter(row => cards.some(card => card.name === row.a) && cards.some(card => card.name === row.b));
|
|
18
24
|
return withNote(command.expired === true ? formatStatus(live) : formatQueue(live, 'pending'), loaded.note);
|
|
19
25
|
}
|
|
20
26
|
if (command.verb === 'candidates') {
|
|
21
|
-
const loaded = await
|
|
27
|
+
const loaded = await load();
|
|
22
28
|
const rows = command.retry === true ? loaded.state.rows.filter(row => row.state === 'approved') : loaded.state.rows;
|
|
23
29
|
return withNote(formatQueue(rows, command.retry === true ? 'fuse' : 'verify'), loaded.note);
|
|
24
30
|
}
|
|
25
31
|
if (command.verb === 'skipped') {
|
|
26
|
-
const loaded = await
|
|
32
|
+
const loaded = await load();
|
|
27
33
|
return withNote(formatQueue(loaded.state.rows, 'skipped'), loaded.note);
|
|
28
34
|
}
|
|
29
35
|
return null;
|
|
@@ -25,10 +25,14 @@ export async function runResumeCommand(options) {
|
|
|
25
25
|
},
|
|
26
26
|
}),
|
|
27
27
|
...(options.timeoutMinutes === undefined ? {} : { timeoutMinutes: options.timeoutMinutes }),
|
|
28
|
+
...(options.isOwnerActive === undefined ? {} : { isOwnerActive: options.isOwnerActive }),
|
|
28
29
|
});
|
|
29
30
|
}
|
|
30
31
|
if (row.state !== 'fuse' && row.state !== 'approved')
|
|
31
32
|
return { ok: false, message: 'row is not resumable from state ' + row.state };
|
|
33
|
+
if (row.runId !== undefined && (await options.isOwnerActive?.(row.runId)) === true) {
|
|
34
|
+
return { ok: false, message: 'merge run still owns this fuse row: ' + row.runId };
|
|
35
|
+
}
|
|
32
36
|
const decision = row.decision;
|
|
33
37
|
if (decision === undefined)
|
|
34
38
|
return { ok: false, message: 'fuse row has no decision' };
|
package/lib/types/runtime.js
CHANGED
|
@@ -232,9 +232,17 @@ export function createMergeRuntime(deps) {
|
|
|
232
232
|
return { ok: true, text: '已清除合并行:' + cleared.id };
|
|
233
233
|
}
|
|
234
234
|
const loaded = await loadMergeState(deps.io, deps.home);
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
235
|
+
let row = command.id === undefined ? undefined : loaded.state.rows.find(item => item.id === command.id);
|
|
236
|
+
if (command.id === undefined) {
|
|
237
|
+
for (const item of loaded.state.rows) {
|
|
238
|
+
if (item.state !== 'fuse' && item.state !== 'verify' && !(command.retry === true && item.state === 'approved'))
|
|
239
|
+
continue;
|
|
240
|
+
if (item.runId !== undefined && (await deps.isOwnerActive?.(item.runId)) === true)
|
|
241
|
+
continue;
|
|
242
|
+
row = item;
|
|
243
|
+
break;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
238
246
|
if (row === undefined)
|
|
239
247
|
return { ok: false, text: 'merge row not found: ' + (command.id ?? '(auto)') };
|
|
240
248
|
const signal = new AbortController().signal;
|
package/lib/types/state.js
CHANGED
|
@@ -16,7 +16,7 @@ export function mergeStatePath(home) {
|
|
|
16
16
|
function parseState(raw) {
|
|
17
17
|
const parsed = parseLedger(raw);
|
|
18
18
|
if (!parsed.ok)
|
|
19
|
-
return { ok: false, rows: [] };
|
|
19
|
+
return { ok: false, rows: [], ...(parsed.note === undefined ? {} : { note: parsed.note }) };
|
|
20
20
|
return {
|
|
21
21
|
ok: true,
|
|
22
22
|
rows: parsed.ledger.rows,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lmzhen/dsh-evolution-merge",
|
|
3
3
|
"description": "Skill auto-merge domain: screening, two-round authoring, queues and commit orchestration (community build)",
|
|
4
|
-
"version": "0.30.
|
|
4
|
+
"version": "0.30.16",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
"license": "MIT",
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@deepseek-ai/schemastery": "^3.18.5",
|
|
30
|
-
"@lmzhen/dsh-evolution-core": "^0.30.
|
|
31
|
-
"@lmzhen/dsh-evolution-merge-engine": "^0.30.
|
|
30
|
+
"@lmzhen/dsh-evolution-core": "^0.30.16",
|
|
31
|
+
"@lmzhen/dsh-evolution-merge-engine": "^0.30.16"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
|
34
34
|
"@deepseek-ai/cordis": "^4.0.5"
|