@pennixrv/trellis 0.7.1-beta.1 → 0.7.1-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/README.md +10 -7
  2. package/dist/cli/index.d.ts.map +1 -1
  3. package/dist/cli/index.js +6 -4
  4. package/dist/cli/index.js.map +1 -1
  5. package/dist/commands/ablate.d.ts.map +1 -1
  6. package/dist/commands/ablate.js +2 -0
  7. package/dist/commands/ablate.js.map +1 -1
  8. package/dist/commands/backup.d.ts +4 -0
  9. package/dist/commands/backup.d.ts.map +1 -0
  10. package/dist/commands/backup.js +75 -0
  11. package/dist/commands/backup.js.map +1 -0
  12. package/dist/commands/init.d.ts.map +1 -1
  13. package/dist/commands/init.js +687 -676
  14. package/dist/commands/init.js.map +1 -1
  15. package/dist/commands/mem.d.ts.map +1 -1
  16. package/dist/commands/mem.js +49 -7
  17. package/dist/commands/mem.js.map +1 -1
  18. package/dist/commands/task-progress.d.ts +1 -0
  19. package/dist/commands/task-progress.d.ts.map +1 -1
  20. package/dist/commands/task-progress.js +67 -25
  21. package/dist/commands/task-progress.js.map +1 -1
  22. package/dist/commands/teamwork/spawn.d.ts.map +1 -1
  23. package/dist/commands/teamwork/spawn.js +5 -2
  24. package/dist/commands/teamwork/spawn.js.map +1 -1
  25. package/dist/commands/teamwork/teammate-adapters.d.ts +0 -2
  26. package/dist/commands/teamwork/teammate-adapters.d.ts.map +1 -1
  27. package/dist/commands/teamwork/teammate-adapters.js +0 -2
  28. package/dist/commands/teamwork/teammate-adapters.js.map +1 -1
  29. package/dist/commands/teamwork/teammate-launch.d.ts +1 -2
  30. package/dist/commands/teamwork/teammate-launch.d.ts.map +1 -1
  31. package/dist/commands/teamwork/teammate-launch.js +0 -2
  32. package/dist/commands/teamwork/teammate-launch.js.map +1 -1
  33. package/dist/commands/uninstall.d.ts.map +1 -1
  34. package/dist/commands/uninstall.js +92 -84
  35. package/dist/commands/uninstall.js.map +1 -1
  36. package/dist/commands/update.d.ts.map +1 -1
  37. package/dist/commands/update.js +589 -591
  38. package/dist/commands/update.js.map +1 -1
  39. package/dist/commands/workflow.d.ts.map +1 -1
  40. package/dist/commands/workflow.js +94 -89
  41. package/dist/commands/workflow.js.map +1 -1
  42. package/dist/configurators/shared.js +2 -2
  43. package/dist/configurators/shared.js.map +1 -1
  44. package/dist/constants/paths.d.ts +3 -10
  45. package/dist/constants/paths.d.ts.map +1 -1
  46. package/dist/constants/paths.js +4 -13
  47. package/dist/constants/paths.js.map +1 -1
  48. package/dist/migrations/manifests/0.7.1-beta.10.json +9 -0
  49. package/dist/migrations/manifests/0.7.1-beta.2.json +522 -0
  50. package/dist/migrations/manifests/0.7.1-beta.3.json +9 -0
  51. package/dist/migrations/manifests/0.7.1-beta.4.json +9 -0
  52. package/dist/migrations/manifests/0.7.1-beta.5.json +9 -0
  53. package/dist/migrations/manifests/0.7.1-beta.6.json +10 -0
  54. package/dist/migrations/manifests/0.7.1-beta.7.json +8 -0
  55. package/dist/migrations/manifests/0.7.1-beta.8.json +481 -0
  56. package/dist/migrations/manifests/0.7.1-beta.9.json +191 -0
  57. package/dist/templates/claude/hooks/statusline.py +9 -4
  58. package/dist/templates/common/bundled-skills/trellis-decision-space-construction-and-merging/workflow.md +2 -0
  59. package/dist/templates/common/bundled-skills/trellis-goal-exploration-and-requirements/workflow.md +2 -0
  60. package/dist/templates/common/bundled-skills/trellis-meta/SKILL.md +1 -1
  61. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/add-project-local-conventions.md +1 -1
  62. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-context-loading.md +5 -5
  63. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-task-lifecycle.md +3 -2
  64. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/overview.md +1 -1
  65. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/context-injection.md +1 -1
  66. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/task-system.md +8 -2
  67. package/dist/templates/common/bundled-skills/trellis-session-insight/references/cli-quick-reference.md +2 -1
  68. package/dist/templates/common/bundled-skills/trellis-session-insight/references/triggering-patterns.md +2 -2
  69. package/dist/templates/common/bundled-skills/trellis-solution-design-and-convergence/workflow.md +4 -0
  70. package/dist/templates/common/bundled-skills/trellis-spec-bootstrap/references/mcp-setup.md +4 -2
  71. package/dist/templates/common/bundled-skills/trellis-spec-bootstrap/references/spec-task-planning.md +2 -2
  72. package/dist/templates/common/bundled-skills/trellis-teamwork/SKILL.md +7 -2
  73. package/dist/templates/common/bundled-skills/trellis-teamwork/references/coordination-modes.md +3 -1
  74. package/dist/templates/common/bundled-skills/trellis-teamwork/references/teammate-configuration-matrix.md +11 -6
  75. package/dist/templates/common/bundled-skills/trellis-teamwork/references/teammate-processes.md +50 -6
  76. package/dist/templates/common/bundled-skills/trellis-teamwork/references/teamwork-plan-construction.md +49 -9
  77. package/dist/templates/common/commands/start.md +2 -2
  78. package/dist/templates/common/skills/before-dev.md +1 -4
  79. package/dist/templates/common/skills/break-loop.md +7 -18
  80. package/dist/templates/common/skills/check.md +7 -11
  81. package/dist/templates/common/skills/{brainstorm.md → request-intake.md} +5 -3
  82. package/dist/templates/common/skills/update-spec.md +5 -7
  83. package/dist/templates/omp/extensions/trellis/index.ts.txt +1 -1
  84. package/dist/templates/opencode/lib/session-utils.js +301 -209
  85. package/dist/templates/snow/SNOW.md +1 -1
  86. package/dist/templates/trellis/agents/teammate.md +16 -5
  87. package/dist/templates/trellis/index.d.ts +3 -0
  88. package/dist/templates/trellis/index.d.ts.map +1 -1
  89. package/dist/templates/trellis/index.js +6 -0
  90. package/dist/templates/trellis/index.js.map +1 -1
  91. package/dist/templates/trellis/scripts/add_session.py +1 -1
  92. package/dist/templates/trellis/scripts/common/active_task.py +3 -47
  93. package/dist/templates/trellis/scripts/common/paths.py +9 -25
  94. package/dist/templates/trellis/scripts/common/safe_commit.py +8 -8
  95. package/dist/templates/trellis/scripts/common/task_context.py +11 -51
  96. package/dist/templates/trellis/scripts/common/task_continuity.py +53 -45
  97. package/dist/templates/trellis/scripts/common/task_layout.py +80 -0
  98. package/dist/templates/trellis/scripts/common/task_move.py +345 -0
  99. package/dist/templates/trellis/scripts/common/task_store.py +28 -55
  100. package/dist/templates/trellis/scripts/common/task_utils.py +23 -19
  101. package/dist/templates/trellis/scripts/common/task_workflow.py +72 -31
  102. package/dist/templates/trellis/scripts/common/tasks.py +6 -5
  103. package/dist/templates/trellis/scripts/hooks/linear_sync.py +13 -3
  104. package/dist/templates/trellis/scripts/task.py +41 -23
  105. package/dist/templates/trellis/workflow.md +4 -2
  106. package/dist/utils/ablation-store.d.ts +1 -1
  107. package/dist/utils/ablation-store.d.ts.map +1 -1
  108. package/dist/utils/ablation-store.js +58 -24
  109. package/dist/utils/ablation-store.js.map +1 -1
  110. package/dist/utils/asset-backup.d.ts +138 -0
  111. package/dist/utils/asset-backup.d.ts.map +1 -0
  112. package/dist/utils/asset-backup.js +514 -0
  113. package/dist/utils/asset-backup.js.map +1 -0
  114. package/dist/utils/atomic-write.d.ts +1 -1
  115. package/dist/utils/atomic-write.d.ts.map +1 -1
  116. package/dist/utils/atomic-write.js +6 -3
  117. package/dist/utils/atomic-write.js.map +1 -1
  118. package/dist/utils/manifest-prune.d.ts +3 -1
  119. package/dist/utils/manifest-prune.d.ts.map +1 -1
  120. package/dist/utils/manifest-prune.js +7 -3
  121. package/dist/utils/manifest-prune.js.map +1 -1
  122. package/dist/utils/template-hash.d.ts +5 -4
  123. package/dist/utils/template-hash.d.ts.map +1 -1
  124. package/dist/utils/template-hash.js +24 -17
  125. package/dist/utils/template-hash.js.map +1 -1
  126. package/package.json +2 -2
@@ -0,0 +1,514 @@
1
+ import { createHash, randomUUID } from "node:crypto";
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import { z } from "zod";
5
+ import { VERSION } from "../constants/version.js";
6
+ import { ALL_MANAGED_DIRS, getConfiguredPlatforms, } from "../configurators/index.js";
7
+ import { getAllMigrations } from "../migrations/index.js";
8
+ import { loadHashes } from "./template-hash.js";
9
+ import { writeFileAtomic } from "./atomic-write.js";
10
+ import { TRELLIS_BLOCK_START, TRELLIS_BLOCK_END } from "./managed-paths.js";
11
+ import { canonicalProjectRoot, projectKey, fingerprintPath, fingerprintsEqual, getTransactionPaths, loadAblationTransaction, withAblationProjectLock, } from "./ablation-store.js";
12
+ import { validateManagedRelativePath } from "./managed-removal.js";
13
+ const fileSchema = z
14
+ .object({
15
+ kind: z.literal("file"),
16
+ sha256: z.string().regex(/^[a-f0-9]{64}$/),
17
+ size: z.number().int().nonnegative(),
18
+ mode: z.number().int().min(0).max(0o7777),
19
+ })
20
+ .strict();
21
+ const fingerprintSchema = z.union([
22
+ fileSchema,
23
+ z.object({ kind: z.literal("absent") }).strict(),
24
+ ]);
25
+ const entrySchema = z
26
+ .object({
27
+ path: z.string(),
28
+ before: fingerprintSchema,
29
+ after: fingerprintSchema.optional(),
30
+ afterBlock: z.string().optional(),
31
+ })
32
+ .strict();
33
+ const manifestSchema = z
34
+ .object({
35
+ schema: z.literal(1),
36
+ contract: z.literal("status-layout-v1/five-phases-v1"),
37
+ id: z.string(),
38
+ projectRoot: z.string(),
39
+ projectKey: z.string(),
40
+ createdAt: z.string().datetime(),
41
+ version: z.string(),
42
+ sourceVersion: z.string(),
43
+ workflow: z.string(),
44
+ platforms: z.array(z.string()),
45
+ runtime: z.record(z.string(), fingerprintSchema),
46
+ reason: z.enum(["manual", "update", "restore-recovery"]),
47
+ update: z.enum(["pending", "succeeded", "restored", "not-applicable"]),
48
+ entries: z.array(entrySchema),
49
+ restore: z
50
+ .object({
51
+ status: z.enum(["restoring", "complete"]),
52
+ review: z.string(),
53
+ recovery: z.string(),
54
+ entries: z.array(z
55
+ .object({
56
+ path: z.string(),
57
+ current: fingerprintSchema,
58
+ desired: fingerprintSchema,
59
+ })
60
+ .strict()),
61
+ })
62
+ .strict()
63
+ .optional(),
64
+ })
65
+ .strict();
66
+ const BACKUP_ID = /^\.backup-\d{4}-\d{2}-\d{2}T[\d-]+Z-[a-f0-9-]{36}$/;
67
+ const LEGACY_ID = /^\.backup-\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}(?:-\d{3}Z)?$/;
68
+ const META = [".trellis/.version", ".trellis/.template-hashes.json"];
69
+ const RUNTIME = [
70
+ ".trellis/scripts/common/task_layout.py",
71
+ ".trellis/scripts/common/task_workflow.py",
72
+ ];
73
+ const PROTECTED = /(?:^|\/)(?:tasks|spec|workspace|backlog|session-handoffs|sessions|history|logs?|cache|node_modules|worktrees?|agent-traces|\.runtime|\.git|credentials?|secrets?)(?:\/|$)|(?:^|\/)\.backup-|(?:^|\/)\.env(?:\.|$)|(?:^|\/)(?:\.developer|\.task-layout-migration\.json)$/i;
74
+ /** Reject all symlink components, including links that happen to stay in-project. */
75
+ function safePath(root, relative) {
76
+ validateManagedRelativePath(relative);
77
+ root = canonicalProjectRoot(root);
78
+ let cursor = root;
79
+ for (const part of relative.split("/")) {
80
+ cursor = path.join(cursor, part);
81
+ try {
82
+ const stat = fs.lstatSync(cursor);
83
+ if (stat.isSymbolicLink())
84
+ throw new Error(`Symlink in asset path: ${relative}`);
85
+ if (cursor !== path.join(root, relative) && !stat.isDirectory())
86
+ throw new Error(`Invalid asset parent: ${relative}`);
87
+ }
88
+ catch (error) {
89
+ if (error.code !== "ENOENT")
90
+ throw error;
91
+ }
92
+ }
93
+ return cursor;
94
+ }
95
+ function assetPath(relative) {
96
+ validateManagedRelativePath(relative);
97
+ return (!PROTECTED.test(relative) &&
98
+ (relative === "AGENTS.md" ||
99
+ ALL_MANAGED_DIRS.some((dir) => relative.startsWith(`${dir}/`))));
100
+ }
101
+ function current(root, relative) {
102
+ const fp = fingerprintPath(safePath(root, relative));
103
+ if (fp.kind !== "file" && fp.kind !== "absent")
104
+ throw new Error(`Asset must be a regular file: ${relative}`);
105
+ return fp;
106
+ }
107
+ function digest(value) {
108
+ return createHash("sha256").update(JSON.stringify(value)).digest("hex");
109
+ }
110
+ function block(content) {
111
+ const start = content.indexOf(TRELLIS_BLOCK_START);
112
+ const end = content.indexOf(TRELLIS_BLOCK_END);
113
+ if (start < 0 ||
114
+ end < start ||
115
+ content.indexOf(TRELLIS_BLOCK_START, start + 1) >= 0 ||
116
+ content.indexOf(TRELLIS_BLOCK_END, end + 1) >= 0)
117
+ return undefined;
118
+ return content.slice(start, end + TRELLIS_BLOCK_END.length);
119
+ }
120
+ function backupDir(root, id) {
121
+ if (!BACKUP_ID.test(id))
122
+ throw new Error(`Invalid asset backup id: ${id}`);
123
+ return safePath(root, `.trellis/${id}`);
124
+ }
125
+ function save(root, backup) {
126
+ const dir = backupDir(root, backup.id);
127
+ const file = safePath(dir, "manifest.json");
128
+ writeFileAtomic(file, `${JSON.stringify(manifestSchema.parse(backup), null, 2)}\n`, 0o600);
129
+ }
130
+ export function loadAssetBackup(root, id) {
131
+ root = canonicalProjectRoot(root);
132
+ const dir = backupDir(root, id);
133
+ const result = manifestSchema.parse(JSON.parse(fs.readFileSync(safePath(dir, "manifest.json"), "utf-8")));
134
+ if (result.id !== id ||
135
+ result.projectRoot !== root ||
136
+ result.projectKey !== projectKey(root))
137
+ throw new Error("Asset backup belongs to a different project.");
138
+ const paths = new Set();
139
+ for (const entry of result.entries) {
140
+ if (!assetPath(entry.path) || paths.has(entry.path))
141
+ throw new Error(`Invalid or duplicate asset scope: ${entry.path}`);
142
+ paths.add(entry.path);
143
+ const stored = current(dir, `files/${entry.path}`);
144
+ if (!fingerprintsEqual(stored, entry.before))
145
+ throw new Error(`Asset backup integrity failure: ${entry.path}`);
146
+ }
147
+ if (result.restore) {
148
+ if (result.restore.entries.length !== result.entries.length)
149
+ throw new Error("Invalid restore scope.");
150
+ for (const entry of result.restore.entries)
151
+ if (!paths.delete(entry.path))
152
+ throw new Error("Invalid restore path.");
153
+ }
154
+ if (treeSize(dir).files !==
155
+ 1 + result.entries.filter((entry) => entry.before.kind === "file").length)
156
+ throw new Error("Unexpected files in asset backup; retained for inspection.");
157
+ return result;
158
+ }
159
+ export function assetBackupScope(root, extra = []) {
160
+ return [...new Set([...Object.keys(loadHashes(root)), ...META, ...extra])]
161
+ .filter(assetPath)
162
+ .sort();
163
+ }
164
+ /** Caller holds the shared maintenance lock through the associated asset writes. */
165
+ export function createAssetBackup(root, reason = "manual", paths = assetBackupScope(root)) {
166
+ root = canonicalProjectRoot(root);
167
+ const id = `.backup-${new Date().toISOString().replace(/[:.]/g, "-")}-${randomUUID()}`;
168
+ const dir = backupDir(root, id);
169
+ const staging = safePath(root, `.trellis/.backup-preparing-${randomUUID()}`);
170
+ const scope = [...new Set(paths)].sort();
171
+ const entries = scope.map((relative) => {
172
+ if (!assetPath(relative))
173
+ throw new Error(`Protected or unmanaged asset: ${relative}`);
174
+ return { path: relative, before: current(root, relative) };
175
+ });
176
+ fs.mkdirSync(staging, { mode: 0o700 });
177
+ for (const entry of entries) {
178
+ if (entry.before.kind === "absent")
179
+ continue;
180
+ const source = safePath(root, entry.path);
181
+ const target = safePath(staging, `files/${entry.path}`);
182
+ fs.mkdirSync(path.dirname(target), { recursive: true, mode: 0o700 });
183
+ fs.copyFileSync(source, target, fs.constants.COPYFILE_EXCL);
184
+ if (process.platform !== "win32")
185
+ fs.chmodSync(target, entry.before.mode);
186
+ if (!fingerprintsEqual(current(staging, `files/${entry.path}`), entry.before) ||
187
+ !fingerprintsEqual(current(root, entry.path), entry.before))
188
+ throw new Error(`Asset changed during backup: ${entry.path}`);
189
+ }
190
+ const versionFile = safePath(root, ".trellis/.version");
191
+ const workflowFile = safePath(root, ".trellis/workflow.md");
192
+ const backup = {
193
+ schema: 1,
194
+ contract: "status-layout-v1/five-phases-v1",
195
+ id,
196
+ projectRoot: root,
197
+ projectKey: projectKey(root),
198
+ createdAt: new Date().toISOString(),
199
+ version: VERSION,
200
+ sourceVersion: fs.existsSync(versionFile)
201
+ ? fs.readFileSync(versionFile, "utf-8").trim()
202
+ : "unknown",
203
+ workflow: fs.existsSync(workflowFile)
204
+ ? digest(fs.readFileSync(workflowFile))
205
+ : "absent",
206
+ runtime: Object.fromEntries(RUNTIME.map((relative) => [relative, current(root, relative)])),
207
+ platforms: [...getConfiguredPlatforms(root)],
208
+ reason,
209
+ update: reason === "update" ? "pending" : "not-applicable",
210
+ entries,
211
+ };
212
+ fs.writeFileSync(path.join(staging, "manifest.json"), `${JSON.stringify(manifestSchema.parse(backup), null, 2)}\n`, { mode: 0o600, flag: "wx" });
213
+ fs.renameSync(staging, dir);
214
+ return loadAssetBackup(root, id);
215
+ }
216
+ export function bindAssetUpdate(root, id) {
217
+ const backup = loadAssetBackup(root, id);
218
+ for (const entry of backup.entries) {
219
+ entry.after = current(root, entry.path);
220
+ if (entry.path === "AGENTS.md" && entry.after.kind === "file") {
221
+ const managed = block(fs.readFileSync(safePath(root, entry.path), "utf-8"));
222
+ if (managed !== undefined)
223
+ entry.afterBlock = digest(managed);
224
+ }
225
+ }
226
+ backup.update = "succeeded";
227
+ save(root, backup);
228
+ }
229
+ function treeSize(root) {
230
+ const stat = fs.lstatSync(root);
231
+ if (stat.isSymbolicLink())
232
+ throw new Error("Symlink in backup storage.");
233
+ if (stat.isFile())
234
+ return { bytes: stat.size, files: 1 };
235
+ if (!stat.isDirectory())
236
+ throw new Error("Unsupported backup storage object.");
237
+ const total = { bytes: 0, files: 0 };
238
+ for (const name of fs.readdirSync(root)) {
239
+ const size = treeSize(path.join(root, name));
240
+ total.bytes += size.bytes;
241
+ total.files += size.files;
242
+ }
243
+ return total;
244
+ }
245
+ export function listAssetBackups(root) {
246
+ const workflow = safePath(root, ".trellis");
247
+ if (!fs.existsSync(workflow))
248
+ return [];
249
+ const result = [];
250
+ const activeRecovery = new Set();
251
+ for (const id of fs
252
+ .readdirSync(workflow)
253
+ .filter((name) => name.startsWith(".backup-"))
254
+ .sort()) {
255
+ const relative = `.trellis/${id}`;
256
+ const item = {
257
+ id,
258
+ path: relative,
259
+ kind: "protected",
260
+ bytes: 0,
261
+ files: 0,
262
+ fingerprint: "",
263
+ };
264
+ try {
265
+ const location = safePath(root, relative);
266
+ Object.assign(item, treeSize(location));
267
+ item.fingerprint = digest(fingerprintPath(location));
268
+ if (BACKUP_ID.test(id)) {
269
+ const backup = loadAssetBackup(root, id);
270
+ if (backup.restore?.status === "restoring")
271
+ activeRecovery.add(backup.restore.recovery);
272
+ if (backup.update === "pending" ||
273
+ backup.restore?.status === "restoring")
274
+ item.problem =
275
+ "Unresolved update or restore; inspect before cleanup.";
276
+ else
277
+ item.kind = "complete";
278
+ }
279
+ else if (LEGACY_ID.test(id)) {
280
+ const names = fs.readdirSync(location);
281
+ const roots = new Set(ALL_MANAGED_DIRS.map((dir) => dir.split("/")[0]));
282
+ if (!names.length ||
283
+ !names.some((name) => name === ".trellis" || name === "AGENTS.md") ||
284
+ names.some((name) => name !== "AGENTS.md" &&
285
+ name !== ".backup-complete" &&
286
+ !roots.has(name)))
287
+ throw new Error("Unknown legacy backup scope.");
288
+ const marker = path.join(location, ".backup-complete");
289
+ if (fs.existsSync(marker) &&
290
+ !/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(fs.readFileSync(marker, "utf-8").trim()))
291
+ throw new Error("Unknown legacy completion marker.");
292
+ item.kind = "legacy";
293
+ }
294
+ else
295
+ item.problem = "Unknown or incomplete backup; retained.";
296
+ }
297
+ catch (error) {
298
+ item.problem = error instanceof Error ? error.message : String(error);
299
+ }
300
+ result.push(item);
301
+ }
302
+ for (const item of result) {
303
+ if (activeRecovery.has(item.id)) {
304
+ item.kind = "protected";
305
+ item.problem = "Unresolved restore depends on this recovery snapshot.";
306
+ }
307
+ }
308
+ const owned = new Set([
309
+ ...Object.keys(loadHashes(root)),
310
+ ...getAllMigrations().flatMap((item) => [
311
+ item.from,
312
+ ...(item.to ? [item.to] : []),
313
+ ]),
314
+ ]);
315
+ for (const original of owned) {
316
+ if (!assetPath(original))
317
+ continue;
318
+ const relative = `${original}.backup`;
319
+ try {
320
+ const location = safePath(root, relative);
321
+ if (!fs.existsSync(location))
322
+ continue;
323
+ if (!fs.lstatSync(location).isFile())
324
+ throw new Error("Migration sidecar is not a regular file; retained.");
325
+ const size = treeSize(location);
326
+ result.push({
327
+ id: relative,
328
+ path: relative,
329
+ kind: "sidecar",
330
+ ...size,
331
+ fingerprint: digest(fingerprintPath(location)),
332
+ });
333
+ }
334
+ catch (error) {
335
+ result.push({
336
+ id: relative,
337
+ path: relative,
338
+ kind: "protected",
339
+ bytes: 0,
340
+ files: 0,
341
+ fingerprint: "",
342
+ problem: error instanceof Error ? error.message : String(error),
343
+ });
344
+ }
345
+ }
346
+ return result;
347
+ }
348
+ export function assertNoAssetRecovery(root) {
349
+ const active = listAssetBackups(root).filter((item) => item.problem?.startsWith("Unresolved"));
350
+ if (active.length)
351
+ throw new Error(`Unresolved asset recovery: ${active.map((item) => item.id).join(", ")}. Inspect the backup before changing assets.`);
352
+ }
353
+ export function withAssetMaintenance(root, operation, readOnly = false) {
354
+ if (readOnly)
355
+ return operation();
356
+ return withAblationProjectLock(getTransactionPaths(root), () => {
357
+ if (loadAblationTransaction(root))
358
+ throw new Error("An ablation transaction exists; use trellis restore first.");
359
+ assertNoAssetRecovery(root);
360
+ return operation();
361
+ });
362
+ }
363
+ export function pruneAssetBackups(root, options = {}) {
364
+ const inventory = listAssetBackups(root);
365
+ const keep = options.keep ?? 3;
366
+ if (!Number.isSafeInteger(keep) || keep < 3)
367
+ throw new Error("Daily retention requires at least three complete backups; use explicit --all for full cleanup.");
368
+ if (options.includeLegacy && !options.all)
369
+ throw new Error("Legacy cleanup requires --all --include-legacy.");
370
+ const eligible = inventory.filter((item) => item.kind === "complete");
371
+ const selected = options.all
372
+ ? inventory.filter((item) => item.kind === "complete" ||
373
+ (options.includeLegacy &&
374
+ (item.kind === "legacy" || item.kind === "sidecar")))
375
+ : eligible.slice(0, Math.max(0, eligible.length - keep));
376
+ const report = {
377
+ selected,
378
+ protected: inventory.filter((item) => !selected.includes(item)),
379
+ deleted: [],
380
+ failed: [],
381
+ };
382
+ if (!options.yes)
383
+ return report;
384
+ if (loadAblationTransaction(root))
385
+ throw new Error("An ablation transaction exists; cleanup is blocked.");
386
+ for (const item of selected) {
387
+ try {
388
+ const latest = listAssetBackups(root).find((candidate) => candidate.path === item.path);
389
+ if (latest?.kind !== item.kind || latest.fingerprint !== item.fingerprint)
390
+ throw new Error("Backup changed since cleanup preflight.");
391
+ const location = safePath(root, item.path);
392
+ treeSize(location);
393
+ fs.rmSync(location, { recursive: true });
394
+ report.deleted.push(item.path);
395
+ }
396
+ catch (error) {
397
+ report.failed.push({
398
+ path: item.path,
399
+ error: error instanceof Error ? error.message : String(error),
400
+ });
401
+ }
402
+ }
403
+ return report;
404
+ }
405
+ function desiredContent(root, backup, relative) {
406
+ const entry = backup.entries.find((item) => item.path === relative);
407
+ if (!entry || entry.before.kind === "absent")
408
+ return undefined;
409
+ const stored = fs.readFileSync(safePath(backupDir(root, backup.id), `files/${relative}`));
410
+ if (relative !== "AGENTS.md" || current(root, relative).kind === "absent")
411
+ return stored;
412
+ const previous = block(stored.toString("utf-8"));
413
+ const now = fs.readFileSync(safePath(root, relative), "utf-8");
414
+ const active = block(now);
415
+ return previous && active
416
+ ? Buffer.from(now.replace(active, previous))
417
+ : stored;
418
+ }
419
+ export function planAssetRestore(root, id, replaceModified = false) {
420
+ const backup = loadAssetBackup(root, id);
421
+ // Asset rollback cannot roll back task data; require the exact task runtime.
422
+ if (Object.keys(backup.runtime).length !== RUNTIME.length ||
423
+ RUNTIME.some((relative) => {
424
+ const recorded = backup.runtime[relative];
425
+ return (recorded?.kind !== "file" ||
426
+ !fingerprintsEqual(recorded, current(root, relative)));
427
+ }))
428
+ throw new Error("Task layout/phase runtime compatibility cannot be verified; assets were not changed.");
429
+ const entries = backup.entries.map((entry) => {
430
+ const actual = current(root, entry.path);
431
+ const data = desiredContent(root, backup, entry.path);
432
+ const desired = data === undefined
433
+ ? { kind: "absent" }
434
+ : {
435
+ kind: "file",
436
+ sha256: createHash("sha256").update(data).digest("hex"),
437
+ size: data.length,
438
+ mode: entry.before.kind === "file" ? entry.before.mode : 0o644,
439
+ };
440
+ const resumed = backup.restore?.status === "restoring"
441
+ ? backup.restore.entries.find((item) => item.path === entry.path)
442
+ : undefined;
443
+ const mixedMatch = entry.path === "AGENTS.md" &&
444
+ entry.afterBlock !== undefined &&
445
+ actual.kind === "file" &&
446
+ digest(block(fs.readFileSync(safePath(root, entry.path), "utf-8"))) ===
447
+ entry.afterBlock;
448
+ const safe = resumed
449
+ ? fingerprintsEqual(actual, resumed.current) ||
450
+ fingerprintsEqual(actual, resumed.desired)
451
+ : entry.after !== undefined &&
452
+ (fingerprintsEqual(actual, entry.after) || mixedMatch);
453
+ const same = fingerprintsEqual(actual, desired);
454
+ const action = same
455
+ ? "keep"
456
+ : safe || (replaceModified && !resumed)
457
+ ? desired.kind === "absent"
458
+ ? "delete"
459
+ : "write"
460
+ : "conflict";
461
+ return { path: entry.path, current: actual, desired, action };
462
+ });
463
+ return { id, review: digest({ id, replaceModified, entries }), entries };
464
+ }
465
+ export function restoreAssetBackup(root, id, options = {}) {
466
+ const plan = planAssetRestore(root, id, options.replaceModified);
467
+ if (!options.yes)
468
+ return plan;
469
+ if (options.review !== plan.review)
470
+ throw new Error("Restore requires the current preview --review digest; preview again after any change.");
471
+ if (plan.entries.some((entry) => entry.action === "conflict"))
472
+ throw new Error("Restore conflicts remain; no assets changed.");
473
+ const backup = loadAssetBackup(root, id);
474
+ if (!backup.restore || backup.restore.status === "complete") {
475
+ const recovery = createAssetBackup(root, "restore-recovery", backup.entries.map((entry) => entry.path));
476
+ backup.restore = {
477
+ status: "restoring",
478
+ review: plan.review,
479
+ recovery: recovery.id,
480
+ entries: plan.entries.map(({ path: relative, current: actual, desired }) => ({
481
+ path: relative,
482
+ current: actual,
483
+ desired,
484
+ })),
485
+ };
486
+ save(root, backup);
487
+ }
488
+ for (const entry of plan.entries) {
489
+ if (entry.action === "keep")
490
+ continue;
491
+ const target = safePath(root, entry.path);
492
+ if (!fingerprintsEqual(current(root, entry.path), entry.current))
493
+ throw new Error(`Asset changed during restore: ${entry.path}`);
494
+ if (entry.action === "delete")
495
+ fs.unlinkSync(target);
496
+ else {
497
+ const data = desiredContent(root, backup, entry.path);
498
+ if (data === undefined || entry.desired.kind !== "file")
499
+ throw new Error("Missing restore payload.");
500
+ fs.mkdirSync(path.dirname(target), { recursive: true });
501
+ writeFileAtomic(target, data, entry.desired.mode);
502
+ }
503
+ if (!fingerprintsEqual(current(root, entry.path), entry.desired))
504
+ throw new Error(`Restore verification failed: ${entry.path}`);
505
+ }
506
+ if (!backup.restore)
507
+ throw new Error("Missing restore transaction.");
508
+ backup.restore.status = "complete";
509
+ if (backup.update === "pending")
510
+ backup.update = "restored";
511
+ save(root, backup);
512
+ return plan;
513
+ }
514
+ //# sourceMappingURL=asset-backup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asset-backup.js","sourceRoot":"","sources":["../../src/utils/asset-backup.ts"],"names":[],"mappings":"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"}
@@ -8,5 +8,5 @@
8
8
  * On failure the temp file is removed on a best-effort basis and the
9
9
  * original error is re-thrown.
10
10
  */
11
- export declare function writeFileAtomic(filePath: string, data: string | Uint8Array): void;
11
+ export declare function writeFileAtomic(filePath: string, data: string | Uint8Array, mode?: number): void;
12
12
  //# sourceMappingURL=atomic-write.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"atomic-write.d.ts","sourceRoot":"","sources":["../../src/utils/atomic-write.ts"],"names":[],"mappings":"AAGA;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GAAG,UAAU,GACxB,IAAI,CAcN"}
1
+ {"version":3,"file":"atomic-write.d.ts","sourceRoot":"","sources":["../../src/utils/atomic-write.ts"],"names":[],"mappings":"AAIA;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GAAG,UAAU,EACzB,IAAI,CAAC,EAAE,MAAM,GACZ,IAAI,CAmBN"}
@@ -1,5 +1,6 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
+ import { randomUUID } from "node:crypto";
3
4
  /**
4
5
  * Write a file atomically: stream into a temp file in the same directory,
5
6
  * then rename it over the target. A crash, Ctrl-C, or ENOSPC mid-write
@@ -10,11 +11,13 @@ import path from "node:path";
10
11
  * On failure the temp file is removed on a best-effort basis and the
11
12
  * original error is re-thrown.
12
13
  */
13
- export function writeFileAtomic(filePath, data) {
14
+ export function writeFileAtomic(filePath, data, mode) {
14
15
  const dir = path.dirname(filePath);
15
- const tmp = path.join(dir, `.${path.basename(filePath)}.${process.pid}.tmp`);
16
+ const tmp = path.join(dir, `.${path.basename(filePath)}.${process.pid}.${randomUUID()}.tmp`);
16
17
  try {
17
- fs.writeFileSync(tmp, data);
18
+ fs.writeFileSync(tmp, data, { flag: "wx", mode });
19
+ if (mode !== undefined && process.platform !== "win32")
20
+ fs.chmodSync(tmp, mode);
18
21
  fs.renameSync(tmp, filePath);
19
22
  }
20
23
  catch (err) {
@@ -1 +1 @@
1
- {"version":3,"file":"atomic-write.js","sourceRoot":"","sources":["../../src/utils/atomic-write.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B;;;;;;;;;GASG;AACH,MAAM,UAAU,eAAe,CAC7B,QAAgB,EAChB,IAAyB;IAEzB,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnC,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,OAAO,CAAC,GAAG,MAAM,CAAC,CAAC;IAC7E,IAAI,CAAC;QACH,EAAE,CAAC,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC5B,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IAC/B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,CAAC;YACH,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAClC,CAAC;QAAC,MAAM,CAAC;YACP,wDAAwD;QAC1D,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"atomic-write.js","sourceRoot":"","sources":["../../src/utils/atomic-write.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC;;;;;;;;;GASG;AACH,MAAM,UAAU,eAAe,CAC7B,QAAgB,EAChB,IAAyB,EACzB,IAAa;IAEb,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnC,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CACnB,GAAG,EACH,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,OAAO,CAAC,GAAG,IAAI,UAAU,EAAE,MAAM,CACjE,CAAC;IACF,IAAI,CAAC;QACH,EAAE,CAAC,aAAa,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAClD,IAAI,IAAI,KAAK,SAAS,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO;YACpD,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC1B,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IAC/B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,CAAC;YACH,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAClC,CAAC;QAAC,MAAM,CAAC;YACP,wDAAwD;QAC1D,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC"}
@@ -14,7 +14,9 @@
14
14
  * self-correct on the next routine command.
15
15
  *
16
16
  * Rules:
17
- * - `.trellis/*` entries are kept unless an explicitly retired file is missing.
17
+ * - `.trellis/*` entries are kept unless excluded from template tracking
18
+ * (user data, runtime state, caches) or an explicitly retired file is missing.
19
+ * Existing registry-managed spec baselines are retained.
18
20
  * `trellis uninstall` removes
19
21
  * `.trellis/` wholesale via `fs.rmSync(..., { recursive: true })`, so
20
22
  * manifest accuracy there doesn't affect uninstall data-loss. `update`
@@ -1 +1 @@
1
- {"version":3,"file":"manifest-prune.d.ts","sourceRoot":"","sources":["../../src/utils/manifest-prune.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAWH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,WAAW,WAAW;IAC1B,0DAA0D;IAC1D,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,6EAA6E;IAC7E,MAAM,EAAE,cAAc,CAAC;CACxB;AAoDD,MAAM,WAAW,YAAY;IAC3B;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,MAAM,EACX,mBAAmB,EAAE,SAAS,MAAM,EAAE,EACtC,MAAM,EAAE,cAAc,EACtB,OAAO,GAAE,YAAiB,GACzB,WAAW,CA0Cb"}
1
+ {"version":3,"file":"manifest-prune.d.ts","sourceRoot":"","sources":["../../src/utils/manifest-prune.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAWH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,WAAW,WAAW;IAC1B,0DAA0D;IAC1D,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,6EAA6E;IAC7E,MAAM,EAAE,cAAc,CAAC;CACxB;AAoDD,MAAM,WAAW,YAAY;IAC3B;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,MAAM,EACX,mBAAmB,EAAE,SAAS,MAAM,EAAE,EACtC,MAAM,EAAE,cAAc,EACtB,OAAO,GAAE,YAAiB,GACzB,WAAW,CA8Cb"}
@@ -14,7 +14,9 @@
14
14
  * self-correct on the next routine command.
15
15
  *
16
16
  * Rules:
17
- * - `.trellis/*` entries are kept unless an explicitly retired file is missing.
17
+ * - `.trellis/*` entries are kept unless excluded from template tracking
18
+ * (user data, runtime state, caches) or an explicitly retired file is missing.
19
+ * Existing registry-managed spec baselines are retained.
18
20
  * `trellis uninstall` removes
19
21
  * `.trellis/` wholesale via `fs.rmSync(..., { recursive: true })`, so
20
22
  * manifest accuracy there doesn't affect uninstall data-loss. `update`
@@ -36,7 +38,7 @@ import path from "node:path";
36
38
  import { collectPlatformTemplates } from "../configurators/index.js";
37
39
  import { FILE_NAMES } from "../constants/paths.js";
38
40
  import { getAllMigrations } from "../migrations/index.js";
39
- import { saveHashes } from "./template-hash.js";
41
+ import { isRuntimeHashPath, saveHashes, shouldExcludeFromHash } from "./template-hash.js";
40
42
  import { toPosix } from "./posix.js";
41
43
  import { TRELLIS_BLOCK_END, TRELLIS_BLOCK_START } from "./managed-paths.js";
42
44
  /**
@@ -111,7 +113,9 @@ export function pruneOrphanManifestKeys(cwd, configuredPlatforms, hashes, option
111
113
  const key = toPosix(rawKey);
112
114
  // Missing retired files no longer need a modified-file baseline.
113
115
  if (key.startsWith(".trellis/") || key === ".trellis") {
114
- if (retired.has(key) && !fs.existsSync(path.join(cwd, key))) {
116
+ if (isRuntimeHashPath(key) ||
117
+ (shouldExcludeFromHash(key) && !key.startsWith(".trellis/spec/")) ||
118
+ (retired.has(key) && !fs.existsSync(path.join(cwd, key)))) {
115
119
  pruned.push(key);
116
120
  }
117
121
  else {