@codyswann/lisa 3.2.0 → 3.4.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 (175) hide show
  1. package/dist/cli/doctor-lisa-owned-artifacts.d.ts.map +1 -1
  2. package/dist/cli/doctor-lisa-owned-artifacts.js +41 -2
  3. package/dist/cli/doctor-lisa-owned-artifacts.js.map +1 -1
  4. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  5. package/dist/core/upstream-evidence-manifest.js +90 -16
  6. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  7. package/expo/create-only/.github/workflows/nightly-e2e-health.yml +21 -2
  8. package/package.json +1 -1
  9. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  10. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  11. package/plugins/lisa/.codex-plugin/skills/lisa-implement/SKILL.md +3 -1
  12. package/plugins/lisa/.codex-plugin/skills/lisa-quality-review/SKILL.md +7 -0
  13. package/plugins/lisa/.codex-plugin/skills/lisa-review-local/SKILL.md +27 -0
  14. package/plugins/lisa/.codex-plugin/skills/lisa-tdd-implementation/SKILL.md +1 -0
  15. package/plugins/lisa/.codex-plugin/skills/lisa-tracker-source-artifacts/SKILL.md +2 -0
  16. package/plugins/lisa/rules/eager/design-source-of-truth.md +38 -0
  17. package/plugins/lisa/rules/eager/do-it-now.md +11 -0
  18. package/plugins/lisa/rules/eager/empirical-inquiry.md +1 -0
  19. package/plugins/lisa/rules/eager/falsifiable-checks.md +2 -0
  20. package/plugins/lisa/rules/eager/integration-access-layer.md +5 -0
  21. package/plugins/lisa/rules/eager/learnings-ladder.md +18 -0
  22. package/plugins/lisa/rules/eager/local-ci-first.md +15 -0
  23. package/plugins/lisa/rules/eager/not-blocked-just-waiting.md +13 -0
  24. package/plugins/lisa/rules/eager/session-status-updates.md +19 -0
  25. package/plugins/lisa/rules/eager/wiki-knowledge-source.md +6 -11
  26. package/plugins/lisa/rules/reference/design-source-of-truth.md +195 -0
  27. package/plugins/lisa/rules/reference/do-it-now.md +37 -0
  28. package/plugins/lisa/rules/reference/empirical-inquiry.md +1 -0
  29. package/plugins/lisa/rules/reference/falsifiable-checks.md +24 -2
  30. package/plugins/lisa/rules/reference/integration-access-layer.md +8 -0
  31. package/plugins/lisa/rules/reference/learnings-ladder.md +41 -0
  32. package/plugins/lisa/rules/reference/local-ci-first.md +34 -0
  33. package/plugins/lisa/rules/reference/not-blocked-just-waiting.md +41 -0
  34. package/plugins/lisa/rules/reference/session-status-updates.md +60 -0
  35. package/plugins/lisa/rules/reference/wiki-knowledge-source.md +21 -5
  36. package/plugins/lisa/scripts/design-source-gate.mjs +530 -0
  37. package/plugins/lisa/skills/lisa-implement/SKILL.md +3 -1
  38. package/plugins/lisa/skills/lisa-quality-review/SKILL.md +7 -0
  39. package/plugins/lisa/skills/lisa-review-local/SKILL.md +27 -0
  40. package/plugins/lisa/skills/lisa-tdd-implementation/SKILL.md +1 -0
  41. package/plugins/lisa/skills/lisa-tracker-source-artifacts/SKILL.md +2 -0
  42. package/plugins/lisa-agy/plugin.json +1 -1
  43. package/plugins/lisa-agy/scripts/design-source-gate.mjs +530 -0
  44. package/plugins/lisa-agy/skills/lisa-implement/SKILL.md +3 -1
  45. package/plugins/lisa-agy/skills/lisa-quality-review/SKILL.md +7 -0
  46. package/plugins/lisa-agy/skills/lisa-review-local/SKILL.md +27 -0
  47. package/plugins/lisa-agy/skills/lisa-tdd-implementation/SKILL.md +1 -0
  48. package/plugins/lisa-agy/skills/lisa-tracker-source-artifacts/SKILL.md +2 -0
  49. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  50. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  51. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  52. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  53. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  54. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  55. package/plugins/lisa-copilot/rules/eager/design-source-of-truth.md +38 -0
  56. package/plugins/lisa-copilot/rules/eager/do-it-now.md +11 -0
  57. package/plugins/lisa-copilot/rules/eager/empirical-inquiry.md +1 -0
  58. package/plugins/lisa-copilot/rules/eager/falsifiable-checks.md +2 -0
  59. package/plugins/lisa-copilot/rules/eager/integration-access-layer.md +5 -0
  60. package/plugins/lisa-copilot/rules/eager/learnings-ladder.md +18 -0
  61. package/plugins/lisa-copilot/rules/eager/local-ci-first.md +15 -0
  62. package/plugins/lisa-copilot/rules/eager/not-blocked-just-waiting.md +13 -0
  63. package/plugins/lisa-copilot/rules/eager/session-status-updates.md +19 -0
  64. package/plugins/lisa-copilot/rules/eager/wiki-knowledge-source.md +6 -11
  65. package/plugins/lisa-copilot/rules/reference/design-source-of-truth.md +195 -0
  66. package/plugins/lisa-copilot/rules/reference/do-it-now.md +37 -0
  67. package/plugins/lisa-copilot/rules/reference/empirical-inquiry.md +1 -0
  68. package/plugins/lisa-copilot/rules/reference/falsifiable-checks.md +24 -2
  69. package/plugins/lisa-copilot/rules/reference/integration-access-layer.md +8 -0
  70. package/plugins/lisa-copilot/rules/reference/learnings-ladder.md +41 -0
  71. package/plugins/lisa-copilot/rules/reference/local-ci-first.md +34 -0
  72. package/plugins/lisa-copilot/rules/reference/not-blocked-just-waiting.md +41 -0
  73. package/plugins/lisa-copilot/rules/reference/session-status-updates.md +60 -0
  74. package/plugins/lisa-copilot/rules/reference/wiki-knowledge-source.md +21 -5
  75. package/plugins/lisa-copilot/scripts/design-source-gate.mjs +530 -0
  76. package/plugins/lisa-copilot/skills/lisa-implement/SKILL.md +3 -1
  77. package/plugins/lisa-copilot/skills/lisa-quality-review/SKILL.md +7 -0
  78. package/plugins/lisa-copilot/skills/lisa-review-local/SKILL.md +27 -0
  79. package/plugins/lisa-copilot/skills/lisa-tdd-implementation/SKILL.md +1 -0
  80. package/plugins/lisa-copilot/skills/lisa-tracker-source-artifacts/SKILL.md +2 -0
  81. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  82. package/plugins/lisa-cursor/rules/design-source-of-truth-reference.mdc +200 -0
  83. package/plugins/lisa-cursor/rules/design-source-of-truth.mdc +43 -0
  84. package/plugins/lisa-cursor/rules/do-it-now-reference.mdc +42 -0
  85. package/plugins/lisa-cursor/rules/do-it-now.mdc +16 -0
  86. package/plugins/lisa-cursor/rules/empirical-inquiry-reference.mdc +1 -0
  87. package/plugins/lisa-cursor/rules/empirical-inquiry.mdc +1 -0
  88. package/plugins/lisa-cursor/rules/falsifiable-checks-reference.mdc +24 -2
  89. package/plugins/lisa-cursor/rules/falsifiable-checks.mdc +2 -0
  90. package/plugins/lisa-cursor/rules/integration-access-layer-reference.mdc +8 -0
  91. package/plugins/lisa-cursor/rules/integration-access-layer.mdc +5 -0
  92. package/plugins/lisa-cursor/rules/learnings-ladder-reference.mdc +46 -0
  93. package/plugins/lisa-cursor/rules/learnings-ladder.mdc +23 -0
  94. package/plugins/lisa-cursor/rules/local-ci-first-reference.mdc +39 -0
  95. package/plugins/lisa-cursor/rules/local-ci-first.mdc +20 -0
  96. package/plugins/lisa-cursor/rules/not-blocked-just-waiting-reference.mdc +46 -0
  97. package/plugins/lisa-cursor/rules/not-blocked-just-waiting.mdc +18 -0
  98. package/plugins/lisa-cursor/rules/session-status-updates-reference.mdc +65 -0
  99. package/plugins/lisa-cursor/rules/session-status-updates.mdc +24 -0
  100. package/plugins/lisa-cursor/rules/wiki-knowledge-source-reference.mdc +21 -5
  101. package/plugins/lisa-cursor/rules/wiki-knowledge-source.mdc +7 -12
  102. package/plugins/lisa-cursor/scripts/design-source-gate.mjs +530 -0
  103. package/plugins/lisa-cursor/skills/lisa-implement/SKILL.md +3 -1
  104. package/plugins/lisa-cursor/skills/lisa-quality-review/SKILL.md +7 -0
  105. package/plugins/lisa-cursor/skills/lisa-review-local/SKILL.md +27 -0
  106. package/plugins/lisa-cursor/skills/lisa-tdd-implementation/SKILL.md +1 -0
  107. package/plugins/lisa-cursor/skills/lisa-tracker-source-artifacts/SKILL.md +2 -0
  108. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  109. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  110. package/plugins/lisa-expo-agy/plugin.json +1 -1
  111. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  112. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  113. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  114. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  115. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  116. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  117. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  118. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  119. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  120. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  121. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  122. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  123. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  124. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  125. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  126. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  127. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  128. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  129. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  130. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  131. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  132. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  133. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  134. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  135. package/plugins/lisa-rails-agy/plugin.json +1 -1
  136. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  137. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  138. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  139. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  140. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  141. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  142. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  143. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  144. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  145. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  146. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  147. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  148. package/plugins/src/base/rules/eager/design-source-of-truth.md +38 -0
  149. package/plugins/src/base/rules/eager/do-it-now.md +11 -0
  150. package/plugins/src/base/rules/eager/empirical-inquiry.md +1 -0
  151. package/plugins/src/base/rules/eager/falsifiable-checks.md +2 -0
  152. package/plugins/src/base/rules/eager/integration-access-layer.md +5 -0
  153. package/plugins/src/base/rules/eager/learnings-ladder.md +18 -0
  154. package/plugins/src/base/rules/eager/local-ci-first.md +15 -0
  155. package/plugins/src/base/rules/eager/not-blocked-just-waiting.md +13 -0
  156. package/plugins/src/base/rules/eager/session-status-updates.md +19 -0
  157. package/plugins/src/base/rules/eager/wiki-knowledge-source.md +6 -11
  158. package/plugins/src/base/rules/reference/design-source-of-truth.md +195 -0
  159. package/plugins/src/base/rules/reference/do-it-now.md +37 -0
  160. package/plugins/src/base/rules/reference/empirical-inquiry.md +1 -0
  161. package/plugins/src/base/rules/reference/falsifiable-checks.md +24 -2
  162. package/plugins/src/base/rules/reference/integration-access-layer.md +8 -0
  163. package/plugins/src/base/rules/reference/learnings-ladder.md +41 -0
  164. package/plugins/src/base/rules/reference/local-ci-first.md +34 -0
  165. package/plugins/src/base/rules/reference/not-blocked-just-waiting.md +41 -0
  166. package/plugins/src/base/rules/reference/session-status-updates.md +60 -0
  167. package/plugins/src/base/rules/reference/wiki-knowledge-source.md +21 -5
  168. package/plugins/src/base/scripts/design-source-gate.mjs +530 -0
  169. package/plugins/src/base/skills/lisa-implement/SKILL.md +3 -1
  170. package/plugins/src/base/skills/lisa-quality-review/SKILL.md +7 -0
  171. package/plugins/src/base/skills/lisa-review-local/SKILL.md +27 -0
  172. package/plugins/src/base/skills/lisa-tdd-implementation/SKILL.md +1 -0
  173. package/plugins/src/base/skills/lisa-tracker-source-artifacts/SKILL.md +2 -0
  174. package/typescript/copy-overwrite/scripts/check-nightly-e2e-health.mjs +173 -8
  175. package/typescript/copy-overwrite/scripts/nightly-e2e-suites.schema.json +12 -0
@@ -0,0 +1,195 @@
1
+ # Design Source of Truth
2
+
3
+ Design has always leaked in one direction. A ticket arrives with a Figma frame, the frame gets
4
+ built, and then — during implementation, during a bug fix, during a "quick" empty state nobody
5
+ specified — new UI gets invented directly in code. Nothing ever carries it back. A year later the
6
+ Figma file describes a product that no longer exists, and the only way to answer "what is this
7
+ screen supposed to look like?" is to read the code, which is precisely the question the design
8
+ source was supposed to answer.
9
+
10
+ Lisa had every design obligation conditioned on a design artifact *already existing*. Ticket gate
11
+ S12 fires only `when artifacts_attached = true`. `work-item-definition-of-ready` requires
12
+ design-source precedence "when artifacts exist". `lisa-implement` treats a linked Figma file as a
13
+ required tool and hard-stops when access to it fails. The nearest adjacent behavior —
14
+ `lisa-tracker-source-artifacts` asking UI tickets to flag design-vs-code divergence — files that
15
+ divergence as a *ticket comment*, which closes with the ticket.
16
+
17
+ Every one of those is about UI that has a source. **None of them govern UI that has none.** That is
18
+ the gap this contract closes, and it closes it on the code side, where the invented UI actually
19
+ lives.
20
+
21
+ ## What the contract asks
22
+
23
+ One question, per UI surface a change touches: **where did this design come from?**
24
+
25
+ Not "is it pretty", not "does it use the right token", not "should this component exist" — those are
26
+ the host design system's questions, and it answers them far better than a vendor-neutral contract
27
+ could. This contract asks only whether the answer to the provenance question is written down.
28
+
29
+ ## Membership
30
+
31
+ A file is a UI surface when a change makes it render something user-observable: a screen,
32
+ component, layout, style token, visual state, or markup a user reads. The gate's default detection
33
+ is two-tier, and the split is deliberate:
34
+
35
+ - **Extensions that always render** — `.tsx`, `.jsx`, `.vue`, `.svelte` — count wherever they live.
36
+ - **Markup and style extensions** — `.css`, `.scss`, `.sass`, `.less`, `.styl`, `.html`, `.erb`,
37
+ `.haml`, `.slim`, `.swift`, `.kt`, `.dart`, `.xml` — count only inside a rendering directory
38
+ (`components`, `screens`, `views`, `pages`, `ui`, `widgets`, `layouts`, `templates`, `atoms`,
39
+ `molecules`, `organisms`).
40
+
41
+ The second tier is why a `.ts` barrel under `components/` is out: `src/components/atoms/index.ts`
42
+ re-exports and renders nothing, so demanding a design source from it would be noise, and noise is
43
+ how a gate earns its way into an ignore list. Tests, specs, stories, snapshots, `.d.ts` declarations,
44
+ `node_modules`, and build output are excluded for the same reason.
45
+
46
+ Projects tune this in `.lisa.config.json`:
47
+
48
+ ```json
49
+ {
50
+ "designSource": {
51
+ "include": ["**/*.mjml"],
52
+ "exclude": ["src/legacy/**"]
53
+ }
54
+ }
55
+ ```
56
+
57
+ `include` widens the surface; `exclude` narrows it. Neither turns the obligation off — a project that
58
+ excluded its whole UI tree would be declaring it has no UI, which review can see.
59
+
60
+ ## The marker grammar
61
+
62
+ Exactly one declaration per file, written as an ordinary comment in whatever syntax the file already
63
+ uses. The gate reads the annotation, not the comment characters around it, so all of these are the
64
+ same declaration:
65
+
66
+ ```tsx
67
+ // DESIGN-SOURCE: https://www.figma.com/design/AbC123/Checkout?node-id=412-1187
68
+ ```
69
+
70
+ ```css
71
+ /* DESIGN-SOURCE: none — not in Figma */
72
+ ```
73
+
74
+ ```svelte
75
+ <!-- DESIGN-SOURCE: none — not in Figma — internal-only debug affordance -->
76
+ ```
77
+
78
+ ### `DESIGN-SOURCE: <figma-url>` — sealed
79
+
80
+ The surface is backed by a design node. Only a `figma.com` URL counts. A screenshot link, a Slack
81
+ permalink, a Jira attachment, or a path to a PNG in the repo is **malformed**, not proof: those are
82
+ copies of a design, and a copy cannot be updated when the design changes. Prefer a URL carrying a
83
+ `node-id` so the citation resolves to the frame rather than the file.
84
+
85
+ ### `DESIGN-SOURCE: none — not in Figma` — the recorded exception
86
+
87
+ The spelling is fixed, including the em dash, and it is load-bearing: the gate, the rule, the review
88
+ path, and the implement path all cite the same string, so a drifted spelling silently disarms the
89
+ gate rather than failing loudly. An optional trailing ` — <reason>` records why the surface is not
90
+ captured at the source, and the gate surfaces reasonless markers separately (below).
91
+
92
+ ### Everything else
93
+
94
+ `DESIGN-SOURCE:` followed by anything that is neither form is **malformed** and fails. This is not
95
+ pedantry — it is what stops the annotation from degrading into a comment that says "design source:
96
+ ask Priya" and passes. **Silence is a violation, never a pass.**
97
+
98
+ A file that carries both a Figma URL and the none-marker is **conflicting** and fails. It is
99
+ asserting two contradictory things about the same surface, and the gate does not pick a winner.
100
+
101
+ ## Sync-back is the default
102
+
103
+ The order of preference is not decorative:
104
+
105
+ 1. **The surface already exists in Figma.** Cite the node. Nothing else to do.
106
+ 2. **Figma access is available and the surface belongs in the design source.** Reflect it in Figma,
107
+ then cite the node. This is the expected outcome for real product UI, and the whole reason the
108
+ `tool-access-gate` probe enumerates Figma as a required tool when the work item links one.
109
+ 3. **The surface genuinely does not belong in the design source.** Mark it. Debug affordances,
110
+ dev-only playgrounds, internal tooling, and diagnostics live here.
111
+
112
+ The marker is the exception, not the default. When Figma access has been proven and a marked
113
+ exception records no reason, the gate reports it under `syncBackPreferred` — non-blocking, because
114
+ turning a preference into a second hard gate would make the honest exception more expensive than a
115
+ copy-pasted Figma link, which is exactly the wrong incentive. It is a review prompt: *you could have
116
+ synced this back — why didn't you?*
117
+
118
+ ## Host design-system rules stay authoritative
119
+
120
+ Several Lisa host projects already carry a design-system rule of their own —
121
+ `figma-design-system.md`, `design-system.md`, `use-the-design-library.md`. Those files are
122
+ **host-owned**. They define the component hierarchy, the closed token vocabulary, the atom layer,
123
+ the escape hatches, and the lint manifest that enforces all of it, and they are specific to a product
124
+ in ways no shared contract can or should be.
125
+
126
+ **This contract governs whether the design source is declared, never what to build.** It adds one
127
+ orthogonal obligation on top of whatever the host rule already says. Where a host rule already
128
+ mandates a Figma mapping, this contract is satisfied by that mapping — cite the node and move on.
129
+
130
+ Two consequences worth stating plainly:
131
+
132
+ - **Do not duplicate host content into this contract, and do not rewrite host rules to restate this
133
+ one.** Wire them: the host rule points at this slug for the provenance obligation, this contract
134
+ points at the host rule for everything else.
135
+ - **Several host design-system rules are generated artifacts** carrying a "generated from
136
+ `docs/design-system-rfc.md` — do not edit this file directly" provenance header. Respect it:
137
+ **amend the RFC and regenerate.** A hand-edit to a generated rule is lost on the next
138
+ regeneration, which is worse than not making the change at all, because it looks like it shipped.
139
+
140
+ ## Gate semantics
141
+
142
+ `scripts/design-source-gate.mjs` is the executable arm of this contract, and it **fails closed**.
143
+
144
+ ```
145
+ node design-source-gate.mjs --base=origin/main [--head=HEAD] [--figma-access] [--json]
146
+ ```
147
+
148
+ Exit `0` = PASS, `1` = FAIL, `2` = usage error. It classifies every changed file into one status:
149
+
150
+ | Status | Verdict | Meaning |
151
+ |---|---|---|
152
+ | `figma-source` | pass | Sealed by a Figma node. |
153
+ | `marked-exception` | pass | Explicitly declared as not captured at the source. |
154
+ | `not-applicable` | pass | Not a UI surface, or a deletion — nothing to declare. |
155
+ | `undeclared` | **fail** | A UI surface with no annotation at all. |
156
+ | `malformed` | **fail** | An annotation whose value is neither form. |
157
+ | `conflicting` | **fail** | Cites Figma *and* denies having a source. |
158
+ | `unreadable` | **fail** | The changed file could not be read. |
159
+
160
+ Plus two change-level failures that exist purely so the gate cannot pass on ignorance:
161
+ `changed-files-unresolved` (the file list never materialized) and `diff-unresolved` (git could not
162
+ compute the range). **A gate that returns PASS when it could not look proves nothing.** This is the
163
+ same discipline `claim-evidence-mapping` applies to verification evidence and `bdd-e2e-coverage`
164
+ applies to a missing runner: the absence of a check is never a passing check.
165
+
166
+ The gate aggregates — it reports every violating file, not the first one — so a single run tells the
167
+ implementer everything they need to fix.
168
+
169
+ ## Where it is enforced
170
+
171
+ - **`lisa-implement`** — building or changing a UI surface includes declaring its design source, and
172
+ the sync-back preference applies while the work is being done, when reflecting the surface in Figma
173
+ is cheap. The `tool-access-gate` probe already establishes whether Figma access exists.
174
+ - **`lisa-tdd-implementation`** — the declaration lands with the implementation, in the same commit
175
+ as the surface it describes.
176
+ - **`lisa-review-local` and `lisa-quality-review`** — the gate runs on the branch diff, and a FAIL is
177
+ a **blocking** finding. It qualifies under `convergent-review` because it names a concrete failure
178
+ scenario: the design source silently diverges from the shipped product, and nobody can tell which
179
+ one is authoritative.
180
+ - **`lisa-tracker-source-artifacts`** — its existing design-vs-code divergence note covers the
181
+ *ticket* side of the same event. It points here for the code side, so the two are one behavior
182
+ rather than two half-behaviors.
183
+
184
+ ## Bootstrap and degradation
185
+
186
+ Adoption is never a backfill project. The gate judges only the surfaces the current change touched,
187
+ so a repository with hundreds of unannotated legacy components can adopt the contract on a Tuesday
188
+ and be green on Tuesday. Pre-existing unannotated UI is **burndown**: recorded, worked down
189
+ opportunistically as files are touched, never treated as the current work item's blocker.
190
+
191
+ A project with no Figma at all is not exempt. Every changed surface carries the marker, and the
192
+ resulting exception list is the honest, mounting record of how much of the product lives outside its
193
+ design source — which is far more useful than an exemption flag that makes the question disappear.
194
+ Deleting or excluding a surface to make the gate green is a violation of the same kind as deleting a
195
+ BDD scenario to improve coverage: mark it, do not drop it.
@@ -0,0 +1,37 @@
1
+ # Do It Now
2
+
3
+ ## The failure
4
+
5
+ An agent notices something that needs doing — a lint rule that would have caught the bug it just fixed, a stale comment, a real defect found beside the one it was sent for, a ticket that should be flipped to ready — and writes a sentence about it instead of doing it. "Worth adding a rule for this later." "We should file that." "Follow-up: update the doc."
6
+
7
+ Almost none of those happen. The note lands in a session transcript nobody re-reads, or in a report the human skims once. Even when it survives, the next session pays full price to rebuild the context that made the work obvious — which is the moment you are in right now, and it will not come back this cheap.
8
+
9
+ The originating example: a session closed a non-reproducing bug, found a genuine defect next to it, filed a ticket for the real defect, and then left the ticket sitting outside the ready lane. Every individual step was correct. The handoff was incomplete, and the work sat.
10
+
11
+ ## The rule
12
+
13
+ **If the factory is allowed to do it, do it in this session.** Allowed means: within scope, within your permissions, and not behind an exterior human gate. That covers the great majority of "later" items:
14
+
15
+ - Filing the ticket — and flipping it to the ready role so something picks it up (`tracked-work`).
16
+ - Adding the lint rule, ast-grep pattern, or test that prevents the recurrence (`promotion-contract` — and note that promotion is atomic: enable the control, fix the existing violations, ship the diagnostic, delete the superseded prose).
17
+ - Fixing the flaky test rather than re-running it.
18
+ - Updating the doc, comment, or rule your change just made wrong (`stale-state-claims`).
19
+ - Cleaning up the scaffolding you introduced.
20
+
21
+ ## The exception, and its shape
22
+
23
+ Lisa's exterior gates exist on purpose and this rule does not override them. A protected deployment, a held-back PRD, a low-confidence learning awaiting human review, a product judgement only a person can make — these wait for the human, by design.
24
+
25
+ The exception is narrower than it first appears, because it applies to the **gated step**, not to the whole item. Do everything up to the gate now:
26
+
27
+ 1. Do the allowed part — file it, write it, prepare it, get it to the edge of the gate.
28
+ 2. Mark the gate explicitly, in the tracker, so it is visible outside your session.
29
+ 3. Say plainly, in your update, what is waiting on a human and what will happen once they act.
30
+
31
+ "Waiting on a human" is a state you report, never a place you leave work silently.
32
+
33
+ ## Deferring is a decision
34
+
35
+ Sometimes not doing it now is genuinely right: the change is out of scope, it would balloon the diff past reviewability, it depends on a decision not yet made, or it belongs to a different work item. Those are legitimate — and they are **decisions**, which means they get said out loud with a reason, and the deferred item becomes tracked work rather than a sentence.
36
+
37
+ What is never acceptable is the implied deferral: noticing, saying nothing, and moving on. The human cannot act on what you did not tell them, and neither can the next session.
@@ -21,6 +21,7 @@ This is the inquiry counterpart to the `verification` rule: `verification` prove
21
21
  ## What this rule forbids
22
22
 
23
23
  - Presenting a guess, a recollection, or a documentation summary as established fact when it was cheap to verify and you did not.
24
+ - **Interpreting a diff, or reporting scope, without first establishing your branch position.** Run `git rev-list --count HEAD..origin/<default>` before you read a diff and before you describe how large a change is. A worktree that is thirty commits behind renders everyone else's merged work as though it were part of your change — the observed incident reported it as massive scope creep, in reverse, and the reviewer nearly acted on it. The count is one command and it turns an ambiguous diff into an unambiguous one.
24
25
  - "Should work" / "probably" / "the docs say" as the basis for a load-bearing decision that an experiment could have settled.
25
26
  - Skipping the probe because the answer "seems obvious" — obvious answers are exactly the ones that quietly drift from reality.
26
27
 
@@ -62,11 +62,33 @@ A clean result is a statement about what the check can perceive, not about the c
62
62
  ## How to apply
63
63
 
64
64
  1. Author the check.
65
- 2. Deliberately break the guarded property.
66
- 3. Confirm the check **fails and names the right file/line**. A failure that does not localize is weak evidence the check is measuring the right thing.
65
+ 2. Deliberately break the guarded property — specifically, introduce **the exact regression the guard exists to prevent**, not a nearby or convenient break.
66
+ 3. Confirm the check **fails, names the right file/line, and that exactly one test fails**. A failure that does not localize is weak evidence the check is measuring the right thing.
67
67
  4. Restore, and confirm green again.
68
68
  5. Report the falsification alongside the result.
69
69
 
70
+ ### The failure count is part of the evidence
71
+
72
+ Step 3's cardinality is not pedantry; each deviation names a distinct defect.
73
+
74
+ - **Zero failures** — the guard is inert. It was authored, it is green, and it asserts nothing about the property it names. The originating incident: a guard pinned one field of a structure and the regression it was written to stop walked straight through it with all fifty tests green, because nothing in the suite touched the field that actually moved.
75
+ - **More than one failure** — the break is too coarse, the guard is over-broad, or unrelated tests share the fixture. Any of the three means the guard's next real failure will not tell the reader what broke, which is most of a guard's value.
76
+ - **Exactly one failure** — the guard localizes. That is the evidence, and it is what gets reported.
77
+
78
+ ### Never narrate a red state you did not run
79
+
80
+ A guard's red leg, a "before" state, a reproduction of a fixed defect: each is an **observation**, and an observation you did not make is a fabrication however sound the reasoning behind it. The originating incident here was an evidence file asserting "working tree clean" while listing two untracked scripts a few lines further down — internally contradictory, because the clean-tree line was reasoned rather than run.
81
+
82
+ When the red state no longer exists in your working tree — it was fixed, or it lives at an earlier commit — **reconstruct it in a throwaway detached-HEAD worktree** and run it there:
83
+
84
+ ```
85
+ git worktree add --detach <scratch-path> <sha>
86
+ # run the check in <scratch-path>, capture the real output
87
+ git worktree remove <scratch-path>
88
+ ```
89
+
90
+ This costs seconds, leaves your working tree untouched, and produces genuine output. There is no situation in which writing down what the command *would* have printed is preferable to running it.
91
+
70
92
  For generated or validated inputs, replace steps 2–4 with a direct unit test of the checker against synthetic bad input.
71
93
 
72
94
  **A check whose failure has never been observed is reported as `unvalidated`, not as passing.** "Mentally reverting" does not satisfy step 3 — the author of a guard already believes it is load-bearing, so reasoning about the failure reproduces the belief rather than testing it. `unvalidated` is a legitimate state to report and land; silently presenting an unfalsified gate as a passing one is not.
@@ -1,5 +1,13 @@
1
1
  # Integration Access Layer
2
2
 
3
+ ## Secrets resolve through `lisa-secrets-access`
4
+
5
+ Credentials follow the same chokepoint discipline as vendor integrations: every secret a session needs resolves through the `lisa-secrets-access` skill, which owns the supported provider list (Bitwarden, 1Password, AWS, Doppler, Vault, env), the note format attached to each secret, the `tool:` declaration of which CLIs a credential drives, and the resolution and verification order.
6
+
7
+ That contract is deliberately **not restated here or anywhere else.** A second copy of the note format is a copy that drifts, and a drifted copy of a credential contract is worse than no copy, because it is followed. Read the skill.
8
+
9
+ The one operational consequence worth stating in an always-loaded rule: **do not ask a human to paste a value the configured provider can supply**, and do not read keychains, `.env` files, or provider CLIs directly to work around the skill. If resolution fails, the failure is a bug in the provider bootstrap and gets reported as one.
10
+
3
11
  Every Lisa skill or rule that consumes an external integration MUST route through
4
12
  the integration's `*-access` skill instead of calling that vendor's MCP tools or
5
13
  REST API directly.
@@ -0,0 +1,41 @@
1
+ # Learnings Ladder — Where Does This Go?
2
+
3
+ ## The problem this solves
4
+
5
+ The taxonomy was never missing. Lisa has had the six-rung ladder since the `skill-evaluator` agent shipped, and the gardener has always routed by it. What was missing is that the taxonomy lived inside an agent definition most sessions never open, so the practical answer to "where does this learning go?" was whichever knowledge file the agent happened to have in context — which is how a single project rules file accretes lint rules, product specs, and incident notes into one undifferentiated blob that every session pays for.
6
+
7
+ This rule is a pointer, not a second taxonomy. It exists so the routing question is answerable without opening anything.
8
+
9
+ ## The rungs, ordered by what they cost to carry
10
+
11
+ | Rung | Destination | Enters context | Admission |
12
+ | --- | --- | --- | --- |
13
+ | EXECUTABLE-CONTROL | Lint / ast-grep / type / test / hook / `package.lisa.json` force | Never — the diagnostic fires on violation | Mechanically decidable, stable, and it has recurred |
14
+ | EAGER-RULE | The host rules directory `.agents/rules/`; Lisa's own shipped rules originate in the plugin rules tree | Unconditionally, every session | Earned by failure evidence — repeated misses despite the knowledge being reachable |
15
+ | SKILL | A `SKILL.md` procedure | Description eager; body on invoke | Procedural, multi-step, with a recognizable trigger |
16
+ | WIKI | Wiki page plus an index entry | Only when queried | Durable declarative reference knowledge |
17
+ | KEEP-IN-LEDGER | The learnings ledger (`.lisa/PROJECT_LEARNINGS.md`, or the configured `learnings.file`) | Bounded contract projection only | The default landing zone; probationary and expiring |
18
+ | RETIRE | Nowhere — the prose is deleted | Never | Redundant with a mechanical owner, stale, or superseded |
19
+
20
+ Each rung also carries an orthogonal **scope**: `project` (apply here) or `upstream` (raise to `CodySwannGT/lisa`). Scope changes where the promotion work is filed; it never changes the rung.
21
+
22
+ ## How to choose
23
+
24
+ Work down the list and stop at the first honest yes:
25
+
26
+ 1. **Can a machine decide it?** Then it is EXECUTABLE-CONTROL, and prose describing it is redundant. This is the strongest rung and the cheapest to carry: it costs nothing until someone violates it, and then it says exactly what is wrong.
27
+ 2. **Is it a procedure with a trigger?** SKILL. The description is what gets loaded eagerly; the body arrives only when invoked.
28
+ 3. **Is it reference knowledge someone would go and look up?** WIKI. Deep project knowledge belongs on a rung that is paid for only when routed to — which is why `wiki-knowledge-source` is query-on-demand rather than load-at-startup.
29
+ 4. **Otherwise, KEEP-IN-LEDGER.** This is the default and it is not a failure state. Most learnings are provisional, and the ledger is where a candidate proves whether it recurs.
30
+
31
+ **EAGER-RULE is not on that list on purpose.** It is not something you choose; it is something a candidate earns, on cited evidence that agents repeatedly missed the knowledge even though it was already reachable. The eager tier charges every session on every agent, so admission is demotion-biased and the gardener re-audits the tier on every run — including Lisa's own shipped eager rules. A candidate with no recurrence evidence can reach WIKI, KEEP-IN-LEDGER, or RETIRE, and can never reach EAGER-RULE.
32
+
33
+ ## Capture is yours; promotion is not
34
+
35
+ The division is deliberate and it is what keeps knowledge surfaces from silently growing:
36
+
37
+ - **You capture.** Record the learning through `lisa-persist-learning`, with its provenance and evidence. That is the whole of a session's authority here.
38
+ - **The gardener promotes.** `/lisa:learnings:audit` — available as an opt-in weekly automation via `lisa-setup-automations` — audits the ledger, rules trees, skills, and wiki, routes candidates through the `skill-evaluator`, and files **human-gated tracker tickets** for promotions, demotions, and retirements. A human approves each one.
39
+ - **Nothing hand-appends.** Never write a learning directly into `AGENTS.md`, a host rules file, or the human decree surface. Those are human-authored, and an automated append to them is exactly the accretion this ladder exists to stop.
40
+
41
+ Promotion tickets are themselves governed: `promotion-contract` requires an EXECUTABLE-CONTROL promotion to be atomic — enable the control, fix the existing violation population, ship a remediation-teaching diagnostic, and delete the superseded prose, all in one PR. Promote-without-remove double-pays forever.
@@ -0,0 +1,34 @@
1
+ # Local CI First — CI Is Not a Debugger
2
+
3
+ End-to-end suites — Playwright, Maestro, Cypress, and anything else that only runs in a workflow on a normal day — fail differently from unit tests. The failure is usually environmental (a selector that moved, a fixture that did not seed, a simulator that booted slowly), and the instinct is to guess, push, and read the next CI run.
4
+
5
+ That instinct is what this rule exists to break. A CI round trip is five to twenty minutes, produces one bit of information per attempt, gives no interactive access to the failing state, and occupies a runner that other work is queued behind. Three speculative pushes cost the better part of an hour and still leave you without a reproduction. The same three attempts run locally take minutes and hand you the actual DOM, the actual screenshot, and the actual stack.
6
+
7
+ ## Reconstruct the invocation, do not approximate it
8
+
9
+ The workflow file is the specification of what CI ran. Read it and mirror it:
10
+
11
+ - The **exact command**, including the config file, project/suite selector, and tag filters (`--project=chromium`, `--grep`, `include_tags`).
12
+ - The **environment**: env vars the job sets, the base URL it points at, whether it runs headless, and which secrets it injects. Anything you cannot supply locally is a known difference — write it down rather than assuming it is irrelevant.
13
+ - The **target**: browser version, device or simulator model, OS. Mobile e2e is especially sensitive here; a Maestro flow that passes on one iOS version fails on the next over accessibility-label matching alone.
14
+ - The **fixture and data state**: seed scripts, migrations, and whether the job runs against a fresh database or a shared environment.
15
+
16
+ Setting all of that up — installing the browser, booting the simulator, seeding the database — is part of doing the work. "Local setup would take a while" is not a reason to use the shared CI queue as a REPL.
17
+
18
+ ## When it genuinely will not reproduce
19
+
20
+ Some failures are real and local-only-invisible: a race that appears only on a slower runner, a secret that exists only in CI, an artifact that only the CI build produces. That case is legitimate, and the rule's requirement is honesty about it, not denial:
21
+
22
+ 1. **Say so explicitly**, and name what differs — runner OS, CPU count, headless mode, network latency, a device you do not have, a secret you cannot read.
23
+ 2. **Change one thing per push, and state what that push is testing.** A push that alters four things and goes green teaches you nothing about which one mattered.
24
+ 3. **Add the observability you are missing** — a trace, a video, a screenshot on failure, a verbose log — in the same push, so the next run answers the question rather than repeating it.
25
+
26
+ ## Forbidden
27
+
28
+ - Pushing a speculative fix "to see if it helps" when the suite has never been run locally.
29
+ - Re-running a failed CI job unchanged in the hope of a different outcome, without labelling the failure as suspected-flake and investigating it as one.
30
+ - Reporting a fix as verified on the strength of a green CI run that followed several red ones, without knowing which change was responsible.
31
+
32
+ ## Relationship to other rules
33
+
34
+ `empirical-inquiry` says to run the cheapest probe that settles a question; local reproduction *is* that probe for an e2e failure. `verification` requires proof by using the software — a local run of the same suite produces that proof directly, and produces it faster.
@@ -0,0 +1,41 @@
1
+ # Waiting Is Not Blocked
2
+
3
+ Three failure modes share one root: a session that stops producing while still consuming the human's clock and attention. Each was observed directly.
4
+
5
+ ## 1. Poll; do not wait for a message
6
+
7
+ An agent dispatches a subagent, a CI run, a deploy, or a long build — and then waits for a notification that never arrives, or arrives long after it mattered. Callbacks are best-effort. Notification channels drop. A background process can exit without anything telling you.
8
+
9
+ **While the session is active, go and check.** Roughly every five minutes, run the command that answers the question: `gh run list`, `gh pr checks`, a status query, a log tail, a file existence check. Polling is cheap; an idle session is not.
10
+
11
+ This is not an instruction to busy-wait. It is the opposite: between polls you should be doing other work (see rule 3). The poll is a periodic check, not an occupation.
12
+
13
+ Two corollaries:
14
+
15
+ - **An absent result is information.** If a subagent has produced nothing after several polls, investigate whether it is running at all rather than assuming it needs more time.
16
+ - **Never claim an outcome you have not observed.** "The tests are probably green by now" is a fabrication; go look. See `falsifiable-checks` and `claim-evidence-mapping`.
17
+
18
+ ## 2. Blocked means you physically cannot proceed
19
+
20
+ The word is load-bearing and it gets diluted. **Blocked** means there is no action available to you: a credential you cannot obtain, an API that rejects you, a decision whose answer changes what you would build, a dependency that does not exist yet.
21
+
22
+ These are **not** blocked:
23
+
24
+ - Waiting for a review, a CI run, a deploy, or a build.
25
+ - Waiting for a human to confirm something you could reasonably proceed on and correct later.
26
+ - Waiting for a subagent you dispatched.
27
+ - Not yet having done the work.
28
+
29
+ Report those as **waiting**, and say what you are doing in the meantime. Reporting them as blocked misinforms the human twice: it suggests they must act when they need not, and it devalues the word for the times you genuinely cannot proceed.
30
+
31
+ ## 3. Plan phases are parallel unless stated otherwise
32
+
33
+ A numbered plan is a decomposition, not a dependency graph. Unless a phase's input is another phase's output — or the user said the order matters — the phases run concurrently. An agent that serializes a plan because it is written as a list turns a parallel workload into a queue and multiplies the wall-clock cost by the number of steps.
34
+
35
+ Practically: when you would otherwise idle waiting on rule 1, start the next independent phase. When you dispatch subagents, dispatch every independent one in the same breath rather than one at a time.
36
+
37
+ Where a real dependency exists, name it — "phase 3 needs the schema from phase 2" — so the human can see why the order is what it is.
38
+
39
+ ## Scope: sessions, not the tracker
40
+
41
+ This rule governs **session** stuckness. It does not touch the factory's tracker lifecycle vocabulary — the `blocked` role and the `human_needed` outcome used by `lisa-implement`, `lisa-repair-intake`, and the intake flows. That vocabulary is stricter and deliberately so: an item marked `human_needed` is one an adversarial gate decided a person must resolve, and nothing in this rule permits a session to re-classify it. If you are unsure which vocabulary you are in, ask whether you are describing your own next five minutes (this rule) or the state of a tracked work item (the factory contract).
@@ -0,0 +1,60 @@
1
+ # Session Status Updates — Plain Language, and Always Say If It's Safe to Close
2
+
3
+ ## Why this is a rule and not a style preference
4
+
5
+ Lisa's premise is that a non-technical person can direct software work by describing outcomes. That premise already binds everything crossing a gate outward — intake rejections, clarifying questions, ticket descriptions, verification reports — because a non-technical operator is standing at the gate.
6
+
7
+ In-session conversation was never held to the same bar, and the result was a split personality: careful, plain-language ticket prose and simultaneously a stream of chat messages full of file paths, rule slugs, and reasoning narrative. The human reading both is the same human. This rule closes the split.
8
+
9
+ ## The three-part shape
10
+
11
+ Every update answers, in this order:
12
+
13
+ 1. **What changed** — what is different in the world now that was not before. Shipped, fixed, filed, deployed.
14
+ 2. **What's blocked** — using the strict meaning from `not-blocked-just-waiting`. If nothing is blocked, say so; "waiting on the CI run" belongs here labelled as waiting.
15
+ 3. **What needs a decision** — see below.
16
+
17
+ What is deliberately excluded: how you found it. The files you read, the searches you ran, the hypotheses you discarded, the dead ends. That is your working memory, not their update. If they want it they will ask, and the offer to elaborate costs one clause.
18
+
19
+ ## Voice
20
+
21
+ Write the way you would speak to a competent colleague who does not work on this system.
22
+
23
+ - Prefer the user-visible name of a thing over its implementation name. "The login page broke" beats "the auth guard regressed at the controller boundary."
24
+ - Do not use Lisa vocabulary (rung, gate, leaf, intake, ratchet) with someone who has not asked for it.
25
+ - Do not use a file path where a description works. Paths are for when the human will open the file.
26
+ - Short sentences. No preamble about what you are about to say.
27
+
28
+ Two lines the user themselves offered as the target: *"just tell me what's going on and what my options are"* and *"give me the summary, I'll ask for detail if I want it."*
29
+
30
+ ## Decisions
31
+
32
+ A decision presented as a paragraph of context is a decision the human has to excavate. State it as a decision:
33
+
34
+ - **The decision** — one sentence naming the choice to be made.
35
+ - **Your recommendation** — you have more context than they do; do not withhold it. Recommending is not deciding.
36
+ - **The ramifications of each option** — one line apiece, in terms of consequences they care about (time, cost, risk, what breaks, what it forecloses), not in terms of implementation.
37
+
38
+ An option you consider unacceptable is still listed, with the reason it is unacceptable. Presenting one option as if it were the only one is a decision you made on their behalf without saying so.
39
+
40
+ ## The close line
41
+
42
+ Every update ends with exactly:
43
+
44
+ ```
45
+ Safe to close: yes/no — <reason>
46
+ ```
47
+
48
+ `yes` means killing the session right now loses nothing: work is committed and pushed, tickets are in the state they should be in, nothing is running that will not finish on its own.
49
+
50
+ `no` names the specific in-flight thing that would be lost. Real examples: a local dev server or test run still going; a ticket filed but not yet flipped to ready, so nothing will pick it up; a commit that exists only in the working tree; a PR whose checks nobody is watching; a deploy mid-flight.
51
+
52
+ The line exists because the human's most common question — asked or unasked — is "can I close this?" Making them ask it costs a round trip; making them guess costs them work.
53
+
54
+ ## Relationship to the other communication rules
55
+
56
+ - `report-actionability` governs **completeness**: the denominator, every item accounted for, who acts on each. It is about what a report must contain.
57
+ - `automation-runbook-contract` governs the **outcome line** a terminating flow opens with.
58
+ - This rule governs the **voice** of a session update, its three-part shape, and the close line.
59
+
60
+ None of the three is relaxed by the others. An update can satisfy all three at once and usually should: outcome line first, denominator stated, plain language throughout, close line last.
@@ -9,13 +9,29 @@ A project has a wiki in one of two shapes:
9
9
 
10
10
  Either way, freshness is not your concern. The query and ingest skills run `scripts/ensure-wiki.mjs` as their own first step, which resolves the wiki root and — for a remote wiki — clones the mirror if missing and fast-forwards it when stale (subject to a short TTL, and tolerant of being offline: it proceeds with the existing mirror and warns rather than blocking). The freshness guarantee lives in the tool, not in the caller's discipline. Do **not** add a separate "make sure the wiki is current" step to your own workflow — calling the skill already does it.
11
11
 
12
- Before researching project background, conventions, ownership, architecture, glossary terms, or "how/why does X work here":
12
+ ## Load posture: on demand, not at session start
13
13
 
14
- 1. Consult the wiki first via the wiki query skill (`/lisa-wiki-query`, or the runtime's wiki query skill), which resolves the wiki root for you. For a local wiki you may also start from `wiki/index.md` and follow links.
15
- 2. Use what the wiki says as the authoritative answer when it covers the question. Do not re-derive it from raw sources when the wiki already documents it.
16
- 3. Fall back to primary sources (code, tickets, commit history, external docs) only when the wiki is silent, ambiguous, or contradicted by what you observe in the code.
14
+ The wiki is **not** read during session bootstrap, and no flow may add a "load the wiki" step to its startup. This is a deliberate reversal of the rule's earlier "consult the wiki first" posture, recorded in `wiki/decisions/2026-08-12-agent-neutral-host-rules-path.md` section 6 (decision D3). The reasoning is context budget: the wiki is deep declarative knowledge, which is the WIKI rung of the learnings ladder precisely *because* it should be paid for only when routed to. Loading it unconditionally converts an on-demand rung into an eager one and charges every session — including the large majority that never ask a knowledge question — for knowledge they do not use.
15
+
16
+ What survives the softening is discoverability. An agent must **know the wiki exists and know how to query it**, so that a question needing depth goes to the curated answer instead of a fresh scrape of the codebase. What is dropped is the obligation to consult it before every piece of research, and the framing of the wiki as the authority that outranks primary sources.
17
+
18
+ When you do need project depth:
19
+
20
+ 1. Call the wiki query skill (`/lisa-wiki-query`, or the runtime's equivalent), which resolves the wiki root for you. For a local wiki you may also start from `wiki/index.md` and follow links.
21
+ 2. Prefer what the wiki says over re-deriving the same answer from raw sources — that is what it is curated for.
22
+ 3. Fall back to primary sources (code, tickets, commit history, external docs) when the wiki is silent, ambiguous, or contradicted by what you observe in the code.
17
23
  4. If you find the wiki is wrong, stale, or missing knowledge that belongs there, surface the gap — and where the project's workflow supports it, capture the correction back into the wiki via its ingestion path (`/lisa-wiki-ingest` or equivalent) rather than leaving the knowledge only in this session.
18
24
 
19
25
  The wiki documents knowledge; it does not override executable behavior. When the wiki and the running code disagree about what the system actually does, trust the code and treat the wiki as out of date. See the `documentation-source-paths` rule for how source-material directories relate to the wiki.
20
26
 
21
- If the project has neither a local `wiki/` nor a `wiki.source` pointer in `.lisa.config.json`, this rule does not apply.
27
+ ## Applicability is the plugin gate, not just the wiki content
28
+
29
+ This rule ships in the **base** plugin, but the skill it directs you to (`lisa-wiki-query`) ships in the **wiki** plugin. Those are gated differently, and for a period a base-only project received this rule pointing at a skill it did not have — a rule with a dangling instruction, which teaches an agent to distrust its rules.
30
+
31
+ The applicability condition is therefore stated as the *installation* gate rather than as "does a `wiki/` folder exist". The `lisa-wiki` plugin is selected when `wiki/lisa-wiki.config.json` exists **or** `.lisa.config.json` declares a top-level `wiki` key (`src/core/lisa-plugin-selection.ts`); on Claude Code it is additionally gated by `enabledPlugins["lisa-wiki@lisa"]` in `.claude/settings.json`. When that gate is not satisfied:
32
+
33
+ - This rule does not apply. There is no wiki to query and no query skill to call.
34
+ - The recovery path is `/lisa-wiki-install`, the bootstrap skill that **base** ships precisely so a project that never enabled the wiki plugin can still discover it. Naming a base-shipped skill is what keeps the instruction reachable in every install.
35
+ - **Never block on the absent skill.** Degrade to primary sources and continue, per the same degrade-never-block posture `readiness-rubric` and `rejection-detection` use for surfaces that may not be installed.
36
+
37
+ A remote-only wiki declared through `wiki.source` is covered by the `wiki` config key, so the pointer form satisfies the same gate.