@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
@@ -12,7 +12,7 @@ name: 🌙 Nightly E2E Health
12
12
  #
13
13
  # All the logic lives in Lisa's reusable `nightly-e2e-health.yml` plus the
14
14
  # Lisa-shipped guard `scripts/check-nightly-e2e-health.mjs`. The contract —
15
- # including the 25-row fail-closed truth table and the bypass rules — is
15
+ # including the 30-row fail-closed truth table and the bypass rules — is
16
16
  # `docs/nightly-e2e-gate.md` in Lisa. This caller owns only the project-specific
17
17
  # values: which suites, which branch, and where the gate is required.
18
18
  #
@@ -25,7 +25,10 @@ name: 🌙 Nightly E2E Health
25
25
  # 2. Leave `bootstrap_until` set to a date ~2 weeks out while you burn the
26
26
  # suite down. Missing evidence will report but not block, with the expiry
27
27
  # visible on every PR. A red suite still blocks. When the date passes the
28
- # gate arms itself with no further action.
28
+ # gate arms itself with no further action. LATER, when you add a suite to
29
+ # the armed repo, do NOT re-open this window — give that one suite a
30
+ # `first_seen` anchor instead (see the note above `suites`), so the suites
31
+ # that were already gating stay armed.
29
32
  # 3. Add the required status check to the ruleset for the branch below. The
30
33
  # context is `🌙 Nightly E2E Health / 🌙 Gate` — the composite of THIS
31
34
  # job's name and the reusable's job name, byte for byte, emoji included.
@@ -130,6 +133,22 @@ jobs:
130
133
  #
131
134
  # Do NOT add a suite whose job `ci.yml` skips — a skipped job never
132
135
  # reports, and the gate would read it as missing evidence forever.
136
+ #
137
+ # ADDING A SUITE TO AN ALREADY-ARMED REPO: give it a `first_seen` anchor
138
+ # rather than re-opening `bootstrap_until`. A new suite has no nightly of
139
+ # its own yet, so without one it is row 9 (no run at all) and blocks every
140
+ # pull request from the moment you save this file. `first_seen` forgives
141
+ # THAT SUITE for 14 days (`grace_days` may shorten it) while every other
142
+ # suite stays armed — which is exactly what widening the global window
143
+ # would have destroyed. It may not be in the future, and the window may
144
+ # not run beyond `bootstrap_max_days`; both are hard failures, not clamps.
145
+ #
146
+ # {
147
+ # "label": "Playwright browser e2e",
148
+ # "workflow": "ci.yml",
149
+ # "match": { "mode": "run" },
150
+ # "first_seen": "2026-08-10T00:00:00Z"
151
+ # }
133
152
  suites: |
134
153
  [
135
154
  {
package/package.json CHANGED
@@ -120,7 +120,7 @@
120
120
  }
121
121
  },
122
122
  "name": "@codyswann/lisa",
123
- "version": "3.2.0",
123
+ "version": "3.4.0",
124
124
  "description": "Claude Code governance framework that applies guardrails, guidance, and automated enforcement to projects",
125
125
  "main": "dist/index.js",
126
126
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "3.2.0",
3
+ "version": "3.4.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": "3.2.0",
3
+ "version": "3.4.0",
4
4
  "description": "Universal governance: agents, skills, commands, hooks, and rules for all projects.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -155,7 +155,9 @@ IF it is a Fix (bug), execute the Reproduce sub-flow FIRST:
155
155
 
156
156
  For any Fix flow, and for any Build flow that changes user-visible behavior, regression coverage is a required deliverable at the highest practical observation level for the reported surface. If the project has a browser, device, or end-to-end harness for that platform (for example Playwright, Maestro, Detox, Cypress, or an equivalent runtime), the task plan and definition of done MUST include a deterministic regression spec against the reported surface, using mocked or seeded data where needed. This is alongside unit or integration coverage, not a substitute for it. For **frontend work** the deliverable is defined by the `bdd-e2e-coverage` rule and has two halves, both landing in this PR: the Gherkin scenario (stable ID, required platforms) added or updated in the project's behavior contract, and aligned automation in the project's configured runner for **every** platform that scenario requires — no runner substitutes for another, because they guard different platforms of the same behavior. The coverage gate must pass and the matrix and burndown be regenerated before the item is done. Cite the rule; do not restate its scenario, waiver, or bootstrap mechanics here.
157
157
 
158
- For work that adds or changes **persistent state**, the `reset-seed-coverage` rule adds a second non-demotable deliverable landing in this same PR: every entity the item introduces or changes is classified in the project's state contract (`fixture-owned` / `preserve` / `derived-rebuild` / `forbidden`) with a reason and an owner, anything `fixture-owned` declares its ownership predicate and is actually swept, and the state-classification check passes. Writing a flow that creates a record and deletes it only on its happy path does NOT satisfy thisthat is the leak, not the coverage. Cite the rule; do not restate its policy, waiver, or bootstrap mechanics here.
158
+ For work that adds or changes a **UI surface**, the `design-source-of-truth` rule adds a second non-demotable deliverable landing in this same PR: every UI surface the change touches declares where its design came from. Figma is the source of truth, so **prefer sync-back** if the surface is not in Figma yet and the tool-access preflight proved Figma access, reflect it there and cite the node with `DESIGN-SOURCE: <figma-url>`. Only when the surface genuinely does not belong in the design source (debug affordance, dev-only playground, internal tooling) does it carry the exception marker `DESIGN-SOURCE: none not in Figma`, ideally with a trailing reason. `scripts/design-source-gate.mjs` decides this deterministically and fails closed on anything it cannot resolve; a FAIL blocks the item exactly as a failing coverage gate does. Host design-system rules (`figma-design-system`, `design-system`, `use-the-design-library`, or the project's equivalent) stay authoritative about *what* to build this obligation is only about declaring the source. Cite the rule; do not restate its marker grammar, host-precedence, or bootstrap mechanics here.
159
+
160
+ For work that adds or changes **persistent state**, the `reset-seed-coverage` rule adds a third non-demotable deliverable landing in this same PR: every entity the item introduces or changes is classified in the project's state contract (`fixture-owned` / `preserve` / `derived-rebuild` / `forbidden`) with a reason and an owner, anything `fixture-owned` declares its ownership predicate and is actually swept, and the state-classification check passes. Writing a flow that creates a record and deletes it only on its happy path does NOT satisfy this — that is the leak, not the coverage. Cite the rule; do not restate its policy, waiver, or bootstrap mechanics here.
159
161
 
160
162
  The team lead may not waive, defer, demote, or phrase this regression spec as "optional", "if cheap", "nice to have", or equivalent. The only permitted exits are:
161
163
 
@@ -16,6 +16,13 @@ For each changed file, evaluate:
16
16
  3. **Test coverage** -- Tests present? Testing behavior, not implementation details? Edge cases covered?
17
17
  4. **Documentation** -- JSDoc on new functions explaining "why"? Preambles on new files?
18
18
  5. **Code clarity** -- Readable variable names? Unnecessary complexity? Could a new team member understand this?
19
+ 6. **Design source** -- For UI surfaces, does each changed file say where its design came from? Run the deterministic gate rather than judging by eye:
20
+
21
+ ```bash
22
+ node "${CLAUDE_PLUGIN_ROOT:-.}/scripts/design-source-gate.mjs" --base=main --head=HEAD
23
+ ```
24
+
25
+ Exit 1 is a **Critical** finding under the `design-source-of-truth` rule -- the change is blocked until every UI surface either cites a Figma node (`DESIGN-SOURCE: <figma-url>`, the preferred fix -- sync it back) or carries the exception marker `DESIGN-SOURCE: none — not in Figma`. The gate fails closed: an unreadable file or an uncomputable diff is a FAIL, not a pass. Host design-system rules (`figma-design-system`, `design-system`, `use-the-design-library`, or the project's equivalent) stay authoritative about what to build; this checks only that the source is declared. If the gate script is absent, say so in the review rather than skipping silently.
19
26
 
20
27
  ## Output Format
21
28
 
@@ -14,6 +14,33 @@ maintainability feedback are non-blocking unless a repository rule or work item
14
14
  explicitly makes them release criteria. A blocking finding without a concrete
15
15
  failure scenario is malformed and must be filtered out.
16
16
 
17
+ One deterministic gate runs ahead of the judgement-based review and is exempt
18
+ from the confidence filtering below, because it is decided by a script rather
19
+ than by an agent's opinion.
20
+
21
+ **Design-source gate (`design-source-of-truth` rule).** Run it against the
22
+ branch diff before step 1:
23
+
24
+ ```bash
25
+ node "${CLAUDE_PLUGIN_ROOT:-.}/scripts/design-source-gate.mjs" --base=main --head=HEAD
26
+ ```
27
+
28
+ Exit 0 = PASS, exit 1 = FAIL. A FAIL is a **blocking** review finding and is
29
+ reported verbatim at the top of the review — it is never scored, never filtered
30
+ by confidence, and never demoted to a nitpick. It qualifies under
31
+ `convergent-review` because it names a concrete failure scenario: the design
32
+ source silently diverges from the shipped product and nobody can tell which one
33
+ is authoritative. The gate fails closed, so an unresolvable diff or an unreadable
34
+ file is a FAIL too. Each violation is fixed one of two ways, sync-back first:
35
+ reflect the surface in Figma and cite the node with `DESIGN-SOURCE: <figma-url>`,
36
+ or — only when the surface genuinely does not belong in the design source — mark
37
+ it `DESIGN-SOURCE: none — not in Figma`. Host design-system rules
38
+ (`figma-design-system`, `design-system`, `use-the-design-library`, or the
39
+ project's equivalent) remain authoritative about what to build; this gate only
40
+ asks whether the source is declared. If the gate script is not present (the
41
+ project predates the plugin version that ships it), say so explicitly in the
42
+ review — a silent skip is not one of the exits.
43
+
17
44
  To do this, follow these steps precisely:
18
45
 
19
46
  1. Use a Haiku agent to check the current git state:
@@ -71,6 +71,7 @@ TDD Cycle:
71
71
 
72
72
  - Write the minimum production code to make the test pass
73
73
  - Do not optimize, do not add features beyond what the test requires
74
+ - For any UI surface the implementation adds or changes, the `design-source-of-truth` rule requires its design-source declaration to land in the same commit as the surface it describes — `DESIGN-SOURCE: <figma-url>` when the surface is backed by a Figma node (sync it back first if Figma access exists), or the exception marker `DESIGN-SOURCE: none — not in Figma` when it genuinely is not captured at the source. `scripts/design-source-gate.mjs` fails closed on an undeclared surface. Cite the rule; do not restate its marker grammar here.
74
75
  - The goal is the simplest code that makes the test green
75
76
 
76
77
  ### REFACTOR Phase
@@ -93,6 +93,8 @@ Mocks define visual *intent*, not implementation shortcut. Every UI-touching tic
93
93
 
94
94
  If no existing component fits, building a new one is an explicit decision that must be recorded in the ticket (with rationale) before implementation. Lovable-generated components are never the reuse target — always use the project's own components.
95
95
 
96
+ The divergence note above covers the **ticket** side of this event. The **code** side is governed by the `design-source-of-truth` rule: a UI surface built with no Figma source behind it is either synced back to Figma and annotated `DESIGN-SOURCE: <figma-url>`, or explicitly marked `DESIGN-SOURCE: none — not in Figma`, and review fails closed if neither happened. Cite the rule for the code obligation rather than restating it here — a ticket comment closes with the ticket, the annotation stays with the surface.
97
+
96
98
  ## 8. Preservation gate (run after creating tickets)
97
99
 
98
100
  Before declaring done, verify every extracted artifact is reachable from the created tickets.
@@ -0,0 +1,38 @@
1
+ # Design Source of Truth (load-bearing)
2
+
3
+ **Figma is the design source of truth, and every UI surface a change touches declares where its design came from.** A changed UI surface that neither cites a Figma node nor carries the designated marker is a contract violation — and so is a surface whose declaration the gate cannot resolve.
4
+
5
+ **One vendor-neutral contract, cited by** `lisa-implement`, `lisa-tdd-implementation`, `lisa-review-local`, `lisa-quality-review`, and `lisa-tracker-source-artifacts` (the `leaf-only-lifecycle` / `repo-scope-split` precedent: one shared slug, never divergent per-skill prose).
6
+
7
+ ## Membership
8
+
9
+ Membership is **surface, not repo name or file extension**: a file is in scope the moment a change makes it render something user-observable — a screen, component, layout, style token, visual state, or markup a user reads. Barrels, pure-logic modules, tests, stories, generated output, and vendored code are out. Projects narrow or widen the default detection through `designSource.include` / `designSource.exclude` in `.lisa.config.json`; they never turn the obligation off.
10
+
11
+ ## The two declarations
12
+
13
+ Exactly one of these, written as an ordinary comment in whatever syntax the file uses:
14
+
15
+ | Form | Means |
16
+ |---|---|
17
+ | `DESIGN-SOURCE: <figma-url>` | The surface is backed by a Figma node — it already existed there, or it was synced back. |
18
+ | `DESIGN-SOURCE: none — not in Figma` | The surface is deliberately not captured at the design source. |
19
+
20
+ The marker's spelling is fixed and load-bearing; a drifted spelling silently disarms the gate. An optional trailing ` — <reason>` records why. Only a `figma.com` URL seals a surface: a link to a screenshot, a Slack thread, or any other mock is **malformed**, not proof.
21
+
22
+ ## Sync-back is the default; the marker is the exception, not the default
23
+
24
+ When the flow has proven Figma access (the `tool-access-gate` probe), reflecting the surface in Figma and citing the node is the expected outcome. Reach for the marker only when the surface genuinely does not belong in the design source — a debug affordance, a dev-only playground, a throwaway internal tool. The gate reports every marked exception so review can challenge it, and reports a reasonless exception separately when Figma access was available.
25
+
26
+ ## Host design-system rules stay authoritative
27
+
28
+ Projects that carry their own design-system rules (`figma-design-system`, `design-system`, `use-the-design-library`, or an equivalent) keep them. This contract never restates component hierarchy, token vocabulary, or reuse policy, and never overrides them. It asks one orthogonal question the host rules do not: is the design source declared?
29
+
30
+ ## The gate fails closed
31
+
32
+ `scripts/design-source-gate.mjs` decides the change deterministically. It fails on an undeclared surface, a malformed annotation, a file that both cites Figma and denies having a source, a changed file it could not read, and a diff it could not compute. **A design-source violation is a blocking review finding, never a warning** — it is not demoted to "optional", "if cheap", or a follow-up. A gate that passes on what it could not read proves nothing, so it never does.
33
+
34
+ ## Bootstrap and degradation
35
+
36
+ Adoption never demands a retroactive backfill: the gate judges **only the surfaces this change touched**. Pre-existing unannotated UI is burndown, recorded and worked down, not this work item's blocker. If a project has no Figma at all, that is not an exemption — every changed surface carries the marker, and the resulting exception list is the honest record of how much of the product lives outside its design source. Behavior obligations for the same surfaces are unchanged and still governed by `bdd-e2e-coverage`.
37
+
38
+ Full contract (marker grammar, gate semantics, host-rule precedence, bootstrap procedure): [reference/design-source-of-truth.md](../reference/design-source-of-truth.md).
@@ -0,0 +1,11 @@
1
+ # Do It Now (load-bearing)
2
+
3
+ If something needs to happen eventually and **the factory is allowed to do it**, do it in this session. File the ticket, flip it to ready, add the lint rule, fix the flaky test, update the doc that just went stale. Not in a "follow-up" sentence — now.
4
+
5
+ **"I'll get to that later" is not an acceptable close** for work that is in scope and permitted. A deferral costs a whole future session its context, and most of them are never picked up at all.
6
+
7
+ The one exception is an **exterior human gate** — a protected deploy, a held-back PRD, a low-confidence learning, a product call only a person can make. There you do the allowed part now (file it, mark the gate, flip everything you may flip) and say plainly what is waiting on a human and why.
8
+
9
+ Deferring is itself a decision. If you genuinely should not do it now, say so and say why; never leave it implied, and never leave it only in your own head.
10
+
11
+ Full prose: [reference/do-it-now.md](../reference/do-it-now.md).
@@ -16,6 +16,7 @@ Do not reason your way to a confident-sounding answer from documentation, prior
16
16
  - Presenting a guess, recollection, or doc summary as established fact when it was cheap to verify and you did not.
17
17
  - "Should work" / "probably" / "the docs say" as the basis for a load-bearing decision an experiment could have settled.
18
18
  - Skipping the probe because the answer "seems obvious" — those are exactly the ones that quietly drift from reality.
19
+ - Interpreting a diff, or reporting scope, before establishing where your checkout sits: run `git rev-list --count HEAD..origin/<default>` first. A worktree 30 commits behind makes everyone else's changes read as yours, and the diff was reported as massive scope creep in reverse.
19
20
  - Treating a recorded "not yet" / "pending" / "blocked" / "human-gated" note as current state. It is a claim about the day it was written; probe the live state before planning around it, escalating it, or reporting it as a blocker (`stale-state-claims`).
20
21
 
21
22
  This is the inquiry counterpart to the `verification` rule (which proves completed work behaves correctly). Both reject "it looks correct" as evidence.
@@ -18,6 +18,8 @@ Each has been observed in real runs; each reported success while asserting nothi
18
18
  ## Mandatory
19
19
 
20
20
  - **Falsify before reporting.** No clean result is reportable until the check has been shown to fail on a deliberate break. **"Mentally reverting" does not count** — reasoning that the assertion *would* fail is precisely the step that lets a non-functional guard ship, because the author already believes it is load-bearing. Run the break.
21
+ - **Count the failures: introduce the exact regression the guard exists to prevent, and confirm **exactly one** test fails, then revert.** Zero means the guard is inert; many means it is over-broad and its next failure will not name the cause. A guard that pinned one field of a structure shipped with all 50 tests green while the regression walked straight through.
22
+ - **Reconstruct a red state; never narrate one you did not run.** Evidence describing a failing or dirty state must come from a run you actually observed — an evidence file once claimed "working tree clean" while listing two untracked scripts in the same file. To observe a state that no longer exists, check that commit out in a **throwaway detached-HEAD worktree** and run it there. Writing down what the output would have said is fabrication, however confident the reasoning.
21
23
  - **Say how it was falsified.** "0 findings" alone is not a result; state what you broke and that the check caught it. A gate whose falsification is untested must be reported as *unvalidated*, not as passing.
22
24
  - **Prefer structural over textual checks.** Parse the AST/structure instead of matching source text: text matching cannot distinguish a field from a comment, an alias, or a nested occurrence, and it produces false positives that mask the real ones.
23
25
  - **A negative result is scoped to what the check can see.** State the blind spot. A presence check cannot see a wrong value; a per-file check cannot see a cross-file interaction; fixing one instance of a class is not fixing the class — sweep the class.
@@ -4,6 +4,11 @@ Skills and rules that use external integrations route through the matching
4
4
  `*-access` skill. Do not call vendor MCP tools or REST APIs directly from a
5
5
  consumer skill.
6
6
 
7
+ Secrets are the same shape: every credential resolves through
8
+ `lisa-secrets-access`, which owns the provider list, the note format, and the
9
+ resolution order. Read it rather than restating it — and never ask a human to
10
+ paste a value the provider can supply.
11
+
7
12
  Resolution order is the configured-provider token/CLI substrate first when its
8
13
  bootstrap credential is present and identity-matched, then the interactive MCP as
9
14
  fallback, then a loud error naming the exact credential to set. Identity-match is
@@ -0,0 +1,18 @@
1
+ # Learnings Ladder — Where Does This Go? (load-bearing)
2
+
3
+ When you learn something durable, route it by **what it costs to carry**, not by whichever file you happen to have open. Six rungs, strongest enforcement first:
4
+
5
+ | Rung | Destination | Enters context |
6
+ | --- | --- | --- |
7
+ | EXECUTABLE-CONTROL | Lint / ast-grep / type / test / hook / `package.lisa.json` force | Never — the diagnostic fires on violation |
8
+ | EAGER-RULE | The host rules directory `.agents/rules/` (Lisa's own shipped rules live in the plugin rules tree) | Unconditionally, every session |
9
+ | SKILL | A `SKILL.md` procedure | Description only; body on invoke |
10
+ | WIKI | Wiki page plus an index entry | Only when queried |
11
+ | KEEP-IN-LEDGER | The learnings ledger (`.lisa/PROJECT_LEARNINGS.md`) | Bounded projection only |
12
+ | RETIRE | Nowhere — delete the prose | Never |
13
+
14
+ **Take the cheapest rung that actually works.** Anything a machine can decide is EXECUTABLE-CONTROL. KEEP-IN-LEDGER is the default landing zone. EAGER-RULE is earned only by evidence of repeated misses despite the knowledge already being reachable, and the tier is demotion-biased — every session pays for it.
15
+
16
+ **You capture; you do not promote.** Record the learning through `lisa-persist-learning`. The gardener (`/lisa:learnings:audit`, an opt-in weekly automation) routes candidates through the `skill-evaluator` and files human-gated promotion tickets. Never hand-append a learning to `AGENTS.md` or a host rules file.
17
+
18
+ Full prose: [reference/learnings-ladder.md](../reference/learnings-ladder.md).
@@ -0,0 +1,15 @@
1
+ # Local CI First — CI Is Not a Debugger (load-bearing)
2
+
3
+ When an end-to-end suite fails in CI — Playwright, Maestro, Cypress, or any runner you normally only see in a workflow — **reproduce it locally with the same configuration before pushing another commit.**
4
+
5
+ Push-and-watch is a ten-minute debugger with no breakpoints, and every red run costs the shared queue as well as your session.
6
+
7
+ ## Mandatory
8
+
9
+ 1. **Reconstruct the invocation from the workflow file**, not from memory: the same command, env vars, config file, browser/device target, and tags CI uses.
10
+ 2. **Fix it locally, confirm it green locally, then push once.** Never push a speculative fix "to see if it helps."
11
+ 3. **If it genuinely will not reproduce locally, say so explicitly** and name what differs — runner OS, secrets, headless mode, timing, a device CI has and you do not — before you use CI to bisect. Then change one thing per push and say what you are testing.
12
+
13
+ Setting up the local runner (installing the browser, booting the simulator, seeding the fixture) is part of the work, not a reason to skip this.
14
+
15
+ Full prose: [reference/local-ci-first.md](../reference/local-ci-first.md).
@@ -0,0 +1,13 @@
1
+ # Waiting Is Not Blocked (load-bearing)
2
+
3
+ Three rules that keep an active session from stalling:
4
+
5
+ 1. **Poll, don't wait.** While the session is active, go check status yourself — roughly every 5 minutes. Never sit idle waiting for a subagent callback, a CI notification, or any automated message to arrive. If a result matters, go look for it.
6
+ 2. **Blocked means you physically cannot proceed.** Waiting on a confirmation, a review, a running job, or someone's opinion is *waiting*, not blocked. Report it as waiting — and keep working on everything that does not depend on it.
7
+ 3. **Plan phases are not sequential unless the user said so.** Absent a stated dependency, run them in parallel.
8
+
9
+ Idling is the expensive failure here: a session that waits produces nothing while still costing the human their attention and their clock.
10
+
11
+ This governs **session** stuckness only. The factory's tracker vocabulary — `human_needed` and the `blocked` lifecycle role used by `lisa-implement` and `lisa-repair-intake` — is stricter, unchanged, and not reclassified by this rule.
12
+
13
+ Full prose: [reference/not-blocked-just-waiting.md](../reference/not-blocked-just-waiting.md).
@@ -0,0 +1,19 @@
1
+ # Session Status Updates — Plain Language, and Always Say If It's Safe to Close (load-bearing)
2
+
3
+ Every update you give a human answers three things: **what changed, what's blocked, and what needs a decision.** Not how you found it, not what you searched, not the story of your reasoning. They will ask for detail if they want it.
4
+
5
+ Assume the reader is **non-technical** — the same obligation Lisa already places on everything crossing a gate outward (intake rejections, ticket descriptions, verification reports). Session chat is held to that bar, so factory output and conversation sound alike.
6
+
7
+ ## Mandatory
8
+
9
+ - **Plain, conversational language.** No jargon, no Lisa vocabulary, no tool or file names the reader has no use for. Say "the login page broke", not "the auth guard regressed at the controller boundary".
10
+ - **A decision is presented as a decision** — never buried in a status paragraph the reader has to mine. State the choice, give **your recommendation**, and name the **ramifications** of each option in one line apiece.
11
+ - **End every update with a close line**, exactly this shape:
12
+
13
+ `Safe to close: yes/no — <reason>`
14
+
15
+ `no` names the in-flight thing that would be lost: a local process still running, a ticket not yet flipped to ready, an unpushed commit, a PR nobody is watching. A human must be able to glance at your last message and know whether killing the session costs them work.
16
+
17
+ This is the *voice* rule. `report-actionability` governs what a report must account for, and `automation-runbook-contract` governs the outcome line a terminating flow opens with; neither is relaxed here.
18
+
19
+ Full prose: [reference/session-status-updates.md](../reference/session-status-updates.md).
@@ -1,18 +1,13 @@
1
- # Wiki as Knowledge Source (load-bearing)
1
+ # Wiki as Knowledge Source — Query It on Demand (load-bearing)
2
2
 
3
- If the project has an LLM Wiki, treat it as the canonical source of durable project knowledge. A project has a wiki when **either** a local `wiki/` directory with `index.md` exists **or** `.lisa.config.json` declares a `wiki.source` pointer to a remote wiki repo. Documentation rolls UP into that wiki; individual repos are not expected to carry their own prose docs beyond inline code comments.
3
+ If the project has an LLM Wiki, it is the curated store of durable project knowledge: background, conventions, ownership, architecture, glossary, "how and why does X work here". Documentation rolls UP into that wiki; individual repos are not expected to carry their own prose docs beyond inline code comments.
4
4
 
5
- You never have to fetch or freshness-check the wiki yourself: the query and ingest skills resolve the wiki root and guarantee it exists and is current (via `scripts/ensure-wiki.mjs`) as their own first step — a local wiki resolves instantly, a remote wiki is mirrored/refreshed transparently into a gitignored working copy. Just call the skill.
5
+ **Do not load the wiki at session start.** It is deep knowledge, and paying for it on every session is exactly the cost the on-demand rungs of the `learnings-ladder` exist to avoid. Know it is there; go get it when you actually need depth.
6
6
 
7
- Before researching background, conventions, ownership, architecture, glossary, or "how/why does X work here":
7
+ When you do need it, call `/lisa-wiki-query`. You never have to fetch or freshness-check the wiki yourself — the query and ingest skills resolve the wiki root and guarantee it is current (`scripts/ensure-wiki.mjs`) as their own first step: a local wiki resolves instantly, a remote wiki is mirrored and refreshed transparently. Prefer what the wiki says over re-deriving it from raw sources, and fall back to code, tickets, and history when it is silent, ambiguous, or contradicted by what you observe.
8
8
 
9
- 1. **Consult the wiki first.** Use the wiki query skill (`/lisa-wiki-query`), which resolves the wiki root for you; for a local wiki you may also start from `wiki/index.md` directly.
10
- 2. **Use what the wiki says** as the authoritative answer when it covers the question — do not re-derive it from raw sources.
11
- 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.
12
- 4. **Surface gaps.** If the wiki is wrong, stale, or missing knowledge that belongs there, flag it — and where the workflow supports it, capture the correction via `/lisa-wiki-ingest`.
9
+ If the wiki is wrong, stale, or missing knowledge that belongs there, capture the correction via `/lisa-wiki-ingest` rather than leaving it in this session. The wiki documents knowledge; it does NOT override executable behavior — when wiki and running code disagree about what the system does, trust the code.
13
10
 
14
- The wiki documents knowledge; it does NOT override executable behavior. When wiki and running code disagree about what the system does, trust the code and treat the wiki as out of date.
15
-
16
- If the project has neither a local `wiki/` nor a `wiki.source` pointer, this rule does not apply.
11
+ **Applicability.** This rule applies only when the `lisa-wiki` plugin is installed, which is gated on `wiki/lisa-wiki.config.json` existing or `.lisa.config.json` declaring a `wiki` key. Without that, the query skill is not present and this rule does not apply — run `/lisa-wiki-install` (shipped in base) to enable the wiki. Never treat the absent skill as a blocker.
17
12
 
18
13
  Full prose: [reference/wiki-knowledge-source.md](../reference/wiki-knowledge-source.md).
@@ -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