@wairon/cli 5.1.1-dev.34 → 5.1.1-dev.35
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/dist/cli/index.js +203 -28
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +200 -25
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -65,7 +65,7 @@ var init_defaults = __esm({
|
|
|
65
65
|
copilot: ".github/prompts",
|
|
66
66
|
codex: ".codex/agents"
|
|
67
67
|
};
|
|
68
|
-
WAIRON_VERSION = "5.1.1-dev.
|
|
68
|
+
WAIRON_VERSION = "5.1.1-dev.35";
|
|
69
69
|
GITHUB_REPO = "SYW-Apps/Waffle-AIron";
|
|
70
70
|
SUPPORTED_ALIASES = ["wai"];
|
|
71
71
|
SCAN_EXCLUDE_DIRS = /* @__PURE__ */ new Set([
|
|
@@ -23562,10 +23562,30 @@ function identityKeyOf(field, item) {
|
|
|
23562
23562
|
return str(o.description);
|
|
23563
23563
|
case "databases":
|
|
23564
23564
|
return str(o.id) ?? str(o.name);
|
|
23565
|
+
// A flow step's own arrays, addressed by the thing the author named them
|
|
23566
|
+
// for. Their `step` is a RELOCATABLE number, never an identity — a switch
|
|
23567
|
+
// case is the value it matches and a catch clause is the error it catches,
|
|
23568
|
+
// and both survive the renumbering that moves their target. (A parallel
|
|
23569
|
+
// arm falls to the default: named, it merges by name; unnamed, it carries
|
|
23570
|
+
// no identity at all and the list replaces wholesale, which is the same
|
|
23571
|
+
// rule everywhere else.)
|
|
23572
|
+
case "cases":
|
|
23573
|
+
return str(o.value);
|
|
23574
|
+
case "catches":
|
|
23575
|
+
return str(o.error);
|
|
23565
23576
|
default:
|
|
23566
23577
|
return str(o.name) ?? str(o.id);
|
|
23567
23578
|
}
|
|
23568
23579
|
}
|
|
23580
|
+
function stepFieldsFor(type) {
|
|
23581
|
+
const own = STEP_TYPE_FIELDS[type] ?? [];
|
|
23582
|
+
const allowed = /* @__PURE__ */ new Set([...STEP_COMMON_FIELDS, ...own]);
|
|
23583
|
+
for (const field of own) {
|
|
23584
|
+
const twin = STEP_LABEL_TWINS[field];
|
|
23585
|
+
if (twin) allowed.add(twin);
|
|
23586
|
+
}
|
|
23587
|
+
return allowed;
|
|
23588
|
+
}
|
|
23569
23589
|
function reportIdentityOf(field, item) {
|
|
23570
23590
|
if (item !== null && typeof item === "object") {
|
|
23571
23591
|
const step = item.stepNumber;
|
|
@@ -23841,7 +23861,7 @@ function findLegacySpecFiles() {
|
|
|
23841
23861
|
function updateSpec(kind, id, delta, hooks) {
|
|
23842
23862
|
return current().updateSpec(kind, id, delta, hooks);
|
|
23843
23863
|
}
|
|
23844
|
-
var fs17, path23, NO_ROOT_SUBSYSTEMS, SIGNATURE_TTL_MS, SpecWorkspace, workspaces;
|
|
23864
|
+
var fs17, path23, NO_ROOT_SUBSYSTEMS, SIGNATURE_TTL_MS, STEP_TYPE_FIELDS, STEP_COMMON_FIELDS, STEP_LABEL_TWINS, SpecWorkspace, workspaces;
|
|
23845
23865
|
var init_specs2 = __esm({
|
|
23846
23866
|
"src/core/specs.ts"() {
|
|
23847
23867
|
"use strict";
|
|
@@ -23859,6 +23879,36 @@ var init_specs2 = __esm({
|
|
|
23859
23879
|
init_diagram();
|
|
23860
23880
|
NO_ROOT_SUBSYSTEMS = /* @__PURE__ */ new Set();
|
|
23861
23881
|
SIGNATURE_TTL_MS = 2e3;
|
|
23882
|
+
STEP_TYPE_FIELDS = {
|
|
23883
|
+
local: [],
|
|
23884
|
+
call: ["targetComponent", "targetMethod", "auth", "detach"],
|
|
23885
|
+
register: ["targetComponent", "targetMethod"],
|
|
23886
|
+
dispatch: ["targetComponent", "capability", "auth", "detach"],
|
|
23887
|
+
branch: ["condition", "onTrueStep", "onFalseStep"],
|
|
23888
|
+
switch: ["on", "cases", "defaultStep"],
|
|
23889
|
+
loop: ["loopKind", "over", "condition", "endStep"],
|
|
23890
|
+
try: ["endStep", "catches", "finallyStep"],
|
|
23891
|
+
parallel: ["endStep", "branches"],
|
|
23892
|
+
jump: ["toStep"],
|
|
23893
|
+
return: ["outcome"],
|
|
23894
|
+
throw: ["error"]
|
|
23895
|
+
};
|
|
23896
|
+
STEP_COMMON_FIELDS = [
|
|
23897
|
+
"stepNumber",
|
|
23898
|
+
"label",
|
|
23899
|
+
"description",
|
|
23900
|
+
"type",
|
|
23901
|
+
"assertsGuarantees",
|
|
23902
|
+
"assertsInvariants"
|
|
23903
|
+
];
|
|
23904
|
+
STEP_LABEL_TWINS = {
|
|
23905
|
+
onTrueStep: "onTrueLabel",
|
|
23906
|
+
onFalseStep: "onFalseLabel",
|
|
23907
|
+
defaultStep: "defaultLabel",
|
|
23908
|
+
endStep: "endLabel",
|
|
23909
|
+
finallyStep: "finallyLabel",
|
|
23910
|
+
toStep: "toLabel"
|
|
23911
|
+
};
|
|
23862
23912
|
SpecWorkspace = class {
|
|
23863
23913
|
constructor(rootDir) {
|
|
23864
23914
|
this.cachedIndex = null;
|
|
@@ -25096,9 +25146,39 @@ var init_specs2 = __esm({
|
|
|
25096
25146
|
// Granular delta updates (sdd_update_spec)
|
|
25097
25147
|
// -------------------------------------------------------------------------
|
|
25098
25148
|
/**
|
|
25099
|
-
*
|
|
25100
|
-
*
|
|
25101
|
-
*
|
|
25149
|
+
* Apply a delta to one stored spec, in this ORDER — the order is the contract,
|
|
25150
|
+
* because every stage below can see what the stage above left:
|
|
25151
|
+
*
|
|
25152
|
+
* 1. LOAD the stored spec for the addressed kind and id; a spec that does
|
|
25153
|
+
* not exist refuses, and a mis-selected `system` kind refuses by name.
|
|
25154
|
+
* 2. REFUSE unknown delta keys, whole. A key the level's schema does not
|
|
25155
|
+
* know is dropped on write, so the edit would report a success it never
|
|
25156
|
+
* performed.
|
|
25157
|
+
* 3. QUALIFY the delta's id-bearing references against the spec's namespace,
|
|
25158
|
+
* BEFORE the merge — post-merge a bare id is ambiguous.
|
|
25159
|
+
* 4. MERGE. Identity-keyed arrays upsert element by element and honour their
|
|
25160
|
+
* delete markers, at every depth. Narrative step deltas apply in ASCENDING
|
|
25161
|
+
* stepNumber order, each against the numbering the earlier entries of the
|
|
25162
|
+
* same delta left behind — delete step 3 and step 7 becomes step 6, so a
|
|
25163
|
+
* second delete written as 7 addresses what used to be step 8. That is why
|
|
25164
|
+
* a delete may restate the step's `label` or `description` as a guard, and
|
|
25165
|
+
* why labels are the reliable way to name a jump target. Inserts and
|
|
25166
|
+
* deletes relocate every jump field in the same narrative around them; a
|
|
25167
|
+
* step whose `type` changes is REBUILT for its new type, keeping its
|
|
25168
|
+
* description and label.
|
|
25169
|
+
* 5. UNSET the fields the delta names, at the level each `unset` sits in.
|
|
25170
|
+
* 6. RESOLVE symbolic `*Label` references against the MERGED numbering — after
|
|
25171
|
+
* the merge, so a delta may anchor on a label that only pre-existing steps
|
|
25172
|
+
* carry, and a label in the delta retargets the stored numeric jump it
|
|
25173
|
+
* twins. An unresolved reference aborts the whole update.
|
|
25174
|
+
* 7. COMPARE with what is stored, both read through the level's canonical
|
|
25175
|
+
* schema. Equal means nothing is written and `written` is false.
|
|
25176
|
+
* 8. GATE the merged spec through the caller's hook, then SAVE.
|
|
25177
|
+
*
|
|
25178
|
+
* Returns the change report, whose `notices` carry the non-fatal effects (an
|
|
25179
|
+
* insert whose position was a jump target, so the relocated jumps now bypass
|
|
25180
|
+
* the inserted step; the fields a retype dropped) — empty when the merge had
|
|
25181
|
+
* nothing to say.
|
|
25102
25182
|
*/
|
|
25103
25183
|
updateSpec(kind, id, delta, hooks) {
|
|
25104
25184
|
const notices = [];
|
|
@@ -25212,14 +25292,113 @@ var init_specs2 = __esm({
|
|
|
25212
25292
|
);
|
|
25213
25293
|
}
|
|
25214
25294
|
};
|
|
25215
|
-
const
|
|
25295
|
+
const NO_NESTED_MERGE = /* @__PURE__ */ new Set(["ext", "narrative", "unset"]);
|
|
25296
|
+
const mergeElement = (existing, deltaItem) => {
|
|
25297
|
+
const out = { ...existing, ...deltaItem };
|
|
25298
|
+
if (!existing || typeof existing !== "object" || !deltaItem || typeof deltaItem !== "object") return out;
|
|
25299
|
+
for (const [key, value] of Object.entries(deltaItem)) {
|
|
25300
|
+
if (NO_NESTED_MERGE.has(key) || !Array.isArray(value) || value.length === 0) continue;
|
|
25301
|
+
const before = existing[key];
|
|
25302
|
+
if (before !== void 0 && !Array.isArray(before)) continue;
|
|
25303
|
+
const stored = Array.isArray(before) ? before : [];
|
|
25304
|
+
if (!isIdentifiedArray(key, stored, value)) continue;
|
|
25305
|
+
out[key] = mergeIdentifiedArray(key, stored, value);
|
|
25306
|
+
}
|
|
25307
|
+
return out;
|
|
25308
|
+
};
|
|
25309
|
+
const retargetByLabel = (merged, deltaStep) => {
|
|
25310
|
+
const out = { ...merged };
|
|
25311
|
+
for (const [stepField, labelField] of Object.entries(STEP_LABEL_TWINS)) {
|
|
25312
|
+
if (deltaStep?.[labelField] !== void 0 && deltaStep?.[stepField] === void 0) delete out[stepField];
|
|
25313
|
+
}
|
|
25314
|
+
for (const key of ["cases", "catches"]) {
|
|
25315
|
+
const deltaEntries = deltaStep?.[key];
|
|
25316
|
+
if (!Array.isArray(deltaEntries) || !Array.isArray(out[key])) continue;
|
|
25317
|
+
const retargeted = new Set(
|
|
25318
|
+
deltaEntries.filter((e) => e?.label !== void 0 && e?.step === void 0).map((e) => identityKeyOf(key, e)).filter((k) => k !== null)
|
|
25319
|
+
);
|
|
25320
|
+
if (!retargeted.size) continue;
|
|
25321
|
+
out[key] = out[key].map((e) => {
|
|
25322
|
+
const k = identityKeyOf(key, e);
|
|
25323
|
+
if (k === null || !retargeted.has(k)) return e;
|
|
25324
|
+
const { step, ...rest } = e;
|
|
25325
|
+
return rest;
|
|
25326
|
+
});
|
|
25327
|
+
}
|
|
25328
|
+
return out;
|
|
25329
|
+
};
|
|
25330
|
+
const rebuildOnRetype = (stored, deltaStep, merged, methodName) => {
|
|
25331
|
+
const newType = merged?.type;
|
|
25332
|
+
if (typeof newType !== "string" || stored?.type === newType) return merged;
|
|
25333
|
+
if (!Object.prototype.hasOwnProperty.call(STEP_TYPE_FIELDS, newType)) return merged;
|
|
25334
|
+
const allowed = stepFieldsFor(newType);
|
|
25335
|
+
const stated = Object.keys(deltaStep).filter(
|
|
25336
|
+
(k) => k !== "type" && deltaStep[k] !== void 0 && !allowed.has(k)
|
|
25337
|
+
);
|
|
25338
|
+
if (stated.length) {
|
|
25339
|
+
throw new Error(
|
|
25340
|
+
`Refusing to retype narrative step ${stored.stepNumber} of "${methodName}" from "${stored.type}" to "${newType}": the same delta sets ${stated.map((f) => `"${f}"`).join(", ")}, which a ${newType} step cannot carry. Drop those keys, or retype to a step type that carries them.`
|
|
25341
|
+
);
|
|
25342
|
+
}
|
|
25343
|
+
const out = {};
|
|
25344
|
+
const dropped = [];
|
|
25345
|
+
for (const [key, value] of Object.entries(merged)) {
|
|
25346
|
+
if (allowed.has(key)) out[key] = value;
|
|
25347
|
+
else dropped.push(key);
|
|
25348
|
+
}
|
|
25349
|
+
if (dropped.length) {
|
|
25350
|
+
notices.push(
|
|
25351
|
+
`Narrative step ${stored.stepNumber} of "${methodName}" was retyped ${stored.type} -> ${newType}: ${dropped.join(", ")} dropped \u2014 a ${newType} step cannot carry ${dropped.length === 1 ? "it" : "them"}. Its description and label are kept.`
|
|
25352
|
+
);
|
|
25353
|
+
}
|
|
25354
|
+
return out;
|
|
25355
|
+
};
|
|
25356
|
+
const mergeNarrative = (methodName, existingSteps, deltaSteps) => {
|
|
25216
25357
|
let steps = [...existingSteps];
|
|
25217
25358
|
const sortedDeltas = [...deltaSteps].sort((a, b) => a.stepNumber - b.stepNumber);
|
|
25218
25359
|
for (const deltaStep of sortedDeltas) {
|
|
25219
25360
|
const stepNum = deltaStep.stepNumber;
|
|
25361
|
+
if (typeof stepNum !== "number") {
|
|
25362
|
+
throw new Error(
|
|
25363
|
+
`Refusing to update the narrative of "${methodName}": a step delta must carry the "stepNumber" it addresses, got ${JSON.stringify(stepNum ?? null)}.`
|
|
25364
|
+
);
|
|
25365
|
+
}
|
|
25366
|
+
if ("remove" in deltaStep && typeof deltaStep.remove !== "boolean") {
|
|
25367
|
+
throw new Error(
|
|
25368
|
+
`Refusing to update narrative step ${stepNum} of "${methodName}": "remove" must be the boolean true, got ${JSON.stringify(deltaStep.remove)}. A non-boolean is ignored, which would leave the step in place while reporting success.`
|
|
25369
|
+
);
|
|
25370
|
+
}
|
|
25371
|
+
if ("action" in deltaStep && deltaStep.action !== "insert" && deltaStep.action !== "delete") {
|
|
25372
|
+
throw new Error(
|
|
25373
|
+
`Refusing to update narrative step ${stepNum} of "${methodName}": unknown action ${JSON.stringify(deltaStep.action)} \u2014 expected "insert" or "delete", or no action at all to edit the step in place. An unknown verb is ignored, which would report success for an edit never made.`
|
|
25374
|
+
);
|
|
25375
|
+
}
|
|
25376
|
+
if ("captureJumps" in deltaStep && deltaStep.action !== "insert") {
|
|
25377
|
+
throw new Error(
|
|
25378
|
+
`Refusing to update narrative step ${stepNum} of "${methodName}": "captureJumps" only means anything on an inserted step \u2014 it decides whether jumps aimed at that number follow the shifted original or land on the new step. On any other delta it is ignored.`
|
|
25379
|
+
);
|
|
25380
|
+
}
|
|
25220
25381
|
if (deltaStep.action === "delete" || deltaStep.remove === true) {
|
|
25221
25382
|
const idx = steps.findIndex((s) => s.stepNumber === stepNum);
|
|
25222
25383
|
if (idx !== -1) {
|
|
25384
|
+
const victim = steps[idx];
|
|
25385
|
+
for (const field of ["label", "description"]) {
|
|
25386
|
+
if (deltaStep[field] === void 0) continue;
|
|
25387
|
+
if (victim[field] !== deltaStep[field]) {
|
|
25388
|
+
throw new Error(
|
|
25389
|
+
`Refusing to delete narrative step ${stepNum}: the delta states ${field} ${JSON.stringify(deltaStep[field])}, but step ${stepNum} holds ${JSON.stringify(victim[field] ?? null)}. Step deltas apply in ascending order against the numbering earlier entries of the same delta left behind, so a later delete can address a step that has already moved.`
|
|
25390
|
+
);
|
|
25391
|
+
}
|
|
25392
|
+
}
|
|
25393
|
+
if (typeof victim.endStep === "number") {
|
|
25394
|
+
const body = steps.filter((s) => s.stepNumber > stepNum && s.stepNumber <= victim.endStep);
|
|
25395
|
+
if (body.length) {
|
|
25396
|
+
const span = body.length === 1 ? `step ${body[0].stepNumber}` : `steps ${body[0].stepNumber}-${body[body.length - 1].stepNumber}`;
|
|
25397
|
+
throw new Error(
|
|
25398
|
+
`Cannot delete narrative step ${stepNum}: it is a ${victim.type} header and ${span} ${body.length === 1 ? "is" : "are"} still its body. Deleting it would leave them in place with no ${victim.type} around them \u2014 a change of meaning nothing later reports. Dissolve the region first: retype step ${stepNum} to a type that carries no region (the region fields are dropped and reported), then delete it.`
|
|
25399
|
+
);
|
|
25400
|
+
}
|
|
25401
|
+
}
|
|
25223
25402
|
const referrers = steps.filter((s) => s.stepNumber !== stepNum).map((s) => ({ n: s.stepNumber, refs: jumpRefsTo(s, stepNum) })).filter((r) => r.refs.length > 0);
|
|
25224
25403
|
if (referrers.length) {
|
|
25225
25404
|
throw new Error(
|
|
@@ -25232,6 +25411,11 @@ var init_specs2 = __esm({
|
|
|
25232
25411
|
stepNum,
|
|
25233
25412
|
-1
|
|
25234
25413
|
));
|
|
25414
|
+
} else {
|
|
25415
|
+
const present = steps.length ? ` \u2014 it has steps ${steps[0].stepNumber}-${steps[steps.length - 1].stepNumber}` : " \u2014 it has no steps";
|
|
25416
|
+
throw new Error(
|
|
25417
|
+
`Refusing to delete narrative step ${stepNum}: this narrative has no step ${stepNum}${present}. Step deltas apply in ascending order against the numbering earlier entries of the same delta left behind, so a later delete can address a step that has already moved.`
|
|
25418
|
+
);
|
|
25235
25419
|
}
|
|
25236
25420
|
} else if (deltaStep.action === "insert") {
|
|
25237
25421
|
const capture = deltaStep.captureJumps === true;
|
|
@@ -25255,10 +25439,9 @@ var init_specs2 = __esm({
|
|
|
25255
25439
|
const idx = steps.findIndex((s) => s.stepNumber === stepNum);
|
|
25256
25440
|
if (idx !== -1) {
|
|
25257
25441
|
const { action, remove: remove2, ...cleanStep } = deltaStep;
|
|
25258
|
-
steps[idx]
|
|
25259
|
-
|
|
25260
|
-
|
|
25261
|
-
}, deltaStep);
|
|
25442
|
+
const stored = steps[idx];
|
|
25443
|
+
const merged = withUnset(retargetByLabel(mergeElement(stored, cleanStep), cleanStep), deltaStep);
|
|
25444
|
+
steps[idx] = rebuildOnRetype(stored, cleanStep, merged, methodName);
|
|
25262
25445
|
} else {
|
|
25263
25446
|
const { action, remove: remove2, ...cleanStep } = deltaStep;
|
|
25264
25447
|
steps.push(withUnset(cleanStep, deltaStep));
|
|
@@ -25289,12 +25472,11 @@ var init_specs2 = __esm({
|
|
|
25289
25472
|
const existingMethod = merged[idx];
|
|
25290
25473
|
let narrative = existingMethod.narrative ? [...existingMethod.narrative] : [];
|
|
25291
25474
|
if (Array.isArray(deltaMethod.narrative)) {
|
|
25292
|
-
narrative = deltaMethod.narrative.length === 0 ? [] : mergeNarrative(narrative, deltaMethod.narrative);
|
|
25475
|
+
narrative = deltaMethod.narrative.length === 0 ? [] : mergeNarrative(String(deltaMethod.name), narrative, deltaMethod.narrative);
|
|
25293
25476
|
}
|
|
25294
25477
|
const { narrative: _, ...cleanMethod } = deltaMethod;
|
|
25295
25478
|
merged[idx] = withUnset({
|
|
25296
|
-
...existingMethod,
|
|
25297
|
-
...cleanMethod,
|
|
25479
|
+
...mergeElement(existingMethod, cleanMethod),
|
|
25298
25480
|
...deltaMethod.ext !== void 0 ? { ext: mergeExt(existingMethod.ext, deltaMethod.ext) } : {},
|
|
25299
25481
|
narrative
|
|
25300
25482
|
}, deltaMethod);
|
|
@@ -25316,12 +25498,8 @@ var init_specs2 = __esm({
|
|
|
25316
25498
|
merged.splice(idx, 1);
|
|
25317
25499
|
} else {
|
|
25318
25500
|
merged[idx] = withUnset({
|
|
25319
|
-
...merged[idx],
|
|
25320
|
-
...deltaItem,
|
|
25321
|
-
...deltaItem.ext !== void 0 ? { ext: mergeExt(merged[idx].ext, deltaItem.ext) } : {},
|
|
25322
|
-
// An interface method's findings upsert and delete by code, like
|
|
25323
|
-
// lint.allow; an empty list still clears them outright.
|
|
25324
|
-
...Array.isArray(deltaItem.findings) && deltaItem.findings.length > 0 ? { findings: mergeIdentifiedArray("findings", merged[idx].findings ?? [], deltaItem.findings) } : {}
|
|
25501
|
+
...mergeElement(merged[idx], deltaItem),
|
|
25502
|
+
...deltaItem.ext !== void 0 ? { ext: mergeExt(merged[idx].ext, deltaItem.ext) } : {}
|
|
25325
25503
|
}, deltaItem);
|
|
25326
25504
|
}
|
|
25327
25505
|
} else {
|
|
@@ -25340,7 +25518,7 @@ var init_specs2 = __esm({
|
|
|
25340
25518
|
if (deltaItem.remove === true || deltaItem.action === "delete") {
|
|
25341
25519
|
merged.splice(idx, 1);
|
|
25342
25520
|
} else {
|
|
25343
|
-
merged[idx] = withUnset(
|
|
25521
|
+
merged[idx] = withUnset(mergeElement(merged[idx], deltaItem), deltaItem);
|
|
25344
25522
|
}
|
|
25345
25523
|
} else {
|
|
25346
25524
|
assertUnmatchedIsAnAddition(deltaItem, keyOf(deltaItem), merged.map(keyOf), "entry");
|
|
@@ -25359,10 +25537,7 @@ var init_specs2 = __esm({
|
|
|
25359
25537
|
if (deltaItem.remove === true || deltaItem.action === "delete") {
|
|
25360
25538
|
merged.splice(idx, 1);
|
|
25361
25539
|
} else {
|
|
25362
|
-
merged[idx] = withUnset(
|
|
25363
|
-
...merged[idx],
|
|
25364
|
-
...deltaItem
|
|
25365
|
-
}, deltaItem);
|
|
25540
|
+
merged[idx] = withUnset(mergeElement(merged[idx], deltaItem), deltaItem);
|
|
25366
25541
|
}
|
|
25367
25542
|
} else {
|
|
25368
25543
|
assertUnmatchedIsAnAddition(deltaItem, piKey(deltaItem), merged.map(piKey), "publicInterface");
|
|
@@ -25380,7 +25555,7 @@ var init_specs2 = __esm({
|
|
|
25380
25555
|
const isDelete = deltaItem?.remove === true || deltaItem?.action === "delete";
|
|
25381
25556
|
if (idx !== -1) {
|
|
25382
25557
|
if (isDelete) merged.splice(idx, 1);
|
|
25383
|
-
else merged[idx] = withUnset(
|
|
25558
|
+
else merged[idx] = withUnset(mergeElement(merged[idx], deltaItem), deltaItem);
|
|
25384
25559
|
} else {
|
|
25385
25560
|
if (key !== null) {
|
|
25386
25561
|
assertUnmatchedIsAnAddition(
|
|
@@ -26389,7 +26564,7 @@ var init_status = __esm({
|
|
|
26389
26564
|
// src/core/authoring.ts
|
|
26390
26565
|
function candidateOptions() {
|
|
26391
26566
|
try {
|
|
26392
|
-
const config =
|
|
26567
|
+
const config = loadProjectConfig2();
|
|
26393
26568
|
return config ? { rules: config.rules, projectType: config.projectType } : {};
|
|
26394
26569
|
} catch {
|
|
26395
26570
|
return {};
|
|
@@ -26422,7 +26597,7 @@ var init_authoring = __esm({
|
|
|
26422
26597
|
init_specs2();
|
|
26423
26598
|
init_validation();
|
|
26424
26599
|
init_candidate();
|
|
26425
|
-
|
|
26600
|
+
init_core();
|
|
26426
26601
|
}
|
|
26427
26602
|
});
|
|
26428
26603
|
|
|
@@ -27718,7 +27893,7 @@ NOTICE:
|
|
|
27718
27893
|
inputSchema: {
|
|
27719
27894
|
kind: import_zod11.z.enum(["system", "subsystem", "component", "interface", "implementation", "type"]).describe("The spec kind to update (system = the singleton L0 \u2014 vision, boundaries, globalRequirements, databases, and publicInterfaces: the project gateway surface, each entry {id, name, subsystem, component, type, details, audience: project|department|instance|partner|external}; id is informational)"),
|
|
27720
27895
|
id: import_zod11.z.string().describe("The ID of the spec to update (namespaced if needed)"),
|
|
27721
|
-
delta: import_zod11.z.record(import_zod11.z.any()).describe(`The partial fields to merge into the spec. ARRAYS UPSERT, they do not replace: an array whose elements carry an identity is merged element-by-element, so a delta naming ONE element leaves the others intact. Identity is "name" or "id" by default, and per field: dispatch by "capability", lifecycle by phase+component+method, emits/subscribesTo by topic+event, trustedLinks by "subsystem", invariants and patterns by "id", lint.allow by "code", an interface method's findings by "code", boundaries by "name", globalRequirements by "description". Add "action: 'delete'" (or "remove: true") alongside that identity to REMOVE an element \u2014 including a stale lint allow. Arrays of plain STRINGS (owns, dependsOn, guarantees) carry no per-element identity and are replaced wholesale; pass [] to clear any array outright. To REMOVE an optional field entirely, list it in "unset": e.g. {"unset": ["basePath", "variant"]} \u2014 passing null/undefined means "no change" (they are skipped), and writing "" would leave the field present but empty, which is a different and usually wrong spec. Unsetting a required field is refused by schema validation, which names it. For narrative steps, match by "stepNumber" and use "action: 'insert'" (shifts subsequent steps up) or "action: 'delete'" (shifts subsequent steps down and removes it). Renumbering RELOCATES every flow jump field (onTrueStep/onFalseStep/cases.step/defaultStep/endStep/catches.step/finallyStep/toStep) in the same narrative
|
|
27896
|
+
delta: import_zod11.z.record(import_zod11.z.any()).describe(`The partial fields to merge into the spec. ARRAYS UPSERT, they do not replace: an array whose elements carry an identity is merged element-by-element, so a delta naming ONE element leaves the others intact. Identity is "name" or "id" by default, and per field: dispatch by "capability", lifecycle by phase+component+method, emits/subscribesTo by topic+event, trustedLinks by "subsystem", invariants and patterns by "id", lint.allow by "code", an interface method's findings by "code", boundaries by "name", globalRequirements by "description", switch cases by "value", try catches by "error". Identity merging applies at EVERY depth, including an array INSIDE an element (a method's params, a step's catches). Add "action: 'delete'" (or "remove: true") alongside that identity to REMOVE an element \u2014 including a stale lint allow. Arrays of plain STRINGS (owns, dependsOn, guarantees) carry no per-element identity and are replaced wholesale; pass [] to clear any array outright. To REMOVE an optional field entirely, list it in "unset": e.g. {"unset": ["basePath", "variant"]} \u2014 passing null/undefined means "no change" (they are skipped), and writing "" would leave the field present but empty, which is a different and usually wrong spec. Unsetting a required field is refused by schema validation, which names it. For narrative steps, match by "stepNumber" and use "action: 'insert'" (shifts subsequent steps up) or "action: 'delete'" (shifts subsequent steps down and removes it). Step entries apply in ASCENDING stepNumber order, each against the numbering the earlier entries of the SAME delta left behind \u2014 delete step 3 and step 7 becomes step 6 \u2014 so prefer labels, and restate the step's "label" or "description" on a delete to have it checked against the step actually addressed. Renumbering RELOCATES every flow jump field (onTrueStep/onFalseStep/cases.step/defaultStep/endStep/catches.step/finallyStep/toStep) in the same narrative. A delete is REJECTED when the narrative has no such step, when a jump still targets it (retarget the referrers first), when a restated label/description does not match, or when it is a loop/try/parallel header whose body would be left standing (retype the header first to dissolve the region, then delete it). Changing a step's "type" REBUILDS it for the new type: its description and label are kept and every field the new type cannot carry is dropped (returned as a NOTICE); a delta that retypes AND sets such a field is refused. A step delta is also refused when it carries a marker the merge does not recognise: a non-boolean "remove", an "action" that is neither "insert" nor "delete", a "captureJumps" outside an insert, or no "stepNumber" to address. Inserting AT a jump target relocates those jumps past the inserted step by default (a NOTICE is returned) \u2014 add "captureJumps": true on the inserted step to retarget entry jumps onto it (loop/try endStep region tails always relocate with the body and are never captured). Every jump field has a "*Label" twin (toLabel, onFalseLabel, endLabel, \u2026, and "label" on a cases/catches entry) resolved against step labels AFTER the merge, so a delta may anchor on a label only pre-existing steps carry; a label the delta supplies REPLACES the stored number it twins, while setting the number and its label together in one delta is refused as a contradiction. Reference ids in deltas may use LOCAL names \u2014 they are qualified against the spec's namespace exactly as the loader would. Per-spec lint suppression: set "lint: { allow: [{ code, reason }] }" to silence a WARNING code on this spec only (errors always surface; stale allows are flagged).`)
|
|
27722
27897
|
}
|
|
27723
27898
|
},
|
|
27724
27899
|
({ kind, id, delta }) => {
|