@lmzhen/dsh-evolution-merge 0.30.17 → 0.30.19
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/README.md +25 -7
- package/data/minhash_params.json +1063 -0
- package/lib/index.js +7308 -1800
- package/lib/types/adapters/channel.d.ts +1 -0
- package/lib/types/adapters/channel.js +15 -1
- package/lib/types/adapters/engine-screen.d.ts +1 -1
- package/lib/types/adapters/engine-screen.js +5 -2
- package/lib/types/adapters/library.js +4 -1
- package/lib/types/adapters/model-runner.d.ts +0 -5
- package/lib/types/adapters/model-runner.js +8 -2
- package/lib/types/adapters/model.d.ts +31 -0
- package/lib/types/adapters/model.js +47 -0
- package/lib/types/adapters/select.js +12 -8
- package/lib/types/approve-command.d.ts +14 -1
- package/lib/types/approve-command.js +72 -44
- package/lib/types/authoring-flow.d.ts +19 -1
- package/lib/types/authoring-flow.js +49 -15
- package/lib/types/channel-port.d.ts +3 -1
- package/lib/types/channel-port.js +8 -3
- package/lib/types/command-defs.d.ts +5 -0
- package/lib/types/command-defs.js +33 -0
- package/lib/types/command-surface.d.ts +5 -0
- package/lib/types/command-surface.js +11 -0
- package/lib/types/commands.d.ts +3 -4
- package/lib/types/commands.js +33 -72
- package/lib/types/commit-assembly.d.ts +16 -1
- package/lib/types/commit-assembly.js +72 -11
- package/lib/types/commit-execute.d.ts +14 -2
- package/lib/types/commit-execute.js +76 -14
- package/lib/types/commit-plan.d.ts +7 -1
- package/lib/types/commit-plan.js +4 -0
- package/lib/types/commit-receipt.d.ts +3 -0
- package/lib/types/commit-recovery.d.ts +7 -2
- package/lib/types/commit-recovery.js +73 -96
- package/lib/types/contracts.d.ts +44 -1
- package/lib/types/contracts.js +1 -1
- package/lib/types/coordinator.d.ts +3 -2
- package/lib/types/coordinator.js +4 -3
- package/lib/types/decision.js +1 -1
- package/lib/types/doctor.d.ts +18 -1
- package/lib/types/doctor.js +164 -10
- package/lib/types/domain/authoring-manifest.d.ts +26 -0
- package/lib/types/domain/authoring-manifest.js +43 -0
- package/lib/types/domain/claim.d.ts +4 -1
- package/lib/types/domain/claim.js +2 -2
- package/lib/types/domain/commit-journal-store.js +5 -1
- package/lib/types/domain/commit-journal.js +1 -1
- package/lib/types/domain/consistency.d.ts +22 -0
- package/lib/types/domain/consistency.js +50 -0
- package/lib/types/domain/engine-criteria.d.ts +10 -0
- package/lib/types/domain/engine-criteria.js +11 -0
- package/lib/types/domain/engine-input.d.ts +10 -0
- package/lib/types/domain/engine-input.js +26 -0
- package/lib/types/domain/errors.d.ts +15 -1
- package/lib/types/domain/errors.js +23 -4
- package/lib/types/domain/evidence-hash.d.ts +3 -0
- package/lib/types/domain/evidence-hash.js +14 -0
- package/lib/types/domain/failure-route.d.ts +14 -0
- package/lib/types/domain/failure-route.js +12 -0
- package/lib/types/domain/ledger.js +10 -1
- package/lib/types/domain/live-facts.d.ts +31 -0
- package/lib/types/domain/live-facts.js +54 -0
- package/lib/types/domain/merge-limits.d.ts +18 -0
- package/lib/types/domain/merge-limits.js +22 -0
- package/lib/types/domain/merge-report.d.ts +41 -0
- package/lib/types/domain/merge-report.js +2 -0
- package/lib/types/domain/merge-snapshot.d.ts +99 -0
- package/lib/types/domain/merge-snapshot.js +82 -0
- package/lib/types/domain/migrate-v3.d.ts +20 -0
- package/lib/types/domain/migrate-v3.js +68 -0
- package/lib/types/domain/pair-ledger.d.ts +34 -0
- package/lib/types/domain/pair-ledger.js +96 -0
- package/lib/types/domain/pre-1b-backup.d.ts +43 -0
- package/lib/types/domain/pre-1b-backup.js +140 -0
- package/lib/types/domain/provider-key.d.ts +2 -0
- package/lib/types/domain/provider-key.js +11 -0
- package/lib/types/domain/read-probe.d.ts +5 -0
- package/lib/types/domain/read-probe.js +11 -0
- package/lib/types/domain/reconcile.d.ts +47 -0
- package/lib/types/domain/reconcile.js +178 -0
- package/lib/types/domain/resolve-pair.d.ts +2 -9
- package/lib/types/domain/resolve-pair.js +2 -15
- package/lib/types/domain/row-tx.d.ts +27 -0
- package/lib/types/domain/row-tx.js +31 -0
- package/lib/types/domain/row-v3-bridge.d.ts +6 -0
- package/lib/types/domain/row-v3-bridge.js +47 -0
- package/lib/types/domain/row-v3.d.ts +113 -0
- package/lib/types/domain/row-v3.js +107 -0
- package/lib/types/domain/row-v4.d.ts +148 -0
- package/lib/types/domain/row-v4.js +159 -0
- package/lib/types/domain/row.d.ts +1 -0
- package/lib/types/domain/run-coordinator.d.ts +51 -0
- package/lib/types/domain/run-coordinator.js +45 -0
- package/lib/types/domain/schema4.d.ts +53 -0
- package/lib/types/domain/schema4.js +129 -0
- package/lib/types/domain/selection-policy.d.ts +14 -0
- package/lib/types/domain/selection-policy.js +6 -0
- package/lib/types/domain/skipped-expiry.d.ts +5 -0
- package/lib/types/domain/skipped-expiry.js +16 -0
- package/lib/types/domain/stage-aggregate.d.ts +96 -0
- package/lib/types/domain/stage-aggregate.js +293 -0
- package/lib/types/domain/staging-index.d.ts +15 -0
- package/lib/types/domain/staging-index.js +41 -0
- package/lib/types/domain/state-bootstrap.d.ts +43 -0
- package/lib/types/domain/state-bootstrap.js +267 -0
- package/lib/types/domain/state-v3.d.ts +4 -0
- package/lib/types/domain/state-v3.js +4 -0
- package/lib/types/domain/undo-journal.d.ts +19 -0
- package/lib/types/domain/undo-journal.js +20 -0
- package/lib/types/domain/undo-receipt.d.ts +18 -0
- package/lib/types/domain/undo-receipt.js +22 -0
- package/lib/types/domain/validation-plan.d.ts +65 -0
- package/lib/types/domain/validation-plan.js +49 -0
- package/lib/types/facts.d.ts +26 -0
- package/lib/types/facts.js +65 -0
- package/lib/types/gate-filter.d.ts +31 -0
- package/lib/types/gate-filter.js +64 -0
- package/lib/types/index.d.ts +7 -2
- package/lib/types/index.js +185 -82
- package/lib/types/ladder.js +1 -1
- package/lib/types/merge-command.d.ts +3 -1
- package/lib/types/merge-command.js +10 -6
- package/lib/types/merge-routes.d.ts +12 -7
- package/lib/types/merge-routes.js +87 -23
- package/lib/types/merge-tool.d.ts +1 -1
- package/lib/types/merge-tool.js +2 -2
- package/lib/types/metrics.d.ts +16 -0
- package/lib/types/metrics.js +27 -0
- package/lib/types/new-child-authoring.d.ts +5 -1
- package/lib/types/new-child-authoring.js +71 -13
- package/lib/types/params.d.ts +2 -4
- package/lib/types/params.js +13 -0
- package/lib/types/pending-actions.d.ts +2 -2
- package/lib/types/pending-actions.js +17 -17
- package/lib/types/prompts.d.ts +2 -4
- package/lib/types/prompts.js +21 -8
- package/lib/types/propose.d.ts +26 -0
- package/lib/types/propose.js +69 -0
- package/lib/types/read-commands.d.ts +4 -4
- package/lib/types/read-commands.js +19 -26
- package/lib/types/recovery-coordinator.d.ts +34 -0
- package/lib/types/recovery-coordinator.js +84 -0
- package/lib/types/recovery-projection.d.ts +31 -0
- package/lib/types/recovery-projection.js +96 -0
- package/lib/types/resume-command.d.ts +7 -1
- package/lib/types/resume-command.js +50 -14
- package/lib/types/revision.d.ts +17 -0
- package/lib/types/revision.js +39 -3
- package/lib/types/round2-outcome.d.ts +2 -1
- package/lib/types/round2-outcome.js +68 -12
- package/lib/types/run-shell.d.ts +16 -2
- package/lib/types/run-shell.js +49 -5
- package/lib/types/runtime.d.ts +4 -6
- package/lib/types/runtime.js +341 -86
- package/lib/types/scan-command.d.ts +1 -0
- package/lib/types/scan-command.js +2 -0
- package/lib/types/scan-ports.d.ts +21 -1
- package/lib/types/scan-ports.js +51 -23
- package/lib/types/scan-run.d.ts +17 -0
- package/lib/types/scan-run.js +221 -63
- package/lib/types/screening-port.d.ts +47 -0
- package/lib/types/screening-port.js +93 -0
- package/lib/types/screening.d.ts +30 -0
- package/lib/types/screening.js +75 -0
- package/lib/types/stage-tool-registry.d.ts +7 -0
- package/lib/types/stage-tool-registry.js +12 -1
- package/lib/types/state.d.ts +15 -1
- package/lib/types/state.js +39 -17
- package/lib/types/status.d.ts +8 -0
- package/lib/types/status.js +64 -0
- package/lib/types/surface/body.d.ts +4 -0
- package/lib/types/surface/body.js +16 -0
- package/lib/types/surface/merge-view.d.ts +14 -0
- package/lib/types/surface/merge-view.js +126 -0
- package/lib/types/target-claim.d.ts +1 -0
- package/lib/types/target-claim.js +63 -18
- package/lib/types/undo-operation.d.ts +24 -0
- package/lib/types/undo-operation.js +135 -0
- package/lib/types/unit-claim.d.ts +5 -0
- package/lib/types/unit-claim.js +15 -0
- package/lib/types/wire-projection.d.ts +36 -0
- package/lib/types/wire-projection.js +69 -0
- package/lib/types/wire.d.ts +273 -0
- package/lib/types/wire.js +3 -0
- package/package.json +10 -4
- package/lib/types/routes.d.ts +0 -70
- package/lib/types/routes.js +0 -78
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse `{"target":..., "files":[...]}` from a child's final turn text.
|
|
3
|
+
* @param text - the child's answer (JSON is expected; prose is tolerated).
|
|
4
|
+
* @returns the manifest, or null when the turn carried no well-formed envelope.
|
|
5
|
+
*/
|
|
6
|
+
export function parseAuthoringManifest(text) {
|
|
7
|
+
try {
|
|
8
|
+
const value = JSON.parse(text);
|
|
9
|
+
if (!Array.isArray(value.files) || value.files.some(file => typeof file !== 'string'))
|
|
10
|
+
return null;
|
|
11
|
+
if (value.target !== undefined && typeof value.target !== 'string')
|
|
12
|
+
return null;
|
|
13
|
+
return { ...(typeof value.target === 'string' ? { target: value.target } : {}), files: value.files };
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/** Files a manifest promises for a staged tree (declared list, or the tree when undeclared). */
|
|
20
|
+
export function manifestFilesOf(manifest, stagedPaths) {
|
|
21
|
+
if (manifest !== null)
|
|
22
|
+
return manifest.files;
|
|
23
|
+
return ['SKILL.md', ...stagedPaths];
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The first file the manifest promises but the staged tree does not contain.
|
|
27
|
+
* SKILL.md itself is always required, whether or not the manifest lists it.
|
|
28
|
+
* @param files - manifest files (see {@link manifestFilesOf}).
|
|
29
|
+
* @param stagedPaths - support-file paths actually present in the staged tree.
|
|
30
|
+
* @returns the missing path, or null when the declaration is satisfied.
|
|
31
|
+
*/
|
|
32
|
+
export function missingManifestFile(files, stagedPaths) {
|
|
33
|
+
if (!files.includes('SKILL.md'))
|
|
34
|
+
return 'SKILL.md';
|
|
35
|
+
for (const path of files) {
|
|
36
|
+
if (path === 'SKILL.md')
|
|
37
|
+
continue;
|
|
38
|
+
if (!stagedPaths.includes(path))
|
|
39
|
+
return path;
|
|
40
|
+
}
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=authoring-manifest.js.map
|
|
@@ -3,8 +3,11 @@ export interface Claim {
|
|
|
3
3
|
readonly id: string;
|
|
4
4
|
readonly token: string;
|
|
5
5
|
readonly expiresAt: number;
|
|
6
|
+
readonly pid?: number;
|
|
7
|
+
/** Process start time; detects pid reuse when the same pid hosts a newer process. */
|
|
8
|
+
readonly startedAt?: number;
|
|
6
9
|
}
|
|
7
|
-
export declare function acquireClaim(current: Claim | undefined, now: number, leaseMs: number, token: string): Claim | undefined;
|
|
10
|
+
export declare function acquireClaim(current: Claim | undefined, now: number, leaseMs: number, token: string, pid?: number, startedAt?: number): Claim | undefined;
|
|
8
11
|
export declare function releaseClaim(current: Claim | undefined, token: string): Claim | undefined;
|
|
9
12
|
export declare function isClaimExpired(current: Claim | undefined, now: number): boolean;
|
|
10
13
|
//# sourceMappingURL=claim.d.ts.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export function acquireClaim(current, now, leaseMs, token) {
|
|
1
|
+
export function acquireClaim(current, now, leaseMs, token, pid, startedAt) {
|
|
2
2
|
if (current !== undefined && current.expiresAt > now)
|
|
3
3
|
return undefined;
|
|
4
|
-
return { id: 'claim', token, expiresAt: now + Math.max(1, leaseMs) };
|
|
4
|
+
return { id: 'claim', token, expiresAt: now + Math.max(1, leaseMs), ...(pid === undefined ? {} : { pid }), ...(startedAt === undefined ? {} : { startedAt }) };
|
|
5
5
|
}
|
|
6
6
|
export function releaseClaim(current, token) {
|
|
7
7
|
return current?.token === token ? undefined : current;
|
|
@@ -5,7 +5,11 @@ export function journalPath(home, runId) {
|
|
|
5
5
|
}
|
|
6
6
|
export async function writeJournal(io, home, journal) {
|
|
7
7
|
const path = journalPath(home, journal.runId);
|
|
8
|
-
|
|
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);
|
|
9
13
|
return path;
|
|
10
14
|
}
|
|
11
15
|
export async function readJournal(io, home, runId) {
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/** RG0 cross-artifact consistency. Pure; no IO. */
|
|
2
|
+
export type RowState = 'verify' | 'pending' | 'approved' | 'fuse' | 'skipped' | 'merged';
|
|
3
|
+
export type RunState = 'none' | 'awaiting-approval' | 'running' | 'succeeded' | 'failed' | 'cancelled' | 'orphan';
|
|
4
|
+
export type StagingState = 'none' | 'cleaned' | 'kept' | 'missing';
|
|
5
|
+
export type JournalState = 'none' | 'committing' | 'prepared' | 'committed' | 'rolled-back' | 'failed';
|
|
6
|
+
export type EvidenceState = 'none' | 'receipt';
|
|
7
|
+
export interface ArtifactState {
|
|
8
|
+
readonly row: RowState;
|
|
9
|
+
readonly run: RunState;
|
|
10
|
+
readonly staging: StagingState;
|
|
11
|
+
readonly journal: JournalState;
|
|
12
|
+
readonly evidence: EvidenceState;
|
|
13
|
+
readonly activeRuns: number;
|
|
14
|
+
readonly hasOwner?: boolean;
|
|
15
|
+
readonly recovery?: boolean;
|
|
16
|
+
}
|
|
17
|
+
export interface ConsistencyResult {
|
|
18
|
+
readonly ok: boolean;
|
|
19
|
+
readonly reason?: string;
|
|
20
|
+
}
|
|
21
|
+
export declare function validateArtifacts(state: ArtifactState): ConsistencyResult;
|
|
22
|
+
//# sourceMappingURL=consistency.d.ts.map
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
const ALLOWED = [
|
|
2
|
+
{ row: 'verify', run: 'none', staging: 'none', journal: 'none', evidence: 'none', activeRuns: 0 },
|
|
3
|
+
{ row: 'verify', run: 'running', staging: 'none', journal: 'none', evidence: 'none', activeRuns: 1 },
|
|
4
|
+
{ row: 'verify', run: 'failed', staging: 'none', journal: 'none', evidence: 'none', activeRuns: 0 },
|
|
5
|
+
{ row: 'pending', run: 'none', staging: 'none', journal: 'none', evidence: 'none', activeRuns: 0 },
|
|
6
|
+
{ row: 'pending', run: 'awaiting-approval', staging: 'none', journal: 'none', evidence: 'none', activeRuns: 1 },
|
|
7
|
+
{ row: 'approved', run: 'none', staging: 'none', journal: 'none', evidence: 'none', activeRuns: 0 },
|
|
8
|
+
{ row: 'approved', run: 'running', staging: 'none', journal: 'none', evidence: 'none', activeRuns: 1 },
|
|
9
|
+
{ row: 'fuse', run: 'none', staging: 'kept', journal: 'none', evidence: 'none', activeRuns: 0 },
|
|
10
|
+
{ row: 'fuse', run: 'running', staging: 'kept', journal: 'none', evidence: 'none', activeRuns: 1 },
|
|
11
|
+
{ row: 'fuse', run: 'failed', staging: 'kept', journal: 'none', evidence: 'none', activeRuns: 0 },
|
|
12
|
+
{ row: 'fuse', run: 'orphan', staging: 'kept', journal: 'none', evidence: 'none', activeRuns: 0 },
|
|
13
|
+
{ row: 'fuse', run: 'none', staging: 'none', journal: 'none', evidence: 'none', activeRuns: 0, recovery: true },
|
|
14
|
+
{ row: 'fuse', run: 'failed', staging: 'none', journal: 'none', evidence: 'none', activeRuns: 0, recovery: true },
|
|
15
|
+
{ row: 'fuse', run: 'orphan', staging: 'none', journal: 'none', evidence: 'none', activeRuns: 0, recovery: true },
|
|
16
|
+
{ row: 'fuse', run: 'running', staging: 'none', journal: 'none', evidence: 'none', activeRuns: 1, recovery: true },
|
|
17
|
+
{ row: 'fuse', run: 'none', staging: 'missing', journal: 'none', evidence: 'none', activeRuns: 0, recovery: true },
|
|
18
|
+
{ row: 'fuse', run: 'failed', staging: 'missing', journal: 'none', evidence: 'none', activeRuns: 0, recovery: true },
|
|
19
|
+
{ row: 'fuse', run: 'orphan', staging: 'missing', journal: 'none', evidence: 'none', activeRuns: 0, recovery: true },
|
|
20
|
+
{ row: 'fuse', run: 'running', staging: 'missing', journal: 'none', evidence: 'none', activeRuns: 1, recovery: true },
|
|
21
|
+
{ row: 'fuse', run: 'running', staging: 'kept', journal: 'committing', evidence: 'none', activeRuns: 1 },
|
|
22
|
+
{ row: 'skipped', run: 'none', staging: 'none', journal: 'none', evidence: 'none', activeRuns: 0 },
|
|
23
|
+
{ row: 'merged', run: 'succeeded', staging: 'cleaned', journal: 'committed', evidence: 'receipt', activeRuns: 0 },
|
|
24
|
+
{ row: 'merged', run: 'succeeded', staging: 'kept', journal: 'committed', evidence: 'receipt', activeRuns: 0 },
|
|
25
|
+
];
|
|
26
|
+
function same(a, b) {
|
|
27
|
+
return a.row === b.row && a.run === b.run && a.staging === b.staging && a.journal === b.journal
|
|
28
|
+
&& a.evidence === b.evidence && a.activeRuns === b.activeRuns
|
|
29
|
+
&& (b.recovery ?? false) === (a.recovery ?? false);
|
|
30
|
+
}
|
|
31
|
+
export function validateArtifacts(state) {
|
|
32
|
+
if (state.activeRuns > 1)
|
|
33
|
+
return { ok: false, reason: 'multiple-active-runs' };
|
|
34
|
+
if (state.activeRuns > 0 && state.hasOwner === false)
|
|
35
|
+
return { ok: false, reason: 'active-run-no-owner' };
|
|
36
|
+
if (ALLOWED.some(item => same(state, item)))
|
|
37
|
+
return { ok: true };
|
|
38
|
+
if (state.row === 'pending' && state.staging !== 'none')
|
|
39
|
+
return { ok: false, reason: 'pending-staging' };
|
|
40
|
+
if (state.row === 'skipped' && state.run === 'running')
|
|
41
|
+
return { ok: false, reason: 'skipped-running' };
|
|
42
|
+
if (state.row === 'fuse' && state.staging === 'missing' && state.recovery !== true)
|
|
43
|
+
return { ok: false, reason: 'fuse-lost-staging' };
|
|
44
|
+
if (state.journal === 'committed' && state.evidence !== 'receipt')
|
|
45
|
+
return { ok: false, reason: 'committed-no-evidence' };
|
|
46
|
+
if (state.row === 'merged' && state.journal === 'rolled-back')
|
|
47
|
+
return { ok: false, reason: 'committed-rollback' };
|
|
48
|
+
return { ok: false, reason: 'not-allowed' };
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=consistency.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Batch 3 engine criteria projection: merge maps level/verdict/action, engine does not. */
|
|
2
|
+
export interface EngineCriteria {
|
|
3
|
+
readonly decision: 'keep' | 'merge' | 'candidate';
|
|
4
|
+
readonly validation: 'not-run' | 'report-only' | 'required';
|
|
5
|
+
readonly commit: 'never' | 'if-approved' | 'required';
|
|
6
|
+
readonly archive: 'none' | 'sources';
|
|
7
|
+
readonly evidence: 'none' | 'receipt';
|
|
8
|
+
}
|
|
9
|
+
export declare function criteriaFrom(level: 'L0' | 'L1' | 'L2', verdict: 1 | 0 | -1, action: 'keep' | 'merge'): EngineCriteria;
|
|
10
|
+
//# sourceMappingURL=engine-criteria.d.ts.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export function criteriaFrom(level, verdict, action) {
|
|
2
|
+
const candidate = level === 'L2' && verdict !== -1;
|
|
3
|
+
return {
|
|
4
|
+
decision: action === 'keep' ? 'keep' : candidate ? 'merge' : 'candidate',
|
|
5
|
+
validation: level === 'L2' ? 'required' : 'report-only',
|
|
6
|
+
commit: candidate && action === 'merge' ? 'required' : 'never',
|
|
7
|
+
archive: candidate && action === 'merge' ? 'sources' : 'none',
|
|
8
|
+
evidence: candidate && action === 'merge' ? 'receipt' : 'none',
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=engine-criteria.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** OI-11 engine input allowlist: exactly modelsRoot/reportOnly/maxTokens/timeoutMs. */
|
|
2
|
+
export interface EngineInput {
|
|
3
|
+
readonly modelsRoot: string;
|
|
4
|
+
readonly reportOnly: boolean;
|
|
5
|
+
readonly maxTokens: number;
|
|
6
|
+
readonly timeoutMs: number;
|
|
7
|
+
}
|
|
8
|
+
export declare const ENGINE_FORBIDDEN_KEYS: readonly ["offline", "auto_provision", "embed_backend", "rank_mode", "models_dir", "embedder_model", "embedder_model_last", "judge"];
|
|
9
|
+
export declare function resolveEngineInput(input?: unknown): EngineInput;
|
|
10
|
+
//# sourceMappingURL=engine-input.d.ts.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const ALLOWED = new Set(['modelsRoot', 'reportOnly', 'maxTokens', 'timeoutMs']);
|
|
2
|
+
export const ENGINE_FORBIDDEN_KEYS = ['offline', 'auto_provision', 'embed_backend', 'rank_mode', 'models_dir', 'embedder_model', 'embedder_model_last', 'judge'];
|
|
3
|
+
function integer(name, value, fallback) {
|
|
4
|
+
if (value === undefined)
|
|
5
|
+
return fallback;
|
|
6
|
+
if (typeof value !== 'number' || !Number.isInteger(value) || value < 0)
|
|
7
|
+
throw new Error(name + ' must be a non-negative integer');
|
|
8
|
+
return value;
|
|
9
|
+
}
|
|
10
|
+
export function resolveEngineInput(input = {}) {
|
|
11
|
+
if (typeof input !== 'object' || input === null || Array.isArray(input))
|
|
12
|
+
throw new Error('engine input must be an object');
|
|
13
|
+
for (const key of Object.keys(input)) {
|
|
14
|
+
if (ENGINE_FORBIDDEN_KEYS.includes(key))
|
|
15
|
+
throw new Error('engine input key is forbidden: ' + key);
|
|
16
|
+
if (!ALLOWED.has(key))
|
|
17
|
+
throw new Error('unknown engine input: ' + key);
|
|
18
|
+
}
|
|
19
|
+
const record = input;
|
|
20
|
+
if (record.modelsRoot !== undefined && typeof record.modelsRoot !== 'string')
|
|
21
|
+
throw new Error('modelsRoot must be a string');
|
|
22
|
+
if (record.reportOnly !== undefined && typeof record.reportOnly !== 'boolean')
|
|
23
|
+
throw new Error('reportOnly must be a boolean');
|
|
24
|
+
return { modelsRoot: typeof record.modelsRoot === 'string' ? record.modelsRoot : '', reportOnly: record.reportOnly === true, maxTokens: integer('maxTokens', record.maxTokens, 0), timeoutMs: integer('timeoutMs', record.timeoutMs, 0) };
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=engine-input.js.map
|
|
@@ -1,12 +1,26 @@
|
|
|
1
|
-
/** Pure merge error rendering: parameter errors
|
|
1
|
+
/** Pure merge error rendering: parameter errors stay one line; command failures are code/hint/next. */
|
|
2
2
|
export type MergeErrorKind = 'parameter' | 'runtime' | 'target' | 'approval';
|
|
3
3
|
export interface MergeError {
|
|
4
4
|
readonly kind: MergeErrorKind;
|
|
5
5
|
readonly code: string;
|
|
6
6
|
readonly message: string;
|
|
7
|
+
/** Reader-facing explanation; defaults to the message (plus detail). */
|
|
8
|
+
readonly hint?: string;
|
|
9
|
+
/** The one next step; every runtime failure names one. */
|
|
10
|
+
readonly next?: string;
|
|
7
11
|
readonly detail?: string;
|
|
8
12
|
readonly stage?: string;
|
|
9
13
|
readonly runId?: string;
|
|
10
14
|
}
|
|
15
|
+
/** Build the typed failure every command/CLI/runtime branch returns. */
|
|
16
|
+
export declare function commandError(stage: string, code: string, hint: string, next: string, runId?: string): MergeError;
|
|
17
|
+
/** Render a merge command failure: one line for syntax, three lines (code/hint/next) for runtime. */
|
|
11
18
|
export declare function formatMergeError(error: MergeError): string;
|
|
19
|
+
/** A typed failure result: `message` is the rendered three-line text, `error` keeps the fields. */
|
|
20
|
+
export interface FailureResult {
|
|
21
|
+
readonly ok: false;
|
|
22
|
+
readonly message: string;
|
|
23
|
+
readonly error: MergeError;
|
|
24
|
+
}
|
|
25
|
+
export declare function failure(stage: string, code: string, hint: string, next: string, runId?: string): FailureResult;
|
|
12
26
|
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -4,12 +4,31 @@ function redact(text) {
|
|
|
4
4
|
.replace(/Bearer\s+\S+/gi, 'Bearer [redacted]')
|
|
5
5
|
.replace(/(api[_-]?key\s*[:=]\s*)\S+/gi, '$1[redacted]');
|
|
6
6
|
}
|
|
7
|
+
/** Build the typed failure every command/CLI/runtime branch returns. */
|
|
8
|
+
export function commandError(stage, code, hint, next, runId) {
|
|
9
|
+
return { kind: 'runtime', code, message: hint, hint, next, stage, ...(runId === undefined ? {} : { runId }) };
|
|
10
|
+
}
|
|
11
|
+
function oneLine(value) {
|
|
12
|
+
return value.replace(/\r?\n+/g, ' ').trim();
|
|
13
|
+
}
|
|
14
|
+
function render(error) {
|
|
15
|
+
const where = [
|
|
16
|
+
error.stage === undefined ? undefined : 'stage=' + error.stage,
|
|
17
|
+
error.runId === undefined ? undefined : 'run=' + error.runId,
|
|
18
|
+
].filter((value) => value !== undefined).join(', ');
|
|
19
|
+
const heading = 'code: ' + error.code + (where === '' ? '' : ' (' + where + ')');
|
|
20
|
+
const hint = 'hint: ' + oneLine(error.hint ?? [error.message, error.detail].filter((value) => value !== undefined && value !== '').join(' — '));
|
|
21
|
+
const next = 'next: ' + oneLine(error.next ?? error.detail ?? 'fix the target or rerun after the cause is gone');
|
|
22
|
+
return redact([heading, hint, next].join('\n'));
|
|
23
|
+
}
|
|
24
|
+
/** Render a merge command failure: one line for syntax, three lines (code/hint/next) for runtime. */
|
|
7
25
|
export function formatMergeError(error) {
|
|
8
26
|
if (error.kind === 'parameter')
|
|
9
27
|
return 'merge: ' + error.message + ' (' + error.code + ')';
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
28
|
+
return render(error);
|
|
29
|
+
}
|
|
30
|
+
export function failure(stage, code, hint, next, runId) {
|
|
31
|
+
const error = commandError(stage, code, hint, next, runId);
|
|
32
|
+
return { ok: false, message: formatMergeError(error), error };
|
|
14
33
|
}
|
|
15
34
|
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Canonical evidence JSON hash shared with core unit receipts. */
|
|
2
|
+
import { createHash } from 'node:crypto';
|
|
3
|
+
function canonical(value) {
|
|
4
|
+
if (value === null || typeof value !== 'object')
|
|
5
|
+
return JSON.stringify(value);
|
|
6
|
+
if (Array.isArray(value))
|
|
7
|
+
return '[' + value.map(canonical).join(',') + ']';
|
|
8
|
+
const object = value;
|
|
9
|
+
return '{' + Object.keys(object).sort().map(key => JSON.stringify(key) + ':' + canonical(object[key])).join(',') + '}';
|
|
10
|
+
}
|
|
11
|
+
export function evidenceSha256(evidence) {
|
|
12
|
+
return createHash('sha256').update(canonical({ ...evidence, at: 0, mutations: 0 })).digest('hex');
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=evidence-hash.js.map
|
|
@@ -20,6 +20,20 @@ export type MergeFailureRoute = {
|
|
|
20
20
|
} | {
|
|
21
21
|
readonly kind: 'runtime';
|
|
22
22
|
readonly reportOnly: true;
|
|
23
|
+
} | {
|
|
24
|
+
readonly kind: 'over-limit';
|
|
25
|
+
readonly reportOnly: true;
|
|
26
|
+
readonly reason: 'merge-over-limit';
|
|
27
|
+
readonly lengths: Readonly<Record<string, number>>;
|
|
23
28
|
};
|
|
29
|
+
export declare function routeLimitFailure(lengths: Readonly<Record<string, number>>): MergeFailureRoute;
|
|
24
30
|
export declare function routeFailure(code: string): MergeFailureRoute;
|
|
31
|
+
/** Batch 2 typed CAS hook; Batch 3 owns full targetRevision expiry. */
|
|
32
|
+
export type CasFailureCode = 'target-changed' | 'target-taken' | 'source-changed' | 'support-changed';
|
|
33
|
+
export interface CasHookResult {
|
|
34
|
+
readonly kind: 'expired';
|
|
35
|
+
readonly reason: Exclude<CasFailureCode, 'target-changed' | 'support-changed'>;
|
|
36
|
+
readonly write: false;
|
|
37
|
+
}
|
|
38
|
+
export declare function casExpiredHook(code: string): CasHookResult | null;
|
|
25
39
|
//# sourceMappingURL=failure-route.d.ts.map
|
|
@@ -4,7 +4,12 @@ const TARGET_TAKEN = new Set(['target-taken', 'target-exists']);
|
|
|
4
4
|
const VALIDATION = new Set(['validation-failed', 'invalid-decision']);
|
|
5
5
|
const COMMIT = new Set(['commit-failed', 'commit-refused']);
|
|
6
6
|
const SCHEMA = new Set(['schema-invalid', 'schema-version']);
|
|
7
|
+
export function routeLimitFailure(lengths) {
|
|
8
|
+
return { kind: 'over-limit', reportOnly: true, reason: 'merge-over-limit', lengths };
|
|
9
|
+
}
|
|
7
10
|
export function routeFailure(code) {
|
|
11
|
+
if (code === 'merge-over-limit')
|
|
12
|
+
return routeLimitFailure({});
|
|
8
13
|
if (PARAMETER.has(code))
|
|
9
14
|
return { kind: 'parameter', reportOnly: false };
|
|
10
15
|
if (SOURCE_GONE.has(code))
|
|
@@ -19,4 +24,11 @@ export function routeFailure(code) {
|
|
|
19
24
|
return { kind: 'schema', reportOnly: true };
|
|
20
25
|
return { kind: 'runtime', reportOnly: true };
|
|
21
26
|
}
|
|
27
|
+
export function casExpiredHook(code) {
|
|
28
|
+
if (code === 'target-changed' || code === 'target-taken')
|
|
29
|
+
return { kind: 'expired', reason: 'target-taken', write: false };
|
|
30
|
+
if (code === 'source-changed' || code === 'support-changed')
|
|
31
|
+
return { kind: 'expired', reason: 'source-changed', write: false };
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
22
34
|
//# sourceMappingURL=failure-route.js.map
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
/** Pure v2 ledger normalization/projection. No IO. */
|
|
2
2
|
import { migrateV1Row } from "./migrate-v1.js";
|
|
3
|
+
import { isV3Row } from "./row-v3.js";
|
|
4
|
+
import { v3ToLegacy } from "./row-v3-bridge.js";
|
|
3
5
|
import { queueOf } from "./state.js";
|
|
4
6
|
function isRow(value) {
|
|
5
7
|
const row = value;
|
|
@@ -17,11 +19,18 @@ export function parseLedger(raw) {
|
|
|
17
19
|
return { ok: false, ledger: { schemaVersion: 2, rows: [] }, note: 'invalid json' };
|
|
18
20
|
}
|
|
19
21
|
const body = parsed;
|
|
20
|
-
if (typeof body.schemaVersion === 'number' && body.schemaVersion >
|
|
22
|
+
if (typeof body.schemaVersion === 'number' && body.schemaVersion > 3) {
|
|
21
23
|
return { ok: false, ledger: { schemaVersion: 2, rows: [] }, note: 'merge-state-forward-only' };
|
|
22
24
|
}
|
|
23
25
|
if (!Array.isArray(body.rows))
|
|
24
26
|
return { ok: false, ledger: { schemaVersion: 2, rows: [] }, note: 'rows missing' };
|
|
27
|
+
if (body.schemaVersion === 3) {
|
|
28
|
+
if (!body.rows.every(isV3Row)) {
|
|
29
|
+
const v3Like = body.rows.some(row => row !== null && typeof row === 'object' && 'pairKey' in row && 'version' in row);
|
|
30
|
+
return { ok: false, ledger: { schemaVersion: 2, rows: [] }, note: v3Like ? 'merge-state-needs-repair' : 'merge-state-forward-only' };
|
|
31
|
+
}
|
|
32
|
+
return { ok: true, ledger: { schemaVersion: 2, rows: body.rows.map(v3ToLegacy) } };
|
|
33
|
+
}
|
|
25
34
|
const rows = [];
|
|
26
35
|
let skipped = 0;
|
|
27
36
|
for (const value of body.rows) {
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read-time convergence facts for pending rows (FR-LIFE-14).
|
|
3
|
+
*
|
|
4
|
+
* Snapshot and reconcile must agree on WHY a pending row is no longer actionable, but no
|
|
5
|
+
* reader may write. This module is the single derivation both sides call: given the live
|
|
6
|
+
* library view it answers absent/source-gone/target-taken/source-changed, and the
|
|
7
|
+
* persisted row state is only consulted for an already-recorded expiry.
|
|
8
|
+
*/
|
|
9
|
+
import type { RevisionRef } from '../contracts.ts';
|
|
10
|
+
import type { SkillCard } from '../skill-card.ts';
|
|
11
|
+
import type { V4Row } from './row-v4.ts';
|
|
12
|
+
/** Why a pending row reads as expired. `source-gone` rows are removed by reconcile. */
|
|
13
|
+
export type PendingExpiryKind = 'target-taken' | 'source-changed' | 'source-gone';
|
|
14
|
+
/** The live library facts the derivation needs; no io, no writes. */
|
|
15
|
+
export interface LiveRowFacts {
|
|
16
|
+
readonly managed: (name: string) => boolean;
|
|
17
|
+
readonly targetRevisionRef: (name: string) => RevisionRef;
|
|
18
|
+
readonly sourceRevisionRef: (a: string, b: string) => RevisionRef;
|
|
19
|
+
readonly supportDigest: (names: readonly string[]) => string;
|
|
20
|
+
}
|
|
21
|
+
export declare function liveRowFactsOf(cards: readonly SkillCard[]): LiveRowFacts;
|
|
22
|
+
/**
|
|
23
|
+
* The read-only expiry verdict for one row.
|
|
24
|
+
* @param row - the persisted row (only pending rows converge here).
|
|
25
|
+
* @param live - current library facts; absent means "cannot derive".
|
|
26
|
+
* @returns the expiry kind, or null when the row is still actionable.
|
|
27
|
+
*/
|
|
28
|
+
export declare function pendingExpiry(row: V4Row, live: LiveRowFacts | undefined): PendingExpiryKind | null;
|
|
29
|
+
/** The persisted expiry kind, when the row already carries one. */
|
|
30
|
+
export declare function persistedExpiry(row: V4Row): PendingExpiryKind | null;
|
|
31
|
+
//# sourceMappingURL=live-facts.d.ts.map
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { revisionMismatch, sourceRevisionRefOf, supportDigestOf, targetRevisionRefOf } from "../revision.js";
|
|
2
|
+
export function liveRowFactsOf(cards) {
|
|
3
|
+
const byName = new Map(cards.map(card => [card.name, card]));
|
|
4
|
+
return {
|
|
5
|
+
managed: name => byName.get(name)?.managed === true,
|
|
6
|
+
targetRevisionRef: name => targetRevisionRefOf(cards, name),
|
|
7
|
+
sourceRevisionRef: (a, b) => sourceRevisionRefOf(cards, a, b),
|
|
8
|
+
supportDigest: names => supportDigestOf(cards, names),
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* The read-only expiry verdict for one row.
|
|
13
|
+
* @param row - the persisted row (only pending rows converge here).
|
|
14
|
+
* @param live - current library facts; absent means "cannot derive".
|
|
15
|
+
* @returns the expiry kind, or null when the row is still actionable.
|
|
16
|
+
*/
|
|
17
|
+
export function pendingExpiry(row, live) {
|
|
18
|
+
if (live === undefined)
|
|
19
|
+
return null;
|
|
20
|
+
if (row.state === 'verify') {
|
|
21
|
+
return !live.managed(row.a) || !live.managed(row.b) ? 'source-gone' : null;
|
|
22
|
+
}
|
|
23
|
+
if (row.state !== 'pending' && row.state !== 'fuse' && row.state !== 'approved')
|
|
24
|
+
return null;
|
|
25
|
+
if (!live.managed(row.a) || !live.managed(row.b))
|
|
26
|
+
return 'source-gone';
|
|
27
|
+
const decision = row.decision;
|
|
28
|
+
if (row.state !== 'pending') {
|
|
29
|
+
if (revisionMismatch(decision.sourceRevisionRef, live.sourceRevisionRef(row.a, row.b)) !== null)
|
|
30
|
+
return 'source-changed';
|
|
31
|
+
if (decision.supportDigest !== undefined && decision.supportDigest !== live.supportDigest([decision.target, row.a, row.b]))
|
|
32
|
+
return 'source-changed';
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
if (decision.mode !== 'create-umbrella') {
|
|
36
|
+
if (!live.managed(decision.target))
|
|
37
|
+
return 'target-taken';
|
|
38
|
+
}
|
|
39
|
+
// A create-umbrella decision recorded "this name was free"; the name being taken now is
|
|
40
|
+
// the same conflict the approve precheck reports.
|
|
41
|
+
if (revisionMismatch(decision.targetRevisionRef, live.targetRevisionRef(decision.target)) !== null)
|
|
42
|
+
return 'target-taken';
|
|
43
|
+
const expectedSource = decision.sourceRevisionRef;
|
|
44
|
+
if (revisionMismatch(expectedSource, live.sourceRevisionRef(row.a, row.b)) !== null)
|
|
45
|
+
return 'source-changed';
|
|
46
|
+
if (decision.supportDigest !== undefined && decision.supportDigest !== live.supportDigest([decision.target, row.a, row.b]))
|
|
47
|
+
return 'source-changed';
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
/** The persisted expiry kind, when the row already carries one. */
|
|
51
|
+
export function persistedExpiry(row) {
|
|
52
|
+
return row.state === 'pending' && row.expired !== undefined ? row.expired : null;
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=live-facts.js.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { policyStageLimits, type SkillLimits } from '@lmzhen/dsh-evolution-core';
|
|
2
|
+
export interface MergeLimitsSnapshot {
|
|
3
|
+
readonly skillLimits: SkillLimits;
|
|
4
|
+
readonly limitsDigest: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function resolveLimitsSnapshot(policy?: Parameters<typeof policyStageLimits>[0]): MergeLimitsSnapshot;
|
|
7
|
+
export declare function limitsSnapshotOf(skillLimits: SkillLimits): MergeLimitsSnapshot;
|
|
8
|
+
export declare function mergeLimitFinding(path: string, limit: string, observed: number, limitValue: number): {
|
|
9
|
+
readonly rule: string;
|
|
10
|
+
readonly path: string;
|
|
11
|
+
readonly severity: 'block';
|
|
12
|
+
readonly code: 'limit';
|
|
13
|
+
readonly limit: string;
|
|
14
|
+
readonly observed: number;
|
|
15
|
+
readonly limitValue: number;
|
|
16
|
+
readonly message: string;
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=merge-limits.d.ts.map
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/** One limits snapshot shared by authoring, validation and commit. */
|
|
2
|
+
import { createHash } from 'node:crypto';
|
|
3
|
+
import { DEFAULT_SKILL_LIMITS, policyStageLimits } from '@lmzhen/dsh-evolution-core';
|
|
4
|
+
function canonical(value) {
|
|
5
|
+
if (value === null || typeof value !== 'object')
|
|
6
|
+
return JSON.stringify(value);
|
|
7
|
+
if (Array.isArray(value))
|
|
8
|
+
return '[' + value.map(canonical).join(',') + ']';
|
|
9
|
+
const object = value;
|
|
10
|
+
return '{' + Object.keys(object).sort().map(key => JSON.stringify(key) + ':' + canonical(object[key])).join(',') + '}';
|
|
11
|
+
}
|
|
12
|
+
export function resolveLimitsSnapshot(policy) {
|
|
13
|
+
const skillLimits = { ...DEFAULT_SKILL_LIMITS, ...policyStageLimits(policy) };
|
|
14
|
+
return { skillLimits, limitsDigest: createHash('sha256').update(canonical(skillLimits)).digest('hex') };
|
|
15
|
+
}
|
|
16
|
+
export function limitsSnapshotOf(skillLimits) {
|
|
17
|
+
return { skillLimits, limitsDigest: createHash('sha256').update(canonical(skillLimits)).digest('hex') };
|
|
18
|
+
}
|
|
19
|
+
export function mergeLimitFinding(path, limit, observed, limitValue) {
|
|
20
|
+
return { rule: 'limit', path, severity: 'block', code: 'limit', limit, observed, limitValue, message: path + ' exceeds ' + limit + ' (' + String(observed) + ' > ' + String(limitValue) + ')' };
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=merge-limits.js.map
|
|
@@ -0,0 +1,41 @@
|
|
|
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
|