@abelxiaoxing/cadence 1.3.0 → 1.4.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 +115 -10
- package/package.json +5 -3
- package/prompts/abel-design.md +71 -17
- package/prompts/abel-diagnose.md +10 -1
- package/prompts/abel-implement.md +118 -20
- package/prompts/abel-init.md +9 -2
- package/src/apply-transaction.ts +16 -14
- package/src/artifact-store.ts +17 -0
- package/src/candidate-patch.ts +2 -1
- package/src/canonical.ts +16 -0
- package/src/change-contract.ts +268 -0
- package/src/child-session.ts +4 -3
- package/src/contracts.ts +141 -33
- package/src/control-contracts.ts +51 -1
- package/src/delivery-compiler.ts +148 -31
- package/src/design-control.ts +69 -11
- package/src/design-journal.ts +216 -72
- package/src/durable-workflow.ts +4385 -0
- package/src/implement-graph.ts +11 -16
- package/src/index.ts +380 -981
- package/src/isolation-backend.ts +84 -23
- package/src/package-delivery.ts +486 -0
- package/src/package-verification.ts +509 -0
- package/src/route-policy.ts +1 -11
- package/src/run-state.ts +4 -16
- package/src/run-store.ts +5 -144
- package/src/scoped-grep-worker.mjs +23 -0
- package/src/scoped-tools.ts +312 -116
- package/src/sqlite-schema.ts +171 -0
- package/src/storage-schema.ts +352 -0
- package/src/subagent-activity.ts +14 -1
- package/src/submit-tool.ts +20 -2
- package/src/task-ledger.ts +14 -55
- package/src/verification-capability.ts +298 -102
- package/src/verification-environment.ts +213 -0
- package/src/verification-identity.ts +77 -0
- package/src/worker-broker.ts +97 -34
- package/src/workflow-engine.ts +28 -8285
- package/src/workflow-policy.ts +1427 -0
- package/src/workflow-state-machine.ts +4478 -0
- package/src/workspace-io-entry.mjs +58 -0
- package/src/workspace-io-worker.mjs +984 -0
- package/src/workspace-io.ts +84 -0
- package/src/workspace-store.ts +125 -19
- package/skills/abel-workflow/SKILL.md +0 -205
package/src/run-store.ts
CHANGED
|
@@ -11,11 +11,13 @@ import {
|
|
|
11
11
|
reduceRunEvents,
|
|
12
12
|
ZERO_EVENT_HASH,
|
|
13
13
|
} from "./run-state.ts";
|
|
14
|
+
import { configureSqlite, matchesSqliteSchema } from "./sqlite-schema.ts";
|
|
14
15
|
import {
|
|
15
16
|
prepareStateRoot,
|
|
16
17
|
type ResolvedStateRoot,
|
|
17
18
|
StateRootError,
|
|
18
19
|
} from "./state-root.ts";
|
|
20
|
+
import { RUN_SCHEMA as SCHEMA } from "./storage-schema.ts";
|
|
19
21
|
|
|
20
22
|
export class RunStoreFormatError extends Error {
|
|
21
23
|
readonly code = "run-store-reset-required" as const;
|
|
@@ -109,145 +111,10 @@ export interface OperationLeaseStatus {
|
|
|
109
111
|
expiresAt?: number;
|
|
110
112
|
}
|
|
111
113
|
|
|
112
|
-
const SCHEMA = `
|
|
113
|
-
CREATE TABLE IF NOT EXISTS runs (
|
|
114
|
-
run_id TEXT PRIMARY KEY,
|
|
115
|
-
root_hash TEXT NOT NULL,
|
|
116
|
-
stage TEXT NOT NULL,
|
|
117
|
-
lookup_key TEXT NOT NULL,
|
|
118
|
-
change_name TEXT,
|
|
119
|
-
provisional_key TEXT,
|
|
120
|
-
state TEXT NOT NULL,
|
|
121
|
-
sequence INTEGER NOT NULL,
|
|
122
|
-
event_hash TEXT NOT NULL,
|
|
123
|
-
delivery_revision INTEGER,
|
|
124
|
-
projection_json TEXT NOT NULL,
|
|
125
|
-
terminal_tombstone TEXT,
|
|
126
|
-
UNIQUE (root_hash, stage, lookup_key)
|
|
127
|
-
) STRICT;
|
|
128
|
-
|
|
129
|
-
CREATE TABLE IF NOT EXISTS delivery_bindings (
|
|
130
|
-
run_id TEXT NOT NULL REFERENCES runs(run_id) ON DELETE CASCADE,
|
|
131
|
-
gate TEXT NOT NULL,
|
|
132
|
-
revision INTEGER NOT NULL,
|
|
133
|
-
receipt_hash TEXT NOT NULL,
|
|
134
|
-
approval_revision INTEGER,
|
|
135
|
-
contract_hash TEXT,
|
|
136
|
-
record_hash TEXT,
|
|
137
|
-
operation_id TEXT NOT NULL,
|
|
138
|
-
PRIMARY KEY (run_id, gate, revision),
|
|
139
|
-
UNIQUE (run_id, operation_id)
|
|
140
|
-
) STRICT;
|
|
141
|
-
|
|
142
|
-
CREATE TABLE IF NOT EXISTS events (
|
|
143
|
-
run_id TEXT NOT NULL REFERENCES runs(run_id) ON DELETE CASCADE,
|
|
144
|
-
sequence INTEGER NOT NULL,
|
|
145
|
-
type TEXT NOT NULL,
|
|
146
|
-
payload_json TEXT NOT NULL,
|
|
147
|
-
prior_hash TEXT NOT NULL,
|
|
148
|
-
event_hash TEXT NOT NULL,
|
|
149
|
-
PRIMARY KEY (run_id, sequence),
|
|
150
|
-
UNIQUE (run_id, event_hash)
|
|
151
|
-
) STRICT;
|
|
152
|
-
|
|
153
|
-
CREATE TABLE IF NOT EXISTS tasks (
|
|
154
|
-
run_id TEXT NOT NULL REFERENCES runs(run_id) ON DELETE CASCADE,
|
|
155
|
-
task_id TEXT NOT NULL,
|
|
156
|
-
state TEXT NOT NULL,
|
|
157
|
-
phase TEXT,
|
|
158
|
-
projection_json TEXT NOT NULL,
|
|
159
|
-
PRIMARY KEY (run_id, task_id)
|
|
160
|
-
) STRICT;
|
|
161
|
-
|
|
162
|
-
CREATE TABLE IF NOT EXISTS operations (
|
|
163
|
-
run_id TEXT NOT NULL REFERENCES runs(run_id) ON DELETE CASCADE,
|
|
164
|
-
operation_id TEXT NOT NULL,
|
|
165
|
-
kind TEXT NOT NULL,
|
|
166
|
-
state TEXT NOT NULL,
|
|
167
|
-
outcome_json TEXT,
|
|
168
|
-
lease_token TEXT,
|
|
169
|
-
lease_expires_at INTEGER,
|
|
170
|
-
PRIMARY KEY (run_id, operation_id)
|
|
171
|
-
) STRICT;
|
|
172
|
-
|
|
173
|
-
CREATE TABLE IF NOT EXISTS route_health (
|
|
174
|
-
route_fingerprint TEXT PRIMARY KEY,
|
|
175
|
-
state TEXT NOT NULL,
|
|
176
|
-
next_half_open_at INTEGER,
|
|
177
|
-
projection_json TEXT NOT NULL
|
|
178
|
-
) STRICT;
|
|
179
|
-
|
|
180
|
-
CREATE TABLE IF NOT EXISTS artifacts (
|
|
181
|
-
content_hash TEXT PRIMARY KEY,
|
|
182
|
-
size_bytes INTEGER NOT NULL,
|
|
183
|
-
seal_state TEXT NOT NULL,
|
|
184
|
-
owner_run_id TEXT REFERENCES runs(run_id) ON DELETE CASCADE,
|
|
185
|
-
reference_count INTEGER NOT NULL
|
|
186
|
-
) STRICT;
|
|
187
|
-
|
|
188
|
-
CREATE TABLE IF NOT EXISTS workspace_revisions (
|
|
189
|
-
revision_id TEXT PRIMARY KEY,
|
|
190
|
-
owner_run_id TEXT NOT NULL REFERENCES runs(run_id) ON DELETE CASCADE,
|
|
191
|
-
parent_revision_id TEXT,
|
|
192
|
-
manifest_hash TEXT NOT NULL
|
|
193
|
-
) STRICT;
|
|
194
|
-
|
|
195
|
-
CREATE TABLE IF NOT EXISTS apply_transactions (
|
|
196
|
-
transaction_id TEXT PRIMARY KEY,
|
|
197
|
-
owner_run_id TEXT NOT NULL REFERENCES runs(run_id) ON DELETE CASCADE,
|
|
198
|
-
state TEXT NOT NULL,
|
|
199
|
-
intent_json TEXT NOT NULL,
|
|
200
|
-
recovery_json TEXT
|
|
201
|
-
) STRICT;
|
|
202
|
-
|
|
203
|
-
CREATE TABLE IF NOT EXISTS bootstrap_handoffs (
|
|
204
|
-
handoff_id TEXT PRIMARY KEY,
|
|
205
|
-
owner_run_id TEXT NOT NULL REFERENCES runs(run_id) ON DELETE CASCADE,
|
|
206
|
-
receipt_hash TEXT NOT NULL UNIQUE,
|
|
207
|
-
state TEXT NOT NULL,
|
|
208
|
-
facts_json TEXT NOT NULL
|
|
209
|
-
) STRICT;
|
|
210
|
-
`;
|
|
211
|
-
|
|
212
114
|
function requireIdentifier(value: string, label: string): void {
|
|
213
115
|
if (!IDENTIFIER.test(value)) throw new Error(`invalid-${label}`);
|
|
214
116
|
}
|
|
215
117
|
|
|
216
|
-
function configureDatabase(
|
|
217
|
-
database: DatabaseSync,
|
|
218
|
-
busyTimeoutMs: number | undefined,
|
|
219
|
-
): void {
|
|
220
|
-
database.exec("PRAGMA foreign_keys = ON");
|
|
221
|
-
database.exec("PRAGMA journal_mode = WAL");
|
|
222
|
-
database.exec("PRAGMA synchronous = FULL");
|
|
223
|
-
database.exec(
|
|
224
|
-
`PRAGMA busy_timeout = ${Math.max(1, Math.min(30_000, busyTimeoutMs ?? 5_000))}`,
|
|
225
|
-
);
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
const REQUIRED_TABLES = [
|
|
229
|
-
"runs",
|
|
230
|
-
"delivery_bindings",
|
|
231
|
-
"events",
|
|
232
|
-
"tasks",
|
|
233
|
-
"operations",
|
|
234
|
-
"route_health",
|
|
235
|
-
"artifacts",
|
|
236
|
-
"workspace_revisions",
|
|
237
|
-
"apply_transactions",
|
|
238
|
-
"bootstrap_handoffs",
|
|
239
|
-
] as const;
|
|
240
|
-
|
|
241
|
-
const REQUIRED_DELIVERY_BINDING_COLUMNS = [
|
|
242
|
-
"run_id",
|
|
243
|
-
"gate",
|
|
244
|
-
"revision",
|
|
245
|
-
"receipt_hash",
|
|
246
|
-
"approval_revision",
|
|
247
|
-
"contract_hash",
|
|
248
|
-
"record_hash",
|
|
249
|
-
"operation_id",
|
|
250
|
-
] as const;
|
|
251
118
|
const LEGACY_SCHEMA_VERSION = 4;
|
|
252
119
|
|
|
253
120
|
function applicationTables(database: DatabaseSync): string[] {
|
|
@@ -272,15 +139,9 @@ function tableColumns(database: DatabaseSync, table: string): string[] {
|
|
|
272
139
|
|
|
273
140
|
function hasRequiredCoreSchema(
|
|
274
141
|
database: DatabaseSync,
|
|
275
|
-
|
|
142
|
+
_tables: readonly string[],
|
|
276
143
|
): boolean {
|
|
277
|
-
|
|
278
|
-
return (
|
|
279
|
-
REQUIRED_TABLES.every((table) => tables.includes(table)) &&
|
|
280
|
-
REQUIRED_DELIVERY_BINDING_COLUMNS.every((column) =>
|
|
281
|
-
deliveryBindingColumns.includes(column),
|
|
282
|
-
)
|
|
283
|
-
);
|
|
144
|
+
return matchesSqliteSchema(database, SCHEMA);
|
|
284
145
|
}
|
|
285
146
|
|
|
286
147
|
function hasCurrentSchema(
|
|
@@ -474,7 +335,7 @@ export class RunStore {
|
|
|
474
335
|
let database: DatabaseSync | undefined;
|
|
475
336
|
try {
|
|
476
337
|
database = new DatabaseSync(stateRoot.databasePath);
|
|
477
|
-
|
|
338
|
+
configureSqlite(database, options.busyTimeoutMs);
|
|
478
339
|
ensureCurrentSchema(database, stateRoot.databasePath);
|
|
479
340
|
} catch (error) {
|
|
480
341
|
try {
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// Only matching runs here. File admission and bounded reads remain parent-owned.
|
|
2
|
+
// A pathological JavaScript regexp can be terminated without blocking the host.
|
|
3
|
+
import { parentPort } from "node:worker_threads";
|
|
4
|
+
|
|
5
|
+
parentPort.on("message", ({ pattern, path, text, maxMatches, maxBytes }) => {
|
|
6
|
+
const regex = new RegExp(pattern, "u");
|
|
7
|
+
const matches = [];
|
|
8
|
+
let bytes = 0;
|
|
9
|
+
let truncated = false;
|
|
10
|
+
const lines = text.split("\n");
|
|
11
|
+
for (let index = 0; index < lines.length; index++) {
|
|
12
|
+
if (!regex.test(lines[index])) continue;
|
|
13
|
+
const match = { path, line: index + 1, text: lines[index].slice(0, 500) };
|
|
14
|
+
const size = Buffer.byteLength(JSON.stringify(match), "utf8") + 1;
|
|
15
|
+
if (matches.length >= maxMatches || bytes + size > maxBytes) {
|
|
16
|
+
truncated = true;
|
|
17
|
+
break;
|
|
18
|
+
}
|
|
19
|
+
matches.push(match);
|
|
20
|
+
bytes += size;
|
|
21
|
+
}
|
|
22
|
+
parentPort.postMessage({ matches, bytes, truncated });
|
|
23
|
+
});
|