yaaw-se 0.3.11 → 0.3.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/installer/migrations/index.d.ts +2 -2
- package/dist/installer/migrations/index.js +2 -2
- package/dist/installer/migrations/index.js.map +1 -1
- package/dist/installer/migrations/project/index.js +2 -1
- package/dist/installer/migrations/project/index.js.map +1 -1
- package/dist/installer/migrations/project/v2-to-v3.d.ts +2 -0
- package/dist/installer/migrations/project/v2-to-v3.js +56 -0
- package/dist/installer/migrations/project/v2-to-v3.js.map +1 -0
- package/dist/installer/plan.js +98 -268
- package/dist/installer/plan.js.map +1 -1
- package/dist/installer/project-state.js +3 -13
- package/dist/installer/project-state.js.map +1 -1
- package/dist/installer/status.js +67 -231
- package/dist/installer/status.js.map +1 -1
- package/dist/installer/transaction.js +58 -109
- package/dist/installer/transaction.js.map +1 -1
- package/dist/installer/types.d.ts +5 -2
- package/dist/installer/verify.js +27 -27
- package/dist/installer/verify.js.map +1 -1
- package/dist/payload/bootstrap/claude-code.md +6 -6
- package/dist/payload/bootstrap/cline.md +8 -8
- package/dist/payload/bootstrap/codex.md +7 -7
- package/dist/payload/bootstrap/gemini-cli.md +6 -6
- package/dist/payload/payload-files.json +97 -417
- package/dist/payload/payload.json +1 -1
- package/dist/payload/skills/yaaw-create-spec/SKILL.md +2 -6
- package/dist/payload/skills/yaaw-create-ticket/SKILL.md +2 -6
- package/dist/payload/skills/yaaw-create-tickets/SKILL.md +2 -6
- package/dist/payload/skills/yaaw-implement/SKILL.md +2 -6
- package/dist/payload/skills/yaaw-orchestrator/SKILL.md +2 -3
- package/dist/payload/skills/yaaw-planner/SKILL.md +2 -6
- package/dist/payload/skills/yaaw-planning-review/SKILL.md +2 -6
- package/dist/payload/skills/yaaw-prd/SKILL.md +2 -6
- package/dist/payload/skills/yaaw-refine-prd/SKILL.md +2 -6
- package/dist/payload/skills/yaaw-repair/SKILL.md +2 -6
- package/dist/payload/skills/yaaw-review/SKILL.md +2 -6
- package/dist/payload/skills/yaaw-revise-prd/SKILL.md +2 -6
- package/dist/payload/yaaw-core/registries/skills.json +38 -0
- package/dist/payload/yaaw-core/system/SYSTEM.md +121 -0
- package/dist/payload/yaaw-core/system/engine/contracts.mjs +147 -0
- package/dist/payload/yaaw-core/system/engine/repository-identity.mjs +24 -0
- package/dist/payload/yaaw-core/system/engine/routing.mjs +153 -0
- package/dist/payload/yaaw-core/system/engine/runtime.mjs +66 -0
- package/dist/payload/yaaw-core/system/kernel.yaml +145 -0
- package/dist/payload/yaaw-core/system/modules/changeability.md +27 -0
- package/dist/payload/yaaw-core/system/roles/implementer.md +16 -12
- package/dist/payload/yaaw-core/system/roles/orchestrator.md +24 -14
- package/dist/payload/yaaw-core/system/roles/planner.md +37 -11
- package/dist/payload/yaaw-core/system/roles/prd.md +26 -18
- package/dist/payload/yaaw-core/system/roles/reviewer.md +16 -15
- package/dist/payload/yaaw-core/system/schemas/handoff.schema.json +24 -161
- package/dist/payload/yaaw-core/system/schemas/intent.schema.json +11 -64
- package/dist/payload/yaaw-core/system/schemas/observed-state.schema.json +12 -162
- package/dist/payload/yaaw-core/system/schemas/repository-identity.schema.json +12 -39
- package/dist/payload/yaaw-core/system/templates/evidence.json +1 -18
- package/dist/payload/yaaw-core/system/templates/handoff.json +11 -27
- package/dist/payload/yaaw-core/system/templates/intent.json +2 -2
- package/dist/payload/yaaw-core/system/templates/observed-state.json +5 -28
- package/dist/payload/yaaw-core/system/templates/review.md +2 -2
- package/package.json +5 -2
- package/dist/payload/yaaw-core/system/core/artifact-model.md +0 -43
- package/dist/payload/yaaw-core/system/core/authority.md +0 -21
- package/dist/payload/yaaw-core/system/core/context-loading.md +0 -56
- package/dist/payload/yaaw-core/system/core/dispatch-execution.md +0 -28
- package/dist/payload/yaaw-core/system/core/execution-context.md +0 -61
- package/dist/payload/yaaw-core/system/core/framework-integrity.md +0 -60
- package/dist/payload/yaaw-core/system/core/invalidation.md +0 -13
- package/dist/payload/yaaw-core/system/core/io-contract.md +0 -23
- package/dist/payload/yaaw-core/system/core/lifecycle.md +0 -23
- package/dist/payload/yaaw-core/system/core/recovery.md +0 -17
- package/dist/payload/yaaw-core/system/core/routing.md +0 -21
- package/dist/payload/yaaw-core/system/core/state-model.md +0 -14
- package/dist/payload/yaaw-core/system/core/transitions.md +0 -36
- package/dist/payload/yaaw-core/system/expertise/changeability/MODULE.md +0 -58
- package/dist/payload/yaaw-core/system/registries/artifacts.json +0 -99
- package/dist/payload/yaaw-core/system/registries/execution-policy.json +0 -169
- package/dist/payload/yaaw-core/system/registries/expertise.json +0 -47
- package/dist/payload/yaaw-core/system/registries/handoff-policy.json +0 -67
- package/dist/payload/yaaw-core/system/registries/paths.json +0 -18
- package/dist/payload/yaaw-core/system/registries/reconciliation-policy.json +0 -18
- package/dist/payload/yaaw-core/system/registries/role-io.json +0 -30
- package/dist/payload/yaaw-core/system/registries/routing-policy.json +0 -74
- package/dist/payload/yaaw-core/system/registries/skills.json +0 -110
- package/dist/payload/yaaw-core/system/registries/transitions.json +0 -178
- package/dist/payload/yaaw-core/system/registries/workflows.json +0 -38
- package/dist/payload/yaaw-core/system/rules/artifact-writing.md +0 -10
- package/dist/payload/yaaw-core/system/rules/assumption-challenge.md +0 -109
- package/dist/payload/yaaw-core/system/rules/changeability.md +0 -38
- package/dist/payload/yaaw-core/system/rules/durable-memory.md +0 -9
- package/dist/payload/yaaw-core/system/rules/question-format.md +0 -20
- package/dist/payload/yaaw-core/system/rules/recovery-evidence.md +0 -9
- package/dist/payload/yaaw-core/system/rules/repository-identity.md +0 -42
- package/dist/payload/yaaw-core/system/rules/research-admission.md +0 -30
- package/dist/payload/yaaw-core/system/rules/review-independence.md +0 -11
- package/dist/payload/yaaw-core/system/rules/ticket-sizing.md +0 -9
- package/dist/payload/yaaw-core/system/schemas/project-state.schema.json +0 -12
- package/dist/payload/yaaw-core/system/templates/project-state.json +0 -13
- package/dist/payload/yaaw-core/system/tools/orchestration-engine.mjs +0 -210
- package/dist/payload/yaaw-core/system/tools/orchestration-runtime.mjs +0 -46
- package/dist/payload/yaaw-core/system/tools/repository-identity.mjs +0 -92
- package/dist/payload/yaaw-core/system/workflows/implementation/implement-ticket.md +0 -18
- package/dist/payload/yaaw-core/system/workflows/implementation/repair-ticket.md +0 -17
- package/dist/payload/yaaw-core/system/workflows/implementation/select-ticket.md +0 -17
- package/dist/payload/yaaw-core/system/workflows/implementation/verify-ticket.md +0 -19
- package/dist/payload/yaaw-core/system/workflows/orchestration/determine-next-action.md +0 -24
- package/dist/payload/yaaw-core/system/workflows/orchestration/dispatch.md +0 -35
- package/dist/payload/yaaw-core/system/workflows/orchestration/inspect-state.md +0 -19
- package/dist/payload/yaaw-core/system/workflows/orchestration/reconcile-state.md +0 -19
- package/dist/payload/yaaw-core/system/workflows/orchestration/recover-interruption.md +0 -32
- package/dist/payload/yaaw-core/system/workflows/orchestration/route.md +0 -27
- package/dist/payload/yaaw-core/system/workflows/planning/create-spec.md +0 -21
- package/dist/payload/yaaw-core/system/workflows/planning/create-tickets.md +0 -50
- package/dist/payload/yaaw-core/system/workflows/planning/decision-frontier.md +0 -33
- package/dist/payload/yaaw-core/system/workflows/planning/discover.md +0 -21
- package/dist/payload/yaaw-core/system/workflows/planning/question-round.md +0 -22
- package/dist/payload/yaaw-core/system/workflows/planning/readiness-review.md +0 -33
- package/dist/payload/yaaw-core/system/workflows/planning/record-decisions.md +0 -19
- package/dist/payload/yaaw-core/system/workflows/planning/replan.md +0 -24
- package/dist/payload/yaaw-core/system/workflows/planning/research.md +0 -20
- package/dist/payload/yaaw-core/system/workflows/planning/route.md +0 -28
- package/dist/payload/yaaw-core/system/workflows/planning/write-understanding.md +0 -26
- package/dist/payload/yaaw-core/system/workflows/prd/create.md +0 -22
- package/dist/payload/yaaw-core/system/workflows/prd/question-round.md +0 -20
- package/dist/payload/yaaw-core/system/workflows/prd/readiness.md +0 -22
- package/dist/payload/yaaw-core/system/workflows/prd/record-decisions.md +0 -20
- package/dist/payload/yaaw-core/system/workflows/prd/refine.md +0 -15
- package/dist/payload/yaaw-core/system/workflows/prd/revise.md +0 -18
- package/dist/payload/yaaw-core/system/workflows/prd/route.md +0 -23
- package/dist/payload/yaaw-core/system/workflows/review/classify-findings.md +0 -17
- package/dist/payload/yaaw-core/system/workflows/review/inspect-change.md +0 -20
- package/dist/payload/yaaw-core/system/workflows/review/record-review.md +0 -19
- package/dist/payload/yaaw-core/system/workflows/review/review-ticket.md +0 -24
- /package/dist/payload/yaaw-core/system/{tools → engine}/frontmatter.mjs +0 -0
- /package/dist/payload/yaaw-core/system/{tools/framework-integrity.mjs → engine/integrity.mjs} +0 -0
- /package/dist/payload/yaaw-core/system/{expertise/frontend-design/MODULE.md → modules/frontend-design.md} +0 -0
- /package/dist/payload/yaaw-core/system/{expertise/python/MODULE.md → modules/python.md} +0 -0
- /package/dist/payload/yaaw-core/system/{expertise/security/MODULE.md → modules/security.md} +0 -0
- /package/dist/payload/yaaw-core/system/{expertise/testing/MODULE.md → modules/testing.md} +0 -0
package/dist/installer/plan.js
CHANGED
|
@@ -17,85 +17,43 @@ export class ManagedConflictError extends Error {
|
|
|
17
17
|
this.name = "ManagedConflictError";
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
|
-
async function exists(path) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
return true;
|
|
24
|
-
}
|
|
25
|
-
catch {
|
|
26
|
-
return false;
|
|
27
|
-
}
|
|
20
|
+
async function exists(path) { try {
|
|
21
|
+
await access(path);
|
|
22
|
+
return true;
|
|
28
23
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
const registry = JSON.parse(await readFile(join(payloadRoot, "yaaw-core", "system", "registries", "skills.json"), "utf8"));
|
|
43
|
-
return Object.keys(registry).sort().map(id => ({ id, source: join(payloadRoot, "skills", id, "SKILL.md") }));
|
|
44
|
-
}
|
|
45
|
-
export async function resolveSkillSelection(payloadRoot, request) {
|
|
46
|
-
const all = (await canonicalSkills(payloadRoot)).map(x => x.id);
|
|
47
|
-
const core = ["yaaw-orchestrator", "yaaw-prd", "yaaw-planner", "yaaw-implement", "yaaw-review"];
|
|
48
|
-
if (Array.isArray(request)) {
|
|
49
|
-
const unknown = request.filter(x => !all.includes(x));
|
|
50
|
-
if (unknown.length)
|
|
51
|
-
throw new Error(`Unknown skills: ${unknown.join(", ")}`);
|
|
52
|
-
return [...new Set(request)];
|
|
53
|
-
}
|
|
54
|
-
if (request === "standard")
|
|
55
|
-
return all;
|
|
56
|
-
if (request === "core")
|
|
57
|
-
return core;
|
|
58
|
-
const requested = request.split(",").map(x => x.trim()).filter(Boolean);
|
|
59
|
-
const unknown = requested.filter(x => !all.includes(x));
|
|
24
|
+
catch {
|
|
25
|
+
return false;
|
|
26
|
+
} }
|
|
27
|
+
async function walk(dir) { const out = []; for (const entry of await readdir(dir, { withFileTypes: true })) {
|
|
28
|
+
const full = join(dir, entry.name);
|
|
29
|
+
if (entry.isDirectory())
|
|
30
|
+
out.push(...await walk(full));
|
|
31
|
+
else
|
|
32
|
+
out.push(full);
|
|
33
|
+
} return out; }
|
|
34
|
+
async function canonicalSkills(payloadRoot) { const kernel = JSON.parse(await readFile(join(payloadRoot, "yaaw-core", "system", "kernel.yaml"), "utf8")); return Object.keys(kernel.skills ?? {}).sort().map(id => ({ id, source: join(payloadRoot, "skills", id, "SKILL.md") })); }
|
|
35
|
+
export async function resolveSkillSelection(payloadRoot, request) { const all = (await canonicalSkills(payloadRoot)).map(x => x.id), core = ["yaaw-orchestrator", "yaaw-prd", "yaaw-planner", "yaaw-implement", "yaaw-review"]; if (Array.isArray(request)) {
|
|
36
|
+
const unknown = request.filter(x => !all.includes(x));
|
|
60
37
|
if (unknown.length)
|
|
61
38
|
throw new Error(`Unknown skills: ${unknown.join(", ")}`);
|
|
62
|
-
return [...new Set(
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
return
|
|
66
|
-
}
|
|
67
|
-
function
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
let current = dirname(path);
|
|
75
|
-
while (current !== projectRoot && !protectedDirs.has(current)) {
|
|
76
|
-
// Cleanup is intentionally repeatable. Earlier attempts may see sibling
|
|
77
|
-
// managed files that are removed later in the same transaction; the final
|
|
78
|
-
// attempt then removes the now-empty adapter/framework directory.
|
|
79
|
-
operations.push({ type: "remove-empty-dir", path: current, owner });
|
|
80
|
-
current = dirname(current);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
async function currentFileHash(path) {
|
|
84
|
-
try {
|
|
85
|
-
return sha256Bytes(await readFile(path));
|
|
86
|
-
}
|
|
87
|
-
catch {
|
|
88
|
-
return null;
|
|
89
|
-
}
|
|
39
|
+
return [...new Set(request)];
|
|
40
|
+
} if (request === "standard")
|
|
41
|
+
return all; if (request === "core")
|
|
42
|
+
return core; const requested = request.split(",").map(x => x.trim()).filter(Boolean), unknown = requested.filter(x => !all.includes(x)); if (unknown.length)
|
|
43
|
+
throw new Error(`Unknown skills: ${unknown.join(", ")}`); return [...new Set(requested)]; }
|
|
44
|
+
function rel(projectRoot, path) { return relative(projectRoot, path).replaceAll("\\", "/"); }
|
|
45
|
+
function queueEmptyParentCleanup(operations, projectRoot, path, owner) { const protectedDirs = new Set([projectRoot, join(projectRoot, ".yaaw-core"), join(projectRoot, ".yaaw-core", "project"), join(projectRoot, ".yaaw-core", "install")]); let current = dirname(path); while (current !== projectRoot && !protectedDirs.has(current)) {
|
|
46
|
+
operations.push({ type: "remove-empty-dir", path: current, owner });
|
|
47
|
+
current = dirname(current);
|
|
48
|
+
} }
|
|
49
|
+
async function currentFileHash(path) { try {
|
|
50
|
+
return sha256Bytes(await readFile(path));
|
|
90
51
|
}
|
|
52
|
+
catch {
|
|
53
|
+
return null;
|
|
54
|
+
} }
|
|
91
55
|
export async function chooseManagedFile(params) {
|
|
92
|
-
const { ctx, previous, path, owner, operations, records, conflicts, backupStamp } = params;
|
|
93
|
-
const pathRel = rel(ctx.projectRoot, path);
|
|
94
|
-
const expected = params.source ? await readFile(params.source) : Buffer.from(params.content ?? "");
|
|
95
|
-
const expectedHash = sha256Bytes(expected);
|
|
96
|
-
const diskHash = await currentFileHash(path);
|
|
97
|
-
const prior = previous?.managedFiles?.[pathRel];
|
|
98
|
-
const hasConflict = diskHash !== null && (prior ? (prior.localOverride === true || diskHash !== prior.sha256) : diskHash !== expectedHash);
|
|
56
|
+
const { ctx, previous, path, owner, operations, records, conflicts, backupStamp } = params, pathRel = rel(ctx.projectRoot, path), expected = params.source ? await readFile(params.source) : Buffer.from(params.content ?? ""), expectedHash = sha256Bytes(expected), diskHash = await currentFileHash(path), prior = previous?.managedFiles?.[pathRel], hasConflict = diskHash !== null && (prior ? (prior.localOverride === true || diskHash !== prior.sha256) : diskHash !== expectedHash);
|
|
99
57
|
if (hasConflict && ctx.conflictPolicy === "fail") {
|
|
100
58
|
conflicts.push(pathRel);
|
|
101
59
|
return;
|
|
@@ -116,18 +74,13 @@ export async function chooseManagedFile(params) {
|
|
|
116
74
|
records[pathRel] = { owner, sha256: expectedHash };
|
|
117
75
|
}
|
|
118
76
|
export async function chooseManagedSection(params) {
|
|
119
|
-
const { ctx, previous, op, sectionRecords, operations, conflicts, backupStamp } = params;
|
|
120
|
-
const pathRel = rel(ctx.projectRoot, op.path);
|
|
77
|
+
const { ctx, previous, op, sectionRecords, operations, conflicts, backupStamp } = params, pathRel = rel(ctx.projectRoot, op.path);
|
|
121
78
|
let original = "";
|
|
122
79
|
try {
|
|
123
80
|
original = await readFile(op.path, "utf8");
|
|
124
81
|
}
|
|
125
82
|
catch { }
|
|
126
|
-
const existing = extractManagedSection(original, op.sectionId);
|
|
127
|
-
const expectedHash = managedSectionHash(op.content);
|
|
128
|
-
const prior = previous?.managedSections?.[pathRel]?.[op.sectionId];
|
|
129
|
-
const existingHash = existing === null ? null : managedSectionHash(existing);
|
|
130
|
-
const conflict = existing !== null && (prior ? (prior.localOverride === true || existingHash !== prior.sha256) : existingHash !== expectedHash);
|
|
83
|
+
const existing = extractManagedSection(original, op.sectionId), expectedHash = managedSectionHash(op.content), prior = previous?.managedSections?.[pathRel]?.[op.sectionId], existingHash = existing === null ? null : managedSectionHash(existing), conflict = existing !== null && (prior ? (prior.localOverride === true || existingHash !== prior.sha256) : existingHash !== expectedHash);
|
|
131
84
|
if (conflict && ctx.conflictPolicy === "fail") {
|
|
132
85
|
conflicts.push(`${pathRel}#${op.sectionId}`);
|
|
133
86
|
return;
|
|
@@ -138,16 +91,14 @@ export async function chooseManagedSection(params) {
|
|
|
138
91
|
return;
|
|
139
92
|
}
|
|
140
93
|
if (conflict && ctx.conflictPolicy === "backup-replace") {
|
|
141
|
-
|
|
142
|
-
operations.push({ type: "write-managed-file", path: backupPath, content: original, owner: "installer:backup" });
|
|
94
|
+
operations.push({ type: "write-managed-file", path: join(ctx.projectRoot, ".yaaw-core", "install", "backups", backupStamp, pathRel), content: original, owner: "installer:backup" });
|
|
143
95
|
}
|
|
144
96
|
operations.push(op);
|
|
145
97
|
sectionRecords[pathRel] ??= {};
|
|
146
98
|
sectionRecords[pathRel][op.sectionId] = { owner: op.owner, sha256: expectedHash };
|
|
147
99
|
}
|
|
148
100
|
export async function chooseManagedConfigKeys(params) {
|
|
149
|
-
const { ctx, previous, op, configRecords, operations, conflicts, backupStamp } = params;
|
|
150
|
-
const pathRel = rel(ctx.projectRoot, op.path);
|
|
101
|
+
const { ctx, previous, op, configRecords, operations, conflicts, backupStamp } = params, pathRel = rel(ctx.projectRoot, op.path);
|
|
151
102
|
let original = "";
|
|
152
103
|
try {
|
|
153
104
|
original = await readFile(op.path, "utf8");
|
|
@@ -158,11 +109,7 @@ export async function chooseManagedConfigKeys(params) {
|
|
|
158
109
|
const ownedEntries = [];
|
|
159
110
|
let backupQueued = false;
|
|
160
111
|
for (const entry of op.entries) {
|
|
161
|
-
const prior = previous?.managedConfigKeys?.[pathRel]?.[entry.key];
|
|
162
|
-
const current = readTomlManagedValue(original, entry.key);
|
|
163
|
-
const expectedHash = semanticConfigHash(entry.value);
|
|
164
|
-
const currentHash = current === undefined ? null : semanticConfigHash(current);
|
|
165
|
-
const namespacedRole = entry.key.startsWith("agents.yaaw_");
|
|
112
|
+
const prior = previous?.managedConfigKeys?.[pathRel]?.[entry.key], current = readTomlManagedValue(original, entry.key), expectedHash = semanticConfigHash(entry.value), currentHash = current === undefined ? null : semanticConfigHash(current), namespacedRole = entry.key.startsWith("agents.yaaw_");
|
|
166
113
|
if (!prior) {
|
|
167
114
|
if (current === undefined) {
|
|
168
115
|
ownedEntries.push(entry);
|
|
@@ -170,17 +117,14 @@ export async function chooseManagedConfigKeys(params) {
|
|
|
170
117
|
configRecords[pathRel][entry.key] = { owner: op.owner, sha256: expectedHash, value: entry.value };
|
|
171
118
|
continue;
|
|
172
119
|
}
|
|
173
|
-
if (!namespacedRole && currentHash === expectedHash)
|
|
174
|
-
// Compatible user-owned value satisfies the request. Do not claim ownership.
|
|
120
|
+
if (!namespacedRole && currentHash === expectedHash)
|
|
175
121
|
continue;
|
|
176
|
-
}
|
|
177
122
|
if (ctx.conflictPolicy === "fail" || ctx.conflictPolicy === "keep") {
|
|
178
123
|
conflicts.push(`${pathRel}#${entry.key}`);
|
|
179
124
|
continue;
|
|
180
125
|
}
|
|
181
126
|
if (ctx.conflictPolicy === "backup-replace" && !backupQueued) {
|
|
182
|
-
|
|
183
|
-
operations.push({ type: "write-managed-file", path: backupPath, content: original, owner: "installer:backup" });
|
|
127
|
+
operations.push({ type: "write-managed-file", path: join(ctx.projectRoot, ".yaaw-core", "install", "backups", backupStamp, pathRel), content: original, owner: "installer:backup" });
|
|
184
128
|
backupQueued = true;
|
|
185
129
|
}
|
|
186
130
|
ownedEntries.push(entry);
|
|
@@ -196,19 +140,12 @@ export async function chooseManagedConfigKeys(params) {
|
|
|
196
140
|
if (modified && ctx.conflictPolicy === "keep") {
|
|
197
141
|
if (current !== undefined) {
|
|
198
142
|
configRecords[pathRel] ??= {};
|
|
199
|
-
configRecords[pathRel][entry.key] = {
|
|
200
|
-
owner: op.owner,
|
|
201
|
-
sha256: currentHash,
|
|
202
|
-
value: current,
|
|
203
|
-
packageSha256: expectedHash,
|
|
204
|
-
localOverride: true
|
|
205
|
-
};
|
|
143
|
+
configRecords[pathRel][entry.key] = { owner: op.owner, sha256: currentHash, value: current, packageSha256: expectedHash, localOverride: true };
|
|
206
144
|
}
|
|
207
145
|
continue;
|
|
208
146
|
}
|
|
209
147
|
if (modified && ctx.conflictPolicy === "backup-replace" && !backupQueued) {
|
|
210
|
-
|
|
211
|
-
operations.push({ type: "write-managed-file", path: backupPath, content: original, owner: "installer:backup" });
|
|
148
|
+
operations.push({ type: "write-managed-file", path: join(ctx.projectRoot, ".yaaw-core", "install", "backups", backupStamp, pathRel), content: original, owner: "installer:backup" });
|
|
212
149
|
backupQueued = true;
|
|
213
150
|
}
|
|
214
151
|
ownedEntries.push(entry);
|
|
@@ -219,8 +156,7 @@ export async function chooseManagedConfigKeys(params) {
|
|
|
219
156
|
operations.push({ ...op, entries: ownedEntries });
|
|
220
157
|
}
|
|
221
158
|
export async function protectConfigRemoval(params) {
|
|
222
|
-
const { ctx, pathRel, records, operations, conflicts, backupStamp } = params;
|
|
223
|
-
const path = join(ctx.projectRoot, pathRel);
|
|
159
|
+
const { ctx, pathRel, records, operations, conflicts, backupStamp } = params, path = join(ctx.projectRoot, pathRel);
|
|
224
160
|
let original = "";
|
|
225
161
|
try {
|
|
226
162
|
original = await readFile(path, "utf8");
|
|
@@ -235,8 +171,7 @@ export async function protectConfigRemoval(params) {
|
|
|
235
171
|
const current = readTomlManagedValue(original, key);
|
|
236
172
|
if (current === undefined)
|
|
237
173
|
continue;
|
|
238
|
-
const currentHash = semanticConfigHash(current);
|
|
239
|
-
const modified = record.localOverride === true || currentHash !== record.sha256;
|
|
174
|
+
const currentHash = semanticConfigHash(current), modified = record.localOverride === true || currentHash !== record.sha256;
|
|
240
175
|
if (modified && ctx.conflictPolicy === "fail") {
|
|
241
176
|
conflicts.push(`${pathRel}#${key}`);
|
|
242
177
|
continue;
|
|
@@ -244,8 +179,7 @@ export async function protectConfigRemoval(params) {
|
|
|
244
179
|
if (modified && ctx.conflictPolicy === "keep")
|
|
245
180
|
continue;
|
|
246
181
|
if (modified && ctx.conflictPolicy === "backup-replace" && !backupQueued) {
|
|
247
|
-
|
|
248
|
-
operations.push({ type: "write-managed-file", path: backupPath, content: original, owner: "installer:backup" });
|
|
182
|
+
operations.push({ type: "write-managed-file", path: join(ctx.projectRoot, ".yaaw-core", "install", "backups", backupStamp, pathRel), content: original, owner: "installer:backup" });
|
|
249
183
|
backupQueued = true;
|
|
250
184
|
}
|
|
251
185
|
removable.push(key);
|
|
@@ -255,62 +189,32 @@ export async function protectConfigRemoval(params) {
|
|
|
255
189
|
queueEmptyParentCleanup(operations, ctx.projectRoot, path, "integration:codex");
|
|
256
190
|
}
|
|
257
191
|
}
|
|
258
|
-
async function protectRemoval(params) {
|
|
259
|
-
const
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
if (modified && ctx.conflictPolicy === "keep") {
|
|
270
|
-
operations.push({ type: "preserve", path, reason: "local managed-file override retained during removal" });
|
|
271
|
-
return;
|
|
272
|
-
}
|
|
273
|
-
if (modified && ctx.conflictPolicy === "backup-replace") {
|
|
274
|
-
const backupPath = join(ctx.projectRoot, ".yaaw-core", "install", "backups", backupStamp, pathRel);
|
|
275
|
-
operations.push({ type: "write-managed-file", path: backupPath, content: await readFile(path), owner: "installer:backup" });
|
|
276
|
-
}
|
|
277
|
-
operations.push({ type: "remove-managed-file", path, owner: record.owner });
|
|
278
|
-
queueEmptyParentCleanup(operations, ctx.projectRoot, path, record.owner);
|
|
279
|
-
}
|
|
280
|
-
async function protectSectionRemoval(params) {
|
|
281
|
-
const { ctx, pathRel, sectionId, record, operations, conflicts, backupStamp } = params;
|
|
282
|
-
const path = join(ctx.projectRoot, pathRel);
|
|
283
|
-
let original = "";
|
|
284
|
-
try {
|
|
285
|
-
original = await readFile(path, "utf8");
|
|
286
|
-
}
|
|
287
|
-
catch {
|
|
288
|
-
return;
|
|
289
|
-
}
|
|
290
|
-
const existing = extractManagedSection(original, sectionId);
|
|
291
|
-
if (existing === null)
|
|
292
|
-
return;
|
|
293
|
-
const modified = record.localOverride === true || managedSectionHash(existing) !== record.sha256;
|
|
294
|
-
if (modified && ctx.conflictPolicy === "fail") {
|
|
295
|
-
conflicts.push(`${pathRel}#${sectionId}`);
|
|
296
|
-
return;
|
|
297
|
-
}
|
|
298
|
-
if (modified && ctx.conflictPolicy === "keep") {
|
|
299
|
-
operations.push({ type: "preserve", path, reason: "local managed-section override retained during removal" });
|
|
300
|
-
return;
|
|
301
|
-
}
|
|
302
|
-
if (modified && ctx.conflictPolicy === "backup-replace") {
|
|
303
|
-
const backupPath = join(ctx.projectRoot, ".yaaw-core", "install", "backups", backupStamp, pathRel);
|
|
304
|
-
operations.push({ type: "write-managed-file", path: backupPath, content: original, owner: "installer:backup" });
|
|
305
|
-
}
|
|
306
|
-
operations.push({ type: "remove-managed-section", path, sectionId, owner: record.owner });
|
|
192
|
+
async function protectRemoval(params) { const { ctx, pathRel, record, operations, conflicts, backupStamp } = params, path = join(ctx.projectRoot, pathRel), diskHash = await currentFileHash(path); if (diskHash === null)
|
|
193
|
+
return; const modified = record.localOverride === true || diskHash !== record.sha256; if (modified && ctx.conflictPolicy === "fail") {
|
|
194
|
+
conflicts.push(pathRel);
|
|
195
|
+
return;
|
|
196
|
+
} if (modified && ctx.conflictPolicy === "keep") {
|
|
197
|
+
operations.push({ type: "preserve", path, reason: "local managed-file override retained during removal" });
|
|
198
|
+
return;
|
|
199
|
+
} if (modified && ctx.conflictPolicy === "backup-replace")
|
|
200
|
+
operations.push({ type: "write-managed-file", path: join(ctx.projectRoot, ".yaaw-core", "install", "backups", backupStamp, pathRel), content: await readFile(path), owner: "installer:backup" }); operations.push({ type: "remove-managed-file", path, owner: record.owner }); queueEmptyParentCleanup(operations, ctx.projectRoot, path, record.owner); }
|
|
201
|
+
async function protectSectionRemoval(params) { const { ctx, pathRel, sectionId, record, operations, conflicts, backupStamp } = params, path = join(ctx.projectRoot, pathRel); let original = ""; try {
|
|
202
|
+
original = await readFile(path, "utf8");
|
|
307
203
|
}
|
|
204
|
+
catch {
|
|
205
|
+
return;
|
|
206
|
+
} const existing = extractManagedSection(original, sectionId); if (existing === null)
|
|
207
|
+
return; const modified = record.localOverride === true || managedSectionHash(existing) !== record.sha256; if (modified && ctx.conflictPolicy === "fail") {
|
|
208
|
+
conflicts.push(`${pathRel}#${sectionId}`);
|
|
209
|
+
return;
|
|
210
|
+
} if (modified && ctx.conflictPolicy === "keep") {
|
|
211
|
+
operations.push({ type: "preserve", path, reason: "local managed-section override retained during removal" });
|
|
212
|
+
return;
|
|
213
|
+
} if (modified && ctx.conflictPolicy === "backup-replace")
|
|
214
|
+
operations.push({ type: "write-managed-file", path: join(ctx.projectRoot, ".yaaw-core", "install", "backups", backupStamp, pathRel), content: original, owner: "installer:backup" }); operations.push({ type: "remove-managed-section", path, sectionId, owner: record.owner }); }
|
|
308
215
|
export async function buildInstallPlan(ctx, previous) {
|
|
309
|
-
const warnings = [];
|
|
310
|
-
const
|
|
311
|
-
const conflicts = [];
|
|
312
|
-
const now = new Date().toISOString();
|
|
313
|
-
const backupStamp = now.replace(/[:.]/g, "-");
|
|
216
|
+
const warnings = [], operations = [{ type: "mkdir", path: ctx.projectRoot, owner: "layout" }], conflicts = [];
|
|
217
|
+
const now = new Date().toISOString(), backupStamp = now.replace(/[:.]/g, "-");
|
|
314
218
|
previous = previous ? migrateInstallationManifest(previous) : null;
|
|
315
219
|
if (ctx.action === "uninstall") {
|
|
316
220
|
if (!previous)
|
|
@@ -320,27 +224,15 @@ export async function buildInstallPlan(ctx, previous) {
|
|
|
320
224
|
continue;
|
|
321
225
|
await protectRemoval({ ctx, previous, pathRel, record, operations, conflicts, backupStamp });
|
|
322
226
|
}
|
|
323
|
-
for (const [pathRel, sections] of Object.entries(previous.managedSections))
|
|
324
|
-
for (const [sectionId, record] of Object.entries(sections))
|
|
227
|
+
for (const [pathRel, sections] of Object.entries(previous.managedSections))
|
|
228
|
+
for (const [sectionId, record] of Object.entries(sections))
|
|
325
229
|
await protectSectionRemoval({ ctx, previous, pathRel, sectionId, record, operations, conflicts, backupStamp });
|
|
326
|
-
|
|
327
|
-
}
|
|
328
|
-
for (const [pathRel, records] of Object.entries(previous.managedConfigKeys ?? {})) {
|
|
230
|
+
for (const [pathRel, records] of Object.entries(previous.managedConfigKeys ?? {}))
|
|
329
231
|
await protectConfigRemoval({ ctx, pathRel, records, operations, conflicts, backupStamp });
|
|
330
|
-
}
|
|
331
232
|
if (conflicts.length)
|
|
332
233
|
throw new ManagedConflictError(conflicts);
|
|
333
|
-
operations.push({ type: "remove-managed-file", path: join(ctx.projectRoot, MANIFEST_RELATIVE_PATH), owner: "installer" });
|
|
334
|
-
operations.
|
|
335
|
-
type: "write-managed-file",
|
|
336
|
-
path: join(ctx.projectRoot, ".yaaw-core", "install", "uninstalled.json"),
|
|
337
|
-
content: JSON.stringify({ schema: "yaaw.uninstalled/v1", version: previous.yaawVersion, uninstalledAt: now, projectMemory: ".yaaw-core/project" }, null, 2) + "\n",
|
|
338
|
-
owner: "installer"
|
|
339
|
-
});
|
|
340
|
-
return {
|
|
341
|
-
plan: { action: ctx.action, projectRoot: ctx.projectRoot, operations, selectedIntegrations: [], selectedSkills: [], warnings: ["Durable .yaaw-core/project data will be preserved."] },
|
|
342
|
-
manifest: null
|
|
343
|
-
};
|
|
234
|
+
operations.push({ type: "remove-managed-file", path: join(ctx.projectRoot, MANIFEST_RELATIVE_PATH), owner: "installer" }, { type: "write-managed-file", path: join(ctx.projectRoot, ".yaaw-core", "install", "uninstalled.json"), content: JSON.stringify({ schema: "yaaw.uninstalled/v1", version: previous.yaawVersion, uninstalledAt: now, projectMemory: ".yaaw-core/project" }, null, 2) + "\n", owner: "installer" });
|
|
235
|
+
return { plan: { action: ctx.action, projectRoot: ctx.projectRoot, operations, selectedIntegrations: [], selectedSkills: [], warnings: ["Durable .yaaw-core/project data will be preserved."] }, manifest: null };
|
|
344
236
|
}
|
|
345
237
|
if (previous) {
|
|
346
238
|
if (previous.installationSchema > CURRENT_INSTALLATION_SCHEMA)
|
|
@@ -351,89 +243,46 @@ export async function buildInstallPlan(ctx, previous) {
|
|
|
351
243
|
throw new Error(`Installed project schema ${previous.projectSchema} is newer than this package supports (${CURRENT_PROJECT_SCHEMA}); downgrade is blocked.`);
|
|
352
244
|
for (const integrationId of ctx.selectedIntegrations) {
|
|
353
245
|
const installed = previous.integrations[integrationId];
|
|
354
|
-
if (installed && installed.adapterVersion > getIntegration(integrationId).adapterVersion)
|
|
246
|
+
if (installed && installed.adapterVersion > getIntegration(integrationId).adapterVersion)
|
|
355
247
|
throw new Error(`Installed ${integrationId} adapter v${installed.adapterVersion} is newer than this package supports; downgrade is blocked.`);
|
|
356
|
-
}
|
|
357
248
|
}
|
|
358
249
|
}
|
|
359
250
|
const manifest = emptyManifest(ctx.packageVersion, previous?.installedAt ?? now);
|
|
360
251
|
manifest.updatedAt = now;
|
|
361
252
|
manifest.skills = [...ctx.selectedSkills];
|
|
362
|
-
const coreRoot = join(ctx.payloadRoot, "yaaw-core", "system");
|
|
363
|
-
const coreFiles = await walk(coreRoot);
|
|
364
|
-
const desiredFilePaths = new Set();
|
|
253
|
+
const coreRoot = join(ctx.payloadRoot, "yaaw-core", "system"), coreFiles = await walk(coreRoot), desiredFilePaths = new Set();
|
|
365
254
|
for (const source of coreFiles) {
|
|
366
|
-
const coreRel = relative(coreRoot, source);
|
|
367
|
-
const target = join(ctx.projectRoot, ".yaaw-core", "system", coreRel);
|
|
255
|
+
const coreRel = relative(coreRoot, source), target = join(ctx.projectRoot, ".yaaw-core", "system", coreRel);
|
|
368
256
|
desiredFilePaths.add(rel(ctx.projectRoot, target));
|
|
369
257
|
await chooseManagedFile({ ctx, previous, path: target, owner: "package:system", source, operations, records: manifest.managedFiles, conflicts, backupStamp });
|
|
370
258
|
}
|
|
371
259
|
operations.push(...await planProjectInitialization(ctx.payloadRoot, ctx.projectRoot));
|
|
372
260
|
if (["quick-update", "modify", "repair"].includes(ctx.action)) {
|
|
373
|
-
for (const name of ["observed-state.json", "handoff.json", "intent.json", "dispatch-failures.json"])
|
|
374
|
-
operations.push({
|
|
375
|
-
type: "remove-runtime-file",
|
|
376
|
-
path: join(ctx.projectRoot, ".yaaw-core", "runtime", name),
|
|
377
|
-
owner: "runtime:invalidate"
|
|
378
|
-
});
|
|
379
|
-
}
|
|
261
|
+
for (const name of ["observed-state.json", "handoff.json", "intent.json", "dispatch-failures.json"])
|
|
262
|
+
operations.push({ type: "remove-runtime-file", path: join(ctx.projectRoot, ".yaaw-core", "runtime", name), owner: "runtime:invalidate" });
|
|
380
263
|
warnings.push("Replaceable YAAW runtime coordination caches will be invalidated after package changes.");
|
|
381
264
|
}
|
|
382
|
-
if (previous)
|
|
383
|
-
for (const migration of migrationPath(projectMigrations, previous.projectSchema, CURRENT_PROJECT_SCHEMA))
|
|
384
|
-
operations.push(...await migration.plan({
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
toVersion: migration.to
|
|
389
|
-
}));
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
const configurationSummaries = [];
|
|
393
|
-
const skillMap = new Map((await canonicalSkills(ctx.payloadRoot)).map(x => [x.id, x]));
|
|
394
|
-
const selectedCanonical = ctx.selectedSkills.map(id => {
|
|
395
|
-
const skill = skillMap.get(id);
|
|
396
|
-
if (!skill)
|
|
397
|
-
throw new Error(`Unknown canonical skill: ${id}`);
|
|
398
|
-
return skill;
|
|
399
|
-
});
|
|
265
|
+
if (previous)
|
|
266
|
+
for (const migration of migrationPath(projectMigrations, previous.projectSchema, CURRENT_PROJECT_SCHEMA))
|
|
267
|
+
operations.push(...await migration.plan({ projectRoot: ctx.projectRoot, payloadRoot: ctx.payloadRoot, fromVersion: migration.from, toVersion: migration.to }));
|
|
268
|
+
const configurationSummaries = [], skillMap = new Map((await canonicalSkills(ctx.payloadRoot)).map(x => [x.id, x]));
|
|
269
|
+
const selectedCanonical = ctx.selectedSkills.map(id => { const skill = skillMap.get(id); if (!skill)
|
|
270
|
+
throw new Error(`Unknown canonical skill: ${id}`); return skill; });
|
|
400
271
|
for (const integrationId of ctx.selectedIntegrations) {
|
|
401
|
-
const adapter = getIntegration(integrationId);
|
|
402
|
-
const previousRecord = previous?.integrations?.[integrationId];
|
|
403
|
-
const previousConfiguration = previousRecord?.configuration;
|
|
272
|
+
const adapter = getIntegration(integrationId), previousRecord = previous?.integrations?.[integrationId], previousConfiguration = previousRecord?.configuration;
|
|
404
273
|
let settings = ctx.integrationSettings?.[integrationId] ?? previousConfiguration?.settings ?? previousRecord?.runtime;
|
|
405
274
|
if (adapter.configuration && settings === undefined)
|
|
406
275
|
settings = adapter.configuration.defaultSettings();
|
|
407
|
-
const ictx = { projectRoot: ctx.projectRoot, payloadRoot: ctx.payloadRoot, settings };
|
|
408
|
-
const
|
|
409
|
-
const adapterOps = [...await adapter.planSkills(ictx, selectedCanonical), ...await adapter.planBootstrap(ictx), ...runtimeOps];
|
|
410
|
-
const installationRecord = {
|
|
411
|
-
adapterVersion: adapter.adapterVersion,
|
|
412
|
-
skillsRoot: rel(ctx.projectRoot, adapter.skillsRoot(ctx.projectRoot)),
|
|
413
|
-
bootstrap: adapter.bootstrapRelativePath
|
|
414
|
-
};
|
|
276
|
+
const ictx = { projectRoot: ctx.projectRoot, payloadRoot: ctx.payloadRoot, settings }, runtimeOps = adapter.configuration ? await adapter.configuration.plan(ictx) : adapter.planRuntime ? await adapter.planRuntime(ictx) : [], adapterOps = [...await adapter.planSkills(ictx, selectedCanonical), ...await adapter.planBootstrap(ictx), ...runtimeOps];
|
|
277
|
+
const installationRecord = { adapterVersion: adapter.adapterVersion, skillsRoot: rel(ctx.projectRoot, adapter.skillsRoot(ctx.projectRoot)), bootstrap: adapter.bootstrapRelativePath };
|
|
415
278
|
if (adapter.configuration) {
|
|
416
|
-
const normalizedSettings = adapter.configuration.normalize(settings);
|
|
417
|
-
const preserveReviewedState = Boolean(previousConfiguration && ["quick-update", "repair"].includes(ctx.action));
|
|
418
|
-
const configuration = preserveReviewedState
|
|
419
|
-
? structuredClone(previousConfiguration)
|
|
420
|
-
: {
|
|
421
|
-
schema: "yaaw.integration-config/v1",
|
|
422
|
-
appliedRevision: adapter.configuration.revision,
|
|
423
|
-
notifiedRevision: adapter.configuration.revision,
|
|
424
|
-
profile: ctx.integrationProfiles?.[integrationId] ?? previousConfiguration?.profile ?? { id: "custom", revision: adapter.configuration.revision },
|
|
425
|
-
settings: normalizedSettings
|
|
426
|
-
};
|
|
279
|
+
const normalizedSettings = adapter.configuration.normalize(settings), preserveReviewedState = Boolean(previousConfiguration && ["quick-update", "repair"].includes(ctx.action)), configuration = preserveReviewedState ? structuredClone(previousConfiguration) : { schema: "yaaw.integration-config/v1", appliedRevision: adapter.configuration.revision, notifiedRevision: adapter.configuration.revision, profile: ctx.integrationProfiles?.[integrationId] ?? previousConfiguration?.profile ?? { id: "custom", revision: adapter.configuration.revision }, settings: normalizedSettings };
|
|
427
280
|
if (ctx.action === "quick-update" && ctx.acknowledgeConfigurationUpdates?.includes(integrationId))
|
|
428
281
|
configuration.notifiedRevision = adapter.configuration.revision;
|
|
429
282
|
configuration.settings = preserveReviewedState ? previousConfiguration.settings : normalizedSettings;
|
|
430
283
|
installationRecord.configuration = configuration;
|
|
431
284
|
installationRecord.runtime = configuration.settings;
|
|
432
|
-
configurationSummaries.push({
|
|
433
|
-
integrationId,
|
|
434
|
-
profile: configuration.profile ? `${configuration.profile.id} r${configuration.profile.revision}` : "custom",
|
|
435
|
-
description: adapter.configuration.describe(configuration.settings)
|
|
436
|
-
});
|
|
285
|
+
configurationSummaries.push({ integrationId, profile: configuration.profile ? `${configuration.profile.id} r${configuration.profile.revision}` : "custom", description: adapter.configuration.describe(configuration.settings) });
|
|
437
286
|
}
|
|
438
287
|
else if (adapter.planRuntime)
|
|
439
288
|
installationRecord.runtime = settings ?? null;
|
|
@@ -447,47 +296,28 @@ export async function buildInstallPlan(ctx, previous) {
|
|
|
447
296
|
desiredFilePaths.add(rel(ctx.projectRoot, op.path));
|
|
448
297
|
await chooseManagedFile({ ctx, previous, path: op.path, owner: op.owner, content: op.content, operations, records: manifest.managedFiles, conflicts, backupStamp });
|
|
449
298
|
}
|
|
450
|
-
else if (op.type === "update-managed-section")
|
|
299
|
+
else if (op.type === "update-managed-section")
|
|
451
300
|
await chooseManagedSection({ ctx, previous, op, sectionRecords: manifest.managedSections, operations, conflicts, backupStamp });
|
|
452
|
-
|
|
453
|
-
else if (op.type === "update-managed-config-keys") {
|
|
301
|
+
else if (op.type === "update-managed-config-keys")
|
|
454
302
|
await chooseManagedConfigKeys({ ctx, previous, op, configRecords: manifest.managedConfigKeys, operations, conflicts, backupStamp });
|
|
455
|
-
}
|
|
456
303
|
}
|
|
457
304
|
}
|
|
458
305
|
if (previous) {
|
|
459
|
-
for (const [pathRel, record] of Object.entries(previous.managedFiles))
|
|
460
|
-
if (!desiredFilePaths.has(pathRel) && record.owner !== "installer:backup")
|
|
306
|
+
for (const [pathRel, record] of Object.entries(previous.managedFiles))
|
|
307
|
+
if (!desiredFilePaths.has(pathRel) && record.owner !== "installer:backup")
|
|
461
308
|
await protectRemoval({ ctx, previous, pathRel, record, operations, conflicts, backupStamp });
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
for (const [sectionId, record] of Object.entries(sections)) {
|
|
466
|
-
if (!manifest.managedSections[pathRel]?.[sectionId]) {
|
|
309
|
+
for (const [pathRel, sections] of Object.entries(previous.managedSections))
|
|
310
|
+
for (const [sectionId, record] of Object.entries(sections))
|
|
311
|
+
if (!manifest.managedSections[pathRel]?.[sectionId])
|
|
467
312
|
await protectSectionRemoval({ ctx, previous, pathRel, sectionId, record, operations, conflicts, backupStamp });
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
313
|
for (const [pathRel, records] of Object.entries(previous.managedConfigKeys ?? {})) {
|
|
472
314
|
const obsolete = Object.fromEntries(Object.entries(records).filter(([key]) => !manifest.managedConfigKeys[pathRel]?.[key]));
|
|
473
|
-
if (Object.keys(obsolete).length)
|
|
315
|
+
if (Object.keys(obsolete).length)
|
|
474
316
|
await protectConfigRemoval({ ctx, pathRel, records: obsolete, operations, conflicts, backupStamp });
|
|
475
|
-
}
|
|
476
317
|
}
|
|
477
318
|
}
|
|
478
319
|
if (conflicts.length)
|
|
479
320
|
throw new ManagedConflictError(conflicts);
|
|
480
|
-
return {
|
|
481
|
-
plan: {
|
|
482
|
-
action: ctx.action,
|
|
483
|
-
projectRoot: ctx.projectRoot,
|
|
484
|
-
operations,
|
|
485
|
-
selectedIntegrations: [...ctx.selectedIntegrations],
|
|
486
|
-
selectedSkills: [...ctx.selectedSkills],
|
|
487
|
-
warnings,
|
|
488
|
-
configurationSummaries
|
|
489
|
-
},
|
|
490
|
-
manifest
|
|
491
|
-
};
|
|
321
|
+
return { plan: { action: ctx.action, projectRoot: ctx.projectRoot, operations, selectedIntegrations: [...ctx.selectedIntegrations], selectedSkills: [...ctx.selectedSkills], warnings, configurationSummaries }, manifest };
|
|
492
322
|
}
|
|
493
323
|
//# sourceMappingURL=plan.js.map
|