@mindfoldhq/trellis 0.6.5 → 0.6.7
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/README.md +1 -1
- package/dist/cli/index.js +1 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/commands/channel/guard.d.ts.map +1 -1
- package/dist/commands/channel/guard.js +7 -2
- package/dist/commands/channel/guard.js.map +1 -1
- package/dist/commands/channel/store/paths.d.ts +14 -0
- package/dist/commands/channel/store/paths.d.ts.map +1 -1
- package/dist/commands/channel/store/paths.js +26 -0
- package/dist/commands/channel/store/paths.js.map +1 -1
- package/dist/commands/channel/supervisor/stdout.d.ts +7 -5
- package/dist/commands/channel/supervisor/stdout.d.ts.map +1 -1
- package/dist/commands/channel/supervisor/stdout.js +65 -18
- package/dist/commands/channel/supervisor/stdout.js.map +1 -1
- package/dist/commands/channel/supervisor.d.ts +13 -0
- package/dist/commands/channel/supervisor.d.ts.map +1 -1
- package/dist/commands/channel/supervisor.js +36 -16
- package/dist/commands/channel/supervisor.js.map +1 -1
- package/dist/commands/init.d.ts +1 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/uninstall.d.ts +9 -0
- package/dist/commands/uninstall.d.ts.map +1 -1
- package/dist/commands/uninstall.js +74 -4
- package/dist/commands/uninstall.js.map +1 -1
- package/dist/commands/update.d.ts +29 -1
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +128 -58
- package/dist/commands/update.js.map +1 -1
- package/dist/configurators/copilot.d.ts +1 -0
- package/dist/configurators/copilot.d.ts.map +1 -1
- package/dist/configurators/copilot.js +4 -1
- package/dist/configurators/copilot.js.map +1 -1
- package/dist/configurators/index.d.ts.map +1 -1
- package/dist/configurators/index.js +7 -1
- package/dist/configurators/index.js.map +1 -1
- package/dist/configurators/omp.d.ts +11 -0
- package/dist/configurators/omp.d.ts.map +1 -0
- package/dist/configurators/omp.js +51 -0
- package/dist/configurators/omp.js.map +1 -0
- package/dist/configurators/shared.d.ts +7 -0
- package/dist/configurators/shared.d.ts.map +1 -1
- package/dist/configurators/shared.js +27 -0
- package/dist/configurators/shared.js.map +1 -1
- package/dist/configurators/zcode.d.ts +3 -3
- package/dist/configurators/zcode.js +12 -12
- package/dist/configurators/zcode.js.map +1 -1
- package/dist/migrations/manifests/0.6.6.json +17 -0
- package/dist/migrations/manifests/0.6.7.json +9 -0
- package/dist/templates/codex/hooks/session-start.py +6 -6
- package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-agents.md +1 -1
- package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-skills-or-commands.md +1 -1
- package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/bundled-skills.md +2 -1
- package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/generated-files.md +2 -2
- package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/agents.md +1 -1
- package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/overview.md +3 -3
- package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/platform-map.md +19 -2
- package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/skills-and-commands.md +1 -1
- package/dist/templates/common/bundled-skills/trellis-session-insight/SKILL.md +1 -1
- package/dist/templates/copilot/copilot-instructions.md +11 -0
- package/dist/templates/copilot/hooks/session-start.py +6 -6
- package/dist/templates/copilot/index.d.ts +6 -1
- package/dist/templates/copilot/index.d.ts.map +1 -1
- package/dist/templates/copilot/index.js +8 -1
- package/dist/templates/copilot/index.js.map +1 -1
- package/dist/templates/omp/agents/trellis-check.md +41 -0
- package/dist/templates/omp/agents/trellis-implement.md +45 -0
- package/dist/templates/omp/agents/trellis-research.md +30 -0
- package/dist/templates/omp/extensions/trellis/index.ts.txt +462 -0
- package/dist/templates/omp/index.d.ts +4 -0
- package/dist/templates/omp/index.d.ts.map +1 -0
- package/dist/templates/omp/index.js +9 -0
- package/dist/templates/omp/index.js.map +1 -0
- package/dist/templates/pi/extensions/trellis/index.ts.txt +47 -21
- package/dist/templates/shared-hooks/inject-workflow-state.py +5 -5
- package/dist/templates/shared-hooks/session-start.py +7 -7
- package/dist/templates/trellis/scripts/add_session.py +65 -17
- package/dist/templates/trellis/scripts/common/cli_adapter.py +36 -1
- package/dist/templates/trellis/scripts/common/config.py +29 -0
- package/dist/templates/trellis/scripts/common/io.py +20 -3
- package/dist/templates/trellis/scripts/common/session_context.py +1 -1
- package/dist/templates/trellis/scripts/common/task_store.py +90 -19
- package/dist/templates/trellis/scripts/common/task_utils.py +22 -0
- package/dist/templates/trellis/scripts/task.py +8 -2
- package/dist/templates/trellis/workflow.md +13 -13
- package/dist/templates/zcode/agents/trellis-research.md +133 -0
- package/dist/templates/zcode/index.d.ts +6 -5
- package/dist/templates/zcode/index.d.ts.map +1 -1
- package/dist/templates/zcode/index.js +6 -5
- package/dist/templates/zcode/index.js.map +1 -1
- package/dist/types/ai-tools.d.ts +3 -3
- package/dist/types/ai-tools.d.ts.map +1 -1
- package/dist/types/ai-tools.js +29 -2
- package/dist/types/ai-tools.js.map +1 -1
- package/dist/utils/atomic-write.d.ts +12 -0
- package/dist/utils/atomic-write.d.ts.map +1 -0
- package/dist/utils/atomic-write.js +30 -0
- package/dist/utils/atomic-write.js.map +1 -0
- package/dist/utils/file-writer.d.ts.map +1 -1
- package/dist/utils/file-writer.js +6 -5
- package/dist/utils/file-writer.js.map +1 -1
- package/dist/utils/registry-config.d.ts.map +1 -1
- package/dist/utils/registry-config.js +3 -2
- package/dist/utils/registry-config.js.map +1 -1
- package/dist/utils/template-fetcher.d.ts.map +1 -1
- package/dist/utils/template-fetcher.js +36 -4
- package/dist/utils/template-fetcher.js.map +1 -1
- package/dist/utils/template-hash.d.ts.map +1 -1
- package/dist/utils/template-hash.js +2 -1
- package/dist/utils/template-hash.js.map +1 -1
- package/dist/utils/uninstall-scrubbers.d.ts +1 -0
- package/dist/utils/uninstall-scrubbers.d.ts.map +1 -1
- package/dist/utils/uninstall-scrubbers.js +19 -0
- package/dist/utils/uninstall-scrubbers.js.map +1 -1
- package/package.json +2 -2
package/dist/commands/update.js
CHANGED
|
@@ -16,14 +16,15 @@ import { getAllScripts, getAllAgents,
|
|
|
16
16
|
// Configuration
|
|
17
17
|
configYamlTemplate, gitignoreTemplate, workflowMdTemplate, } from "../templates/trellis/index.js";
|
|
18
18
|
import { agentsMdContent } from "../templates/markdown/index.js";
|
|
19
|
+
import { COPILOT_INSTRUCTIONS_BLOCK_END, COPILOT_INSTRUCTIONS_BLOCK_START, COPILOT_INSTRUCTIONS_PATH, getCopilotInstructions, } from "../templates/copilot/index.js";
|
|
19
20
|
import { ALL_MANAGED_DIRS, getConfiguredPlatforms, collectPlatformTemplates, isManagedPath, isManagedRootDir, } from "../configurators/index.js";
|
|
20
21
|
import { replacePythonCommandLiterals } from "../configurators/shared.js";
|
|
21
22
|
import { pruneOrphanManifestKeys } from "../utils/manifest-prune.js";
|
|
22
23
|
import { fetchRegistrySpecTemplates, collectDirectoryFiles, removeDirectory, parseRegistrySource, probeRegistryIndex, downloadTemplateById, } from "../utils/template-fetcher.js";
|
|
23
24
|
import { loadSpecRegistryConfig } from "../utils/registry-config.js";
|
|
24
25
|
const CLAUDE_SETTINGS_PATH = ".claude/settings.json";
|
|
25
|
-
const TRELLIS_BLOCK_START = "<!-- TRELLIS:START -->";
|
|
26
|
-
const TRELLIS_BLOCK_END = "<!-- TRELLIS:END -->";
|
|
26
|
+
export const TRELLIS_BLOCK_START = "<!-- TRELLIS:START -->";
|
|
27
|
+
export const TRELLIS_BLOCK_END = "<!-- TRELLIS:END -->";
|
|
27
28
|
const LEGACY_UNTRACKED_AGENTS_MD_BLOCK_HASHES = new Set([
|
|
28
29
|
// v0.5.0-beta.17 and earlier wrote AGENTS.md but did not hash-track it.
|
|
29
30
|
// This hash is the pristine Trellis-managed block before the Subagents
|
|
@@ -40,57 +41,63 @@ const PROTECTED_PATHS = [
|
|
|
40
41
|
`${DIR_NAMES.WORKFLOW}/.developer`,
|
|
41
42
|
`${DIR_NAMES.WORKFLOW}/.current-task`,
|
|
42
43
|
];
|
|
43
|
-
function
|
|
44
|
-
const start = content.indexOf(
|
|
44
|
+
function getManagedBlock(content, startMarker, endMarker) {
|
|
45
|
+
const start = content.indexOf(startMarker);
|
|
45
46
|
if (start === -1) {
|
|
46
47
|
return null;
|
|
47
48
|
}
|
|
48
|
-
const end = content.indexOf(
|
|
49
|
+
const end = content.indexOf(endMarker, start);
|
|
49
50
|
if (end === -1) {
|
|
50
51
|
return null;
|
|
51
52
|
}
|
|
52
|
-
return content.slice(start, end +
|
|
53
|
+
return content.slice(start, end + endMarker.length);
|
|
54
|
+
}
|
|
55
|
+
function getTrellisManagedBlock(content) {
|
|
56
|
+
return getManagedBlock(content, TRELLIS_BLOCK_START, TRELLIS_BLOCK_END);
|
|
53
57
|
}
|
|
54
|
-
function
|
|
55
|
-
const existingStart = existingContent.indexOf(
|
|
58
|
+
function replaceManagedBlock(existingContent, templateContent, startMarker, endMarker) {
|
|
59
|
+
const existingStart = existingContent.indexOf(startMarker);
|
|
56
60
|
if (existingStart === -1) {
|
|
57
61
|
return null;
|
|
58
62
|
}
|
|
59
|
-
const existingEnd = existingContent.indexOf(
|
|
63
|
+
const existingEnd = existingContent.indexOf(endMarker, existingStart);
|
|
60
64
|
if (existingEnd === -1) {
|
|
61
65
|
return null;
|
|
62
66
|
}
|
|
63
|
-
const templateBlock =
|
|
67
|
+
const templateBlock = getManagedBlock(templateContent, startMarker, endMarker);
|
|
64
68
|
if (!templateBlock) {
|
|
65
69
|
return null;
|
|
66
70
|
}
|
|
67
71
|
return (existingContent.slice(0, existingStart) +
|
|
68
72
|
templateBlock +
|
|
69
|
-
existingContent.slice(existingEnd +
|
|
73
|
+
existingContent.slice(existingEnd + endMarker.length));
|
|
70
74
|
}
|
|
71
|
-
function
|
|
72
|
-
const
|
|
73
|
-
if (!fs.existsSync(fullPath)) {
|
|
74
|
-
return agentsMdContent;
|
|
75
|
-
}
|
|
76
|
-
const existingContent = fs.readFileSync(fullPath, "utf-8");
|
|
77
|
-
// Existing file already has TRELLIS:START/END markers — replace just the
|
|
78
|
-
// managed block, preserving everything outside it.
|
|
79
|
-
const replaced = replaceTrellisManagedBlock(existingContent, agentsMdContent);
|
|
75
|
+
function mergeManagedBlockContent(existingContent, templateContent, startMarker, endMarker) {
|
|
76
|
+
const replaced = replaceManagedBlock(existingContent, templateContent, startMarker, endMarker);
|
|
80
77
|
if (replaced !== null) {
|
|
81
78
|
return replaced;
|
|
82
79
|
}
|
|
83
|
-
|
|
84
|
-
// user hand-wrote AGENTS.md without ever running through Trellis). Append
|
|
85
|
-
// the template's managed block at the end so user content is preserved
|
|
86
|
-
// instead of clobbered.
|
|
87
|
-
const templateBlock = getTrellisManagedBlock(agentsMdContent);
|
|
80
|
+
const templateBlock = getManagedBlock(templateContent, startMarker, endMarker);
|
|
88
81
|
if (!templateBlock) {
|
|
89
|
-
return
|
|
82
|
+
return templateContent;
|
|
90
83
|
}
|
|
91
84
|
const trimmed = existingContent.replace(/\s+$/, "");
|
|
92
85
|
return `${trimmed}\n\n${templateBlock}\n`;
|
|
93
86
|
}
|
|
87
|
+
function buildManagedBlockTemplate(cwd, relativePath, templateContent, startMarker, endMarker) {
|
|
88
|
+
const fullPath = path.join(cwd, ...relativePath.split("/"));
|
|
89
|
+
if (!fs.existsSync(fullPath)) {
|
|
90
|
+
return templateContent;
|
|
91
|
+
}
|
|
92
|
+
const existingContent = fs.readFileSync(fullPath, "utf-8");
|
|
93
|
+
return mergeManagedBlockContent(existingContent, templateContent, startMarker, endMarker);
|
|
94
|
+
}
|
|
95
|
+
function buildAgentsMdTemplate(cwd) {
|
|
96
|
+
return buildManagedBlockTemplate(cwd, FILE_NAMES.AGENTS, agentsMdContent, TRELLIS_BLOCK_START, TRELLIS_BLOCK_END);
|
|
97
|
+
}
|
|
98
|
+
function buildCopilotInstructionsTemplate(cwd) {
|
|
99
|
+
return buildManagedBlockTemplate(cwd, COPILOT_INSTRUCTIONS_PATH, getCopilotInstructions(), COPILOT_INSTRUCTIONS_BLOCK_START, COPILOT_INSTRUCTIONS_BLOCK_END);
|
|
100
|
+
}
|
|
94
101
|
function isKnownUntrackedTemplate(relativePath, existingContent) {
|
|
95
102
|
if (relativePath !== FILE_NAMES.AGENTS) {
|
|
96
103
|
return false;
|
|
@@ -101,6 +108,15 @@ function isKnownUntrackedTemplate(relativePath, existingContent) {
|
|
|
101
108
|
}
|
|
102
109
|
return LEGACY_UNTRACKED_AGENTS_MD_BLOCK_HASHES.has(computeHash(managedBlock));
|
|
103
110
|
}
|
|
111
|
+
function isSafeUntrackedCopilotInstructionsMerge(relativePath, existingContent, newContent) {
|
|
112
|
+
if (relativePath !== COPILOT_INSTRUCTIONS_PATH) {
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
if (getManagedBlock(existingContent, COPILOT_INSTRUCTIONS_BLOCK_START, COPILOT_INSTRUCTIONS_BLOCK_END)) {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
return (mergeManagedBlockContent(existingContent, getCopilotInstructions(), COPILOT_INSTRUCTIONS_BLOCK_START, COPILOT_INSTRUCTIONS_BLOCK_END) === newContent);
|
|
119
|
+
}
|
|
104
120
|
/**
|
|
105
121
|
* Check if a path is blocked by PROTECTED_PATHS
|
|
106
122
|
*/
|
|
@@ -557,6 +573,9 @@ bypassUpdateSkip = false) {
|
|
|
557
573
|
for (const [filePath, content] of platformFiles) {
|
|
558
574
|
files.set(filePath, content);
|
|
559
575
|
}
|
|
576
|
+
if (platformId === "copilot") {
|
|
577
|
+
files.set(COPILOT_INSTRUCTIONS_PATH, buildCopilotInstructionsTemplate(cwd));
|
|
578
|
+
}
|
|
560
579
|
}
|
|
561
580
|
}
|
|
562
581
|
preserveExistingClaudeStatusLine(cwd, files);
|
|
@@ -631,7 +650,9 @@ function analyzeChanges(cwd, hashes, templates) {
|
|
|
631
650
|
const currentHash = computeHash(existingContent);
|
|
632
651
|
if ((storedHash && storedHash === currentHash) ||
|
|
633
652
|
(!storedHash &&
|
|
634
|
-
isKnownUntrackedTemplate(relativePath, existingContent))
|
|
653
|
+
isKnownUntrackedTemplate(relativePath, existingContent)) ||
|
|
654
|
+
(!storedHash &&
|
|
655
|
+
isSafeUntrackedCopilotInstructionsMerge(relativePath, existingContent, newContent))) {
|
|
635
656
|
// Either the tracked hash matches, or this is a known pristine template
|
|
636
657
|
// from before the path was hash-tracked. Safe to auto-update.
|
|
637
658
|
change.status = "changed";
|
|
@@ -648,10 +669,11 @@ function analyzeChanges(cwd, hashes, templates) {
|
|
|
648
669
|
}
|
|
649
670
|
return result;
|
|
650
671
|
}
|
|
651
|
-
function
|
|
672
|
+
function collectMissingManagedFileHashes(changes, hashes) {
|
|
652
673
|
const files = new Map();
|
|
674
|
+
const managedFiles = new Set([FILE_NAMES.AGENTS, COPILOT_INSTRUCTIONS_PATH]);
|
|
653
675
|
for (const file of changes.unchangedFiles) {
|
|
654
|
-
if (file.relativePath
|
|
676
|
+
if (managedFiles.has(file.relativePath) && !hashes[file.relativePath]) {
|
|
655
677
|
files.set(file.relativePath, file.newContent);
|
|
656
678
|
}
|
|
657
679
|
}
|
|
@@ -912,6 +934,13 @@ async function getLatestNpmVersion() {
|
|
|
912
934
|
function collectAllFiles(dirPath, cwd = process.cwd()) {
|
|
913
935
|
if (!fs.existsSync(dirPath))
|
|
914
936
|
return [];
|
|
937
|
+
const rootStat = fs.statSync(dirPath);
|
|
938
|
+
if (rootStat.isFile()) {
|
|
939
|
+
return [dirPath];
|
|
940
|
+
}
|
|
941
|
+
if (!rootStat.isDirectory()) {
|
|
942
|
+
return [];
|
|
943
|
+
}
|
|
915
944
|
const files = [];
|
|
916
945
|
const stack = [dirPath];
|
|
917
946
|
while (stack.length > 0) {
|
|
@@ -1000,7 +1029,20 @@ function isFileSafeToReplace(cwd, relativePath, templates) {
|
|
|
1000
1029
|
/**
|
|
1001
1030
|
* Classify migrations based on file state and user modifications
|
|
1002
1031
|
*/
|
|
1003
|
-
|
|
1032
|
+
/**
|
|
1033
|
+
* Whether the manifest records any file under `dirRelativePath` — i.e. whether
|
|
1034
|
+
* Trellis actually created this directory. Used to gate rename-dir migrations:
|
|
1035
|
+
* a directory Trellis never wrote (e.g. a user's own `.windsurf/` editor
|
|
1036
|
+
* config that merely shares a path with a retired Trellis platform dir) must
|
|
1037
|
+
* not be auto-moved.
|
|
1038
|
+
*/
|
|
1039
|
+
export function dirHasManifestEntries(dirRelativePath, hashes) {
|
|
1040
|
+
const prefix = dirRelativePath.endsWith("/")
|
|
1041
|
+
? dirRelativePath
|
|
1042
|
+
: dirRelativePath + "/";
|
|
1043
|
+
return Object.keys(hashes).some((key) => key === dirRelativePath || key.startsWith(prefix));
|
|
1044
|
+
}
|
|
1045
|
+
export function classifyMigrations(migrations, cwd, hashes, templates) {
|
|
1004
1046
|
const result = {
|
|
1005
1047
|
auto: [],
|
|
1006
1048
|
confirm: [],
|
|
@@ -1069,10 +1111,19 @@ function classifyMigrations(migrations, cwd, hashes, templates) {
|
|
|
1069
1111
|
result.conflict.push(item);
|
|
1070
1112
|
}
|
|
1071
1113
|
}
|
|
1072
|
-
else {
|
|
1073
|
-
//
|
|
1114
|
+
else if (dirHasManifestEntries(item.from, hashes)) {
|
|
1115
|
+
// Trellis created this directory (the manifest tracks files under it),
|
|
1116
|
+
// so the rename is ours to make.
|
|
1074
1117
|
result.auto.push(item);
|
|
1075
1118
|
}
|
|
1119
|
+
else {
|
|
1120
|
+
// Target absent and the source has no manifest record: this is very
|
|
1121
|
+
// likely a user-owned directory that merely shares a path with a
|
|
1122
|
+
// retired Trellis platform dir (e.g. a real `.windsurf/` editor
|
|
1123
|
+
// config). Skipping avoids silently moving the user's data out from
|
|
1124
|
+
// under their editor — even under --force, since skip never executes.
|
|
1125
|
+
result.skip.push(item);
|
|
1126
|
+
}
|
|
1076
1127
|
}
|
|
1077
1128
|
else if (item.type === "delete") {
|
|
1078
1129
|
if (isTemplateModified(cwd, item.from, hashes)) {
|
|
@@ -1140,7 +1191,7 @@ function printMigrationSummary(classified) {
|
|
|
1140
1191
|
console.log("");
|
|
1141
1192
|
}
|
|
1142
1193
|
if (classified.skip.length > 0) {
|
|
1143
|
-
console.log(chalk.gray(" ○ Skipping (
|
|
1194
|
+
console.log(chalk.gray(" ○ Skipping (not found, protected, or not Trellis-owned):"));
|
|
1144
1195
|
for (const item of classified.skip.slice(0, 3)) {
|
|
1145
1196
|
console.log(chalk.gray(` ${item.from}`));
|
|
1146
1197
|
}
|
|
@@ -1430,6 +1481,40 @@ function printMigrationResult(result) {
|
|
|
1430
1481
|
console.log(chalk.cyan(`Migration complete: ${parts.join(", ")}`));
|
|
1431
1482
|
}
|
|
1432
1483
|
}
|
|
1484
|
+
/**
|
|
1485
|
+
* One-time 0.2.0 migration: rename `traces-*.md` → `journal-*.md` in every
|
|
1486
|
+
* developer workspace directory.
|
|
1487
|
+
*
|
|
1488
|
+
* Never overwrites an existing `journal-N.md`: a newer session may already
|
|
1489
|
+
* have created it, and `.trellis/workspace/` is excluded from the update
|
|
1490
|
+
* backup (see `BACKUP_EXCLUDE_PATTERNS`), so clobbering it would be
|
|
1491
|
+
* unrecoverable data loss. Conflicting `traces-N.md` files are left in place
|
|
1492
|
+
* and reported instead.
|
|
1493
|
+
*/
|
|
1494
|
+
export function renameTracesToJournal(workspaceDir) {
|
|
1495
|
+
const skipped = [];
|
|
1496
|
+
let renamed = 0;
|
|
1497
|
+
if (!fs.existsSync(workspaceDir))
|
|
1498
|
+
return { renamed, skipped };
|
|
1499
|
+
for (const dev of fs.readdirSync(workspaceDir)) {
|
|
1500
|
+
const devPath = path.join(workspaceDir, dev);
|
|
1501
|
+
if (!fs.statSync(devPath).isDirectory())
|
|
1502
|
+
continue;
|
|
1503
|
+
for (const file of fs.readdirSync(devPath)) {
|
|
1504
|
+
if (!(file.startsWith("traces-") && file.endsWith(".md")))
|
|
1505
|
+
continue;
|
|
1506
|
+
const oldPath = path.join(devPath, file);
|
|
1507
|
+
const newPath = path.join(devPath, file.replace("traces-", "journal-"));
|
|
1508
|
+
if (fs.existsSync(newPath)) {
|
|
1509
|
+
skipped.push(oldPath);
|
|
1510
|
+
continue;
|
|
1511
|
+
}
|
|
1512
|
+
fs.renameSync(oldPath, newPath);
|
|
1513
|
+
renamed++;
|
|
1514
|
+
}
|
|
1515
|
+
}
|
|
1516
|
+
return { renamed, skipped };
|
|
1517
|
+
}
|
|
1433
1518
|
/**
|
|
1434
1519
|
* Main update command
|
|
1435
1520
|
*/
|
|
@@ -1623,7 +1708,7 @@ export async function update(options) {
|
|
|
1623
1708
|
}
|
|
1624
1709
|
// Analyze changes (pass hashes for modification detection)
|
|
1625
1710
|
const changes = analyzeChanges(cwd, hashes, templates);
|
|
1626
|
-
const
|
|
1711
|
+
const missingManagedFileHashes = collectMissingManagedFileHashes(changes, hashes);
|
|
1627
1712
|
// Print summary
|
|
1628
1713
|
printChangeSummary(changes);
|
|
1629
1714
|
// First-time hash tracking hint
|
|
@@ -1646,8 +1731,8 @@ export async function update(options) {
|
|
|
1646
1731
|
changes.changedFiles.length === 0 &&
|
|
1647
1732
|
!hasPendingMigrations &&
|
|
1648
1733
|
!hasSafeDeletes) {
|
|
1649
|
-
if (!options.dryRun &&
|
|
1650
|
-
updateHashes(cwd,
|
|
1734
|
+
if (!options.dryRun && missingManagedFileHashes.size > 0) {
|
|
1735
|
+
updateHashes(cwd, missingManagedFileHashes);
|
|
1651
1736
|
}
|
|
1652
1737
|
if (isSameVersion) {
|
|
1653
1738
|
console.log(chalk.green("✓ Already up to date!"));
|
|
@@ -1743,27 +1828,12 @@ export async function update(options) {
|
|
|
1743
1828
|
// and variable file numbers (traces-1.md, traces-2.md, etc.), so we can't enumerate them
|
|
1744
1829
|
// in the migration manifest. This is a one-time migration for the 0.2.0 naming redesign.
|
|
1745
1830
|
const workspaceDir = path.join(cwd, PATHS.WORKSPACE);
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
continue;
|
|
1753
|
-
const files = fs.readdirSync(devPath);
|
|
1754
|
-
for (const file of files) {
|
|
1755
|
-
if (file.startsWith("traces-") && file.endsWith(".md")) {
|
|
1756
|
-
const oldPath = path.join(devPath, file);
|
|
1757
|
-
const newFile = file.replace("traces-", "journal-");
|
|
1758
|
-
const newPath = path.join(devPath, newFile);
|
|
1759
|
-
fs.renameSync(oldPath, newPath);
|
|
1760
|
-
journalRenamed++;
|
|
1761
|
-
}
|
|
1762
|
-
}
|
|
1763
|
-
}
|
|
1764
|
-
if (journalRenamed > 0) {
|
|
1765
|
-
console.log(chalk.cyan(`Renamed ${journalRenamed} traces file(s) to journal`));
|
|
1766
|
-
}
|
|
1831
|
+
const { renamed: journalRenamed, skipped: journalSkipped } = renameTracesToJournal(workspaceDir);
|
|
1832
|
+
if (journalRenamed > 0) {
|
|
1833
|
+
console.log(chalk.cyan(`Renamed ${journalRenamed} traces file(s) to journal`));
|
|
1834
|
+
}
|
|
1835
|
+
for (const oldPath of journalSkipped) {
|
|
1836
|
+
console.warn(chalk.yellow(`Kept ${path.relative(cwd, oldPath)}: its journal target already exists`));
|
|
1767
1837
|
}
|
|
1768
1838
|
}
|
|
1769
1839
|
// Execute safe-file-delete (after backup, before template writes)
|
|
@@ -1851,7 +1921,7 @@ export async function update(options) {
|
|
|
1851
1921
|
// Update version file
|
|
1852
1922
|
updateVersionFile(cwd);
|
|
1853
1923
|
// Update template hashes for new, auto-updated, and overwritten files
|
|
1854
|
-
const filesToHash = new Map(
|
|
1924
|
+
const filesToHash = new Map(missingManagedFileHashes);
|
|
1855
1925
|
for (const file of changes.newFiles) {
|
|
1856
1926
|
filesToHash.set(file.relativePath, file.newContent);
|
|
1857
1927
|
}
|