@codyswann/lisa 4.17.18 → 4.18.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/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 +4 -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 +8 -2
  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/package.json +2 -2
  47. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  48. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  49. package/plugins/lisa-agy/plugin.json +1 -1
  50. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  51. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  52. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  53. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  54. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  55. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  56. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  57. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  58. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  59. package/plugins/lisa-expo-agy/plugin.json +1 -1
  60. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  61. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  62. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  63. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  64. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  65. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  66. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  67. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  68. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  69. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  70. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  71. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  72. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  73. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  74. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  75. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  76. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  77. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  78. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  79. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  80. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  81. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  82. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  83. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  84. package/plugins/lisa-rails-agy/plugin.json +1 -1
  85. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  86. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  87. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  88. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  89. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  90. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  91. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  92. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  93. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  94. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  95. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  96. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  97. package/typescript/copy-overwrite/scripts/check-skipped-required-checks.mjs +10 -3
  98. package/ui/README.md +62 -8
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "4.17.18",
3
+ "version": "4.18.0",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "4.17.18",
3
+ "version": "4.18.0",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "4.17.18",
3
+ "version": "4.18.0",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -2164,10 +2164,12 @@ function main(argv) {
2164
2164
  };
2165
2165
  const blocking = result.violations.filter(blocks);
2166
2166
  const refusal = result.vacuity?.refusal ?? null;
2167
+ const refusalBlocks =
2168
+ refusal !== null && (!warnOnly || requireReviewEvidence);
2167
2169
  const failed =
2168
2170
  blocking.length > 0 ||
2169
2171
  (!result.trust.trusted && !warnOnly) ||
2170
- (refusal !== null && (!warnOnly || requireReviewEvidence));
2172
+ refusalBlocks;
2171
2173
 
2172
2174
  if (argv.includes("--json")) {
2173
2175
  process.stdout.write(
@@ -2221,11 +2223,16 @@ function main(argv) {
2221
2223
  ""
2222
2224
  );
2223
2225
  process.stderr.write(
2224
- `::${warnOnly ? "warning" : "error"} title=${refusal.kind}::${refusal.reason.split("\n")[0]}\n`
2226
+ `::${refusalBlocks ? "error" : "warning"} title=${refusal.kind}::${refusal.reason.split("\n")[0]}\n`
2225
2227
  );
2226
2228
  }
2227
2229
 
2228
- if (result.violations.length === 0) {
2230
+ if (refusal !== null && result.violations.length === 0) {
2231
+ // NOT INSPECTED is the whole verdict for this arm. Neither a clean summary
2232
+ // nor a vacuity-violation summary may contradict a result that examined
2233
+ // nothing. Independent offline violations still render below: a refused
2234
+ // evidence read cannot erase what the skip declaration already proved.
2235
+ } else if (result.violations.length === 0) {
2229
2236
  if (result.trust.trusted) {
2230
2237
  lines.push(
2231
2238
  `✅ ${result.checked} \`skip_jobs\` token(s) examined; none silences a ruleset-required status check.`,
package/ui/README.md CHANGED
@@ -4,14 +4,13 @@ A self-contained, zero-build prototype of the Lisa settings console. It catalogs
4
4
  every configuration surface Lisa exposes to host projects and presents it as a
5
5
  navigable, editable-looking settings UI.
6
6
 
7
- **Prototype scope:** every control is interactive (toggles, selects, inputs,
8
- tabs, dirty-state tracking, save bar). Reading real values IS wired up: see
9
- `lisa ui` below. Persistence is partial and the line to read is
10
- `src/sync/registry.ts`: a control whose config key is in `SYNC_REGISTRY` is
11
- written to `.lisa.config.json` through `POST /api/config`; every other control
12
- still only clears the in-memory dirty state on "Save". `gates` is **not** a
13
- registry key, so no console write can touch a gate declaration today — which is
14
- why the Doctor section reports and never repairs.
7
+ **Prototype scope:** controls, tabs, dirty-state tracking, and the save bar are
8
+ interactive. Reading real values IS wired up: see `lisa ui` below. The backend
9
+ write contract now routes authorized keys through `POST /api/config`, but the
10
+ page's **Save changes** button deliberately remains disabled until the separate
11
+ save/rehydration UX ships. `gates` is **not** a registry key, so no console
12
+ write can touch a gate declaration today — which is why the Doctor section
13
+ reports and never repairs.
15
14
 
16
15
  ## Run it
17
16
 
@@ -31,6 +30,61 @@ live config it falls back to Lisa's shipped defaults:
31
30
  open ui/index.html
32
31
  ```
33
32
 
33
+ ## Config write contract (`POST /api/config`)
34
+
35
+ The same-origin endpoint classifies the complete request before reading either
36
+ config file. A key equal to a live `SYNC_REGISTRY` root, or below that root on a
37
+ dot-segment boundary, belongs in the committed `.lisa.config.json`. Exactly
38
+ three console-authorized developer keys belong in the gitignored
39
+ `.lisa.config.local.json`: `atlassian.email`, `intake.assignee`, and
40
+ `playStore.serviceAccountKeyPath`. Every other key — including `tracker`,
41
+ `jira.verified_workflow_hash`, prefix lookalikes, and descendants of a local
42
+ key — is rejected with HTTP 400 before file I/O. Responses contain the
43
+ committed config only, so a local value is never echoed.
44
+
45
+ Both documents remain strict JSON. Writes first compute the complete prospective
46
+ objects, then apply deterministic non-overlapping `jsonc-parser` syntax-tree
47
+ edits against the original text. Existing values replace only their value-node
48
+ range; removals consume only targeted property runs and required commas; missing
49
+ properties insert at stable object offsets. No edit range includes an unrelated
50
+ property node, so bytes outside the targeted spans retain their hand-authored
51
+ formatting even when one request mixes reconciliation and insertion in both
52
+ files. The project root is canonicalized with `realpath`, and every request holds a
53
+ cross-process lock for that canonical root while it takes bounded regular-file
54
+ snapshots of **both** configs, validates both prospective documents, and
55
+ publishes them. The lock lives in a user-private, repository-external temporary
56
+ directory under a hash of the canonical path, so separate UI processes and
57
+ symlink aliases share one transaction without leaving lock residue in the
58
+ project. The root's canonical path and filesystem identity are revalidated
59
+ before and after snapshots, validation, temporary-file creation, and each
60
+ rename. This deterministically refuses a root or ancestor replacement at every
61
+ available boundary. Node does not expose portable descriptor-relative
62
+ temporary creation or rename, so a same-user process that wins the narrow gap
63
+ between the last identity check and a path-based filesystem call can still
64
+ redirect that call; the endpoint does not claim absolute race closure.
65
+
66
+ For every routed key, persistence first removes the same dot path from its
67
+ non-owner config and then sets it in the owner config. Removal is exact: a root
68
+ removes its descendants, while a descendant removal retains unrelated siblings.
69
+ That reconciliation prevents a stale local override and keeps local-only values
70
+ out of both the committed file and the response. A scalar or array ancestor
71
+ that prevents exact non-owner cleanup is rejected rather than silently retaining
72
+ an overlay shadow. Invalid UTF-8 or recursively duplicated properties in either
73
+ the request or config files, a surgical render whose reparsed structure differs
74
+ from the prospective object, and a changed existing target with no write bit all
75
+ reject before the first publish. Existing and rendered config images share the
76
+ same 128 KiB bound, checked for both targets before either is published.
77
+
78
+ Existing permission modes are restored exactly after the temporary write, even
79
+ when umask would narrow a permissive mode such as `0666`; a new local config is
80
+ still `0600`. Semantic no-ops skip replacement. Each changed file is published
81
+ through a durable atomic replacement after its original bytes are rechecked.
82
+ Filesystems do not offer one atomic rename spanning two files, so an I/O failure
83
+ or an external writer arriving between the two final replacements can still
84
+ leave the first target published and the second unchanged. The endpoint reports
85
+ that failure instead of claiming an all-or-nothing cross-file transaction;
86
+ canonical-root locking prevents silent lost updates among endpoint requests.
87
+
34
88
  ## Live status contract
35
89
 
36
90
  When served by `lisa ui`, the page fetches `GET /api/status` from the same