@codyswann/lisa 2.156.0 → 2.157.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 (55) hide show
  1. package/package.json +1 -1
  2. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  3. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  4. package/plugins/lisa/rules/reference/config-resolution.md +13 -8
  5. package/plugins/lisa-agy/plugin.json +1 -1
  6. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  7. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  8. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  9. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  10. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  11. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  12. package/plugins/lisa-copilot/rules/reference/config-resolution.md +13 -8
  13. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  14. package/plugins/lisa-cursor/rules/config-resolution-reference.mdc +13 -8
  15. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  16. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  17. package/plugins/lisa-expo-agy/plugin.json +1 -1
  18. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  19. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  20. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  21. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  22. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  23. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  24. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  25. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  26. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  27. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  28. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  29. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  30. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  31. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  32. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  33. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  34. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  35. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  36. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  37. package/plugins/lisa-rails-agy/plugin.json +1 -1
  38. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  39. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  40. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  41. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  42. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  43. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  44. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  45. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  46. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  47. package/plugins/lisa-wiki/scripts/ensure-wiki.mjs +28 -8
  48. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  49. package/plugins/lisa-wiki-agy/scripts/ensure-wiki.mjs +28 -8
  50. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  51. package/plugins/lisa-wiki-copilot/scripts/ensure-wiki.mjs +28 -8
  52. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  53. package/plugins/lisa-wiki-cursor/scripts/ensure-wiki.mjs +28 -8
  54. package/plugins/src/base/rules/reference/config-resolution.md +13 -8
  55. package/plugins/src/wiki/scripts/ensure-wiki.mjs +28 -8
package/package.json CHANGED
@@ -84,7 +84,7 @@
84
84
  "lodash": ">=4.18.1"
85
85
  },
86
86
  "name": "@codyswann/lisa",
87
- "version": "2.156.0",
87
+ "version": "2.157.0",
88
88
  "description": "Claude Code governance framework that applies guardrails, guidance, and automated enforcement to projects",
89
89
  "main": "dist/index.js",
90
90
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.156.0",
3
+ "version": "2.157.0",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.156.0",
3
+ "version": "2.157.0",
4
4
  "description": "Universal governance: agents, skills, commands, hooks, and rules for all projects.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -171,9 +171,13 @@ fi
171
171
 
172
172
  ### Wiki source (`wiki`)
173
173
 
174
- Declares **where this repo's LLM Wiki lives** so the query/ingest skills can resolve and (for a remote wiki) mirror it. This pointer belongs in the **consumer** repo's `.lisa.config.json` not in `wiki/lisa-wiki.config.json`, which describes a wiki from the inside and is unavailable until the remote wiki is mirrored (chicken-and-egg).
174
+ Declares **where this repo's LLM Wiki lives** so the query/ingest skills can resolve and (for a remote wiki) mirror it. `wiki.source` has two shapes — **local** (`path`) and **remote** (`url`) — and the block belongs in the **consumer** repo's `.lisa.config.json`, not in `wiki/lisa-wiki.config.json` (which describes a wiki from the inside and is unavailable until a remote wiki is mirrored chicken-and-egg). The whole `wiki` block is optional; omit it and the resolver falls back to the in-repo `wiki/` convention.
175
175
 
176
176
  ```json
177
+ // local: an explicit path (optional — equivalent to the default convention)
178
+ "wiki": { "source": { "path": "wiki" } }
179
+
180
+ // remote: mirror a separate wiki repo
177
181
  "wiki": {
178
182
  "source": {
179
183
  "url": "git@github.com:org/wiki.git",
@@ -187,13 +191,14 @@ Declares **where this repo's LLM Wiki lives** so the query/ingest skills can res
187
191
 
188
192
  | Field | Required | Default | Notes |
189
193
  |-------|----------|---------|-------|
190
- | `wiki.source.url` | no | | Clone URL of the canonical wiki repo. **Its presence selects REMOTE mode.** Omit the whole `wiki` block for a local in-repo wiki. |
191
- | `wiki.source.ref` | no | remote HEAD | Branch/ref to mirror. |
192
- | `wiki.source.mirrorPath` | no | `.lisa/wiki` | Where the gitignored mirror is materialized. `ensure-wiki` keeps this path gitignored automatically. |
193
- | `wiki.source.subdir` | no | auto | Wiki root within the cloned repo. Auto-detected as `wiki/` if present, else the repo root. |
194
- | `wiki.ttlSeconds` | no | `300` | Skip the refresh fetch if the mirror was synced more recently than this. |
195
-
196
- `scripts/ensure-wiki.mjs` is the single resolver (`node scripts/ensure-wiki.mjs --json` → `{mode, wikiRoot, …}`). LOCAL mode is a no-op that returns the in-repo `wikiRoot`; REMOTE mode clones-if-missing, fast-forwards when stale, and is offline-tolerant (proceeds with the existing mirror and warns rather than blocking). Callers (`lisa-wiki-query`, `lisa-wiki-ingest`) invoke it as step 0 and never hardcode `wiki/`; the freshness guarantee is the tool's, not the caller's.
194
+ | `wiki.source.path` | no | `wiki` (via convention) | **Local** wiki root, relative to the repo. The explicit form of the in-repo default. Mutually exclusive with `url`. |
195
+ | `wiki.source.url` | no | | Clone URL of a separate wiki repo. **Its presence selects REMOTE mode.** Mutually exclusive with `path`. |
196
+ | `wiki.source.ref` | no | remote HEAD | Branch/ref to mirror (remote only). |
197
+ | `wiki.source.mirrorPath` | no | `.lisa/wiki` | Where the gitignored mirror is materialized (remote only). `ensure-wiki` keeps this path gitignored automatically. |
198
+ | `wiki.source.subdir` | no | auto | Wiki root within the cloned repo (remote only). Auto-detected as `wiki/` if present, else the repo root. |
199
+ | `wiki.ttlSeconds` | no | `300` | Skip the refresh fetch if the mirror was synced more recently than this (remote only). |
200
+
201
+ `scripts/ensure-wiki.mjs` is the single resolver (`node scripts/ensure-wiki.mjs --json` → `{mode, wikiRoot, …}`). **LOCAL** mode (no `url`) is a no-op that resolves the wiki root in precedence order `wiki.source.path` → `wikiRoot` in `wiki/lisa-wiki.config.json` → `wiki`; **REMOTE** mode (`url` set) clones-if-missing, fast-forwards when stale, and is offline-tolerant (proceeds with the existing mirror and warns rather than blocking). Callers (`lisa-wiki-query`, `lisa-wiki-ingest`) invoke it as step 0 and never hardcode `wiki/`; the freshness guarantee is the tool's, not the caller's.
197
202
 
198
203
  ### Vendor sections
199
204
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.156.0",
3
+ "version": "2.157.0",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.156.0",
3
+ "version": "2.157.0",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.156.0",
3
+ "version": "2.157.0",
4
4
  "description": "AWS CDK-specific Lisa plugin.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.156.0",
3
+ "version": "2.157.0",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.156.0",
3
+ "version": "2.157.0",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.156.0",
3
+ "version": "2.157.0",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.156.0",
3
+ "version": "2.157.0",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -171,9 +171,13 @@ fi
171
171
 
172
172
  ### Wiki source (`wiki`)
173
173
 
174
- Declares **where this repo's LLM Wiki lives** so the query/ingest skills can resolve and (for a remote wiki) mirror it. This pointer belongs in the **consumer** repo's `.lisa.config.json` not in `wiki/lisa-wiki.config.json`, which describes a wiki from the inside and is unavailable until the remote wiki is mirrored (chicken-and-egg).
174
+ Declares **where this repo's LLM Wiki lives** so the query/ingest skills can resolve and (for a remote wiki) mirror it. `wiki.source` has two shapes — **local** (`path`) and **remote** (`url`) — and the block belongs in the **consumer** repo's `.lisa.config.json`, not in `wiki/lisa-wiki.config.json` (which describes a wiki from the inside and is unavailable until a remote wiki is mirrored chicken-and-egg). The whole `wiki` block is optional; omit it and the resolver falls back to the in-repo `wiki/` convention.
175
175
 
176
176
  ```json
177
+ // local: an explicit path (optional — equivalent to the default convention)
178
+ "wiki": { "source": { "path": "wiki" } }
179
+
180
+ // remote: mirror a separate wiki repo
177
181
  "wiki": {
178
182
  "source": {
179
183
  "url": "git@github.com:org/wiki.git",
@@ -187,13 +191,14 @@ Declares **where this repo's LLM Wiki lives** so the query/ingest skills can res
187
191
 
188
192
  | Field | Required | Default | Notes |
189
193
  |-------|----------|---------|-------|
190
- | `wiki.source.url` | no | | Clone URL of the canonical wiki repo. **Its presence selects REMOTE mode.** Omit the whole `wiki` block for a local in-repo wiki. |
191
- | `wiki.source.ref` | no | remote HEAD | Branch/ref to mirror. |
192
- | `wiki.source.mirrorPath` | no | `.lisa/wiki` | Where the gitignored mirror is materialized. `ensure-wiki` keeps this path gitignored automatically. |
193
- | `wiki.source.subdir` | no | auto | Wiki root within the cloned repo. Auto-detected as `wiki/` if present, else the repo root. |
194
- | `wiki.ttlSeconds` | no | `300` | Skip the refresh fetch if the mirror was synced more recently than this. |
195
-
196
- `scripts/ensure-wiki.mjs` is the single resolver (`node scripts/ensure-wiki.mjs --json` → `{mode, wikiRoot, …}`). LOCAL mode is a no-op that returns the in-repo `wikiRoot`; REMOTE mode clones-if-missing, fast-forwards when stale, and is offline-tolerant (proceeds with the existing mirror and warns rather than blocking). Callers (`lisa-wiki-query`, `lisa-wiki-ingest`) invoke it as step 0 and never hardcode `wiki/`; the freshness guarantee is the tool's, not the caller's.
194
+ | `wiki.source.path` | no | `wiki` (via convention) | **Local** wiki root, relative to the repo. The explicit form of the in-repo default. Mutually exclusive with `url`. |
195
+ | `wiki.source.url` | no | | Clone URL of a separate wiki repo. **Its presence selects REMOTE mode.** Mutually exclusive with `path`. |
196
+ | `wiki.source.ref` | no | remote HEAD | Branch/ref to mirror (remote only). |
197
+ | `wiki.source.mirrorPath` | no | `.lisa/wiki` | Where the gitignored mirror is materialized (remote only). `ensure-wiki` keeps this path gitignored automatically. |
198
+ | `wiki.source.subdir` | no | auto | Wiki root within the cloned repo (remote only). Auto-detected as `wiki/` if present, else the repo root. |
199
+ | `wiki.ttlSeconds` | no | `300` | Skip the refresh fetch if the mirror was synced more recently than this (remote only). |
200
+
201
+ `scripts/ensure-wiki.mjs` is the single resolver (`node scripts/ensure-wiki.mjs --json` → `{mode, wikiRoot, …}`). **LOCAL** mode (no `url`) is a no-op that resolves the wiki root in precedence order `wiki.source.path` → `wikiRoot` in `wiki/lisa-wiki.config.json` → `wiki`; **REMOTE** mode (`url` set) clones-if-missing, fast-forwards when stale, and is offline-tolerant (proceeds with the existing mirror and warns rather than blocking). Callers (`lisa-wiki-query`, `lisa-wiki-ingest`) invoke it as step 0 and never hardcode `wiki/`; the freshness guarantee is the tool's, not the caller's.
197
202
 
198
203
  ### Vendor sections
199
204
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.156.0",
3
+ "version": "2.157.0",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -176,9 +176,13 @@ fi
176
176
 
177
177
  ### Wiki source (`wiki`)
178
178
 
179
- Declares **where this repo's LLM Wiki lives** so the query/ingest skills can resolve and (for a remote wiki) mirror it. This pointer belongs in the **consumer** repo's `.lisa.config.json` not in `wiki/lisa-wiki.config.json`, which describes a wiki from the inside and is unavailable until the remote wiki is mirrored (chicken-and-egg).
179
+ Declares **where this repo's LLM Wiki lives** so the query/ingest skills can resolve and (for a remote wiki) mirror it. `wiki.source` has two shapes — **local** (`path`) and **remote** (`url`) — and the block belongs in the **consumer** repo's `.lisa.config.json`, not in `wiki/lisa-wiki.config.json` (which describes a wiki from the inside and is unavailable until a remote wiki is mirrored chicken-and-egg). The whole `wiki` block is optional; omit it and the resolver falls back to the in-repo `wiki/` convention.
180
180
 
181
181
  ```json
182
+ // local: an explicit path (optional — equivalent to the default convention)
183
+ "wiki": { "source": { "path": "wiki" } }
184
+
185
+ // remote: mirror a separate wiki repo
182
186
  "wiki": {
183
187
  "source": {
184
188
  "url": "git@github.com:org/wiki.git",
@@ -192,13 +196,14 @@ Declares **where this repo's LLM Wiki lives** so the query/ingest skills can res
192
196
 
193
197
  | Field | Required | Default | Notes |
194
198
  |-------|----------|---------|-------|
195
- | `wiki.source.url` | no | | Clone URL of the canonical wiki repo. **Its presence selects REMOTE mode.** Omit the whole `wiki` block for a local in-repo wiki. |
196
- | `wiki.source.ref` | no | remote HEAD | Branch/ref to mirror. |
197
- | `wiki.source.mirrorPath` | no | `.lisa/wiki` | Where the gitignored mirror is materialized. `ensure-wiki` keeps this path gitignored automatically. |
198
- | `wiki.source.subdir` | no | auto | Wiki root within the cloned repo. Auto-detected as `wiki/` if present, else the repo root. |
199
- | `wiki.ttlSeconds` | no | `300` | Skip the refresh fetch if the mirror was synced more recently than this. |
200
-
201
- `scripts/ensure-wiki.mjs` is the single resolver (`node scripts/ensure-wiki.mjs --json` → `{mode, wikiRoot, …}`). LOCAL mode is a no-op that returns the in-repo `wikiRoot`; REMOTE mode clones-if-missing, fast-forwards when stale, and is offline-tolerant (proceeds with the existing mirror and warns rather than blocking). Callers (`lisa-wiki-query`, `lisa-wiki-ingest`) invoke it as step 0 and never hardcode `wiki/`; the freshness guarantee is the tool's, not the caller's.
199
+ | `wiki.source.path` | no | `wiki` (via convention) | **Local** wiki root, relative to the repo. The explicit form of the in-repo default. Mutually exclusive with `url`. |
200
+ | `wiki.source.url` | no | | Clone URL of a separate wiki repo. **Its presence selects REMOTE mode.** Mutually exclusive with `path`. |
201
+ | `wiki.source.ref` | no | remote HEAD | Branch/ref to mirror (remote only). |
202
+ | `wiki.source.mirrorPath` | no | `.lisa/wiki` | Where the gitignored mirror is materialized (remote only). `ensure-wiki` keeps this path gitignored automatically. |
203
+ | `wiki.source.subdir` | no | auto | Wiki root within the cloned repo (remote only). Auto-detected as `wiki/` if present, else the repo root. |
204
+ | `wiki.ttlSeconds` | no | `300` | Skip the refresh fetch if the mirror was synced more recently than this (remote only). |
205
+
206
+ `scripts/ensure-wiki.mjs` is the single resolver (`node scripts/ensure-wiki.mjs --json` → `{mode, wikiRoot, …}`). **LOCAL** mode (no `url`) is a no-op that resolves the wiki root in precedence order `wiki.source.path` → `wikiRoot` in `wiki/lisa-wiki.config.json` → `wiki`; **REMOTE** mode (`url` set) clones-if-missing, fast-forwards when stale, and is offline-tolerant (proceeds with the existing mirror and warns rather than blocking). Callers (`lisa-wiki-query`, `lisa-wiki-ingest`) invoke it as step 0 and never hardcode `wiki/`; the freshness guarantee is the tool's, not the caller's.
202
207
 
203
208
  ### Vendor sections
204
209
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.156.0",
3
+ "version": "2.157.0",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.156.0",
3
+ "version": "2.157.0",
4
4
  "description": "Expo and React Native-specific skills, agents, rules, and MCP servers.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.156.0",
3
+ "version": "2.157.0",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.156.0",
3
+ "version": "2.157.0",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.156.0",
3
+ "version": "2.157.0",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.156.0",
3
+ "version": "2.157.0",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.156.0",
3
+ "version": "2.157.0",
4
4
  "description": "Harper/Fabric-specific Lisa rules for TypeScript component apps.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.156.0",
3
+ "version": "2.157.0",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.156.0",
3
+ "version": "2.157.0",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.156.0",
3
+ "version": "2.157.0",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.156.0",
3
+ "version": "2.157.0",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.156.0",
3
+ "version": "2.157.0",
4
4
  "description": "NestJS-specific skills and migration write-protection hooks.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.156.0",
3
+ "version": "2.157.0",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.156.0",
3
+ "version": "2.157.0",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.156.0",
3
+ "version": "2.157.0",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "2.156.0",
3
+ "version": "2.157.0",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "2.156.0",
3
+ "version": "2.157.0",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, across Claude and Codex.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "2.156.0",
3
+ "version": "2.157.0",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "2.156.0",
3
+ "version": "2.157.0",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "2.156.0",
3
+ "version": "2.157.0",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.156.0",
3
+ "version": "2.157.0",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.156.0",
3
+ "version": "2.157.0",
4
4
  "description": "Ruby on Rails-specific skills and hooks for RuboCop and ast-grep scanning on edit.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.156.0",
3
+ "version": "2.157.0",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.156.0",
3
+ "version": "2.157.0",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.156.0",
3
+ "version": "2.157.0",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.156.0",
3
+ "version": "2.157.0",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.156.0",
3
+ "version": "2.157.0",
4
4
  "description": "TypeScript-specific hooks for formatting, linting, and ast-grep scanning on edit.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.156.0",
3
+ "version": "2.157.0",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.156.0",
3
+ "version": "2.157.0",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.156.0",
3
+ "version": "2.157.0",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.156.0",
3
+ "version": "2.157.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": "2.156.0",
3
+ "version": "2.157.0",
4
4
  "description": "Distributable LLM Wiki kernel — ingest, query, lint, and maintain a git-native markdown knowledge base across Claude and Codex.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -8,19 +8,27 @@
8
8
  * call as step 0 so they never hardcode `wiki/` and never have to know whether
9
9
  * the wiki is local or remote. The mode decision lives HERE, not in the skills:
10
10
  *
11
- * - LOCAL — the wiki lives in this repo (the common case). Resolve the wiki
12
- * root from `wiki/lisa-wiki.config.json` (`wikiRoot`, default
13
- * `wiki`) and return it. No network, effectively a no-op.
11
+ * - LOCAL — the wiki lives on the local filesystem (the common case). Resolve
12
+ * the wiki root, in precedence order, from `wiki.source.path`, else
13
+ * `wikiRoot` in `wiki/lisa-wiki.config.json`, else `wiki`. No
14
+ * network, a no-op. `wiki.source.path` is just the explicit form of
15
+ * what the convention resolves implicitly.
14
16
  * - REMOTE — `.lisa.config.json` declares `wiki.source.url`. Maintain a
15
17
  * gitignored mirror of that repo and return the wiki root inside
16
18
  * it. Clone-if-missing, fetch+fast-forward when stale (TTL), and
17
19
  * tolerate being offline (proceed with the existing mirror + warn).
18
20
  *
21
+ * `url` (remote) and `path` (local) are the two shapes of `wiki.source`; `url`
22
+ * takes precedence if both are somehow present.
23
+ *
19
24
  * Config (consumer repo `.lisa.config.json`, with `.lisa.config.local.json`
20
25
  * overriding per the config-resolution rule):
21
26
  *
22
27
  * "wiki": {
23
28
  * "source": {
29
+ * // LOCAL shape — optional; defaults to the in-repo `wiki/` convention:
30
+ * "path": "wiki", // local wiki root, relative to repo root
31
+ * // REMOTE shape (instead of path):
24
32
  * "url": "git@github.com:org/wiki.git", // present => REMOTE mode
25
33
  * "ref": "main", // default: remote HEAD / "main"
26
34
  * "mirrorPath": ".lisa/wiki", // default; always gitignored
@@ -98,6 +106,9 @@ const ttlSeconds = Number(
98
106
  if (source.url !== undefined && typeof source.url !== "string") {
99
107
  fail("`wiki.source.url` in .lisa.config.json must be a string");
100
108
  }
109
+ if (source.path !== undefined && typeof source.path !== "string") {
110
+ fail("`wiki.source.path` in .lisa.config.json must be a string");
111
+ }
101
112
 
102
113
  function emit(result) {
103
114
  if (asJson) process.stdout.write(`${JSON.stringify(result)}\n`);
@@ -105,15 +116,24 @@ function emit(result) {
105
116
  process.exit(0);
106
117
  }
107
118
 
108
- // ── LOCAL mode ────────────────────────────────────────────────────────────────
119
+ // ── LOCAL mode (no remote clone) ───────────────────────────────────────────────
120
+ // The wiki lives on the local filesystem. Its root is, in precedence order:
121
+ // 1. `wiki.source.path` — explicit override in .lisa.config.json
122
+ // 2. `wikiRoot` from wiki/lisa-wiki.config.json — the in-repo convention
123
+ // 3. `wiki` — the default
124
+ // No network, a no-op resolve. `wiki.source.path` is just the explicit form of
125
+ // the same thing the convention resolves implicitly.
109
126
  if (!source.url) {
110
- const localCfg = readJsonSafe(
111
- path.join(projectDir, "wiki", "lisa-wiki.config.json")
127
+ const wikiRoot = path.resolve(
128
+ projectDir,
129
+ source.path ??
130
+ readJsonSafe(path.join(projectDir, "wiki", "lisa-wiki.config.json"))
131
+ ?.wikiRoot ??
132
+ "wiki"
112
133
  );
113
- const wikiRoot = path.resolve(projectDir, localCfg?.wikiRoot ?? "wiki");
114
134
  if (!fs.existsSync(path.join(wikiRoot, "index.md"))) {
115
135
  log(
116
- `⚠ no index.md under ${wikiRoot} — local wiki may not be scaffolded yet (run /lisa-wiki:setup)`
136
+ `⚠ no index.md under ${wikiRoot} — check wiki.source.path, or run /lisa-wiki:setup if the wiki is not scaffolded yet`
117
137
  );
118
138
  }
119
139
  log(`✓ local wiki: ${wikiRoot}`);
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.156.0",
3
+ "version": "2.157.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"
@@ -8,19 +8,27 @@
8
8
  * call as step 0 so they never hardcode `wiki/` and never have to know whether
9
9
  * the wiki is local or remote. The mode decision lives HERE, not in the skills:
10
10
  *
11
- * - LOCAL — the wiki lives in this repo (the common case). Resolve the wiki
12
- * root from `wiki/lisa-wiki.config.json` (`wikiRoot`, default
13
- * `wiki`) and return it. No network, effectively a no-op.
11
+ * - LOCAL — the wiki lives on the local filesystem (the common case). Resolve
12
+ * the wiki root, in precedence order, from `wiki.source.path`, else
13
+ * `wikiRoot` in `wiki/lisa-wiki.config.json`, else `wiki`. No
14
+ * network, a no-op. `wiki.source.path` is just the explicit form of
15
+ * what the convention resolves implicitly.
14
16
  * - REMOTE — `.lisa.config.json` declares `wiki.source.url`. Maintain a
15
17
  * gitignored mirror of that repo and return the wiki root inside
16
18
  * it. Clone-if-missing, fetch+fast-forward when stale (TTL), and
17
19
  * tolerate being offline (proceed with the existing mirror + warn).
18
20
  *
21
+ * `url` (remote) and `path` (local) are the two shapes of `wiki.source`; `url`
22
+ * takes precedence if both are somehow present.
23
+ *
19
24
  * Config (consumer repo `.lisa.config.json`, with `.lisa.config.local.json`
20
25
  * overriding per the config-resolution rule):
21
26
  *
22
27
  * "wiki": {
23
28
  * "source": {
29
+ * // LOCAL shape — optional; defaults to the in-repo `wiki/` convention:
30
+ * "path": "wiki", // local wiki root, relative to repo root
31
+ * // REMOTE shape (instead of path):
24
32
  * "url": "git@github.com:org/wiki.git", // present => REMOTE mode
25
33
  * "ref": "main", // default: remote HEAD / "main"
26
34
  * "mirrorPath": ".lisa/wiki", // default; always gitignored
@@ -98,6 +106,9 @@ const ttlSeconds = Number(
98
106
  if (source.url !== undefined && typeof source.url !== "string") {
99
107
  fail("`wiki.source.url` in .lisa.config.json must be a string");
100
108
  }
109
+ if (source.path !== undefined && typeof source.path !== "string") {
110
+ fail("`wiki.source.path` in .lisa.config.json must be a string");
111
+ }
101
112
 
102
113
  function emit(result) {
103
114
  if (asJson) process.stdout.write(`${JSON.stringify(result)}\n`);
@@ -105,15 +116,24 @@ function emit(result) {
105
116
  process.exit(0);
106
117
  }
107
118
 
108
- // ── LOCAL mode ────────────────────────────────────────────────────────────────
119
+ // ── LOCAL mode (no remote clone) ───────────────────────────────────────────────
120
+ // The wiki lives on the local filesystem. Its root is, in precedence order:
121
+ // 1. `wiki.source.path` — explicit override in .lisa.config.json
122
+ // 2. `wikiRoot` from wiki/lisa-wiki.config.json — the in-repo convention
123
+ // 3. `wiki` — the default
124
+ // No network, a no-op resolve. `wiki.source.path` is just the explicit form of
125
+ // the same thing the convention resolves implicitly.
109
126
  if (!source.url) {
110
- const localCfg = readJsonSafe(
111
- path.join(projectDir, "wiki", "lisa-wiki.config.json")
127
+ const wikiRoot = path.resolve(
128
+ projectDir,
129
+ source.path ??
130
+ readJsonSafe(path.join(projectDir, "wiki", "lisa-wiki.config.json"))
131
+ ?.wikiRoot ??
132
+ "wiki"
112
133
  );
113
- const wikiRoot = path.resolve(projectDir, localCfg?.wikiRoot ?? "wiki");
114
134
  if (!fs.existsSync(path.join(wikiRoot, "index.md"))) {
115
135
  log(
116
- `⚠ no index.md under ${wikiRoot} — local wiki may not be scaffolded yet (run /lisa-wiki:setup)`
136
+ `⚠ no index.md under ${wikiRoot} — check wiki.source.path, or run /lisa-wiki:setup if the wiki is not scaffolded yet`
117
137
  );
118
138
  }
119
139
  log(`✓ local wiki: ${wikiRoot}`);
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.156.0",
3
+ "version": "2.157.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"
@@ -8,19 +8,27 @@
8
8
  * call as step 0 so they never hardcode `wiki/` and never have to know whether
9
9
  * the wiki is local or remote. The mode decision lives HERE, not in the skills:
10
10
  *
11
- * - LOCAL — the wiki lives in this repo (the common case). Resolve the wiki
12
- * root from `wiki/lisa-wiki.config.json` (`wikiRoot`, default
13
- * `wiki`) and return it. No network, effectively a no-op.
11
+ * - LOCAL — the wiki lives on the local filesystem (the common case). Resolve
12
+ * the wiki root, in precedence order, from `wiki.source.path`, else
13
+ * `wikiRoot` in `wiki/lisa-wiki.config.json`, else `wiki`. No
14
+ * network, a no-op. `wiki.source.path` is just the explicit form of
15
+ * what the convention resolves implicitly.
14
16
  * - REMOTE — `.lisa.config.json` declares `wiki.source.url`. Maintain a
15
17
  * gitignored mirror of that repo and return the wiki root inside
16
18
  * it. Clone-if-missing, fetch+fast-forward when stale (TTL), and
17
19
  * tolerate being offline (proceed with the existing mirror + warn).
18
20
  *
21
+ * `url` (remote) and `path` (local) are the two shapes of `wiki.source`; `url`
22
+ * takes precedence if both are somehow present.
23
+ *
19
24
  * Config (consumer repo `.lisa.config.json`, with `.lisa.config.local.json`
20
25
  * overriding per the config-resolution rule):
21
26
  *
22
27
  * "wiki": {
23
28
  * "source": {
29
+ * // LOCAL shape — optional; defaults to the in-repo `wiki/` convention:
30
+ * "path": "wiki", // local wiki root, relative to repo root
31
+ * // REMOTE shape (instead of path):
24
32
  * "url": "git@github.com:org/wiki.git", // present => REMOTE mode
25
33
  * "ref": "main", // default: remote HEAD / "main"
26
34
  * "mirrorPath": ".lisa/wiki", // default; always gitignored
@@ -98,6 +106,9 @@ const ttlSeconds = Number(
98
106
  if (source.url !== undefined && typeof source.url !== "string") {
99
107
  fail("`wiki.source.url` in .lisa.config.json must be a string");
100
108
  }
109
+ if (source.path !== undefined && typeof source.path !== "string") {
110
+ fail("`wiki.source.path` in .lisa.config.json must be a string");
111
+ }
101
112
 
102
113
  function emit(result) {
103
114
  if (asJson) process.stdout.write(`${JSON.stringify(result)}\n`);
@@ -105,15 +116,24 @@ function emit(result) {
105
116
  process.exit(0);
106
117
  }
107
118
 
108
- // ── LOCAL mode ────────────────────────────────────────────────────────────────
119
+ // ── LOCAL mode (no remote clone) ───────────────────────────────────────────────
120
+ // The wiki lives on the local filesystem. Its root is, in precedence order:
121
+ // 1. `wiki.source.path` — explicit override in .lisa.config.json
122
+ // 2. `wikiRoot` from wiki/lisa-wiki.config.json — the in-repo convention
123
+ // 3. `wiki` — the default
124
+ // No network, a no-op resolve. `wiki.source.path` is just the explicit form of
125
+ // the same thing the convention resolves implicitly.
109
126
  if (!source.url) {
110
- const localCfg = readJsonSafe(
111
- path.join(projectDir, "wiki", "lisa-wiki.config.json")
127
+ const wikiRoot = path.resolve(
128
+ projectDir,
129
+ source.path ??
130
+ readJsonSafe(path.join(projectDir, "wiki", "lisa-wiki.config.json"))
131
+ ?.wikiRoot ??
132
+ "wiki"
112
133
  );
113
- const wikiRoot = path.resolve(projectDir, localCfg?.wikiRoot ?? "wiki");
114
134
  if (!fs.existsSync(path.join(wikiRoot, "index.md"))) {
115
135
  log(
116
- `⚠ no index.md under ${wikiRoot} — local wiki may not be scaffolded yet (run /lisa-wiki:setup)`
136
+ `⚠ no index.md under ${wikiRoot} — check wiki.source.path, or run /lisa-wiki:setup if the wiki is not scaffolded yet`
117
137
  );
118
138
  }
119
139
  log(`✓ local wiki: ${wikiRoot}`);
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.156.0",
3
+ "version": "2.157.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"
@@ -8,19 +8,27 @@
8
8
  * call as step 0 so they never hardcode `wiki/` and never have to know whether
9
9
  * the wiki is local or remote. The mode decision lives HERE, not in the skills:
10
10
  *
11
- * - LOCAL — the wiki lives in this repo (the common case). Resolve the wiki
12
- * root from `wiki/lisa-wiki.config.json` (`wikiRoot`, default
13
- * `wiki`) and return it. No network, effectively a no-op.
11
+ * - LOCAL — the wiki lives on the local filesystem (the common case). Resolve
12
+ * the wiki root, in precedence order, from `wiki.source.path`, else
13
+ * `wikiRoot` in `wiki/lisa-wiki.config.json`, else `wiki`. No
14
+ * network, a no-op. `wiki.source.path` is just the explicit form of
15
+ * what the convention resolves implicitly.
14
16
  * - REMOTE — `.lisa.config.json` declares `wiki.source.url`. Maintain a
15
17
  * gitignored mirror of that repo and return the wiki root inside
16
18
  * it. Clone-if-missing, fetch+fast-forward when stale (TTL), and
17
19
  * tolerate being offline (proceed with the existing mirror + warn).
18
20
  *
21
+ * `url` (remote) and `path` (local) are the two shapes of `wiki.source`; `url`
22
+ * takes precedence if both are somehow present.
23
+ *
19
24
  * Config (consumer repo `.lisa.config.json`, with `.lisa.config.local.json`
20
25
  * overriding per the config-resolution rule):
21
26
  *
22
27
  * "wiki": {
23
28
  * "source": {
29
+ * // LOCAL shape — optional; defaults to the in-repo `wiki/` convention:
30
+ * "path": "wiki", // local wiki root, relative to repo root
31
+ * // REMOTE shape (instead of path):
24
32
  * "url": "git@github.com:org/wiki.git", // present => REMOTE mode
25
33
  * "ref": "main", // default: remote HEAD / "main"
26
34
  * "mirrorPath": ".lisa/wiki", // default; always gitignored
@@ -98,6 +106,9 @@ const ttlSeconds = Number(
98
106
  if (source.url !== undefined && typeof source.url !== "string") {
99
107
  fail("`wiki.source.url` in .lisa.config.json must be a string");
100
108
  }
109
+ if (source.path !== undefined && typeof source.path !== "string") {
110
+ fail("`wiki.source.path` in .lisa.config.json must be a string");
111
+ }
101
112
 
102
113
  function emit(result) {
103
114
  if (asJson) process.stdout.write(`${JSON.stringify(result)}\n`);
@@ -105,15 +116,24 @@ function emit(result) {
105
116
  process.exit(0);
106
117
  }
107
118
 
108
- // ── LOCAL mode ────────────────────────────────────────────────────────────────
119
+ // ── LOCAL mode (no remote clone) ───────────────────────────────────────────────
120
+ // The wiki lives on the local filesystem. Its root is, in precedence order:
121
+ // 1. `wiki.source.path` — explicit override in .lisa.config.json
122
+ // 2. `wikiRoot` from wiki/lisa-wiki.config.json — the in-repo convention
123
+ // 3. `wiki` — the default
124
+ // No network, a no-op resolve. `wiki.source.path` is just the explicit form of
125
+ // the same thing the convention resolves implicitly.
109
126
  if (!source.url) {
110
- const localCfg = readJsonSafe(
111
- path.join(projectDir, "wiki", "lisa-wiki.config.json")
127
+ const wikiRoot = path.resolve(
128
+ projectDir,
129
+ source.path ??
130
+ readJsonSafe(path.join(projectDir, "wiki", "lisa-wiki.config.json"))
131
+ ?.wikiRoot ??
132
+ "wiki"
112
133
  );
113
- const wikiRoot = path.resolve(projectDir, localCfg?.wikiRoot ?? "wiki");
114
134
  if (!fs.existsSync(path.join(wikiRoot, "index.md"))) {
115
135
  log(
116
- `⚠ no index.md under ${wikiRoot} — local wiki may not be scaffolded yet (run /lisa-wiki:setup)`
136
+ `⚠ no index.md under ${wikiRoot} — check wiki.source.path, or run /lisa-wiki:setup if the wiki is not scaffolded yet`
117
137
  );
118
138
  }
119
139
  log(`✓ local wiki: ${wikiRoot}`);
@@ -171,9 +171,13 @@ fi
171
171
 
172
172
  ### Wiki source (`wiki`)
173
173
 
174
- Declares **where this repo's LLM Wiki lives** so the query/ingest skills can resolve and (for a remote wiki) mirror it. This pointer belongs in the **consumer** repo's `.lisa.config.json` not in `wiki/lisa-wiki.config.json`, which describes a wiki from the inside and is unavailable until the remote wiki is mirrored (chicken-and-egg).
174
+ Declares **where this repo's LLM Wiki lives** so the query/ingest skills can resolve and (for a remote wiki) mirror it. `wiki.source` has two shapes — **local** (`path`) and **remote** (`url`) — and the block belongs in the **consumer** repo's `.lisa.config.json`, not in `wiki/lisa-wiki.config.json` (which describes a wiki from the inside and is unavailable until a remote wiki is mirrored chicken-and-egg). The whole `wiki` block is optional; omit it and the resolver falls back to the in-repo `wiki/` convention.
175
175
 
176
176
  ```json
177
+ // local: an explicit path (optional — equivalent to the default convention)
178
+ "wiki": { "source": { "path": "wiki" } }
179
+
180
+ // remote: mirror a separate wiki repo
177
181
  "wiki": {
178
182
  "source": {
179
183
  "url": "git@github.com:org/wiki.git",
@@ -187,13 +191,14 @@ Declares **where this repo's LLM Wiki lives** so the query/ingest skills can res
187
191
 
188
192
  | Field | Required | Default | Notes |
189
193
  |-------|----------|---------|-------|
190
- | `wiki.source.url` | no | | Clone URL of the canonical wiki repo. **Its presence selects REMOTE mode.** Omit the whole `wiki` block for a local in-repo wiki. |
191
- | `wiki.source.ref` | no | remote HEAD | Branch/ref to mirror. |
192
- | `wiki.source.mirrorPath` | no | `.lisa/wiki` | Where the gitignored mirror is materialized. `ensure-wiki` keeps this path gitignored automatically. |
193
- | `wiki.source.subdir` | no | auto | Wiki root within the cloned repo. Auto-detected as `wiki/` if present, else the repo root. |
194
- | `wiki.ttlSeconds` | no | `300` | Skip the refresh fetch if the mirror was synced more recently than this. |
195
-
196
- `scripts/ensure-wiki.mjs` is the single resolver (`node scripts/ensure-wiki.mjs --json` → `{mode, wikiRoot, …}`). LOCAL mode is a no-op that returns the in-repo `wikiRoot`; REMOTE mode clones-if-missing, fast-forwards when stale, and is offline-tolerant (proceeds with the existing mirror and warns rather than blocking). Callers (`lisa-wiki-query`, `lisa-wiki-ingest`) invoke it as step 0 and never hardcode `wiki/`; the freshness guarantee is the tool's, not the caller's.
194
+ | `wiki.source.path` | no | `wiki` (via convention) | **Local** wiki root, relative to the repo. The explicit form of the in-repo default. Mutually exclusive with `url`. |
195
+ | `wiki.source.url` | no | | Clone URL of a separate wiki repo. **Its presence selects REMOTE mode.** Mutually exclusive with `path`. |
196
+ | `wiki.source.ref` | no | remote HEAD | Branch/ref to mirror (remote only). |
197
+ | `wiki.source.mirrorPath` | no | `.lisa/wiki` | Where the gitignored mirror is materialized (remote only). `ensure-wiki` keeps this path gitignored automatically. |
198
+ | `wiki.source.subdir` | no | auto | Wiki root within the cloned repo (remote only). Auto-detected as `wiki/` if present, else the repo root. |
199
+ | `wiki.ttlSeconds` | no | `300` | Skip the refresh fetch if the mirror was synced more recently than this (remote only). |
200
+
201
+ `scripts/ensure-wiki.mjs` is the single resolver (`node scripts/ensure-wiki.mjs --json` → `{mode, wikiRoot, …}`). **LOCAL** mode (no `url`) is a no-op that resolves the wiki root in precedence order `wiki.source.path` → `wikiRoot` in `wiki/lisa-wiki.config.json` → `wiki`; **REMOTE** mode (`url` set) clones-if-missing, fast-forwards when stale, and is offline-tolerant (proceeds with the existing mirror and warns rather than blocking). Callers (`lisa-wiki-query`, `lisa-wiki-ingest`) invoke it as step 0 and never hardcode `wiki/`; the freshness guarantee is the tool's, not the caller's.
197
202
 
198
203
  ### Vendor sections
199
204
 
@@ -8,19 +8,27 @@
8
8
  * call as step 0 so they never hardcode `wiki/` and never have to know whether
9
9
  * the wiki is local or remote. The mode decision lives HERE, not in the skills:
10
10
  *
11
- * - LOCAL — the wiki lives in this repo (the common case). Resolve the wiki
12
- * root from `wiki/lisa-wiki.config.json` (`wikiRoot`, default
13
- * `wiki`) and return it. No network, effectively a no-op.
11
+ * - LOCAL — the wiki lives on the local filesystem (the common case). Resolve
12
+ * the wiki root, in precedence order, from `wiki.source.path`, else
13
+ * `wikiRoot` in `wiki/lisa-wiki.config.json`, else `wiki`. No
14
+ * network, a no-op. `wiki.source.path` is just the explicit form of
15
+ * what the convention resolves implicitly.
14
16
  * - REMOTE — `.lisa.config.json` declares `wiki.source.url`. Maintain a
15
17
  * gitignored mirror of that repo and return the wiki root inside
16
18
  * it. Clone-if-missing, fetch+fast-forward when stale (TTL), and
17
19
  * tolerate being offline (proceed with the existing mirror + warn).
18
20
  *
21
+ * `url` (remote) and `path` (local) are the two shapes of `wiki.source`; `url`
22
+ * takes precedence if both are somehow present.
23
+ *
19
24
  * Config (consumer repo `.lisa.config.json`, with `.lisa.config.local.json`
20
25
  * overriding per the config-resolution rule):
21
26
  *
22
27
  * "wiki": {
23
28
  * "source": {
29
+ * // LOCAL shape — optional; defaults to the in-repo `wiki/` convention:
30
+ * "path": "wiki", // local wiki root, relative to repo root
31
+ * // REMOTE shape (instead of path):
24
32
  * "url": "git@github.com:org/wiki.git", // present => REMOTE mode
25
33
  * "ref": "main", // default: remote HEAD / "main"
26
34
  * "mirrorPath": ".lisa/wiki", // default; always gitignored
@@ -98,6 +106,9 @@ const ttlSeconds = Number(
98
106
  if (source.url !== undefined && typeof source.url !== "string") {
99
107
  fail("`wiki.source.url` in .lisa.config.json must be a string");
100
108
  }
109
+ if (source.path !== undefined && typeof source.path !== "string") {
110
+ fail("`wiki.source.path` in .lisa.config.json must be a string");
111
+ }
101
112
 
102
113
  function emit(result) {
103
114
  if (asJson) process.stdout.write(`${JSON.stringify(result)}\n`);
@@ -105,15 +116,24 @@ function emit(result) {
105
116
  process.exit(0);
106
117
  }
107
118
 
108
- // ── LOCAL mode ────────────────────────────────────────────────────────────────
119
+ // ── LOCAL mode (no remote clone) ───────────────────────────────────────────────
120
+ // The wiki lives on the local filesystem. Its root is, in precedence order:
121
+ // 1. `wiki.source.path` — explicit override in .lisa.config.json
122
+ // 2. `wikiRoot` from wiki/lisa-wiki.config.json — the in-repo convention
123
+ // 3. `wiki` — the default
124
+ // No network, a no-op resolve. `wiki.source.path` is just the explicit form of
125
+ // the same thing the convention resolves implicitly.
109
126
  if (!source.url) {
110
- const localCfg = readJsonSafe(
111
- path.join(projectDir, "wiki", "lisa-wiki.config.json")
127
+ const wikiRoot = path.resolve(
128
+ projectDir,
129
+ source.path ??
130
+ readJsonSafe(path.join(projectDir, "wiki", "lisa-wiki.config.json"))
131
+ ?.wikiRoot ??
132
+ "wiki"
112
133
  );
113
- const wikiRoot = path.resolve(projectDir, localCfg?.wikiRoot ?? "wiki");
114
134
  if (!fs.existsSync(path.join(wikiRoot, "index.md"))) {
115
135
  log(
116
- `⚠ no index.md under ${wikiRoot} — local wiki may not be scaffolded yet (run /lisa-wiki:setup)`
136
+ `⚠ no index.md under ${wikiRoot} — check wiki.source.path, or run /lisa-wiki:setup if the wiki is not scaffolded yet`
117
137
  );
118
138
  }
119
139
  log(`✓ local wiki: ${wikiRoot}`);