@cleocode/core 2026.4.11 → 2026.4.13
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/dist/codebase-map/analyzers/architecture.d.ts.map +1 -1
- package/dist/codebase-map/analyzers/architecture.js +0 -1
- package/dist/codebase-map/analyzers/architecture.js.map +1 -1
- package/dist/conduit/local-transport.d.ts +18 -8
- package/dist/conduit/local-transport.d.ts.map +1 -1
- package/dist/conduit/local-transport.js +23 -13
- package/dist/conduit/local-transport.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +0 -1
- package/dist/config.js.map +1 -1
- package/dist/errors.d.ts +19 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +6 -0
- package/dist/errors.js.map +1 -1
- package/dist/index.js +175 -68950
- package/dist/index.js.map +1 -7
- package/dist/init.d.ts +1 -2
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +1 -2
- package/dist/init.js.map +1 -1
- package/dist/internal.d.ts +8 -3
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +13 -6
- package/dist/internal.js.map +1 -1
- package/dist/memory/learnings.d.ts +2 -2
- package/dist/memory/patterns.d.ts +6 -6
- package/dist/output.d.ts +32 -11
- package/dist/output.d.ts.map +1 -1
- package/dist/output.js +67 -67
- package/dist/output.js.map +1 -1
- package/dist/paths.js +80 -14
- package/dist/paths.js.map +1 -1
- package/dist/skills/dynamic-skill-generator.d.ts +0 -2
- package/dist/skills/dynamic-skill-generator.d.ts.map +1 -1
- package/dist/skills/dynamic-skill-generator.js.map +1 -1
- package/dist/store/agent-registry-accessor.d.ts +203 -12
- package/dist/store/agent-registry-accessor.d.ts.map +1 -1
- package/dist/store/agent-registry-accessor.js +618 -100
- package/dist/store/agent-registry-accessor.js.map +1 -1
- package/dist/store/api-key-kdf.d.ts +73 -0
- package/dist/store/api-key-kdf.d.ts.map +1 -0
- package/dist/store/api-key-kdf.js +84 -0
- package/dist/store/api-key-kdf.js.map +1 -0
- package/dist/store/cleanup-legacy.js +171 -0
- package/dist/store/cleanup-legacy.js.map +1 -0
- package/dist/store/conduit-sqlite.d.ts +184 -0
- package/dist/store/conduit-sqlite.d.ts.map +1 -0
- package/dist/store/conduit-sqlite.js +570 -0
- package/dist/store/conduit-sqlite.js.map +1 -0
- package/dist/store/global-salt.d.ts +78 -0
- package/dist/store/global-salt.d.ts.map +1 -0
- package/dist/store/global-salt.js +147 -0
- package/dist/store/global-salt.js.map +1 -0
- package/dist/store/migrate-signaldock-to-conduit.d.ts +81 -0
- package/dist/store/migrate-signaldock-to-conduit.d.ts.map +1 -0
- package/dist/store/migrate-signaldock-to-conduit.js +555 -0
- package/dist/store/migrate-signaldock-to-conduit.js.map +1 -0
- package/dist/store/nexus-sqlite.js +28 -3
- package/dist/store/nexus-sqlite.js.map +1 -1
- package/dist/store/signaldock-sqlite.d.ts +122 -19
- package/dist/store/signaldock-sqlite.d.ts.map +1 -1
- package/dist/store/signaldock-sqlite.js +401 -251
- package/dist/store/signaldock-sqlite.js.map +1 -1
- package/dist/store/sqlite-backup.js +122 -4
- package/dist/store/sqlite-backup.js.map +1 -1
- package/dist/system/backup.d.ts +0 -26
- package/dist/system/backup.d.ts.map +1 -1
- package/dist/system/runtime.d.ts +0 -2
- package/dist/system/runtime.d.ts.map +1 -1
- package/dist/system/runtime.js +3 -3
- package/dist/system/runtime.js.map +1 -1
- package/dist/tasks/add.d.ts +1 -1
- package/dist/tasks/add.d.ts.map +1 -1
- package/dist/tasks/add.js +98 -23
- package/dist/tasks/add.js.map +1 -1
- package/dist/tasks/complete.d.ts.map +1 -1
- package/dist/tasks/complete.js +4 -1
- package/dist/tasks/complete.js.map +1 -1
- package/dist/tasks/find.d.ts.map +1 -1
- package/dist/tasks/find.js +4 -1
- package/dist/tasks/find.js.map +1 -1
- package/dist/tasks/labels.d.ts.map +1 -1
- package/dist/tasks/labels.js +4 -1
- package/dist/tasks/labels.js.map +1 -1
- package/dist/tasks/relates.d.ts.map +1 -1
- package/dist/tasks/relates.js +16 -4
- package/dist/tasks/relates.js.map +1 -1
- package/dist/tasks/show.d.ts.map +1 -1
- package/dist/tasks/show.js +4 -1
- package/dist/tasks/show.js.map +1 -1
- package/dist/tasks/update.d.ts.map +1 -1
- package/dist/tasks/update.js +32 -6
- package/dist/tasks/update.js.map +1 -1
- package/dist/validation/engine.d.ts.map +1 -1
- package/dist/validation/engine.js +16 -4
- package/dist/validation/engine.js.map +1 -1
- package/dist/validation/param-utils.d.ts +5 -3
- package/dist/validation/param-utils.d.ts.map +1 -1
- package/dist/validation/param-utils.js +8 -6
- package/dist/validation/param-utils.js.map +1 -1
- package/dist/validation/protocols/_shared.d.ts.map +1 -1
- package/dist/validation/protocols/_shared.js +13 -6
- package/dist/validation/protocols/_shared.js.map +1 -1
- package/package.json +9 -7
- package/src/adapters/__tests__/manager.test.ts +0 -1
- package/src/codebase-map/analyzers/architecture.ts +0 -1
- package/src/conduit/__tests__/local-credential-flow.test.ts +20 -18
- package/src/conduit/__tests__/local-transport.test.ts +14 -12
- package/src/conduit/local-transport.ts +23 -13
- package/src/config.ts +0 -1
- package/src/errors.ts +24 -0
- package/src/hooks/handlers/__tests__/hook-automation-e2e.test.ts +2 -5
- package/src/init.ts +1 -2
- package/src/internal.ts +96 -2
- package/src/lifecycle/cant/lifecycle-rcasd.cant +133 -0
- package/src/memory/__tests__/engine-compat.test.ts +2 -2
- package/src/memory/__tests__/pipeline-manifest-sqlite.test.ts +4 -4
- package/src/observability/__tests__/index.test.ts +4 -4
- package/src/observability/__tests__/log-filter.test.ts +4 -4
- package/src/output.ts +73 -75
- package/src/sessions/__tests__/session-grade.integration.test.ts +1 -1
- package/src/sessions/__tests__/session-grade.test.ts +2 -2
- package/src/skills/__tests__/dynamic-skill-generator.test.ts +0 -2
- package/src/skills/dynamic-skill-generator.ts +0 -2
- package/src/store/__tests__/agent-registry-accessor.test.ts +807 -0
- package/src/store/__tests__/api-key-kdf.test.ts +113 -0
- package/src/store/__tests__/backup-crypto.test.ts +101 -0
- package/src/store/__tests__/backup-pack.test.ts +491 -0
- package/src/store/__tests__/backup-unpack.test.ts +298 -0
- package/src/store/__tests__/conduit-sqlite.test.ts +413 -0
- package/src/store/__tests__/global-salt.test.ts +195 -0
- package/src/store/__tests__/migrate-signaldock-to-conduit.test.ts +715 -0
- package/src/store/__tests__/regenerators.test.ts +234 -0
- package/src/store/__tests__/restore-conflict-report.test.ts +274 -0
- package/src/store/__tests__/restore-json-merge.test.ts +521 -0
- package/src/store/__tests__/signaldock-sqlite.test.ts +652 -0
- package/src/store/__tests__/sqlite-backup-global.test.ts +307 -3
- package/src/store/__tests__/sqlite-backup.test.ts +5 -1
- package/src/store/__tests__/t310-integration.test.ts +1150 -0
- package/src/store/__tests__/t310-readiness.test.ts +111 -0
- package/src/store/__tests__/t311-integration.test.ts +661 -0
- package/src/store/agent-registry-accessor.ts +847 -140
- package/src/store/api-key-kdf.ts +104 -0
- package/src/store/backup-crypto.ts +209 -0
- package/src/store/backup-pack.ts +739 -0
- package/src/store/backup-unpack.ts +583 -0
- package/src/store/conduit-sqlite.ts +655 -0
- package/src/store/global-salt.ts +175 -0
- package/src/store/migrate-signaldock-to-conduit.ts +669 -0
- package/src/store/regenerators.ts +243 -0
- package/src/store/restore-conflict-report.ts +317 -0
- package/src/store/restore-json-merge.ts +653 -0
- package/src/store/signaldock-sqlite.ts +431 -254
- package/src/store/sqlite-backup.ts +185 -10
- package/src/store/t310-readiness.ts +119 -0
- package/src/system/backup.ts +2 -62
- package/src/system/runtime.ts +4 -6
- package/src/tasks/__tests__/error-hints.test.ts +256 -0
- package/src/tasks/add.ts +99 -9
- package/src/tasks/complete.ts +4 -1
- package/src/tasks/find.ts +4 -1
- package/src/tasks/labels.ts +4 -1
- package/src/tasks/relates.ts +16 -4
- package/src/tasks/show.ts +4 -1
- package/src/tasks/update.ts +32 -3
- package/src/validation/__tests__/error-hints.test.ts +97 -0
- package/src/validation/engine.ts +16 -1
- package/src/validation/param-utils.ts +10 -7
- package/src/validation/protocols/_shared.ts +14 -6
- package/src/validation/protocols/cant/architecture-decision.cant +80 -0
- package/src/validation/protocols/cant/artifact-publish.cant +95 -0
- package/src/validation/protocols/cant/consensus.cant +74 -0
- package/src/validation/protocols/cant/contribution.cant +82 -0
- package/src/validation/protocols/cant/decomposition.cant +92 -0
- package/src/validation/protocols/cant/implementation.cant +67 -0
- package/src/validation/protocols/cant/provenance.cant +88 -0
- package/src/validation/protocols/cant/release.cant +96 -0
- package/src/validation/protocols/cant/research.cant +66 -0
- package/src/validation/protocols/cant/specification.cant +67 -0
- package/src/validation/protocols/cant/testing.cant +88 -0
- package/src/validation/protocols/cant/validation.cant +65 -0
- package/src/validation/protocols/protocols-markdown/decomposition.md +0 -4
- package/templates/config.template.json +0 -1
- package/templates/global-config.template.json +0 -1
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Global-salt subsystem for the CLEO API key KDF.
|
|
3
|
+
*
|
|
4
|
+
* @task T348
|
|
5
|
+
* @epic T310
|
|
6
|
+
* @why ADR-037 §5 — API key KDF uses machine-key + global-salt + agentId.
|
|
7
|
+
* global-salt must persist across process restarts but is machine-local.
|
|
8
|
+
* @what Atomic first-run generation, memoized read, permission/size validation.
|
|
9
|
+
*/
|
|
10
|
+
import crypto from 'node:crypto';
|
|
11
|
+
import fs from 'node:fs';
|
|
12
|
+
import path from 'node:path';
|
|
13
|
+
import { getCleoHome } from '../paths.js';
|
|
14
|
+
/** Filename for the global salt file under CLEO home. */
|
|
15
|
+
export const GLOBAL_SALT_FILENAME = 'global-salt';
|
|
16
|
+
/** Required size of the global salt in bytes. */
|
|
17
|
+
export const GLOBAL_SALT_SIZE = 32;
|
|
18
|
+
/** Required file permission mode for the global salt file (POSIX). */
|
|
19
|
+
const SALT_FILE_MODE = 0o600;
|
|
20
|
+
/**
|
|
21
|
+
* In-process memoization. Invalidated only by process restart.
|
|
22
|
+
* Cleared in tests via `__clearGlobalSaltCache()` (test-only export).
|
|
23
|
+
*/
|
|
24
|
+
let cached = null;
|
|
25
|
+
/**
|
|
26
|
+
* Returns the absolute path to the global-salt file.
|
|
27
|
+
*
|
|
28
|
+
* @returns Absolute path: `{cleoHome}/global-salt`
|
|
29
|
+
*
|
|
30
|
+
* @task T348
|
|
31
|
+
* @epic T310
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```typescript
|
|
35
|
+
* const saltPath = getGlobalSaltPath();
|
|
36
|
+
* // Linux: "/home/user/.local/share/cleo/global-salt"
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export function getGlobalSaltPath() {
|
|
40
|
+
return path.join(getCleoHome(), GLOBAL_SALT_FILENAME);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Returns the 32-byte global salt. Generates and persists atomically on first
|
|
44
|
+
* call when the file does not exist. Subsequent calls return the memoized value.
|
|
45
|
+
*
|
|
46
|
+
* Never overwrites an existing salt — doing so would invalidate every stored
|
|
47
|
+
* API key derived from it.
|
|
48
|
+
*
|
|
49
|
+
* @returns A 32-byte Buffer containing the global salt
|
|
50
|
+
* @throws {Error} If the salt file exists with wrong size or wrong permissions
|
|
51
|
+
*
|
|
52
|
+
* @task T348
|
|
53
|
+
* @epic T310
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```typescript
|
|
57
|
+
* const salt = getGlobalSalt(); // Buffer(32) [...]
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export function getGlobalSalt() {
|
|
61
|
+
if (cached !== null)
|
|
62
|
+
return cached;
|
|
63
|
+
const saltPath = getGlobalSaltPath();
|
|
64
|
+
const cleoHome = getCleoHome();
|
|
65
|
+
if (!fs.existsSync(saltPath)) {
|
|
66
|
+
// First-run generation: ensure the directory exists
|
|
67
|
+
if (!fs.existsSync(cleoHome)) {
|
|
68
|
+
fs.mkdirSync(cleoHome, { recursive: true });
|
|
69
|
+
}
|
|
70
|
+
const salt = crypto.randomBytes(GLOBAL_SALT_SIZE);
|
|
71
|
+
// Atomic write: write to tmp file, chmod, then rename into place
|
|
72
|
+
const tmpPath = `${saltPath}.tmp-${process.pid}-${Date.now()}`;
|
|
73
|
+
fs.writeFileSync(tmpPath, salt, { mode: SALT_FILE_MODE });
|
|
74
|
+
// Explicit chmod in case writeFileSync's mode arg is ignored on some FS
|
|
75
|
+
fs.chmodSync(tmpPath, SALT_FILE_MODE);
|
|
76
|
+
fs.renameSync(tmpPath, saltPath);
|
|
77
|
+
cached = salt;
|
|
78
|
+
return cached;
|
|
79
|
+
}
|
|
80
|
+
// Existing file — validate before trusting
|
|
81
|
+
const stat = fs.statSync(saltPath);
|
|
82
|
+
if (stat.size !== GLOBAL_SALT_SIZE) {
|
|
83
|
+
throw new Error(`global-salt at ${saltPath} has wrong size: expected ${GLOBAL_SALT_SIZE} bytes, got ${stat.size}. ` +
|
|
84
|
+
`Refusing to use a corrupted salt file. Delete the file manually if you intend to regenerate it ` +
|
|
85
|
+
`(this will invalidate all stored API keys).`);
|
|
86
|
+
}
|
|
87
|
+
// Permission check: only meaningful on POSIX; Windows does not support mode bits
|
|
88
|
+
if (process.platform !== 'win32') {
|
|
89
|
+
const mode = stat.mode & 0o777;
|
|
90
|
+
if (mode !== SALT_FILE_MODE) {
|
|
91
|
+
throw new Error(`global-salt at ${saltPath} has wrong permissions: expected 0o600, got 0o${mode.toString(8)}. ` +
|
|
92
|
+
`Fix with: chmod 600 ${saltPath}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
const salt = fs.readFileSync(saltPath);
|
|
96
|
+
cached = salt;
|
|
97
|
+
return cached;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Runtime validation helper for startup integrity checks.
|
|
101
|
+
*
|
|
102
|
+
* Throws if the salt file exists but is malformed (wrong size or permissions).
|
|
103
|
+
* Safe to call when the file does not yet exist — returns silently in that case
|
|
104
|
+
* because first-run generation is handled lazily by `getGlobalSalt()`.
|
|
105
|
+
*
|
|
106
|
+
* @throws {Error} If the salt file exists with wrong size or wrong permissions
|
|
107
|
+
*
|
|
108
|
+
* @task T348
|
|
109
|
+
* @epic T310
|
|
110
|
+
*
|
|
111
|
+
* @example
|
|
112
|
+
* ```typescript
|
|
113
|
+
* // Called at process startup to catch accidental salt corruption early
|
|
114
|
+
* validateGlobalSalt();
|
|
115
|
+
* ```
|
|
116
|
+
*/
|
|
117
|
+
export function validateGlobalSalt() {
|
|
118
|
+
const saltPath = getGlobalSaltPath();
|
|
119
|
+
if (!fs.existsSync(saltPath)) {
|
|
120
|
+
// Not yet generated — first-run case; no error
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
const stat = fs.statSync(saltPath);
|
|
124
|
+
if (stat.size !== GLOBAL_SALT_SIZE) {
|
|
125
|
+
throw new Error(`global-salt validation failed: size ${stat.size}, expected ${GLOBAL_SALT_SIZE}`);
|
|
126
|
+
}
|
|
127
|
+
if (process.platform !== 'win32') {
|
|
128
|
+
const mode = stat.mode & 0o777;
|
|
129
|
+
if (mode !== SALT_FILE_MODE) {
|
|
130
|
+
throw new Error(`global-salt validation failed: permissions 0o${mode.toString(8)}, expected 0o600`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Clears the in-process memoization cache so tests can exercise the
|
|
136
|
+
* first-call generation path independently.
|
|
137
|
+
*
|
|
138
|
+
* @internal TEST ONLY — do NOT export through internal.ts or re-export
|
|
139
|
+
* from any public barrel. This symbol must never appear in production call paths.
|
|
140
|
+
*
|
|
141
|
+
* @task T348
|
|
142
|
+
* @epic T310
|
|
143
|
+
*/
|
|
144
|
+
export function __clearGlobalSaltCache() {
|
|
145
|
+
cached = null;
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=global-salt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"global-salt.js","sourceRoot":"","sources":["../../src/store/global-salt.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Automatic first-run migration executor: project-tier signaldock.db → conduit.db.
|
|
3
|
+
*
|
|
4
|
+
* Implements ADR-037 §8 — on the first cleo invocation after upgrading to
|
|
5
|
+
* v2026.4.12, if a project-tier `.cleo/signaldock.db` exists and
|
|
6
|
+
* `.cleo/conduit.db` does not, this module migrates all project-local data to
|
|
7
|
+
* conduit.db and copies global-identity rows to the global-tier signaldock.db.
|
|
8
|
+
*
|
|
9
|
+
* Key properties:
|
|
10
|
+
* - Idempotent: `needsSignaldockToConduitMigration` returns false once conduit.db exists.
|
|
11
|
+
* - Atomic per file: transactions are used for conduit.db and global signaldock.db writes.
|
|
12
|
+
* - Non-destructive: legacy signaldock.db is renamed to `.pre-t310.bak`, not deleted.
|
|
13
|
+
* - Multi-project safe: `INSERT OR IGNORE` prevents duplicate global rows when multiple
|
|
14
|
+
* projects migrate the same agent.
|
|
15
|
+
* - Migrated agents flagged `requires_reauth=1` (new KDF scheme, ADR-037 §5).
|
|
16
|
+
*
|
|
17
|
+
* @task T358
|
|
18
|
+
* @epic T310
|
|
19
|
+
* @why ADR-037 §8 — automatic first-run migration from the pre-T310 project-tier
|
|
20
|
+
* signaldock.db to the new T310 topology (conduit.db + global signaldock.db
|
|
21
|
+
* + global-salt). Runs once per project on first cleo invocation after upgrade.
|
|
22
|
+
*/
|
|
23
|
+
/**
|
|
24
|
+
* Result returned by `migrateSignaldockToConduit`.
|
|
25
|
+
*
|
|
26
|
+
* @task T358
|
|
27
|
+
* @epic T310
|
|
28
|
+
*/
|
|
29
|
+
export interface MigrationResult {
|
|
30
|
+
/** `migrated` = migration ran and succeeded; `no-op` = not needed; `failed` = error occurred. */
|
|
31
|
+
status: 'migrated' | 'no-op' | 'failed';
|
|
32
|
+
/** Absolute path to the project root that was migrated. */
|
|
33
|
+
projectRoot: string;
|
|
34
|
+
/** Number of agents copied to global signaldock.db. */
|
|
35
|
+
agentsCopied: number;
|
|
36
|
+
/** Absolute path to the conduit.db that was created. */
|
|
37
|
+
conduitPath: string;
|
|
38
|
+
/** Absolute path to the global signaldock.db. */
|
|
39
|
+
globalSignaldockPath: string;
|
|
40
|
+
/** Absolute path to the legacy `.pre-t310.bak` file, or null if rename did not complete. */
|
|
41
|
+
bakPath: string | null;
|
|
42
|
+
/** Errors encountered during migration steps. Never thrown — always captured here. */
|
|
43
|
+
errors: Array<{
|
|
44
|
+
step: string;
|
|
45
|
+
error: string;
|
|
46
|
+
}>;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Returns true when the legacy migration is needed for the given project.
|
|
50
|
+
*
|
|
51
|
+
* Detection heuristic (ADR-037 §8):
|
|
52
|
+
* - `.cleo/signaldock.db` EXISTS AND `.cleo/conduit.db` DOES NOT EXIST
|
|
53
|
+
*
|
|
54
|
+
* Idempotent: returns false once conduit.db is present, regardless of .bak state.
|
|
55
|
+
*
|
|
56
|
+
* @param projectRoot - Absolute path to the project root directory.
|
|
57
|
+
* @returns True if migration is needed; false otherwise.
|
|
58
|
+
*
|
|
59
|
+
* @task T358
|
|
60
|
+
* @epic T310
|
|
61
|
+
*/
|
|
62
|
+
export declare function needsSignaldockToConduitMigration(projectRoot: string): boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Runs the signaldock.db → conduit.db migration for the given project.
|
|
65
|
+
*
|
|
66
|
+
* The migration is atomic per file (SQLite transactions for DB writes, atomic
|
|
67
|
+
* rename for the backup step). Failures are captured in `result.errors` and
|
|
68
|
+
* the function never throws — callers receive a `MigrationResult` with
|
|
69
|
+
* `status: 'failed'` on error.
|
|
70
|
+
*
|
|
71
|
+
* Safe to call when no migration is needed (returns `{status: 'no-op', ...}`).
|
|
72
|
+
* Safe to call on a partially-migrated install (idempotent via needsMigration check).
|
|
73
|
+
*
|
|
74
|
+
* @param projectRoot - Absolute path to the project root directory.
|
|
75
|
+
* @returns A `MigrationResult` describing what was done and any errors encountered.
|
|
76
|
+
*
|
|
77
|
+
* @task T358
|
|
78
|
+
* @epic T310
|
|
79
|
+
*/
|
|
80
|
+
export declare function migrateSignaldockToConduit(projectRoot: string): MigrationResult;
|
|
81
|
+
//# sourceMappingURL=migrate-signaldock-to-conduit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrate-signaldock-to-conduit.d.ts","sourceRoot":"","sources":["../../src/store/migrate-signaldock-to-conduit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAsBH;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,iGAAiG;IACjG,MAAM,EAAE,UAAU,GAAG,OAAO,GAAG,QAAQ,CAAC;IACxC,2DAA2D;IAC3D,WAAW,EAAE,MAAM,CAAC;IACpB,uDAAuD;IACvD,YAAY,EAAE,MAAM,CAAC;IACrB,wDAAwD;IACxD,WAAW,EAAE,MAAM,CAAC;IACpB,iDAAiD;IACjD,oBAAoB,EAAE,MAAM,CAAC;IAC7B,4FAA4F;IAC5F,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,sFAAsF;IACtF,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAChD;AAwCD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iCAAiC,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAI9E;AA8GD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,0BAA0B,CAAC,WAAW,EAAE,MAAM,GAAG,eAAe,CAma/E"}
|