@codyswann/lisa 2.198.2 → 2.200.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 (98) hide show
  1. package/cdk/create-only/.github/workflows/deploy.yml +27 -3
  2. package/dist/cli/index.d.ts +6 -0
  3. package/dist/cli/index.d.ts.map +1 -1
  4. package/dist/cli/index.js +30 -3
  5. package/dist/cli/index.js.map +1 -1
  6. package/dist/cli/sync-cmd.d.ts +21 -0
  7. package/dist/cli/sync-cmd.d.ts.map +1 -0
  8. package/dist/cli/sync-cmd.js +43 -0
  9. package/dist/cli/sync-cmd.js.map +1 -0
  10. package/dist/cli/ui-cmd.d.ts +35 -0
  11. package/dist/cli/ui-cmd.d.ts.map +1 -0
  12. package/dist/cli/ui-cmd.js +104 -0
  13. package/dist/cli/ui-cmd.js.map +1 -0
  14. package/dist/sync/config-sync.d.ts +42 -0
  15. package/dist/sync/config-sync.d.ts.map +1 -0
  16. package/dist/sync/config-sync.js +272 -0
  17. package/dist/sync/config-sync.js.map +1 -0
  18. package/dist/sync/json-path.d.ts +58 -0
  19. package/dist/sync/json-path.d.ts.map +1 -0
  20. package/dist/sync/json-path.js +107 -0
  21. package/dist/sync/json-path.js.map +1 -0
  22. package/dist/sync/registry.d.ts +64 -0
  23. package/dist/sync/registry.d.ts.map +1 -0
  24. package/dist/sync/registry.js +207 -0
  25. package/dist/sync/registry.js.map +1 -0
  26. package/expo/create-only/.github/workflows/deploy.yml +27 -3
  27. package/nestjs/create-only/.github/workflows/deploy.yml +26 -3
  28. package/package.json +2 -1
  29. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  30. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  31. package/plugins/lisa/.codex-plugin/skills/lisa-setup-github-repo/SKILL.md +58 -3
  32. package/plugins/lisa/commands/lisa/setup/github-repo.md +1 -1
  33. package/plugins/lisa/rules/reference/config-resolution.md +6 -0
  34. package/plugins/lisa/skills/lisa-setup-github-repo/SKILL.md +59 -4
  35. package/plugins/lisa-agy/commands/lisa/setup/github-repo.md +1 -1
  36. package/plugins/lisa-agy/plugin.json +1 -1
  37. package/plugins/lisa-agy/skills/lisa-setup-github-repo/SKILL.md +59 -4
  38. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  39. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  40. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  41. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  42. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  43. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  44. package/plugins/lisa-copilot/commands/lisa/setup/github-repo.md +1 -1
  45. package/plugins/lisa-copilot/rules/reference/config-resolution.md +6 -0
  46. package/plugins/lisa-copilot/skills/lisa-setup-github-repo/SKILL.md +59 -4
  47. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  48. package/plugins/lisa-cursor/commands/lisa/setup/github-repo.md +1 -1
  49. package/plugins/lisa-cursor/rules/config-resolution-reference.mdc +6 -0
  50. package/plugins/lisa-cursor/skills/lisa-setup-github-repo/SKILL.md +59 -4
  51. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  52. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  53. package/plugins/lisa-expo-agy/plugin.json +1 -1
  54. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  55. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  56. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  57. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  58. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  59. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  60. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  61. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  62. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  63. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  64. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  65. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  66. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  67. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  68. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  69. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  70. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  71. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  72. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  73. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  74. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  75. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  76. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  77. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  78. package/plugins/lisa-rails-agy/plugin.json +1 -1
  79. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  80. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  81. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  82. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  83. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  84. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  85. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  86. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  87. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  88. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  89. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  90. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  91. package/plugins/src/base/commands/lisa/setup/github-repo.md +1 -1
  92. package/plugins/src/base/rules/reference/config-resolution.md +6 -0
  93. package/plugins/src/base/skills/lisa-setup-github-repo/SKILL.md +59 -4
  94. package/scripts/lisa-github-environments.sh +256 -0
  95. package/scripts/lisa-github-repo-setup.sh +11 -4
  96. package/typescript/copy-overwrite/.github/GITHUB_ACTIONS.md +30 -1
  97. package/ui/README.md +180 -0
  98. package/ui/index.html +5396 -0
@@ -0,0 +1,272 @@
1
+ /**
2
+ * Config-sync engine: makes `.lisa.config.json` (plus the per-developer
3
+ * `.lisa.config.local.json` overlay) the source of truth for every registry
4
+ * setting.
5
+ *
6
+ * Populate direction (only when a config value is completely missing):
7
+ * absorb the value from an existing artifact file if one holds it, otherwise
8
+ * fall back to the built-in default. Pure-default populations are recorded in
9
+ * the config's `_lisaSync.populated` block so a later Lisa version that ships
10
+ * a changed default can distinguish "still the default" (safe to update) from
11
+ * "the project chose this value" (never touched).
12
+ *
13
+ * Sync direction (always): the effective config value is written into every
14
+ * artifact file that exists on disk — config wins.
15
+ * @module sync/config-sync
16
+ */
17
+ import * as fse from "fs-extra";
18
+ import * as path from "node:path";
19
+ import { deepMerge, readJsonOrNull, writeJson } from "../utils/index.js";
20
+ import { fillMissing, getAtPath, isJsonObject, jsonEquals, setAtPath, } from "./json-path.js";
21
+ import { REQUIRED_KEYS, SYNC_REGISTRY, } from "./registry.js";
22
+ /** Key holding sync provenance metadata inside `.lisa.config.json`. */
23
+ export const SYNC_METADATA_KEY = "_lisaSync";
24
+ /**
25
+ * Check whether a registry relevance condition matches the merged config.
26
+ * @param merged - Merged (committed + local) config view
27
+ * @param condition - `"section"` (path exists) or `"path=value"` (equality)
28
+ * @returns True when the condition matches
29
+ */
30
+ function conditionMatches(merged, condition) {
31
+ const eqIndex = condition.indexOf("=");
32
+ if (eqIndex === -1) {
33
+ return getAtPath(merged, condition) !== undefined;
34
+ }
35
+ const value = getAtPath(merged, condition.slice(0, eqIndex));
36
+ return value === condition.slice(eqIndex + 1);
37
+ }
38
+ /**
39
+ * Whether a registry entry applies to this project's current config.
40
+ * @param merged - Merged (committed + local) config view
41
+ * @param relevantWhen - Entry conditions (absent = always relevant)
42
+ * @returns True when the entry should be synced
43
+ */
44
+ function isRelevant(merged, relevantWhen) {
45
+ if (relevantWhen === undefined) {
46
+ return true;
47
+ }
48
+ return relevantWhen.some(condition => conditionMatches(merged, condition));
49
+ }
50
+ /**
51
+ * Read the first existing artifact's value for a setting.
52
+ * @param destDir - Project root
53
+ * @param entry - Registry entry
54
+ * @returns The artifact value, or undefined when no artifact holds one
55
+ */
56
+ async function readArtifactValue(destDir, entry) {
57
+ const bindings = entry.artifacts ?? [];
58
+ const reads = await Promise.all(bindings.map(async (binding) => {
59
+ const parsed = await readJsonOrNull(path.join(destDir, binding.file));
60
+ return parsed === null ? undefined : getAtPath(parsed, binding.pointer);
61
+ }));
62
+ return reads.find(value => value !== undefined);
63
+ }
64
+ /**
65
+ * Read the recorded populated-default value for a key, if any. Provenance
66
+ * keys are stored literally (dots included) inside `_lisaSync.populated`.
67
+ * @param committed - Committed config object
68
+ * @param key - Config key
69
+ * @returns The value recorded at population time, or undefined
70
+ */
71
+ function recordedPopulation(committed, key) {
72
+ const populated = getAtPath(committed, `${SYNC_METADATA_KEY}.populated`);
73
+ return isJsonObject(populated) ? populated[key] : undefined;
74
+ }
75
+ /**
76
+ * Record that a key was auto-populated with a default value, storing the key
77
+ * literally (dots included) so later runs can detect default evolution.
78
+ * @param committed - Committed config object
79
+ * @param key - Config key
80
+ * @param value - The default value written
81
+ * @returns Updated committed config
82
+ */
83
+ function recordPopulation(committed, key, value) {
84
+ const populated = getAtPath(committed, `${SYNC_METADATA_KEY}.populated`);
85
+ const populatedObject = isJsonObject(populated) ? populated : {};
86
+ return setAtPath(committed, `${SYNC_METADATA_KEY}.populated`, {
87
+ ...populatedObject,
88
+ [key]: value,
89
+ });
90
+ }
91
+ /**
92
+ * Build the next state with an updated committed config and appended action.
93
+ * @param state - Current sync state
94
+ * @param committed - Updated committed config
95
+ * @param action - Action to append to the report
96
+ * @returns Updated state
97
+ */
98
+ function withAction(state, committed, action) {
99
+ return { ...state, committed, actions: [...state.actions, action] };
100
+ }
101
+ /**
102
+ * Populate a config key that is completely missing: absorb the artifact
103
+ * value when one exists, otherwise write the built-in default and record it.
104
+ * @param state - Current sync state
105
+ * @param entry - Registry entry
106
+ * @param artifactValue - Value found in an existing artifact, if any
107
+ * @returns Updated state
108
+ */
109
+ function populateMissing(state, entry, artifactValue) {
110
+ if (artifactValue !== undefined) {
111
+ const absorbed = fillMissing(artifactValue, entry.defaultValue);
112
+ return withAction(state, setAtPath(state.committed, entry.key, absorbed), {
113
+ key: entry.key,
114
+ kind: "absorbed-artifact",
115
+ detail: `value absorbed from ${entry.artifacts?.[0]?.file ?? "artifact"}`,
116
+ });
117
+ }
118
+ const committed = recordPopulation(setAtPath(state.committed, entry.key, entry.defaultValue), entry.key, entry.defaultValue);
119
+ return withAction(state, committed, {
120
+ key: entry.key,
121
+ kind: "populated-default",
122
+ detail: "built-in default written to .lisa.config.json",
123
+ });
124
+ }
125
+ /**
126
+ * Resolve the next committed config for one entry (populate direction).
127
+ * @param state - Current sync state
128
+ * @param entry - Registry entry
129
+ * @param merged - Merged config view (local overlay applied)
130
+ * @param artifactValue - Value found in an existing artifact, if any
131
+ * @returns Updated state
132
+ */
133
+ function populateEntry(state, entry, merged, artifactValue) {
134
+ const configValue = getAtPath(merged, entry.key);
135
+ if (configValue === undefined) {
136
+ return populateMissing(state, entry, artifactValue);
137
+ }
138
+ const recorded = recordedPopulation(state.committed, entry.key);
139
+ if (recorded !== undefined &&
140
+ jsonEquals(configValue, recorded) &&
141
+ !jsonEquals(configValue, entry.defaultValue)) {
142
+ const committed = recordPopulation(setAtPath(state.committed, entry.key, entry.defaultValue), entry.key, entry.defaultValue);
143
+ return withAction(state, committed, {
144
+ key: entry.key,
145
+ kind: "default-evolved",
146
+ detail: "value still matched the old default; updated to the new one",
147
+ });
148
+ }
149
+ const filled = fillMissing(configValue, entry.defaultValue);
150
+ if (!jsonEquals(filled, configValue)) {
151
+ return withAction(state, setAtPath(state.committed, entry.key, filled), {
152
+ key: entry.key,
153
+ kind: "filled-missing",
154
+ detail: "missing sub-keys filled with defaults",
155
+ });
156
+ }
157
+ return state;
158
+ }
159
+ /**
160
+ * Queue artifact writes for one entry (sync direction: config wins). Only
161
+ * files that already exist on disk are written — sync never scaffolds
162
+ * artifacts into stacks that do not use them.
163
+ * @param state - Current sync state
164
+ * @param entry - Registry entry
165
+ * @param destDir - Project root
166
+ * @param local - Local config overlay
167
+ * @returns Updated state
168
+ */
169
+ async function syncArtifacts(state, entry, destDir, local) {
170
+ const bindings = entry.artifacts ?? [];
171
+ if (bindings.length === 0) {
172
+ return state;
173
+ }
174
+ const effective = getAtPath(deepMerge(state.committed, local), entry.key);
175
+ if (effective === undefined) {
176
+ return state;
177
+ }
178
+ return bindings.reduce(async (statePromise, binding) => {
179
+ const current = await statePromise;
180
+ const filePath = path.join(destDir, binding.file);
181
+ const pending = current.artifactWrites.get(binding.file);
182
+ const parsed = pending ?? (await readJsonOrNull(filePath)) ?? undefined;
183
+ if (parsed === undefined && !(await fse.pathExists(filePath))) {
184
+ return current;
185
+ }
186
+ const fileObject = isJsonObject(parsed) ? parsed : {};
187
+ if (jsonEquals(getAtPath(fileObject, binding.pointer), effective)) {
188
+ return current;
189
+ }
190
+ const updated = setAtPath(fileObject, binding.pointer, effective);
191
+ const writes = new Map([
192
+ ...current.artifactWrites,
193
+ [binding.file, updated],
194
+ ]);
195
+ return {
196
+ ...current,
197
+ artifactWrites: writes,
198
+ actions: [
199
+ ...current.actions,
200
+ {
201
+ key: entry.key,
202
+ kind: "artifact-synced",
203
+ detail: `${binding.file} updated from config`,
204
+ },
205
+ ],
206
+ };
207
+ }, Promise.resolve(state));
208
+ }
209
+ /**
210
+ * Report required keys that are missing from the merged config.
211
+ * @param merged - Merged config view
212
+ * @returns Missing required keys with their setup hints
213
+ */
214
+ function findMissingRequired(merged) {
215
+ return REQUIRED_KEYS.filter(required => isRelevant(merged, required.relevantWhen) &&
216
+ getAtPath(merged, required.key) === undefined).map(required => ({ key: required.key, setupHint: required.setupHint }));
217
+ }
218
+ /**
219
+ * Run one populate-and-sync pass over a project.
220
+ *
221
+ * Precedence per setting: existing config value → existing artifact value →
222
+ * built-in default. After population, every existing artifact file is
223
+ * rewritten from the (local-overlaid) config value.
224
+ * @param destDir - Absolute path to the project root
225
+ * @param options - Sync options
226
+ * @returns Report of every action taken (or planned, when dryRun)
227
+ */
228
+ export async function runConfigSync(destDir, options = {}) {
229
+ const committedPath = path.join(destDir, ".lisa.config.json");
230
+ const localPath = path.join(destDir, ".lisa.config.local.json");
231
+ const committedRaw = await readJsonOrNull(committedPath);
232
+ const localRaw = await readJsonOrNull(localPath);
233
+ const committed = isJsonObject(committedRaw) ? committedRaw : {};
234
+ const local = isJsonObject(localRaw) ? localRaw : {};
235
+ const initial = {
236
+ committed,
237
+ actions: [],
238
+ artifactWrites: new Map(),
239
+ };
240
+ const finalState = await SYNC_REGISTRY.reduce(async (statePromise, entry) => {
241
+ const state = await statePromise;
242
+ const merged = deepMerge(state.committed, local);
243
+ if (!isRelevant(merged, entry.relevantWhen)) {
244
+ return state;
245
+ }
246
+ const artifactValue = await readArtifactValue(destDir, entry);
247
+ const populated = populateEntry(state, entry, merged, artifactValue);
248
+ return syncArtifacts(populated, entry, destDir, local);
249
+ }, Promise.resolve(initial));
250
+ const mergedFinal = deepMerge(finalState.committed, local);
251
+ if (options.dryRun !== true) {
252
+ await persistState(destDir, committed, finalState);
253
+ }
254
+ return {
255
+ actions: finalState.actions,
256
+ missingRequired: findMissingRequired(mergedFinal),
257
+ dryRun: options.dryRun === true,
258
+ };
259
+ }
260
+ /**
261
+ * Write the updated committed config and every queued artifact file.
262
+ * @param destDir - Project root
263
+ * @param originalCommitted - Committed config as read at the start of the run
264
+ * @param state - Final sync state
265
+ */
266
+ async function persistState(destDir, originalCommitted, state) {
267
+ if (!jsonEquals(originalCommitted, state.committed)) {
268
+ await writeJson(path.join(destDir, ".lisa.config.json"), state.committed);
269
+ }
270
+ await Promise.all(Array.from(state.artifactWrites.entries()).map(([file, content]) => writeJson(path.join(destDir, file), content)));
271
+ }
272
+ //# sourceMappingURL=config-sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-sync.js","sourceRoot":"","sources":["../../src/sync/config-sync.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Dot-path helpers for reading and immutably updating nested JSON values.
3
+ *
4
+ * Used by the config-sync engine to address settings inside
5
+ * `.lisa.config.json` (e.g. `quality.testCoverage.global.statements`) and
6
+ * inside mirrored artifact files (e.g. the `thresholds` key of
7
+ * `stryker.conf.json`).
8
+ * @module sync/json-path
9
+ */
10
+ /** Any JSON-compatible value. */
11
+ export type JsonValue = string | number | boolean | null | JsonValue[] | {
12
+ readonly [key: string]: JsonValue;
13
+ };
14
+ /** A JSON object record (non-array, non-null). */
15
+ export type JsonObject = {
16
+ readonly [key: string]: JsonValue;
17
+ };
18
+ /**
19
+ * Check whether a value is a plain (non-array) JSON object.
20
+ * @param value - Candidate value
21
+ * @returns True when the value is a plain JSON object record
22
+ */
23
+ export declare function isJsonObject(value: unknown): value is JsonObject;
24
+ /**
25
+ * Read the value at a dot path inside a JSON object.
26
+ * @param root - Object to read from
27
+ * @param dotPath - Dot-separated key path (empty string returns the root)
28
+ * @returns The value at the path, or undefined when any segment is missing
29
+ */
30
+ export declare function getAtPath(root: unknown, dotPath: string): JsonValue | undefined;
31
+ /**
32
+ * Return a copy of a JSON object with the value at a dot path replaced.
33
+ * Missing intermediate objects are created; existing siblings are preserved.
34
+ * The input object is never mutated.
35
+ * @param root - Object to copy
36
+ * @param dotPath - Dot-separated key path (empty string replaces the root)
37
+ * @param value - Value to write at the path
38
+ * @returns A new object with the update applied
39
+ */
40
+ export declare function setAtPath(root: JsonObject, dotPath: string, value: JsonValue): JsonObject;
41
+ /**
42
+ * Compare two JSON-compatible values for structural equality, independent of
43
+ * object key insertion order.
44
+ * @param a - First value
45
+ * @param b - Second value
46
+ * @returns True when the values are structurally equal
47
+ */
48
+ export declare function jsonEquals(a: unknown, b: unknown): boolean;
49
+ /**
50
+ * Fill missing keys of a JSON value from a fallback, recursively. Present
51
+ * values always win over the fallback; only absent object keys are filled.
52
+ * Arrays and scalars are taken wholesale from whichever side is present.
53
+ * @param value - The preferred value (may be undefined)
54
+ * @param fallback - Values used only where `value` has gaps
55
+ * @returns The value with gaps filled from the fallback
56
+ */
57
+ export declare function fillMissing(value: JsonValue | undefined, fallback: JsonValue): JsonValue;
58
+ //# sourceMappingURL=json-path.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-path.d.ts","sourceRoot":"","sources":["../../src/sync/json-path.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,iCAAiC;AACjC,MAAM,MAAM,SAAS,GACjB,MAAM,GACN,MAAM,GACN,OAAO,GACP,IAAI,GACJ,SAAS,EAAE,GACX;IAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC;AAE1C,kDAAkD;AAClD,MAAM,MAAM,UAAU,GAAG;IAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC;AAE/D;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,UAAU,CAEhE;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE,OAAO,EACb,OAAO,EAAE,MAAM,GACd,SAAS,GAAG,SAAS,CAYvB;AAED;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE,UAAU,EAChB,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,SAAS,GACf,UAAU,CAkBZ;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,OAAO,CAe1D;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,SAAS,GAAG,SAAS,EAC5B,QAAQ,EAAE,SAAS,GAClB,SAAS,CAoBX"}
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Dot-path helpers for reading and immutably updating nested JSON values.
3
+ *
4
+ * Used by the config-sync engine to address settings inside
5
+ * `.lisa.config.json` (e.g. `quality.testCoverage.global.statements`) and
6
+ * inside mirrored artifact files (e.g. the `thresholds` key of
7
+ * `stryker.conf.json`).
8
+ * @module sync/json-path
9
+ */
10
+ /**
11
+ * Check whether a value is a plain (non-array) JSON object.
12
+ * @param value - Candidate value
13
+ * @returns True when the value is a plain JSON object record
14
+ */
15
+ export function isJsonObject(value) {
16
+ return typeof value === "object" && value !== null && !Array.isArray(value);
17
+ }
18
+ /**
19
+ * Read the value at a dot path inside a JSON object.
20
+ * @param root - Object to read from
21
+ * @param dotPath - Dot-separated key path (empty string returns the root)
22
+ * @returns The value at the path, or undefined when any segment is missing
23
+ */
24
+ export function getAtPath(root, dotPath) {
25
+ if (dotPath === "") {
26
+ return root;
27
+ }
28
+ const segments = dotPath.split(".");
29
+ return segments.reduce((node, segment) => isJsonObject(node)
30
+ ? node[segment]
31
+ : undefined, root);
32
+ }
33
+ /**
34
+ * Return a copy of a JSON object with the value at a dot path replaced.
35
+ * Missing intermediate objects are created; existing siblings are preserved.
36
+ * The input object is never mutated.
37
+ * @param root - Object to copy
38
+ * @param dotPath - Dot-separated key path (empty string replaces the root)
39
+ * @param value - Value to write at the path
40
+ * @returns A new object with the update applied
41
+ */
42
+ export function setAtPath(root, dotPath, value) {
43
+ if (dotPath === "") {
44
+ if (!isJsonObject(value)) {
45
+ throw new Error("setAtPath: replacing the document root requires an object value");
46
+ }
47
+ return value;
48
+ }
49
+ const dotIndex = dotPath.indexOf(".");
50
+ const head = dotIndex === -1 ? dotPath : dotPath.slice(0, dotIndex);
51
+ const rest = dotIndex === -1 ? "" : dotPath.slice(dotIndex + 1);
52
+ if (rest === "") {
53
+ return { ...root, [head]: value };
54
+ }
55
+ const child = root[head];
56
+ const childObject = isJsonObject(child) ? child : {};
57
+ return { ...root, [head]: setAtPath(childObject, rest, value) };
58
+ }
59
+ /**
60
+ * Compare two JSON-compatible values for structural equality, independent of
61
+ * object key insertion order.
62
+ * @param a - First value
63
+ * @param b - Second value
64
+ * @returns True when the values are structurally equal
65
+ */
66
+ export function jsonEquals(a, b) {
67
+ if (Array.isArray(a) && Array.isArray(b)) {
68
+ return (a.length === b.length && a.every((entry, i) => jsonEquals(entry, b[i])));
69
+ }
70
+ if (isJsonObject(a) && isJsonObject(b)) {
71
+ const aKeys = Object.keys(a);
72
+ const bKeys = Object.keys(b);
73
+ return (aKeys.length === bKeys.length &&
74
+ aKeys.every(key => Object.hasOwn(b, key) && jsonEquals(a[key], b[key])));
75
+ }
76
+ return a === b;
77
+ }
78
+ /**
79
+ * Fill missing keys of a JSON value from a fallback, recursively. Present
80
+ * values always win over the fallback; only absent object keys are filled.
81
+ * Arrays and scalars are taken wholesale from whichever side is present.
82
+ * @param value - The preferred value (may be undefined)
83
+ * @param fallback - Values used only where `value` has gaps
84
+ * @returns The value with gaps filled from the fallback
85
+ */
86
+ export function fillMissing(value, fallback) {
87
+ if (value === undefined) {
88
+ return fallback;
89
+ }
90
+ if (isJsonObject(value) && isJsonObject(fallback)) {
91
+ const keys = new Set([...Object.keys(fallback), ...Object.keys(value)]);
92
+ const entries = Array.from(keys).map((key) => {
93
+ const own = Object.hasOwn(value, key) ? value[key] : undefined;
94
+ const fill = Object.hasOwn(fallback, key) ? fallback[key] : undefined;
95
+ if (own === undefined) {
96
+ return [key, fill];
97
+ }
98
+ if (fill === undefined) {
99
+ return [key, own];
100
+ }
101
+ return [key, fillMissing(own, fill)];
102
+ });
103
+ return Object.fromEntries(entries);
104
+ }
105
+ return value;
106
+ }
107
+ //# sourceMappingURL=json-path.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-path.js","sourceRoot":"","sources":["../../src/sync/json-path.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Registry of synced settings: the single map between `.lisa.config.json`
3
+ * keys, their built-in defaults, and the project artifact files that mirror
4
+ * them (test thresholds, lint budgets, mutation gates).
5
+ *
6
+ * The registry drives `lisa sync`: every entry is populated into the config
7
+ * when missing (absorbing an existing artifact value first, falling back to
8
+ * the built-in default), and afterwards the config value is written back into
9
+ * each artifact file — config is the source of truth unless a value is
10
+ * completely missing.
11
+ * @module sync/registry
12
+ */
13
+ import type { JsonValue } from "./json-path.js";
14
+ /**
15
+ * A project file that mirrors a synced setting. Artifact files are only ever
16
+ * written when they already exist on disk — sync never scaffolds an artifact
17
+ * into a project whose stack does not use it.
18
+ */
19
+ export interface ArtifactBinding {
20
+ /** Repo-relative path of the mirrored file */
21
+ readonly file: string;
22
+ /** Dot path of the mirrored value inside the file ("" = whole document) */
23
+ readonly pointer: string;
24
+ }
25
+ /** One synced setting: a config key, its default, and optional mirrors. */
26
+ export interface SyncedSetting {
27
+ /** Dot path of the setting inside `.lisa.config.json` */
28
+ readonly key: string;
29
+ /** Built-in default used when neither config nor artifact has a value */
30
+ readonly defaultValue: JsonValue;
31
+ /** Files that mirror this value (written from config on every sync) */
32
+ readonly artifacts?: readonly ArtifactBinding[];
33
+ /**
34
+ * Entry applies when ANY condition matches (absent = always applies).
35
+ * `"github"` means the `github` section exists; `"tracker=jira"` means the
36
+ * `tracker` key equals `"jira"`.
37
+ */
38
+ readonly relevantWhen?: readonly string[];
39
+ /** One-line human description used in sync reports */
40
+ readonly description: string;
41
+ }
42
+ /** A key sync cannot default and must report when missing. */
43
+ export interface RequiredKey {
44
+ /** Dot path of the required setting */
45
+ readonly key: string;
46
+ /** Applies when ANY condition matches (absent = always required) */
47
+ readonly relevantWhen?: readonly string[];
48
+ /** Setup command that provisions the key */
49
+ readonly setupHint: string;
50
+ }
51
+ /**
52
+ * All settings `lisa sync` manages. Local-only keys (`atlassian.email`,
53
+ * `intake.assignee`, `jira.verified_workflow_hash`, secret paths) are
54
+ * deliberately absent — sync never populates the committed file with values
55
+ * that belong in `.lisa.config.local.json`.
56
+ */
57
+ export declare const SYNC_REGISTRY: readonly SyncedSetting[];
58
+ /**
59
+ * Keys sync can never default: they identify external systems and must come
60
+ * from a human (via the matching `/lisa:setup:*` skill). Sync reports them
61
+ * when missing instead of inventing values.
62
+ */
63
+ export declare const REQUIRED_KEYS: readonly RequiredKey[];
64
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/sync/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,8CAA8C;IAC9C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,2EAA2E;IAC3E,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,2EAA2E;AAC3E,MAAM,WAAW,aAAa;IAC5B,yDAAyD;IACzD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,yEAAyE;IACzE,QAAQ,CAAC,YAAY,EAAE,SAAS,CAAC;IACjC,uEAAuE;IACvE,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;IAChD;;;;OAIG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,sDAAsD;IACtD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED,8DAA8D;AAC9D,MAAM,WAAW,WAAW;IAC1B,uCAAuC;IACvC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,oEAAoE;IACpE,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,4CAA4C;IAC5C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAoCD;;;;;GAKG;AACH,eAAO,MAAM,aAAa,EAAE,SAAS,aAAa,EAyHjD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,aAAa,EAAE,SAAS,WAAW,EA0C/C,CAAC"}