@neocompose/cli 0.81.3 → 0.81.4
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 +15 -0
- package/dist/neo.mjs +216 -47
- package/dist/test-worker.mjs +48 -3
- package/package.json +1 -1
- package/skills/neocompose-cli/SKILL.md +5 -1
- package/skills/neocompose-cli/references/cli-development.md +1 -1
- package/skills/neocompose-cli/references/commands-and-sync.md +19 -0
- package/skills/neocompose-cli/references/values-identities-and-references.md +18 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.81.4
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 7ed5870: Reject values on boolean flags so `push --dry-run=true` cannot silently perform a real commit. Use bare switches such as `--dry-run` and `--help`.
|
|
8
|
+
- 887fb8c: Reject unused branch flags and unsupported dry-run requests before command execution, so branch creation and other mutating commands cannot silently ignore a requested preview.
|
|
9
|
+
- 6631cef: Refuse initialization into a nonempty directory, apart from Git metadata, so init cannot overwrite existing source or managed files without consent.
|
|
10
|
+
- b2a688d: Resolve source conflicts with CRLF or mixed line endings while preserving the selected source bytes and formatting.
|
|
11
|
+
- 743783d: Refuse branch switches with unpushed changes, conflicts, invalid source, or pending push recovery so switching cannot silently discard local work.
|
|
12
|
+
- b0b945f: Report constructor parameter errors at their source location instead of crashing
|
|
13
|
+
with an internal missing-constructor manifest error during status or push.
|
|
14
|
+
- c11209a: Fix lookup initializers losing row identities in projected selection sets.
|
|
15
|
+
Accept Reference(value) for evaluated class values, including collection
|
|
16
|
+
callbacks, while preserving type checking and the original value identity.
|
|
17
|
+
|
|
3
18
|
## 0.81.3
|
|
4
19
|
|
|
5
20
|
### Patch Changes
|
package/dist/neo.mjs
CHANGED
|
@@ -19229,6 +19229,11 @@ function parseArgs(argv) {
|
|
|
19229
19229
|
const equals = arg.indexOf("=");
|
|
19230
19230
|
const name = arg.slice(2, equals < 0 ? void 0 : equals);
|
|
19231
19231
|
if (equals >= 0) {
|
|
19232
|
+
if (BOOLEAN_FLAGS.has(name)) {
|
|
19233
|
+
throw new NeoCliUsageError(
|
|
19234
|
+
`--${name} does not accept a value. Pass --${name} to enable it, or omit the flag.`
|
|
19235
|
+
);
|
|
19236
|
+
}
|
|
19232
19237
|
flags.set(name, arg.slice(equals + 1));
|
|
19233
19238
|
continue;
|
|
19234
19239
|
}
|
|
@@ -19283,6 +19288,38 @@ function assertAllowedFlags(args, allowed) {
|
|
|
19283
19288
|
);
|
|
19284
19289
|
}
|
|
19285
19290
|
}
|
|
19291
|
+
function assertCommandFlags(args) {
|
|
19292
|
+
const subcommand = args.positional[0];
|
|
19293
|
+
if (args.command === "branch") {
|
|
19294
|
+
const allowed = /* @__PURE__ */ new Set(["api"]);
|
|
19295
|
+
if (subcommand === "list") {
|
|
19296
|
+
allowed.add("json");
|
|
19297
|
+
allowed.add("all");
|
|
19298
|
+
}
|
|
19299
|
+
if (subcommand === "create") allowed.add("from");
|
|
19300
|
+
if (subcommand === "refresh") allowed.add("dry-run");
|
|
19301
|
+
assertAllowedFlags(args, allowed);
|
|
19302
|
+
}
|
|
19303
|
+
if (!args.flags.has("dry-run")) return;
|
|
19304
|
+
switch (args.command) {
|
|
19305
|
+
case "push":
|
|
19306
|
+
case "merge":
|
|
19307
|
+
case "refresh":
|
|
19308
|
+
return;
|
|
19309
|
+
case "branch":
|
|
19310
|
+
if (subcommand === "refresh") return;
|
|
19311
|
+
break;
|
|
19312
|
+
case "release":
|
|
19313
|
+
if (subcommand === "cut") return;
|
|
19314
|
+
break;
|
|
19315
|
+
case "migrate":
|
|
19316
|
+
if (subcommand === "run") return;
|
|
19317
|
+
break;
|
|
19318
|
+
}
|
|
19319
|
+
throw new NeoCliUsageError(
|
|
19320
|
+
`Flag "--dry-run" is not supported by neo ${args.command}${subcommand === void 0 ? "" : ` ${subcommand}`}. No changes were made.`
|
|
19321
|
+
);
|
|
19322
|
+
}
|
|
19286
19323
|
var NeoCliUsageError, BOOLEAN_FLAGS, KNOWN_FLAGS, TEST_ONLY_FLAGS;
|
|
19287
19324
|
var init_args = __esm({
|
|
19288
19325
|
"src/args.ts"() {
|
|
@@ -33735,7 +33772,48 @@ var init_strict_resolver = __esm({
|
|
|
33735
33772
|
);
|
|
33736
33773
|
case "call": {
|
|
33737
33774
|
const receiverValue = this.callReceiver(expression.callee, scope);
|
|
33738
|
-
if (expression.callee.kind === "ident" && expression.callee.name === "Reference"
|
|
33775
|
+
if (expression.callee.kind === "ident" && expression.callee.name === "Reference") {
|
|
33776
|
+
if (expression.args.length === 1 && expression.argumentNames?.[0] == null) {
|
|
33777
|
+
if ((expression.typeArguments?.length ?? 0) > 1) {
|
|
33778
|
+
throw new CompileError(
|
|
33779
|
+
"Reference accepts at most one generic target type.",
|
|
33780
|
+
expression.pos
|
|
33781
|
+
);
|
|
33782
|
+
}
|
|
33783
|
+
const explicit = expression.typeArguments?.[0];
|
|
33784
|
+
const targetType = explicit === void 0 ? void 0 : this.resolveType(explicit);
|
|
33785
|
+
const target = this.resolveExpression(
|
|
33786
|
+
expression.args[0],
|
|
33787
|
+
scope,
|
|
33788
|
+
targetType
|
|
33789
|
+
);
|
|
33790
|
+
const type = targetType ?? target.type;
|
|
33791
|
+
if (type.kind !== "typeParameter" && !(type.kind === "named" && this.project.typeById.get(type.typeId)?.kind === "class")) {
|
|
33792
|
+
throw new CompileError(
|
|
33793
|
+
"Reference(value) requires a class value.",
|
|
33794
|
+
expression.pos
|
|
33795
|
+
);
|
|
33796
|
+
}
|
|
33797
|
+
if (!isNeoScriptTypeAssignable(target.type, type, this.project)) {
|
|
33798
|
+
throw new CompileError(
|
|
33799
|
+
`Reference target ${this.describe(target.type)} is not assignable to ${this.describe(type)}.`,
|
|
33800
|
+
expression.pos
|
|
33801
|
+
);
|
|
33802
|
+
}
|
|
33803
|
+
if (expected !== void 0 && !isNeoScriptTypeAssignable(type, expected, this.project)) {
|
|
33804
|
+
throw new CompileError(
|
|
33805
|
+
`Reference target ${this.describe(type)} is not assignable to ${this.describe(expected)}.`,
|
|
33806
|
+
expression.pos
|
|
33807
|
+
);
|
|
33808
|
+
}
|
|
33809
|
+
return { ...target, type };
|
|
33810
|
+
}
|
|
33811
|
+
if (expression.typeArguments === void 0) {
|
|
33812
|
+
throw new CompileError(
|
|
33813
|
+
'Reference requires one class value, or Reference<T>(id: "...").',
|
|
33814
|
+
expression.pos
|
|
33815
|
+
);
|
|
33816
|
+
}
|
|
33739
33817
|
const [referenceTypeArgument] = expression.typeArguments;
|
|
33740
33818
|
if (expression.typeArguments.length !== 1 || referenceTypeArgument === void 0) {
|
|
33741
33819
|
throw new CompileError(
|
|
@@ -45719,6 +45797,7 @@ function validateExpression(expression, expected, scope, environment, uri, range
|
|
|
45719
45797
|
validateReferenceExpression(
|
|
45720
45798
|
expression,
|
|
45721
45799
|
expected,
|
|
45800
|
+
scope,
|
|
45722
45801
|
environment,
|
|
45723
45802
|
uri,
|
|
45724
45803
|
range2,
|
|
@@ -46496,7 +46575,10 @@ function inferExpressionType(expression, scope, environment) {
|
|
|
46496
46575
|
const explicit = expression.typeArguments?.[0];
|
|
46497
46576
|
if (explicit) return semanticAstType(explicit);
|
|
46498
46577
|
const target = expression.args[0] ? referenceTargetPath(expression.args[0]) : null;
|
|
46499
|
-
|
|
46578
|
+
const symbolType = target ? environment.referenceTargets.get(target)?.type : void 0;
|
|
46579
|
+
if (symbolType !== void 0) return symbolType;
|
|
46580
|
+
const argument2 = expression.args[0];
|
|
46581
|
+
return argument2 === void 0 ? void 0 : inferExpressionType(argument2, scope, environment);
|
|
46500
46582
|
}
|
|
46501
46583
|
return environment.functions.get(expression.callee.name)?.[0]?.returnType;
|
|
46502
46584
|
}
|
|
@@ -46544,7 +46626,7 @@ function subscriptKeyType(receiver) {
|
|
|
46544
46626
|
if (receiver?.name === "List") return primitiveType("int");
|
|
46545
46627
|
return void 0;
|
|
46546
46628
|
}
|
|
46547
|
-
function validateReferenceExpression(expression, declared, environment, uri, range2, diagnostics) {
|
|
46629
|
+
function validateReferenceExpression(expression, declared, scope, environment, uri, range2, diagnostics) {
|
|
46548
46630
|
const expected = declared?.name === "NeoDialogueReference" ? { ...declared, name: "NeoDialogue" } : declared;
|
|
46549
46631
|
const typeArguments = expression.typeArguments ?? [];
|
|
46550
46632
|
const names = expression.argumentNames ?? [];
|
|
@@ -46632,6 +46714,7 @@ function validateReferenceExpression(expression, declared, environment, uri, ran
|
|
|
46632
46714
|
if (path !== null && path.startsWith("root.")) return;
|
|
46633
46715
|
const target = path ? environment.referenceTargets.get(path) : void 0;
|
|
46634
46716
|
if (!target) {
|
|
46717
|
+
if (path === null || scope.has(path.split(".")[0])) return;
|
|
46635
46718
|
malformed(
|
|
46636
46719
|
"Reference target must be a local value, stored static value, or dialogue class symbol."
|
|
46637
46720
|
);
|
|
@@ -54564,7 +54647,7 @@ var init_registry = __esm({
|
|
|
54564
54647
|
"../packages/manifest/schema-contract/registry.mjs"() {
|
|
54565
54648
|
"use strict";
|
|
54566
54649
|
PROJECT_SCHEMA_CONTRACT = Object.freeze({
|
|
54567
|
-
cliVersion: "0.81.
|
|
54650
|
+
cliVersion: "0.81.4",
|
|
54568
54651
|
projectFileUploadBatchSize: 32,
|
|
54569
54652
|
documentRecords: {
|
|
54570
54653
|
member: {
|
|
@@ -93948,6 +94031,7 @@ function evaluateMemberInitializer(args) {
|
|
|
93948
94031
|
__constructedFieldSchemaKeysByValue: /* @__PURE__ */ new WeakMap(),
|
|
93949
94032
|
__createdStorageKeyDeclarations: args.storageKeyDeclarations ?? /* @__PURE__ */ new Map()
|
|
93950
94033
|
};
|
|
94034
|
+
let evaluatedContext = ctx;
|
|
93951
94035
|
const result = (() => {
|
|
93952
94036
|
try {
|
|
93953
94037
|
return evaluateNSGetterWithEffects(
|
|
@@ -93956,6 +94040,9 @@ function evaluateMemberInitializer(args) {
|
|
|
93956
94040
|
args.argumentValues ?? [],
|
|
93957
94041
|
{
|
|
93958
94042
|
exportInitializerValues: true,
|
|
94043
|
+
inspectResult: (_value, runtimeContext) => {
|
|
94044
|
+
evaluatedContext = runtimeContext;
|
|
94045
|
+
},
|
|
93959
94046
|
// Seeded rows already hold their placement.
|
|
93960
94047
|
...args.sessionValues === void 0 ? {
|
|
93961
94048
|
initializerResult: {
|
|
@@ -93981,7 +94068,7 @@ function evaluateMemberInitializer(args) {
|
|
|
93981
94068
|
args.member,
|
|
93982
94069
|
result.value,
|
|
93983
94070
|
created,
|
|
93984
|
-
|
|
94071
|
+
evaluatedContext
|
|
93985
94072
|
);
|
|
93986
94073
|
}
|
|
93987
94074
|
const rootRow = initializerRootRow(result.value, created);
|
|
@@ -96947,7 +97034,9 @@ function isNamePath(expression) {
|
|
|
96947
97034
|
}
|
|
96948
97035
|
function isLiteralCall(expression) {
|
|
96949
97036
|
if (expression.callee.kind === "ident" && expression.callee.name === "Reference") {
|
|
96950
|
-
return true;
|
|
97037
|
+
if (expression.argumentNames?.some((name) => name !== null)) return true;
|
|
97038
|
+
const argument2 = expression.args[0];
|
|
97039
|
+
return expression.args.length === 1 && argument2 !== void 0 && (isNamePath(argument2) || argument2.kind === "litString");
|
|
96951
97040
|
}
|
|
96952
97041
|
return expression.callee.kind === "member" && expression.callee.name === "Slice";
|
|
96953
97042
|
}
|
|
@@ -97341,21 +97430,15 @@ function lowerClassConstructors(context, declaration, classId, lowerParameterTyp
|
|
|
97341
97430
|
const declared = declaration.constructors.map((declared2) => {
|
|
97342
97431
|
const id2 = declaredConstructorId2(declaration, declared2);
|
|
97343
97432
|
const base = context.baseConstructors.get(id2);
|
|
97344
|
-
const parameters = declared2.parameters.map(
|
|
97345
|
-
|
|
97346
|
-
|
|
97347
|
-
|
|
97348
|
-
|
|
97349
|
-
|
|
97350
|
-
|
|
97351
|
-
|
|
97352
|
-
|
|
97353
|
-
`${declaration.name}.${declared2.name}(${parameter4.name})`
|
|
97354
|
-
),
|
|
97355
|
-
source: span({ source: parameter4.source }),
|
|
97356
|
-
selectionSpan: span({ source: parameter4.source })
|
|
97357
|
-
};
|
|
97358
|
-
});
|
|
97433
|
+
const parameters = declared2.parameters.map(
|
|
97434
|
+
(parameter4) => lowerConstructorParameter(
|
|
97435
|
+
context,
|
|
97436
|
+
parameter4,
|
|
97437
|
+
declaration,
|
|
97438
|
+
lowerParameterType,
|
|
97439
|
+
`${declaration.name}.${declared2.name}(${parameter4.name})`
|
|
97440
|
+
)
|
|
97441
|
+
);
|
|
97359
97442
|
const baseArguments = lowerBaseArguments(
|
|
97360
97443
|
context,
|
|
97361
97444
|
declaration,
|
|
@@ -97400,26 +97483,41 @@ function lowerRequiredConstructor(context, declaration, classId, lowerParameterT
|
|
|
97400
97483
|
selectionSpan: sourceSpan
|
|
97401
97484
|
},
|
|
97402
97485
|
classId,
|
|
97403
|
-
arguments: required2.parameters.map(
|
|
97404
|
-
|
|
97405
|
-
|
|
97406
|
-
|
|
97407
|
-
|
|
97408
|
-
|
|
97409
|
-
|
|
97410
|
-
|
|
97411
|
-
|
|
97412
|
-
`${declaration.name}(${parameter4.name})`
|
|
97413
|
-
),
|
|
97414
|
-
source: span({ source: parameter4.source }),
|
|
97415
|
-
selectionSpan: span({ source: parameter4.source })
|
|
97416
|
-
};
|
|
97417
|
-
}),
|
|
97486
|
+
arguments: required2.parameters.map(
|
|
97487
|
+
(parameter4) => lowerConstructorParameter(
|
|
97488
|
+
context,
|
|
97489
|
+
parameter4,
|
|
97490
|
+
declaration,
|
|
97491
|
+
lowerParameterType,
|
|
97492
|
+
`${declaration.name}(${parameter4.name})`
|
|
97493
|
+
)
|
|
97494
|
+
),
|
|
97418
97495
|
code: requiredConstructorBody(required2.body, base?.code),
|
|
97419
97496
|
...baseArguments.length === 0 ? {} : { baseArguments },
|
|
97420
97497
|
...baseInitializerFields.length === 0 ? {} : { baseInitializerFields }
|
|
97421
97498
|
};
|
|
97422
97499
|
}
|
|
97500
|
+
function lowerConstructorParameter(context, parameter4, declaration, lowerParameterType, path) {
|
|
97501
|
+
try {
|
|
97502
|
+
const type = lowerParameterType(parameter4.type, declaration);
|
|
97503
|
+
return {
|
|
97504
|
+
name: parameter4.name,
|
|
97505
|
+
type,
|
|
97506
|
+
default: lowerParameterDefault(context, parameter4, type, path),
|
|
97507
|
+
source: span({ source: parameter4.source }),
|
|
97508
|
+
selectionSpan: span({ source: parameter4.source })
|
|
97509
|
+
};
|
|
97510
|
+
} catch (error) {
|
|
97511
|
+
if (error instanceof SchemaSourceError) throw error;
|
|
97512
|
+
throw new SchemaSourceError(
|
|
97513
|
+
error instanceof Error ? error.message : String(error),
|
|
97514
|
+
parameter4.source.uri,
|
|
97515
|
+
parameter4.source.range.start.line + 1,
|
|
97516
|
+
parameter4.source.range.start.character + 1,
|
|
97517
|
+
"schema-lowering"
|
|
97518
|
+
);
|
|
97519
|
+
}
|
|
97520
|
+
}
|
|
97423
97521
|
function requiredConstructorRecordId(classId) {
|
|
97424
97522
|
return isPendingId(classId) ? pendingRequiredConstructorId(classId) : derivedRequiredConstructorId(classId);
|
|
97425
97523
|
}
|
|
@@ -97533,6 +97631,7 @@ var init_lower_constructors = __esm({
|
|
|
97533
97631
|
init_pending_id();
|
|
97534
97632
|
init_declared_constructors();
|
|
97535
97633
|
init_required_constructor_id();
|
|
97634
|
+
init_source_diagnostics();
|
|
97536
97635
|
init_declared_constructors2();
|
|
97537
97636
|
init_lower_parameter_defaults();
|
|
97538
97637
|
init_init_source();
|
|
@@ -148727,6 +148826,11 @@ function computeStatus(workspace, options, conflictedFiles, parseErrors, parseWa
|
|
|
148727
148826
|
Object.values(loweringRecords)
|
|
148728
148827
|
)
|
|
148729
148828
|
});
|
|
148829
|
+
if (failedDeclarations.size > 0 && validAnalysis.schema.classes.some(
|
|
148830
|
+
(declaration) => failedDeclarations.has(declaration)
|
|
148831
|
+
)) {
|
|
148832
|
+
return refusedStatus(conflictedFiles, parseErrors, parseWarnings);
|
|
148833
|
+
}
|
|
148730
148834
|
const loweredMemberIds = new Set(
|
|
148731
148835
|
manifest.members.map((member) => member.id)
|
|
148732
148836
|
);
|
|
@@ -159758,7 +159862,7 @@ function projectSignatureHelp(analysis, document, position) {
|
|
|
159758
159862
|
);
|
|
159759
159863
|
}
|
|
159760
159864
|
if (callee.text === "Reference") {
|
|
159761
|
-
const parameters = ["symbol or id", "withProvenance = false"];
|
|
159865
|
+
const parameters = ["class value, symbol, or id", "withProvenance = false"];
|
|
159762
159866
|
return signatureResult(
|
|
159763
159867
|
"Reference",
|
|
159764
159868
|
parameters,
|
|
@@ -189657,7 +189761,13 @@ var init_exports = {};
|
|
|
189657
189761
|
__export(init_exports, {
|
|
189658
189762
|
runInit: () => runInit
|
|
189659
189763
|
});
|
|
189660
|
-
import {
|
|
189764
|
+
import {
|
|
189765
|
+
existsSync as existsSync19,
|
|
189766
|
+
mkdirSync as mkdirSync14,
|
|
189767
|
+
readFileSync as readFileSync25,
|
|
189768
|
+
readdirSync as readdirSync7,
|
|
189769
|
+
writeFileSync as writeFileSync15
|
|
189770
|
+
} from "node:fs";
|
|
189661
189771
|
import { join as join23, resolve as resolve4 } from "node:path";
|
|
189662
189772
|
async function runInit(options) {
|
|
189663
189773
|
let projectId = options.projectId;
|
|
@@ -189758,6 +189868,16 @@ async function runInit(options) {
|
|
|
189758
189868
|
if (existsSync19(join23(root, NEO_CONFIG_FILE))) {
|
|
189759
189869
|
throw new Error(`"${join23(root, NEO_CONFIG_FILE)}" already exists.`);
|
|
189760
189870
|
}
|
|
189871
|
+
if (existsSync19(root)) {
|
|
189872
|
+
const existing = readdirSync7(root).find(
|
|
189873
|
+
(name) => name !== ".git" && name !== ".gitignore"
|
|
189874
|
+
);
|
|
189875
|
+
if (existing !== void 0) {
|
|
189876
|
+
throw new Error(
|
|
189877
|
+
`Cannot initialize ${JSON.stringify(root)} because it contains ${JSON.stringify(existing)}. Choose an empty directory, or back up and move existing files first.`
|
|
189878
|
+
);
|
|
189879
|
+
}
|
|
189880
|
+
}
|
|
189761
189881
|
mkdirSync14(root, { recursive: true });
|
|
189762
189882
|
await acquireWorkspaceLock(root, "init");
|
|
189763
189883
|
ensurePrivateStateIgnored(root);
|
|
@@ -193079,7 +193199,7 @@ import { createHash as createHash18, randomUUID as randomUUID8 } from "node:cryp
|
|
|
193079
193199
|
import {
|
|
193080
193200
|
existsSync as existsSync20,
|
|
193081
193201
|
mkdirSync as mkdirSync15,
|
|
193082
|
-
readdirSync as
|
|
193202
|
+
readdirSync as readdirSync8,
|
|
193083
193203
|
readFileSync as readFileSync27,
|
|
193084
193204
|
realpathSync as realpathSync2,
|
|
193085
193205
|
renameSync as renameSync10,
|
|
@@ -194373,7 +194493,7 @@ function testBuildFiles(root) {
|
|
|
194373
194493
|
if (!existsSync20(root)) return [];
|
|
194374
194494
|
const files = [];
|
|
194375
194495
|
const visit = (directory) => {
|
|
194376
|
-
for (const entry of
|
|
194496
|
+
for (const entry of readdirSync8(directory, { withFileTypes: true })) {
|
|
194377
194497
|
if (entry.isSymbolicLink()) continue;
|
|
194378
194498
|
const path = join24(directory, entry.name);
|
|
194379
194499
|
if (entry.isDirectory()) visit(path);
|
|
@@ -197660,6 +197780,47 @@ function findVersion(versions, ref) {
|
|
|
197660
197780
|
(version) => version.id === ref || version.name === ref || version.semver.label === ref
|
|
197661
197781
|
);
|
|
197662
197782
|
}
|
|
197783
|
+
function assertCleanBranchSwitch(workspace) {
|
|
197784
|
+
assertNoPendingPushRecovery(workspace);
|
|
197785
|
+
const records3 = Object.values(workspace.state.records);
|
|
197786
|
+
for (const record7 of records3) {
|
|
197787
|
+
if (record7.conflictServerHash !== void 0) {
|
|
197788
|
+
throw new Error(
|
|
197789
|
+
"Cannot switch branches with unresolved record conflicts. Run neo resolve before switching."
|
|
197790
|
+
);
|
|
197791
|
+
}
|
|
197792
|
+
}
|
|
197793
|
+
if (records3.length === 0) {
|
|
197794
|
+
const inputs = listProjectExportInputsV4(workspace.root);
|
|
197795
|
+
if (inputs.sources.length === 0 && inputs.binaries.length === 0) return;
|
|
197796
|
+
}
|
|
197797
|
+
const status = computeWorkspaceStatus2(workspace);
|
|
197798
|
+
if (status.conflictedFiles.length > 0) {
|
|
197799
|
+
throw new Error(
|
|
197800
|
+
"Cannot switch branches with unresolved conflicts. Resolve them before switching."
|
|
197801
|
+
);
|
|
197802
|
+
}
|
|
197803
|
+
if (status.parseErrors.length > 0) {
|
|
197804
|
+
throw new Error(
|
|
197805
|
+
"Cannot switch branches while local source has errors. Run neo status and fix or back up your edits before switching."
|
|
197806
|
+
);
|
|
197807
|
+
}
|
|
197808
|
+
if (status.changes.length > 0) {
|
|
197809
|
+
throw new Error(
|
|
197810
|
+
"Cannot switch branches with unpushed changes. Push or back up your edits first; use neo pull --force only to deliberately discard them."
|
|
197811
|
+
);
|
|
197812
|
+
}
|
|
197813
|
+
if (status.authoredValueSeeds.size > 0) {
|
|
197814
|
+
throw new Error(
|
|
197815
|
+
"Cannot switch branches with unpushed value seeds. Push or back up your edits first; use neo pull --force only to deliberately discard them."
|
|
197816
|
+
);
|
|
197817
|
+
}
|
|
197818
|
+
if ((status.binaryChanges?.length ?? 0) > 0) {
|
|
197819
|
+
throw new Error(
|
|
197820
|
+
"Cannot switch branches with pending file changes. Run neo status and settle those changes before switching."
|
|
197821
|
+
);
|
|
197822
|
+
}
|
|
197823
|
+
}
|
|
197663
197824
|
async function runBranch(workspace, subcommand, positional, fromRef) {
|
|
197664
197825
|
if (subcommand === "list") {
|
|
197665
197826
|
const { versions } = await loadVersionMetadata(workspace);
|
|
@@ -197750,9 +197911,13 @@ async function runBranch(workspace, subcommand, positional, fromRef) {
|
|
|
197750
197911
|
console.log(`Already on ${displayLabel(target)}.`);
|
|
197751
197912
|
return;
|
|
197752
197913
|
}
|
|
197914
|
+
assertCleanBranchSwitch(workspace);
|
|
197753
197915
|
workspace.config = { ...workspace.config, versionId: target.id };
|
|
197754
197916
|
writeWorkspaceConfig(workspace.root, workspace.config);
|
|
197755
|
-
workspace.state = {
|
|
197917
|
+
workspace.state = {
|
|
197918
|
+
records: workspace.state.records,
|
|
197919
|
+
localValues: workspace.state.localValues
|
|
197920
|
+
};
|
|
197756
197921
|
writeWorkspaceState(workspace.root, workspace.state);
|
|
197757
197922
|
success(
|
|
197758
197923
|
`Switched to ${color.bold(displayLabel(target))} ${color.dim(`(${target.id})`)}. Pulling\u2026`
|
|
@@ -198212,6 +198377,8 @@ var init_branch = __esm({
|
|
|
198212
198377
|
init_value_comparison();
|
|
198213
198378
|
init_ui();
|
|
198214
198379
|
init_pull();
|
|
198380
|
+
init_workspace_status();
|
|
198381
|
+
init_push_recovery();
|
|
198215
198382
|
init_http();
|
|
198216
198383
|
init_project_transaction();
|
|
198217
198384
|
displayLabel = projectVersionDisplayLabel;
|
|
@@ -201237,7 +201404,7 @@ var dev_exports = {};
|
|
|
201237
201404
|
__export(dev_exports, {
|
|
201238
201405
|
runDev: () => runDev
|
|
201239
201406
|
});
|
|
201240
|
-
import { readdirSync as
|
|
201407
|
+
import { readdirSync as readdirSync9, statSync as statSync6, watch } from "node:fs";
|
|
201241
201408
|
import { basename as basename5, dirname as dirname15, join as join27, resolve as resolve6 } from "node:path";
|
|
201242
201409
|
import { emitKeypressEvents } from "node:readline";
|
|
201243
201410
|
async function runDev(root, loadWorkspace2, options) {
|
|
@@ -201370,7 +201537,7 @@ function countsAsExportInput(root, relativePath, event, directories) {
|
|
|
201370
201537
|
function rememberDirectories(root, relativePath, directories) {
|
|
201371
201538
|
let entries;
|
|
201372
201539
|
try {
|
|
201373
|
-
entries =
|
|
201540
|
+
entries = readdirSync9(join27(root, relativePath), { withFileTypes: true });
|
|
201374
201541
|
} catch (error) {
|
|
201375
201542
|
if (error instanceof Error && "code" in error) {
|
|
201376
201543
|
if (error.code === "ENOENT") return;
|
|
@@ -201549,18 +201716,19 @@ function resolveMarkers(source, side) {
|
|
|
201549
201716
|
const output = [];
|
|
201550
201717
|
let mode = "outside";
|
|
201551
201718
|
for (const line of lines) {
|
|
201552
|
-
|
|
201719
|
+
const marker = line.endsWith("\r") ? line.slice(0, -1) : line;
|
|
201720
|
+
if (marker.startsWith("<<<<<<<")) {
|
|
201553
201721
|
if (mode !== "outside") {
|
|
201554
201722
|
throw new Error("Nested conflict markers are not supported.");
|
|
201555
201723
|
}
|
|
201556
201724
|
mode = "local";
|
|
201557
201725
|
continue;
|
|
201558
201726
|
}
|
|
201559
|
-
if (
|
|
201727
|
+
if (marker === "=======" && mode === "local") {
|
|
201560
201728
|
mode = "server";
|
|
201561
201729
|
continue;
|
|
201562
201730
|
}
|
|
201563
|
-
if (
|
|
201731
|
+
if (marker.startsWith(">>>>>>>")) {
|
|
201564
201732
|
if (mode !== "server") {
|
|
201565
201733
|
throw new Error("Unbalanced conflict markers.");
|
|
201566
201734
|
}
|
|
@@ -201847,7 +202015,7 @@ There is no --keep-current: preserving current semantic state defines flatten.
|
|
|
201847
202015
|
async function main() {
|
|
201848
202016
|
const args = parseArgs(process.argv.slice(2));
|
|
201849
202017
|
if (args.command === "--version") {
|
|
201850
|
-
console.log("0.81.
|
|
202018
|
+
console.log("0.81.4");
|
|
201851
202019
|
return;
|
|
201852
202020
|
}
|
|
201853
202021
|
if (args.command === null || args.command === "help" || args.command === "--help" || args.command === "-h") {
|
|
@@ -201859,6 +202027,7 @@ async function main() {
|
|
|
201859
202027
|
return;
|
|
201860
202028
|
}
|
|
201861
202029
|
assertKnownFlags(args);
|
|
202030
|
+
assertCommandFlags(args);
|
|
201862
202031
|
if (WORKSPACE_LOCK_COMMANDS.has(args.command)) {
|
|
201863
202032
|
const root = findWorkspaceRoot(process.cwd());
|
|
201864
202033
|
if (root !== null) {
|
package/dist/test-worker.mjs
CHANGED
|
@@ -35697,6 +35697,7 @@ function evaluateMemberInitializer(args) {
|
|
|
35697
35697
|
__constructedFieldSchemaKeysByValue: /* @__PURE__ */ new WeakMap(),
|
|
35698
35698
|
__createdStorageKeyDeclarations: args.storageKeyDeclarations ?? /* @__PURE__ */ new Map()
|
|
35699
35699
|
};
|
|
35700
|
+
let evaluatedContext = ctx;
|
|
35700
35701
|
const result = (() => {
|
|
35701
35702
|
try {
|
|
35702
35703
|
return evaluateNSGetterWithEffects(
|
|
@@ -35705,6 +35706,9 @@ function evaluateMemberInitializer(args) {
|
|
|
35705
35706
|
args.argumentValues ?? [],
|
|
35706
35707
|
{
|
|
35707
35708
|
exportInitializerValues: true,
|
|
35709
|
+
inspectResult: (_value, runtimeContext) => {
|
|
35710
|
+
evaluatedContext = runtimeContext;
|
|
35711
|
+
},
|
|
35708
35712
|
// Seeded rows already hold their placement.
|
|
35709
35713
|
...args.sessionValues === void 0 ? {
|
|
35710
35714
|
initializerResult: {
|
|
@@ -35730,7 +35734,7 @@ function evaluateMemberInitializer(args) {
|
|
|
35730
35734
|
args.member,
|
|
35731
35735
|
result.value,
|
|
35732
35736
|
created,
|
|
35733
|
-
|
|
35737
|
+
evaluatedContext
|
|
35734
35738
|
);
|
|
35735
35739
|
}
|
|
35736
35740
|
const rootRow = initializerRootRow(result.value, created);
|
|
@@ -40073,7 +40077,48 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
|
|
|
40073
40077
|
);
|
|
40074
40078
|
case "call": {
|
|
40075
40079
|
const receiverValue = this.callReceiver(expression.callee, scope);
|
|
40076
|
-
if (expression.callee.kind === "ident" && expression.callee.name === "Reference"
|
|
40080
|
+
if (expression.callee.kind === "ident" && expression.callee.name === "Reference") {
|
|
40081
|
+
if (expression.args.length === 1 && expression.argumentNames?.[0] == null) {
|
|
40082
|
+
if ((expression.typeArguments?.length ?? 0) > 1) {
|
|
40083
|
+
throw new CompileError(
|
|
40084
|
+
"Reference accepts at most one generic target type.",
|
|
40085
|
+
expression.pos
|
|
40086
|
+
);
|
|
40087
|
+
}
|
|
40088
|
+
const explicit = expression.typeArguments?.[0];
|
|
40089
|
+
const targetType = explicit === void 0 ? void 0 : this.resolveType(explicit);
|
|
40090
|
+
const target = this.resolveExpression(
|
|
40091
|
+
expression.args[0],
|
|
40092
|
+
scope,
|
|
40093
|
+
targetType
|
|
40094
|
+
);
|
|
40095
|
+
const type = targetType ?? target.type;
|
|
40096
|
+
if (type.kind !== "typeParameter" && !(type.kind === "named" && this.project.typeById.get(type.typeId)?.kind === "class")) {
|
|
40097
|
+
throw new CompileError(
|
|
40098
|
+
"Reference(value) requires a class value.",
|
|
40099
|
+
expression.pos
|
|
40100
|
+
);
|
|
40101
|
+
}
|
|
40102
|
+
if (!isNeoScriptTypeAssignable(target.type, type, this.project)) {
|
|
40103
|
+
throw new CompileError(
|
|
40104
|
+
`Reference target ${this.describe(target.type)} is not assignable to ${this.describe(type)}.`,
|
|
40105
|
+
expression.pos
|
|
40106
|
+
);
|
|
40107
|
+
}
|
|
40108
|
+
if (expected !== void 0 && !isNeoScriptTypeAssignable(type, expected, this.project)) {
|
|
40109
|
+
throw new CompileError(
|
|
40110
|
+
`Reference target ${this.describe(type)} is not assignable to ${this.describe(expected)}.`,
|
|
40111
|
+
expression.pos
|
|
40112
|
+
);
|
|
40113
|
+
}
|
|
40114
|
+
return { ...target, type };
|
|
40115
|
+
}
|
|
40116
|
+
if (expression.typeArguments === void 0) {
|
|
40117
|
+
throw new CompileError(
|
|
40118
|
+
'Reference requires one class value, or Reference<T>(id: "...").',
|
|
40119
|
+
expression.pos
|
|
40120
|
+
);
|
|
40121
|
+
}
|
|
40077
40122
|
const [referenceTypeArgument] = expression.typeArguments;
|
|
40078
40123
|
if (expression.typeArguments.length !== 1 || referenceTypeArgument === void 0) {
|
|
40079
40124
|
throw new CompileError(
|
|
@@ -59593,7 +59638,7 @@ var INITIALIZER_KEY_PLACEHOLDER = new RegExp(
|
|
|
59593
59638
|
|
|
59594
59639
|
// ../packages/manifest/schema-contract/registry.mjs
|
|
59595
59640
|
var PROJECT_SCHEMA_CONTRACT = Object.freeze({
|
|
59596
|
-
cliVersion: "0.81.
|
|
59641
|
+
cliVersion: "0.81.4",
|
|
59597
59642
|
projectFileUploadBatchSize: 32,
|
|
59598
59643
|
documentRecords: {
|
|
59599
59644
|
member: {
|
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@ description: >-
|
|
|
9
9
|
`@neocompose/cli` or `node cli/bin/neo.mjs` in the neo-compose repository.
|
|
10
10
|
---
|
|
11
11
|
|
|
12
|
-
<!-- reviewed-through-cli: 0.81.
|
|
12
|
+
<!-- reviewed-through-cli: 0.81.4 -->
|
|
13
13
|
|
|
14
14
|
# Neo Compose CLI
|
|
15
15
|
|
|
@@ -88,6 +88,10 @@ neo doctor
|
|
|
88
88
|
Use `node cli/bin/neo.mjs` while developing the repository. Pass explicit flags
|
|
89
89
|
and IDs in automation. Non-TTY/CI commands never wait for pickers or confirms.
|
|
90
90
|
|
|
91
|
+
`neo init` requires a new or empty destination, apart from `.git` and
|
|
92
|
+
`.gitignore`. It refuses other existing entries before writing anything; choose
|
|
93
|
+
a separate directory when recovering a checkout whose config is missing.
|
|
94
|
+
|
|
91
95
|
Require `formatVersion: 4` in `neo.json`. There is no format-3 reader or
|
|
92
96
|
upgrader. Reconstruct an authoritative format-4 checkout with `neo init`.
|
|
93
97
|
|
|
@@ -129,7 +129,7 @@ wrappers.
|
|
|
129
129
|
The marker near the top of `SKILL.md` must exactly match the package version:
|
|
130
130
|
|
|
131
131
|
```html
|
|
132
|
-
<!-- reviewed-through-cli: 0.81.
|
|
132
|
+
<!-- reviewed-through-cli: 0.81.4 -->
|
|
133
133
|
```
|
|
134
134
|
|
|
135
135
|
The quoted version above is checked too, so this instruction cannot go stale
|
|
@@ -29,6 +29,11 @@ neo push
|
|
|
29
29
|
neo push --dry-run --force-recompile
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
+
`neo status` reports invalid constructor parameters at their `.neo` file, line,
|
|
33
|
+
and column. Fix the reported parameter type before pushing. For example,
|
|
34
|
+
constructor parameters use `Item`; `Reference<Item>` declares member storage.
|
|
35
|
+
A failed class or constructor declaration blocks candidate preparation.
|
|
36
|
+
|
|
32
37
|
Use `neo pull --regenerate-source-names` to replace generated default dialogue
|
|
33
38
|
names with readable ones. It keeps chosen names and rewrites references. Use
|
|
34
39
|
`--reset` to regenerate canonical source and managed binaries. Reset retains
|
|
@@ -151,6 +156,9 @@ become real only after acceptance.
|
|
|
151
156
|
|
|
152
157
|
## Conflicts and files
|
|
153
158
|
|
|
159
|
+
Conflict resolution accepts LF, CRLF, and mixed line endings. It retains the
|
|
160
|
+
selected source lines and their existing line endings.
|
|
161
|
+
|
|
154
162
|
Resolve source conflicts by editing the final intended source. Use
|
|
155
163
|
`neo resolve --mine` or `neo resolve --theirs` only for a deliberate whole-side
|
|
156
164
|
choice. Pull, inspect, dry-run, and retry; there is no force-CAS path.
|
|
@@ -228,6 +236,11 @@ neo history status --run <run-id>
|
|
|
228
236
|
neo history resume --run <run-id>
|
|
229
237
|
```
|
|
230
238
|
|
|
239
|
+
Branch switching requires a clean working copy. Unpushed source or binary
|
|
240
|
+
changes, unresolved conflicts, source errors, and pending push recovery stop the
|
|
241
|
+
switch before it changes the selected version or baseline. Push or back up edits
|
|
242
|
+
first; use `neo pull --force` only when discarding them is intended.
|
|
243
|
+
|
|
231
244
|
Treat branches as copy-on-write forks and releases as immutable snapshots. The
|
|
232
245
|
server derives the minimum compatibility bump; a caller may only raise it.
|
|
233
246
|
Require the release login profile for release operations.
|
|
@@ -294,6 +307,12 @@ so concurrent environments sharing one OS user cannot read, overwrite, or
|
|
|
294
307
|
delete each other's tokens. Login, logout, and authenticated commands all
|
|
295
308
|
honor both variables.
|
|
296
309
|
|
|
310
|
+
Boolean flags are switches: pass `--dry-run` or `--help` without a value.
|
|
311
|
+
Values such as `--dry-run=true` are rejected before a command runs.
|
|
312
|
+
`--dry-run` is supported by push, merge, refresh, branch refresh, release cut,
|
|
313
|
+
and migrate run. Other commands reject it before taking action. Branch options
|
|
314
|
+
are scoped to their subcommands; branch create does not support dry-run.
|
|
315
|
+
|
|
297
316
|
Pass explicit project/version IDs and flags in automation. Prefer `--json` for
|
|
298
317
|
machine-readable output and do not depend on interactive pickers or confirms.
|
|
299
318
|
|
|
@@ -180,6 +180,22 @@ is one such row — its identity comes from the schema key its parameter settles
|
|
|
180
180
|
|
|
181
181
|
## Same-push references
|
|
182
182
|
|
|
183
|
+
`Reference<T>` and `Set<Reference<T>>` declare lookup storage. Their runtime
|
|
184
|
+
values are `T` and `Set<T>`, so a projection can assign existing class values
|
|
185
|
+
directly:
|
|
186
|
+
|
|
187
|
+
```neo
|
|
188
|
+
EligibleIngredients = root.Assets.Crafting.FurnaceRecipes
|
|
189
|
+
.Select((MachineRecipe recipe) => recipe.Ingredient)
|
|
190
|
+
.ToSet()
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Writing `Reference(recipe.Ingredient)` inside the callback is also valid.
|
|
194
|
+
`Reference(value)` preserves an evaluated class value and its identity; it does
|
|
195
|
+
not clone it or turn it into a separate wrapper object. An optional generic
|
|
196
|
+
argument checks the target type. Lookup assignment still requires an existing
|
|
197
|
+
backing row and enforces its declared target and collection constraints.
|
|
198
|
+
|
|
183
199
|
Use the `Reference` intrinsic. Prefer the most readable form the target
|
|
184
200
|
supports:
|
|
185
201
|
|
|
@@ -197,9 +213,8 @@ Reference<NeoDialogue>(id: "capitol-dialogue-id")
|
|
|
197
213
|
- Use `key:` only for a collection with a unique index. Omit `index:` when the
|
|
198
214
|
collection has exactly one usable unique index; supply the bare member name
|
|
199
215
|
when it has more than one.
|
|
200
|
-
- Use the generic `id:` form when the ID is the only target information.
|
|
201
|
-
|
|
202
|
-
name rather than read as an ID.
|
|
216
|
+
- Use the generic `id:` form when the ID is the only target information.
|
|
217
|
+
Unrecognized named arguments are rejected rather than read as IDs.
|
|
203
218
|
- Inside executable NeoScript, add `withProvenance: true` when the ID names an
|
|
204
219
|
authored row and the reference must select its nearest `sourceValueId` clone
|
|
205
220
|
in the lexical receiver's ownership graph. The parameter defaults to `false`;
|