@lmzhen/dsh-evolution-core 0.30.16 → 0.30.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/composition/index.js +2 -2
- package/lib/{composition-D8Y3-ROd.js → composition-DSesmTvf.js} +3 -3
- package/lib/{http-routes-ifJKGnu6.js → http-routes-D1Ty6nnh.js} +2 -0
- package/lib/http-routes.js +1 -1
- package/lib/index.js +2863 -2049
- package/lib/subagent/index.js +1 -1
- package/lib/types/composition/composer.js +1 -1
- package/lib/types/frontmatter.js +1 -1
- package/lib/types/http-routes.d.ts +2 -0
- package/lib/types/http-routes.js +2 -0
- package/lib/types/index.d.ts +4 -0
- package/lib/types/index.js +4 -0
- package/lib/types/params.js +0 -1
- package/lib/types/platform-services.d.ts +1 -1
- package/lib/types/platform-services.js +2 -2
- package/lib/types/redact.js +2 -2
- package/lib/types/run-registry.d.ts +8 -0
- package/lib/types/run-registry.js +20 -0
- package/lib/types/skill-store.d.ts +10 -0
- package/lib/types/skill-store.js +70 -3
- package/lib/types/tree-lock.d.ts +3 -0
- package/lib/types/tree-lock.js +13 -5
- package/lib/types/unit-backend.d.ts +5 -0
- package/lib/types/unit-backend.js +49 -0
- package/lib/types/unit-journal.d.ts +29 -0
- package/lib/types/unit-journal.js +50 -0
- package/lib/types/unit-recovery.d.ts +5 -0
- package/lib/types/unit-recovery.js +12 -0
- package/lib/types/unit-storage.d.ts +83 -0
- package/lib/types/unit-storage.js +124 -0
- package/lib/types/unit-transaction.d.ts +195 -0
- package/lib/types/unit-transaction.js +445 -0
- package/package.json +1 -1
- package/lib/{ensure-MEYMj9jn.js → ensure-BuWsjPGD.js} +1 -1
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import type { EvolutionIoLike } from './io.ts';
|
|
2
|
+
export declare const UNIT_STORAGE_SCHEMA_VERSION = 1;
|
|
3
|
+
export interface UnitSnapshot {
|
|
4
|
+
readonly schemaVersion: typeof UNIT_STORAGE_SCHEMA_VERSION;
|
|
5
|
+
readonly unitId: string;
|
|
6
|
+
readonly planDigest: string;
|
|
7
|
+
readonly runId: string;
|
|
8
|
+
readonly target: string;
|
|
9
|
+
readonly targetExists: boolean;
|
|
10
|
+
readonly targetBefore: string | null;
|
|
11
|
+
readonly targetAfter?: string;
|
|
12
|
+
readonly supportBefore: readonly {
|
|
13
|
+
path: string;
|
|
14
|
+
content: string | null;
|
|
15
|
+
}[];
|
|
16
|
+
readonly supportAfter: readonly {
|
|
17
|
+
path: string;
|
|
18
|
+
content: string;
|
|
19
|
+
}[];
|
|
20
|
+
readonly sourceBefore: readonly {
|
|
21
|
+
name: string;
|
|
22
|
+
body: string;
|
|
23
|
+
}[];
|
|
24
|
+
readonly origin: string;
|
|
25
|
+
readonly summary: string;
|
|
26
|
+
readonly createdAt: number;
|
|
27
|
+
}
|
|
28
|
+
export interface UnitEvidenceRecord {
|
|
29
|
+
readonly schemaVersion: typeof UNIT_STORAGE_SCHEMA_VERSION;
|
|
30
|
+
readonly unitId: string;
|
|
31
|
+
readonly runId: string;
|
|
32
|
+
readonly planDigest: string;
|
|
33
|
+
readonly state: 'target-only' | 'sources-partial' | 'complete';
|
|
34
|
+
readonly target: {
|
|
35
|
+
before: string | null;
|
|
36
|
+
after: string;
|
|
37
|
+
supportDigest: string;
|
|
38
|
+
created: boolean;
|
|
39
|
+
};
|
|
40
|
+
readonly sources: readonly {
|
|
41
|
+
name: string;
|
|
42
|
+
before: string;
|
|
43
|
+
after: string | null;
|
|
44
|
+
archived: boolean;
|
|
45
|
+
absorbedInto: string;
|
|
46
|
+
}[];
|
|
47
|
+
readonly mutations: number;
|
|
48
|
+
readonly at: number;
|
|
49
|
+
}
|
|
50
|
+
export interface UnitIndexEntry {
|
|
51
|
+
readonly unitId: string;
|
|
52
|
+
readonly storageKey: string;
|
|
53
|
+
readonly runId: string;
|
|
54
|
+
readonly planDigest: string;
|
|
55
|
+
readonly state: UnitEvidenceRecord['state'];
|
|
56
|
+
readonly receiptPath?: string;
|
|
57
|
+
readonly updatedAt: number;
|
|
58
|
+
}
|
|
59
|
+
/** Stable, filesystem-safe key; unitId stays opaque (may contain ':' or '/'). */
|
|
60
|
+
export declare function unitStorageKey(unitId: string): string;
|
|
61
|
+
export declare function unitSnapshotsDir(home: string): string;
|
|
62
|
+
export declare function unitSnapshotPath(home: string, unitId: string): string;
|
|
63
|
+
export declare function unitEvidencePath(home: string, unitId: string): string;
|
|
64
|
+
export declare function unitIndexPath(home: string): string;
|
|
65
|
+
export declare function writeUnitSnapshot(io: EvolutionIoLike, home: string, snapshot: UnitSnapshot): Promise<string>;
|
|
66
|
+
export declare function readUnitSnapshot(io: EvolutionIoLike, home: string, unitId: string): Promise<UnitSnapshot | null>;
|
|
67
|
+
export declare function writeUnitEvidence(io: EvolutionIoLike, home: string, evidence: UnitEvidenceRecord): Promise<string>;
|
|
68
|
+
export declare function readUnitEvidence(io: EvolutionIoLike, home: string, unitId: string): Promise<UnitEvidenceRecord | null>;
|
|
69
|
+
export declare function readUnitIndex(io: EvolutionIoLike, home: string): Promise<UnitIndexEntry[]>;
|
|
70
|
+
export declare function upsertUnitIndex(io: EvolutionIoLike, home: string, entry: UnitIndexEntry): Promise<void>;
|
|
71
|
+
export interface UnitReceiptRecord {
|
|
72
|
+
readonly schemaVersion: typeof UNIT_STORAGE_SCHEMA_VERSION;
|
|
73
|
+
readonly unitId: string;
|
|
74
|
+
readonly runId: string;
|
|
75
|
+
readonly planDigest: string;
|
|
76
|
+
readonly target: string;
|
|
77
|
+
readonly archived: readonly string[];
|
|
78
|
+
readonly at: number;
|
|
79
|
+
}
|
|
80
|
+
export declare function unitReceiptPath(home: string, unitId: string): string;
|
|
81
|
+
export declare function writeUnitReceipt(io: EvolutionIoLike, home: string, receipt: UnitReceiptRecord): Promise<string>;
|
|
82
|
+
export declare function readUnitReceipt(io: EvolutionIoLike, home: string, unitId: string): Promise<UnitReceiptRecord | null>;
|
|
83
|
+
//# sourceMappingURL=unit-storage.d.ts.map
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/** G2 unit storage: opaque unitId -> Windows-safe storage key. */
|
|
2
|
+
import { createHash } from 'node:crypto';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
export const UNIT_STORAGE_SCHEMA_VERSION = 1;
|
|
5
|
+
/** Stable, filesystem-safe key; unitId stays opaque (may contain ':' or '/'). */
|
|
6
|
+
export function unitStorageKey(unitId) {
|
|
7
|
+
return createHash('sha256').update(unitId).digest('hex');
|
|
8
|
+
}
|
|
9
|
+
export function unitSnapshotsDir(home) {
|
|
10
|
+
return join(home, 'merge', 'unit-snapshots');
|
|
11
|
+
}
|
|
12
|
+
export function unitSnapshotPath(home, unitId) {
|
|
13
|
+
return join(unitSnapshotsDir(home), unitStorageKey(unitId) + '.json');
|
|
14
|
+
}
|
|
15
|
+
export function unitEvidencePath(home, unitId) {
|
|
16
|
+
return join(home, 'merge', 'units', unitStorageKey(unitId), 'evidence.json');
|
|
17
|
+
}
|
|
18
|
+
export function unitIndexPath(home) {
|
|
19
|
+
return join(home, 'merge', 'unit-index.json');
|
|
20
|
+
}
|
|
21
|
+
export async function writeUnitSnapshot(io, home, snapshot) {
|
|
22
|
+
const path = unitSnapshotPath(home, snapshot.unitId);
|
|
23
|
+
const content = JSON.stringify(snapshot, null, 2) + '\n';
|
|
24
|
+
if (io.transact !== undefined)
|
|
25
|
+
await io.transact(path, () => content);
|
|
26
|
+
else
|
|
27
|
+
await io.writeText(path, content);
|
|
28
|
+
return path;
|
|
29
|
+
}
|
|
30
|
+
export async function readUnitSnapshot(io, home, unitId) {
|
|
31
|
+
const raw = await io.readText(unitSnapshotPath(home, unitId));
|
|
32
|
+
if (raw === null)
|
|
33
|
+
return null;
|
|
34
|
+
try {
|
|
35
|
+
return JSON.parse(raw);
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
export async function writeUnitEvidence(io, home, evidence) {
|
|
42
|
+
const path = unitEvidencePath(home, evidence.unitId);
|
|
43
|
+
const content = JSON.stringify(evidence, null, 2) + '\n';
|
|
44
|
+
if (io.transact !== undefined)
|
|
45
|
+
await io.transact(path, () => content);
|
|
46
|
+
else
|
|
47
|
+
await io.writeText(path, content);
|
|
48
|
+
await upsertUnitIndex(io, home, {
|
|
49
|
+
unitId: evidence.unitId,
|
|
50
|
+
storageKey: unitStorageKey(evidence.unitId),
|
|
51
|
+
runId: evidence.runId,
|
|
52
|
+
planDigest: evidence.planDigest,
|
|
53
|
+
state: evidence.state,
|
|
54
|
+
updatedAt: evidence.at,
|
|
55
|
+
});
|
|
56
|
+
return path;
|
|
57
|
+
}
|
|
58
|
+
export async function readUnitEvidence(io, home, unitId) {
|
|
59
|
+
const raw = await io.readText(unitEvidencePath(home, unitId));
|
|
60
|
+
if (raw === null)
|
|
61
|
+
return null;
|
|
62
|
+
try {
|
|
63
|
+
return JSON.parse(raw);
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
export async function readUnitIndex(io, home) {
|
|
70
|
+
const raw = await io.readText(unitIndexPath(home));
|
|
71
|
+
if (raw === null)
|
|
72
|
+
return [];
|
|
73
|
+
try {
|
|
74
|
+
const parsed = JSON.parse(raw);
|
|
75
|
+
return Array.isArray(parsed.entries) ? parsed.entries : [];
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
return [];
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
export async function upsertUnitIndex(io, home, entry) {
|
|
82
|
+
const path = unitIndexPath(home);
|
|
83
|
+
const content = (current) => {
|
|
84
|
+
let entries = [];
|
|
85
|
+
if (current !== null) {
|
|
86
|
+
try {
|
|
87
|
+
entries = JSON.parse(current).entries ?? [];
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
entries = [];
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
const next = entries.filter(item => item.unitId !== entry.unitId).concat(entry);
|
|
94
|
+
return JSON.stringify({ schemaVersion: UNIT_STORAGE_SCHEMA_VERSION, entries: next }, null, 2) + '\n';
|
|
95
|
+
};
|
|
96
|
+
if (io.transact !== undefined)
|
|
97
|
+
await io.transact(path, content);
|
|
98
|
+
else
|
|
99
|
+
await io.writeText(path, content(await io.readText(path)));
|
|
100
|
+
}
|
|
101
|
+
export function unitReceiptPath(home, unitId) {
|
|
102
|
+
return join(home, 'merge', 'unit-receipts', unitStorageKey(unitId) + '.json');
|
|
103
|
+
}
|
|
104
|
+
export async function writeUnitReceipt(io, home, receipt) {
|
|
105
|
+
const path = unitReceiptPath(home, receipt.unitId);
|
|
106
|
+
const text = JSON.stringify(receipt, null, 2) + '\n';
|
|
107
|
+
if (io.transact !== undefined)
|
|
108
|
+
await io.transact(path, () => text);
|
|
109
|
+
else
|
|
110
|
+
await io.writeText(path, text);
|
|
111
|
+
return path;
|
|
112
|
+
}
|
|
113
|
+
export async function readUnitReceipt(io, home, unitId) {
|
|
114
|
+
const raw = await io.readText(unitReceiptPath(home, unitId));
|
|
115
|
+
if (raw === null)
|
|
116
|
+
return null;
|
|
117
|
+
try {
|
|
118
|
+
return JSON.parse(raw);
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=unit-storage.js.map
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import type { EvolutionIoLike } from "./io.ts";
|
|
2
|
+
import { type UnitEvidenceRecord } from "./unit-storage.ts";
|
|
3
|
+
import { type UnitJournalPhase } from "./unit-journal.ts";
|
|
4
|
+
export interface UnitSupportFile {
|
|
5
|
+
readonly path: string;
|
|
6
|
+
readonly content: string;
|
|
7
|
+
}
|
|
8
|
+
export interface UnitPlan {
|
|
9
|
+
readonly runId: string;
|
|
10
|
+
readonly pairKey: string;
|
|
11
|
+
readonly target: string;
|
|
12
|
+
readonly targetExists: boolean;
|
|
13
|
+
readonly sources: readonly string[];
|
|
14
|
+
readonly body: string;
|
|
15
|
+
readonly supportFiles: readonly UnitSupportFile[];
|
|
16
|
+
readonly expectedTargetBody: string | null;
|
|
17
|
+
readonly expectedSourceBodies: readonly {
|
|
18
|
+
name: string;
|
|
19
|
+
body: string;
|
|
20
|
+
}[];
|
|
21
|
+
readonly origin: "foreground" | "subagent" | "background_review";
|
|
22
|
+
readonly summary: string;
|
|
23
|
+
}
|
|
24
|
+
export interface UnitCommitResult {
|
|
25
|
+
readonly ok: boolean;
|
|
26
|
+
readonly message: string;
|
|
27
|
+
readonly archived?: readonly string[];
|
|
28
|
+
readonly mutations?: number;
|
|
29
|
+
}
|
|
30
|
+
export interface UnitBackend {
|
|
31
|
+
readSkill(name: string): Promise<string | null>;
|
|
32
|
+
readSupportFile(name: string, path: string): Promise<string | null>;
|
|
33
|
+
commit(plan: UnitPlan, onPhase?: (phase: "target-pending" | "target-applied" | "target-written" | "source-archiving" | "sources-archived" | "support-pending" | "unit-written", detail?: {
|
|
34
|
+
source?: string;
|
|
35
|
+
}) => void | Promise<void>, signal?: AbortSignal, assertFence?: () => Promise<boolean>): Promise<UnitCommitResult>;
|
|
36
|
+
restoreTarget(name: string, body: string | null): Promise<void>;
|
|
37
|
+
restoreSource(name: string, body: string): Promise<void>;
|
|
38
|
+
restoreSupportFile?(name: string, path: string, content: string | null): Promise<void>;
|
|
39
|
+
}
|
|
40
|
+
export interface UnitClaim {
|
|
41
|
+
release(): Promise<void>;
|
|
42
|
+
}
|
|
43
|
+
export interface UnitClaimPort {
|
|
44
|
+
acquire(target: string, runId: string): Promise<UnitClaim>;
|
|
45
|
+
}
|
|
46
|
+
export interface UnitTransactionOptions {
|
|
47
|
+
readonly io: EvolutionIoLike;
|
|
48
|
+
readonly home: string;
|
|
49
|
+
readonly backend: UnitBackend;
|
|
50
|
+
readonly claim: UnitClaimPort;
|
|
51
|
+
readonly now?: () => number;
|
|
52
|
+
readonly waitMs?: number;
|
|
53
|
+
/** Gate/fault-injection seam: called after each journal phase is durable. */
|
|
54
|
+
readonly onPhase?: (phase: UnitJournalPhase) => void | Promise<void>;
|
|
55
|
+
/** Gate instrumentation: tree fence then target claim. */
|
|
56
|
+
readonly onLock?: (lock: "tree" | "claim") => void;
|
|
57
|
+
}
|
|
58
|
+
export type UnitErrorCode = "unit-plan-missing" | "unit-conflict" | "unit-committed" | "unit-prepare-failed" | "unit-commit-failed" | "unit-claim-failed" | "unit-fence-failed" | "unit-rollback-blocked";
|
|
59
|
+
export interface UnitFailure {
|
|
60
|
+
readonly ok: false;
|
|
61
|
+
readonly code: UnitErrorCode;
|
|
62
|
+
readonly message: string;
|
|
63
|
+
}
|
|
64
|
+
export interface UnitPrepared {
|
|
65
|
+
readonly unitId: string;
|
|
66
|
+
readonly planDigest: string;
|
|
67
|
+
}
|
|
68
|
+
export interface UnitTransaction {
|
|
69
|
+
prepare(plan: UnitPlan): Promise<{
|
|
70
|
+
ok: true;
|
|
71
|
+
prepared: UnitPrepared;
|
|
72
|
+
} | UnitFailure>;
|
|
73
|
+
commit(prepared: UnitPrepared, options?: {
|
|
74
|
+
signal?: AbortSignal;
|
|
75
|
+
}): Promise<{
|
|
76
|
+
ok: true;
|
|
77
|
+
evidence: UnitEvidenceRecord;
|
|
78
|
+
} | UnitFailure>;
|
|
79
|
+
verify(ref: {
|
|
80
|
+
unitId: string;
|
|
81
|
+
} | {
|
|
82
|
+
runId: string;
|
|
83
|
+
}): Promise<UnitEvidenceRecord | UnitEvidenceRecord[] | null>;
|
|
84
|
+
rollback(ref: {
|
|
85
|
+
unitId: string;
|
|
86
|
+
reason: string;
|
|
87
|
+
}): Promise<{
|
|
88
|
+
ok: true;
|
|
89
|
+
evidence: UnitEvidenceRecord;
|
|
90
|
+
} | UnitFailure>;
|
|
91
|
+
finalize(unitId: string): Promise<{
|
|
92
|
+
ok: true;
|
|
93
|
+
evidence: UnitEvidenceRecord;
|
|
94
|
+
} | UnitFailure>;
|
|
95
|
+
rollForward(unitId: string): Promise<{
|
|
96
|
+
ok: true;
|
|
97
|
+
evidence: UnitEvidenceRecord;
|
|
98
|
+
} | UnitFailure>;
|
|
99
|
+
cancel(unitId: string, reason: string): Promise<{
|
|
100
|
+
ok: boolean;
|
|
101
|
+
phase: UnitJournalPhase | "none";
|
|
102
|
+
}>;
|
|
103
|
+
}
|
|
104
|
+
export declare class UnitTransactions implements UnitTransaction {
|
|
105
|
+
private readonly options;
|
|
106
|
+
private readonly prepared;
|
|
107
|
+
private readonly commits;
|
|
108
|
+
private readonly now;
|
|
109
|
+
constructor(options: UnitTransactionOptions);
|
|
110
|
+
private unitId;
|
|
111
|
+
private snapshot;
|
|
112
|
+
prepare(plan: UnitPlan): Promise<{
|
|
113
|
+
ok: true;
|
|
114
|
+
prepared: {
|
|
115
|
+
unitId: string;
|
|
116
|
+
planDigest: string;
|
|
117
|
+
};
|
|
118
|
+
code?: never;
|
|
119
|
+
message?: never;
|
|
120
|
+
} | {
|
|
121
|
+
ok: false;
|
|
122
|
+
code: "unit-conflict";
|
|
123
|
+
message: string;
|
|
124
|
+
prepared?: never;
|
|
125
|
+
}>;
|
|
126
|
+
commit(prepared: UnitPrepared, options?: {
|
|
127
|
+
signal?: AbortSignal;
|
|
128
|
+
}): Promise<{
|
|
129
|
+
ok: true;
|
|
130
|
+
evidence: UnitEvidenceRecord;
|
|
131
|
+
} | UnitFailure>;
|
|
132
|
+
private commitOnce;
|
|
133
|
+
verify(ref: {
|
|
134
|
+
unitId: string;
|
|
135
|
+
} | {
|
|
136
|
+
runId: string;
|
|
137
|
+
}): Promise<UnitEvidenceRecord | UnitEvidenceRecord[] | null>;
|
|
138
|
+
finalize(unitId: string): Promise<{
|
|
139
|
+
ok: true;
|
|
140
|
+
evidence: UnitEvidenceRecord;
|
|
141
|
+
code?: never;
|
|
142
|
+
message?: never;
|
|
143
|
+
} | {
|
|
144
|
+
ok: false;
|
|
145
|
+
code: "unit-rollback-blocked";
|
|
146
|
+
message: string;
|
|
147
|
+
evidence?: never;
|
|
148
|
+
}>;
|
|
149
|
+
rollForward(unitId: string): Promise<{
|
|
150
|
+
ok: true;
|
|
151
|
+
evidence: UnitEvidenceRecord;
|
|
152
|
+
code?: never;
|
|
153
|
+
message?: never;
|
|
154
|
+
} | {
|
|
155
|
+
ok: false;
|
|
156
|
+
code: "unit-rollback-blocked";
|
|
157
|
+
message: string;
|
|
158
|
+
evidence?: never;
|
|
159
|
+
}>;
|
|
160
|
+
rollback(ref: {
|
|
161
|
+
unitId: string;
|
|
162
|
+
reason: string;
|
|
163
|
+
}): Promise<{
|
|
164
|
+
ok: false;
|
|
165
|
+
code: "unit-committed";
|
|
166
|
+
message: string;
|
|
167
|
+
evidence?: never;
|
|
168
|
+
} | {
|
|
169
|
+
ok: false;
|
|
170
|
+
code: "unit-rollback-blocked";
|
|
171
|
+
message: string;
|
|
172
|
+
evidence?: never;
|
|
173
|
+
} | {
|
|
174
|
+
ok: false;
|
|
175
|
+
code: "unit-fence-failed";
|
|
176
|
+
message: string;
|
|
177
|
+
evidence?: never;
|
|
178
|
+
} | {
|
|
179
|
+
ok: true;
|
|
180
|
+
evidence: UnitEvidenceRecord;
|
|
181
|
+
code?: never;
|
|
182
|
+
message?: never;
|
|
183
|
+
}>;
|
|
184
|
+
cancel(unitId: string, reason: string): Promise<{
|
|
185
|
+
ok: boolean;
|
|
186
|
+
phase: "none";
|
|
187
|
+
} | {
|
|
188
|
+
ok: boolean;
|
|
189
|
+
phase: "target-pending" | "target-written" | "source-archiving" | "sources-archived";
|
|
190
|
+
} | {
|
|
191
|
+
ok: boolean;
|
|
192
|
+
phase: "prepared" | "support-pending" | "committed" | "failed" | "rolled-back";
|
|
193
|
+
}>;
|
|
194
|
+
}
|
|
195
|
+
//# sourceMappingURL=unit-transaction.d.ts.map
|