ultra-builder-pro-cli 0.19.1 → 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.
- package/.ultra-template/docs/research/README.md +26 -5
- package/.ultra-template/specs/discovery.md +1 -1
- package/.ultra-template/tasks/tasks.json +1 -1
- package/CHANGELOG.md +90 -1
- package/README.md +62 -29
- package/adapters/_shared/codex-assets.cjs +69 -11
- package/adapters/_shared/interaction-contract.cjs +60 -5
- package/adapters/_shared/runtime-assets.cjs +41 -1
- package/adapters/claude.js +7 -5
- package/adapters/codex.js +1 -1
- package/adapters/kimi.js +2 -8
- package/adapters/opencode.js +30 -28
- package/bin/orchestrator.js +64 -24
- package/commands/ultra-research.md +1 -1
- package/docs/AGENT-CONTEXT.md +79 -45
- package/docs/ARCHITECTURE.md +75 -38
- package/docs/ARTIFACT-AUTHORITY.md +234 -0
- package/docs/DECISIONS.md +20 -10
- package/docs/LEGACY-CLI-CROSSWALK.md +15 -11
- package/docs/PLUGIN-ISOLATION-CONTRACT.md +4 -3
- package/docs/ROADMAP.md +21 -6
- package/docs/RUNTIME-COMPAT-MATRIX.md +30 -13
- package/docs/STATE-DB-ACCESS-POLICY.md +11 -9
- package/docs/WORKFLOW-LIFECYCLE.md +105 -54
- package/hooks/README.md +6 -5
- package/hooks/active_task_context.py +97 -12
- package/hooks/context_spine.py +16 -4
- package/hooks/health_check.py +5 -4
- package/hooks/pre_stop_check.py +5 -2
- package/hooks/runtime_paths.py +396 -0
- package/hooks/subagent_tracker.py +5 -2
- package/hooks/workflow_checkpoint.py +16 -3
- package/hooks/workflow_context.py +11 -3
- package/hooks/workflow_resume.py +7 -4
- package/mcp-server/breadcrumb.cjs +20 -2
- package/mcp-server/lib/archive-journal.cjs +1026 -111
- package/mcp-server/lib/archive-mutation-worker.py +365 -0
- package/mcp-server/lib/artifact-registry.cjs +1126 -0
- package/mcp-server/lib/baseline-workflow.cjs +9 -4
- package/mcp-server/lib/change-packet.cjs +818 -0
- package/mcp-server/lib/change-workflow.cjs +932 -176
- package/mcp-server/lib/context-paths.cjs +111 -0
- package/mcp-server/lib/context-spine.cjs +511 -45
- package/mcp-server/lib/decision-dialogue.cjs +427 -12
- package/mcp-server/lib/delivery-transaction.cjs +471 -0
- package/mcp-server/lib/doctor-backup-worker.cjs +328 -0
- package/mcp-server/lib/doctor.cjs +375 -12
- package/mcp-server/lib/git-bootstrap.cjs +459 -47
- package/mcp-server/lib/init-project.cjs +190 -95
- package/mcp-server/lib/plan-publication-worker.cjs +830 -0
- package/mcp-server/lib/plan-store.cjs +700 -5
- package/mcp-server/lib/project-breadcrumb.cjs +23 -4
- package/mcp-server/lib/projector.cjs +174 -40
- package/mcp-server/lib/runtime-paths.cjs +1687 -0
- package/mcp-server/lib/safe-project-file.cjs +385 -0
- package/mcp-server/lib/spec-learning.cjs +28 -12
- package/mcp-server/lib/state-db.cjs +397 -13
- package/mcp-server/lib/state-ops.cjs +248 -49
- package/mcp-server/lib/telemetry.cjs +12 -3
- package/mcp-server/lib/workflow-state.cjs +614 -62
- package/mcp-server/server.cjs +282 -33
- package/orchestrator/daemon.cjs +2 -10
- package/orchestrator/parallel-orchestrator.cjs +314 -50
- package/orchestrator/planner/plan-builder.cjs +1 -1
- package/orchestrator/recovery.cjs +125 -7
- package/orchestrator/session-close-journal-worker.cjs +5 -0
- package/orchestrator/session-close-journal.cjs +1014 -0
- package/orchestrator/session-runner.cjs +679 -69
- package/orchestrator/worktree-manager.cjs +186 -35
- package/package.json +2 -3
- package/skills/cc-collab/SKILL.md +4 -1
- package/skills/codex-collab/SKILL.md +5 -2
- package/skills/ultra-change/SKILL.md +38 -13
- package/skills/ultra-deliver/SKILL.md +23 -11
- package/skills/ultra-dev/SKILL.md +33 -6
- package/skills/ultra-doctor/SKILL.md +6 -2
- package/skills/ultra-init/SKILL.md +4 -2
- package/skills/ultra-plan/SKILL.md +68 -18
- package/skills/ultra-research/SKILL.md +45 -32
- package/skills/ultra-review/SKILL.md +9 -5
- package/skills/ultra-status/SKILL.md +9 -4
- package/skills/ultra-test/SKILL.md +15 -7
- package/skills/ultra-think/SKILL.md +6 -0
- package/skills/ultra-think/references/decision-dialogue.md +61 -14
- package/skills/ultra-verify/SKILL.md +4 -1
- package/spec/cli-protocol.md +19 -7
- package/spec/mcp-tools.yaml +531 -46
- package/spec/schemas/change-delta.v1.schema.json +153 -0
- package/spec/schemas/documentation-reconciliation.v1.schema.json +106 -0
- package/spec/schemas/mcp-tools.schema.json +1 -1
- package/spec/schemas/state-db.sql +57 -17
- package/spec/schemas/tasks.v4.5.schema.json +1 -1
- package/ultra-tools/cli.cjs +3 -2
- package/ultra-tools/commands/db.cjs +76 -25
- package/ultra-tools/commands/migrate.cjs +995 -80
- package/ultra-tools/commands/session.cjs +34 -8
- package/ultra-tools/commands/status.cjs +34 -7
- package/ultra-tools/commands/system.cjs +129 -22
- package/commands/learn.md +0 -10
- package/orchestrator/skill-miner.cjs +0 -133
- package/output-styles/coding-vibes.md +0 -67
- package/output-styles/structural-thinking.md +0 -61
- 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(
|
|
412
|
+
function createResumeSnapshot(ultraDir, stateDbPath) {
|
|
411
413
|
const token = `${process.pid}-${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
|
412
|
-
const
|
|
413
|
-
const
|
|
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, {
|
|
457
|
+
function restoreResumeSnapshot(snapshot, {
|
|
458
|
+
renameSync = fs.renameSync,
|
|
459
|
+
} = {}) {
|
|
450
460
|
if (!snapshot) return [];
|
|
451
461
|
const errors = [];
|
|
452
|
-
const
|
|
453
|
-
|
|
454
|
-
|
|
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
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
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.
|
|
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
|
-
|
|
565
|
-
|
|
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
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
baselineResult = baselines.
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
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
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
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
|
-
|
|
642
|
-
|
|
643
|
-
|
|
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
|
-
'
|
|
648
|
-
|
|
649
|
-
|
|
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(
|
|
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
|
|
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 =
|
|
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
|
};
|