@abelxiaoxing/cadence 1.2.4 → 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.
Files changed (46) hide show
  1. package/README.md +155 -10
  2. package/package.json +5 -3
  3. package/prompts/abel-design.md +71 -17
  4. package/prompts/abel-diagnose.md +10 -1
  5. package/prompts/abel-implement.md +118 -20
  6. package/prompts/abel-init.md +9 -2
  7. package/src/apply-transaction.ts +16 -14
  8. package/src/artifact-store.ts +17 -0
  9. package/src/candidate-patch.ts +2 -1
  10. package/src/canonical.ts +16 -0
  11. package/src/change-contract.ts +268 -0
  12. package/src/child-session.ts +4 -3
  13. package/src/contracts.ts +141 -33
  14. package/src/control-contracts.ts +51 -1
  15. package/src/delivery-compiler.ts +148 -31
  16. package/src/design-control.ts +83 -15
  17. package/src/design-journal.ts +216 -72
  18. package/src/durable-workflow.ts +4385 -0
  19. package/src/implement-graph.ts +11 -16
  20. package/src/index.ts +399 -1079
  21. package/src/isolation-backend.ts +84 -23
  22. package/src/openspec-cli.ts +494 -0
  23. package/src/package-delivery.ts +486 -0
  24. package/src/package-verification.ts +509 -0
  25. package/src/route-policy.ts +1 -11
  26. package/src/run-state.ts +4 -16
  27. package/src/run-store.ts +5 -144
  28. package/src/scoped-grep-worker.mjs +23 -0
  29. package/src/scoped-tools.ts +312 -116
  30. package/src/sqlite-schema.ts +171 -0
  31. package/src/storage-schema.ts +352 -0
  32. package/src/subagent-activity.ts +14 -1
  33. package/src/submit-tool.ts +20 -2
  34. package/src/task-ledger.ts +14 -55
  35. package/src/verification-capability.ts +298 -102
  36. package/src/verification-environment.ts +213 -0
  37. package/src/verification-identity.ts +77 -0
  38. package/src/worker-broker.ts +97 -34
  39. package/src/workflow-engine.ts +28 -8285
  40. package/src/workflow-policy.ts +1427 -0
  41. package/src/workflow-state-machine.ts +4478 -0
  42. package/src/workspace-io-entry.mjs +58 -0
  43. package/src/workspace-io-worker.mjs +984 -0
  44. package/src/workspace-io.ts +84 -0
  45. package/src/workspace-store.ts +125 -19
  46. 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
- tables: readonly string[],
142
+ _tables: readonly string[],
276
143
  ): boolean {
277
- const deliveryBindingColumns = tableColumns(database, "delivery_bindings");
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
- configureDatabase(database, options.busyTimeoutMs);
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
+ });