@neocompose/cli 0.38.5 → 0.38.6
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,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.38.6] - 2026-08-29
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- Preserve locally edited nested records when the server deletes their owning
|
|
8
|
+
graph, restore kept records as explicit absent-CAS creates, and accept a
|
|
9
|
+
later server recreation cleanly after local deletion wins.
|
|
10
|
+
- Warn during pull when a conflicted record's retained local base strands
|
|
11
|
+
newly downloaded descendant value rows, before a later push reaches the
|
|
12
|
+
stale-base safety refusal.
|
|
13
|
+
|
|
3
14
|
## [0.38.5] - 2026-08-29
|
|
4
15
|
|
|
5
16
|
### Fixed
|
package/dist/neo.mjs
CHANGED
|
@@ -100786,6 +100786,28 @@ var init_value_base_desync = __esm({
|
|
|
100786
100786
|
});
|
|
100787
100787
|
|
|
100788
100788
|
// src/project-source/workspace-status-core.ts
|
|
100789
|
+
function recordUpsertChange(args) {
|
|
100790
|
+
if (args.base.conflictServerHash === null) {
|
|
100791
|
+
return {
|
|
100792
|
+
kind: "create",
|
|
100793
|
+
recordKind: args.recordKind,
|
|
100794
|
+
recordId: args.recordId,
|
|
100795
|
+
file: args.file,
|
|
100796
|
+
nextData: args.nextData
|
|
100797
|
+
};
|
|
100798
|
+
}
|
|
100799
|
+
const inConflictState = typeof args.base.conflictServerHash === "string";
|
|
100800
|
+
return {
|
|
100801
|
+
kind: "update",
|
|
100802
|
+
recordKind: args.recordKind,
|
|
100803
|
+
recordId: args.recordId,
|
|
100804
|
+
file: args.file,
|
|
100805
|
+
nextData: args.nextData,
|
|
100806
|
+
baseData: inConflictState ? args.base.conflictServerData : args.base.data,
|
|
100807
|
+
baseContentHash: args.base.contentHash,
|
|
100808
|
+
casBaseHash: inConflictState ? args.base.conflictServerHash : args.base.contentHash
|
|
100809
|
+
};
|
|
100810
|
+
}
|
|
100789
100811
|
function listVirtualProjectSourceFilesV4(files) {
|
|
100790
100812
|
const selected = files.filter((file) => {
|
|
100791
100813
|
const kind = neoProjectSourceKind(file.path);
|
|
@@ -101269,16 +101291,15 @@ function computeWorkspaceStatus(workspace, options) {
|
|
|
101269
101291
|
}
|
|
101270
101292
|
const inConflictState = baseState.conflictServerHash !== void 0;
|
|
101271
101293
|
if (!recordsSemanticallyEqual(record3.recordKind, fullData, baseState.data) || inConflictState) {
|
|
101272
|
-
changes.push(
|
|
101273
|
-
|
|
101274
|
-
|
|
101275
|
-
|
|
101276
|
-
|
|
101277
|
-
|
|
101278
|
-
|
|
101279
|
-
|
|
101280
|
-
|
|
101281
|
-
});
|
|
101294
|
+
changes.push(
|
|
101295
|
+
recordUpsertChange({
|
|
101296
|
+
base: baseState,
|
|
101297
|
+
recordKind: record3.recordKind,
|
|
101298
|
+
recordId: record3.recordId,
|
|
101299
|
+
file: record3.file,
|
|
101300
|
+
nextData: fullData
|
|
101301
|
+
})
|
|
101302
|
+
);
|
|
101282
101303
|
}
|
|
101283
101304
|
}
|
|
101284
101305
|
const deletedValueIds = /* @__PURE__ */ new Set();
|
|
@@ -101290,6 +101311,7 @@ function computeWorkspaceStatus(workspace, options) {
|
|
|
101290
101311
|
(error) => error.file === recordFile && isBlockingSchemaSourceError(error)
|
|
101291
101312
|
) || conflictedFiles.includes(recordFile);
|
|
101292
101313
|
if (fileStillBroken) continue;
|
|
101314
|
+
if (recordState.conflictServerHash === null) continue;
|
|
101293
101315
|
if (recordState.recordKind === "value") {
|
|
101294
101316
|
deletedValueIds.add(recordState.recordId);
|
|
101295
101317
|
}
|
|
@@ -101450,16 +101472,15 @@ function computeWorkspaceStatus(workspace, options) {
|
|
|
101450
101472
|
)) {
|
|
101451
101473
|
continue;
|
|
101452
101474
|
}
|
|
101453
|
-
changes.push(
|
|
101454
|
-
|
|
101455
|
-
|
|
101456
|
-
|
|
101457
|
-
|
|
101458
|
-
|
|
101459
|
-
|
|
101460
|
-
|
|
101461
|
-
|
|
101462
|
-
});
|
|
101475
|
+
changes.push(
|
|
101476
|
+
recordUpsertChange({
|
|
101477
|
+
base,
|
|
101478
|
+
recordKind: "project-file",
|
|
101479
|
+
recordId: fileId,
|
|
101480
|
+
file: record3.file,
|
|
101481
|
+
nextData: record3.fullData
|
|
101482
|
+
})
|
|
101483
|
+
);
|
|
101463
101484
|
}
|
|
101464
101485
|
let binaryFiles = [];
|
|
101465
101486
|
let binaryChanges = [];
|
|
@@ -113587,7 +113608,8 @@ ${blockingErrors.map((error) => ` ${error.message}`).join("\n")}`
|
|
|
113587
113608
|
if (serverRecord.deleted) continue;
|
|
113588
113609
|
const baseState = workspace.state.records[key];
|
|
113589
113610
|
const local = localByKey.get(key);
|
|
113590
|
-
|
|
113611
|
+
const acceptedServerDeletionRecreated = baseState?.conflictServerHash === null && local === void 0;
|
|
113612
|
+
if (destructive || baseState === void 0 || acceptedServerDeletionRecreated) {
|
|
113591
113613
|
plans.set(key, {
|
|
113592
113614
|
emitData: serverRecord.data,
|
|
113593
113615
|
serverHash: serverRecord.contentHash,
|
|
@@ -113834,13 +113856,23 @@ async function finishFormat4Pull(args) {
|
|
|
113834
113856
|
(serverResult?.files ?? []).map((file) => [file.path, file])
|
|
113835
113857
|
);
|
|
113836
113858
|
const conflictPaths = /* @__PURE__ */ new Set();
|
|
113859
|
+
const authoredLocalConflictKeysByPath = /* @__PURE__ */ new Map();
|
|
113837
113860
|
for (const key of conflictKeys) {
|
|
113838
|
-
const
|
|
113861
|
+
const localPath = localResult.recordFiles.get(key);
|
|
113862
|
+
const serverPath = serverResult?.recordFiles.get(key);
|
|
113863
|
+
const path = localPath ?? serverPath ?? workspace.state.records[key]?.file;
|
|
113839
113864
|
if (path) conflictPaths.add(path);
|
|
113865
|
+
if (path === void 0 || localPath !== void 0 || serverPath !== void 0) {
|
|
113866
|
+
continue;
|
|
113867
|
+
}
|
|
113868
|
+
const keys = authoredLocalConflictKeysByPath.get(path) ?? [];
|
|
113869
|
+
keys.push(key);
|
|
113870
|
+
authoredLocalConflictKeysByPath.set(path, keys);
|
|
113840
113871
|
}
|
|
113841
113872
|
const emittedPaths = /* @__PURE__ */ new Set([
|
|
113842
113873
|
...localByPath.keys(),
|
|
113843
|
-
...[...conflictPaths].filter((path) => serverByPath.has(path))
|
|
113874
|
+
...[...conflictPaths].filter((path) => serverByPath.has(path)),
|
|
113875
|
+
...authoredLocalConflictKeysByPath.keys()
|
|
113844
113876
|
]);
|
|
113845
113877
|
const rewritePaths = projectSourcePathsRequiringRewriteV4({
|
|
113846
113878
|
destructive,
|
|
@@ -113860,7 +113892,17 @@ async function finishFormat4Pull(args) {
|
|
|
113860
113892
|
const resolveSourcePath = createWorkspaceSourcePathResolver(workspace.root);
|
|
113861
113893
|
let written = 0;
|
|
113862
113894
|
for (const path of emittedPaths) {
|
|
113863
|
-
const
|
|
113895
|
+
const absolute = resolveSourcePath(path);
|
|
113896
|
+
const existing = existsSync8(absolute) ? readFileSync9(absolute, "utf8") : null;
|
|
113897
|
+
const unprojectedConflictKeys = authoredLocalConflictKeysByPath.get(path) ?? [];
|
|
113898
|
+
if (unprojectedConflictKeys.length > 0 && existing === null) {
|
|
113899
|
+
throw new Error(
|
|
113900
|
+
`Cannot preserve deleted-server conflict ${unprojectedConflictKeys.join(
|
|
113901
|
+
", "
|
|
113902
|
+
)}: its prior source file ${JSON.stringify(path)} no longer exists.`
|
|
113903
|
+
);
|
|
113904
|
+
}
|
|
113905
|
+
const local = unprojectedConflictKeys.length > 0 ? existing ?? void 0 : localByPath.get(path)?.content;
|
|
113864
113906
|
const server = serverByPath.get(path)?.content;
|
|
113865
113907
|
const content = conflictPaths.has(path) ? renderConflictFileV4({
|
|
113866
113908
|
localContent: local,
|
|
@@ -113868,9 +113910,7 @@ async function finishFormat4Pull(args) {
|
|
|
113868
113910
|
versionId: workspace.config.versionId
|
|
113869
113911
|
}) : local;
|
|
113870
113912
|
if (content === void 0) continue;
|
|
113871
|
-
const absolute = resolveSourcePath(path);
|
|
113872
113913
|
mkdirSync8(dirname8(absolute), { recursive: true });
|
|
113873
|
-
const existing = existsSync8(absolute) ? readFileSync9(absolute, "utf8") : null;
|
|
113874
113914
|
if (existing !== null && !rewritePaths.has(path)) continue;
|
|
113875
113915
|
if (existing !== content) {
|
|
113876
113916
|
writeFileSync8(absolute, content, "utf8");
|
|
@@ -113892,6 +113932,7 @@ async function finishFormat4Pull(args) {
|
|
|
113892
113932
|
}
|
|
113893
113933
|
}
|
|
113894
113934
|
const records2 = {};
|
|
113935
|
+
const previousRecords = workspace.state.records;
|
|
113895
113936
|
for (const [key, plan] of plans) {
|
|
113896
113937
|
const baseState = workspace.state.records[key];
|
|
113897
113938
|
const serverRecord = document.records.get(key);
|
|
@@ -113934,6 +113975,10 @@ async function finishFormat4Pull(args) {
|
|
|
113934
113975
|
const record3 = records2[key];
|
|
113935
113976
|
if (record3) record3.projectBinary = state;
|
|
113936
113977
|
}
|
|
113978
|
+
const staleConflictTears = conflictCount === 0 ? [] : findNewlyUnanchoredConflictValues({
|
|
113979
|
+
previousRecords,
|
|
113980
|
+
records: records2
|
|
113981
|
+
});
|
|
113937
113982
|
workspace.state.records = records2;
|
|
113938
113983
|
if (nextCursor !== null) {
|
|
113939
113984
|
workspace.state.documentRevisionCursor = mutableCursor(nextCursor);
|
|
@@ -113985,6 +114030,12 @@ async function finishFormat4Pull(args) {
|
|
|
113985
114030
|
'Conflict markers were written into the affected files. Edit them to the desired final state and push \u2014 the push is the resolution. To keep one side everywhere, use "neo resolve --mine" or "neo resolve --theirs".'
|
|
113986
114031
|
);
|
|
113987
114032
|
for (const key of conflictKeys) console.log(` ${sym.fail} ${key}`);
|
|
114033
|
+
for (const tear of staleConflictTears) {
|
|
114034
|
+
const rowLabel = tear.unanchoredValueCount === 1 ? "row" : "rows";
|
|
114035
|
+
warn(
|
|
114036
|
+
`Conflict ${tear.recordKind} "${tear.recordId}" retained a local base that does not anchor ${tear.unanchoredValueCount} newly pulled descendant value ${rowLabel}. Resolve it with "neo resolve --mine" or "neo resolve --theirs" before pushing.`
|
|
114037
|
+
);
|
|
114038
|
+
}
|
|
113988
114039
|
}
|
|
113989
114040
|
if (binaries.conflicted > 0) {
|
|
113990
114041
|
warn(
|
|
@@ -113993,6 +114044,65 @@ async function finishFormat4Pull(args) {
|
|
|
113993
114044
|
for (const path of binaries.conflicts) console.log(` ${sym.fail} ${path}`);
|
|
113994
114045
|
}
|
|
113995
114046
|
}
|
|
114047
|
+
function findNewlyUnanchoredConflictValues(args) {
|
|
114048
|
+
const newlyLandedValueIds = /* @__PURE__ */ new Set();
|
|
114049
|
+
for (const [key, record3] of Object.entries(args.records)) {
|
|
114050
|
+
if (args.previousRecords[key] !== void 0) continue;
|
|
114051
|
+
if (record3.recordKind !== "value") continue;
|
|
114052
|
+
if (record3.file === void 0) continue;
|
|
114053
|
+
if (record3.conflictServerHash !== void 0) continue;
|
|
114054
|
+
newlyLandedValueIds.add(record3.recordId);
|
|
114055
|
+
}
|
|
114056
|
+
if (newlyLandedValueIds.size === 0) return [];
|
|
114057
|
+
const unanchored = new Set(
|
|
114058
|
+
unanchoredValueDeleteIds({
|
|
114059
|
+
records: args.records,
|
|
114060
|
+
deletedValueIds: newlyLandedValueIds
|
|
114061
|
+
})
|
|
114062
|
+
);
|
|
114063
|
+
if (unanchored.size === 0) return [];
|
|
114064
|
+
const tears = [];
|
|
114065
|
+
for (const conflict2 of Object.values(args.records)) {
|
|
114066
|
+
if (typeof conflict2.conflictServerHash !== "string") continue;
|
|
114067
|
+
if (conflict2.file === void 0) continue;
|
|
114068
|
+
const serverAnchored = /* @__PURE__ */ new Set();
|
|
114069
|
+
collectNamedCandidateValues(
|
|
114070
|
+
conflict2.conflictServerData,
|
|
114071
|
+
newlyLandedValueIds,
|
|
114072
|
+
serverAnchored
|
|
114073
|
+
);
|
|
114074
|
+
let unanchoredValueCount = 0;
|
|
114075
|
+
for (const valueId of serverAnchored) {
|
|
114076
|
+
if (!unanchored.has(valueId)) continue;
|
|
114077
|
+
const value = args.records[`value:${valueId}`];
|
|
114078
|
+
if (value?.file !== conflict2.file) continue;
|
|
114079
|
+
unanchoredValueCount += 1;
|
|
114080
|
+
}
|
|
114081
|
+
if (unanchoredValueCount === 0) continue;
|
|
114082
|
+
tears.push({
|
|
114083
|
+
recordKind: conflict2.recordKind,
|
|
114084
|
+
recordId: conflict2.recordId,
|
|
114085
|
+
unanchoredValueCount
|
|
114086
|
+
});
|
|
114087
|
+
}
|
|
114088
|
+
return tears;
|
|
114089
|
+
}
|
|
114090
|
+
function collectNamedCandidateValues(value, candidates, found) {
|
|
114091
|
+
if (typeof value === "string") {
|
|
114092
|
+
if (candidates.has(value)) found.add(value);
|
|
114093
|
+
return;
|
|
114094
|
+
}
|
|
114095
|
+
if (Array.isArray(value)) {
|
|
114096
|
+
for (const element of value) {
|
|
114097
|
+
collectNamedCandidateValues(element, candidates, found);
|
|
114098
|
+
}
|
|
114099
|
+
return;
|
|
114100
|
+
}
|
|
114101
|
+
if (!isObjectRecord2(value)) return;
|
|
114102
|
+
for (const nested of Object.values(value)) {
|
|
114103
|
+
collectNamedCandidateValues(nested, candidates, found);
|
|
114104
|
+
}
|
|
114105
|
+
}
|
|
113996
114106
|
function deltaRequiresSourceProjectionV4(args) {
|
|
113997
114107
|
const mainLocale = workspaceMainLocale(args.workspace.state.records);
|
|
113998
114108
|
for (const key of args.changedRecordKeys) {
|
|
@@ -114185,6 +114295,7 @@ var init_pull = __esm({
|
|
|
114185
114295
|
init_dialogue_sources();
|
|
114186
114296
|
init_static_value_seed_records();
|
|
114187
114297
|
init_static_member_ownership_recovery();
|
|
114298
|
+
init_value_base_desync();
|
|
114188
114299
|
}
|
|
114189
114300
|
});
|
|
114190
114301
|
|
|
@@ -114194,7 +114305,7 @@ __export(init_exports, {
|
|
|
114194
114305
|
runInit: () => runInit
|
|
114195
114306
|
});
|
|
114196
114307
|
import { existsSync as existsSync9, mkdirSync as mkdirSync9, readFileSync as readFileSync10, writeFileSync as writeFileSync9 } from "node:fs";
|
|
114197
|
-
import { join as
|
|
114308
|
+
import { join as join10, resolve as resolve3 } from "node:path";
|
|
114198
114309
|
async function runInit(options) {
|
|
114199
114310
|
let projectId = options.projectId;
|
|
114200
114311
|
let projects = [];
|
|
@@ -114291,8 +114402,8 @@ async function runInit(options) {
|
|
|
114291
114402
|
}) : "neo";
|
|
114292
114403
|
}
|
|
114293
114404
|
const root = resolve3(directory);
|
|
114294
|
-
if (existsSync9(
|
|
114295
|
-
throw new Error(`"${
|
|
114405
|
+
if (existsSync9(join10(root, NEO_CONFIG_FILE))) {
|
|
114406
|
+
throw new Error(`"${join10(root, NEO_CONFIG_FILE)}" already exists.`);
|
|
114296
114407
|
}
|
|
114297
114408
|
mkdirSync9(root, { recursive: true });
|
|
114298
114409
|
ensurePrivateStateIgnored(root);
|
|
@@ -114317,7 +114428,7 @@ async function runInit(options) {
|
|
|
114317
114428
|
});
|
|
114318
114429
|
}
|
|
114319
114430
|
function ensurePrivateStateIgnored(root) {
|
|
114320
|
-
const path =
|
|
114431
|
+
const path = join10(root, ".gitignore");
|
|
114321
114432
|
const existing = existsSync9(path) ? readFileSync10(path, "utf8") : "";
|
|
114322
114433
|
if (existing.split(/\r?\n/u).some((line) => line.trim() === ".neo/" || line.trim() === ".neo")) {
|
|
114323
114434
|
return;
|
|
@@ -115724,7 +115835,7 @@ var init_save_overlay_resolution = __esm({
|
|
|
115724
115835
|
|
|
115725
115836
|
// src/commands/push-body-diagnostics.ts
|
|
115726
115837
|
import { existsSync as existsSync10, readFileSync as readFileSync11 } from "node:fs";
|
|
115727
|
-
import { join as
|
|
115838
|
+
import { join as join11 } from "node:path";
|
|
115728
115839
|
function createNeoScriptBodySourceLocator(workspace, status) {
|
|
115729
115840
|
const textByFile = /* @__PURE__ */ new Map();
|
|
115730
115841
|
return {
|
|
@@ -115746,7 +115857,7 @@ function createNeoScriptBodySourceLocator(workspace, status) {
|
|
|
115746
115857
|
textOf(file) {
|
|
115747
115858
|
const cached = textByFile.get(file);
|
|
115748
115859
|
if (cached !== void 0) return cached;
|
|
115749
|
-
const path =
|
|
115860
|
+
const path = join11(workspace.root, file);
|
|
115750
115861
|
const text = existsSync10(path) ? readFileSync11(path, "utf8") : null;
|
|
115751
115862
|
textByFile.set(file, text);
|
|
115752
115863
|
return text;
|
|
@@ -117550,25 +117661,25 @@ var init_project_source_identity = __esm({
|
|
|
117550
117661
|
import { spawn } from "node:child_process";
|
|
117551
117662
|
import { createHash as createHash9 } from "node:crypto";
|
|
117552
117663
|
import { existsSync as existsSync11, readFileSync as readFileSync13, readdirSync as readdirSync4 } from "node:fs";
|
|
117553
|
-
import { join as
|
|
117664
|
+
import { join as join12, relative as relative4, sep as sep4 } from "node:path";
|
|
117554
117665
|
function fingerprintPushInputs(workspace, options = {}) {
|
|
117555
117666
|
const paths = /* @__PURE__ */ new Set([
|
|
117556
|
-
|
|
117667
|
+
join12(workspace.root, "neo.json"),
|
|
117557
117668
|
...listProjectSourceFilesV4(workspace.root),
|
|
117558
117669
|
...options.includeTests === false ? [] : listProjectTestFilesV1(workspace.root),
|
|
117559
|
-
...workspace.config.unityConfigPath === void 0 ? [] : [
|
|
117670
|
+
...workspace.config.unityConfigPath === void 0 ? [] : [join12(workspace.root, workspace.config.unityConfigPath)]
|
|
117560
117671
|
]);
|
|
117561
117672
|
const visitManaged = (directory) => {
|
|
117562
117673
|
if (!existsSync11(directory)) return;
|
|
117563
117674
|
for (const entry of readdirSync4(directory, { withFileTypes: true })) {
|
|
117564
117675
|
if (entry.isSymbolicLink()) continue;
|
|
117565
|
-
const path =
|
|
117676
|
+
const path = join12(directory, entry.name);
|
|
117566
117677
|
if (entry.isDirectory()) visitManaged(path);
|
|
117567
117678
|
else if (entry.isFile()) paths.add(path);
|
|
117568
117679
|
}
|
|
117569
117680
|
};
|
|
117570
|
-
visitManaged(
|
|
117571
|
-
visitManaged(
|
|
117681
|
+
visitManaged(join12(workspace.root, "Files", "Images"));
|
|
117682
|
+
visitManaged(join12(workspace.root, "Files", "AudioClips"));
|
|
117572
117683
|
const hash = createHash9("sha256");
|
|
117573
117684
|
for (const path of [...paths].sort()) {
|
|
117574
117685
|
const name = relative4(workspace.root, path).split(sep4).join("/");
|
|
@@ -117713,7 +117824,7 @@ var init_push_hook = __esm({
|
|
|
117713
117824
|
});
|
|
117714
117825
|
|
|
117715
117826
|
// src/project-source/project-file-push.ts
|
|
117716
|
-
import { basename as basename2, join as
|
|
117827
|
+
import { basename as basename2, join as join13 } from "node:path";
|
|
117717
117828
|
import { readFileSync as readFileSync14 } from "node:fs";
|
|
117718
117829
|
function ensureProjectFileBinaryChangesV4(args) {
|
|
117719
117830
|
for (const binary of args.binaryChanges) {
|
|
@@ -117759,7 +117870,7 @@ function prepareProjectFilePushesV4(args) {
|
|
|
117759
117870
|
`Project file ${recordId} has upload bytes but its source change has no record data.`
|
|
117760
117871
|
);
|
|
117761
117872
|
}
|
|
117762
|
-
const absolute =
|
|
117873
|
+
const absolute = join13(args.workspace.root, binary.path);
|
|
117763
117874
|
const bytes = new Uint8Array(readFileSync14(absolute));
|
|
117764
117875
|
const digest = sha256Bytes(bytes);
|
|
117765
117876
|
if (binary.localSha256 !== null && digest !== binary.localSha256) {
|
|
@@ -118243,7 +118354,7 @@ import {
|
|
|
118243
118354
|
readFileSync as readFileSync15,
|
|
118244
118355
|
statSync as statSync2
|
|
118245
118356
|
} from "node:fs";
|
|
118246
|
-
import { dirname as dirname9, join as
|
|
118357
|
+
import { dirname as dirname9, join as join14, relative as relative5, sep as sep5 } from "node:path";
|
|
118247
118358
|
function assignPendingIds(changes, authoredValueSeeds, reconstructed3, localInitializerMaterialization) {
|
|
118248
118359
|
const assigned = /* @__PURE__ */ new Map();
|
|
118249
118360
|
const assign = (pendingId2) => {
|
|
@@ -119020,7 +119131,7 @@ async function runPush(workspace, options, preparationOverride) {
|
|
|
119020
119131
|
);
|
|
119021
119132
|
}
|
|
119022
119133
|
if (options.noVerify !== true) {
|
|
119023
|
-
const preparedBuildDir = configuredHook === void 0 ? void 0 :
|
|
119134
|
+
const preparedBuildDir = configuredHook === void 0 ? void 0 : join14(
|
|
119024
119135
|
workspace.root,
|
|
119025
119136
|
".neo",
|
|
119026
119137
|
"test-build",
|
|
@@ -119037,7 +119148,7 @@ async function runPush(workspace, options, preparationOverride) {
|
|
|
119037
119148
|
const documentJson = JSON.stringify(candidate.document);
|
|
119038
119149
|
mkdirSync10(preparedBuildDir, { recursive: true });
|
|
119039
119150
|
writeFileSync10(
|
|
119040
|
-
|
|
119151
|
+
join14(preparedBuildDir, "candidate.json"),
|
|
119041
119152
|
`${JSON.stringify({
|
|
119042
119153
|
version: 1,
|
|
119043
119154
|
projectFingerprint: `sha256:${preparedLocal.source.sourceHash}`,
|
|
@@ -120296,7 +120407,7 @@ function authoredMemberFormsByFile(root, alternates) {
|
|
|
120296
120407
|
for (const alternate of alternates) {
|
|
120297
120408
|
let existing = contents.get(alternate.path);
|
|
120298
120409
|
if (existing === void 0) {
|
|
120299
|
-
const absolute =
|
|
120410
|
+
const absolute = join14(root, alternate.path);
|
|
120300
120411
|
existing = existsSync12(absolute) ? readFileSync15(absolute, "utf8") : null;
|
|
120301
120412
|
contents.set(alternate.path, existing);
|
|
120302
120413
|
}
|
|
@@ -120867,16 +120978,13 @@ function prepareCompleteNeoScriptBodyChanges(workspace, status, schema, options
|
|
|
120867
120978
|
`Cannot include server-derived NeoScript refresh for member "${compiled.id}": its reconstructed working-copy row is missing.`
|
|
120868
120979
|
);
|
|
120869
120980
|
}
|
|
120870
|
-
const cascadeChange = {
|
|
120871
|
-
|
|
120981
|
+
const cascadeChange = recordUpsertChange({
|
|
120982
|
+
base,
|
|
120872
120983
|
recordKind: "member",
|
|
120873
120984
|
recordId: compiled.id,
|
|
120874
120985
|
file: reconstructed3.file,
|
|
120875
|
-
nextData
|
|
120876
|
-
|
|
120877
|
-
baseContentHash: base.contentHash,
|
|
120878
|
-
casBaseHash: base.conflictServerHash ?? base.contentHash
|
|
120879
|
-
};
|
|
120986
|
+
nextData
|
|
120987
|
+
});
|
|
120880
120988
|
status.changes.push(cascadeChange);
|
|
120881
120989
|
changesById.set(compiled.id, cascadeChange);
|
|
120882
120990
|
}
|
|
@@ -120945,16 +121053,13 @@ function prepareNSPropertySetterChanges(workspace, status) {
|
|
|
120945
121053
|
`Cannot cascade removal of NeoScript property setter to override "${memberId}": its working-copy state is missing.`
|
|
120946
121054
|
);
|
|
120947
121055
|
}
|
|
120948
|
-
const cascadeChange = {
|
|
120949
|
-
|
|
121056
|
+
const cascadeChange = recordUpsertChange({
|
|
121057
|
+
base,
|
|
120950
121058
|
recordKind: "member",
|
|
120951
121059
|
recordId: memberId,
|
|
120952
121060
|
file: reconstructed3.file,
|
|
120953
|
-
nextData: next
|
|
120954
|
-
|
|
120955
|
-
baseContentHash: base.contentHash,
|
|
120956
|
-
casBaseHash: base.conflictServerHash ?? base.contentHash
|
|
120957
|
-
};
|
|
121061
|
+
nextData: next
|
|
121062
|
+
});
|
|
120958
121063
|
status.changes.push(cascadeChange);
|
|
120959
121064
|
changesById.set(memberId, cascadeChange);
|
|
120960
121065
|
}
|
|
@@ -121021,16 +121126,13 @@ function prepareNSFunctionBodyChanges(workspace, status) {
|
|
|
121021
121126
|
`Cannot recompile NeoScript function override "${memberId}": its working-copy state is missing.`
|
|
121022
121127
|
);
|
|
121023
121128
|
}
|
|
121024
|
-
const cascadeChange = {
|
|
121025
|
-
|
|
121129
|
+
const cascadeChange = recordUpsertChange({
|
|
121130
|
+
base,
|
|
121026
121131
|
recordKind: "member",
|
|
121027
121132
|
recordId: memberId,
|
|
121028
121133
|
file: reconstructed3.file,
|
|
121029
|
-
nextData: member
|
|
121030
|
-
|
|
121031
|
-
baseContentHash: base.contentHash,
|
|
121032
|
-
casBaseHash: base.conflictServerHash ?? base.contentHash
|
|
121033
|
-
};
|
|
121134
|
+
nextData: member
|
|
121135
|
+
});
|
|
121034
121136
|
status.changes.push(cascadeChange);
|
|
121035
121137
|
changesById.set(memberId, cascadeChange);
|
|
121036
121138
|
}
|
|
@@ -121241,7 +121343,7 @@ var init_registry2 = __esm({
|
|
|
121241
121343
|
PROJECT_SCHEMA_CONTRACT = Object.freeze({
|
|
121242
121344
|
formatVersion: 3,
|
|
121243
121345
|
contractVersion: "3.15",
|
|
121244
|
-
cliVersion: "0.38.
|
|
121346
|
+
cliVersion: "0.38.6",
|
|
121245
121347
|
projectFileUploadBatchSize: 32,
|
|
121246
121348
|
documentRecords: {
|
|
121247
121349
|
member: {
|
|
@@ -122578,7 +122680,7 @@ import {
|
|
|
122578
122680
|
basename as basename3,
|
|
122579
122681
|
dirname as dirname10,
|
|
122580
122682
|
isAbsolute as isAbsolute3,
|
|
122581
|
-
join as
|
|
122683
|
+
join as join15,
|
|
122582
122684
|
relative as relative6,
|
|
122583
122685
|
resolve as resolve4,
|
|
122584
122686
|
sep as sep6
|
|
@@ -122785,7 +122887,7 @@ function preparedHookCandidate(workspace) {
|
|
|
122785
122887
|
);
|
|
122786
122888
|
}
|
|
122787
122889
|
const parsed = JSON.parse(
|
|
122788
|
-
readFileSync16(
|
|
122890
|
+
readFileSync16(join15(directory, "candidate.json"), "utf8")
|
|
122789
122891
|
);
|
|
122790
122892
|
if (!isRecord10(parsed)) {
|
|
122791
122893
|
throw new NeoTestPreparedCandidateError(
|
|
@@ -122842,7 +122944,7 @@ function fingerprintTestCandidateInputs(workspace) {
|
|
|
122842
122944
|
}
|
|
122843
122945
|
function testCandidateCachePath(workspace, inputFingerprint) {
|
|
122844
122946
|
const cacheKey = createHash11("sha256").update(inputFingerprint).digest("hex");
|
|
122845
|
-
return
|
|
122947
|
+
return join15(
|
|
122846
122948
|
workspace.root,
|
|
122847
122949
|
".neo",
|
|
122848
122950
|
"test-build",
|
|
@@ -122867,7 +122969,7 @@ function cachedTestCandidate(workspace, inputFingerprint) {
|
|
|
122867
122969
|
}
|
|
122868
122970
|
if (typeof parsed.documentSha256 !== "string") return null;
|
|
122869
122971
|
const documentJson = readFileSync16(
|
|
122870
|
-
|
|
122972
|
+
join15(dirname10(candidatePath), "document.json"),
|
|
122871
122973
|
"utf8"
|
|
122872
122974
|
);
|
|
122873
122975
|
if (createHash11("sha256").update(documentJson).digest("hex") !== parsed.documentSha256) {
|
|
@@ -122888,7 +122990,7 @@ function cacheTestCandidate(workspace, inputFingerprint, candidate) {
|
|
|
122888
122990
|
const documentJson = JSON.stringify(candidate.document);
|
|
122889
122991
|
const documentSha256 = createHash11("sha256").update(documentJson).digest("hex");
|
|
122890
122992
|
const candidatePath = testCandidateCachePath(workspace, inputFingerprint);
|
|
122891
|
-
atomicWrite(
|
|
122993
|
+
atomicWrite(join15(dirname10(candidatePath), "document.json"), documentJson);
|
|
122892
122994
|
atomicWrite(
|
|
122893
122995
|
candidatePath,
|
|
122894
122996
|
JSON.stringify({
|
|
@@ -122908,7 +123010,7 @@ function compileSpec(workspace, document, absolutePath, projectCompilationHash2)
|
|
|
122908
123010
|
const path = relative6(workspace.root, absolutePath).split(sep6).join("/");
|
|
122909
123011
|
const source = readFileSync16(absolutePath, "utf8");
|
|
122910
123012
|
const sourceHash = createHash11("sha256").update(source).digest("hex");
|
|
122911
|
-
const artifactPath =
|
|
123013
|
+
const artifactPath = join15(
|
|
122912
123014
|
workspace.root,
|
|
122913
123015
|
".neo",
|
|
122914
123016
|
"test-build",
|
|
@@ -123743,7 +123845,7 @@ function testBuildFiles(root) {
|
|
|
123743
123845
|
const visit = (directory) => {
|
|
123744
123846
|
for (const entry of readdirSync5(directory, { withFileTypes: true })) {
|
|
123745
123847
|
if (entry.isSymbolicLink()) continue;
|
|
123746
|
-
const path =
|
|
123848
|
+
const path = join15(directory, entry.name);
|
|
123747
123849
|
if (entry.isDirectory()) visit(path);
|
|
123748
123850
|
else if (entry.isFile()) {
|
|
123749
123851
|
const stats = statSync3(path);
|
|
@@ -123804,7 +123906,7 @@ function formatStatusCounts(passed, failed, total, skipped = 0) {
|
|
|
123804
123906
|
async function runTest(workspace, options, dependencies = {}) {
|
|
123805
123907
|
const started = Date.now();
|
|
123806
123908
|
const performanceStarted = performance.now();
|
|
123807
|
-
const testBuildRoot =
|
|
123909
|
+
const testBuildRoot = join15(workspace.root, ".neo", "test-build");
|
|
123808
123910
|
maintainNeoTestBuildCache(testBuildRoot);
|
|
123809
123911
|
const startedAt = new Date(started).toISOString();
|
|
123810
123912
|
let projectFingerprint = null;
|
|
@@ -123983,7 +124085,7 @@ async function runTest(workspace, options, dependencies = {}) {
|
|
|
123983
124085
|
}))
|
|
123984
124086
|
};
|
|
123985
124087
|
atomicWrite(
|
|
123986
|
-
|
|
124088
|
+
join15(workspace.root, ".neo", "test-build", "v1", "manifest.json"),
|
|
123987
124089
|
`${JSON.stringify(buildManifest, null, 2)}
|
|
123988
124090
|
`
|
|
123989
124091
|
);
|
|
@@ -124072,7 +124174,7 @@ async function runTest(workspace, options, dependencies = {}) {
|
|
|
124072
124174
|
if (options.outputFile !== null) {
|
|
124073
124175
|
try {
|
|
124074
124176
|
atomicWrite(
|
|
124075
|
-
isAbsolute3(options.outputFile) ? options.outputFile :
|
|
124177
|
+
isAbsolute3(options.outputFile) ? options.outputFile : join15(workspace.root, options.outputFile),
|
|
124076
124178
|
serialized
|
|
124077
124179
|
);
|
|
124078
124180
|
} catch (error) {
|
|
@@ -124286,7 +124388,7 @@ import {
|
|
|
124286
124388
|
existsSync as existsSync14,
|
|
124287
124389
|
readFileSync as readFileSync17
|
|
124288
124390
|
} from "node:fs";
|
|
124289
|
-
import { extname as extname2, isAbsolute as isAbsolute4, join as
|
|
124391
|
+
import { extname as extname2, isAbsolute as isAbsolute4, join as join16, relative as relative7, sep as sep7 } from "node:path";
|
|
124290
124392
|
function inspectNeoDoctor(workspace) {
|
|
124291
124393
|
const formatCompatible = workspace.config.formatVersion === CURRENT_FORMAT_VERSION;
|
|
124292
124394
|
const compiler = inspectCompilerContract();
|
|
@@ -124402,7 +124504,7 @@ function inspectSourceContract(workspace) {
|
|
|
124402
124504
|
}
|
|
124403
124505
|
}
|
|
124404
124506
|
function inspectExtensionContract(root) {
|
|
124405
|
-
const cachePath =
|
|
124507
|
+
const cachePath = join16(root, PROJECT_SOURCE_ANALYSIS_V4_CACHE_PATH);
|
|
124406
124508
|
if (!existsSync14(cachePath)) {
|
|
124407
124509
|
return {
|
|
124408
124510
|
id: NEO_VSCODE_EXTENSION_ID,
|
|
@@ -124486,7 +124588,7 @@ function inspectTrackedBinary(root, record3, errors) {
|
|
|
124486
124588
|
`Project file ${record3.recordId} has an invalid SHA-256 base digest.`
|
|
124487
124589
|
);
|
|
124488
124590
|
}
|
|
124489
|
-
const absolute =
|
|
124591
|
+
const absolute = join16(root, path);
|
|
124490
124592
|
if (existsSync14(absolute) && !canAccess(absolute, fsConstants.R_OK)) {
|
|
124491
124593
|
errors.push(`Tracked project file ${path} is not readable.`);
|
|
124492
124594
|
}
|
|
@@ -124629,7 +124731,7 @@ __export(migrate_exports, {
|
|
|
124629
124731
|
});
|
|
124630
124732
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
124631
124733
|
import { existsSync as existsSync15, mkdirSync as mkdirSync12, readdirSync as readdirSync6, writeFileSync as writeFileSync12 } from "node:fs";
|
|
124632
|
-
import { join as
|
|
124734
|
+
import { join as join17 } from "node:path";
|
|
124633
124735
|
async function runMigrate(workspace, subcommand, positional, targetRef, json, dependencies = {}) {
|
|
124634
124736
|
if (subcommand === "new") {
|
|
124635
124737
|
const name = positional[0];
|
|
@@ -124638,7 +124740,7 @@ async function runMigrate(workspace, subcommand, positional, targetRef, json, de
|
|
|
124638
124740
|
"Usage: neo migrate new <name> [--target <ClassName|project>]"
|
|
124639
124741
|
);
|
|
124640
124742
|
}
|
|
124641
|
-
const migrationsDir =
|
|
124743
|
+
const migrationsDir = join17(workspace.root, "Migrations");
|
|
124642
124744
|
mkdirSync12(migrationsDir, { recursive: true });
|
|
124643
124745
|
let nextOrder = 1;
|
|
124644
124746
|
if (existsSync15(migrationsDir)) {
|
|
@@ -124650,7 +124752,7 @@ async function runMigrate(workspace, subcommand, positional, targetRef, json, de
|
|
|
124650
124752
|
}
|
|
124651
124753
|
}
|
|
124652
124754
|
const relPath = migrationFileName(nextOrder, name);
|
|
124653
|
-
const absolute =
|
|
124755
|
+
const absolute = join17(workspace.root, relPath);
|
|
124654
124756
|
if (existsSync15(absolute)) {
|
|
124655
124757
|
throw new Error(`"${relPath}" already exists.`);
|
|
124656
124758
|
}
|
|
@@ -127444,7 +127546,7 @@ __export(export_exports, {
|
|
|
127444
127546
|
runExportUnity: () => runExportUnity
|
|
127445
127547
|
});
|
|
127446
127548
|
import { mkdirSync as mkdirSync13, writeFileSync as writeFileSync13 } from "node:fs";
|
|
127447
|
-
import { join as
|
|
127549
|
+
import { join as join18 } from "node:path";
|
|
127448
127550
|
async function runExportUnity(workspace, outDir) {
|
|
127449
127551
|
if (outDir === null) {
|
|
127450
127552
|
throw new Error(
|
|
@@ -127456,23 +127558,23 @@ async function runExportUnity(workspace, outDir) {
|
|
|
127456
127558
|
`/api/projects/${workspace.config.projectId}/export`,
|
|
127457
127559
|
{ versionId: workspace.config.versionId }
|
|
127458
127560
|
);
|
|
127459
|
-
const resourcesDir =
|
|
127460
|
-
const localizationDir =
|
|
127461
|
-
const scriptsDir =
|
|
127561
|
+
const resourcesDir = join18(outDir, "Resources", "Neo");
|
|
127562
|
+
const localizationDir = join18(resourcesDir, "Localization");
|
|
127563
|
+
const scriptsDir = join18(outDir, "Scripts", "Neo");
|
|
127462
127564
|
mkdirSync13(localizationDir, { recursive: true });
|
|
127463
127565
|
mkdirSync13(scriptsDir, { recursive: true });
|
|
127464
|
-
writeFileSync13(
|
|
127566
|
+
writeFileSync13(join18(resourcesDir, "project.json"), response.projectJson);
|
|
127465
127567
|
writeFileSync13(
|
|
127466
|
-
|
|
127568
|
+
join18(scriptsDir, "NeoGeneratedTypes.cs"),
|
|
127467
127569
|
response.generatedTypes
|
|
127468
127570
|
);
|
|
127469
127571
|
for (const file of response.localizationFiles ?? []) {
|
|
127470
|
-
writeFileSync13(
|
|
127572
|
+
writeFileSync13(join18(localizationDir, file.fileName), file.content);
|
|
127471
127573
|
}
|
|
127472
|
-
console.log(`wrote ${
|
|
127473
|
-
console.log(`wrote ${
|
|
127574
|
+
console.log(`wrote ${join18(resourcesDir, "project.json")}`);
|
|
127575
|
+
console.log(`wrote ${join18(scriptsDir, "NeoGeneratedTypes.cs")}`);
|
|
127474
127576
|
for (const file of response.localizationFiles ?? []) {
|
|
127475
|
-
console.log(`wrote ${
|
|
127577
|
+
console.log(`wrote ${join18(localizationDir, file.fileName)}`);
|
|
127476
127578
|
}
|
|
127477
127579
|
const diagnostics = response.diagnostics ?? [];
|
|
127478
127580
|
for (const diagnostic of diagnostics) {
|
|
@@ -127495,7 +127597,7 @@ __export(dev_exports, {
|
|
|
127495
127597
|
runDev: () => runDev
|
|
127496
127598
|
});
|
|
127497
127599
|
import { watch } from "node:fs";
|
|
127498
|
-
import { join as
|
|
127600
|
+
import { join as join19 } from "node:path";
|
|
127499
127601
|
import { emitKeypressEvents } from "node:readline";
|
|
127500
127602
|
import { ConvexClient } from "convex/browser";
|
|
127501
127603
|
function isSchemaSignal(value) {
|
|
@@ -127605,7 +127707,7 @@ async function runDev(workspace, options) {
|
|
|
127605
127707
|
};
|
|
127606
127708
|
for (const dir of ["Classes", "Enums"]) {
|
|
127607
127709
|
try {
|
|
127608
|
-
watch(
|
|
127710
|
+
watch(join19(workspace.root, dir), { persistent: true }, onFileChange);
|
|
127609
127711
|
} catch {
|
|
127610
127712
|
}
|
|
127611
127713
|
}
|
|
@@ -127661,7 +127763,7 @@ __export(resolve_exports, {
|
|
|
127661
127763
|
workspaceFilePath: () => workspaceFilePath
|
|
127662
127764
|
});
|
|
127663
127765
|
import { readFileSync as readFileSync19, rmSync as rmSync8, writeFileSync as writeFileSync14 } from "node:fs";
|
|
127664
|
-
import { join as
|
|
127766
|
+
import { join as join20 } from "node:path";
|
|
127665
127767
|
function runResolve(workspace, side) {
|
|
127666
127768
|
const resolvedRecords = adoptServerConflictBases(workspace);
|
|
127667
127769
|
let resolvedFiles = 0;
|
|
@@ -127677,12 +127779,12 @@ function runResolve(workspace, side) {
|
|
|
127677
127779
|
const binary = state.projectBinary;
|
|
127678
127780
|
const conflict2 = binary?.conflict;
|
|
127679
127781
|
if (binary === void 0 || conflict2 === void 0) continue;
|
|
127680
|
-
const destination =
|
|
127782
|
+
const destination = join20(workspace.root, binary.path);
|
|
127681
127783
|
if (side === "theirs") {
|
|
127682
127784
|
if (conflict2.remoteSha256 !== null && conflict2.artifactPath !== void 0) {
|
|
127683
127785
|
writeVerifiedBinaryDownloadV4(
|
|
127684
127786
|
destination,
|
|
127685
|
-
readFileSync19(
|
|
127787
|
+
readFileSync19(join20(workspace.root, conflict2.artifactPath)),
|
|
127686
127788
|
conflict2.remoteSha256
|
|
127687
127789
|
);
|
|
127688
127790
|
binary.sha256 = conflict2.remoteSha256;
|
|
@@ -127692,7 +127794,7 @@ function runResolve(workspace, side) {
|
|
|
127692
127794
|
}
|
|
127693
127795
|
}
|
|
127694
127796
|
if (conflict2.artifactPath !== void 0) {
|
|
127695
|
-
rmSync8(
|
|
127797
|
+
rmSync8(join20(workspace.root, conflict2.artifactPath), { force: true });
|
|
127696
127798
|
}
|
|
127697
127799
|
delete binary.conflict;
|
|
127698
127800
|
resolvedBinaries += 1;
|
|
@@ -127761,7 +127863,7 @@ function resolveMarkers(source, side) {
|
|
|
127761
127863
|
return output.join("\n");
|
|
127762
127864
|
}
|
|
127763
127865
|
function workspaceFilePath(workspace, file) {
|
|
127764
|
-
return
|
|
127866
|
+
return join20(workspace.root, file);
|
|
127765
127867
|
}
|
|
127766
127868
|
var init_resolve = __esm({
|
|
127767
127869
|
"src/commands/resolve.ts"() {
|
|
@@ -127966,7 +128068,7 @@ There is no --keep-current: preserving current semantic state defines flatten.
|
|
|
127966
128068
|
async function main() {
|
|
127967
128069
|
const args = parseArgs(process.argv.slice(2));
|
|
127968
128070
|
if (args.command === "--version") {
|
|
127969
|
-
console.log("0.38.
|
|
128071
|
+
console.log("0.38.6");
|
|
127970
128072
|
return;
|
|
127971
128073
|
}
|
|
127972
128074
|
if (args.command === null || args.command === "help" || args.command === "--help" || args.command === "-h") {
|
package/package.json
CHANGED
|
@@ -83,7 +83,7 @@ wrappers.
|
|
|
83
83
|
The marker near the top of `SKILL.md` must exactly match the package version:
|
|
84
84
|
|
|
85
85
|
```html
|
|
86
|
-
<!-- reviewed-through-cli: 0.38.
|
|
86
|
+
<!-- reviewed-through-cli: 0.38.6 -->
|
|
87
87
|
```
|
|
88
88
|
|
|
89
89
|
The quoted version above is checked too, so this instruction cannot go stale
|
|
@@ -94,6 +94,13 @@ rows its own file projection holds, so the plan would delete live server rows.
|
|
|
94
94
|
Nothing is planned in that state; run `neo pull` and retry. The same message
|
|
95
95
|
as a warning reports the inconsistency without blocking.
|
|
96
96
|
|
|
97
|
+
When pull conflicts with a server-side deletion, keeping the authored record
|
|
98
|
+
restores it as an explicit create guarded by an absent-record CAS check;
|
|
99
|
+
removing it from the resolved source accepts the deletion without sending a
|
|
100
|
+
write. Pull also warns immediately when a conflicted record's retained local
|
|
101
|
+
base strands newly downloaded descendant value rows. Resolve that conflict
|
|
102
|
+
with `neo resolve --mine` or `neo resolve --theirs` before pushing.
|
|
103
|
+
|
|
97
104
|
For `base-hash-conflict`, pull and merge. For `version-bump-required`, inspect
|
|
98
105
|
the classification and use `neo push --accept-bump` only when the bump is
|
|
99
106
|
intended.
|