@bigking67/pi-67 0.10.12 → 0.10.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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.10.13]
|
|
4
|
+
|
|
5
|
+
- Normalizes `settings.json` BOM/CRLF line endings during `update --repair`
|
|
6
|
+
even when the runtime `lastChangelogVersion` marker is already absent,
|
|
7
|
+
clearing Windows Git EOL false-dirty states without changing provider,
|
|
8
|
+
model, theme, or other JSON content.
|
|
9
|
+
|
|
3
10
|
## [0.10.12]
|
|
4
11
|
|
|
5
12
|
- Pins `settings.json` to LF line endings in `.gitattributes` while preserving
|
package/package.json
CHANGED
package/scripts/check.mjs
CHANGED
|
@@ -9,6 +9,7 @@ import { parseCommandOptions, splitGlobalArgs } from "../src/lib/args.mjs";
|
|
|
9
9
|
import { readExtensionRegistry, validateExtensionRegistry } from "../src/lib/extension-registry.mjs";
|
|
10
10
|
import { buildPlanDecisions, classifyGitShort } from "../src/lib/update-plan.mjs";
|
|
11
11
|
import {
|
|
12
|
+
migrateSettingsRuntimeState,
|
|
12
13
|
mergeSettingsRuntimeMarkerIntoState,
|
|
13
14
|
settingsRuntimeMarkerFromObject,
|
|
14
15
|
stripSettingsRuntimeMarkerText,
|
|
@@ -406,6 +407,27 @@ function runSettingsRuntimeStateSelfTests() {
|
|
|
406
407
|
state.runtimeMarkers.lastChangelogVersion.storage === "state.json",
|
|
407
408
|
"settings runtime marker must migrate into state runtimeMarkers",
|
|
408
409
|
);
|
|
410
|
+
const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), "pi67-settings-runtime-state-"));
|
|
411
|
+
const agentDir = path.join(tmpRoot, "agent");
|
|
412
|
+
const stateDir = path.join(tmpRoot, "state");
|
|
413
|
+
fs.mkdirSync(agentDir, { recursive: true });
|
|
414
|
+
fs.writeFileSync(path.join(agentDir, "settings.json"), "{\r\n \"theme\": \"gruvbox-dark\"\r\n}\r\n", "utf8");
|
|
415
|
+
const lineEndingResult = migrateSettingsRuntimeState(
|
|
416
|
+
{ agentDir, repoRoot: agentDir, stateDir },
|
|
417
|
+
{ normalizeSettingsJson: true },
|
|
418
|
+
);
|
|
419
|
+
const normalizedSettings = fs.readFileSync(path.join(agentDir, "settings.json"), "utf8");
|
|
420
|
+
assert(lineEndingResult.markerFound === false, "line-ending normalization must not require runtime marker");
|
|
421
|
+
assert(lineEndingResult.settingsNormalized === true, "CRLF settings.json must be normalized under --normalize");
|
|
422
|
+
assert(
|
|
423
|
+
lineEndingResult.settingsNormalizeReasons.includes("line-endings"),
|
|
424
|
+
"settings normalization must classify CRLF as line-endings",
|
|
425
|
+
);
|
|
426
|
+
assert(
|
|
427
|
+
normalizedSettings === "{\n \"theme\": \"gruvbox-dark\"\n}\n",
|
|
428
|
+
"settings line-ending normalization must preserve JSON content and indentation",
|
|
429
|
+
);
|
|
430
|
+
fs.rmSync(tmpRoot, { recursive: true, force: true });
|
|
409
431
|
}
|
|
410
432
|
|
|
411
433
|
function runUpdatePreflightMigrationSelfTests() {
|
package/src/commands/install.mjs
CHANGED
|
@@ -58,7 +58,7 @@ export async function installCommand(ctx, argv) {
|
|
|
58
58
|
info("Migrated settings.json lastChangelogVersion to ignored state: ~/.pi/pi67/state.json");
|
|
59
59
|
}
|
|
60
60
|
if (runtimeState.settingsNormalized) {
|
|
61
|
-
info("Normalized settings.json
|
|
61
|
+
info("Normalized settings.json runtime marker/line endings.");
|
|
62
62
|
}
|
|
63
63
|
if (runtimeState.gitFilterInstalled) {
|
|
64
64
|
info("Installed local git clean filter for future settings.json runtime markers.");
|
package/src/commands/update.mjs
CHANGED
|
@@ -100,7 +100,7 @@ function reportSettingsRuntimeStateMigration(ctx, options = {}) {
|
|
|
100
100
|
info(`${phase}${dryRun ? "would migrate" : "Migrated"} settings.json lastChangelogVersion to ignored state: ~/.pi/pi67/state.json`);
|
|
101
101
|
}
|
|
102
102
|
if (result.settingsNormalized) {
|
|
103
|
-
info(`${phase}${dryRun ? "would normalize" : "Normalized"} settings.json
|
|
103
|
+
info(`${phase}${dryRun ? "would normalize" : "Normalized"} settings.json runtime marker/line endings.`);
|
|
104
104
|
}
|
|
105
105
|
if (result.gitFilterInstalled) {
|
|
106
106
|
info(`${phase}${dryRun ? "would install" : "Installed"} local git clean filter for future settings.json runtime markers.`);
|
|
@@ -67,6 +67,7 @@ export function migrateSettingsRuntimeState(ctx, options = {}) {
|
|
|
67
67
|
markerValue: "",
|
|
68
68
|
stateWritten: false,
|
|
69
69
|
settingsNormalized: false,
|
|
70
|
+
settingsNormalizeReasons: [],
|
|
70
71
|
gitFilterInstalled: false,
|
|
71
72
|
skipped: [],
|
|
72
73
|
errors: [],
|
|
@@ -75,10 +76,12 @@ export function migrateSettingsRuntimeState(ctx, options = {}) {
|
|
|
75
76
|
if (!fs.existsSync(settingsPath)) {
|
|
76
77
|
result.skipped.push("settings.json missing");
|
|
77
78
|
} else {
|
|
79
|
+
let rawSettingsText = "";
|
|
78
80
|
let settingsText = "";
|
|
79
81
|
let settings = null;
|
|
80
82
|
try {
|
|
81
|
-
|
|
83
|
+
rawSettingsText = fs.readFileSync(settingsPath, "utf8");
|
|
84
|
+
settingsText = rawSettingsText.replace(/^\uFEFF/, "");
|
|
82
85
|
settings = JSON.parse(settingsText);
|
|
83
86
|
} catch (error) {
|
|
84
87
|
result.errors.push(`settings.json is not valid JSON: ${error.message}`);
|
|
@@ -95,14 +98,28 @@ export function migrateSettingsRuntimeState(ctx, options = {}) {
|
|
|
95
98
|
}
|
|
96
99
|
if (normalizeSettingsJson) {
|
|
97
100
|
const normalizedText = stableSettingsJson(stripSettingsRuntimeMarker(settings));
|
|
98
|
-
if (normalizedText !==
|
|
101
|
+
if (normalizedText !== rawSettingsText) {
|
|
99
102
|
if (!dryRun) {
|
|
100
103
|
fs.writeFileSync(settingsPath, normalizedText, "utf8");
|
|
101
104
|
}
|
|
102
105
|
result.settingsNormalized = true;
|
|
106
|
+
result.settingsNormalizeReasons.push("runtime-marker");
|
|
107
|
+
if (normalizeSettingsTextLineEndings(rawSettingsText) !== rawSettingsText) {
|
|
108
|
+
result.settingsNormalizeReasons.push("line-endings");
|
|
109
|
+
}
|
|
103
110
|
}
|
|
104
111
|
}
|
|
105
112
|
} else {
|
|
113
|
+
if (normalizeSettingsJson && settings) {
|
|
114
|
+
const normalizedText = normalizeSettingsTextLineEndings(rawSettingsText);
|
|
115
|
+
if (normalizedText !== rawSettingsText) {
|
|
116
|
+
if (!dryRun) {
|
|
117
|
+
fs.writeFileSync(settingsPath, normalizedText, "utf8");
|
|
118
|
+
}
|
|
119
|
+
result.settingsNormalized = true;
|
|
120
|
+
result.settingsNormalizeReasons.push("line-endings");
|
|
121
|
+
}
|
|
122
|
+
}
|
|
106
123
|
result.skipped.push("settings.json runtime marker absent");
|
|
107
124
|
}
|
|
108
125
|
}
|
|
@@ -117,6 +134,12 @@ export function migrateSettingsRuntimeState(ctx, options = {}) {
|
|
|
117
134
|
return result;
|
|
118
135
|
}
|
|
119
136
|
|
|
137
|
+
export function normalizeSettingsTextLineEndings(text) {
|
|
138
|
+
return String(text || "")
|
|
139
|
+
.replace(/^\uFEFF/, "")
|
|
140
|
+
.replace(/\r\n?/g, "\n");
|
|
141
|
+
}
|
|
142
|
+
|
|
120
143
|
export function installSettingsRuntimeGitFilter(ctx, options = {}) {
|
|
121
144
|
const result = {
|
|
122
145
|
installed: false,
|
|
@@ -51,7 +51,7 @@ function printHuman(result) {
|
|
|
51
51
|
console.log("PASS settings.json runtime marker is already absent");
|
|
52
52
|
}
|
|
53
53
|
if (result.settingsNormalized) {
|
|
54
|
-
console.log("PASS normalized settings.json
|
|
54
|
+
console.log("PASS normalized settings.json runtime marker/line endings");
|
|
55
55
|
}
|
|
56
56
|
if (result.gitFilterInstalled) {
|
|
57
57
|
console.log("PASS installed local git clean filter for settings.json runtime marker");
|