ultra-builder-pro-cli 0.20.0 → 0.21.1

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 (102) hide show
  1. package/.ultra-template/docs/research/README.md +26 -5
  2. package/.ultra-template/specs/discovery.md +1 -1
  3. package/.ultra-template/tasks/tasks.json +1 -1
  4. package/CHANGELOG.md +66 -0
  5. package/README.md +54 -24
  6. package/adapters/_shared/codex-assets.cjs +69 -11
  7. package/adapters/_shared/interaction-contract.cjs +36 -3
  8. package/adapters/_shared/runtime-assets.cjs +41 -1
  9. package/adapters/claude.js +7 -5
  10. package/adapters/codex.js +1 -1
  11. package/adapters/kimi.js +2 -8
  12. package/adapters/opencode.js +30 -28
  13. package/bin/orchestrator.js +64 -24
  14. package/docs/AGENT-CONTEXT.md +74 -43
  15. package/docs/ARCHITECTURE.md +63 -31
  16. package/docs/ARTIFACT-AUTHORITY.md +234 -0
  17. package/docs/DECISIONS.md +10 -4
  18. package/docs/LEGACY-CLI-CROSSWALK.md +6 -4
  19. package/docs/PLUGIN-ISOLATION-CONTRACT.md +4 -3
  20. package/docs/ROADMAP.md +19 -5
  21. package/docs/RUNTIME-COMPAT-MATRIX.md +24 -13
  22. package/docs/STATE-DB-ACCESS-POLICY.md +11 -9
  23. package/docs/WORKFLOW-LIFECYCLE.md +70 -39
  24. package/hooks/README.md +6 -5
  25. package/hooks/active_task_context.py +97 -12
  26. package/hooks/context_spine.py +16 -4
  27. package/hooks/health_check.py +5 -4
  28. package/hooks/pre_stop_check.py +5 -2
  29. package/hooks/runtime_paths.py +396 -0
  30. package/hooks/subagent_tracker.py +5 -2
  31. package/hooks/workflow_checkpoint.py +16 -3
  32. package/hooks/workflow_context.py +11 -3
  33. package/hooks/workflow_resume.py +7 -4
  34. package/mcp-server/breadcrumb.cjs +20 -2
  35. package/mcp-server/lib/archive-journal.cjs +1026 -111
  36. package/mcp-server/lib/archive-mutation-worker.py +365 -0
  37. package/mcp-server/lib/artifact-registry.cjs +1126 -0
  38. package/mcp-server/lib/baseline-workflow.cjs +9 -4
  39. package/mcp-server/lib/change-packet.cjs +818 -0
  40. package/mcp-server/lib/change-workflow.cjs +932 -176
  41. package/mcp-server/lib/context-paths.cjs +111 -0
  42. package/mcp-server/lib/context-spine.cjs +511 -45
  43. package/mcp-server/lib/decision-dialogue.cjs +345 -3
  44. package/mcp-server/lib/delivery-transaction.cjs +471 -0
  45. package/mcp-server/lib/doctor-backup-worker.cjs +328 -0
  46. package/mcp-server/lib/doctor.cjs +373 -11
  47. package/mcp-server/lib/git-bootstrap.cjs +459 -47
  48. package/mcp-server/lib/init-project.cjs +190 -95
  49. package/mcp-server/lib/plan-publication-worker.cjs +830 -0
  50. package/mcp-server/lib/plan-store.cjs +700 -5
  51. package/mcp-server/lib/project-breadcrumb.cjs +23 -4
  52. package/mcp-server/lib/projector.cjs +174 -40
  53. package/mcp-server/lib/runtime-paths.cjs +1687 -0
  54. package/mcp-server/lib/safe-project-file.cjs +385 -0
  55. package/mcp-server/lib/spec-learning.cjs +28 -12
  56. package/mcp-server/lib/state-db.cjs +263 -9
  57. package/mcp-server/lib/state-ops.cjs +248 -49
  58. package/mcp-server/lib/telemetry.cjs +12 -3
  59. package/mcp-server/lib/workflow-state.cjs +610 -58
  60. package/mcp-server/server.cjs +278 -33
  61. package/orchestrator/daemon.cjs +2 -10
  62. package/orchestrator/parallel-orchestrator.cjs +314 -50
  63. package/orchestrator/planner/plan-builder.cjs +1 -1
  64. package/orchestrator/recovery.cjs +125 -7
  65. package/orchestrator/session-close-journal-worker.cjs +5 -0
  66. package/orchestrator/session-close-journal.cjs +1014 -0
  67. package/orchestrator/session-runner.cjs +679 -69
  68. package/orchestrator/worktree-manager.cjs +186 -35
  69. package/package.json +2 -3
  70. package/skills/cc-collab/SKILL.md +4 -1
  71. package/skills/codex-collab/SKILL.md +5 -2
  72. package/skills/ultra-change/SKILL.md +26 -8
  73. package/skills/ultra-deliver/SKILL.md +23 -11
  74. package/skills/ultra-dev/SKILL.md +33 -6
  75. package/skills/ultra-doctor/SKILL.md +6 -2
  76. package/skills/ultra-init/SKILL.md +4 -2
  77. package/skills/ultra-plan/SKILL.md +49 -16
  78. package/skills/ultra-research/SKILL.md +30 -27
  79. package/skills/ultra-review/SKILL.md +9 -5
  80. package/skills/ultra-status/SKILL.md +9 -4
  81. package/skills/ultra-test/SKILL.md +10 -5
  82. package/skills/ultra-think/SKILL.md +6 -2
  83. package/skills/ultra-think/references/decision-dialogue.md +17 -6
  84. package/skills/ultra-verify/SKILL.md +4 -1
  85. package/spec/cli-protocol.md +18 -7
  86. package/spec/mcp-tools.yaml +502 -44
  87. package/spec/schemas/change-delta.v1.schema.json +153 -0
  88. package/spec/schemas/documentation-reconciliation.v1.schema.json +106 -0
  89. package/spec/schemas/mcp-tools.schema.json +1 -1
  90. package/spec/schemas/state-db.sql +50 -13
  91. package/spec/schemas/tasks.v4.5.schema.json +1 -1
  92. package/ultra-tools/cli.cjs +3 -2
  93. package/ultra-tools/commands/db.cjs +76 -25
  94. package/ultra-tools/commands/migrate.cjs +995 -80
  95. package/ultra-tools/commands/session.cjs +34 -8
  96. package/ultra-tools/commands/status.cjs +32 -6
  97. package/ultra-tools/commands/system.cjs +129 -22
  98. package/commands/learn.md +0 -10
  99. package/orchestrator/skill-miner.cjs +0 -133
  100. package/output-styles/coding-vibes.md +0 -67
  101. package/output-styles/structural-thinking.md +0 -61
  102. package/skills/learn/SKILL.md +0 -58
@@ -13,11 +13,13 @@
13
13
 
14
14
  const fs = require('node:fs');
15
15
  const path = require('node:path');
16
+ const Database = require('better-sqlite3');
16
17
 
17
18
  const { EXPECTED_VERSION, initStateDb } = require('./state-db.cjs');
18
19
  const { assertStateAuthority, inspectProjection } = require('./state-authority.cjs');
19
20
  const baselines = require('./baseline-workflow.cjs');
20
21
  const gitBootstrap = require('./git-bootstrap.cjs');
22
+ const runtimePaths = require('./runtime-paths.cjs');
21
23
  const runtimeState = require('./runtime-state.cjs');
22
24
  const ops = require('./state-ops.cjs');
23
25
  const workflows = require('./workflow-state.cjs');
@@ -407,16 +409,21 @@ function rollbackInitialization(ultraDir, backupPath) {
407
409
  return errors;
408
410
  }
409
411
 
410
- function createResumeSnapshot(db, ultraDir, stateDbPath) {
412
+ function createResumeSnapshot(ultraDir, stateDbPath) {
411
413
  const token = `${process.pid}-${Date.now()}-${Math.random().toString(16).slice(2)}`;
412
- const statePath = path.join(ultraDir, `.resume-state-${token}.db`);
413
- const projectionDir = path.join(ultraDir, `.resume-projections-${token}`);
414
+ const runtimeDir = path.dirname(stateDbPath);
415
+ const statePath = path.join(runtimeDir, `.resume-state-${token}.db`);
416
+ const projectionDir = path.join(runtimeDir, `.resume-projections-${token}`);
414
417
  const projectionTargets = [
415
418
  path.join('tasks', 'tasks.json'),
416
419
  path.join('tasks', 'contexts'),
417
420
  ];
421
+ let db;
418
422
  try {
423
+ db = new Database(stateDbPath, { fileMustExist: true });
419
424
  db.prepare('VACUUM INTO ?').run(statePath);
425
+ db.close();
426
+ db = null;
420
427
  const projections = projectionTargets.map((relative) => {
421
428
  const source = path.join(ultraDir, relative);
422
429
  const existed = fs.existsSync(source);
@@ -429,6 +436,7 @@ function createResumeSnapshot(db, ultraDir, stateDbPath) {
429
436
  });
430
437
  return { statePath, projectionDir, projections, stateDbPath, ultraDir };
431
438
  } catch (error) {
439
+ if (db?.open) db.close();
432
440
  for (const target of [statePath, projectionDir]) {
433
441
  try { fs.rmSync(target, { recursive: true, force: true }); } catch { /* best effort */ }
434
442
  }
@@ -446,23 +454,55 @@ function discardResumeSnapshot(snapshot) {
446
454
  return errors;
447
455
  }
448
456
 
449
- function restoreResumeSnapshot(snapshot, { stateSourcePath = null } = {}) {
457
+ function restoreResumeSnapshot(snapshot, {
458
+ renameSync = fs.renameSync,
459
+ } = {}) {
450
460
  if (!snapshot) return [];
451
461
  const errors = [];
452
- const source = stateSourcePath && fs.existsSync(stateSourcePath)
453
- ? stateSourcePath
454
- : snapshot.statePath;
462
+ const runtimeDir = path.dirname(snapshot.stateDbPath);
463
+ const liveStage = path.join(
464
+ runtimeDir,
465
+ `.resume-live-${process.pid}-${Date.now()}-${Math.random().toString(16).slice(2)}`,
466
+ );
467
+ const movedLive = [];
455
468
  try {
469
+ fs.mkdirSync(liveStage, { recursive: false });
456
470
  for (const suffix of ['', '-wal', '-shm']) {
457
- fs.rmSync(`${snapshot.stateDbPath}${suffix}`, { force: true });
458
- }
459
- if (source === snapshot.statePath) {
460
- fs.renameSync(source, snapshot.stateDbPath);
461
- } else {
462
- fs.copyFileSync(source, snapshot.stateDbPath);
471
+ const live = `${snapshot.stateDbPath}${suffix}`;
472
+ if (!fs.existsSync(live)) continue;
473
+ const staged = path.join(liveStage, `state.db${suffix}`);
474
+ renameSync(live, staged);
475
+ movedLive.push({ live, staged });
463
476
  }
477
+ renameSync(snapshot.statePath, snapshot.stateDbPath);
464
478
  } catch (error) {
465
479
  errors.push(`state.db restore failed: ${error.message}`);
480
+ for (const item of [...movedLive].reverse()) {
481
+ try {
482
+ if (fs.existsSync(item.live)) {
483
+ errors.push(`live state rollback target already exists: ${item.live}`);
484
+ continue;
485
+ }
486
+ renameSync(item.staged, item.live);
487
+ } catch (rollbackError) {
488
+ errors.push(`live state rollback failed for ${item.live}: ${rollbackError.message}`);
489
+ }
490
+ }
491
+ // The snapshot and staged live image are recovery evidence. Never destroy
492
+ // either when publication or rollback is incomplete.
493
+ try {
494
+ if (fs.existsSync(liveStage) && fs.readdirSync(liveStage).length === 0) {
495
+ fs.rmdirSync(liveStage);
496
+ }
497
+ } catch (cleanupError) {
498
+ errors.push(`live state staging cleanup failed: ${cleanupError.message}`);
499
+ }
500
+ return errors;
501
+ }
502
+ try {
503
+ fs.rmSync(liveStage, { recursive: true, force: true });
504
+ } catch (error) {
505
+ errors.push(`prior live state cleanup failed: ${error.message}`);
466
506
  }
467
507
  for (const item of snapshot.projections) {
468
508
  const target = path.join(snapshot.ultraDir, item.relative);
@@ -477,7 +517,9 @@ function restoreResumeSnapshot(snapshot, { stateSourcePath = null } = {}) {
477
517
  errors.push(`projection restore failed for ${item.relative}: ${error.message}`);
478
518
  }
479
519
  }
480
- errors.push(...discardResumeSnapshot(snapshot));
520
+ if (errors.length === 0) {
521
+ errors.push(...discardResumeSnapshot(snapshot));
522
+ }
481
523
  return errors;
482
524
  }
483
525
 
@@ -523,7 +565,7 @@ function ensureInitializationWorkflows(db, baseline, { rootDir }) {
523
565
  status: 'completed',
524
566
  evidence: [{
525
567
  kind: 'authority',
526
- ref: '.ultra/state.db',
568
+ ref: '.ultra/.runtime/state.db',
527
569
  summary: 'State authority, scaffold, projection, and repository classification were verified.',
528
570
  }],
529
571
  }, { rootDir });
@@ -561,94 +603,128 @@ function resumeProject({
561
603
  absTarget, ultraDir, source, project_name, project_type, stack, resolvedMode,
562
604
  scope, repositoryProfile, projection, git_mode,
563
605
  }) {
564
- const stateDbPath = path.join(ultraDir, 'state.db');
565
- const stateExisted = fs.existsSync(stateDbPath);
606
+ let locatedStatePath;
607
+ try {
608
+ locatedStatePath = runtimePaths.locateStateDb(absTarget, { env: {} });
609
+ } catch (error) {
610
+ throw new InitProjectError(
611
+ error.code || 'RUNTIME_STATE_CONFLICT',
612
+ error.message,
613
+ { cause: error, details: error.details },
614
+ );
615
+ }
616
+ const stateExisted = fs.existsSync(locatedStatePath);
617
+ let runtimeLayout;
618
+ let gitSetup;
619
+ const stateDbPath = runtimePaths.pathsFor(absTarget).stateDbPath;
566
620
  let initialized;
567
621
  let copiedFiles = [];
568
622
  let baselineResult;
569
623
  let workflowResult;
570
- let gitSetup;
571
624
  let resumeSnapshot;
572
- try {
573
- initialized = initStateDb(stateDbPath);
574
- const { db } = initialized;
575
- if (stateExisted) {
576
- resumeSnapshot = createResumeSnapshot(db, ultraDir, stateDbPath);
577
- }
578
- if (projection && projection.taskCount > 0) assertStateAuthority(db, absTarget);
579
- copiedFiles = copyMissingTemplate(source, ultraDir);
580
- validateTasksTemplate(ultraDir);
581
- gitSetup = gitBootstrap.bootstrapGit(absTarget, { mode: git_mode });
582
- repositoryProfile.git = gitSetup.result;
583
- baselineResult = baselines.readBaseline(db);
584
- if (!baselineResult) {
585
- baselineResult = baselines.startBaseline(db, {
586
- id: 'project-baseline', project_name, project_type, stack,
587
- mode: resolvedMode, repository_revision: baselines.gitHead(absTarget),
588
- scope: scope === undefined ? ['.'] : scope,
589
- classification: repositoryProfile,
590
- }, { rootDir: absTarget });
591
- } else {
592
- baselineResult = baselines.refreshInProgressBaseline(db, {
593
- id: baselineResult.id,
594
- project_name,
595
- project_type,
596
- stack,
597
- classification: repositoryProfile,
598
- }, { rootDir: absTarget });
599
- }
600
- workflowResult = ensureInitializationWorkflows(db, baselineResult, { rootDir: absTarget });
601
- ops.appendEvent(db, {
602
- type: 'project_resumed',
603
- payload: {
604
- project_name, mode: baselineResult.mode, baseline_id: baselineResult.id,
605
- installed_missing_files: copiedFiles.length, git: gitSetup.result,
606
- },
607
- });
608
- const job = runtimeState.enqueueProjection(db, { tool_name: 'task.init_project' });
609
- const projectionResult = runtimeState.processProjectionJobs(db, { rootDir: absTarget, limit: 1 });
610
- const projected = projectionResult.jobs.find((item) => item.id === job.id);
611
- if (!projected || projected.status !== 'completed') {
612
- throw new Error(
613
- `resume projection did not complete: ${projected?.error || 'projection job missing'}`,
625
+ const completeResume = () => {
626
+ try {
627
+ if (stateExisted) {
628
+ // Snapshot the exact entry authority before initStateDb can migrate its
629
+ // schema. A failed snapshot therefore cannot partially upgrade state.
630
+ resumeSnapshot = createResumeSnapshot(ultraDir, stateDbPath);
631
+ }
632
+ initialized = initStateDb(stateDbPath);
633
+ const { db } = initialized;
634
+ if (projection && projection.taskCount > 0) assertStateAuthority(db, absTarget);
635
+ copiedFiles = copyMissingTemplate(source, ultraDir);
636
+ validateTasksTemplate(ultraDir);
637
+ repositoryProfile.git = gitSetup.result;
638
+ baselineResult = baselines.readBaseline(db);
639
+ if (!baselineResult) {
640
+ baselineResult = baselines.startBaseline(db, {
641
+ id: 'project-baseline', project_name, project_type, stack,
642
+ mode: resolvedMode, repository_revision: baselines.gitHead(absTarget),
643
+ scope: scope === undefined ? ['.'] : scope,
644
+ classification: repositoryProfile,
645
+ }, { rootDir: absTarget });
646
+ } else {
647
+ baselineResult = baselines.refreshInProgressBaseline(db, {
648
+ id: baselineResult.id,
649
+ project_name,
650
+ project_type,
651
+ stack,
652
+ classification: repositoryProfile,
653
+ }, { rootDir: absTarget });
654
+ }
655
+ workflowResult = ensureInitializationWorkflows(db, baselineResult, { rootDir: absTarget });
656
+ ops.appendEvent(db, {
657
+ type: 'project_resumed',
658
+ payload: {
659
+ project_name, mode: baselineResult.mode, baseline_id: baselineResult.id,
660
+ installed_missing_files: copiedFiles.length, git: gitSetup.result,
661
+ },
662
+ });
663
+ const job = runtimeState.enqueueProjection(db, { tool_name: 'task.init_project' });
664
+ const projectionResult = runtimeState.processProjectionJobs(
665
+ db, { rootDir: absTarget, limit: 1 },
614
666
  );
615
- }
616
- } catch (error) {
617
- if (initialized?.db?.open) initialized.db.close();
618
- const stateRollbackErrors = stateExisted
619
- ? restoreResumeSnapshot(resumeSnapshot, {
620
- // initStateDb creates this durable snapshot before a schema migration.
621
- // A later resume failure must return to the exact entry authority, not
622
- // merely to the successfully migrated intermediate database.
623
- stateSourcePath: initialized?.backup_path || null,
624
- })
625
- : [];
626
- const gitRollbackErrors = gitBootstrap.rollbackGitBootstrap(absTarget, gitSetup?.internal);
627
- for (const rel of copiedFiles.reverse()) {
628
- try { fs.rmSync(path.join(ultraDir, rel), { force: true }); } catch { /* best effort */ }
629
- }
630
- if (!stateExisted) {
631
- for (const suffix of ['', '-wal', '-shm']) {
632
- try { fs.rmSync(`${stateDbPath}${suffix}`, { force: true }); } catch { /* best effort */ }
667
+ const projected = projectionResult.jobs.find((item) => item.id === job.id);
668
+ if (!projected || projected.status !== 'completed') {
669
+ throw new Error(
670
+ `resume projection did not complete: ${projected?.error || 'projection job missing'}`,
671
+ );
672
+ }
673
+ } catch (error) {
674
+ if (initialized?.db?.open) initialized.db.close();
675
+ const stateRollbackErrors = stateExisted
676
+ ? restoreResumeSnapshot(resumeSnapshot)
677
+ : [];
678
+ const gitRollbackErrors = gitBootstrap.rollbackGitBootstrap(
679
+ absTarget, gitSetup?.internal,
680
+ );
681
+ for (const rel of copiedFiles.reverse()) {
682
+ try { fs.rmSync(path.join(ultraDir, rel), { force: true }); } catch { /* best effort */ }
683
+ }
684
+ if (!stateExisted) {
685
+ for (const suffix of ['', '-wal', '-shm']) {
686
+ try { fs.rmSync(`${stateDbPath}${suffix}`, { force: true }); } catch { /* best effort */ }
687
+ }
688
+ }
689
+ const rollbackErrors = [...stateRollbackErrors, ...gitRollbackErrors];
690
+ if (error.code && ['LEGACY_STATE_MIGRATION_REQUIRED', 'STATE_AUTHORITY_CONFLICT', 'STATE_PROJECTION_INVALID'].includes(error.code)) {
691
+ throw new InitProjectError(
692
+ error.code,
693
+ error.message,
694
+ { cause: error, details: error.details },
695
+ );
696
+ }
697
+ if (error instanceof gitBootstrap.GitBootstrapError) {
698
+ throw new InitProjectError(
699
+ error.code,
700
+ `${error.message}${rollbackErrors.length ? `; ${rollbackErrors.join('; ')}` : ''}`,
701
+ { cause: error },
702
+ );
633
703
  }
634
- }
635
- const rollbackErrors = [...stateRollbackErrors, ...gitRollbackErrors];
636
- if (error.code && ['LEGACY_STATE_MIGRATION_REQUIRED', 'STATE_AUTHORITY_CONFLICT', 'STATE_PROJECTION_INVALID'].includes(error.code)) {
637
- throw new InitProjectError(error.code, error.message, { cause: error, details: error.details });
638
- }
639
- if (error instanceof gitBootstrap.GitBootstrapError) {
640
704
  throw new InitProjectError(
641
- error.code,
642
- `${error.message}${rollbackErrors.length ? `; ${rollbackErrors.join('; ')}` : ''}`,
643
- { cause: error },
705
+ 'IO_ERROR',
706
+ `project resume failed: ${error.message}; `
707
+ + `${rollbackErrors.length ? 'resume rollback was incomplete' : 'existing authority and projections were restored'}`
708
+ + `${rollbackErrors.length ? `; ${rollbackErrors.join('; ')}` : ''}`,
709
+ { retriable: true, cause: error },
644
710
  );
645
711
  }
712
+ };
713
+
714
+ try {
715
+ runtimeLayout = runtimePaths.ensureRuntimeState(absTarget, {
716
+ admitStorageBoundary: () => {
717
+ gitSetup = gitBootstrap.bootstrapGit(absTarget, { mode: git_mode });
718
+ completeResume();
719
+ return gitSetup;
720
+ },
721
+ });
722
+ } catch (error) {
723
+ if (error instanceof InitProjectError) throw error;
646
724
  throw new InitProjectError(
647
- 'IO_ERROR',
648
- `project resume failed: ${error.message}; `
649
- + `${rollbackErrors.length ? 'resume rollback was incomplete' : 'existing authority and projections were restored'}`
650
- + `${rollbackErrors.length ? `; ${rollbackErrors.join('; ')}` : ''}`,
651
- { retriable: true, cause: error },
725
+ error.code || 'RUNTIME_STATE_MIGRATION_FAILED',
726
+ error.message,
727
+ { cause: error, details: error.details },
652
728
  );
653
729
  }
654
730
  initialized.db.close();
@@ -676,6 +752,9 @@ function resumeProject({
676
752
  workflow: workflowResult,
677
753
  };
678
754
  if (initialized.backup_path) result.migration_backup_path = initialized.backup_path;
755
+ if (runtimeLayout.backupPath) {
756
+ result.runtime_migration_backup_path = runtimeLayout.backupPath;
757
+ }
679
758
  return result;
680
759
  }
681
760
 
@@ -725,8 +804,18 @@ function initProject({
725
804
  cause: error, details: error.details,
726
805
  });
727
806
  }
807
+ let locatedStatePath;
808
+ try {
809
+ locatedStatePath = runtimePaths.locateStateDb(absTarget, { env: {} });
810
+ } catch (error) {
811
+ throw new InitProjectError(
812
+ error.code || 'RUNTIME_STATE_CONFLICT',
813
+ error.message,
814
+ { cause: error, details: error.details },
815
+ );
816
+ }
728
817
  if (projection && projection.taskCount > 0
729
- && !fs.existsSync(path.join(ultraDir, 'state.db'))) {
818
+ && !fs.existsSync(locatedStatePath)) {
730
819
  throw projectionMigrationError(projection);
731
820
  }
732
821
  return resumeProject({
@@ -758,7 +847,8 @@ function initProject({
758
847
  validateTasksTemplate(ultraDir);
759
848
  gitSetup = gitBootstrap.bootstrapGit(absTarget, { mode: git_mode });
760
849
  repositoryProfile.git = gitSetup.result;
761
- const stateDbPath = path.join(ultraDir, 'state.db');
850
+ const runtimeLayout = runtimePaths.ensureRuntimeState(absTarget);
851
+ const stateDbPath = runtimeLayout.stateDbPath;
762
852
  const { db } = initStateDb(stateDbPath);
763
853
  try {
764
854
  baselineResult = baselines.startBaseline(db, {
@@ -805,7 +895,7 @@ function initProject({
805
895
  );
806
896
  }
807
897
 
808
- const stateDbPath = path.join(ultraDir, 'state.db');
898
+ const stateDbPath = runtimePaths.pathsFor(absTarget).stateDbPath;
809
899
  const result = {
810
900
  created_path: ultraDir,
811
901
  state_db_path: stateDbPath,
@@ -834,4 +924,9 @@ function initProject({
834
924
 
835
925
  module.exports = {
836
926
  initProject, InitProjectError, DEFAULT_TEMPLATE, detectProjectMode, classifyRepository,
927
+ _internal: {
928
+ createResumeSnapshot,
929
+ discardResumeSnapshot,
930
+ restoreResumeSnapshot,
931
+ },
837
932
  };