@codyswann/lisa 4.17.19 → 4.19.0

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.
Files changed (102) hide show
  1. package/dist/cli/ui-config-write-document.d.ts +53 -0
  2. package/dist/cli/ui-config-write-document.d.ts.map +1 -0
  3. package/dist/cli/ui-config-write-document.js +212 -0
  4. package/dist/cli/ui-config-write-document.js.map +1 -0
  5. package/dist/cli/ui-config-write-patch-plan.d.ts +30 -0
  6. package/dist/cli/ui-config-write-patch-plan.d.ts.map +1 -0
  7. package/dist/cli/ui-config-write-patch-plan.js +151 -0
  8. package/dist/cli/ui-config-write-patch-plan.js.map +1 -0
  9. package/dist/cli/ui-config-write-persistence.d.ts +19 -0
  10. package/dist/cli/ui-config-write-persistence.d.ts.map +1 -0
  11. package/dist/cli/ui-config-write-persistence.js +294 -0
  12. package/dist/cli/ui-config-write-persistence.js.map +1 -0
  13. package/dist/cli/ui-config-write-property-edits.d.ts +40 -0
  14. package/dist/cli/ui-config-write-property-edits.d.ts.map +1 -0
  15. package/dist/cli/ui-config-write-property-edits.js +250 -0
  16. package/dist/cli/ui-config-write-property-edits.js.map +1 -0
  17. package/dist/cli/ui-config-write-provenance.d.ts +12 -0
  18. package/dist/cli/ui-config-write-provenance.d.ts.map +1 -0
  19. package/dist/cli/ui-config-write-provenance.js +29 -0
  20. package/dist/cli/ui-config-write-provenance.js.map +1 -0
  21. package/dist/cli/ui-config-write-root-identity.d.ts +25 -0
  22. package/dist/cli/ui-config-write-root-identity.d.ts.map +1 -0
  23. package/dist/cli/ui-config-write-root-identity.js +66 -0
  24. package/dist/cli/ui-config-write-root-identity.js.map +1 -0
  25. package/dist/cli/ui-config-write.d.ts.map +1 -1
  26. package/dist/cli/ui-config-write.js +47 -92
  27. package/dist/cli/ui-config-write.js.map +1 -1
  28. package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
  29. package/dist/core/lisa-owned-hash-ledger.js +14 -0
  30. package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
  31. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  32. package/dist/core/upstream-evidence-manifest.js +21 -5
  33. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  34. package/dist/sync/json-path.d.ts +10 -0
  35. package/dist/sync/json-path.d.ts.map +1 -1
  36. package/dist/sync/json-path.js +14 -0
  37. package/dist/sync/json-path.js.map +1 -1
  38. package/dist/sync/sync-population.d.ts +6 -0
  39. package/dist/sync/sync-population.d.ts.map +1 -1
  40. package/dist/sync/sync-population.js +8 -0
  41. package/dist/sync/sync-population.js.map +1 -1
  42. package/dist/utils/atomic-file-write.d.ts +5 -4
  43. package/dist/utils/atomic-file-write.d.ts.map +1 -1
  44. package/dist/utils/atomic-file-write.js +3 -0
  45. package/dist/utils/atomic-file-write.js.map +1 -1
  46. package/expo/copy-overwrite/scripts/bdd/baseline.mjs +10 -2
  47. package/expo/copy-overwrite/scripts/bdd/render.mjs +3 -2
  48. package/expo/copy-overwrite/scripts/bdd-matrix.mjs +3 -3
  49. package/package.json +7 -2
  50. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  51. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  52. package/plugins/lisa-agy/plugin.json +1 -1
  53. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  54. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  55. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  56. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  57. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  58. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  59. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  60. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  61. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  62. package/plugins/lisa-expo-agy/plugin.json +1 -1
  63. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  64. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  65. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  66. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  67. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  68. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  69. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  70. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  71. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  72. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  73. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  74. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  75. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  76. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  77. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  78. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  79. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  80. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  81. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  82. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  83. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  84. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  85. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  86. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  87. package/plugins/lisa-rails-agy/plugin.json +1 -1
  88. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  89. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  90. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  91. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  92. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  93. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  94. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  95. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  96. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  97. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  98. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  99. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  100. package/scripts/check-ui-demo-data.mjs +102 -0
  101. package/ui/README.md +94 -8
  102. package/ui/index.html +901 -115
@@ -0,0 +1,53 @@
1
+ import { type JsonObject, type JsonValue } from "../sync/json-path.js";
2
+ /** Minimum source image needed for one surgical render. */
3
+ export interface ConfigDocumentSource {
4
+ /** Fixed public filename used only in safe diagnostics. */
5
+ readonly filename: string;
6
+ /** Strict UTF-8 JSON source. */
7
+ readonly text: string;
8
+ /** Semantic source document paired with the text. */
9
+ readonly document: JsonObject;
10
+ }
11
+ /** Fully checked textual and semantic prospective document. */
12
+ export interface RenderedConfigDocument {
13
+ /** Surgical strict-JSON text ready for atomic persistence. */
14
+ readonly text: string;
15
+ /** Reparsing result proven structurally equal to the requested edits. */
16
+ readonly document: JsonObject;
17
+ /** Whether any owner set or non-owner cleanup changed the source. */
18
+ readonly changed: boolean;
19
+ }
20
+ /**
21
+ * Parse one strict, unambiguous object document.
22
+ *
23
+ * `JSON.parse` deliberately accepts duplicate object properties using
24
+ * last-value-wins semantics, while a positional syntax-tree lookup can select
25
+ * an earlier occurrence. Rejecting duplicates prevents those two views from
26
+ * claiming a successful write to different semantic documents.
27
+ * @param text - Strict JSON source or rendered candidate
28
+ * @param filename - Safe fixed filename used in diagnostics
29
+ * @returns Parsed JSON object with exactly one value per property
30
+ */
31
+ export declare function parseConfigDocument(text: string, filename: string): JsonObject;
32
+ /**
33
+ * Parse strict JSON while refusing recursively duplicated property names.
34
+ *
35
+ * This remains separate from the object-document contract because HTTP input
36
+ * must reject ambiguity before payload shape validation, while preserving the
37
+ * existing shape-specific 400 responses for valid arrays and scalars.
38
+ * @param text - Strict JSON source from a bounded, fatal UTF-8 decode
39
+ * @param filename - Safe fixed label used in diagnostics
40
+ * @returns Parsed JSON value with exactly one value per object property
41
+ */
42
+ export declare function parseUnambiguousJson(text: string, filename: string): unknown;
43
+ /**
44
+ * Apply owner sets after non-owner removals and prove both representations
45
+ * agree. Ordering is significant for overlapping ancestor/descendant inputs.
46
+ * @param source - Strict source image to edit
47
+ * @param removals - Routed owner paths removed from this non-owner document
48
+ * @param changes - Routed values owned by this document
49
+ * @param exactRemovals - Exact property paths whose segments may contain dots
50
+ * @returns Reparsing-verified prospective document and surgical text
51
+ */
52
+ export declare function renderConfigChanges(source: ConfigDocumentSource, removals: readonly string[], changes: Readonly<Record<string, JsonValue>>, exactRemovals?: readonly (readonly string[])[]): RenderedConfigDocument;
53
+ //# sourceMappingURL=ui-config-write-document.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui-config-write-document.d.ts","sourceRoot":"","sources":["../../src/cli/ui-config-write-document.ts"],"names":[],"mappings":"AAQA,OAAO,EAIL,KAAK,UAAU,EACf,KAAK,SAAS,EACf,MAAM,sBAAsB,CAAC;AAM9B,2DAA2D;AAC3D,MAAM,WAAW,oBAAoB;IACnC,2DAA2D;IAC3D,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,gCAAgC;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,qDAAqD;IACrD,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC;CAC/B;AAED,+DAA+D;AAC/D,MAAM,WAAW,sBAAsB;IACrC,8DAA8D;IAC9D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,yEAAyE;IACzE,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC;IAC9B,qEAAqE;IACrE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B;AASD;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,GACf,UAAU,CAMZ;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAU5E;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,oBAAoB,EAC5B,QAAQ,EAAE,SAAS,MAAM,EAAE,EAC3B,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,EAC5C,aAAa,GAAE,SAAS,CAAC,SAAS,MAAM,EAAE,CAAC,EAAO,GACjD,sBAAsB,CAiCxB"}
@@ -0,0 +1,212 @@
1
+ /**
2
+ * Strict, ambiguity-free surgical editing for UI config documents.
3
+ *
4
+ * Strict parsing and the prospective semantic edit stay paired here so the
5
+ * source-relative planner can be checked by reparsing before publication.
6
+ * @module cli/ui-config-write-document
7
+ */
8
+ import { applyEdits, parseTree } from "jsonc-parser";
9
+ import { getAtPropertyPath, isJsonObject, jsonEquals, } from "../sync/json-path.js";
10
+ import { planConfigTextEdits, } from "./ui-config-write-patch-plan.js";
11
+ /**
12
+ * Parse one strict, unambiguous object document.
13
+ *
14
+ * `JSON.parse` deliberately accepts duplicate object properties using
15
+ * last-value-wins semantics, while a positional syntax-tree lookup can select
16
+ * an earlier occurrence. Rejecting duplicates prevents those two views from
17
+ * claiming a successful write to different semantic documents.
18
+ * @param text - Strict JSON source or rendered candidate
19
+ * @param filename - Safe fixed filename used in diagnostics
20
+ * @returns Parsed JSON object with exactly one value per property
21
+ */
22
+ export function parseConfigDocument(text, filename) {
23
+ const parsed = parseUnambiguousJson(text, filename);
24
+ if (!isJsonObject(parsed)) {
25
+ throw new Error(`${filename} must contain a JSON object`);
26
+ }
27
+ return parsed;
28
+ }
29
+ /**
30
+ * Parse strict JSON while refusing recursively duplicated property names.
31
+ *
32
+ * This remains separate from the object-document contract because HTTP input
33
+ * must reject ambiguity before payload shape validation, while preserving the
34
+ * existing shape-specific 400 responses for valid arrays and scalars.
35
+ * @param text - Strict JSON source from a bounded, fatal UTF-8 decode
36
+ * @param filename - Safe fixed label used in diagnostics
37
+ * @returns Parsed JSON value with exactly one value per object property
38
+ */
39
+ export function parseUnambiguousJson(text, filename) {
40
+ const parsed = JSON.parse(text);
41
+ const tree = parseTree(text, [], {
42
+ allowTrailingComma: false,
43
+ disallowComments: true,
44
+ });
45
+ if (tree === undefined || hasDuplicateObjectKey(tree)) {
46
+ throw new Error(`${filename} contains duplicate object keys`);
47
+ }
48
+ return parsed;
49
+ }
50
+ /**
51
+ * Apply owner sets after non-owner removals and prove both representations
52
+ * agree. Ordering is significant for overlapping ancestor/descendant inputs.
53
+ * @param source - Strict source image to edit
54
+ * @param removals - Routed owner paths removed from this non-owner document
55
+ * @param changes - Routed values owned by this document
56
+ * @param exactRemovals - Exact property paths whose segments may contain dots
57
+ * @returns Reparsing-verified prospective document and surgical text
58
+ */
59
+ export function renderConfigChanges(source, removals, changes, exactRemovals = []) {
60
+ const edits = [
61
+ ...removals.map(key => ({ kind: "remove", path: key.split(".") })),
62
+ ...exactRemovals.map(path => ({ kind: "remove", path })),
63
+ ...Object.entries(changes).map(([key, value]) => ({ kind: "set", path: key.split("."), value })),
64
+ ];
65
+ const prospective = edits.reduce((state, edit) => applySemanticEdit(state, edit), {
66
+ document: source.document,
67
+ changed: false,
68
+ touched: [],
69
+ });
70
+ if (!prospective.changed) {
71
+ return { text: source.text, document: source.document, changed: false };
72
+ }
73
+ const tree = requireConfigTree(source.text, source.filename);
74
+ const textEdits = planConfigTextEdits(source.text, tree, source.document, prospective.document, prospective.touched);
75
+ const renderedText = applyEdits(source.text, [...textEdits]);
76
+ const reparsed = parseConfigDocument(renderedText, source.filename);
77
+ if (!jsonEquals(reparsed, prospective.document)) {
78
+ throw new Error(`${source.filename} surgical edit was ambiguous`);
79
+ }
80
+ return { text: renderedText, document: reparsed, changed: true };
81
+ }
82
+ /**
83
+ * Detect ambiguity recursively because a changed path may sit below a duplicate
84
+ * ancestor even when its own final property appears only once.
85
+ * @param node - Strict JSON syntax tree node
86
+ * @returns Whether any object contains the same property more than once
87
+ */
88
+ function hasDuplicateObjectKey(node) {
89
+ if (node.type === "object") {
90
+ const keys = (node.children ?? [])
91
+ .map(property => property.children?.[0]?.value)
92
+ .filter((key) => typeof key === "string");
93
+ if (new Set(keys).size !== keys.length) {
94
+ return true;
95
+ }
96
+ }
97
+ return (node.children ?? []).some(hasDuplicateObjectKey);
98
+ }
99
+ /**
100
+ * Apply one edit to the prospective object before planning source ranges.
101
+ * @param state - Semantic result accumulated from earlier ordered edits
102
+ * @param edit - Owner set or non-owner removal
103
+ * @returns Prospective state plus only the edits that changed semantics
104
+ */
105
+ function applySemanticEdit(state, edit) {
106
+ if (edit.kind === "remove") {
107
+ assertRemovalPathIsReachable(state.document, edit.path);
108
+ }
109
+ const current = getAtPropertyPath(state.document, edit.path);
110
+ if ((edit.kind === "remove" && current === undefined) ||
111
+ (edit.kind === "set" && jsonEquals(current, edit.value))) {
112
+ return state;
113
+ }
114
+ return {
115
+ document: edit.kind === "remove"
116
+ ? removeAtPropertyPath(state.document, edit.path)
117
+ : setAtPropertyPath(state.document, edit.path, edit.value),
118
+ changed: true,
119
+ touched: [...state.touched, edit],
120
+ };
121
+ }
122
+ /**
123
+ * Reparse the already validated source into the positional tree used for edits.
124
+ * @param text - Original strict JSON bytes decoded as text
125
+ * @param filename - Safe fixed filename used in diagnostics
126
+ * @returns Root object node whose offsets all refer to the original text
127
+ */
128
+ function requireConfigTree(text, filename) {
129
+ const tree = parseTree(text, [], {
130
+ allowTrailingComma: false,
131
+ disallowComments: true,
132
+ });
133
+ if (tree?.type !== "object") {
134
+ throw new Error(`${filename} must contain a JSON object`);
135
+ }
136
+ return tree;
137
+ }
138
+ /**
139
+ * Refuse descendant cleanup when a scalar or array ancestor shadows its owner.
140
+ * Deleting that ancestor would also delete data outside the routed path, while
141
+ * treating the cleanup as a no-op would leave overlay precedence unchanged.
142
+ * @param root - Non-owner document being reconciled
143
+ * @param propertyPath - Exact routed owner path that must become absent here
144
+ */
145
+ function assertRemovalPathIsReachable(root, propertyPath) {
146
+ const ancestors = propertyPath.slice(0, -1);
147
+ assertObjectAncestors(root, ancestors);
148
+ }
149
+ /**
150
+ * Walk only present ancestors: an absent branch cannot shadow anything, while
151
+ * every present branch must remain an object for exact descendant removal.
152
+ * @param node - Present object at the current path depth
153
+ * @param segments - Remaining ancestor segments before the routed leaf
154
+ */
155
+ function assertObjectAncestors(node, segments) {
156
+ const [head, ...rest] = segments;
157
+ if (head === undefined)
158
+ return;
159
+ const child = node[head];
160
+ if (child === undefined)
161
+ return;
162
+ if (!isJsonObject(child)) {
163
+ throw new Error("Config owner cleanup is blocked by a non-object ancestor");
164
+ }
165
+ assertObjectAncestors(child, rest);
166
+ }
167
+ /**
168
+ * Remove exactly one property path while retaining every ancestor and sibling.
169
+ * @param root - Prospective object to copy
170
+ * @param propertyPath - Exact path being removed from the non-owner document
171
+ * @returns Object without that path and with unrelated siblings intact
172
+ */
173
+ function removeAtPropertyPath(root, propertyPath) {
174
+ const [head, ...rest] = propertyPath;
175
+ if (head === undefined) {
176
+ throw new Error("Config root removal is not writable");
177
+ }
178
+ if (rest.length === 0) {
179
+ const { [head]: _removed, ...remaining } = root;
180
+ return remaining;
181
+ }
182
+ const child = root[head];
183
+ if (!isJsonObject(child)) {
184
+ return root;
185
+ }
186
+ return { ...root, [head]: removeAtPropertyPath(child, rest) };
187
+ }
188
+ /**
189
+ * Immutably set an exact property path, creating missing object ancestors.
190
+ * @param root - Object to copy
191
+ * @param propertyPath - Exact decoded property names
192
+ * @param value - JSON value to write
193
+ * @returns Updated object
194
+ */
195
+ function setAtPropertyPath(root, propertyPath, value) {
196
+ const [head, ...rest] = propertyPath;
197
+ if (head === undefined) {
198
+ if (!isJsonObject(value)) {
199
+ throw new Error("Config root replacement requires an object value");
200
+ }
201
+ return value;
202
+ }
203
+ if (rest.length === 0) {
204
+ return { ...root, [head]: value };
205
+ }
206
+ const child = root[head];
207
+ return {
208
+ ...root,
209
+ [head]: setAtPropertyPath(isJsonObject(child) ? child : {}, rest, value),
210
+ };
211
+ }
212
+ //# sourceMappingURL=ui-config-write-document.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui-config-write-document.js","sourceRoot":"","sources":["../../src/cli/ui-config-write-document.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAyB,MAAM,cAAc,CAAC;AAC5E,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,UAAU,GAGX,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,mBAAmB,GAEpB,MAAM,iCAAiC,CAAC;AA6BzC;;;;;;;;;;GAUG;AACH,MAAM,UAAU,mBAAmB,CACjC,IAAY,EACZ,QAAgB;IAEhB,MAAM,MAAM,GAAG,oBAAoB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACpD,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,GAAG,QAAQ,6BAA6B,CAAC,CAAC;IAC5D,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAY,EAAE,QAAgB;IACjE,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAY,CAAC;IAC3C,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,EAAE,EAAE,EAAE;QAC/B,kBAAkB,EAAE,KAAK;QACzB,gBAAgB,EAAE,IAAI;KACvB,CAAC,CAAC;IACH,IAAI,IAAI,KAAK,SAAS,IAAI,qBAAqB,CAAC,IAAI,CAAC,EAAE,CAAC;QACtD,MAAM,IAAI,KAAK,CAAC,GAAG,QAAQ,iCAAiC,CAAC,CAAC;IAChE,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CACjC,MAA4B,EAC5B,QAA2B,EAC3B,OAA4C,EAC5C,gBAAgD,EAAE;IAElD,MAAM,KAAK,GAAkC;QAC3C,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAU,CAAC;QAC3E,GAAG,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAU,CAAC;QACjE,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,GAAG,CAC5B,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,CAAU,CAC1E;KACF,CAAC;IACF,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,CAC9B,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,iBAAiB,CAAC,KAAK,EAAE,IAAI,CAAC,EAC/C;QACE,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,OAAO,EAAE,KAAK;QACd,OAAO,EAAE,EAAE;KACZ,CACF,CAAC;IACF,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;QACzB,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC1E,CAAC;IACD,MAAM,IAAI,GAAG,iBAAiB,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC7D,MAAM,SAAS,GAAG,mBAAmB,CACnC,MAAM,CAAC,IAAI,EACX,IAAI,EACJ,MAAM,CAAC,QAAQ,EACf,WAAW,CAAC,QAAQ,EACpB,WAAW,CAAC,OAAO,CACpB,CAAC;IACF,MAAM,YAAY,GAAG,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC;IAC7D,MAAM,QAAQ,GAAG,mBAAmB,CAAC,YAAY,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IACpE,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC;QAChD,MAAM,IAAI,KAAK,CAAC,GAAG,MAAM,CAAC,QAAQ,8BAA8B,CAAC,CAAC;IACpE,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AACnE,CAAC;AAED;;;;;GAKG;AACH,SAAS,qBAAqB,CAAC,IAAc;IAC3C,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC3B,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC;aAC/B,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC;aAC9C,MAAM,CAAC,CAAC,GAAG,EAAiB,EAAE,CAAC,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC;QAC3D,IAAI,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;YACvC,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;AAC3D,CAAC;AAED;;;;;GAKG;AACH,SAAS,iBAAiB,CACxB,KAAoB,EACpB,IAAwB;IAExB,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC3B,4BAA4B,CAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1D,CAAC;IACD,MAAM,OAAO,GAAG,iBAAiB,CAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7D,IACE,CAAC,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,OAAO,KAAK,SAAS,CAAC;QACjD,CAAC,IAAI,CAAC,IAAI,KAAK,KAAK,IAAI,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EACxD,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO;QACL,QAAQ,EACN,IAAI,CAAC,IAAI,KAAK,QAAQ;YACpB,CAAC,CAAC,oBAAoB,CAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC;YACjD,CAAC,CAAC,iBAAiB,CAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC;QAC9D,OAAO,EAAE,IAAI;QACb,OAAO,EAAE,CAAC,GAAG,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC;KAClC,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,SAAS,iBAAiB,CAAC,IAAY,EAAE,QAAgB;IACvD,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,EAAE,EAAE,EAAE;QAC/B,kBAAkB,EAAE,KAAK;QACzB,gBAAgB,EAAE,IAAI;KACvB,CAAC,CAAC;IACH,IAAI,IAAI,EAAE,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,GAAG,QAAQ,6BAA6B,CAAC,CAAC;IAC5D,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;GAMG;AACH,SAAS,4BAA4B,CACnC,IAAgB,EAChB,YAA+B;IAE/B,MAAM,SAAS,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC5C,qBAAqB,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;AACzC,CAAC;AAED;;;;;GAKG;AACH,SAAS,qBAAqB,CAC5B,IAAgB,EAChB,QAA2B;IAE3B,MAAM,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,GAAG,QAAQ,CAAC;IACjC,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO;IAC/B,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;IACzB,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO;IAChC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC;IAC9E,CAAC;IACD,qBAAqB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;AACrC,CAAC;AAED;;;;;GAKG;AACH,SAAS,oBAAoB,CAC3B,IAAgB,EAChB,YAA+B;IAE/B,MAAM,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,GAAG,YAAY,CAAC;IACrC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IACzD,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,GAAG,SAAS,EAAE,GAAG,IAAI,CAAC;QAChD,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;IACzB,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,EAAE,GAAG,IAAI,EAAE,CAAC,IAAI,CAAC,EAAE,oBAAoB,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC;AAChE,CAAC;AAED;;;;;;GAMG;AACH,SAAS,iBAAiB,CACxB,IAAgB,EAChB,YAA+B,EAC/B,KAAgB;IAEhB,MAAM,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,GAAG,YAAY,CAAC;IACrC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;QACtE,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO,EAAE,GAAG,IAAI,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC;IACpC,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;IACzB,OAAO;QACL,GAAG,IAAI;QACP,CAAC,IAAI,CAAC,EAAE,iBAAiB,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC;KACzE,CAAC;AACJ,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * @file ui-config-write-patch-plan.ts
3
+ * @description Deterministic non-overlapping patch planning for UI config JSON.
4
+ * @module cli/ui-config-write-patch-plan
5
+ */
6
+ import { type Edit as JsonTextEdit, type Node as JsonNode } from "jsonc-parser";
7
+ import { type JsonObject, type JsonValue } from "../sync/json-path.js";
8
+ /** One requested semantic mutation in endpoint order. */
9
+ export type ConfigDocumentEdit = {
10
+ readonly kind: "remove";
11
+ readonly path: readonly string[];
12
+ } | {
13
+ readonly kind: "set";
14
+ readonly path: readonly string[];
15
+ readonly value: JsonValue;
16
+ };
17
+ /**
18
+ * Plan every changed path against one immutable original syntax tree.
19
+ *
20
+ * Missing descendants collapse to the first absent/non-object branch, so a
21
+ * formatter never needs to borrow and replace an unrelated sibling for context.
22
+ * @param text - Original strict JSON text
23
+ * @param tree - Original syntax tree whose offsets refer to `text`
24
+ * @param source - Original semantic document
25
+ * @param prospective - Final semantic document after ordered edits
26
+ * @param touched - Ordered edits that changed semantics
27
+ * @returns Deterministic non-overlapping original-offset text edits
28
+ */
29
+ export declare function planConfigTextEdits(text: string, tree: JsonNode, source: JsonObject, prospective: JsonObject, touched: readonly ConfigDocumentEdit[]): readonly JsonTextEdit[];
30
+ //# sourceMappingURL=ui-config-write-patch-plan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui-config-write-patch-plan.d.ts","sourceRoot":"","sources":["../../src/cli/ui-config-write-patch-plan.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAEL,KAAK,IAAI,IAAI,YAAY,EACzB,KAAK,IAAI,IAAI,QAAQ,EACtB,MAAM,cAAc,CAAC;AACtB,OAAO,EAGL,KAAK,UAAU,EACf,KAAK,SAAS,EACf,MAAM,sBAAsB,CAAC;AAQ9B,yDAAyD;AACzD,MAAM,MAAM,kBAAkB,GAC1B;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,GAC7D;IACE,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;CAC3B,CAAC;AAEN;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,QAAQ,EACd,MAAM,EAAE,UAAU,EAClB,WAAW,EAAE,UAAU,EACvB,OAAO,EAAE,SAAS,kBAAkB,EAAE,GACrC,SAAS,YAAY,EAAE,CAazB"}
@@ -0,0 +1,151 @@
1
+ /**
2
+ * @file ui-config-write-patch-plan.ts
3
+ * @description Deterministic non-overlapping patch planning for UI config JSON.
4
+ * @module cli/ui-config-write-patch-plan
5
+ */
6
+ import { findNodeAtLocation, } from "jsonc-parser";
7
+ import { getAtPropertyPath, isJsonObject, } from "../sync/json-path.js";
8
+ import { planObjectPatchEdits, serializeConfigValue, } from "./ui-config-write-property-edits.js";
9
+ /**
10
+ * Plan every changed path against one immutable original syntax tree.
11
+ *
12
+ * Missing descendants collapse to the first absent/non-object branch, so a
13
+ * formatter never needs to borrow and replace an unrelated sibling for context.
14
+ * @param text - Original strict JSON text
15
+ * @param tree - Original syntax tree whose offsets refer to `text`
16
+ * @param source - Original semantic document
17
+ * @param prospective - Final semantic document after ordered edits
18
+ * @param touched - Ordered edits that changed semantics
19
+ * @returns Deterministic non-overlapping original-offset text edits
20
+ */
21
+ export function planConfigTextEdits(text, tree, source, prospective, touched) {
22
+ const patches = collapseConfigPatches(source, prospective, touched);
23
+ const planned = patches.reduce((plan, patch) => planConfigPatch(tree, plan, patch), {
24
+ replacements: [],
25
+ groups: [],
26
+ });
27
+ return [
28
+ ...planned.replacements,
29
+ ...planned.groups.flatMap(group => planObjectPatchEdits(text, tree, group)),
30
+ ];
31
+ }
32
+ /**
33
+ * Collapse overlapping changes to the shallowest original source property.
34
+ * @param source - Original semantic document
35
+ * @param prospective - Final semantic document after ordered edits
36
+ * @param touched - Ordered edits that actually changed semantics
37
+ * @returns Stable property patches with no ancestor/descendant overlap
38
+ */
39
+ function collapseConfigPatches(source, prospective, touched) {
40
+ const candidates = touched.map((edit, order) => {
41
+ const requestedPath = edit.path;
42
+ const path = edit.kind === "remove"
43
+ ? requestedPath
44
+ : findSetPatchPath(source, requestedPath);
45
+ return { path, value: getAtPropertyPath(prospective, path), order };
46
+ });
47
+ const collapsed = [...candidates]
48
+ .sort((left, right) => left.path.length - right.path.length || left.order - right.order)
49
+ .reduce((patches, candidate) => {
50
+ return patches.some(patch => isPathPrefix(patch.path, candidate.path))
51
+ ? patches
52
+ : [...patches, candidate];
53
+ }, []);
54
+ return [...collapsed].sort((left, right) => left.order - right.order);
55
+ }
56
+ /**
57
+ * Find the shallowest property whose replacement can express a set operation.
58
+ * @param node - Original value at the current path depth
59
+ * @param segments - Remaining requested dot-path segments
60
+ * @param prefix - Original path already proven to contain objects
61
+ * @returns Existing leaf or first missing/non-object branch to replace
62
+ */
63
+ function findSetPatchPath(node, segments, prefix = []) {
64
+ const [head, ...rest] = segments;
65
+ if (head === undefined)
66
+ return prefix;
67
+ const path = [...prefix, head];
68
+ if (rest.length === 0)
69
+ return path;
70
+ const child = node[head];
71
+ return isJsonObject(child) ? findSetPatchPath(child, rest, path) : path;
72
+ }
73
+ /**
74
+ * Compare dot paths without joining them into ambiguous strings.
75
+ * @param prefix - Candidate ancestor path
76
+ * @param candidate - Candidate descendant path
77
+ * @returns Whether every prefix segment matches the candidate
78
+ */
79
+ function isPathPrefix(prefix, candidate) {
80
+ return (prefix.length <= candidate.length &&
81
+ prefix.every((segment, index) => candidate[index] === segment));
82
+ }
83
+ /**
84
+ * Plan one patch as an existing value replacement or grouped child mutation.
85
+ * @param tree - Original strict-JSON syntax tree
86
+ * @param plan - Replacements and object groups accumulated so far
87
+ * @param plan.replacements - Existing-value edits accumulated so far
88
+ * @param plan.groups - Direct object-child mutations accumulated so far
89
+ * @param patch - Collapsed semantic patch
90
+ * @returns Plan including this patch
91
+ */
92
+ function planConfigPatch(tree, plan, patch) {
93
+ const valueNode = findNodeAtLocation(tree, [...patch.path]);
94
+ if (valueNode !== undefined && patch.value !== undefined) {
95
+ return {
96
+ ...plan,
97
+ replacements: [
98
+ ...plan.replacements,
99
+ {
100
+ offset: valueNode.offset,
101
+ length: valueNode.length,
102
+ content: serializeConfigValue(patch.value),
103
+ },
104
+ ],
105
+ };
106
+ }
107
+ const parentPath = patch.path.slice(0, -1);
108
+ const key = patch.path.at(-1);
109
+ if (key === undefined) {
110
+ throw new Error("Config root replacement is not writable");
111
+ }
112
+ return {
113
+ ...plan,
114
+ groups: addObjectPatch(plan.groups, parentPath, key, patch, valueNode !== undefined),
115
+ };
116
+ }
117
+ /**
118
+ * Add one insertion or removal to an immutable parent-object group.
119
+ * @param groups - Groups accumulated for earlier patches
120
+ * @param parentPath - Original object that owns the direct property
121
+ * @param key - Direct property name
122
+ * @param patch - Final insertion value and stable request order
123
+ * @param removesExisting - Whether the original tree contains this property
124
+ * @returns Groups including this mutation
125
+ */
126
+ function addObjectPatch(groups, parentPath, key, patch, removesExisting) {
127
+ const existing = groups.find(group => pathsEqual(group.parentPath, parentPath));
128
+ const next = {
129
+ parentPath,
130
+ removals: removesExisting
131
+ ? [...(existing?.removals ?? []), key]
132
+ : (existing?.removals ?? []),
133
+ insertions: removesExisting
134
+ ? (existing?.insertions ?? [])
135
+ : [...(existing?.insertions ?? []), patch],
136
+ };
137
+ return existing === undefined
138
+ ? [...groups, next]
139
+ : groups.map(group => pathsEqual(group.parentPath, parentPath) ? next : group);
140
+ }
141
+ /**
142
+ * Compare two syntax-tree paths exactly.
143
+ * @param left - First path
144
+ * @param right - Second path
145
+ * @returns Whether both contain the same segments in the same order
146
+ */
147
+ function pathsEqual(left, right) {
148
+ return (left.length === right.length &&
149
+ left.every((segment, index) => right[index] === segment));
150
+ }
151
+ //# sourceMappingURL=ui-config-write-patch-plan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui-config-write-patch-plan.js","sourceRoot":"","sources":["../../src/cli/ui-config-write-patch-plan.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { JsonObject, JsonValue } from "../sync/json-path.js";
2
+ /** Changes already classified at the request boundary, before any file I/O. */
3
+ export interface RoutedConfigChanges {
4
+ /** Registry-root or registry-descendant changes for committed governance. */
5
+ readonly committed: Readonly<Record<string, JsonValue>>;
6
+ /** Exact console-authorized changes for the gitignored developer overlay. */
7
+ readonly local: Readonly<Record<string, JsonValue>>;
8
+ }
9
+ /** Callback that enforces registry validators against the prospective config. */
10
+ export type ValidateCommittedConfig = (config: JsonObject) => void;
11
+ /**
12
+ * Persist one pre-classified request under the project write queue.
13
+ * @param destDir - Project root containing the two fixed config filenames
14
+ * @param changes - Changes split by committed versus local ownership
15
+ * @param validateCommitted - Registry validation applied before either write
16
+ * @returns Prospective committed config only; local values are never echoed
17
+ */
18
+ export declare function persistRoutedConfigChanges(destDir: string, changes: RoutedConfigChanges, validateCommitted: ValidateCommittedConfig): Promise<JsonObject>;
19
+ //# sourceMappingURL=ui-config-write-persistence.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui-config-write-persistence.d.ts","sourceRoot":"","sources":["../../src/cli/ui-config-write-persistence.ts"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AA0BlE,+EAA+E;AAC/E,MAAM,WAAW,mBAAmB;IAClC,6EAA6E;IAC7E,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;IACxD,6EAA6E;IAC7E,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;CACrD;AAoBD,iFAAiF;AACjF,MAAM,MAAM,uBAAuB,GAAG,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;AAEnE;;;;;;GAMG;AACH,wBAAsB,0BAA0B,CAC9C,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,mBAAmB,EAC5B,iBAAiB,EAAE,uBAAuB,GACzC,OAAO,CAAC,UAAU,CAAC,CAwCrB"}