@lmzhen/dsh-evolution-merge 0.47.0 → 0.48.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.
Files changed (73) hide show
  1. package/lib/index.js +175 -758
  2. package/lib/types/adapters/engine-screen.d.ts +0 -3
  3. package/lib/types/authoring-flow.d.ts +5 -0
  4. package/lib/types/authoring-flow.js +17 -10
  5. package/lib/types/commit-execute.js +1 -22
  6. package/lib/types/contracts.d.ts +0 -1
  7. package/lib/types/contracts.js +0 -1
  8. package/lib/types/doctor.d.ts +0 -1
  9. package/lib/types/doctor.js +2 -31
  10. package/lib/types/domain/consistency.d.ts +0 -1
  11. package/lib/types/domain/consistency.js +2 -11
  12. package/lib/types/domain/merge-limits.d.ts +0 -10
  13. package/lib/types/domain/merge-limits.js +0 -3
  14. package/lib/types/domain/merge-snapshot.js +4 -6
  15. package/lib/types/domain/pair-ledger.d.ts +0 -1
  16. package/lib/types/domain/row-v3.d.ts +0 -45
  17. package/lib/types/domain/row-v3.js +0 -68
  18. package/lib/types/domain/row.d.ts +2 -84
  19. package/lib/types/domain/row.js +1 -110
  20. package/lib/types/domain/run-coordinator.d.ts +0 -24
  21. package/lib/types/domain/run-coordinator.js +0 -1
  22. package/lib/types/domain/stage-aggregate.d.ts +0 -42
  23. package/lib/types/domain/stage-aggregate.js +1 -116
  24. package/lib/types/domain/state.d.ts +1 -53
  25. package/lib/types/domain/state.js +0 -55
  26. package/lib/types/domain/undo-journal.d.ts +4 -4
  27. package/lib/types/domain/undo-journal.js +5 -7
  28. package/lib/types/index.d.ts +0 -1
  29. package/lib/types/index.js +0 -1
  30. package/lib/types/new-child-authoring.js +4 -10
  31. package/lib/types/prompts.d.ts +0 -1
  32. package/lib/types/prompts.js +0 -1
  33. package/lib/types/read-commands.d.ts +0 -1
  34. package/lib/types/read-commands.js +0 -4
  35. package/lib/types/recovery-projection.js +0 -3
  36. package/lib/types/round2-outcome.js +15 -37
  37. package/lib/types/scan-run.js +0 -3
  38. package/lib/types/skipped.d.ts +1 -2
  39. package/lib/types/skipped.js +0 -8
  40. package/lib/types/staging.d.ts +0 -2
  41. package/lib/types/staging.js +0 -9
  42. package/lib/types/state.d.ts +0 -2
  43. package/lib/types/state.js +0 -13
  44. package/lib/types/surface/merge-view.d.ts +1 -2
  45. package/lib/types/surface/merge-view.js +0 -1
  46. package/lib/types/undo-operation.js +0 -9
  47. package/lib/types/unit-protocol.d.ts +6 -0
  48. package/lib/types/unit-protocol.js +72 -102
  49. package/package.json +4 -4
  50. package/lib/types/commit-recovery.d.ts +0 -14
  51. package/lib/types/commit-recovery.js +0 -96
  52. package/lib/types/coordinator.d.ts +0 -77
  53. package/lib/types/coordinator.js +0 -137
  54. package/lib/types/domain/commit-journal-store.d.ts +0 -6
  55. package/lib/types/domain/commit-journal-store.js +0 -26
  56. package/lib/types/domain/commit-journal.d.ts +0 -16
  57. package/lib/types/domain/commit-journal.js +0 -26
  58. package/lib/types/domain/indexes.d.ts +0 -21
  59. package/lib/types/domain/indexes.js +0 -15
  60. package/lib/types/domain/merge-report.d.ts +0 -41
  61. package/lib/types/domain/merge-report.js +0 -2
  62. package/lib/types/domain/pair-index-store.d.ts +0 -6
  63. package/lib/types/domain/pair-index-store.js +0 -25
  64. package/lib/types/domain/pair-index.d.ts +0 -9
  65. package/lib/types/domain/pair-index.js +0 -28
  66. package/lib/types/domain/resolve-pair.d.ts +0 -4
  67. package/lib/types/domain/resolve-pair.js +0 -4
  68. package/lib/types/domain/row-tx.d.ts +0 -27
  69. package/lib/types/domain/row-tx.js +0 -31
  70. package/lib/types/domain/run-record.d.ts +0 -45
  71. package/lib/types/domain/run-record.js +0 -24
  72. package/lib/types/domain/state-v3.d.ts +0 -4
  73. package/lib/types/domain/state-v3.js +0 -4
@@ -1,96 +0,0 @@
1
- /** Startup replay for non-terminal commit journals: report only, never write skills. */
2
- import { join } from 'node:path';
3
- import { writeJournal } from "./domain/commit-journal-store.js";
4
- import { readCommitReceipt } from "./commit-receipt.js";
5
- import { readUnitEvidence } from '@lmzhen/dsh-evolution-core/write';
6
- export async function recoverCommitJournals(io, home, now, isActive) {
7
- const dir = join(home, 'merge', 'journals');
8
- const reports = [];
9
- let files = [];
10
- if (await io.exists(dir)) {
11
- try {
12
- files = (await io.list(dir)).filter(name => name.endsWith('.json'));
13
- }
14
- catch {
15
- reports.push({ runId: '(list)', phase: 'unknown', action: 'journal-list-failed', ok: false, journalPath: dir });
16
- }
17
- }
18
- for (const file of files) {
19
- const path = join(dir, file);
20
- try {
21
- let journal;
22
- try {
23
- journal = JSON.parse(await io.readText(path) ?? '');
24
- }
25
- catch {
26
- reports.push({ runId: file.replace(/\.json$/, ''), phase: 'unknown', action: 'journal-unreadable', ok: false, journalPath: path });
27
- continue;
28
- }
29
- if (isActive?.(journal.runId) === true) {
30
- reports.push({ runId: journal.runId, phase: journal.phase, action: 'skipped-active-run', ok: true, target: journal.target, sources: journal.sources, journalPath: path });
31
- continue;
32
- }
33
- let receipt = null;
34
- try {
35
- receipt = await readCommitReceipt(io, home, journal.runId, journal.target);
36
- }
37
- catch {
38
- reports.push({ runId: journal.runId, phase: journal.phase, action: 'receipt-read-failed', ok: false, target: journal.target, sources: journal.sources, journalPath: path });
39
- continue;
40
- }
41
- if (receipt !== null) {
42
- await writeJournal(io, home, { ...journal, phase: 'committed', unitId: receipt.unitId, updatedAt: new Date(now).toISOString() });
43
- reports.push({ runId: journal.runId, phase: journal.phase, action: 'receipt-committed', ok: true, target: journal.target, sources: journal.sources, journalPath: path, unitId: receipt.unitId });
44
- continue;
45
- }
46
- if (journal.phase === 'committed') {
47
- reports.push({ runId: journal.runId, phase: journal.phase, action: 'receipt-missing', ok: false, target: journal.target, sources: journal.sources, journalPath: path });
48
- continue;
49
- }
50
- if (journal.phase === 'failed' || journal.phase === 'rolled-back')
51
- continue;
52
- reports.push({
53
- runId: journal.runId, phase: journal.phase, action: 'manual-required', ok: false,
54
- target: journal.target, sources: journal.sources, journalPath: path,
55
- });
56
- }
57
- catch (error) {
58
- reports.push({ runId: file.replace(/\.json$/, ''), phase: 'unknown', action: 'recovery-error: ' + (error instanceof Error ? error.message : String(error)), ok: false, journalPath: path });
59
- }
60
- }
61
- const unitDir = join(home, 'merge', 'unit-journals');
62
- if (await io.exists(unitDir)) {
63
- let unitFiles = [];
64
- try {
65
- unitFiles = (await io.list(unitDir)).filter(name => name.endsWith('.json'));
66
- }
67
- catch { /* no unit journals */ }
68
- for (const file of unitFiles) {
69
- const path = join(unitDir, file);
70
- try {
71
- const journal = JSON.parse(await io.readText(path) ?? '');
72
- const evidence = await readUnitEvidence(io, home, journal.unitId);
73
- if (evidence !== null) {
74
- reports.push({ runId: journal.runId, phase: 'committed', action: 'unit-committed', ok: true, target: journal.target, sources: journal.sources, journalPath: path, unitId: journal.unitId });
75
- continue;
76
- }
77
- if (journal.phase === 'committed') {
78
- reports.push({ runId: journal.runId, phase: 'committed', action: 'unit-evidence-missing', ok: false, target: journal.target, sources: journal.sources, journalPath: path, unitId: journal.unitId });
79
- continue;
80
- }
81
- if (journal.phase === 'failed' || journal.phase === 'rolled-back')
82
- continue;
83
- reports.push({ runId: journal.runId, phase: journal.phase, action: 'unit-manual-required', ok: false, target: journal.target, sources: journal.sources, journalPath: path, unitId: journal.unitId });
84
- }
85
- catch {
86
- reports.push({ runId: '(unit)', phase: 'unknown', action: 'unit-journal-unreadable', ok: false, journalPath: path });
87
- }
88
- }
89
- }
90
- try {
91
- await io.writeText(join(home, 'merge', 'recovery.json'), JSON.stringify(reports, null, 2));
92
- }
93
- catch { /* report file is best-effort; reports are still returned */ }
94
- return reports;
95
- }
96
- //# sourceMappingURL=commit-recovery.js.map
@@ -1,77 +0,0 @@
1
- /**
2
- * Pure merge transition table. No io, no run shell, no subagents.
3
- *
4
- * Every transition returns the whole next row (or a drop), so the caller can persist it
5
- * through one state transaction. Invalid transitions are refused by name;
6
- * a caller never "repairs" a row by guessing which state the operator meant.
7
- */
8
- import { type MergeDecision, type MergeFailure, type MergeRow } from './contracts.ts';
9
- export type MergeEvent = {
10
- readonly type: 'candidate';
11
- readonly a: string;
12
- readonly b: string;
13
- readonly at: string;
14
- } | {
15
- readonly type: 'round1-keep';
16
- readonly at: string;
17
- } | {
18
- readonly type: 'round1-merge';
19
- readonly approval: 'on' | 'off';
20
- readonly decision?: MergeDecision;
21
- readonly stagingRef?: string;
22
- readonly stagingExpiresAt?: number;
23
- readonly sourceRevision?: string;
24
- readonly targetRevision?: string;
25
- readonly at: string;
26
- } | {
27
- readonly type: 'round1-fail';
28
- readonly failure: MergeFailure;
29
- readonly at: string;
30
- } | {
31
- readonly type: 'approve';
32
- readonly runId?: string;
33
- readonly at: string;
34
- } | {
35
- readonly type: 'reject';
36
- readonly at: string;
37
- } | {
38
- readonly type: 'round2-fail';
39
- readonly failure: MergeFailure;
40
- readonly at: string;
41
- } | {
42
- readonly type: 'round2-cancel';
43
- readonly at: string;
44
- } | {
45
- readonly type: 'round2-success';
46
- readonly unitId?: string;
47
- readonly at: string;
48
- } | {
49
- readonly type: 'restore';
50
- readonly at: string;
51
- } | {
52
- readonly type: 'source-gone';
53
- readonly at: string;
54
- } | {
55
- readonly type: 'target-taken';
56
- readonly at: string;
57
- } | {
58
- readonly type: 'source-changed';
59
- readonly at: string;
60
- } | {
61
- readonly type: 'gate-keep';
62
- readonly a: string;
63
- readonly b: string;
64
- readonly reason?: string;
65
- readonly at: string;
66
- };
67
- export type TransitionResult = {
68
- readonly ok: true;
69
- readonly row: MergeRow | null;
70
- } | {
71
- readonly ok: false;
72
- readonly code: 'invalid-transition';
73
- readonly message: string;
74
- };
75
- /** Legacy v2 projection only; runtime writes must use transitionV3/RowTx. */
76
- export declare function transitionLegacyForProjection(current: MergeRow | undefined, event: MergeEvent): TransitionResult;
77
- //# sourceMappingURL=coordinator.d.ts.map
@@ -1,137 +0,0 @@
1
- /**
2
- * Pure merge transition table. No io, no run shell, no subagents.
3
- *
4
- * Every transition returns the whole next row (or a drop), so the caller can persist it
5
- * through one state transaction. Invalid transitions are refused by name;
6
- * a caller never "repairs" a row by guessing which state the operator meant.
7
- */
8
- import { pairKey, queueOf, rowIdOf, } from "./contracts.js";
9
- function invalid(event, state) {
10
- return {
11
- ok: false,
12
- code: 'invalid-transition',
13
- message: 'cannot apply ' + event.type + ' to ' + (state ?? 'no row'),
14
- };
15
- }
16
- /** Drop fields that must not survive a transition; optional fields stay absent. */
17
- function base(row, at) {
18
- return {
19
- id: row.id,
20
- pairKey: row.pairKey,
21
- a: row.a,
22
- b: row.b,
23
- state: row.state,
24
- queue: row.queue,
25
- createdAt: row.createdAt,
26
- updatedAt: at,
27
- ...(row.runId === undefined ? {} : { runId: row.runId }),
28
- ...(row.unitId === undefined ? {} : { unitId: row.unitId }),
29
- ...(row.origin === undefined ? {} : { origin: row.origin }),
30
- ...(row.decision === undefined ? {} : { decision: row.decision }),
31
- ...(row.sourceRevision === undefined ? {} : { sourceRevision: row.sourceRevision }),
32
- ...(row.targetRevision === undefined ? {} : { targetRevision: row.targetRevision }),
33
- ...(row.attempts === undefined ? {} : { attempts: row.attempts }),
34
- ...(row.stagingRef === undefined ? {} : { stagingRef: row.stagingRef }),
35
- ...(row.stagingExpiresAt === undefined ? {} : { stagingExpiresAt: row.stagingExpiresAt }),
36
- ...(row.expired === undefined ? {} : { expired: row.expired }),
37
- ...(row.reason === undefined ? {} : { reason: row.reason }),
38
- ...(row.target === undefined ? {} : { target: row.target }),
39
- };
40
- }
41
- function next(row, at, state, patch = {}) {
42
- return {
43
- ok: true,
44
- row: {
45
- ...base(row, at),
46
- state,
47
- queue: queueOf(state),
48
- ...patch,
49
- },
50
- };
51
- }
52
- /** Legacy v2 projection only; runtime writes must use transitionV3/RowTx. */
53
- export function transitionLegacyForProjection(current, event) {
54
- if (event.type === 'candidate') {
55
- if (current !== undefined)
56
- return { ok: true, row: current };
57
- const key = pairKey(event.a, event.b);
58
- return {
59
- ok: true,
60
- row: {
61
- id: rowIdOf(key),
62
- pairKey: key,
63
- a: event.a,
64
- b: event.b,
65
- state: 'verify',
66
- queue: 'verify',
67
- createdAt: event.at,
68
- updatedAt: event.at,
69
- },
70
- };
71
- }
72
- if (event.type === 'source-gone')
73
- return { ok: true, row: null };
74
- if (event.type === 'gate-keep') {
75
- if (current !== undefined)
76
- return { ok: true, row: current };
77
- const key = pairKey(event.a, event.b);
78
- return {
79
- ok: true,
80
- row: {
81
- id: rowIdOf(key),
82
- pairKey: key,
83
- a: event.a,
84
- b: event.b,
85
- state: 'skipped',
86
- queue: 'skipped',
87
- origin: 'agent',
88
- createdAt: event.at,
89
- updatedAt: event.at,
90
- },
91
- };
92
- }
93
- if (current === undefined)
94
- return invalid(event, undefined);
95
- switch (event.type) {
96
- case 'round1-keep':
97
- return current.state === 'verify' ? next(current, event.at, 'skipped', { origin: 'agent' }) : invalid(event, current.state);
98
- case 'round1-merge':
99
- if (current.state !== 'verify')
100
- return invalid(event, current.state);
101
- return event.approval === 'on'
102
- ? next(current, event.at, 'pending', { ...(event.decision === undefined ? {} : { decision: event.decision }), ...(event.stagingRef === undefined ? {} : { stagingRef: event.stagingRef }), ...(event.stagingExpiresAt === undefined ? {} : { stagingExpiresAt: event.stagingExpiresAt }), ...(event.sourceRevision === undefined ? {} : { sourceRevision: event.sourceRevision }), ...(event.targetRevision === undefined ? {} : { targetRevision: event.targetRevision }) })
103
- : next(current, event.at, 'approved', { ...(event.decision === undefined ? {} : { decision: event.decision }), ...(event.stagingRef === undefined ? {} : { stagingRef: event.stagingRef }), ...(event.stagingExpiresAt === undefined ? {} : { stagingExpiresAt: event.stagingExpiresAt }), ...(event.sourceRevision === undefined ? {} : { sourceRevision: event.sourceRevision }), ...(event.targetRevision === undefined ? {} : { targetRevision: event.targetRevision }) });
104
- case 'round1-fail':
105
- return current.state === 'verify'
106
- ? next(current, event.at, 'verify', { failure: event.failure, attempts: (current.attempts ?? 0) + 1 })
107
- : invalid(event, current.state);
108
- case 'approve':
109
- return current.state === 'pending'
110
- ? next(current, event.at, 'approved', (event.runId === undefined ? {} : { runId: event.runId }))
111
- : invalid(event, current.state);
112
- case 'reject':
113
- return current.state === 'pending' ? next(current, event.at, 'skipped', { origin: 'human' }) : invalid(event, current.state);
114
- case 'round2-cancel':
115
- return current.state === 'fuse' || current.state === 'approved'
116
- ? next(current, event.at, 'approved')
117
- : invalid(event, current.state);
118
- case 'round2-fail':
119
- return current.state === 'fuse' || current.state === 'approved'
120
- ? next(current, event.at, 'approved', { failure: event.failure, attempts: (current.attempts ?? 0) + 1 })
121
- : invalid(event, current.state);
122
- case 'round2-success':
123
- return current.state === 'fuse' || current.state === 'approved'
124
- ? { ok: true, row: null }
125
- : invalid(event, current.state);
126
- case 'target-taken':
127
- case 'source-changed':
128
- return current.state === 'pending' || current.state === 'approved' || current.state === 'fuse'
129
- ? next(current, event.at, current.state, { expired: event.type })
130
- : invalid(event, current.state);
131
- case 'restore':
132
- return current.state === 'skipped'
133
- ? next(current, event.at, 'verify')
134
- : invalid(event, current.state);
135
- }
136
- }
137
- //# sourceMappingURL=coordinator.js.map
@@ -1,6 +0,0 @@
1
- import type { EvolutionIoLike } from '@lmzhen/dsh-evolution-core';
2
- import type { CommitJournal } from './commit-journal.ts';
3
- export declare function journalPath(home: string, runId: string): string;
4
- export declare function writeJournal(io: EvolutionIoLike, home: string, journal: CommitJournal): Promise<string>;
5
- export declare function readJournal(io: EvolutionIoLike, home: string, runId: string): Promise<CommitJournal | null>;
6
- //# sourceMappingURL=commit-journal-store.d.ts.map
@@ -1,26 +0,0 @@
1
- /** Durable commit journal: <home>/merge/journals/<run>.json. */
2
- import { join } from 'node:path';
3
- export function journalPath(home, runId) {
4
- return join(home, 'merge', 'journals', runId.replace(/[^A-Za-z0-9_-]+/g, '_') + '.json');
5
- }
6
- export async function writeJournal(io, home, journal) {
7
- const path = journalPath(home, journal.runId);
8
- const content = JSON.stringify(journal, null, 2);
9
- if (io.transact !== undefined)
10
- await io.transact(path, () => content);
11
- else
12
- await io.writeText(path, content);
13
- return path;
14
- }
15
- export async function readJournal(io, home, runId) {
16
- const raw = await io.readText(journalPath(home, runId));
17
- if (raw === null)
18
- return null;
19
- try {
20
- return JSON.parse(raw);
21
- }
22
- catch {
23
- return null;
24
- }
25
- }
26
- //# sourceMappingURL=commit-journal-store.js.map
@@ -1,16 +0,0 @@
1
- /** Pure commit-journal phases for target-first merge. */
2
- export type JournalPhase = 'prepared' | 'target-written' | 'sources-archived' | 'committed' | 'rolled-back' | 'failed';
3
- export interface CommitJournal {
4
- readonly runId: string;
5
- readonly unitId?: string;
6
- readonly target: string;
7
- readonly create: boolean;
8
- readonly sources: readonly string[];
9
- readonly phase: JournalPhase;
10
- readonly updatedAt: string;
11
- }
12
- export declare function advanceJournal(journal: CommitJournal, phase: JournalPhase, at: string): CommitJournal;
13
- export type JournalRecovery = 'none' | 'retry-commit' | 'rollback-target' | 'rollback-sources' | 'refuse';
14
- /** What a restart may do with the last durable phase. */
15
- export declare function recoveryFor(journal: CommitJournal): JournalRecovery;
16
- //# sourceMappingURL=commit-journal.d.ts.map
@@ -1,26 +0,0 @@
1
- const NEXT = {
2
- prepared: ['committed', 'target-written', 'failed'],
3
- 'target-written': ['sources-archived', 'rolled-back', 'failed'],
4
- 'sources-archived': ['committed', 'rolled-back', 'failed'],
5
- committed: [],
6
- 'rolled-back': [],
7
- failed: [],
8
- };
9
- export function advanceJournal(journal, phase, at) {
10
- if (!NEXT[journal.phase].includes(phase))
11
- throw new Error('invalid journal transition: ' + journal.phase + ' -> ' + phase);
12
- return { ...journal, phase, updatedAt: at };
13
- }
14
- /** What a restart may do with the last durable phase. */
15
- export function recoveryFor(journal) {
16
- switch (journal.phase) {
17
- case 'prepared': return 'retry-commit';
18
- case 'target-written': return 'rollback-target';
19
- case 'sources-archived': return 'rollback-sources';
20
- case 'committed':
21
- case 'rolled-back':
22
- case 'failed': return 'none';
23
- default: return 'refuse';
24
- }
25
- }
26
- //# sourceMappingURL=commit-journal.js.map
@@ -1,21 +0,0 @@
1
- /** Pure pairKey result index and archived-history projection. No IO. */
2
- export interface PairIndexEntryV2 {
3
- readonly pairKey: string;
4
- readonly runId: string;
5
- readonly result: 'merged' | 'kept' | 'failed' | 'cancelled' | 'undone';
6
- readonly target?: string;
7
- readonly reportRef?: string;
8
- }
9
- export type HistoryKind = 'merged' | 'deleted' | 'split' | 'other';
10
- export interface HistoryRecord {
11
- readonly name: string;
12
- readonly kind: HistoryKind;
13
- readonly reason: string;
14
- readonly lastVersion: number;
15
- readonly archivedAt: string;
16
- readonly sourceRunId?: string;
17
- }
18
- export declare function putPair(index: ReadonlyMap<string, PairIndexEntryV2>, entry: PairIndexEntryV2): Map<string, PairIndexEntryV2>;
19
- export declare function historyRecord(input: HistoryRecord): HistoryRecord;
20
- export declare function summarizeHistory(records: readonly HistoryRecord[]): Record<HistoryKind, number>;
21
- //# sourceMappingURL=indexes.d.ts.map
@@ -1,15 +0,0 @@
1
- export function putPair(index, entry) {
2
- const next = new Map(index);
3
- next.set(entry.pairKey, entry);
4
- return next;
5
- }
6
- export function historyRecord(input) {
7
- return { ...input, lastVersion: Math.max(1, Math.trunc(input.lastVersion)) };
8
- }
9
- export function summarizeHistory(records) {
10
- const counts = { merged: 0, deleted: 0, split: 0, other: 0 };
11
- for (const record of records)
12
- counts[record.kind] += 1;
13
- return counts;
14
- }
15
- //# sourceMappingURL=indexes.js.map
@@ -1,41 +0,0 @@
1
- /** 1b-1 additive report schema; values are filled by later batches. */
2
- export interface MergeReportLimits {
3
- readonly maxSkillFileBytes?: number;
4
- readonly maxTokenBytes?: number;
5
- readonly pairTimeoutMinutes?: number;
6
- }
7
- export interface MergeReportValidation {
8
- readonly ok: boolean;
9
- readonly errors: readonly string[];
10
- }
11
- export interface MergeReport {
12
- readonly schemaVersion: 2;
13
- readonly reportId: string;
14
- readonly runId: string;
15
- readonly pairKey: string;
16
- readonly target: string;
17
- readonly sourceRevisions?: Readonly<Record<string, string>>;
18
- readonly targetRevision?: string;
19
- readonly validation: MergeReportValidation;
20
- readonly limits: MergeReportLimits;
21
- readonly q09?: {
22
- readonly forwardRefs: readonly string[];
23
- readonly reverseRefs: readonly string[];
24
- readonly orphanFiles: readonly string[];
25
- };
26
- readonly threat?: {
27
- readonly body: string;
28
- readonly source: string;
29
- };
30
- readonly createdAt: string;
31
- }
32
- export interface MergeReportRef {
33
- readonly path: string;
34
- readonly digest: string;
35
- readonly writtenAt: string;
36
- }
37
- export interface MergeReportWriter {
38
- write(report: MergeReport): Promise<MergeReportRef>;
39
- read(runId: string): Promise<MergeReport | null>;
40
- }
41
- //# sourceMappingURL=merge-report.d.ts.map
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=merge-report.js.map
@@ -1,6 +0,0 @@
1
- import type { EvolutionIoLike } from '@lmzhen/dsh-evolution-core';
2
- import type { PairIndexEntryV2 } from './indexes.ts';
3
- export declare function pairIndexPath(home: string): string;
4
- export declare function loadPairIndex(io: EvolutionIoLike, home: string): Promise<Map<string, PairIndexEntryV2>>;
5
- export declare function recordPair(io: EvolutionIoLike, home: string, entry: PairIndexEntryV2): Promise<void>;
6
- //# sourceMappingURL=pair-index-store.d.ts.map
@@ -1,25 +0,0 @@
1
- /** Durable pairKey index at <home>/merge/pair-index.json. */
2
- import { join } from 'node:path';
3
- import { transactIo } from '@lmzhen/dsh-evolution-core';
4
- import { parsePairIndex, serializePairIndex } from "./pair-index.js";
5
- export function pairIndexPath(home) {
6
- return join(home, 'merge', 'pair-index.json');
7
- }
8
- export async function loadPairIndex(io, home) {
9
- let raw = null;
10
- try {
11
- raw = await io.readText(pairIndexPath(home));
12
- }
13
- catch {
14
- return new Map();
15
- }
16
- return parsePairIndex(raw);
17
- }
18
- export async function recordPair(io, home, entry) {
19
- await transactIo(io, pairIndexPath(home), (current) => {
20
- const index = parsePairIndex(current);
21
- index.set(entry.pairKey, entry);
22
- return serializePairIndex(index);
23
- });
24
- }
25
- //# sourceMappingURL=pair-index-store.js.map
@@ -1,9 +0,0 @@
1
- /** Pure pairKey index serialization. No IO. */
2
- import type { PairIndexEntryV2 } from './indexes.ts';
3
- export interface PairIndexFile {
4
- readonly schemaVersion: 1;
5
- readonly entries: readonly PairIndexEntryV2[];
6
- }
7
- export declare function parsePairIndex(raw: string | null): Map<string, PairIndexEntryV2>;
8
- export declare function serializePairIndex(index: ReadonlyMap<string, PairIndexEntryV2>): string;
9
- //# sourceMappingURL=pair-index.d.ts.map
@@ -1,28 +0,0 @@
1
- export function parsePairIndex(raw) {
2
- const index = new Map();
3
- if (raw === null)
4
- return index;
5
- let parsed;
6
- try {
7
- parsed = JSON.parse(raw);
8
- }
9
- catch {
10
- return index;
11
- }
12
- const body = parsed;
13
- if (!Array.isArray(body.entries))
14
- return index;
15
- for (const value of body.entries) {
16
- const entry = value;
17
- if (typeof entry.pairKey !== 'string' || typeof entry.runId !== 'string' || typeof entry.result !== 'string')
18
- continue;
19
- if (!['merged', 'kept', 'failed', 'cancelled', 'undone'].includes(entry.result))
20
- continue;
21
- index.set(entry.pairKey, entry);
22
- }
23
- return index;
24
- }
25
- export function serializePairIndex(index) {
26
- return JSON.stringify({ schemaVersion: 1, entries: [...index.values()] }, null, 2);
27
- }
28
- //# sourceMappingURL=pair-index.js.map
@@ -1,4 +0,0 @@
1
- /** Pure pair-index lookup. No run-record merge fields. */
2
- import type { PairIndexEntryV2 } from './indexes.ts';
3
- export declare function findPairRun(pairs: readonly PairIndexEntryV2[], pairKey: string): PairIndexEntryV2 | undefined;
4
- //# sourceMappingURL=resolve-pair.d.ts.map
@@ -1,4 +0,0 @@
1
- export function findPairRun(pairs, pairKey) {
2
- return pairs.find(entry => entry.pairKey === pairKey);
3
- }
4
- //# sourceMappingURL=resolve-pair.js.map
@@ -1,27 +0,0 @@
1
- /** G3-5 RowTx pure write API: only createVerify/createSkipped/transition. */
2
- import { type SkippedRowV3, type V3Event, type V3Row, type VerifyRowV3 } from './row-v3.ts';
3
- export type RowWrite = {
4
- readonly kind: 'createVerify';
5
- readonly row: VerifyRowV3;
6
- } | {
7
- readonly kind: 'createSkipped';
8
- readonly row: SkippedRowV3;
9
- } | {
10
- readonly kind: 'transition';
11
- readonly id: string;
12
- readonly event: V3Event;
13
- readonly expectedVersion: number;
14
- };
15
- type RowWriteErrorCode = 'row-invalid' | 'row-duplicate' | 'row-not-found' | 'version-conflict' | 'illegal-transition';
16
- export type RowWriteResult = {
17
- readonly ok: true;
18
- readonly rows: readonly V3Row[];
19
- readonly row: V3Row | null;
20
- } | {
21
- readonly ok: false;
22
- readonly code: RowWriteErrorCode;
23
- readonly message: string;
24
- };
25
- export declare function applyRowWrite(rows: readonly V3Row[], write: RowWrite, at: string): RowWriteResult;
26
- export {};
27
- //# sourceMappingURL=row-tx.d.ts.map
@@ -1,31 +0,0 @@
1
- /** G3-5 RowTx pure write API: only createVerify/createSkipped/transition. */
2
- import { isV3Row, transitionV3 } from "./row-v3.js";
3
- function bad(code, message) { return { ok: false, code, message }; }
4
- export function applyRowWrite(rows, write, at) {
5
- if (write.kind === 'transition') {
6
- const index = rows.findIndex(row => row.id === write.id);
7
- if (index < 0)
8
- return bad('row-not-found', 'row not found: ' + write.id);
9
- const current = rows[index];
10
- const moved = transitionV3(current, write.event, write.expectedVersion, at);
11
- if (!moved.ok)
12
- return bad(moved.code, moved.message);
13
- if (moved.row === null)
14
- return { ok: true, rows: rows.filter((_, atIndex) => atIndex !== index), row: null };
15
- const next = [...rows];
16
- next[index] = moved.row;
17
- return { ok: true, rows: next, row: moved.row };
18
- }
19
- if (write.row.version !== 0)
20
- return bad('row-invalid', 'create requires version 0');
21
- if (write.kind === 'createVerify' && (write.row.state !== 'verify' || write.row.verifySubState !== 'unverified'))
22
- return bad('row-invalid', 'createVerify requires verify/unverified');
23
- if (write.kind === 'createSkipped' && write.row.state !== 'skipped')
24
- return bad('row-invalid', 'createSkipped requires skipped');
25
- if (!isV3Row(write.row))
26
- return bad('row-invalid', 'created row is invalid');
27
- if (rows.some(row => row.id === write.row.id))
28
- return bad('row-duplicate', 'duplicate row id: ' + write.row.id);
29
- return { ok: true, rows: [...rows, write.row], row: write.row };
30
- }
31
- //# sourceMappingURL=row-tx.js.map