@deksden-com/dd-flow-cli 0.9.0-beta.121 → 0.9.0-beta.123

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 (49) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/build-info.json +5 -5
  3. package/dist/cli/hook-ingress.js +4 -3
  4. package/dist/cli/native-hook-ingress.js +34 -2
  5. package/dist/cli/run-cli.js +3 -0
  6. package/dist/harness-runtime/bin/dd-agy.mjs +6 -3
  7. package/dist/harness-runtime/lib/dd-agy-daemon.mjs +68 -6
  8. package/dist/harness-runtime/lib/dd-codex-daemon.mjs +21 -5
  9. package/dist/harness-runtime/lib/dd-codex.mjs +5 -1
  10. package/dist/harness-runtime/lib/dd-zcode-daemon.mjs +60 -8
  11. package/dist/harness-runtime/lib/dd-zcode.mjs +40 -16
  12. package/dist/harness-runtime/lib/delegation-instructions.mjs +3 -3
  13. package/dist/harness-runtime/lib/lifecycle-command.d.mts +20 -0
  14. package/dist/harness-runtime/lib/lifecycle-command.mjs +218 -0
  15. package/dist/harness-runtime/lib/lifecycle-contract.d.mts +10 -0
  16. package/dist/harness-runtime/lib/lifecycle-contract.mjs +19 -0
  17. package/dist/harness-runtime/lib/managed-daemon.mjs +3 -2
  18. package/dist/harness-runtime/lib/model-observations.mjs +16 -9
  19. package/dist/harness-runtime/lib/native-hook-command.d.mts +2 -2
  20. package/dist/harness-runtime/lib/native-hook-command.mjs +36 -5
  21. package/dist/harness-runtime/lib/tool-observations.d.mts +1 -0
  22. package/dist/harness-runtime/lib/tool-observations.mjs +52 -11
  23. package/dist/runtime/context.js +1 -1
  24. package/dist/schemas/flow-run.schema.json +1 -0
  25. package/dist/services/codex-capacity.js +131 -12
  26. package/dist/services/codex-hook-delivery.js +6 -2
  27. package/dist/services/eval-snapshots.js +13 -8
  28. package/dist/services/external-work-launch.js +27 -9
  29. package/dist/services/hooks.js +51 -59
  30. package/dist/services/lifecycle-command.js +1 -383
  31. package/dist/services/lifecycle-contract.js +1 -30
  32. package/dist/services/lifecycle-invocations.js +34 -13
  33. package/dist/services/merge-server.js +26 -9
  34. package/dist/services/review-copy.js +21 -0
  35. package/dist/services/run-controller-adapter.js +25 -3
  36. package/dist/services/run-controller-recovery.js +9 -2
  37. package/dist/services/run-controller.js +59 -20
  38. package/dist/services/run-observations.js +7 -2
  39. package/dist/services/runs.js +60 -47
  40. package/dist/services/stage-report-renderer.js +44 -2
  41. package/dist/services/verification-matrix.js +345 -0
  42. package/dist/services/vnext-code-review.js +30 -11
  43. package/dist/services/vnext-code.js +31 -10
  44. package/dist/services/vnext-merge.js +30 -7
  45. package/dist/services/vnext-plan-review.js +28 -7
  46. package/dist/services/vnext-plan.js +16 -3
  47. package/dist/services/work-registry.js +15 -1
  48. package/dist/storage/database.js +43 -9
  49. package/package.json +4 -1
@@ -21,6 +21,7 @@ import { acceptStageReport, prepareStageReport } from "./stage-report-renderer.j
21
21
  import { applyExternalStageContext, prepareExternalStageContext } from "./stage-context.js";
22
22
  import { subagentCapacityKey } from "./vnext-fanout.js";
23
23
  import { stageLifecycleInstruction } from "../harness-runtime/lib/delegation-instructions.mjs";
24
+ import { prepareRunVerificationMatrix, acceptVerificationMatrix, commitVerificationMatrixStart, verificationMatrixInstruction } from "./verification-matrix.js";
24
25
  export function isVnextPlanRun(context, input) {
25
26
  const project = requireProjectByRoot(context, resolveProjectRoot(input.projectRoot));
26
27
  return Boolean(context.db.get("SELECT id FROM runs WHERE project_id = ? AND id = ? AND flow_kind = 'vnext_protocolize'", [project.id, input.runId]));
@@ -41,7 +42,7 @@ export function prepareVnextPlanStart(context, input) {
41
42
  const { profile: codeCheckProfile } = readCodeCheckProfile(run.workspace_root);
42
43
  if (context.db.get("SELECT 1 FROM works WHERE project_id = ? AND run_id = ? AND task = ? AND status = 'running'", [project.id, run.id, planTask]))
43
44
  throw new AppError("invalid_work_state", "PLAN already has a running Work", 1, { run_id: run.id });
44
- prepareFlowRunStageAttachment(context, { projectRoot, runId: run.id, stage: "plan", dir: "03-plan", status: "running", dataSchemaId: "dd-flow/protocol-plan@6" });
45
+ const attachment = prepareFlowRunStageAttachment(context, { projectRoot, runId: run.id, stage: "plan", dir: "03-plan", status: "running", dataSchemaId: "dd-flow/protocol-plan@6" });
45
46
  const root = path.join(home, vnextStageDirectory("plan"));
46
47
  if (input.externalContext)
47
48
  prepareExternalStageContext({ stageRoot: root, loaded: input.externalContext });
@@ -58,12 +59,16 @@ export function prepareVnextPlanStart(context, input) {
58
59
  const git = gitFacts(run.workspace_root);
59
60
  for (const file of [...planPaths, ...mapPaths, ...["stage-prompt.md", "work-context.json", "fixture-root.prompt.md"].map(name => path.join(root, name))])
60
61
  prepareOutputFile(file);
61
- return { projectRoot, project, run, home, root, rootWork, workspaceRoute, protocols, template, codeCheckProfile, planPaths, mapPaths, owned, identities, aspects, runVariables, mergeRequired, git };
62
+ const matrix = prepareRunVerificationMatrix(context, { projectId: project.id, runId: run.id, stage: "plan", role: "input", stageAttempt: attachment.attempt });
63
+ return { projectRoot, project, run, home, root, rootWork, workspaceRoute, protocols, template, codeCheckProfile, planPaths, mapPaths, owned, identities, aspects, runVariables, mergeRequired, git, matrix };
62
64
  }
63
65
  export function startVnextPlan(context, input, prepared = prepareVnextPlanStart(context, input)) {
64
66
  const { projectRoot, project, run, root, rootWork, workspaceRoute, protocols, template, codeCheckProfile, planPaths, mapPaths, owned, identities, aspects, runVariables, mergeRequired, git, home } = prepared;
65
67
  ensureWorkRegistry(context);
66
68
  assertStageStartHookEvent(context, { projectId: project.id, eventKey: input.hookEventId, runId: run.id, stage: "plan", projectRoot, ...(input.contextSha256 ? { contextSha256: input.contextSha256 } : {}) });
69
+ if (context.db.get("SELECT 1 FROM works WHERE project_id = ? AND run_id = ? AND task = ? AND status = 'running'", [project.id, run.id, planTask]))
70
+ throw new AppError("invalid_work_state", "PLAN already has a running Work", 1, { run_id: run.id });
71
+ prepareFlowRunStageAttachment(context, { projectRoot, runId: run.id, stage: "plan", dir: "03-plan", status: "running", dataSchemaId: "dd-flow/protocol-plan@6" }, true);
67
72
  fs.mkdirSync(root, { recursive: true });
68
73
  const now = context.now();
69
74
  // Imported stage fixtures have a synthetic running root with no prior agent.
@@ -113,9 +118,13 @@ export function startVnextPlan(context, input, prepared = prepareVnextPlanStart(
113
118
  : `PLAN-REVIEW mode is ${planReviewMode}: include review groups only for genuinely applicable aspects; an empty set is allowed.`;
114
119
  fs.writeFileSync(promptPath, `${prompt}\n<review_mode_rule>${reviewModeRule}</review_mode_rule>\n<verification_rule>Every flow check must be an autonomous executable command. Do not declare external/manual proof or a human review as a check, evidence substitute, DEF, or gate. The only user interaction supported by this flow is an explicit stage pause for a material unanswered question.</verification_rule>\n${stageLifecycleInstruction}\n`);
115
120
  const externalContext = applyExternalStageContext({ stageRoot: root, promptPath, ...(input.externalContext ? { loaded: input.externalContext } : {}) });
121
+ if (prepared.matrix)
122
+ fs.appendFileSync(promptPath, verificationMatrixInstruction(prepared.matrix.metadata, home, "designing the source PLAN and its tests"));
116
123
  fs.writeFileSync(path.join(root, "work-context.json"), JSON.stringify({ schema_id: "dd-flow/work-context@1", system: { run_id: run.id, work_id: planWorkId, stage: "plan" }, workspace: { project_root: projectRoot, workspace_root: run.workspace_root, stage_root: root }, artifacts: artifactMaterialization, input: { protocols, owned_obligations: Object.fromEntries(owned) } }, null, 2));
117
124
  const binding = bindStageCoordinatorWork(context, { workId: planWorkId, hookEventId: input.hookEventId, stage: "plan", promptPath, resultPath: path.join(root, "stage-report.json"), ...(input.contextSha256 ? { contextSha256: input.contextSha256 } : {}) });
118
- attachFlowRunStage(context, { projectRoot, runId: run.id, stage: "plan", dir: "03-plan", status: "running", dataSchemaId: "dd-flow/protocol-plan@6" });
125
+ const attachmentInput = { projectRoot, runId: run.id, stage: "plan", dir: "03-plan", status: "running", dataSchemaId: "dd-flow/protocol-plan@6" };
126
+ const attachment = prepareFlowRunStageAttachment(context, attachmentInput);
127
+ commitVerificationMatrixStart(context, prepared.matrix, () => attachFlowRunStage(context, attachmentInput, attachment));
119
128
  const workSessionId = String(binding.work_session_id);
120
129
  const sessionId = String(binding.session_id);
121
130
  refreshRunWorkProjection(context, project.id, run.id);
@@ -169,6 +178,9 @@ function finishVnextPlanOwned(context, input) {
169
178
  plan_checksums: planFiles.map((file) => ({ path: path.relative(run.workspace_root, file).split(path.sep).join("/"), sha256: checksum(file) })),
170
179
  aspect_map_checksums: mapFiles.map((file) => ({ path: path.relative(home, file).split(path.sep).join("/"), sha256: checksum(file) }))
171
180
  });
181
+ const matrix = prepareRunVerificationMatrix(context, { projectId: project.id, runId: run.id, stage: "plan", role: "output" });
182
+ if (matrix)
183
+ Object.assign(report.semantic, { verification_matrix: matrix.metadata });
172
184
  const preparedReport = prepareStageReport(report);
173
185
  validateSchema({ schemaName: "stage-report", file: path.join(root, "stage-report.json"), data: preparedReport.normalized, projectRoot, ddFlowHome: context.ddFlowHome, runId: run.id, runRoot: home });
174
186
  const completionInput = { projectRoot, runId: run.id, stage: "plan", status: "done", data: "stage-report.json", dataSchemaId: "dd-flow/stage-report@1", report: "stage-report.md", stageReport: "stage-report.html", dataSha256: preparedReport.sha256, git: report.mechanical.git };
@@ -179,6 +191,7 @@ function finishVnextPlanOwned(context, input) {
179
191
  throw new AppError("invalid_work_state", "PLAN Work changed during finish preparation", 1);
180
192
  context.db.run("UPDATE works SET status = 'completed', result = ?, completed_at = ?, updated_at = ? WHERE work_id = ?", ["PLAN accepted; awaiting PLAN-REVIEW", now, now, work.work_id]);
181
193
  context.db.run("UPDATE work_sessions SET status = 'completed', result_path = ?, updated_at = ?, completed_at = ? WHERE id = ?", [path.join(root, "stage-report.json"), now, now, workSession.id]);
194
+ acceptVerificationMatrix(context, matrix);
182
195
  acceptStageReport(context, { projectId: project.id, runId: run.id, stage: "plan", root, prepared: preparedReport });
183
196
  completeFlowRunStage(context, completionInput, preparedCompletion);
184
197
  refreshRunWorkProjection(context, project.id, run.id);
@@ -25,6 +25,7 @@ import { prepareError, prepareJsonFile } from "../cli/input-preparation.js";
25
25
  import { lifecycleRetryInstruction } from "../harness-runtime/lib/delegation-instructions.mjs";
26
26
  import { acceptedDecisionPrecedence } from "./stage-context.js";
27
27
  import { reviewEnvironmentAllowed, reviewExecutionCopyHash, reviewSourceHash, reviewSourcePaths } from "./review-copy.js";
28
+ import { latestRunVerificationMatrix, verificationMatrixInstruction, verificationMatrixContract } from "./verification-matrix.js";
28
29
  const workColumns = "work_id, project_id, run_id, parent_work_id, task, launch_policy, result_schema, payload_json, depends_on_json, status, result, created_at, started_at, updated_at, completed_at";
29
30
  export function ensureWorkRegistry(context) { context.db.exec("SELECT 1 FROM works LIMIT 1"); context.db.exec("SELECT 1 FROM work_sessions LIMIT 1"); }
30
31
  function ownsPhysicalWorkSession(context, projectId, owner, identity) {
@@ -986,6 +987,16 @@ function assertSharedReviewInput(context, work, run, generation = recoveryGuard(
986
987
  if (value.cycle !== payload?.review_cycle)
987
988
  throw new AppError("review_input_invalid", "CODE-REVIEW cycle differs from its Work", 1);
988
989
  }
990
+ const matrix = latestRunVerificationMatrix(context, work.project_id, work.run_id, String(kind), "input");
991
+ const marked = JSON.parse(context.db.get("SELECT index_json FROM runs WHERE project_id = ? AND id = ?", [work.project_id, work.run_id]).index_json).verification_matrix_contract === verificationMatrixContract;
992
+ if (marked && !matrix)
993
+ throw new AppError("review_input_contract_missing", "Marked reviewer Stage lacks its immutable matrix baseline", 1, { stage: kind });
994
+ if (matrix) {
995
+ add("run", matrix.metadata.json.path, matrix.metadata.json.sha256);
996
+ add("run", matrix.metadata.markdown.path, matrix.metadata.markdown.sha256);
997
+ }
998
+ for (const item of value.reviewer_inputs ?? [])
999
+ add("workspace", item.path, item.sha256);
989
1000
  const runInputs = [...expected].map(([key, sha]) => { const [root, ...parts] = key.split(":"); return { root: root, path: parts.join(":"), sha256: sha }; }).sort((a, b) => `${a.root}:${a.path}`.localeCompare(`${b.root}:${b.path}`));
990
1001
  for (const item of runInputs) {
991
1002
  const target = reviewInputPath(item.root === "run" ? home : run.workspace_root, item.path);
@@ -1236,7 +1247,10 @@ export function validateReviewResolutions(workId, assigned, resolutions) {
1236
1247
  }
1237
1248
  function renderWorkerPrompt(context, work, run, dependencies, commands) {
1238
1249
  const body = renderWorkerPromptBody(context, work, run, dependencies, commands);
1239
- return ["<accepted_decision_precedence>", `Read ${path.join(requireRunHome(run), "01-specify", "specify.json")} and later accepted RUN decisions relevant to this Work.`, acceptedDecisionPrecedence, "</accepted_decision_precedence>", "", body].join("\n");
1250
+ const kind = parsePayload(work)?.kind;
1251
+ const matrixStage = kind === "plan-review" || kind === "code-review" ? kind : codePacket(work) ? "code" : null;
1252
+ const matrix = matrixStage ? latestRunVerificationMatrix(context, work.project_id, work.run_id, matrixStage, kind === "plan-review" || kind === "code-review" ? "input" : undefined) : null;
1253
+ return ["<accepted_decision_precedence>", `Read ${path.join(requireRunHome(run), "01-specify", "specify.json")} and later accepted RUN decisions relevant to this Work.`, acceptedDecisionPrecedence, "</accepted_decision_precedence>", "", body, verificationMatrixInstruction(matrix?.metadata ?? null, requireRunHome(run), `assigned Work ${work.work_id}`)].join("\n");
1240
1254
  }
1241
1255
  function workerLifecycleCommands(context, work, run) {
1242
1256
  const resultInputPath = path.join(requireRunHome(run), "works", work.work_id, "result-input.json");
@@ -331,7 +331,16 @@ export function ensureWorkLaunchStorage(db) {
331
331
  CREATE INDEX IF NOT EXISTS idx_work_launches_status ON work_launches(status, updated_at DESC);
332
332
  `);
333
333
  }
334
- export function getDatabase(ddFlowHome, mode = "initialize", importPermitId) {
334
+ export function getDatabase(ddFlowHome, mode = "initialize", importPermitId, hookDeadlineAt) {
335
+ if (hookDeadlineAt !== undefined && (!Number.isSafeInteger(hookDeadlineAt) || mode !== "hook"))
336
+ throw new AppError("hook_deadline_invalid", "Hook deadline must be a finite absolute millisecond deadline", 1, { effect: "unknown" });
337
+ const deadline = hookDeadlineAt === undefined ? undefined : (phase) => {
338
+ const remaining = hookDeadlineAt - Date.now();
339
+ if (remaining <= 0)
340
+ throw new AppError("native_hook_timeout", "Native hook deadline expired before durable admission", 1, { phase, deadline_at: hookDeadlineAt, effect: "unknown" });
341
+ return Math.max(1, Math.min(4000, remaining));
342
+ };
343
+ deadline?.("store_open");
335
344
  if (mode !== "read_existing")
336
345
  assertImportAdmission(ddFlowHome, importPermitId);
337
346
  const dbPath = path.join(ddFlowHome, "db.sqlite");
@@ -344,7 +353,12 @@ export function getDatabase(ddFlowHome, mode = "initialize", importPermitId) {
344
353
  if (!exists || mode === "migrate")
345
354
  ensureDir(ddFlowHome);
346
355
  const db = mode === "read_existing" ? new DatabaseSync(dbPath, { readOnly: true }) : new DatabaseSync(dbPath);
347
- db.exec("PRAGMA busy_timeout = 4000");
356
+ try {
357
+ db.exec(`PRAGMA busy_timeout = ${deadline?.("store_open") ?? 4000}`);
358
+ }
359
+ catch (error) {
360
+ return closeAfterOpenFailure(db, error);
361
+ }
348
362
  if (mode !== "read_existing") {
349
363
  try {
350
364
  registerStoreWriter(db);
@@ -354,7 +368,7 @@ export function getDatabase(ddFlowHome, mode = "initialize", importPermitId) {
354
368
  }
355
369
  }
356
370
  try {
357
- configureDatabase(db, mode);
371
+ configureDatabase(db, mode, deadline);
358
372
  }
359
373
  catch (error) {
360
374
  return closeAfterOpenFailure(db, error);
@@ -374,6 +388,7 @@ export function getDatabase(ddFlowHome, mode = "initialize", importPermitId) {
374
388
  migrateSessionStorageKeys(db, dbPath);
375
389
  }
376
390
  else {
391
+ deadline?.("store_validation");
377
392
  assertHookStoreReady(db);
378
393
  }
379
394
  }
@@ -384,7 +399,7 @@ export function getDatabase(ddFlowHome, mode = "initialize", importPermitId) {
384
399
  if (mode === "read_existing")
385
400
  db.exec("PRAGMA query_only = ON");
386
401
  db.exec("PRAGMA foreign_keys = ON");
387
- return databaseFacade(dbPath, mode !== "read_existing", db);
402
+ return databaseFacade(dbPath, mode !== "read_existing", db, undefined, deadline);
388
403
  }
389
404
  /**
390
405
  * Hook ingress is a hot, synchronous path. It may write receipts, but it
@@ -554,7 +569,7 @@ function emptyReadOnlyDatabase(dbPath) {
554
569
  all: () => []
555
570
  };
556
571
  }
557
- function databaseFacade(dbPath, writable, db, close = () => db.close?.()) {
572
+ function databaseFacade(dbPath, writable, db, close = () => db.close?.(), deadline) {
558
573
  let reserved = false;
559
574
  let poisoned = false;
560
575
  let closed = false;
@@ -567,6 +582,14 @@ function databaseFacade(dbPath, writable, db, close = () => db.close?.()) {
567
582
  let manualFrames = [];
568
583
  let readDepth = 0;
569
584
  const writerTiming = channel("dd-flow.sqlite.writer");
585
+ const ingressPhase = channel("dd-flow.sqlite.ingress");
586
+ const bound = (phase) => {
587
+ const remaining = deadline?.(phase);
588
+ if (remaining !== undefined)
589
+ db.exec(`PRAGMA busy_timeout = ${remaining}`);
590
+ if (ingressPhase.hasSubscribers)
591
+ ingressPhase.publish({ phase, ...(remaining !== undefined ? { remaining_ms: remaining } : {}) });
592
+ };
570
593
  const publishCommitted = () => {
571
594
  const pending = afterCommit;
572
595
  afterCommit = [];
@@ -584,8 +607,11 @@ function databaseFacade(dbPath, writable, db, close = () => db.close?.()) {
584
607
  throw new AppError("read_snapshot_write", "Cannot reserve a writer inside a read snapshot", 1);
585
608
  if (!writable)
586
609
  throw new AppError("read_only_storage", "Read-only access cannot start a write transaction", 1, { path: dbPath });
610
+ bound("writer_reservation");
587
611
  db.exec("BEGIN IMMEDIATE");
588
612
  reserved = true;
613
+ if (ingressPhase.hasSubscribers)
614
+ ingressPhase.publish({ phase: "writer_reserved" });
589
615
  };
590
616
  const rollback = (sql, original) => {
591
617
  try {
@@ -626,6 +652,8 @@ function databaseFacade(dbPath, writable, db, close = () => db.close?.()) {
626
652
  beginWriteTransaction();
627
653
  }
628
654
  catch (error) {
655
+ if (error instanceof AppError)
656
+ throw error;
629
657
  throw new AppError("storage_write_failed", "Cannot reserve SQLite writer", 1, { cause: errorDetails(error), transaction_phase: "begin", transaction_rolled_back: true });
630
658
  }
631
659
  let phase = "body";
@@ -636,11 +664,14 @@ function databaseFacade(dbPath, writable, db, close = () => db.close?.()) {
636
664
  throw new AppError("write_transaction_async", "Write transaction callback must be synchronous", 1);
637
665
  }
638
666
  phase = "commit";
667
+ bound("commit");
639
668
  if (nested)
640
669
  db.exec(`RELEASE ${marker}`);
641
670
  else
642
671
  db.exec("COMMIT");
643
672
  phase = "committed";
673
+ if (ingressPhase.hasSubscribers)
674
+ ingressPhase.publish({ phase: "committed" });
644
675
  if (!nested && writerTiming.hasSubscribers)
645
676
  writerTiming.publish({ operation: operationName, wall_time_ms: performance.now() - startedAt, path: dbPath });
646
677
  if (!nested)
@@ -786,22 +817,25 @@ function databaseFacade(dbPath, writable, db, close = () => db.close?.()) {
786
817
  executePublications([operation]);
787
818
  } },
788
819
  run: (sql, params = []) => { assertUsable(); if (readDepth)
789
- throw new AppError("read_snapshot_write", "Cannot write inside a read snapshot", 1); return db.prepare(sql).run(...params); },
790
- get: (sql, params = []) => { assertUsable(); return db.prepare(sql).get(...params); },
791
- all: (sql, params = []) => { assertUsable(); return db.prepare(sql).all(...params); }
820
+ throw new AppError("read_snapshot_write", "Cannot write inside a read snapshot", 1); bound("write"); return db.prepare(sql).run(...params); },
821
+ get: (sql, params = []) => { assertUsable(); bound("lookup"); return db.prepare(sql).get(...params); },
822
+ all: (sql, params = []) => { assertUsable(); bound("lookup"); return db.prepare(sql).all(...params); }
792
823
  };
793
824
  }
794
825
  function errorDetails(error) {
795
826
  const value = error;
796
827
  return { message: String(value?.message ?? error), ...(typeof value?.code === "string" ? { code: value.code } : {}), ...(typeof value?.errcode === "number" ? { sqlite_extended_code: value.errcode } : {}) };
797
828
  }
798
- function configureDatabase(db, mode) {
829
+ function configureDatabase(db, mode, ingressDeadline) {
799
830
  if (mode !== "read_existing") {
800
831
  // Concurrent first openers can collide while changing journal mode, even
801
832
  // with busy_timeout set. Retrying this configuration does not replay writes.
802
833
  const deadline = performance.now() + 4000, pause = new Int32Array(new SharedArrayBuffer(4));
803
834
  for (;;) {
804
835
  try {
836
+ const remaining = ingressDeadline?.("store_configuration");
837
+ if (remaining !== undefined)
838
+ db.exec(`PRAGMA busy_timeout = ${remaining}`);
805
839
  const current = db.prepare("PRAGMA journal_mode").get();
806
840
  if (current.journal_mode !== "wal")
807
841
  db.exec("PRAGMA journal_mode = WAL");
package/package.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "@deksden-com/dd-flow-cli",
3
- "version": "0.9.0-beta.121",
3
+ "version": "0.9.0-beta.123",
4
4
  "description": "Mechanical runtime CLI for dd-flow workflows.",
5
5
  "type": "module",
6
+ "packageManager": "pnpm@10.23.0",
6
7
  "bin": {
7
8
  "dd-flow": "dist/cli.js",
8
9
  "dd-codex": "dist/harness-runtime/bin/dd-codex.mjs",
@@ -49,6 +50,8 @@
49
50
  "ajv": "^8.20.0",
50
51
  "shell-quote": "^1.10.0",
51
52
  "smol-toml": "^1.6.1",
53
+ "tree-sitter": "0.25.1",
54
+ "tree-sitter-bash": "0.25.1",
52
55
  "yaml": "^2.9.0"
53
56
  },
54
57
  "publishConfig": {