@lmzhen/dsh-evolution-merge 0.45.0 → 0.47.0
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 +58 -451
- package/lib/types/index.js +0 -5
- package/lib/types/merge-routes.d.ts +5 -21
- package/lib/types/merge-routes.js +53 -93
- package/lib/types/state.d.ts +1 -37
- package/lib/types/state.js +2 -65
- package/lib/types/surface/merge-view.js +1 -1
- package/package.json +4 -4
- package/lib/types/facts.d.ts +0 -26
- package/lib/types/facts.js +0 -65
- package/lib/types/metrics.d.ts +0 -16
- package/lib/types/metrics.js +0 -27
- package/lib/types/wire-projection.d.ts +0 -36
- package/lib/types/wire-projection.js +0 -77
package/lib/index.js
CHANGED
|
@@ -1273,7 +1273,7 @@ function parseV4State(raw) {
|
|
|
1273
1273
|
* The one merge-state ledger: <home>/merge/merge-state.json.
|
|
1274
1274
|
*
|
|
1275
1275
|
* Reads are pure projections (no write, no reconciliation side effect). Every write goes
|
|
1276
|
-
* through
|
|
1276
|
+
* through pairLedger and a single transactIo, so there is no second file and no
|
|
1277
1277
|
* incremental writer. A row's queue is always derived from its state on read; a hand-edited
|
|
1278
1278
|
* mismatch is repaired by the next write, never by a GET.
|
|
1279
1279
|
*/
|
|
@@ -1357,96 +1357,6 @@ async function loadStateSchema(io, home) {
|
|
|
1357
1357
|
return null;
|
|
1358
1358
|
}
|
|
1359
1359
|
}
|
|
1360
|
-
/** G3-5 runtime write API: only createVerify/createSkipped/transition. v2 writes are rejected. */
|
|
1361
|
-
async function transactRows(_io, _home, _fn) {
|
|
1362
|
-
throw new Error("legacy-writer-removed");
|
|
1363
|
-
}
|
|
1364
|
-
/** The ONE write point. The callback returns the whole row set, not a delta. */
|
|
1365
|
-
async function mutateMergeState(_io, _home, _now, _fn) {
|
|
1366
|
-
throw new Error("legacy-writer-removed");
|
|
1367
|
-
}
|
|
1368
|
-
async function upsertRow(io, home, now, row, expect = "any", cas) {
|
|
1369
|
-
return await mutateMergeState(io, home, now, (rows) => {
|
|
1370
|
-
const index = rows.findIndex((item) => item.pairKey === row.pairKey);
|
|
1371
|
-
const current = index < 0 ? void 0 : rows[index];
|
|
1372
|
-
if (cas !== void 0 && (cas === null && current !== void 0 || cas !== null && current?.updatedAt !== cas)) return {
|
|
1373
|
-
rows,
|
|
1374
|
-
result: {
|
|
1375
|
-
ok: false,
|
|
1376
|
-
current: current ?? row
|
|
1377
|
-
}
|
|
1378
|
-
};
|
|
1379
|
-
if (current !== void 0 && expect !== "any" && (expect === "absent" || queueOf(current.state) !== expect)) return {
|
|
1380
|
-
rows,
|
|
1381
|
-
result: {
|
|
1382
|
-
ok: false,
|
|
1383
|
-
current
|
|
1384
|
-
}
|
|
1385
|
-
};
|
|
1386
|
-
if (current === void 0 && expect !== "any" && expect !== "absent" && expect !== "verify") return {
|
|
1387
|
-
rows,
|
|
1388
|
-
result: {
|
|
1389
|
-
ok: false,
|
|
1390
|
-
current: row
|
|
1391
|
-
}
|
|
1392
|
-
};
|
|
1393
|
-
const normalized = {
|
|
1394
|
-
...row,
|
|
1395
|
-
queue: queueOf(row.state)
|
|
1396
|
-
};
|
|
1397
|
-
const next = [...rows];
|
|
1398
|
-
if (current === void 0) next.push(normalized);
|
|
1399
|
-
else next[index] = {
|
|
1400
|
-
...normalized,
|
|
1401
|
-
createdAt: current.createdAt
|
|
1402
|
-
};
|
|
1403
|
-
return {
|
|
1404
|
-
rows: next,
|
|
1405
|
-
result: { ok: true }
|
|
1406
|
-
};
|
|
1407
|
-
});
|
|
1408
|
-
}
|
|
1409
|
-
async function moveRow(io, home, now, id, patch) {
|
|
1410
|
-
return await mutateMergeState(io, home, now, (rows) => {
|
|
1411
|
-
const index = rows.findIndex((item) => item.id === id);
|
|
1412
|
-
if (index < 0) return {
|
|
1413
|
-
rows,
|
|
1414
|
-
result: void 0
|
|
1415
|
-
};
|
|
1416
|
-
const current = rows[index];
|
|
1417
|
-
const state = patch.state ?? current.state;
|
|
1418
|
-
const next = {
|
|
1419
|
-
...current,
|
|
1420
|
-
state,
|
|
1421
|
-
queue: queueOf(state),
|
|
1422
|
-
updatedAt: new Date(now()).toISOString(),
|
|
1423
|
-
...patch.failure === void 0 ? {} : { failure: patch.failure },
|
|
1424
|
-
...patch.runId === void 0 ? {} : { runId: patch.runId },
|
|
1425
|
-
...patch.unitId === void 0 ? {} : { unitId: patch.unitId },
|
|
1426
|
-
...patch.origin === void 0 ? {} : { origin: patch.origin },
|
|
1427
|
-
...patch.attempts === void 0 ? {} : { attempts: patch.attempts }
|
|
1428
|
-
};
|
|
1429
|
-
const copy = [...rows];
|
|
1430
|
-
copy[index] = next;
|
|
1431
|
-
return {
|
|
1432
|
-
rows: copy,
|
|
1433
|
-
result: next
|
|
1434
|
-
};
|
|
1435
|
-
});
|
|
1436
|
-
}
|
|
1437
|
-
/** G3-5 v3-aware drop: only terminal events. */
|
|
1438
|
-
async function dropRowV3(_io, _home, _id, _event, _unitId = "unknown") {
|
|
1439
|
-
throw new Error("legacy-writer-removed");
|
|
1440
|
-
}
|
|
1441
|
-
async function dropRow(io, home, now, id) {
|
|
1442
|
-
return await mutateMergeState(io, home, now, (rows) => {
|
|
1443
|
-
const next = rows.filter((item) => item.id !== id);
|
|
1444
|
-
return {
|
|
1445
|
-
rows: next,
|
|
1446
|
-
result: next.length !== rows.length
|
|
1447
|
-
};
|
|
1448
|
-
});
|
|
1449
|
-
}
|
|
1450
1360
|
async function rowsOf(io, home, queue) {
|
|
1451
1361
|
const loaded = await loadMergeState(io, home);
|
|
1452
1362
|
return queue === void 0 ? loaded.state.rows : loaded.state.rows.filter((row) => row.queue === queue);
|
|
@@ -2924,7 +2834,7 @@ const emptyCounts = {
|
|
|
2924
2834
|
},
|
|
2925
2835
|
expired: 0
|
|
2926
2836
|
};
|
|
2927
|
-
const queueOf$
|
|
2837
|
+
const queueOf$1 = (state) => state === "approved" || state === "fuse" ? "fuse" : state === "verify" ? "verify" : state === "pending" ? "pending" : "skipped";
|
|
2928
2838
|
async function readMergeSnapshot(options) {
|
|
2929
2839
|
const readAt = (options.now ?? (() => Date.now()))();
|
|
2930
2840
|
const hostOnly = options.hostOnly === void 0 ? void 0 : await options.hostOnly().catch((error) => ({
|
|
@@ -2976,7 +2886,7 @@ async function readMergeSnapshot(options) {
|
|
|
2976
2886
|
const live = options.live !== void 0 && (ledger?.rows ?? []).some((row) => row.state === "pending" && row.expired === void 0 || row.state === "verify" || row.state === "fuse" || row.state === "approved") ? await options.live().catch(() => void 0) : void 0;
|
|
2977
2887
|
for (const row of ledger?.rows ?? []) {
|
|
2978
2888
|
const stage = stages.find((item) => item.rowId === row.id) ?? null;
|
|
2979
|
-
const queue = queueOf$
|
|
2889
|
+
const queue = queueOf$1(row.state);
|
|
2980
2890
|
const bSide = live !== void 0 && live.managed(row.b) ? "live" : "archive";
|
|
2981
2891
|
const bodies = [{
|
|
2982
2892
|
rowId: row.id,
|
|
@@ -4438,7 +4348,7 @@ function verifyState(row) {
|
|
|
4438
4348
|
if (row.row.verifySubState === "screened") return "running";
|
|
4439
4349
|
return "queued";
|
|
4440
4350
|
}
|
|
4441
|
-
function toRowFact
|
|
4351
|
+
function toRowFact(row) {
|
|
4442
4352
|
const state = row.row;
|
|
4443
4353
|
const target = state.state === "pending" || state.state === "approved" || state.state === "fuse" ? {
|
|
4444
4354
|
requested: state.target,
|
|
@@ -4548,7 +4458,7 @@ function runView(run, readAt, includeResultRef = false) {
|
|
|
4548
4458
|
]
|
|
4549
4459
|
};
|
|
4550
4460
|
}
|
|
4551
|
-
function buildFacts
|
|
4461
|
+
function buildFacts(snapshot) {
|
|
4552
4462
|
const ordered = [...snapshot.runs].sort((a, b) => b.record.startedAt - a.record.startedAt);
|
|
4553
4463
|
const active = ordered.find((run) => run.record.state === "running");
|
|
4554
4464
|
const last = ordered.find((run) => run.record.state !== "running");
|
|
@@ -4597,7 +4507,7 @@ function buildQueuePage(snapshot, queue, expiredOnly, cursor, limit = 50) {
|
|
|
4597
4507
|
queue,
|
|
4598
4508
|
expiredOnly,
|
|
4599
4509
|
counts: counts(snapshot.rows),
|
|
4600
|
-
rows: page.map(toRowFact
|
|
4510
|
+
rows: page.map(toRowFact),
|
|
4601
4511
|
...next === void 0 ? {} : { nextCursor: next },
|
|
4602
4512
|
notes: snapshot.notes
|
|
4603
4513
|
};
|
|
@@ -4638,7 +4548,7 @@ function buildRunDetail(snapshot, runId) {
|
|
|
4638
4548
|
pairKey: pair.pairKey,
|
|
4639
4549
|
a: pair.pairKey.split("\0")[0] ?? "",
|
|
4640
4550
|
b: pair.pairKey.split("\0")[1] ?? "",
|
|
4641
|
-
outcome: pair.result === "kept" ? "kept" : pair.result === "failed" ? "failed" : pair.result === "cancelled" ? "cancelled" : "merged",
|
|
4551
|
+
outcome: pair.result === "kept" ? "kept" : pair.result === "failed" ? "failed" : pair.result === "cancelled" ? "cancelled" : pair.result === "undone" ? "undone" : "merged",
|
|
4642
4552
|
...pair.target === void 0 ? {} : { target: { requested: pair.target } }
|
|
4643
4553
|
})),
|
|
4644
4554
|
pairsTruncated: false
|
|
@@ -5621,240 +5531,14 @@ async function recoverCommitUnits(options) {
|
|
|
5621
5531
|
return reports;
|
|
5622
5532
|
}
|
|
5623
5533
|
//#endregion
|
|
5624
|
-
//#region lib/types/facts.js
|
|
5625
|
-
const queueOf$2 = (row) => row.state === "approved" ? "fuse" : row.queue;
|
|
5626
|
-
const isExpired = (row) => row.expired !== void 0;
|
|
5627
|
-
function countsOf(rows) {
|
|
5628
|
-
const active = {
|
|
5629
|
-
verify: 0,
|
|
5630
|
-
pending: 0,
|
|
5631
|
-
fuse: 0,
|
|
5632
|
-
skipped: 0
|
|
5633
|
-
};
|
|
5634
|
-
let expired = 0;
|
|
5635
|
-
for (const row of rows) {
|
|
5636
|
-
if (isExpired(row)) {
|
|
5637
|
-
expired += 1;
|
|
5638
|
-
continue;
|
|
5639
|
-
}
|
|
5640
|
-
active[queueOf$2(row)] += 1;
|
|
5641
|
-
}
|
|
5642
|
-
return {
|
|
5643
|
-
active,
|
|
5644
|
-
expired
|
|
5645
|
-
};
|
|
5646
|
-
}
|
|
5647
|
-
function toRunView(record, readAt, meta = null) {
|
|
5648
|
-
const state = record.state;
|
|
5649
|
-
return {
|
|
5650
|
-
wireVersion: 1,
|
|
5651
|
-
readAt,
|
|
5652
|
-
id: record.id,
|
|
5653
|
-
state,
|
|
5654
|
-
command: record.command ?? "scan",
|
|
5655
|
-
...record.stage === void 0 ? {} : { stage: record.stage },
|
|
5656
|
-
progress: record.progress === void 0 ? null : {
|
|
5657
|
-
done: record.progress.done,
|
|
5658
|
-
total: record.progress.total
|
|
5659
|
-
},
|
|
5660
|
-
startedAt: record.startedAt,
|
|
5661
|
-
...record.endedAt === void 0 ? {} : { endedAt: record.endedAt },
|
|
5662
|
-
...record.failure === void 0 ? {} : { failure: {
|
|
5663
|
-
stage: "settle",
|
|
5664
|
-
code: "run-failed",
|
|
5665
|
-
retryable: false,
|
|
5666
|
-
retryFrom: "none",
|
|
5667
|
-
detail: record.failure
|
|
5668
|
-
} },
|
|
5669
|
-
...record.parentRunId === void 0 ? {} : { parentRunId: record.parentRunId },
|
|
5670
|
-
actions: [
|
|
5671
|
-
{
|
|
5672
|
-
id: "status",
|
|
5673
|
-
command: "/evolution merge status " + record.id,
|
|
5674
|
-
confirm: false,
|
|
5675
|
-
enabled: true
|
|
5676
|
-
},
|
|
5677
|
-
{
|
|
5678
|
-
id: "report",
|
|
5679
|
-
command: "/evolution merge report " + record.id,
|
|
5680
|
-
confirm: false,
|
|
5681
|
-
enabled: record.resultRef !== void 0
|
|
5682
|
-
},
|
|
5683
|
-
{
|
|
5684
|
-
id: "cancel",
|
|
5685
|
-
command: "/evolution merge cancel " + record.id,
|
|
5686
|
-
confirm: false,
|
|
5687
|
-
enabled: state === "running"
|
|
5688
|
-
}
|
|
5689
|
-
]
|
|
5690
|
-
};
|
|
5691
|
-
}
|
|
5692
|
-
function buildFacts(input) {
|
|
5693
|
-
const ordered = [...input.runs].sort((a, b) => b.startedAt - a.startedAt);
|
|
5694
|
-
const active = ordered.find((run) => run.state === "running");
|
|
5695
|
-
const last = ordered.find((run) => run.state !== "running");
|
|
5696
|
-
const notes = input.notes ?? [];
|
|
5697
|
-
return {
|
|
5698
|
-
wireVersion: 1,
|
|
5699
|
-
readAt: input.readAt,
|
|
5700
|
-
approval: { mergeApproval: input.approval },
|
|
5701
|
-
counts: countsOf(input.rows),
|
|
5702
|
-
active: active === void 0 ? null : toRunView(active, input.readAt, input.runMeta?.get(active.id) ?? null),
|
|
5703
|
-
last: last === void 0 ? null : toRunView(last, input.readAt, input.runMeta?.get(last.id) ?? null),
|
|
5704
|
-
startCommands: {
|
|
5705
|
-
scan: "/evolution merge scan",
|
|
5706
|
-
pair: "/evolution merge pair <a> <b>"
|
|
5707
|
-
},
|
|
5708
|
-
fallback: MERGE_COMMAND_SURFACE.fallback,
|
|
5709
|
-
notes,
|
|
5710
|
-
degraded: notes.length > 0
|
|
5711
|
-
};
|
|
5712
|
-
}
|
|
5713
|
-
//#endregion
|
|
5714
|
-
//#region lib/types/wire-projection.js
|
|
5715
|
-
const queueOf$1 = (row) => row.state === "approved" ? "fuse" : row.queue;
|
|
5716
|
-
const expiredOf = (row) => row.expired !== void 0;
|
|
5717
|
-
/** Host-owned row actions; client only renders/copies them. */
|
|
5718
|
-
function actionRefs(row) {
|
|
5719
|
-
const base = "/evolution merge ";
|
|
5720
|
-
const disabled = row.expired === void 0 ? void 0 : "expired";
|
|
5721
|
-
const action = (id, confirm = false, enabled = true) => ({
|
|
5722
|
-
id,
|
|
5723
|
-
command: base + id + " " + row.id,
|
|
5724
|
-
confirm,
|
|
5725
|
-
enabled,
|
|
5726
|
-
...enabled ? {} : { disabledReason: disabled ?? "invalid" }
|
|
5727
|
-
});
|
|
5728
|
-
if (row.state === "pending" && row.expired !== void 0) return [{
|
|
5729
|
-
id: "discard",
|
|
5730
|
-
command: "/evolution merge discard " + row.id,
|
|
5731
|
-
confirm: true,
|
|
5732
|
-
enabled: true
|
|
5733
|
-
}, {
|
|
5734
|
-
id: "pair",
|
|
5735
|
-
command: "/evolution merge pair " + row.a + " " + row.b,
|
|
5736
|
-
confirm: true,
|
|
5737
|
-
enabled: true
|
|
5738
|
-
}];
|
|
5739
|
-
if (row.state === "pending") return [
|
|
5740
|
-
action("approve"),
|
|
5741
|
-
action("reject", true),
|
|
5742
|
-
action("discard", true)
|
|
5743
|
-
];
|
|
5744
|
-
if (row.state === "approved" || row.state === "fuse") {
|
|
5745
|
-
if (row.failure !== void 0 && row.failure.retryable === false) return [{
|
|
5746
|
-
id: "pair",
|
|
5747
|
-
command: "/evolution merge pair " + row.a + " " + row.b,
|
|
5748
|
-
confirm: true,
|
|
5749
|
-
enabled: true
|
|
5750
|
-
}, action("discard", true)];
|
|
5751
|
-
return [
|
|
5752
|
-
{
|
|
5753
|
-
id: "retry-resume",
|
|
5754
|
-
command: "/evolution merge resume --retry " + row.id,
|
|
5755
|
-
confirm: true,
|
|
5756
|
-
enabled: true
|
|
5757
|
-
},
|
|
5758
|
-
action("discard", true),
|
|
5759
|
-
action("status")
|
|
5760
|
-
];
|
|
5761
|
-
}
|
|
5762
|
-
if (row.state === "skipped") return [action("restore", true)];
|
|
5763
|
-
if (row.state === "verify") return [{
|
|
5764
|
-
id: "retry-candidates",
|
|
5765
|
-
command: "/evolution merge candidates --retry " + row.id,
|
|
5766
|
-
confirm: false,
|
|
5767
|
-
enabled: true
|
|
5768
|
-
}];
|
|
5769
|
-
return [action("pair")];
|
|
5770
|
-
}
|
|
5771
|
-
function toRowFact(row, actions = actionRefs(row)) {
|
|
5772
|
-
return {
|
|
5773
|
-
id: row.id,
|
|
5774
|
-
state: row.state,
|
|
5775
|
-
queue: queueOf$1(row),
|
|
5776
|
-
...row.state === "verify" ? { verifySubState: "queued" } : {},
|
|
5777
|
-
a: row.a,
|
|
5778
|
-
b: row.b,
|
|
5779
|
-
...row.target === void 0 ? {} : { target: {
|
|
5780
|
-
requested: row.target.requested,
|
|
5781
|
-
...row.target.actual === void 0 ? {} : { actual: row.target.actual },
|
|
5782
|
-
...row.target.created === void 0 ? {} : { created: row.target.created }
|
|
5783
|
-
} },
|
|
5784
|
-
...row.state === "pending" ? { summary: {
|
|
5785
|
-
a: null,
|
|
5786
|
-
b: null,
|
|
5787
|
-
rationale: row.decision?.rationale ?? null
|
|
5788
|
-
} } : {},
|
|
5789
|
-
...row.reason === void 0 ? {} : { reason: row.reason },
|
|
5790
|
-
...row.state === "skipped" ? { origin: row.origin ?? "system" } : {},
|
|
5791
|
-
...row.failure === void 0 ? {} : { failure: {
|
|
5792
|
-
stage: row.failure.stage === "screening" ? "screening" : row.failure.stage === "decide" ? "decide" : row.failure.stage === "author" ? "author" : row.failure.stage === "validate" ? "validate" : "commit",
|
|
5793
|
-
code: row.failure.code,
|
|
5794
|
-
retryable: row.failure.retryable,
|
|
5795
|
-
retryFrom: row.failure.retryFrom
|
|
5796
|
-
} },
|
|
5797
|
-
...row.stagingRef === void 0 ? {} : { staging: {
|
|
5798
|
-
state: "kept",
|
|
5799
|
-
...row.stagingExpiresAt === void 0 ? {} : { expiresAt: row.stagingExpiresAt }
|
|
5800
|
-
} },
|
|
5801
|
-
...row.expired === void 0 ? {} : { expired: {
|
|
5802
|
-
kind: row.expired,
|
|
5803
|
-
at: Date.parse(row.updatedAt)
|
|
5804
|
-
} },
|
|
5805
|
-
...row.attempts === void 0 ? {} : { attempts: row.attempts },
|
|
5806
|
-
...row.decision?.confidence === void 0 ? {} : { confidence: row.decision.confidence },
|
|
5807
|
-
...row.state === "skipped" && row.stagingExpiresAt !== void 0 ? { expiresAt: row.stagingExpiresAt } : {},
|
|
5808
|
-
createdAt: Date.parse(row.createdAt),
|
|
5809
|
-
updatedAt: Date.parse(row.updatedAt),
|
|
5810
|
-
actions
|
|
5811
|
-
};
|
|
5812
|
-
}
|
|
5813
|
-
function toQueuePage(rows, queue, expiredOnly, readAt, limit = 50) {
|
|
5814
|
-
const filtered = rows.filter((row) => queueOf$1(row) === queue && (expiredOnly ? expiredOf(row) : !expiredOf(row)));
|
|
5815
|
-
const page = filtered.slice(0, Math.max(0, Math.min(200, limit)));
|
|
5816
|
-
return {
|
|
5817
|
-
wireVersion: 1,
|
|
5818
|
-
readAt,
|
|
5819
|
-
queue,
|
|
5820
|
-
expiredOnly,
|
|
5821
|
-
counts: countsOf(rows),
|
|
5822
|
-
rows: page.map((row) => toRowFact(row)),
|
|
5823
|
-
...filtered.length > page.length ? { nextCursor: String(page.length) } : {},
|
|
5824
|
-
notes: []
|
|
5825
|
-
};
|
|
5826
|
-
}
|
|
5827
|
-
function toBodyView(name, side, text, readAt) {
|
|
5828
|
-
return {
|
|
5829
|
-
wireVersion: 1,
|
|
5830
|
-
readAt,
|
|
5831
|
-
name,
|
|
5832
|
-
side,
|
|
5833
|
-
text,
|
|
5834
|
-
markdown: true,
|
|
5835
|
-
truncated: false,
|
|
5836
|
-
totalBytes: Buffer.byteLength(text, "utf8")
|
|
5837
|
-
};
|
|
5838
|
-
}
|
|
5839
|
-
function toHistoryView(items, readAt) {
|
|
5840
|
-
return {
|
|
5841
|
-
wireVersion: 1,
|
|
5842
|
-
readAt,
|
|
5843
|
-
items: items.map((item) => {
|
|
5844
|
-
const parsed = item.archivedAt === null ? null : typeof item.archivedAt === "number" ? item.archivedAt : Date.parse(item.archivedAt);
|
|
5845
|
-
return {
|
|
5846
|
-
name: item.name,
|
|
5847
|
-
kind: item.kind,
|
|
5848
|
-
reason: item.reason,
|
|
5849
|
-
lastVersion: item.lastVersion,
|
|
5850
|
-
archivedAt: parsed === null || Number.isFinite(parsed) ? parsed : null,
|
|
5851
|
-
...item.sourceRunId === void 0 ? {} : { sourceRunId: item.sourceRunId }
|
|
5852
|
-
};
|
|
5853
|
-
})
|
|
5854
|
-
};
|
|
5855
|
-
}
|
|
5856
|
-
//#endregion
|
|
5857
5534
|
//#region lib/types/merge-routes.js
|
|
5535
|
+
/**
|
|
5536
|
+
* Four read-only merge routes: view / rows / body / history.
|
|
5537
|
+
* The host loads one snapshot; these handlers only project wire envelopes.
|
|
5538
|
+
* There is no second (legacy rows/runs/history) source: the production constructor has
|
|
5539
|
+
* always provided the snapshot, and the legacy branches were the only consumers of
|
|
5540
|
+
* facts.ts / wire-projection.ts (W11 D2b).
|
|
5541
|
+
*/
|
|
5858
5542
|
const MERGE_PATHS = HOST_ROUTES.merge;
|
|
5859
5543
|
const MERGE_BASE = MERGE_PATHS.view.slice(0, -4);
|
|
5860
5544
|
const MERGE_ROUTES = {
|
|
@@ -5870,21 +5554,16 @@ function makeMergeRoutes(deps, _audit) {
|
|
|
5870
5554
|
code: "E-325",
|
|
5871
5555
|
message: "merge service is not mounted"
|
|
5872
5556
|
});
|
|
5873
|
-
const blocked = (
|
|
5557
|
+
const blocked = (snapshot) => snapshot.blocked === void 0 ? null : json(503, {
|
|
5874
5558
|
wireVersion: 1,
|
|
5875
5559
|
code: "merge-state-blocked",
|
|
5876
|
-
readiness
|
|
5560
|
+
readiness: snapshot.blocked.readiness
|
|
5877
5561
|
});
|
|
5878
5562
|
const hostOnly = (snapshot) => snapshot.hostOnly === void 0 ? null : json(503, {
|
|
5879
5563
|
wireVersion: 1,
|
|
5880
5564
|
code: "E-323",
|
|
5881
5565
|
message: snapshot.hostOnly.detail ?? "host data plane unavailable"
|
|
5882
5566
|
});
|
|
5883
|
-
const notReady = async (source) => {
|
|
5884
|
-
if (source.readiness === void 0) return null;
|
|
5885
|
-
const readiness = await source.readiness();
|
|
5886
|
-
return readiness.ok ? null : blocked(readiness);
|
|
5887
|
-
};
|
|
5888
5567
|
const bad = (message) => json(400, {
|
|
5889
5568
|
wireVersion: 1,
|
|
5890
5569
|
code: "merge-bad-query",
|
|
@@ -5892,6 +5571,11 @@ function makeMergeRoutes(deps, _audit) {
|
|
|
5892
5571
|
});
|
|
5893
5572
|
const get = (request) => request.method === "GET" ? null : methodNotAllowed(["GET"]);
|
|
5894
5573
|
const url = (request) => new URL(request.url, "http://local");
|
|
5574
|
+
const snapshotOf = async () => {
|
|
5575
|
+
const source = deps.getSource();
|
|
5576
|
+
return source === void 0 ? null : await source.snapshot();
|
|
5577
|
+
};
|
|
5578
|
+
const unavailable = (snapshot) => snapshot === null ? absent() : blocked(snapshot) ?? hostOnly(snapshot);
|
|
5895
5579
|
return [
|
|
5896
5580
|
{
|
|
5897
5581
|
path: MERGE_ROUTES.view,
|
|
@@ -5900,28 +5584,10 @@ function makeMergeRoutes(deps, _audit) {
|
|
|
5900
5584
|
fetch: async (request) => {
|
|
5901
5585
|
const denied = get(request);
|
|
5902
5586
|
if (denied !== null) return denied;
|
|
5903
|
-
const
|
|
5904
|
-
|
|
5905
|
-
if (
|
|
5906
|
-
|
|
5907
|
-
if (snapshot.blocked !== void 0) return json(503, {
|
|
5908
|
-
wireVersion: 1,
|
|
5909
|
-
code: "merge-state-blocked",
|
|
5910
|
-
readiness: snapshot.blocked.readiness
|
|
5911
|
-
});
|
|
5912
|
-
const capability = hostOnly(snapshot);
|
|
5913
|
-
if (capability !== null) return capability;
|
|
5914
|
-
return json(200, buildFacts$1(snapshot));
|
|
5915
|
-
}
|
|
5916
|
-
const readiness = await notReady(source);
|
|
5917
|
-
if (readiness !== null) return readiness;
|
|
5918
|
-
const readAt = Date.now();
|
|
5919
|
-
return json(200, buildFacts({
|
|
5920
|
-
rows: await source.rows?.() ?? [],
|
|
5921
|
-
runs: await source.runs?.(void 0, 20) ?? [],
|
|
5922
|
-
approval: source.approval?.() === true,
|
|
5923
|
-
readAt
|
|
5924
|
-
}));
|
|
5587
|
+
const snapshot = await snapshotOf();
|
|
5588
|
+
const notReady = unavailable(snapshot);
|
|
5589
|
+
if (notReady !== null) return notReady;
|
|
5590
|
+
return json(200, buildFacts(snapshot));
|
|
5925
5591
|
}
|
|
5926
5592
|
},
|
|
5927
5593
|
{
|
|
@@ -5931,37 +5597,20 @@ function makeMergeRoutes(deps, _audit) {
|
|
|
5931
5597
|
fetch: async (request) => {
|
|
5932
5598
|
const denied = get(request);
|
|
5933
5599
|
if (denied !== null) return denied;
|
|
5934
|
-
const source = deps.getSource();
|
|
5935
|
-
if (source === void 0) return absent();
|
|
5936
5600
|
const query = url(request).searchParams;
|
|
5937
5601
|
const queue = query.get("queue") ?? "verify";
|
|
5938
5602
|
if (queue !== "verify" && queue !== "pending" && queue !== "fuse" && queue !== "skipped") return bad("queue must be verify/pending/fuse/skipped");
|
|
5939
5603
|
const expiredOnly = query.get("expired") === "1";
|
|
5940
5604
|
if (expiredOnly && queue !== "pending") return bad("expired is only allowed for pending");
|
|
5941
5605
|
const limit = Number.parseInt(query.get("limit") ?? "50", 10);
|
|
5942
|
-
|
|
5943
|
-
|
|
5944
|
-
|
|
5945
|
-
|
|
5946
|
-
|
|
5947
|
-
|
|
5948
|
-
|
|
5949
|
-
const capability = hostOnly(snapshot);
|
|
5950
|
-
if (capability !== null) return capability;
|
|
5951
|
-
try {
|
|
5952
|
-
return json(200, buildQueuePage(snapshot, queue, expiredOnly, query.get("cursor") ?? void 0, Number.isFinite(limit) ? limit : 50));
|
|
5953
|
-
} catch (error) {
|
|
5954
|
-
return bad(error instanceof Error ? error.message : "queue cursor is stale");
|
|
5955
|
-
}
|
|
5606
|
+
const snapshot = await snapshotOf();
|
|
5607
|
+
const notReady = unavailable(snapshot);
|
|
5608
|
+
if (notReady !== null) return notReady;
|
|
5609
|
+
try {
|
|
5610
|
+
return json(200, buildQueuePage(snapshot, queue, expiredOnly, query.get("cursor") ?? void 0, Number.isFinite(limit) ? limit : 50));
|
|
5611
|
+
} catch (error) {
|
|
5612
|
+
return bad(error instanceof Error ? error.message : "queue cursor is stale");
|
|
5956
5613
|
}
|
|
5957
|
-
const readiness = await notReady(source);
|
|
5958
|
-
if (readiness !== null) return readiness;
|
|
5959
|
-
const offset = Number.parseInt(query.get("cursor") ?? "0", 10);
|
|
5960
|
-
const page = toQueuePage(await source.rows?.() ?? [], queue, expiredOnly, Date.now(), Number.isFinite(limit) ? limit : 50);
|
|
5961
|
-
return json(200, Number.isFinite(offset) && offset > 0 ? {
|
|
5962
|
-
...page,
|
|
5963
|
-
rows: page.rows.slice(offset)
|
|
5964
|
-
} : page);
|
|
5965
5614
|
}
|
|
5966
5615
|
},
|
|
5967
5616
|
{
|
|
@@ -5982,39 +5631,25 @@ function makeMergeRoutes(deps, _audit) {
|
|
|
5982
5631
|
code: "merge-body-not-found",
|
|
5983
5632
|
message: "merge body requires id or name"
|
|
5984
5633
|
});
|
|
5985
|
-
|
|
5986
|
-
|
|
5987
|
-
|
|
5988
|
-
|
|
5989
|
-
|
|
5990
|
-
|
|
5991
|
-
|
|
5992
|
-
|
|
5993
|
-
|
|
5994
|
-
|
|
5995
|
-
|
|
5996
|
-
|
|
5997
|
-
|
|
5998
|
-
});
|
|
5999
|
-
if (refs.length > 1) return bad("merge body is ambiguous; pass id, name and side");
|
|
6000
|
-
const row = snapshot.rows.find((item) => item.row.id === refs[0].rowId);
|
|
6001
|
-
if (row?.stage?.state === "lost" || row?.stage?.state === "expired") return json(404, {
|
|
6002
|
-
wireVersion: 1,
|
|
6003
|
-
code: "merge-body-not-found",
|
|
6004
|
-
message: "merge stage is lost"
|
|
6005
|
-
});
|
|
6006
|
-
const ref = refs[0];
|
|
6007
|
-
return json(200, buildBodyView(snapshot, ref, (source.bodyRef === void 0 ? null : await source.bodyRef(ref)) ?? ""));
|
|
6008
|
-
}
|
|
6009
|
-
const readiness = await notReady(source);
|
|
6010
|
-
if (readiness !== null) return readiness;
|
|
6011
|
-
if (id === null || id === "" || side !== "a" && side !== "b") return bad("id and side=a|b are required");
|
|
6012
|
-
const content = await source.body?.(id, side) ?? null;
|
|
6013
|
-
return content === null ? json(200, {
|
|
5634
|
+
const snapshot = await source.snapshot();
|
|
5635
|
+
const notReady = blocked(snapshot);
|
|
5636
|
+
if (notReady !== null) return notReady;
|
|
5637
|
+
const sideFilter = side === "a" ? "live" : side === "b" ? "archive" : side === "live" || side === "archive" ? side : void 0;
|
|
5638
|
+
const refs = snapshot.bodyRefs.filter((ref) => (id === null || id === "" || ref.rowId === id) && (name === null || name === "" || ref.name === name) && (sideFilter === void 0 || ref.side === sideFilter));
|
|
5639
|
+
if (refs.length === 0) return json(404, {
|
|
5640
|
+
wireVersion: 1,
|
|
5641
|
+
code: "merge-body-not-found",
|
|
5642
|
+
message: "merge body not found"
|
|
5643
|
+
});
|
|
5644
|
+
if (refs.length > 1) return bad("merge body is ambiguous; pass id, name and side");
|
|
5645
|
+
const row = snapshot.rows.find((item) => item.row.id === refs[0].rowId);
|
|
5646
|
+
if (row?.stage?.state === "lost" || row?.stage?.state === "expired") return json(404, {
|
|
6014
5647
|
wireVersion: 1,
|
|
6015
|
-
code: "merge-body-
|
|
6016
|
-
message: "merge
|
|
6017
|
-
})
|
|
5648
|
+
code: "merge-body-not-found",
|
|
5649
|
+
message: "merge stage is lost"
|
|
5650
|
+
});
|
|
5651
|
+
const ref = refs[0];
|
|
5652
|
+
return json(200, buildBodyView(snapshot, ref, (source.bodyRef === void 0 ? null : await source.bodyRef(ref)) ?? ""));
|
|
6018
5653
|
}
|
|
6019
5654
|
},
|
|
6020
5655
|
{
|
|
@@ -6024,20 +5659,11 @@ function makeMergeRoutes(deps, _audit) {
|
|
|
6024
5659
|
fetch: async (request) => {
|
|
6025
5660
|
const denied = get(request);
|
|
6026
5661
|
if (denied !== null) return denied;
|
|
6027
|
-
const
|
|
6028
|
-
if (
|
|
6029
|
-
|
|
6030
|
-
|
|
6031
|
-
|
|
6032
|
-
wireVersion: 1,
|
|
6033
|
-
code: "merge-state-blocked",
|
|
6034
|
-
readiness: snapshot.blocked.readiness
|
|
6035
|
-
});
|
|
6036
|
-
return json(200, buildHistoryView(snapshot));
|
|
6037
|
-
}
|
|
6038
|
-
const readiness = await notReady(source);
|
|
6039
|
-
if (readiness !== null) return readiness;
|
|
6040
|
-
return json(200, toHistoryView(await source.history?.() ?? [], Date.now()));
|
|
5662
|
+
const snapshot = await snapshotOf();
|
|
5663
|
+
if (snapshot === null) return absent();
|
|
5664
|
+
const notReady = blocked(snapshot);
|
|
5665
|
+
if (notReady !== null) return notReady;
|
|
5666
|
+
return json(200, buildHistoryView(snapshot));
|
|
6041
5667
|
}
|
|
6042
5668
|
},
|
|
6043
5669
|
{
|
|
@@ -6351,13 +5977,13 @@ async function handleReadOnlyMergeCommand(command, io, home, cards, runs, approv
|
|
|
6351
5977
|
...live === void 0 ? {} : { live }
|
|
6352
5978
|
});
|
|
6353
5979
|
if (snapshot.blocked !== void 0) throw new Error(snapshot.blocked.code + ": " + snapshot.blocked.message);
|
|
6354
|
-
const rows = snapshot.rows.map(toRowFact
|
|
5980
|
+
const rows = snapshot.rows.map(toRowFact);
|
|
6355
5981
|
if (command.verb === "status") {
|
|
6356
5982
|
if (command.id !== void 0) {
|
|
6357
5983
|
const row = rows.find((item) => item.id === command.id);
|
|
6358
5984
|
return row === void 0 ? "merge row not found: " + command.id : formatSnapshotStatus([row]);
|
|
6359
5985
|
}
|
|
6360
|
-
return formatFacts(buildFacts
|
|
5986
|
+
return formatFacts(buildFacts(snapshot));
|
|
6361
5987
|
}
|
|
6362
5988
|
if (command.verb === "pending") {
|
|
6363
5989
|
const live = command.expired === true ? rows.filter((row) => row.expired !== void 0) : rows.filter((row) => row.queue === "pending" && row.expired === void 0);
|
|
@@ -11674,25 +11300,6 @@ function apply(ctx, rawConfig = {}) {
|
|
|
11674
11300
|
},
|
|
11675
11301
|
async bodyRef(ref) {
|
|
11676
11302
|
return await resolveBody(io, home, ref, async () => ref.side === "archive" ? await skills.readArchived(ref.name) : await skills.read(ref.name));
|
|
11677
|
-
},
|
|
11678
|
-
approval() {
|
|
11679
|
-
return getParams().mergeApproval;
|
|
11680
|
-
},
|
|
11681
|
-
readiness() {
|
|
11682
|
-
return ready;
|
|
11683
|
-
},
|
|
11684
|
-
commands() {
|
|
11685
|
-
return [
|
|
11686
|
-
"merge scan",
|
|
11687
|
-
"merge doctor",
|
|
11688
|
-
"merge status",
|
|
11689
|
-
"merge pending",
|
|
11690
|
-
"merge skipped",
|
|
11691
|
-
"merge report",
|
|
11692
|
-
"merge runs",
|
|
11693
|
-
"merge cancel",
|
|
11694
|
-
"merge reconcile"
|
|
11695
|
-
];
|
|
11696
11303
|
}
|
|
11697
11304
|
};
|
|
11698
11305
|
doctorFact = async () => {
|
|
@@ -11779,4 +11386,4 @@ function apply(ctx, rawConfig = {}) {
|
|
|
11779
11386
|
});
|
|
11780
11387
|
}
|
|
11781
11388
|
//#endregion
|
|
11782
|
-
export { Config, MERGE_DOCTOR_SCHEMA_VERSION, MERGE_LIFECYCLE_VERBS, MERGE_MAX_ATTEMPTS, MERGE_PAIR_STATES, MERGE_PARAM_DEFAULTS, MERGE_PROMPT_VERSION, MERGE_QUEUES, MERGE_ROUTES, MERGE_STAGE_TOOL_NAME, MERGE_STATE_VERSION, STAGING_SCHEMA_VERSION, STANDBY_PROMPT, StageToolRegistry, apply, applyStageTool, approvePending, assembleStagedCommit, buildCommitPlan, buildRound1Prompt, buildRound2Prompt, buildStandbyPrompt, busyTarget, canRetry, cleanupExpiredStaging, commitReceiptPath, commitStagedRun, committedPairs, configureMergePresentation, copyStagedFile, countRows, createChannelScanPorts, createEngineRunner, createEngineScreening, createMergeCommand, createMergeRuntime, createMergeStageTool, createNewChildRound2, createReadOnlyMergeService, createStageForCards, createStaging,
|
|
11389
|
+
export { Config, MERGE_DOCTOR_SCHEMA_VERSION, MERGE_LIFECYCLE_VERBS, MERGE_MAX_ATTEMPTS, MERGE_PAIR_STATES, MERGE_PARAM_DEFAULTS, MERGE_PROMPT_VERSION, MERGE_QUEUES, MERGE_ROUTES, MERGE_STAGE_TOOL_NAME, MERGE_STATE_VERSION, STAGING_SCHEMA_VERSION, STANDBY_PROMPT, StageToolRegistry, apply, applyStageTool, approvePending, assembleStagedCommit, buildCommitPlan, buildRound1Prompt, buildRound2Prompt, buildStandbyPrompt, busyTarget, canRetry, cleanupExpiredStaging, commitReceiptPath, commitStagedRun, committedPairs, configureMergePresentation, copyStagedFile, countRows, createChannelScanPorts, createEngineRunner, createEngineScreening, createMergeCommand, createMergeRuntime, createMergeStageTool, createNewChildRound2, createReadOnlyMergeService, createStageForCards, createStaging, dropStaging, durableReceiptDir, durableReceiptPath, emptyMergeState, engineConfigFromRoot, ensureStaging, forcedDecisionFor, formatFacts, formatQueue, formatRunDetail, formatRunsView, formatSnapshotQueue, formatSnapshotStatus, formatStatus, handleReadOnlyMergeCommand, hasBlockingFinding, inject, isSkippedPair, listStagedFiles, liveRowFactsOf, loadMergeState, loadStateSchema, makeMergeRoutes, manifestFilesOf, mergeCommandHelp, mergeDoctor, mergeDoctorAvailability, mergeDoctorFact, mergeReportDigestPath, mergeReportPath, mergeRunIdsToSupersede, mergeStatePath, mergeUsage, missingManifestFile, pairKey, parseAuthoringManifest, parseDecision, parseMergeCommand, pendingExpiry, persistedExpiry, promptHashOf, queueOf, readCommitReceipt, readCommitReceipts, readMergeReport, readStagedFile, readStagedTree, readStaging, recordRound2Outcome, rejectPending, resolveMergeParams, resolveTargetName, retryMergeReport, rewriteFrontmatterName, rowIdOf, rowsOf, runApproveCommand, runAuthoring, runMergeCommand, runNewChildAuthoring, runPairCommand, runResumeCommand, runRound1OverChannel, runScan, runScanCommand, setStagingTarget, skillLibraryPort, skillLibraryUndoPort, skippedPairKeys, snapshotCards, sourceBlock, stageKeyOf, stageOf, stagingRoot, subagentChannelAdapter, supersedeMergeRuns, transitionLegacyForProjection, undoMergeReceipt, unitFor, validateStagedTree, withMergeRun, writeCommitReceipt, writeMergeReport, writeStagedFile };
|
package/lib/types/index.js
CHANGED
|
@@ -331,11 +331,6 @@ export function apply(ctx, rawConfig = {}) {
|
|
|
331
331
|
} });
|
|
332
332
|
},
|
|
333
333
|
async bodyRef(ref) { return await resolveBody(io, home, ref, async () => ref.side === 'archive' ? await skills.readArchived(ref.name) : await skills.read(ref.name)); },
|
|
334
|
-
approval() { return getParams().mergeApproval; },
|
|
335
|
-
readiness() { return ready; },
|
|
336
|
-
commands() {
|
|
337
|
-
return ['merge scan', 'merge doctor', 'merge status', 'merge pending', 'merge skipped', 'merge report', 'merge runs', 'merge cancel', 'merge reconcile'];
|
|
338
|
-
},
|
|
339
334
|
};
|
|
340
335
|
doctorFact = async () => {
|
|
341
336
|
const current = source;
|