@lmzhen/dsh-evolution-merge 0.0.0-stage → 0.28.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/README.md +25 -2
- package/lib/index.js +3997 -0
- package/lib/types/adapters/channel.d.ts +42 -0
- package/lib/types/adapters/library.d.ts +8 -0
- package/lib/types/adapters/model.d.ts +31 -0
- package/lib/types/adapters/undo.d.ts +9 -0
- package/lib/types/approve-command.d.ts +22 -0
- package/lib/types/authoring-flow.d.ts +35 -0
- package/lib/types/channel-port.d.ts +60 -0
- package/lib/types/commands.d.ts +55 -0
- package/lib/types/commit-assembly.d.ts +25 -0
- package/lib/types/commit-execute.d.ts +29 -0
- package/lib/types/commit-plan.d.ts +45 -0
- package/lib/types/commit-receipt.d.ts +14 -0
- package/lib/types/contracts.d.ts +136 -0
- package/lib/types/coordinator.d.ts +57 -0
- package/lib/types/decision.d.ts +18 -0
- package/lib/types/doctor.d.ts +10 -0
- package/lib/types/gate-cache.d.ts +12 -0
- package/lib/types/gate-filter.d.ts +31 -0
- package/lib/types/index.d.ts +82 -0
- package/lib/types/ladder.d.ts +65 -0
- package/lib/types/merge-command.d.ts +36 -0
- package/lib/types/merge-routes.d.ts +23 -0
- package/lib/types/merge-tool.d.ts +22 -0
- package/lib/types/new-child-authoring.d.ts +29 -0
- package/lib/types/pair-command.d.ts +20 -0
- package/lib/types/params.d.ts +13 -0
- package/lib/types/pending-actions.d.ts +17 -0
- package/lib/types/prompts.d.ts +13 -0
- package/lib/types/propose.d.ts +26 -0
- package/lib/types/read-commands.d.ts +9 -0
- package/lib/types/report.d.ts +10 -0
- package/lib/types/resume-command.d.ts +24 -0
- package/lib/types/round2-outcome.d.ts +13 -0
- package/lib/types/routes.d.ts +49 -0
- package/lib/types/rules.d.ts +24 -0
- package/lib/types/run-shell.d.ts +65 -0
- package/lib/types/runtime.d.ts +38 -0
- package/lib/types/scan-command.d.ts +21 -0
- package/lib/types/scan-ports.d.ts +32 -0
- package/lib/types/scan-run.d.ts +44 -0
- package/lib/types/screening-port.d.ts +47 -0
- package/lib/types/screening.d.ts +30 -0
- package/lib/types/skipped.d.ts +8 -0
- package/lib/types/stage-tool-registry.d.ts +14 -0
- package/lib/types/stage-tool.d.ts +45 -0
- package/lib/types/staged-tree.d.ts +4 -0
- package/lib/types/staging-files.d.ts +15 -0
- package/lib/types/staging.d.ts +43 -0
- package/lib/types/state.d.ts +29 -0
- package/lib/types/status.d.ts +14 -0
- package/lib/types/supersede.d.ts +8 -0
- package/lib/types/undo-merge.d.ts +13 -0
- package/package.json +40 -4
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adapt the platform SubagentChannel to the merge ConversationChannelLike. The optional
|
|
3
|
+
* two-turn methods are checked at call time so an older channel degrades to E-323 instead
|
|
4
|
+
* of throwing a TypeError.
|
|
5
|
+
*/
|
|
6
|
+
import type { ConversationChannelLike } from '../channel-port.ts';
|
|
7
|
+
interface PlatformTurn {
|
|
8
|
+
readonly childId: unknown;
|
|
9
|
+
readonly stopReason: string;
|
|
10
|
+
readonly text: string;
|
|
11
|
+
}
|
|
12
|
+
type PlatformOutcome = {
|
|
13
|
+
readonly kind: 'ok';
|
|
14
|
+
readonly childId: unknown;
|
|
15
|
+
readonly turn: PlatformTurn;
|
|
16
|
+
} | {
|
|
17
|
+
readonly kind: 'unavailable';
|
|
18
|
+
readonly code: string;
|
|
19
|
+
readonly reason: string;
|
|
20
|
+
} | {
|
|
21
|
+
readonly kind: 'aborted';
|
|
22
|
+
};
|
|
23
|
+
export interface SubagentChannelLike {
|
|
24
|
+
open?(spec: {
|
|
25
|
+
parent: unknown;
|
|
26
|
+
label: string;
|
|
27
|
+
promptText: string;
|
|
28
|
+
kind: 'reviewer' | 'maintainer';
|
|
29
|
+
allow: readonly string[];
|
|
30
|
+
cwd?: string;
|
|
31
|
+
timeoutMs: number;
|
|
32
|
+
signal?: AbortSignal;
|
|
33
|
+
}): Promise<PlatformOutcome>;
|
|
34
|
+
continueTurn?(childId: string, promptText: string, options?: {
|
|
35
|
+
timeoutMs?: number;
|
|
36
|
+
signal?: AbortSignal;
|
|
37
|
+
}): Promise<PlatformOutcome>;
|
|
38
|
+
dispose?(childId: string): Promise<void>;
|
|
39
|
+
}
|
|
40
|
+
export declare function subagentChannelAdapter(channel: SubagentChannelLike): ConversationChannelLike;
|
|
41
|
+
export {};
|
|
42
|
+
//# sourceMappingURL=channel.d.ts.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Library adapter: the only place the merge domain touches SkillLibrary's commit kernel.
|
|
3
|
+
* The domain stays port-shaped; this file is the composition seam.
|
|
4
|
+
*/
|
|
5
|
+
import type { SkillLibrary } from '@lmzhen/dsh-evolution-core';
|
|
6
|
+
import type { CommitPort } from '../commit-execute.ts';
|
|
7
|
+
export declare function skillLibraryPort(skills: SkillLibrary): CommitPort;
|
|
8
|
+
//# sourceMappingURL=library.d.ts.map
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structural ModelPort adapter over the platform llm service. The platform exposes either
|
|
3
|
+
* `stream()` (the current shape) or the older prepareCall()/stream pair; both return raw text
|
|
4
|
+
* because the gate and proposer own JSON extraction.
|
|
5
|
+
*/
|
|
6
|
+
import type { ModelPort } from '../propose.ts';
|
|
7
|
+
export interface ModelRoute {
|
|
8
|
+
readonly provider: string;
|
|
9
|
+
readonly model: string;
|
|
10
|
+
}
|
|
11
|
+
export interface LlmChunkLike {
|
|
12
|
+
readonly type: string;
|
|
13
|
+
readonly text?: string;
|
|
14
|
+
readonly usage?: unknown;
|
|
15
|
+
readonly reason?: {
|
|
16
|
+
readonly kind?: string;
|
|
17
|
+
readonly failure?: {
|
|
18
|
+
readonly message?: string;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export interface LlmCallLike {
|
|
23
|
+
readonly config: Record<string, unknown>;
|
|
24
|
+
stream(input: Record<string, unknown>): AsyncIterable<LlmChunkLike>;
|
|
25
|
+
}
|
|
26
|
+
export interface LlmServiceLike {
|
|
27
|
+
prepareCall?(config: Record<string, unknown>, signal?: AbortSignal): Promise<LlmCallLike>;
|
|
28
|
+
stream?(options: Record<string, unknown>): AsyncIterable<LlmChunkLike>;
|
|
29
|
+
}
|
|
30
|
+
export declare function createModelPort(llm: LlmServiceLike, route: () => ModelRoute): ModelPort;
|
|
31
|
+
//# sourceMappingURL=model.d.ts.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SkillLibrary-backed undo sink. Blobs are content-addressed but the library exposes them by
|
|
3
|
+
* version, so the first readBlob call indexes all version bodies once; an undo is rare enough
|
|
4
|
+
* that this is preferable to adding a second hash index.
|
|
5
|
+
*/
|
|
6
|
+
import { type SkillLibrary } from '@lmzhen/dsh-evolution-core';
|
|
7
|
+
import type { MergeUndoPort } from '../undo-merge.ts';
|
|
8
|
+
export declare function skillLibraryUndoPort(skills: SkillLibrary): MergeUndoPort;
|
|
9
|
+
//# sourceMappingURL=undo.d.ts.map
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* approve command: one pending row is atomically taken to fuse, then a new run executes
|
|
3
|
+
* round2 with the persisted decision. A second approve loses at approvePending (not-pending).
|
|
4
|
+
*/
|
|
5
|
+
import type { EvolutionIoLike } from '@lmzhen/dsh-evolution-core';
|
|
6
|
+
import type { MergeDecision, MergeRow } from './contracts.ts';
|
|
7
|
+
import type { MergeRegistryPort, WithMergeRunResult } from './run-shell.ts';
|
|
8
|
+
import type { ScanRound2Outcome } from './scan-run.ts';
|
|
9
|
+
export interface ApprovePorts {
|
|
10
|
+
round2(row: MergeRow, decision: MergeDecision, signal: AbortSignal, runId: string): Promise<ScanRound2Outcome>;
|
|
11
|
+
}
|
|
12
|
+
export interface RunApproveCommandOptions {
|
|
13
|
+
readonly io: EvolutionIoLike;
|
|
14
|
+
readonly home: string;
|
|
15
|
+
readonly registry: MergeRegistryPort;
|
|
16
|
+
readonly ports: ApprovePorts;
|
|
17
|
+
readonly rowId: string;
|
|
18
|
+
readonly platformWrite: boolean;
|
|
19
|
+
readonly now: () => number;
|
|
20
|
+
}
|
|
21
|
+
export declare function runApproveCommand(options: RunApproveCommandOptions): Promise<WithMergeRunResult>;
|
|
22
|
+
//# sourceMappingURL=approve-command.d.ts.map
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authoring flow: create the staging tree, let the author write it, run the deterministic
|
|
3
|
+
* rule gate, then commit through the injected CommitPort. The channel adapter and the
|
|
4
|
+
* author tool live outside; this is the seam they share.
|
|
5
|
+
*/
|
|
6
|
+
import type { EvolutionIoLike } from '@lmzhen/dsh-evolution-core';
|
|
7
|
+
import { type RuleFinding } from './rules.ts';
|
|
8
|
+
import { type CommitPort, type CommitStagedResult } from './commit-execute.ts';
|
|
9
|
+
import type { StagedTree } from './rules.ts';
|
|
10
|
+
import type { SkillCard } from './screening.ts';
|
|
11
|
+
export interface RunAuthoringOptions {
|
|
12
|
+
readonly io: EvolutionIoLike;
|
|
13
|
+
readonly home: string;
|
|
14
|
+
readonly runId: string;
|
|
15
|
+
readonly target: string;
|
|
16
|
+
readonly cards: readonly SkillCard[];
|
|
17
|
+
readonly author: (staging: {
|
|
18
|
+
readonly home: string;
|
|
19
|
+
readonly runId: string;
|
|
20
|
+
}) => Promise<string>;
|
|
21
|
+
readonly commitPort: CommitPort;
|
|
22
|
+
readonly now: () => number;
|
|
23
|
+
readonly summary: string;
|
|
24
|
+
}
|
|
25
|
+
export type AuthoringResult = {
|
|
26
|
+
readonly ok: true;
|
|
27
|
+
readonly tree: StagedTree;
|
|
28
|
+
readonly commit: CommitStagedResult;
|
|
29
|
+
} | {
|
|
30
|
+
readonly ok: false;
|
|
31
|
+
readonly message: string;
|
|
32
|
+
readonly findings?: readonly RuleFinding[];
|
|
33
|
+
};
|
|
34
|
+
export declare function runAuthoring(options: RunAuthoringOptions): Promise<AuthoringResult>;
|
|
35
|
+
//# sourceMappingURL=authoring-flow.d.ts.map
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Channel adapter for round 1. It opens the merged child, parses the decision, and exposes
|
|
3
|
+
* an author callback for round 2 when the same child continues. Commit is deliberately
|
|
4
|
+
* outside this adapter: the caller owns staging -> commitStagedRun.
|
|
5
|
+
*/
|
|
6
|
+
import type { MergeDecision, MergeRow } from './contracts.ts';
|
|
7
|
+
import type { SkillCard } from './screening.ts';
|
|
8
|
+
import type { ScanRound1Outcome } from './scan-run.ts';
|
|
9
|
+
export interface ChannelTurnLike {
|
|
10
|
+
readonly text: string;
|
|
11
|
+
readonly stopReason: string;
|
|
12
|
+
}
|
|
13
|
+
export type ChannelTurnOutcome = {
|
|
14
|
+
readonly kind: 'ok';
|
|
15
|
+
readonly childId: string;
|
|
16
|
+
readonly turn: ChannelTurnLike;
|
|
17
|
+
} | {
|
|
18
|
+
readonly kind: 'unavailable';
|
|
19
|
+
readonly code: string;
|
|
20
|
+
readonly reason: string;
|
|
21
|
+
} | {
|
|
22
|
+
readonly kind: 'aborted';
|
|
23
|
+
};
|
|
24
|
+
export interface ConversationChannelLike {
|
|
25
|
+
open(spec: {
|
|
26
|
+
readonly parent: unknown;
|
|
27
|
+
readonly label: string;
|
|
28
|
+
readonly promptText: string;
|
|
29
|
+
readonly kind: 'reviewer' | 'maintainer';
|
|
30
|
+
readonly allow: readonly string[];
|
|
31
|
+
readonly cwd?: string;
|
|
32
|
+
readonly timeoutMs: number;
|
|
33
|
+
readonly signal?: AbortSignal;
|
|
34
|
+
}): Promise<ChannelTurnOutcome>;
|
|
35
|
+
continueTurn(childId: string, promptText: string, options?: {
|
|
36
|
+
readonly timeoutMs?: number;
|
|
37
|
+
readonly signal?: AbortSignal;
|
|
38
|
+
}): Promise<ChannelTurnOutcome>;
|
|
39
|
+
dispose(childId: string): Promise<void>;
|
|
40
|
+
}
|
|
41
|
+
export interface ChannelRound1Options {
|
|
42
|
+
readonly channel: ConversationChannelLike;
|
|
43
|
+
readonly parent: unknown;
|
|
44
|
+
readonly cards: readonly SkillCard[];
|
|
45
|
+
readonly allow: readonly string[];
|
|
46
|
+
readonly cwd?: string;
|
|
47
|
+
readonly timeoutMs: number;
|
|
48
|
+
}
|
|
49
|
+
export interface ChannelRound1Result {
|
|
50
|
+
readonly outcome: ScanRound1Outcome;
|
|
51
|
+
readonly childId?: string;
|
|
52
|
+
/** Same-child round 2; absent for keep/fail/unavailable. */
|
|
53
|
+
readonly author?: (row: MergeRow, decision: MergeDecision, signal: AbortSignal) => Promise<string>;
|
|
54
|
+
readonly dispose: () => Promise<void>;
|
|
55
|
+
}
|
|
56
|
+
export declare function runRound1OverChannel(options: ChannelRound1Options, candidate: {
|
|
57
|
+
readonly a: string;
|
|
58
|
+
readonly b: string;
|
|
59
|
+
}, signal: AbortSignal): Promise<ChannelRound1Result>;
|
|
60
|
+
//# sourceMappingURL=channel-port.d.ts.map
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure command-surface parser for the /evolution merge prefix. The command layer only
|
|
3
|
+
* validates shape; run/state effects are injected by the host shell.
|
|
4
|
+
*/
|
|
5
|
+
export type MergeCliCommand = {
|
|
6
|
+
readonly verb: 'scan';
|
|
7
|
+
} | {
|
|
8
|
+
readonly verb: 'pair';
|
|
9
|
+
readonly a: string;
|
|
10
|
+
readonly b: string;
|
|
11
|
+
} | {
|
|
12
|
+
readonly verb: 'status';
|
|
13
|
+
readonly id?: string;
|
|
14
|
+
} | {
|
|
15
|
+
readonly verb: 'report';
|
|
16
|
+
readonly id?: string;
|
|
17
|
+
} | {
|
|
18
|
+
readonly verb: 'cancel';
|
|
19
|
+
readonly id?: string;
|
|
20
|
+
} | {
|
|
21
|
+
readonly verb: 'runs';
|
|
22
|
+
} | {
|
|
23
|
+
readonly verb: 'doctor';
|
|
24
|
+
} | {
|
|
25
|
+
readonly verb: 'pending';
|
|
26
|
+
} | {
|
|
27
|
+
readonly verb: 'approve';
|
|
28
|
+
readonly id: string;
|
|
29
|
+
} | {
|
|
30
|
+
readonly verb: 'reject';
|
|
31
|
+
readonly id: string;
|
|
32
|
+
} | {
|
|
33
|
+
readonly verb: 'resume';
|
|
34
|
+
readonly id?: string;
|
|
35
|
+
readonly clear?: string;
|
|
36
|
+
} | {
|
|
37
|
+
readonly verb: 'skipped';
|
|
38
|
+
readonly restore?: string;
|
|
39
|
+
} | {
|
|
40
|
+
readonly verb: 'undo';
|
|
41
|
+
readonly target: string;
|
|
42
|
+
readonly run: string;
|
|
43
|
+
};
|
|
44
|
+
export type ParseMergeCommandResult = {
|
|
45
|
+
readonly ok: true;
|
|
46
|
+
readonly command: MergeCliCommand;
|
|
47
|
+
readonly help?: boolean;
|
|
48
|
+
} | {
|
|
49
|
+
readonly ok: false;
|
|
50
|
+
readonly code: 'usage';
|
|
51
|
+
readonly message: string;
|
|
52
|
+
};
|
|
53
|
+
export declare function parseMergeCommand(argv: readonly string[]): ParseMergeCommandResult;
|
|
54
|
+
export declare function mergeUsage(): string;
|
|
55
|
+
//# sourceMappingURL=commands.d.ts.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turn a fully written staging tree into a CommitMergePlan.
|
|
3
|
+
*
|
|
4
|
+
* Source bodies come from the LIVE tree (the plan's CAS baseline), the target body from
|
|
5
|
+
* the merged tree. This function is pure except for the injected reads; it never commits.
|
|
6
|
+
*/
|
|
7
|
+
import type { CommitMergePlan, WriteOrigin } from '@lmzhen/dsh-evolution-core';
|
|
8
|
+
import type { EvolutionIoLike } from '@lmzhen/dsh-evolution-core';
|
|
9
|
+
export interface CommitAssemblyPort {
|
|
10
|
+
/** Current SKILL.md body, or null when the skill is not live. */
|
|
11
|
+
readSkill(name: string): Promise<string | null>;
|
|
12
|
+
}
|
|
13
|
+
export interface CommitAssemblyOptions {
|
|
14
|
+
readonly origin: WriteOrigin;
|
|
15
|
+
readonly summary: string;
|
|
16
|
+
}
|
|
17
|
+
export type CommitAssemblyResult = {
|
|
18
|
+
readonly ok: true;
|
|
19
|
+
readonly plan: CommitMergePlan;
|
|
20
|
+
} | {
|
|
21
|
+
readonly ok: false;
|
|
22
|
+
readonly message: string;
|
|
23
|
+
};
|
|
24
|
+
export declare function assembleStagedCommit(io: EvolutionIoLike, home: string, runId: string, port: CommitAssemblyPort, options: CommitAssemblyOptions): Promise<CommitAssemblyResult>;
|
|
25
|
+
//# sourceMappingURL=commit-assembly.d.ts.map
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Execute one staged merge: assemble the plan, call the host commit port, then write the
|
|
3
|
+
* receipt. A failed commit returns without a receipt; a landed commit with a failed receipt
|
|
4
|
+
* stays successful and carries a warning.
|
|
5
|
+
*/
|
|
6
|
+
import type { CommitMergePlan, CommitMergeResult, EvolutionIoLike } from '@lmzhen/dsh-evolution-core';
|
|
7
|
+
import { type CommitAssemblyPort } from './commit-assembly.ts';
|
|
8
|
+
import { type CommitReceipt } from './commit-receipt.ts';
|
|
9
|
+
export interface CommitPort extends CommitAssemblyPort {
|
|
10
|
+
commitMerge(plan: CommitMergePlan): Promise<CommitMergeResult>;
|
|
11
|
+
}
|
|
12
|
+
export interface CommitStagedOptions {
|
|
13
|
+
readonly origin: CommitMergePlan['origin'];
|
|
14
|
+
readonly summary: string;
|
|
15
|
+
readonly now: () => number;
|
|
16
|
+
}
|
|
17
|
+
export type CommitStagedResult = {
|
|
18
|
+
readonly ok: true;
|
|
19
|
+
readonly plan: CommitMergePlan;
|
|
20
|
+
readonly result: CommitMergeResult;
|
|
21
|
+
readonly receipt?: CommitReceipt;
|
|
22
|
+
readonly warning?: string;
|
|
23
|
+
} | {
|
|
24
|
+
readonly ok: false;
|
|
25
|
+
readonly message: string;
|
|
26
|
+
readonly plan?: CommitMergePlan;
|
|
27
|
+
};
|
|
28
|
+
export declare function commitStagedRun(io: EvolutionIoLike, home: string, runId: string, port: CommitPort, options: CommitStagedOptions): Promise<CommitStagedResult>;
|
|
29
|
+
//# sourceMappingURL=commit-execute.d.ts.map
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure commit-plan assembly for a staged merge tree.
|
|
3
|
+
*
|
|
4
|
+
* The control plane has already chosen the target name and the child wrote merged/<target>/.
|
|
5
|
+
* This module only turns those bytes into a CommitMergePlan; it never reads the live tree and
|
|
6
|
+
* never decides whether a merge is allowed (validateStagedTree does that).
|
|
7
|
+
*/
|
|
8
|
+
import type { CommitMergePlan, WriteOrigin } from '@lmzhen/dsh-evolution-core';
|
|
9
|
+
export type ResolveTargetResult = {
|
|
10
|
+
readonly ok: true;
|
|
11
|
+
readonly name: string;
|
|
12
|
+
readonly suffix: number;
|
|
13
|
+
} | {
|
|
14
|
+
readonly ok: false;
|
|
15
|
+
readonly message: string;
|
|
16
|
+
};
|
|
17
|
+
/** Pick the first free target: requested, then -v2, -v3, ... (never truncate a name). */
|
|
18
|
+
export declare function resolveTargetName(requested: string, exists: (name: string) => boolean): ResolveTargetResult;
|
|
19
|
+
/** Rewrite only the frontmatter name; body bytes stay otherwise intact. */
|
|
20
|
+
export declare function rewriteFrontmatterName(body: string, name: string): string;
|
|
21
|
+
export interface BuildCommitPlanInput {
|
|
22
|
+
readonly target: string;
|
|
23
|
+
readonly create: boolean;
|
|
24
|
+
readonly mergedBody: string;
|
|
25
|
+
readonly mergedFiles: readonly {
|
|
26
|
+
readonly path: string;
|
|
27
|
+
readonly content: string;
|
|
28
|
+
}[];
|
|
29
|
+
readonly targetCurrent: string | null;
|
|
30
|
+
readonly sourceBodies: readonly {
|
|
31
|
+
readonly name: string;
|
|
32
|
+
readonly body: string;
|
|
33
|
+
}[];
|
|
34
|
+
readonly origin: WriteOrigin;
|
|
35
|
+
readonly summary: string;
|
|
36
|
+
}
|
|
37
|
+
export type BuildCommitPlanResult = {
|
|
38
|
+
readonly ok: true;
|
|
39
|
+
readonly plan: CommitMergePlan;
|
|
40
|
+
} | {
|
|
41
|
+
readonly ok: false;
|
|
42
|
+
readonly message: string;
|
|
43
|
+
};
|
|
44
|
+
export declare function buildCommitPlan(input: BuildCommitPlanInput): BuildCommitPlanResult;
|
|
45
|
+
//# sourceMappingURL=commit-plan.d.ts.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { EvolutionIoLike } from '@lmzhen/dsh-evolution-core';
|
|
2
|
+
export interface CommitReceipt {
|
|
3
|
+
readonly runId: string;
|
|
4
|
+
readonly unitId: string;
|
|
5
|
+
readonly target: string;
|
|
6
|
+
readonly create: boolean;
|
|
7
|
+
readonly sources: readonly string[];
|
|
8
|
+
readonly archived: readonly string[];
|
|
9
|
+
readonly at: number;
|
|
10
|
+
}
|
|
11
|
+
export declare function commitReceiptPath(home: string, runId: string): string;
|
|
12
|
+
export declare function writeCommitReceipt(io: EvolutionIoLike, home: string, receipt: CommitReceipt): Promise<string>;
|
|
13
|
+
export declare function readCommitReceipt(io: EvolutionIoLike, home: string, runId: string): Promise<CommitReceipt | null>;
|
|
14
|
+
//# sourceMappingURL=commit-receipt.d.ts.map
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Frozen merge-domain vocabulary. No io, no host, no imports from the plugin shell.
|
|
3
|
+
*
|
|
4
|
+
* The data layer keeps four states; the user face collapses verify/fuse into one retry
|
|
5
|
+
* queue and keeps the stage as a chip. The API queue must never expose the raw state.
|
|
6
|
+
*/
|
|
7
|
+
export declare const MERGE_STATE_VERSION = 1;
|
|
8
|
+
export type MergePairState = 'verify' | 'pending' | 'fuse' | 'skipped';
|
|
9
|
+
export type MergeQueue = 'pending' | 'retry' | 'skipped';
|
|
10
|
+
export type MergeStage = 'verify' | 'decide' | 'author' | 'commit';
|
|
11
|
+
export type MergeCommand = 'scan' | 'pair' | 'approve' | 'resume';
|
|
12
|
+
export declare const MERGE_PAIR_STATES: readonly MergePairState[];
|
|
13
|
+
export declare const MERGE_QUEUES: readonly MergeQueue[];
|
|
14
|
+
/** User-facing queue of one data state. verify/fuse share retry, not two tabs. */
|
|
15
|
+
export declare function queueOf(state: MergePairState): MergeQueue;
|
|
16
|
+
/** Coarse stage chip; skipped has no active stage. */
|
|
17
|
+
export declare function stageOf(state: MergePairState): MergeStage | null;
|
|
18
|
+
/** Stable pair identity; NUL cannot appear in a skill name. */
|
|
19
|
+
export declare function pairKey(a: string, b: string): string;
|
|
20
|
+
/** Deterministic, URL-safe id derived from the pair key (FNV-1a 32). */
|
|
21
|
+
export declare function rowIdOf(key: string): string;
|
|
22
|
+
export interface MergeFailure {
|
|
23
|
+
readonly stage: 'screening' | 'decide' | 'author' | 'validate' | 'commit';
|
|
24
|
+
readonly code: string;
|
|
25
|
+
readonly message: string;
|
|
26
|
+
readonly retryable: boolean;
|
|
27
|
+
readonly retryFrom: 'agent1' | 'agent2' | 'none';
|
|
28
|
+
}
|
|
29
|
+
/** One persisted pair. The id is stable for the UI; the pairKey is the natural key. */
|
|
30
|
+
export interface MergeGateFact {
|
|
31
|
+
readonly level: 'L0' | 'L1' | 'L2';
|
|
32
|
+
readonly verdict: 1 | 0 | -1;
|
|
33
|
+
readonly reason: string;
|
|
34
|
+
readonly cached?: boolean;
|
|
35
|
+
readonly auditOverride?: boolean;
|
|
36
|
+
}
|
|
37
|
+
export interface MergeCandidate {
|
|
38
|
+
readonly a: string;
|
|
39
|
+
readonly b: string;
|
|
40
|
+
readonly score?: number;
|
|
41
|
+
readonly arms?: readonly string[];
|
|
42
|
+
readonly reason?: string;
|
|
43
|
+
readonly gate?: MergeGateFact;
|
|
44
|
+
readonly source?: 'lexical' | 'proposed';
|
|
45
|
+
}
|
|
46
|
+
export interface MergeDecision {
|
|
47
|
+
readonly shouldMerge: boolean;
|
|
48
|
+
readonly mode: 'merge-into-existing' | 'create-umbrella' | 'keep';
|
|
49
|
+
readonly target: string;
|
|
50
|
+
readonly sources: readonly string[];
|
|
51
|
+
readonly rationale: string;
|
|
52
|
+
readonly confidence?: number;
|
|
53
|
+
}
|
|
54
|
+
export interface MergeUsage {
|
|
55
|
+
readonly inputTokens?: number;
|
|
56
|
+
readonly outputTokens?: number;
|
|
57
|
+
readonly totalTokens?: number;
|
|
58
|
+
readonly costCny?: number;
|
|
59
|
+
}
|
|
60
|
+
export interface MergeTiming {
|
|
61
|
+
readonly screeningMs?: number;
|
|
62
|
+
readonly gateMs?: number;
|
|
63
|
+
readonly agentMs?: number;
|
|
64
|
+
readonly commitMs?: number;
|
|
65
|
+
}
|
|
66
|
+
export type MergeRunCommand = MergeCommand;
|
|
67
|
+
export interface MergeReportPair {
|
|
68
|
+
readonly id: string;
|
|
69
|
+
readonly pairKey: string;
|
|
70
|
+
readonly a: string;
|
|
71
|
+
readonly b: string;
|
|
72
|
+
readonly queue: MergeQueue;
|
|
73
|
+
readonly candidate?: MergeCandidate;
|
|
74
|
+
readonly gate?: MergeGateFact;
|
|
75
|
+
readonly decision?: MergeDecision;
|
|
76
|
+
readonly outcome: 'merged' | 'kept' | 'pending' | 'failed' | 'cancelled';
|
|
77
|
+
readonly target?: {
|
|
78
|
+
readonly requested: string;
|
|
79
|
+
readonly actual: string;
|
|
80
|
+
readonly created: boolean;
|
|
81
|
+
};
|
|
82
|
+
readonly archived: readonly string[];
|
|
83
|
+
readonly unitId?: string;
|
|
84
|
+
readonly failure?: MergeFailure;
|
|
85
|
+
readonly usage?: MergeUsage;
|
|
86
|
+
readonly timing?: MergeTiming;
|
|
87
|
+
}
|
|
88
|
+
export interface MergeReport {
|
|
89
|
+
readonly schemaVersion: 1;
|
|
90
|
+
readonly runId: string;
|
|
91
|
+
readonly kind: 'merge';
|
|
92
|
+
readonly command: MergeRunCommand;
|
|
93
|
+
readonly startedAt: number;
|
|
94
|
+
readonly endedAt: number;
|
|
95
|
+
readonly stopReason: 'completed' | 'failed' | 'cancelled' | 'timeout';
|
|
96
|
+
readonly approval: {
|
|
97
|
+
readonly platformWrite: boolean;
|
|
98
|
+
readonly mergeApproval: boolean;
|
|
99
|
+
};
|
|
100
|
+
readonly scope: {
|
|
101
|
+
readonly candidatePairs: number;
|
|
102
|
+
readonly queueBefore: Record<MergeQueue, number>;
|
|
103
|
+
};
|
|
104
|
+
readonly pairs: readonly MergeReportPair[];
|
|
105
|
+
readonly totals: Record<'merged' | 'kept' | 'pending' | 'failed', number>;
|
|
106
|
+
readonly notes: readonly string[];
|
|
107
|
+
readonly remaining?: readonly {
|
|
108
|
+
readonly pairKey: string;
|
|
109
|
+
readonly queue: MergeQueue;
|
|
110
|
+
}[];
|
|
111
|
+
}
|
|
112
|
+
export interface MergeRow {
|
|
113
|
+
readonly id: string;
|
|
114
|
+
readonly pairKey: string;
|
|
115
|
+
readonly a: string;
|
|
116
|
+
readonly b: string;
|
|
117
|
+
readonly state: MergePairState;
|
|
118
|
+
readonly queue: MergeQueue;
|
|
119
|
+
readonly failure?: MergeFailure;
|
|
120
|
+
/** Round-1 decision, persisted for the later approve round. */
|
|
121
|
+
readonly decision?: MergeDecision;
|
|
122
|
+
readonly runId?: string;
|
|
123
|
+
readonly unitId?: string;
|
|
124
|
+
readonly origin?: 'agent' | 'human';
|
|
125
|
+
readonly attempts?: number;
|
|
126
|
+
readonly createdAt: string;
|
|
127
|
+
readonly updatedAt: string;
|
|
128
|
+
}
|
|
129
|
+
export interface MergeState {
|
|
130
|
+
readonly schemaVersion: typeof MERGE_STATE_VERSION;
|
|
131
|
+
readonly rows: readonly MergeRow[];
|
|
132
|
+
}
|
|
133
|
+
export declare function emptyMergeState(): MergeState;
|
|
134
|
+
/** One record can be retried only when the failure says so and names a stage. */
|
|
135
|
+
export declare function canRetry(record: Pick<MergeRow, 'state' | 'failure'>): boolean;
|
|
136
|
+
//# sourceMappingURL=contracts.d.ts.map
|
|
@@ -0,0 +1,57 @@
|
|
|
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 mutateMergeState in one 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 at: string;
|
|
22
|
+
} | {
|
|
23
|
+
readonly type: 'round1-fail';
|
|
24
|
+
readonly failure: MergeFailure;
|
|
25
|
+
readonly at: string;
|
|
26
|
+
} | {
|
|
27
|
+
readonly type: 'approve';
|
|
28
|
+
readonly runId?: string;
|
|
29
|
+
readonly at: string;
|
|
30
|
+
} | {
|
|
31
|
+
readonly type: 'reject';
|
|
32
|
+
readonly at: string;
|
|
33
|
+
} | {
|
|
34
|
+
readonly type: 'round2-fail';
|
|
35
|
+
readonly failure: MergeFailure;
|
|
36
|
+
readonly at: string;
|
|
37
|
+
} | {
|
|
38
|
+
readonly type: 'round2-success';
|
|
39
|
+
readonly unitId?: string;
|
|
40
|
+
readonly at: string;
|
|
41
|
+
} | {
|
|
42
|
+
readonly type: 'restore';
|
|
43
|
+
readonly at: string;
|
|
44
|
+
} | {
|
|
45
|
+
readonly type: 'source-gone';
|
|
46
|
+
readonly at: string;
|
|
47
|
+
};
|
|
48
|
+
export type TransitionResult = {
|
|
49
|
+
readonly ok: true;
|
|
50
|
+
readonly row: MergeRow | null;
|
|
51
|
+
} | {
|
|
52
|
+
readonly ok: false;
|
|
53
|
+
readonly code: 'invalid-transition';
|
|
54
|
+
readonly message: string;
|
|
55
|
+
};
|
|
56
|
+
export declare function transition(current: MergeRow | undefined, event: MergeEvent): TransitionResult;
|
|
57
|
+
//# sourceMappingURL=coordinator.d.ts.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Round-1 decision parser. The child returns text; the plugin owns strict shape checks.
|
|
3
|
+
* Accepts a whole JSON object or a fenced json block; everything else is decision-invalid.
|
|
4
|
+
*/
|
|
5
|
+
import type { MergeDecision } from './contracts.ts';
|
|
6
|
+
export type DecisionParse = {
|
|
7
|
+
readonly ok: true;
|
|
8
|
+
readonly decision: MergeDecision;
|
|
9
|
+
} | {
|
|
10
|
+
readonly ok: false;
|
|
11
|
+
readonly code: 'decision-invalid';
|
|
12
|
+
readonly message: string;
|
|
13
|
+
};
|
|
14
|
+
export declare function parseDecision(text: string | undefined, pair: {
|
|
15
|
+
readonly a: string;
|
|
16
|
+
readonly b: string;
|
|
17
|
+
}): DecisionParse;
|
|
18
|
+
//# sourceMappingURL=decision.d.ts.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type EvolutionIoLike } from '@lmzhen/dsh-evolution-core';
|
|
2
|
+
export declare const MERGE_DOCTOR_SCHEMA_VERSION = 3;
|
|
3
|
+
export interface MergeDoctorRow {
|
|
4
|
+
readonly key: string;
|
|
5
|
+
readonly label: string;
|
|
6
|
+
readonly status: 'ok' | 'warn' | 'unknown';
|
|
7
|
+
readonly detail: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function mergeDoctor(io: EvolutionIoLike, home: string): Promise<readonly MergeDoctorRow[]>;
|
|
10
|
+
//# sourceMappingURL=doctor.d.ts.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type EvolutionIoLike } from '@lmzhen/dsh-evolution-core';
|
|
2
|
+
import { GateCache } from './ladder.ts';
|
|
3
|
+
export declare const GATE_CACHE_VERSION = 1;
|
|
4
|
+
export declare function gateCachePath(home: string): string;
|
|
5
|
+
export interface LoadGateCacheResult {
|
|
6
|
+
readonly cache: GateCache;
|
|
7
|
+
readonly note?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function loadGateCache(io: EvolutionIoLike, home: string): Promise<LoadGateCacheResult>;
|
|
10
|
+
export declare function saveGateCache(io: EvolutionIoLike, home: string, cache: GateCache): Promise<void>;
|
|
11
|
+
export declare function hasGateCache(cache: GateCache): boolean;
|
|
12
|
+
//# sourceMappingURL=gate-cache.d.ts.map
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gate filter: turn lexical/proposed candidates into the candidates scan may process.
|
|
3
|
+
* L0 keeps are dropped unless the deterministic 10% audit re-runs L2 and overrides.
|
|
4
|
+
*/
|
|
5
|
+
import type { MergeCandidate } from './contracts.ts';
|
|
6
|
+
import { type GateCache, type GateFacts, type GateModelPort, type GateVerdict } from './ladder.ts';
|
|
7
|
+
export interface GateFilterOptions {
|
|
8
|
+
readonly facts: readonly GateFacts[];
|
|
9
|
+
readonly model: GateModelPort;
|
|
10
|
+
readonly modelName: string;
|
|
11
|
+
readonly signal: AbortSignal;
|
|
12
|
+
readonly runSeed: string;
|
|
13
|
+
readonly cache?: GateCache;
|
|
14
|
+
readonly auditRate?: number;
|
|
15
|
+
}
|
|
16
|
+
export interface GateDecision {
|
|
17
|
+
readonly candidate: MergeCandidate;
|
|
18
|
+
readonly verdicts: readonly GateVerdict[];
|
|
19
|
+
readonly auditOverride: boolean;
|
|
20
|
+
}
|
|
21
|
+
export interface GateFilterResult {
|
|
22
|
+
readonly kept: readonly GateDecision[];
|
|
23
|
+
readonly dropped: readonly GateDecision[];
|
|
24
|
+
readonly errors: readonly {
|
|
25
|
+
readonly candidate: MergeCandidate;
|
|
26
|
+
readonly message: string;
|
|
27
|
+
}[];
|
|
28
|
+
readonly calls: number;
|
|
29
|
+
}
|
|
30
|
+
export declare function filterCandidates(candidates: readonly MergeCandidate[], options: GateFilterOptions): Promise<GateFilterResult>;
|
|
31
|
+
//# sourceMappingURL=gate-filter.d.ts.map
|