@llblab/pi-actors 0.29.1 → 0.29.2
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/AGENTS.md +2 -2
- package/CHANGELOG.md +4 -0
- package/dist/lib/config.d.ts +1 -1
- package/dist/lib/config.js +1 -1
- package/dist/lib/recipe-discovery.d.ts +1 -1
- package/dist/lib/recipe-discovery.js +2 -3
- package/dist/lib/runtime.js +0 -11
- package/dist/skills/actors/SKILL.md +1 -1
- package/dist/skills/swarm/SKILL.md +1 -1
- package/lib/config.ts +1 -1
- package/lib/recipe-discovery.ts +2 -3
- package/lib/runtime.ts +0 -15
- package/package.json +1 -1
- package/skills/actors/SKILL.md +1 -1
- package/skills/swarm/SKILL.md +1 -1
- package/dist/lib/recipe-migration.d.ts +0 -21
- package/dist/lib/recipe-migration.js +0 -90
- package/lib/recipe-migration.ts +0 -121
package/AGENTS.md
CHANGED
|
@@ -45,7 +45,7 @@ Treat this extension as an experimental self-evolution membrane for the agent ha
|
|
|
45
45
|
|
|
46
46
|
## Operating Principles
|
|
47
47
|
|
|
48
|
-
- Prefer explicit
|
|
48
|
+
- Prefer explicit operator action over silent user-config rewrites.
|
|
49
49
|
- Keep published documentation portable: use `~`, `<repo>`, or relative paths instead of machine-local absolute paths.
|
|
50
50
|
- Preserve runtime output discipline because tool output flows directly into agent context.
|
|
51
51
|
- Keep the project lens local-first and cybernetic: agents wrap durable local capabilities as actors, then use semantic tools and messages instead of repeatedly reconstructing shell commands.
|
|
@@ -82,7 +82,7 @@ Treat this extension as an experimental self-evolution membrane for the agent ha
|
|
|
82
82
|
## Recipes And Registry
|
|
83
83
|
|
|
84
84
|
- `~/.pi/agent/recipes/*.json` is executable muscle memory: recipes there become persistent tools by location.
|
|
85
|
-
- Preserve filename identity, atomic writes, explicit operator-gated
|
|
85
|
+
- Preserve filename identity, atomic writes, explicit operator-gated changes, and local transportability.
|
|
86
86
|
- Packaged/ad hoc recipes outside the agent root are components, not user tools.
|
|
87
87
|
- Tool definitions use `template`, not `script`, and built-in/core tool names must not be shadowed.
|
|
88
88
|
- Packaged recipe growth is demand-driven: prefer reusable components over speculative scenario catalogs.
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.29.2: Legacy Migration Removal Hotfix
|
|
6
|
+
|
|
7
|
+
- `[Registry]` Removed the old legacy tool-registry migration path now that recipe-file storage is the only maintained persistence surface.
|
|
8
|
+
|
|
5
9
|
## 0.29.1: Subagent TTL Kill Hotfix
|
|
6
10
|
|
|
7
11
|
- `[Coordinator]` Added `subagent_ttl_ms` / `--subagent-ttl-ms` to the room-swarm adapter so timed-out subagent `pi -p` processes are terminated instead of only awaited.
|
package/dist/lib/config.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Persistent tool registry config helpers
|
|
3
|
-
* Zones: registry config, persistence,
|
|
3
|
+
* Zones: registry config, persistence, normalization
|
|
4
4
|
* Owns registered-tool config loading, normalization, unsupported-shape rejection, and serialization
|
|
5
5
|
*/
|
|
6
6
|
import type { CommandTemplateValue } from "./command-templates.ts";
|
package/dist/lib/config.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Persistent tool registry config helpers
|
|
3
|
-
* Zones: registry config, persistence,
|
|
3
|
+
* Zones: registry config, persistence, normalization
|
|
4
4
|
* Owns registered-tool config loading, normalization, unsupported-shape rejection, and serialization
|
|
5
5
|
*/
|
|
6
6
|
import { existsSync, readFileSync } from "node:fs";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* File-discovered recipe registry helpers
|
|
3
|
-
* Zones: recipe discovery, tool exposure,
|
|
3
|
+
* Zones: recipe discovery, tool exposure, registry diagnostics
|
|
4
4
|
* Owns filename identity discovery across prioritized recipe roots
|
|
5
5
|
*/
|
|
6
6
|
import type { RegisteredTool } from "./config.ts";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* File-discovered recipe registry helpers
|
|
3
|
-
* Zones: recipe discovery, tool exposure,
|
|
3
|
+
* Zones: recipe discovery, tool exposure, registry diagnostics
|
|
4
4
|
* Owns filename identity discovery across prioritized recipe roots
|
|
5
5
|
*/
|
|
6
6
|
import { createHash } from "node:crypto";
|
|
@@ -38,8 +38,7 @@ function listRecipeFiles(root) {
|
|
|
38
38
|
return [];
|
|
39
39
|
return readdirSync(root, { withFileTypes: true })
|
|
40
40
|
.filter((entry) => entry.isFile() &&
|
|
41
|
-
(entry.name.endsWith(".json") || entry.name.endsWith(".md"))
|
|
42
|
-
entry.name !== "legacy-tool-registry-migration-report.json")
|
|
41
|
+
(entry.name.endsWith(".json") || entry.name.endsWith(".md")))
|
|
43
42
|
.map((entry) => join(root, entry.name))
|
|
44
43
|
.sort((a, b) => a
|
|
45
44
|
.replace(/\.md$/, ".json")
|
package/dist/lib/runtime.js
CHANGED
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import * as Paths from "./paths.js";
|
|
7
7
|
import * as RecipeDiscovery from "./recipe-discovery.js";
|
|
8
|
-
import * as RecipeMigration from "./recipe-migration.js";
|
|
9
8
|
import * as Tools from "./tools.js";
|
|
10
9
|
export function createAutoToolsRuntime(deps) {
|
|
11
10
|
const tools = new Map();
|
|
@@ -86,16 +85,6 @@ export function createAutoToolsRuntime(deps) {
|
|
|
86
85
|
const warnings = [];
|
|
87
86
|
const recipeRoot = deps.recipeRoot ?? Paths.getRecipeRoot();
|
|
88
87
|
const packagedRecipeRoot = deps.packagedRecipeRoot ?? Paths.getPackagedRecipeRoot();
|
|
89
|
-
const migration = RecipeMigration.migrateLegacyToolRegistry({
|
|
90
|
-
configPath: deps.configPath,
|
|
91
|
-
recipeRoot,
|
|
92
|
-
reservedToolNames: deps.reservedToolNames,
|
|
93
|
-
});
|
|
94
|
-
warnings.push(...migration.warnings);
|
|
95
|
-
if (migration.conflicts.length > 0)
|
|
96
|
-
warnings.push(`Recipe migration conflicts: ${migration.conflicts.join(", ")}`);
|
|
97
|
-
if (migration.invalid.length > 0)
|
|
98
|
-
warnings.push(`Recipe migration invalid entries: ${migration.invalid.join(", ")}`);
|
|
99
88
|
const discovered = RecipeDiscovery.discoverRecipeSources([
|
|
100
89
|
{ root: recipeRoot, defaultTool: true, mutableUsage: true },
|
|
101
90
|
{ root: packagedRecipeRoot },
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: actors
|
|
3
3
|
description: Highest-density practical guide for pi-actors. Read this skill whenever prompt and tools are not enough for spawn, message, inspect, actor runs, tools, recipes, command templates, async lifecycle, mailboxes, artifacts, and local orchestration mechanics.
|
|
4
4
|
metadata:
|
|
5
|
-
version: 0.29.
|
|
5
|
+
version: 0.29.2
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Actors (pi-actors)
|
package/lib/config.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Persistent tool registry config helpers
|
|
3
|
-
* Zones: registry config, persistence,
|
|
3
|
+
* Zones: registry config, persistence, normalization
|
|
4
4
|
* Owns registered-tool config loading, normalization, unsupported-shape rejection, and serialization
|
|
5
5
|
*/
|
|
6
6
|
|
package/lib/recipe-discovery.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* File-discovered recipe registry helpers
|
|
3
|
-
* Zones: recipe discovery, tool exposure,
|
|
3
|
+
* Zones: recipe discovery, tool exposure, registry diagnostics
|
|
4
4
|
* Owns filename identity discovery across prioritized recipe roots
|
|
5
5
|
*/
|
|
6
6
|
|
|
@@ -98,8 +98,7 @@ function listRecipeFiles(root: string): string[] {
|
|
|
98
98
|
.filter(
|
|
99
99
|
(entry) =>
|
|
100
100
|
entry.isFile() &&
|
|
101
|
-
(entry.name.endsWith(".json") || entry.name.endsWith(".md"))
|
|
102
|
-
entry.name !== "legacy-tool-registry-migration-report.json",
|
|
101
|
+
(entry.name.endsWith(".json") || entry.name.endsWith(".md")),
|
|
103
102
|
)
|
|
104
103
|
.map((entry) => join(root, entry.name))
|
|
105
104
|
.sort(
|
package/lib/runtime.ts
CHANGED
|
@@ -8,7 +8,6 @@ import * as Config from "./config.ts";
|
|
|
8
8
|
import type { RegisteredToolExec } from "./execution.ts";
|
|
9
9
|
import * as Paths from "./paths.ts";
|
|
10
10
|
import * as RecipeDiscovery from "./recipe-discovery.ts";
|
|
11
|
-
import * as RecipeMigration from "./recipe-migration.ts";
|
|
12
11
|
import * as Tools from "./tools.ts";
|
|
13
12
|
|
|
14
13
|
export interface RuntimeContext {
|
|
@@ -142,20 +141,6 @@ export function createAutoToolsRuntime(
|
|
|
142
141
|
const recipeRoot = deps.recipeRoot ?? Paths.getRecipeRoot();
|
|
143
142
|
const packagedRecipeRoot =
|
|
144
143
|
deps.packagedRecipeRoot ?? Paths.getPackagedRecipeRoot();
|
|
145
|
-
const migration = RecipeMigration.migrateLegacyToolRegistry({
|
|
146
|
-
configPath: deps.configPath,
|
|
147
|
-
recipeRoot,
|
|
148
|
-
reservedToolNames: deps.reservedToolNames,
|
|
149
|
-
});
|
|
150
|
-
warnings.push(...migration.warnings);
|
|
151
|
-
if (migration.conflicts.length > 0)
|
|
152
|
-
warnings.push(
|
|
153
|
-
`Recipe migration conflicts: ${migration.conflicts.join(", ")}`,
|
|
154
|
-
);
|
|
155
|
-
if (migration.invalid.length > 0)
|
|
156
|
-
warnings.push(
|
|
157
|
-
`Recipe migration invalid entries: ${migration.invalid.join(", ")}`,
|
|
158
|
-
);
|
|
159
144
|
const discovered = RecipeDiscovery.discoverRecipeSources([
|
|
160
145
|
{ root: recipeRoot, defaultTool: true, mutableUsage: true },
|
|
161
146
|
{ root: packagedRecipeRoot },
|
package/package.json
CHANGED
package/skills/actors/SKILL.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: actors
|
|
3
3
|
description: Highest-density practical guide for pi-actors. Read this skill whenever prompt and tools are not enough for spawn, message, inspect, actor runs, tools, recipes, command templates, async lifecycle, mailboxes, artifacts, and local orchestration mechanics.
|
|
4
4
|
metadata:
|
|
5
|
-
version: 0.29.
|
|
5
|
+
version: 0.29.2
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Actors (pi-actors)
|
package/skills/swarm/SKILL.md
CHANGED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Legacy tool-registry to recipe-file migration helpers
|
|
3
|
-
* Zones: registry migration, recipe persistence, compatibility diagnostics
|
|
4
|
-
* Owns one-way migration from legacy tool registry entries into user recipe files
|
|
5
|
-
*/
|
|
6
|
-
export interface LegacyRegistryMigrationResult {
|
|
7
|
-
migrated: string[];
|
|
8
|
-
skipped: string[];
|
|
9
|
-
conflicts: string[];
|
|
10
|
-
invalid: string[];
|
|
11
|
-
archive?: string;
|
|
12
|
-
report?: string;
|
|
13
|
-
warnings: string[];
|
|
14
|
-
}
|
|
15
|
-
export interface LegacyRegistryMigrationOptions {
|
|
16
|
-
configPath: string;
|
|
17
|
-
recipeRoot: string;
|
|
18
|
-
reservedToolNames: Set<string>;
|
|
19
|
-
archive?: boolean;
|
|
20
|
-
}
|
|
21
|
-
export declare function migrateLegacyToolRegistry(options: LegacyRegistryMigrationOptions): LegacyRegistryMigrationResult;
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Legacy tool-registry to recipe-file migration helpers
|
|
3
|
-
* Zones: registry migration, recipe persistence, compatibility diagnostics
|
|
4
|
-
* Owns one-way migration from legacy tool registry entries into user recipe files
|
|
5
|
-
*/
|
|
6
|
-
import { existsSync, mkdirSync, renameSync } from "node:fs";
|
|
7
|
-
import { basename, join } from "node:path";
|
|
8
|
-
import * as Config from "./config.js";
|
|
9
|
-
import { writeJsonAtomic } from "./file-state.js";
|
|
10
|
-
import * as RecipeReferences from "./recipe-references.js";
|
|
11
|
-
function recipePathForTool(recipeRoot, name) {
|
|
12
|
-
return join(recipeRoot, `${name}.json`);
|
|
13
|
-
}
|
|
14
|
-
function toRecipeConfig(tool) {
|
|
15
|
-
return {
|
|
16
|
-
description: tool.description,
|
|
17
|
-
...(tool.recipe?.async !== undefined ? { async: tool.recipe.async } : {}),
|
|
18
|
-
...(tool.recipe?.state_dir ? { state_dir: tool.recipe.state_dir } : {}),
|
|
19
|
-
...(tool.storedArgs ? { args: tool.storedArgs } : {}),
|
|
20
|
-
...(tool.storedDefaults ? { defaults: tool.storedDefaults } : {}),
|
|
21
|
-
template: tool.template,
|
|
22
|
-
...(tool.recipe?.values ? { values: tool.recipe.values } : {}),
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
function nextArchivePath(configPath) {
|
|
26
|
-
const base = `${configPath}.migrated`;
|
|
27
|
-
if (!existsSync(base))
|
|
28
|
-
return base;
|
|
29
|
-
for (let index = 1; index < 1000; index += 1) {
|
|
30
|
-
const path = `${base}.${index}`;
|
|
31
|
-
if (!existsSync(path))
|
|
32
|
-
return path;
|
|
33
|
-
}
|
|
34
|
-
return `${base}.${Date.now()}`;
|
|
35
|
-
}
|
|
36
|
-
export function migrateLegacyToolRegistry(options) {
|
|
37
|
-
const { configPath, recipeRoot, reservedToolNames } = options;
|
|
38
|
-
const result = {
|
|
39
|
-
migrated: [],
|
|
40
|
-
skipped: [],
|
|
41
|
-
conflicts: [],
|
|
42
|
-
invalid: [],
|
|
43
|
-
warnings: [],
|
|
44
|
-
};
|
|
45
|
-
if (!existsSync(configPath))
|
|
46
|
-
return result;
|
|
47
|
-
const loaded = Config.loadToolConfig(configPath, reservedToolNames);
|
|
48
|
-
result.warnings.push(...loaded.warnings);
|
|
49
|
-
mkdirSync(recipeRoot, { recursive: true });
|
|
50
|
-
for (const [name, tool] of loaded.tools) {
|
|
51
|
-
const path = recipePathForTool(recipeRoot, name);
|
|
52
|
-
if (existsSync(path)) {
|
|
53
|
-
result.conflicts.push(name);
|
|
54
|
-
continue;
|
|
55
|
-
}
|
|
56
|
-
const recipe = toRecipeConfig(tool);
|
|
57
|
-
try {
|
|
58
|
-
writeJsonAtomic(path, recipe);
|
|
59
|
-
const parsed = RecipeReferences.readResolvedRecipeConfig(path);
|
|
60
|
-
if (!parsed) {
|
|
61
|
-
result.invalid.push(name);
|
|
62
|
-
continue;
|
|
63
|
-
}
|
|
64
|
-
result.migrated.push(name);
|
|
65
|
-
}
|
|
66
|
-
catch (error) {
|
|
67
|
-
result.invalid.push(`${name}: ${error instanceof Error ? error.message : String(error)}`);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
if (loaded.tools.size === 0)
|
|
71
|
-
result.skipped.push(basename(configPath));
|
|
72
|
-
const reportPath = join(recipeRoot, "legacy-tool-registry-migration-report.json");
|
|
73
|
-
writeJsonAtomic(reportPath, {
|
|
74
|
-
source: configPath,
|
|
75
|
-
migrated: result.migrated,
|
|
76
|
-
skipped: result.skipped,
|
|
77
|
-
conflicts: result.conflicts,
|
|
78
|
-
invalid: result.invalid,
|
|
79
|
-
warnings: result.warnings,
|
|
80
|
-
});
|
|
81
|
-
result.report = reportPath;
|
|
82
|
-
if (options.archive !== false &&
|
|
83
|
-
result.conflicts.length === 0 &&
|
|
84
|
-
result.invalid.length === 0) {
|
|
85
|
-
const archive = nextArchivePath(configPath);
|
|
86
|
-
renameSync(configPath, archive);
|
|
87
|
-
result.archive = archive;
|
|
88
|
-
}
|
|
89
|
-
return result;
|
|
90
|
-
}
|
package/lib/recipe-migration.ts
DELETED
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Legacy tool-registry to recipe-file migration helpers
|
|
3
|
-
* Zones: registry migration, recipe persistence, compatibility diagnostics
|
|
4
|
-
* Owns one-way migration from legacy tool registry entries into user recipe files
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { existsSync, mkdirSync, renameSync } from "node:fs";
|
|
8
|
-
import { basename, join } from "node:path";
|
|
9
|
-
|
|
10
|
-
import * as Config from "./config.ts";
|
|
11
|
-
import { writeJsonAtomic } from "./file-state.ts";
|
|
12
|
-
import type { TemplateRecipeConfig } from "./recipe-references.ts";
|
|
13
|
-
import * as RecipeReferences from "./recipe-references.ts";
|
|
14
|
-
|
|
15
|
-
export interface LegacyRegistryMigrationResult {
|
|
16
|
-
migrated: string[];
|
|
17
|
-
skipped: string[];
|
|
18
|
-
conflicts: string[];
|
|
19
|
-
invalid: string[];
|
|
20
|
-
archive?: string;
|
|
21
|
-
report?: string;
|
|
22
|
-
warnings: string[];
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export interface LegacyRegistryMigrationOptions {
|
|
26
|
-
configPath: string;
|
|
27
|
-
recipeRoot: string;
|
|
28
|
-
reservedToolNames: Set<string>;
|
|
29
|
-
archive?: boolean;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function recipePathForTool(recipeRoot: string, name: string): string {
|
|
33
|
-
return join(recipeRoot, `${name}.json`);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function toRecipeConfig(tool: Config.RegisteredTool): TemplateRecipeConfig {
|
|
37
|
-
return {
|
|
38
|
-
description: tool.description,
|
|
39
|
-
...(tool.recipe?.async !== undefined ? { async: tool.recipe.async } : {}),
|
|
40
|
-
...(tool.recipe?.state_dir ? { state_dir: tool.recipe.state_dir } : {}),
|
|
41
|
-
...(tool.storedArgs ? { args: tool.storedArgs } : {}),
|
|
42
|
-
...(tool.storedDefaults ? { defaults: tool.storedDefaults } : {}),
|
|
43
|
-
template: tool.template!,
|
|
44
|
-
...(tool.recipe?.values ? { values: tool.recipe.values } : {}),
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function nextArchivePath(configPath: string): string {
|
|
49
|
-
const base = `${configPath}.migrated`;
|
|
50
|
-
if (!existsSync(base)) return base;
|
|
51
|
-
for (let index = 1; index < 1000; index += 1) {
|
|
52
|
-
const path = `${base}.${index}`;
|
|
53
|
-
if (!existsSync(path)) return path;
|
|
54
|
-
}
|
|
55
|
-
return `${base}.${Date.now()}`;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export function migrateLegacyToolRegistry(
|
|
59
|
-
options: LegacyRegistryMigrationOptions,
|
|
60
|
-
): LegacyRegistryMigrationResult {
|
|
61
|
-
const { configPath, recipeRoot, reservedToolNames } = options;
|
|
62
|
-
const result: LegacyRegistryMigrationResult = {
|
|
63
|
-
migrated: [],
|
|
64
|
-
skipped: [],
|
|
65
|
-
conflicts: [],
|
|
66
|
-
invalid: [],
|
|
67
|
-
warnings: [],
|
|
68
|
-
};
|
|
69
|
-
if (!existsSync(configPath)) return result;
|
|
70
|
-
|
|
71
|
-
const loaded = Config.loadToolConfig(configPath, reservedToolNames);
|
|
72
|
-
result.warnings.push(...loaded.warnings);
|
|
73
|
-
mkdirSync(recipeRoot, { recursive: true });
|
|
74
|
-
|
|
75
|
-
for (const [name, tool] of loaded.tools) {
|
|
76
|
-
const path = recipePathForTool(recipeRoot, name);
|
|
77
|
-
if (existsSync(path)) {
|
|
78
|
-
result.conflicts.push(name);
|
|
79
|
-
continue;
|
|
80
|
-
}
|
|
81
|
-
const recipe = toRecipeConfig(tool);
|
|
82
|
-
try {
|
|
83
|
-
writeJsonAtomic(path, recipe);
|
|
84
|
-
const parsed = RecipeReferences.readResolvedRecipeConfig(path);
|
|
85
|
-
if (!parsed) {
|
|
86
|
-
result.invalid.push(name);
|
|
87
|
-
continue;
|
|
88
|
-
}
|
|
89
|
-
result.migrated.push(name);
|
|
90
|
-
} catch (error) {
|
|
91
|
-
result.invalid.push(
|
|
92
|
-
`${name}: ${error instanceof Error ? error.message : String(error)}`,
|
|
93
|
-
);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
if (loaded.tools.size === 0) result.skipped.push(basename(configPath));
|
|
98
|
-
|
|
99
|
-
const reportPath = join(recipeRoot, "legacy-tool-registry-migration-report.json");
|
|
100
|
-
writeJsonAtomic(reportPath, {
|
|
101
|
-
source: configPath,
|
|
102
|
-
migrated: result.migrated,
|
|
103
|
-
skipped: result.skipped,
|
|
104
|
-
conflicts: result.conflicts,
|
|
105
|
-
invalid: result.invalid,
|
|
106
|
-
warnings: result.warnings,
|
|
107
|
-
});
|
|
108
|
-
result.report = reportPath;
|
|
109
|
-
|
|
110
|
-
if (
|
|
111
|
-
options.archive !== false &&
|
|
112
|
-
result.conflicts.length === 0 &&
|
|
113
|
-
result.invalid.length === 0
|
|
114
|
-
) {
|
|
115
|
-
const archive = nextArchivePath(configPath);
|
|
116
|
-
renameSync(configPath, archive);
|
|
117
|
-
result.archive = archive;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
return result;
|
|
121
|
-
}
|