@codyswann/lisa 2.353.0 → 3.1.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 (318) hide show
  1. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  2. package/dist/core/upstream-evidence-manifest.js +83 -47
  3. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  4. package/expo/copy-overwrite/scripts/bdd/discover.mjs +502 -0
  5. package/expo/copy-overwrite/scripts/bdd/envelope.mjs +10 -1
  6. package/expo/copy-overwrite/scripts/bdd/render.mjs +53 -0
  7. package/expo/copy-overwrite/scripts/bdd/report.mjs +46 -0
  8. package/expo/copy-overwrite/scripts/check-bdd-coverage.mjs +39 -4
  9. package/expo/create-only/.github/workflows/nightly-e2e-report.yml +71 -0
  10. package/expo/create-only/bdd/coverage-map.json +16 -0
  11. package/package.json +1 -1
  12. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  13. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  14. package/plugins/lisa/.codex-plugin/skills/lisa-agent-ready/SKILL.md +5 -3
  15. package/plugins/lisa/.codex-plugin/skills/lisa-atlassian-access/SKILL.md +75 -64
  16. package/plugins/lisa/.codex-plugin/skills/lisa-confluence-to-tracker/SKILL.md +2 -1
  17. package/plugins/lisa/.codex-plugin/skills/lisa-debrief-apply/SKILL.md +2 -2
  18. package/plugins/lisa/.codex-plugin/skills/lisa-exploratory-qa/SKILL.md +7 -1
  19. package/plugins/lisa/.codex-plugin/skills/lisa-github-build-intake/SKILL.md +5 -0
  20. package/plugins/lisa/.codex-plugin/skills/lisa-github-create/SKILL.md +3 -1
  21. package/plugins/lisa/.codex-plugin/skills/lisa-github-to-tracker/SKILL.md +2 -1
  22. package/plugins/lisa/.codex-plugin/skills/lisa-github-validate-issue/SKILL.md +7 -3
  23. package/plugins/lisa/.codex-plugin/skills/lisa-github-write-issue/SKILL.md +16 -6
  24. package/plugins/lisa/.codex-plugin/skills/lisa-improve-harness/SKILL.md +1 -1
  25. package/plugins/lisa/.codex-plugin/skills/lisa-jam-access/SKILL.md +13 -5
  26. package/plugins/lisa/.codex-plugin/skills/lisa-jira-build-intake/SKILL.md +5 -0
  27. package/plugins/lisa/.codex-plugin/skills/lisa-jira-create/SKILL.md +2 -0
  28. package/plugins/lisa/.codex-plugin/skills/lisa-jira-write-ticket/SKILL.md +12 -2
  29. package/plugins/lisa/.codex-plugin/skills/lisa-learnings-audit/SKILL.md +6 -1
  30. package/plugins/lisa/.codex-plugin/skills/lisa-linear-access/SKILL.md +30 -10
  31. package/plugins/lisa/.codex-plugin/skills/lisa-linear-build-intake/SKILL.md +5 -0
  32. package/plugins/lisa/.codex-plugin/skills/lisa-linear-create/SKILL.md +3 -1
  33. package/plugins/lisa/.codex-plugin/skills/lisa-linear-to-tracker/SKILL.md +2 -1
  34. package/plugins/lisa/.codex-plugin/skills/lisa-linear-write-issue/SKILL.md +13 -4
  35. package/plugins/lisa/.codex-plugin/skills/lisa-notion-access/SKILL.md +36 -23
  36. package/plugins/lisa/.codex-plugin/skills/lisa-notion-to-tracker/SKILL.md +2 -1
  37. package/plugins/lisa/.codex-plugin/skills/lisa-persist-learning/SKILL.md +1 -1
  38. package/plugins/lisa/.codex-plugin/skills/lisa-posthog-access/SKILL.md +16 -6
  39. package/plugins/lisa/.codex-plugin/skills/lisa-prd-source-write/SKILL.md +4 -2
  40. package/plugins/lisa/.codex-plugin/skills/lisa-qa-fail/SKILL.md +3 -1
  41. package/plugins/lisa/.codex-plugin/skills/lisa-repair-intake/SKILL.md +28 -0
  42. package/plugins/lisa/.codex-plugin/skills/lisa-rework-triage/SKILL.md +2 -2
  43. package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/SKILL.md +8 -0
  44. package/plugins/lisa/.codex-plugin/skills/lisa-sentry-access/SKILL.md +16 -6
  45. package/plugins/lisa/.codex-plugin/skills/lisa-sonarcloud-access/SKILL.md +7 -1
  46. package/plugins/lisa/.codex-plugin/skills/lisa-tracker-build-intake/SKILL.md +1 -0
  47. package/plugins/lisa/.codex-plugin/skills/lisa-tracker-create/SKILL.md +1 -0
  48. package/plugins/lisa/.codex-plugin/skills/lisa-tracker-write/SKILL.md +1 -0
  49. package/plugins/lisa/.codex-plugin/skills/lisa-verify/SKILL.md +1 -1
  50. package/plugins/lisa/rules/eager/bdd-e2e-coverage.md +3 -1
  51. package/plugins/lisa/rules/eager/claim-time-guards.md +30 -0
  52. package/plugins/lisa/rules/eager/integration-access-layer.md +7 -3
  53. package/plugins/lisa/rules/eager/ready-role-filing.md +22 -0
  54. package/plugins/lisa/rules/reference/automation-runbook-contract.md +8 -1
  55. package/plugins/lisa/rules/reference/bdd-e2e-coverage.md +42 -6
  56. package/plugins/lisa/rules/reference/claim-time-guards.md +69 -0
  57. package/plugins/lisa/rules/reference/credential-substrate-precedence.md +166 -0
  58. package/plugins/lisa/rules/reference/integration-access-layer.md +27 -15
  59. package/plugins/lisa/rules/reference/ready-role-filing.md +66 -0
  60. package/plugins/lisa/skills/lisa-agent-ready/SKILL.md +5 -3
  61. package/plugins/lisa/skills/lisa-atlassian-access/SKILL.md +76 -65
  62. package/plugins/lisa/skills/lisa-confluence-to-tracker/SKILL.md +2 -1
  63. package/plugins/lisa/skills/lisa-debrief-apply/SKILL.md +2 -2
  64. package/plugins/lisa/skills/lisa-exploratory-qa/SKILL.md +7 -1
  65. package/plugins/lisa/skills/lisa-github-build-intake/SKILL.md +5 -0
  66. package/plugins/lisa/skills/lisa-github-create/SKILL.md +3 -1
  67. package/plugins/lisa/skills/lisa-github-to-tracker/SKILL.md +2 -1
  68. package/plugins/lisa/skills/lisa-github-validate-issue/SKILL.md +7 -3
  69. package/plugins/lisa/skills/lisa-github-write-issue/SKILL.md +16 -6
  70. package/plugins/lisa/skills/lisa-improve-harness/SKILL.md +1 -1
  71. package/plugins/lisa/skills/lisa-jam-access/SKILL.md +14 -6
  72. package/plugins/lisa/skills/lisa-jira-build-intake/SKILL.md +5 -0
  73. package/plugins/lisa/skills/lisa-jira-create/SKILL.md +2 -0
  74. package/plugins/lisa/skills/lisa-jira-write-ticket/SKILL.md +12 -2
  75. package/plugins/lisa/skills/lisa-learnings-audit/SKILL.md +6 -1
  76. package/plugins/lisa/skills/lisa-linear-access/SKILL.md +31 -11
  77. package/plugins/lisa/skills/lisa-linear-build-intake/SKILL.md +5 -0
  78. package/plugins/lisa/skills/lisa-linear-create/SKILL.md +3 -1
  79. package/plugins/lisa/skills/lisa-linear-to-tracker/SKILL.md +2 -1
  80. package/plugins/lisa/skills/lisa-linear-write-issue/SKILL.md +13 -4
  81. package/plugins/lisa/skills/lisa-notion-access/SKILL.md +37 -24
  82. package/plugins/lisa/skills/lisa-notion-to-tracker/SKILL.md +2 -1
  83. package/plugins/lisa/skills/lisa-persist-learning/SKILL.md +1 -1
  84. package/plugins/lisa/skills/lisa-posthog-access/SKILL.md +17 -7
  85. package/plugins/lisa/skills/lisa-prd-source-write/SKILL.md +4 -2
  86. package/plugins/lisa/skills/lisa-qa-fail/SKILL.md +3 -1
  87. package/plugins/lisa/skills/lisa-repair-intake/SKILL.md +28 -0
  88. package/plugins/lisa/skills/lisa-rework-triage/SKILL.md +2 -2
  89. package/plugins/lisa/skills/lisa-secrets-access/SKILL.md +8 -0
  90. package/plugins/lisa/skills/lisa-sentry-access/SKILL.md +17 -7
  91. package/plugins/lisa/skills/lisa-sonarcloud-access/SKILL.md +7 -1
  92. package/plugins/lisa/skills/lisa-tracker-build-intake/SKILL.md +1 -0
  93. package/plugins/lisa/skills/lisa-tracker-create/SKILL.md +1 -0
  94. package/plugins/lisa/skills/lisa-tracker-write/SKILL.md +1 -0
  95. package/plugins/lisa/skills/lisa-verify/SKILL.md +1 -1
  96. package/plugins/lisa-agy/plugin.json +1 -1
  97. package/plugins/lisa-agy/skills/lisa-agent-ready/SKILL.md +5 -3
  98. package/plugins/lisa-agy/skills/lisa-atlassian-access/SKILL.md +76 -65
  99. package/plugins/lisa-agy/skills/lisa-confluence-to-tracker/SKILL.md +2 -1
  100. package/plugins/lisa-agy/skills/lisa-debrief-apply/SKILL.md +2 -2
  101. package/plugins/lisa-agy/skills/lisa-exploratory-qa/SKILL.md +7 -1
  102. package/plugins/lisa-agy/skills/lisa-github-build-intake/SKILL.md +5 -0
  103. package/plugins/lisa-agy/skills/lisa-github-create/SKILL.md +3 -1
  104. package/plugins/lisa-agy/skills/lisa-github-to-tracker/SKILL.md +2 -1
  105. package/plugins/lisa-agy/skills/lisa-github-validate-issue/SKILL.md +7 -3
  106. package/plugins/lisa-agy/skills/lisa-github-write-issue/SKILL.md +16 -6
  107. package/plugins/lisa-agy/skills/lisa-improve-harness/SKILL.md +1 -1
  108. package/plugins/lisa-agy/skills/lisa-jam-access/SKILL.md +14 -6
  109. package/plugins/lisa-agy/skills/lisa-jira-build-intake/SKILL.md +5 -0
  110. package/plugins/lisa-agy/skills/lisa-jira-create/SKILL.md +2 -0
  111. package/plugins/lisa-agy/skills/lisa-jira-write-ticket/SKILL.md +12 -2
  112. package/plugins/lisa-agy/skills/lisa-learnings-audit/SKILL.md +6 -1
  113. package/plugins/lisa-agy/skills/lisa-linear-access/SKILL.md +31 -11
  114. package/plugins/lisa-agy/skills/lisa-linear-build-intake/SKILL.md +5 -0
  115. package/plugins/lisa-agy/skills/lisa-linear-create/SKILL.md +3 -1
  116. package/plugins/lisa-agy/skills/lisa-linear-to-tracker/SKILL.md +2 -1
  117. package/plugins/lisa-agy/skills/lisa-linear-write-issue/SKILL.md +13 -4
  118. package/plugins/lisa-agy/skills/lisa-notion-access/SKILL.md +37 -24
  119. package/plugins/lisa-agy/skills/lisa-notion-to-tracker/SKILL.md +2 -1
  120. package/plugins/lisa-agy/skills/lisa-persist-learning/SKILL.md +1 -1
  121. package/plugins/lisa-agy/skills/lisa-posthog-access/SKILL.md +17 -7
  122. package/plugins/lisa-agy/skills/lisa-prd-source-write/SKILL.md +4 -2
  123. package/plugins/lisa-agy/skills/lisa-qa-fail/SKILL.md +3 -1
  124. package/plugins/lisa-agy/skills/lisa-repair-intake/SKILL.md +28 -0
  125. package/plugins/lisa-agy/skills/lisa-rework-triage/SKILL.md +2 -2
  126. package/plugins/lisa-agy/skills/lisa-secrets-access/SKILL.md +8 -0
  127. package/plugins/lisa-agy/skills/lisa-sentry-access/SKILL.md +17 -7
  128. package/plugins/lisa-agy/skills/lisa-sonarcloud-access/SKILL.md +7 -1
  129. package/plugins/lisa-agy/skills/lisa-tracker-build-intake/SKILL.md +1 -0
  130. package/plugins/lisa-agy/skills/lisa-tracker-create/SKILL.md +1 -0
  131. package/plugins/lisa-agy/skills/lisa-tracker-write/SKILL.md +1 -0
  132. package/plugins/lisa-agy/skills/lisa-verify/SKILL.md +1 -1
  133. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  134. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  135. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  136. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  137. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  138. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  139. package/plugins/lisa-copilot/rules/eager/bdd-e2e-coverage.md +3 -1
  140. package/plugins/lisa-copilot/rules/eager/claim-time-guards.md +30 -0
  141. package/plugins/lisa-copilot/rules/eager/integration-access-layer.md +7 -3
  142. package/plugins/lisa-copilot/rules/eager/ready-role-filing.md +22 -0
  143. package/plugins/lisa-copilot/rules/reference/automation-runbook-contract.md +8 -1
  144. package/plugins/lisa-copilot/rules/reference/bdd-e2e-coverage.md +42 -6
  145. package/plugins/lisa-copilot/rules/reference/claim-time-guards.md +69 -0
  146. package/plugins/lisa-copilot/rules/reference/credential-substrate-precedence.md +166 -0
  147. package/plugins/lisa-copilot/rules/reference/integration-access-layer.md +27 -15
  148. package/plugins/lisa-copilot/rules/reference/ready-role-filing.md +66 -0
  149. package/plugins/lisa-copilot/skills/lisa-agent-ready/SKILL.md +5 -3
  150. package/plugins/lisa-copilot/skills/lisa-atlassian-access/SKILL.md +76 -65
  151. package/plugins/lisa-copilot/skills/lisa-confluence-to-tracker/SKILL.md +2 -1
  152. package/plugins/lisa-copilot/skills/lisa-debrief-apply/SKILL.md +2 -2
  153. package/plugins/lisa-copilot/skills/lisa-exploratory-qa/SKILL.md +7 -1
  154. package/plugins/lisa-copilot/skills/lisa-github-build-intake/SKILL.md +5 -0
  155. package/plugins/lisa-copilot/skills/lisa-github-create/SKILL.md +3 -1
  156. package/plugins/lisa-copilot/skills/lisa-github-to-tracker/SKILL.md +2 -1
  157. package/plugins/lisa-copilot/skills/lisa-github-validate-issue/SKILL.md +7 -3
  158. package/plugins/lisa-copilot/skills/lisa-github-write-issue/SKILL.md +16 -6
  159. package/plugins/lisa-copilot/skills/lisa-improve-harness/SKILL.md +1 -1
  160. package/plugins/lisa-copilot/skills/lisa-jam-access/SKILL.md +14 -6
  161. package/plugins/lisa-copilot/skills/lisa-jira-build-intake/SKILL.md +5 -0
  162. package/plugins/lisa-copilot/skills/lisa-jira-create/SKILL.md +2 -0
  163. package/plugins/lisa-copilot/skills/lisa-jira-write-ticket/SKILL.md +12 -2
  164. package/plugins/lisa-copilot/skills/lisa-learnings-audit/SKILL.md +6 -1
  165. package/plugins/lisa-copilot/skills/lisa-linear-access/SKILL.md +31 -11
  166. package/plugins/lisa-copilot/skills/lisa-linear-build-intake/SKILL.md +5 -0
  167. package/plugins/lisa-copilot/skills/lisa-linear-create/SKILL.md +3 -1
  168. package/plugins/lisa-copilot/skills/lisa-linear-to-tracker/SKILL.md +2 -1
  169. package/plugins/lisa-copilot/skills/lisa-linear-write-issue/SKILL.md +13 -4
  170. package/plugins/lisa-copilot/skills/lisa-notion-access/SKILL.md +37 -24
  171. package/plugins/lisa-copilot/skills/lisa-notion-to-tracker/SKILL.md +2 -1
  172. package/plugins/lisa-copilot/skills/lisa-persist-learning/SKILL.md +1 -1
  173. package/plugins/lisa-copilot/skills/lisa-posthog-access/SKILL.md +17 -7
  174. package/plugins/lisa-copilot/skills/lisa-prd-source-write/SKILL.md +4 -2
  175. package/plugins/lisa-copilot/skills/lisa-qa-fail/SKILL.md +3 -1
  176. package/plugins/lisa-copilot/skills/lisa-repair-intake/SKILL.md +28 -0
  177. package/plugins/lisa-copilot/skills/lisa-rework-triage/SKILL.md +2 -2
  178. package/plugins/lisa-copilot/skills/lisa-secrets-access/SKILL.md +8 -0
  179. package/plugins/lisa-copilot/skills/lisa-sentry-access/SKILL.md +17 -7
  180. package/plugins/lisa-copilot/skills/lisa-sonarcloud-access/SKILL.md +7 -1
  181. package/plugins/lisa-copilot/skills/lisa-tracker-build-intake/SKILL.md +1 -0
  182. package/plugins/lisa-copilot/skills/lisa-tracker-create/SKILL.md +1 -0
  183. package/plugins/lisa-copilot/skills/lisa-tracker-write/SKILL.md +1 -0
  184. package/plugins/lisa-copilot/skills/lisa-verify/SKILL.md +1 -1
  185. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  186. package/plugins/lisa-cursor/rules/automation-runbook-contract-reference.mdc +8 -1
  187. package/plugins/lisa-cursor/rules/bdd-e2e-coverage-reference.mdc +42 -6
  188. package/plugins/lisa-cursor/rules/bdd-e2e-coverage.mdc +3 -1
  189. package/plugins/lisa-cursor/rules/claim-time-guards-reference.mdc +74 -0
  190. package/plugins/lisa-cursor/rules/claim-time-guards.mdc +35 -0
  191. package/plugins/lisa-cursor/rules/credential-substrate-precedence-reference.mdc +171 -0
  192. package/plugins/lisa-cursor/rules/integration-access-layer-reference.mdc +27 -15
  193. package/plugins/lisa-cursor/rules/integration-access-layer.mdc +7 -3
  194. package/plugins/lisa-cursor/rules/ready-role-filing-reference.mdc +71 -0
  195. package/plugins/lisa-cursor/rules/ready-role-filing.mdc +27 -0
  196. package/plugins/lisa-cursor/skills/lisa-agent-ready/SKILL.md +5 -3
  197. package/plugins/lisa-cursor/skills/lisa-atlassian-access/SKILL.md +76 -65
  198. package/plugins/lisa-cursor/skills/lisa-confluence-to-tracker/SKILL.md +2 -1
  199. package/plugins/lisa-cursor/skills/lisa-debrief-apply/SKILL.md +2 -2
  200. package/plugins/lisa-cursor/skills/lisa-exploratory-qa/SKILL.md +7 -1
  201. package/plugins/lisa-cursor/skills/lisa-github-build-intake/SKILL.md +5 -0
  202. package/plugins/lisa-cursor/skills/lisa-github-create/SKILL.md +3 -1
  203. package/plugins/lisa-cursor/skills/lisa-github-to-tracker/SKILL.md +2 -1
  204. package/plugins/lisa-cursor/skills/lisa-github-validate-issue/SKILL.md +7 -3
  205. package/plugins/lisa-cursor/skills/lisa-github-write-issue/SKILL.md +16 -6
  206. package/plugins/lisa-cursor/skills/lisa-improve-harness/SKILL.md +1 -1
  207. package/plugins/lisa-cursor/skills/lisa-jam-access/SKILL.md +14 -6
  208. package/plugins/lisa-cursor/skills/lisa-jira-build-intake/SKILL.md +5 -0
  209. package/plugins/lisa-cursor/skills/lisa-jira-create/SKILL.md +2 -0
  210. package/plugins/lisa-cursor/skills/lisa-jira-write-ticket/SKILL.md +12 -2
  211. package/plugins/lisa-cursor/skills/lisa-learnings-audit/SKILL.md +6 -1
  212. package/plugins/lisa-cursor/skills/lisa-linear-access/SKILL.md +31 -11
  213. package/plugins/lisa-cursor/skills/lisa-linear-build-intake/SKILL.md +5 -0
  214. package/plugins/lisa-cursor/skills/lisa-linear-create/SKILL.md +3 -1
  215. package/plugins/lisa-cursor/skills/lisa-linear-to-tracker/SKILL.md +2 -1
  216. package/plugins/lisa-cursor/skills/lisa-linear-write-issue/SKILL.md +13 -4
  217. package/plugins/lisa-cursor/skills/lisa-notion-access/SKILL.md +37 -24
  218. package/plugins/lisa-cursor/skills/lisa-notion-to-tracker/SKILL.md +2 -1
  219. package/plugins/lisa-cursor/skills/lisa-persist-learning/SKILL.md +1 -1
  220. package/plugins/lisa-cursor/skills/lisa-posthog-access/SKILL.md +17 -7
  221. package/plugins/lisa-cursor/skills/lisa-prd-source-write/SKILL.md +4 -2
  222. package/plugins/lisa-cursor/skills/lisa-qa-fail/SKILL.md +3 -1
  223. package/plugins/lisa-cursor/skills/lisa-repair-intake/SKILL.md +28 -0
  224. package/plugins/lisa-cursor/skills/lisa-rework-triage/SKILL.md +2 -2
  225. package/plugins/lisa-cursor/skills/lisa-secrets-access/SKILL.md +8 -0
  226. package/plugins/lisa-cursor/skills/lisa-sentry-access/SKILL.md +17 -7
  227. package/plugins/lisa-cursor/skills/lisa-sonarcloud-access/SKILL.md +7 -1
  228. package/plugins/lisa-cursor/skills/lisa-tracker-build-intake/SKILL.md +1 -0
  229. package/plugins/lisa-cursor/skills/lisa-tracker-create/SKILL.md +1 -0
  230. package/plugins/lisa-cursor/skills/lisa-tracker-write/SKILL.md +1 -0
  231. package/plugins/lisa-cursor/skills/lisa-verify/SKILL.md +1 -1
  232. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  233. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  234. package/plugins/lisa-expo-agy/plugin.json +1 -1
  235. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  236. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  237. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  238. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  239. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  240. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  241. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  242. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  243. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  244. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  245. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  246. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  247. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  248. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  249. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  250. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  251. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  252. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  253. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  254. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  255. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  256. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  257. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  258. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  259. package/plugins/lisa-rails-agy/plugin.json +1 -1
  260. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  261. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  262. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  263. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  264. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  265. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  266. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  267. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  268. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  269. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  270. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  271. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  272. package/plugins/src/base/rules/eager/bdd-e2e-coverage.md +3 -1
  273. package/plugins/src/base/rules/eager/claim-time-guards.md +30 -0
  274. package/plugins/src/base/rules/eager/integration-access-layer.md +7 -3
  275. package/plugins/src/base/rules/eager/ready-role-filing.md +22 -0
  276. package/plugins/src/base/rules/reference/automation-runbook-contract.md +8 -1
  277. package/plugins/src/base/rules/reference/bdd-e2e-coverage.md +42 -6
  278. package/plugins/src/base/rules/reference/claim-time-guards.md +69 -0
  279. package/plugins/src/base/rules/reference/credential-substrate-precedence.md +166 -0
  280. package/plugins/src/base/rules/reference/integration-access-layer.md +27 -15
  281. package/plugins/src/base/rules/reference/ready-role-filing.md +66 -0
  282. package/plugins/src/base/skills/lisa-agent-ready/SKILL.md +5 -3
  283. package/plugins/src/base/skills/lisa-atlassian-access/SKILL.md +76 -65
  284. package/plugins/src/base/skills/lisa-confluence-to-tracker/SKILL.md +2 -1
  285. package/plugins/src/base/skills/lisa-debrief-apply/SKILL.md +2 -2
  286. package/plugins/src/base/skills/lisa-exploratory-qa/SKILL.md +7 -1
  287. package/plugins/src/base/skills/lisa-github-build-intake/SKILL.md +5 -0
  288. package/plugins/src/base/skills/lisa-github-create/SKILL.md +3 -1
  289. package/plugins/src/base/skills/lisa-github-to-tracker/SKILL.md +2 -1
  290. package/plugins/src/base/skills/lisa-github-validate-issue/SKILL.md +7 -3
  291. package/plugins/src/base/skills/lisa-github-write-issue/SKILL.md +16 -6
  292. package/plugins/src/base/skills/lisa-improve-harness/SKILL.md +1 -1
  293. package/plugins/src/base/skills/lisa-jam-access/SKILL.md +14 -6
  294. package/plugins/src/base/skills/lisa-jira-build-intake/SKILL.md +5 -0
  295. package/plugins/src/base/skills/lisa-jira-create/SKILL.md +2 -0
  296. package/plugins/src/base/skills/lisa-jira-write-ticket/SKILL.md +12 -2
  297. package/plugins/src/base/skills/lisa-learnings-audit/SKILL.md +6 -1
  298. package/plugins/src/base/skills/lisa-linear-access/SKILL.md +31 -11
  299. package/plugins/src/base/skills/lisa-linear-build-intake/SKILL.md +5 -0
  300. package/plugins/src/base/skills/lisa-linear-create/SKILL.md +3 -1
  301. package/plugins/src/base/skills/lisa-linear-to-tracker/SKILL.md +2 -1
  302. package/plugins/src/base/skills/lisa-linear-write-issue/SKILL.md +13 -4
  303. package/plugins/src/base/skills/lisa-notion-access/SKILL.md +37 -24
  304. package/plugins/src/base/skills/lisa-notion-to-tracker/SKILL.md +2 -1
  305. package/plugins/src/base/skills/lisa-persist-learning/SKILL.md +1 -1
  306. package/plugins/src/base/skills/lisa-posthog-access/SKILL.md +17 -7
  307. package/plugins/src/base/skills/lisa-prd-source-write/SKILL.md +4 -2
  308. package/plugins/src/base/skills/lisa-qa-fail/SKILL.md +3 -1
  309. package/plugins/src/base/skills/lisa-repair-intake/SKILL.md +28 -0
  310. package/plugins/src/base/skills/lisa-rework-triage/SKILL.md +2 -2
  311. package/plugins/src/base/skills/lisa-secrets-access/SKILL.md +8 -0
  312. package/plugins/src/base/skills/lisa-sentry-access/SKILL.md +17 -7
  313. package/plugins/src/base/skills/lisa-sonarcloud-access/SKILL.md +7 -1
  314. package/plugins/src/base/skills/lisa-tracker-build-intake/SKILL.md +1 -0
  315. package/plugins/src/base/skills/lisa-tracker-create/SKILL.md +1 -0
  316. package/plugins/src/base/skills/lisa-tracker-write/SKILL.md +1 -0
  317. package/plugins/src/base/skills/lisa-verify/SKILL.md +1 -1
  318. package/typescript/copy-overwrite/scripts/check-nightly-e2e-health.mjs +631 -5
@@ -10,6 +10,14 @@ Single chokepoint for reading credentials. Caller skills MUST go through this
10
10
 
11
11
  The rule this exists to enforce: **a secret lives in exactly one store.** Every local cache is a copy that will eventually drift from its source, and a drifted copy is indistinguishable from a valid one until something fails in production.
12
12
 
13
+ This skill is also the chokepoint that feeds **tier 1** of the shared
14
+ `credential-substrate-precedence` contract: every `*-access` skill resolves its
15
+ configured-provider token or CLI credential here, ahead of any interactive MCP. That
16
+ is what makes "provider-first" actionable rather than aspirational — including the
17
+ `tool:` note line below, which declares which CLI a given credential is expected to
18
+ drive. This skill decides *where a credential comes from*; it never decides substrate
19
+ ordering, which is settled once in that contract.
20
+
13
21
  ## Two axes, not one
14
22
 
15
23
  A **provider** is where secrets live. A **surface** is where the running code lives, and it determines how secrets reach that code. These are independent: the same Bitwarden project serves a laptop, a CI runner, and a remote agent container, but each obtains its values differently.
@@ -22,13 +22,21 @@ Return parsed JSON in a `<result>` block.
22
22
 
23
23
  ## Substrate Selection
24
24
 
25
- Probe in order:
25
+ Probe in order — the ordering is the shared `credential-substrate-precedence`
26
+ contract, not a Sentry-local choice. The first tier that is ready **and**
27
+ identity-matches the configured org/project is used; a substrate authenticated
28
+ against a different org is skipped, never used.
26
29
 
27
- 1. Sentry MCP, if available and authenticated.
28
- 2. `sentry-cli`, if installed and authenticated to the requested org/project.
29
- 3. `SENTRY_AUTH_TOKEN` bearer token against Sentry REST.
30
+ 1. **Tier 1 configured-provider substrate: `SENTRY_AUTH_TOKEN`** bearer token
31
+ against Sentry REST, resolved through `lisa-secrets-access`.
32
+ 2. **Tier 1a — `sentry-cli`**, if installed and authenticated to the requested
33
+ org/project from that same token (the CLI arm of the provider substrate).
34
+ 3. **Tier 2 — interactive MCP fallback: Sentry MCP**, if available and
35
+ authenticated. Used when tier 1 is genuinely unavailable: no
36
+ `SENTRY_AUTH_TOKEN`, no REST/CLI adapter for the operation, or a Sentry outage.
30
37
 
31
- Sentry documents API auth tokens for REST API calls. The headless REST tier uses:
38
+ Sentry documents API auth tokens for REST API calls, and the same token works
39
+ interactively and headlessly — which is why it leads. The REST tier uses:
32
40
 
33
41
  ```bash
34
42
  sentry_api() {
@@ -50,7 +58,9 @@ Error: no Sentry access substrate available. Authenticate Sentry MCP/CLI or set
50
58
 
51
59
  ## Invariants
52
60
 
53
- - Fallback is gated on `SENTRY_AUTH_TOKEN`.
61
+ - Tier order is `credential-substrate-precedence`: `SENTRY_AUTH_TOKEN` first, the
62
+ Sentry MCP as a preserved first-class fallback. Identity-match against the
63
+ configured org/project is mandatory on every tier.
54
64
  - Org/project come from `.sentryclirc`, `.lisa.config.json`, or explicit
55
65
  operation args; never infer by searching all accessible orgs.
56
66
  - Consumer skills do not embed Sentry REST paths.
@@ -15,7 +15,13 @@ this skill owns the tool selection.
15
15
  There is exactly one substrate: the **official SonarQube MCP server**, provided by
16
16
  the `sonarqube` plugin and launched by the `sonar` CLI (`sonar run mcp`). It
17
17
  authenticates headlessly from environment variables — no browser, no OS keychain —
18
- so it is the same substrate on a developer machine and in a headless cloud routine:
18
+ so it is the same substrate on a developer machine and in a headless cloud routine.
19
+
20
+ That makes this skill conformant with `credential-substrate-precedence` as a
21
+ single-substrate access layer: this MCP **is** the configured-provider substrate
22
+ (it is token-authenticated, not browser-OAuth), so there is no interactive tier to
23
+ demote and no second REST tier to add. Identity-match against the configured org
24
+ remains mandatory, as on every substrate.
19
25
 
20
26
  - `SONARQUBE_CLI_TOKEN` — required (Sonar user/analysis token).
21
27
  - `SONARQUBE_CLI_ORG` — required for SonarQube Cloud.
@@ -83,4 +83,5 @@ If the canonical fix is merged but not yet on the production branch, the close c
83
83
  - **Leaf-only dispatch, every vendor.** Per the `leaf-only-lifecycle` rule, each vendor scanner dispatches leaf work units only and moves or safe-blocks a container (open child work, or a childless Epic) carrying a stale build-ready role according to its lifecycle semantics. This shim does not re-implement the gate — it relies on the vendor scanner's Phase 3a — but the contract is uniform across `jira`, `github`, and `linear` so behavior never drifts by tracker.
84
84
  - **Terminal native closure, every capable vendor.** Per the same rule, each vendor scanner finalizes native open/closed state only at the true terminal `done` value. This shim never performs native closure itself, but callers can rely on the dispatched vendor scanner to apply the contract.
85
85
  - **Duplicate already fixed, every vendor.** Auto-close without a PR is allowed only for `DUPLICATE_ALREADY_FIXED` with canonical reference and empirical base-branch evidence. Do not conflate this with `BLOCKED`.
86
+ - **Claim-time guards, every vendor.** Per the `claim-time-guards` rule, each vendor scanner runs both guards inside its Phase 3b before the claim transition: an item whose own key already appears in git history or an open/merged PR routes to **verify-and-close** rather than being built twice, and the **`two-failed-attempts`** valve moves an item with two `[lisa-build-attempt]` markers to the configured blocked role and stops the cycle. This shim does not re-implement either guard; it forwards the contract so behavior never drifts by tracker.
86
87
  - Never run two intake cycles concurrently against overlapping queues — the scheduling layer is responsible for serialization.
@@ -24,4 +24,5 @@ See the `config-resolution` rule for configuration and dispatch table.
24
24
  ## Rules
25
25
 
26
26
  - All vendor skills delegate every individual ticket write through `lisa-tracker-write`. They never call vendor-specific write tools directly.
27
+ - **Declare readiness on every leaf write.** Per the `ready-role-filing` rule an omitted `build_ready` is **not build-ready** on any tracker, so pass `build_ready: true` on each Sub-task (the leaf work units this skill plans) and never on the Epic or Stories, which are containers per `leaf-only-lifecycle`. A leaf that is deliberately held instead passes `human_gate: "<why a human must judge this first>"`. Filing a leaf with neither is an incomplete handoff and `lisa-tracker-write` rejects it.
27
28
  - This shim is for ad-hoc creation from code files / descriptions. PRD-driven creation goes through the `*-to-tracker` skills (notion / confluence / linear / github).
@@ -52,3 +52,4 @@ See the `config-resolution` rule for the full configuration schema and skill-map
52
52
  - Never accept a tracker value outside `{jira, github, linear}`.
53
53
  - Never mutate `$ARGUMENTS` between layers. The vendor skills define their own input contract.
54
54
  - Never inline gate logic here. All validation rules live in the vendor skills (`lisa-jira-validate-ticket` / `lisa-github-validate-issue` / `lisa-linear-validate-issue`); this skill only routes.
55
+ - **Readiness is the caller's explicit claim, not this shim's default.** Per the `ready-role-filing` rule, an omitted `build_ready` is **not build-ready** on every vendor, so a caller filing work it expects build-intake to pick up must pass `build_ready: true`, and a caller deliberately holding work outside the queue must pass a `human_gate` reason. This shim normalizes nothing — it forwards `$ARGUMENTS` verbatim and the vendor writers enforce the contract — which is exactly why the caller cannot rely on a vendor default here.
@@ -35,7 +35,7 @@ Treat the first successful lead-spawn request (or, on the Codex fallback, the fi
35
35
 
36
36
  Execute the **Verify** flow as defined in the `intent-routing` rule (loaded via the lisa plugin). The flow includes:
37
37
 
38
- 1. **Pre-flight: codification gate** — confirm that every passing local empirical verification on this branch was codified as a regression test (the Implement flow's codify step). If any verification has no committed test and no allowed skip reason (PR / Documentation / Deploy / Investigate-Only), invoke `codify-verification` now and amend the PR before shipping. For frontend work the gate additionally enforces the `bdd-e2e-coverage` rule: the shipped behavior exists as a Gherkin scenario with a stable ID, every required scenario-platform obligation has aligned automation in the project's configured runner for that platform or a dated waiver, and the project's coverage gate passes with the matrix regenerated. A missing runner is never a bare recorded absence — it needs a dated `platformWaivers` entry (per the rule) and, where the runner could reasonably be added, a linked build-ready follow-up ticket referenced from it; never a silent skip. Missing BDD coverage is a verification failure that blocks the ship, not a warning. A change cannot ship until its verifications are guarded. For work that adds or changes persistent state the gate additionally enforces the `reset-seed-coverage` rule: every entity the work introduces or changes is classified in the project's state contract, anything `fixture-owned` has an ownership predicate and a sweep, and the state-classification check passes — an unclassified entity fails closed and blocks the ship exactly as missing BDD coverage does.
38
+ 1. **Pre-flight: codification gate** — confirm that every passing local empirical verification on this branch was codified as a regression test (the Implement flow's codify step). If any verification has no committed test and no allowed skip reason (PR / Documentation / Deploy / Investigate-Only), invoke `codify-verification` now and amend the PR before shipping. For frontend work the gate additionally enforces the `bdd-e2e-coverage` rule: the shipped behavior exists as a Gherkin scenario with a stable ID, every required scenario-platform obligation has aligned automation in the project's configured runner for that platform or a dated waiver, and the project's coverage gate passes with the matrix regenerated. A missing runner is never a bare recorded absence — it needs a dated `platformWaivers` entry (per the rule) and, where the runner could reasonably be added, a linked build-ready follow-up ticket referenced from it — filed through `lisa-tracker-write` with explicit `build_ready: true` per `ready-role-filing`, since an omitted flag is NOT build-ready on any tracker and the waiver would then point at work nothing claims; never a silent skip. Missing BDD coverage is a verification failure that blocks the ship, not a warning. A change cannot ship until its verifications are guarded. For work that adds or changes persistent state the gate additionally enforces the `reset-seed-coverage` rule: every entity the work introduces or changes is classified in the project's state contract, anything `fixture-owned` has an ownership predicate and a sweep, and the state-classification check passes — an unclassified entity fails closed and blocks the ship exactly as missing BDD coverage does.
39
39
  2. **Commit** any pending changes via `lisa-git-commit`
40
40
  3. **Push and PR** via `lisa-git-submit-pr`
41
41
  4. **PR Watch Loop** — drive the PR to MERGED via `lisa-drive-pr-to-merge`, the single source of truth for clearing every blocker: auto-merge with direct-merge fallback, `BEHIND` re-sync, conflict resolution, failing-check fixes, human + bot review-comment handling with thread resolution (it invokes `lisa-pull-request-review` itself), stale `CHANGES_REQUESTED` dismissal, and post-merge ancestry verification. Do not re-implement the loop or its terminal conditions.
@@ -15,7 +15,7 @@ Default locations (a project that already has an equivalent contract keeps its o
15
15
  | Artifact | Default path | What it is |
16
16
  |---|---|---|
17
17
  | Scenarios | `bdd/features/*.feature` | Gherkin, the product-level behavior contract |
18
- | Coverage map | `bdd/coverage-map.json` | scenario → runner/platform/file/evidence mappings, plus waivers |
18
+ | Coverage map | `bdd/coverage-map.json` | scenario → runner/platform/file/evidence mappings, plus waivers, per-runner test-discovery roots, and exclusions |
19
19
  | Generated matrix | `docs/bdd-scenario-matrix.md` | regenerated, never hand-edited |
20
20
  | Burndown | `docs/e2e-bdd-coverage.md` | current coverage per platform |
21
21
 
@@ -36,6 +36,8 @@ The last three are out of the denominator. Deleting a committed capability to ma
36
36
 
37
37
  Coverage is counted per **required scenario-platform obligation**, and an obligation is sealed only by **aligned e2e automation in the project's configured runner for that platform** — the runner→platform mapping is project configuration (e.g. a web runner covering `web`, a device runner covering `ios`/`android`), never named by this contract. A unit test, a route boot, a screenshot, a fixture, an API test, or a passing test on a *different* platform never seals an obligation: they prove something else. Each mapping names the runner, the platforms, the file, and the evidence string inside it, so the gate can prove the mapping still resolves.
38
38
 
39
+ **The gate reads in both directions.** It also walks the test roots the project declares per runner, so an e2e test that exists but that the contract never mentions is a violation — map it to a scenario, or record an exclusion stating why it aligns to no product behavior. Roots are configuration: a subflow or helper directory left undeclared is structurally invisible, which is the same failure as having no gate for it.
40
+
39
41
  **Waivers are dated IOUs, never coverage.** An obligation whose runner genuinely cannot decide it today (no camera on the simulator, no request interception, no provisioned provider credential) is recorded with scenario, platforms, reason, and `recordedAt`. It leaves the denominator; it never counts as covered, and nothing about it asserts the behavior works. A waiver is invalid — and fails the gate — when it names a nonexistent scenario or an undeclared platform, covers an already-excluded scenario, or masks a scenario-platform that already has a mapping. Revisit a waiver when its reason dies.
40
42
 
41
43
  ## Definition of done
@@ -0,0 +1,30 @@
1
+ # Claim-Time Guards (load-bearing)
2
+
3
+ Two guards that run when build-intake claims a ready item, both from failures observed in the fleet: an item built twice because it had already shipped, and a loop burning cycles re-attempting an item that was never going to succeed.
4
+
5
+ **One vendor-neutral contract, cited by every build-intake arm** (the `leaf-only-lifecycle` / `repo-scope-split` / `rejection-detection` / `claim-archaeology` precedent: one shared slug, never three divergent implementations).
6
+
7
+ ## When they run
8
+
9
+ Inside build-intake step `3b`, after `rejection-detection` and `claim-archaeology`, still before the `$READY → $CLAIMED` transition. The `two-failed-attempts` valve runs first — it is cheaper and it is the only pass that can stop the claim outright.
10
+
11
+ ## `already-implemented` → `verify-and-close`
12
+
13
+ A ready item may already be implemented, because agents ship without transitioning. Before implementing, probe for the item's **own** key:
14
+
15
+ ```bash
16
+ git log --all --grep "<key>" --format='%H %aI %s' -n 10
17
+ gh pr list --repo <org>/<repo> --state all --search "<key>" --json number,state,mergedAt,url
18
+ ```
19
+
20
+ On a hit, do not build it twice — switch `3c` to **verify-and-close**: verify what shipped against this item's acceptance criteria, post evidence naming the shipping PR/commit, then run the ordinary `3d` transition and rollup. If the shipped change only partially satisfies the criteria, implement the remaining gap instead of closing.
21
+
22
+ Distinct from `claim-archaeology` (finds a **different** ancestor issue) and from `DUPLICATE_ALREADY_FIXED` (a **different** canonical issue). Unreadable history degrades to "no hit"; the guard never blocks the claim.
23
+
24
+ ## `two-failed-attempts` → blocked
25
+
26
+ Every non-success terminal outcome records a durable marker on the item — a visible line plus `<!-- [lisa-build-attempt] n=<N> outcome=<outcome> -->` (match on the marker, never the title). A cron holds no memory between cycles, so the item carries the count.
27
+
28
+ With **two or more** markers at claim time: do not claim. Move the item to the configured `blocked` role (resolved per `config-resolution`, never hardcoded), post an operator-readable comment naming both attempts and what a human must decide or supply, and **stop the loop** for this cycle. Recovery is deliberate — a human or a `lisa-repair-intake` cycle with the blocker provably cleared returns it to the queue.
29
+
30
+ Full contract (probe bounds, verify-and-close steps, partial-hit handling, marker mechanics): [reference/claim-time-guards.md](../reference/claim-time-guards.md).
@@ -4,7 +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
- Resolution order is MCP when available and authenticated, then documented
8
- token/REST substrate when the env var is set, then a loud error naming the env
9
- var. Full matrix and migration rules:
7
+ Resolution order is the configured-provider token/CLI substrate first when its
8
+ bootstrap credential is present and identity-matched, then the interactive MCP as
9
+ fallback, then a loud error naming the exact credential to set. Identity-match is
10
+ mandatory on every substrate — one authenticated as a different tenant is skipped,
11
+ never used. The ordering itself is settled in
12
+ [reference/credential-substrate-precedence.md](../reference/credential-substrate-precedence.md);
13
+ full matrix and migration rules:
10
14
  [reference/integration-access-layer.md](../reference/integration-access-layer.md).
@@ -0,0 +1,22 @@
1
+ # Ready-Role Filing (load-bearing)
2
+
3
+ Filing a work item without the ready role is an **incomplete handoff** — build-intake scans the ready lane and nothing else, so the item is never picked up. A correct write plus a missing role still loses the work.
4
+
5
+ ## Omitted means NOT ready — on every tracker
6
+
7
+ **An omitted `build_ready` is NOT build-ready on JIRA, GitHub, and Linear alike.** Ready is an explicit claim, never an accident of which tracker a project configured. This is a **breaking change** for GitHub and Linear callers, which previously treated omission as ready; `lisa-github-validate-issue` F4's compensating omitted → `true` normalization is removed with it.
8
+
9
+ ## Every filing declares one of two things
10
+
11
+ - **`build_ready: true`** — complete enough to build; enters the ready lane for auto-pickup. Required for any complete defect found during other work, so it is claimable next cycle with no human flipping status.
12
+ - **`human_gate: "<why a human must judge this first>"`** — deliberately held outside the queue. The writer stamps a visible line plus `<!-- [lisa-human-gate] reason=<short-slug> -->` so the hold is auditable.
13
+
14
+ Filed, not ready, and no `human_gate` is the **incomplete handoff** case — writers reject it and name both ways to resolve it. `build_ready: false` with no reason is the same omission with a value attached. `build_ready` stays subordinate to `leaf-only-lifecycle`: a container is never build-ready and needs no gate.
15
+
16
+ ## The named exception
17
+
18
+ `lisa-exploratory-qa` files findings not-ready **by design** — its findings are candidate defects whose product significance a human should judge. It is the named human-gate exception, not drift: it pairs `ready=false` with an explicit `human_gate` reason. The sibling `e2e-coverage-gaps` skills are the contrast (a missing test is not a product question, so they file build-ready).
19
+
20
+ `lisa-repair-intake` sweeps for open items that are neither in the ready role nor marked `[lisa-human-gate]`, and surfaces them rather than promoting them.
21
+
22
+ Full contract (the per-vendor before/after table, marker format, and recovery sweep): [reference/ready-role-filing.md](../reference/ready-role-filing.md).
@@ -159,7 +159,14 @@ fleet verdict.
159
159
 
160
160
  A loop that cannot proceed escalates by filing a tracker item (through `lisa-tracker-write`, per
161
161
  `tracked-work` and `integration-access-layer`) labeled **`status:blocked`** and **`human-needed`**,
162
- containing exactly these fields:
162
+ containing exactly these fields.
163
+
164
+ Every escalation is a **declared human gate** under `ready-role-filing`: it passes
165
+ `human_gate: "<the smallest unresolved choice>"` so the writer stamps the auditable
166
+ `[lisa-human-gate]` marker. An escalation is precisely a filing whose readiness a human owns, so
167
+ omitting the flag and relying on a tracker default would make a deliberate gate indistinguishable
168
+ from the accidental non-ready filing that rule exists to catch.
169
+
163
170
 
164
171
  | Field | Content |
165
172
  |---|---|
@@ -68,16 +68,43 @@ platforms it requires and that each named platform has a configured runner.
68
68
  "level": "behavioral"
69
69
  }
70
70
  ],
71
+ "testDiscovery": {
72
+ "<runner>": {
73
+ "roots": ["<repo-relative directory>", "..."],
74
+ "extensions": [".<suffix>", "..."],
75
+ "ignore": ["<optional repo-relative path prefix>"],
76
+ "evidence": { "kind": "call-title", "functions": ["test", "it"] }
77
+ }
78
+ },
71
79
  "exclusions": [
72
- { "file": "<path>", "reason": "why this test aligns to no product behavior" }
80
+ {
81
+ "file": "<path>",
82
+ "evidence": "<optional exact title; omit to excuse the whole file>",
83
+ "reason": "why this test aligns to no product behavior"
84
+ }
73
85
  ]
74
86
  }
75
87
  ```
76
88
 
77
89
  `evidence` is what makes a mapping falsifiable: the gate reads the mapped file and confirms the
78
90
  string is still there, so renaming or deleting a test breaks the map loudly instead of leaving a
79
- scenario silently unguarded. `exclusions` records tests that deliberately map to nothing — starter
80
- templates, source-level corroboration — so "unmapped test" stays a meaningful signal.
91
+ scenario silently unguarded.
92
+
93
+ `testDiscovery` closes the other direction. Validating only what the map DECLARES can never see a
94
+ test file nobody declared, so the gate walks the project's own roots and requires **every test it
95
+ finds to be named by a mapping or excused by an exclusion**. Roots and the evidence grammar are
96
+ per-runner configuration — list every directory, including subflow and helper directories, because
97
+ a directory omitted here is structurally invisible to the gate. Evidence grammars are an allowlist
98
+ of two (`call-title` reads `test("…")`-style declarations; `line-field` reads a leading `name:`
99
+ field), never a project-supplied regular expression, and a template-literal title is used verbatim
100
+ from the source rather than rewritten. A missing block is a defect in enforced mode
101
+ (`discovery-missing`); a malformed one is refused in **every** state (`discovery-invalid`), because
102
+ discovery that silently finds nothing looks exactly like a clean repo.
103
+
104
+ `exclusions` records tests that deliberately map to nothing — starter templates, source-level
105
+ corroboration — so "unmapped test" stays a meaningful signal. Each entry states a `reason`, and an
106
+ exclusion whose file is gone, whose title was renamed, or that no discovery root covers is
107
+ `exclusion-stale`: a standing claim about nothing, never a permanent excuse.
81
108
 
82
109
  ## The gate
83
110
 
@@ -94,8 +121,14 @@ Two commands, wired into the project's script surface and into CI:
94
121
  - an invalid waiver (nonexistent scenario, undeclared platform, already-excluded scenario, a
95
122
  `runner` that does not cover the waived platform under `runnerPlatforms`, or one that masks an
96
123
  existing mapping);
124
+ - a discovered test named by no mapping and no exclusion, or an exclusion that no longer excuses
125
+ anything;
97
126
  - a regression against the project's committed `coverageFloor` per platform.
98
127
 
128
+ Regeneration is never blocked by the check: `--write` rewrites the report and burndown whenever a
129
+ report can be built at all, so a stale evidence string can never hold hostage the paperwork that
130
+ documents it.
131
+
99
132
  The percentage measures **aligned automation inventory, not the latest run result**. A mapped test
100
133
  that currently fails is a red CI check, a separate signal; the map only asserts the automation
101
134
  exists and still says what it claimed. Both facts are required — a green gate over a red suite is
@@ -157,9 +190,12 @@ A repo with no contract yet, taking its first frontend work item:
157
190
 
158
191
  1. **Detect runners.** Find the e2e harnesses the project actually has, per the Tool Discovery
159
192
  Process in `verification-lifecycle`. Record which platforms each covers.
160
- 2. **Scaffold the minimum** — `bdd/features/`, `bdd/coverage-map.json` (with `runnerPlatforms` from
161
- step 1 and a coverage floor of the current, honest number), the regenerate + check scripts wired
162
- into the project's script surface, and the CI invocation of the check.
193
+ 2. **Scaffold the minimum** — `bdd/features/`, `bdd/coverage-map.json` (with `runnerPlatforms` and
194
+ `testDiscovery` from step 1 every root each runner's tests actually live in, subflow and helper
195
+ directories included and a coverage floor of the current, honest number), the regenerate +
196
+ check scripts wired into the project's script surface, and the CI invocation of the check.
197
+ Pre-existing tests that align to no product behavior are recorded as `exclusions` with reasons
198
+ during this step, never left undisclosed.
163
199
  3. **Write only this item's scenarios.** The first item is not a backfill project. Pre-existing
164
200
  uncovered behavior becomes burndown in `docs/e2e-bdd-coverage.md`, and the floor starts where the
165
201
  repo actually is.
@@ -0,0 +1,69 @@
1
+ # Claim-Time Guards
2
+
3
+ Two guards that run when build-intake claims a ready item. Both come from geminisportsai's hand-rolled `sprint-loop` and both address failures actually observed there — an item built twice because it had already shipped, and a loop burning cycles re-attempting an item that was never going to succeed.
4
+
5
+ It is a **single vendor-neutral contract** consumed by all three build-intake skills (`lisa-github-build-intake`, `lisa-jira-build-intake`, `lisa-linear-build-intake`). Each arm cites this slug in its claim step rather than growing its own copy, exactly as the arms cite `leaf-only-lifecycle`, `repo-scope-split`, `rejection-detection`, and `claim-archaeology`. One slug is what keeps a guard that fires on GitHub from being absent on Linear.
6
+
7
+ ## Sequencing
8
+
9
+ The shared claim phase is `3a.0` repo-scope gate → `3a` leaf-only claim gate → `3b` Claim → `3c` run lifecycle → `3d` transition to done. Inside `3b`, the pre-transition window now runs four passes in a fixed order:
10
+
11
+ 1. **`rejection-detection`** — needs the current-lane signal the relabel destroys.
12
+ 2. **`claim-archaeology`** — consumes the rejection classification.
13
+ 3. **`two-failed-attempts` valve** (this rule) — may end the cycle before any claim happens.
14
+ 4. **`already-implemented` check** (this rule) — decides whether `3c` implements or verifies.
15
+
16
+ The valve runs before the already-implemented probe because it is cheaper and it is the only one of the four that can stop the claim outright: there is no point spending git and PR queries on an item that is about to be blocked.
17
+
18
+ ## Guard 1 — already-implemented → verify-and-close
19
+
20
+ **Why it exists.** A ready item may already be implemented. Agents ship without transitioning: the PR merges, the work is done, and the item sits in the ready lane looking untouched. Claiming it normally means building the same change a second time — at best a no-op PR, at worst a conflicting reimplementation of work that already landed.
21
+
22
+ **The probe.** Two deterministic searches for the item's **own** canonical key (the ref carried by the `Work-Item:` trailer), bounded and never interactive:
23
+
24
+ ```bash
25
+ # Commits anywhere in history — branches and merged work included — that carry the key.
26
+ git log --all --grep "<key>" --format='%H %aI %s' -n 10
27
+
28
+ # Open and merged PRs referencing the key (GitHub shown; JIRA and Linear use the
29
+ # equivalent search through their access layers, never a direct vendor API call).
30
+ gh pr list --repo <org>/<repo> --state all --search "<key>" --json number,state,mergedAt,url
31
+ ```
32
+
33
+ A hit counts only when it names **this** key. Branch-name coincidence, a similar title, or a reference from an unrelated item is not a hit — that is `claim-archaeology`'s job, not this one.
34
+
35
+ **The outcome.** On a hit, do not implement. Switch `3c` to **verify-and-close**:
36
+
37
+ 1. Read the referenced commits/PR and establish what actually shipped.
38
+ 2. Verify the shipped change against this item's acceptance criteria — the ordinary verification path, not a fresh build.
39
+ 3. On a pass: post evidence naming the shipping PR/commit, then run the normal `3d` transition (which still gates on the PR being merged) and the `3d.1` rollup.
40
+ 4. On a fail — the shipped change does not satisfy the criteria — record that the item is only **partially** implemented, and proceed with the ordinary implement path for the remaining gap. A partial hit must never close an item whose criteria are unmet.
41
+
42
+ **What this is not.** Three nearby behaviors it must not be conflated with:
43
+
44
+ - **`claim-archaeology`** answers "is this item round 2 of a *different* past failure?" — it looks for an **ancestor** issue. This guard looks for **this same item** already having shipped. Different question, different key, different outcome.
45
+ - **`DUPLICATE_ALREADY_FIXED`** (from `lisa-ticket-triage`) is about a **different canonical issue** whose fix covers this one; it closes as a duplicate. This guard finds work done **under this item's own key** and closes it as completed, not as a duplicate.
46
+ - **Rejection reclaim** is about work that shipped and was pushed back. Verify-and-close applies to work that shipped and nobody noticed.
47
+
48
+ **Never block.** An unreadable history, an absent `gh`, or a failed search degrades to "no hit" and the ordinary implement path proceeds. A speculative probe must never strand a ready item.
49
+
50
+ ## Guard 2 — two-failed-attempts → blocked
51
+
52
+ **Why it exists.** Without a valve, a scheduled loop re-claims the same failing item every cycle forever. Each attempt costs a full build flow, and the third attempt is not more likely to succeed than the second — what changed between them was nothing.
53
+
54
+ **The counter.** Attempts are counted from durable markers on the item itself, not from session memory (a cron process holds no state between cycles). On every **non-success terminal outcome** for a claimed item — errored, blocked by a gate, PR abandoned unmerged — the intake arm records a visible comment plus a marker:
55
+
56
+ ```text
57
+ Build attempt <N> did not complete: <one-line operator-readable reason>.
58
+ <!-- [lisa-build-attempt] n=<N> outcome=<outcome> -->
59
+ ```
60
+
61
+ The marker line is verbatim; the count is the number of `[lisa-build-attempt]` markers on the item. Match on the **marker, never the title**. A successful build records no marker, so an item that shipped after one bad attempt starts clean if it is ever re-filed.
62
+
63
+ **The threshold is two.** At the top of the claim, count existing markers. With **two or more**, do not claim:
64
+
65
+ 1. Move the item to the configured `blocked` role (`build.blocked` / `workflow.blocked`, resolved per `config-resolution` — never a hardcoded lane).
66
+ 2. Post an operator-readable comment naming both prior attempts, what each one hit, and what a human would need to decide or supply. Written for a non-technical operator, per `report-actionability`.
67
+ 3. **Stop the loop** — end the cycle without claiming anything else. Stopping is the point: the next scheduled invocation should not immediately pick up the next item as though nothing happened.
68
+
69
+ **Recovery is deliberate.** A blocked item returns to the queue only when a human (or `lisa-repair-intake`, once the named blocker is provably cleared) moves it back. The attempt markers stay on the item as history; re-entering the ready lane after a real fix is a fresh claim whose markers describe why it was hard, not a silent reset of the counter.
@@ -0,0 +1,166 @@
1
+ # Credential-Substrate Precedence
2
+
3
+ **When more than one substrate can reach an external system, the configured credentials
4
+ provider's token/CLI path goes first and the interactive MCP is the fallback — and
5
+ identity-match verification is mandatory on every substrate, at every tier.**
6
+
7
+ This is **one shared, vendor-neutral contract cited by every `*-access` skill** (the
8
+ `leaf-only-lifecycle` / `repo-scope-split` precedent: one shared slug, never divergent
9
+ per-skill prose). An access skill states its per-vendor mechanics — which token, which
10
+ CLI, which identity anchor — and cites this rule for the ordering. It never restates,
11
+ narrows, or locally overrides the ordering.
12
+
13
+ Settled by the decision record `2026-08-12-credential-substrate-precedence` (D6). It is
14
+ a **settled decision** in the `settled-decisions` sense: re-arguing MCP-first inside a
15
+ skill is out of scope for that skill's work.
16
+
17
+ ## The ladder
18
+
19
+ ### Tier 1 — configured-provider substrate
20
+
21
+ The token or CLI path fed by `lisa-secrets-access`. Chosen **whenever its bootstrap
22
+ credential is available AND the resolved substrate identity-matches the configured
23
+ tenant/workspace/site.**
24
+
25
+ `lisa-secrets-access` is the single chokepoint that makes this tier actionable rather
26
+ than aspirational: it owns the one-store rule and the surface ladder, and its `tool:`
27
+ note line already declares which CLI a given credential is expected to drive. An access
28
+ skill resolves its credential through that chokepoint — never by reading an OS keychain
29
+ a second time.
30
+
31
+ Both halves of the gate are load-bearing. A present credential that identity-matches
32
+ nothing is **not** tier 1; it is a failed tier, and the ladder moves on.
33
+
34
+ ### Tier 2 — interactive MCP
35
+
36
+ Used when the tier 1 path is **genuinely unavailable**. The three genuine cases:
37
+
38
+ - **No bootstrap** — the provider credential is absent or the project has not adopted a
39
+ credentials provider at all.
40
+ - **No adapter for the operation** — the token/CLI substrate has no documented adapter
41
+ for the requested operation, and the MCP does (per-operation, not per-session: a skill
42
+ may resolve tier 1 for one operation and tier 2 for the next).
43
+ - **Provider outage** — the provider path is present but failing for reasons the caller
44
+ cannot fix in-session.
45
+
46
+ "The MCP happens to be authenticated" is not one of them. Neither is "tier 1 is slower."
47
+
48
+ ### Tier 3 — loud, actionable failure
49
+
50
+ When no substrate is both available and identity-matched, fail with a message naming the
51
+ exact credential to set and the exact remediation path. Never silently no-op, never
52
+ blind-retry a failed or absent substrate, and never fall through to a substrate that
53
+ failed identity-match.
54
+
55
+ ## Identity-match is mandatory on every substrate
56
+
57
+ Verification runs **in both directions** before any operation: the substrate must claim
58
+ the configured tenant, and the configured tenant must be one the substrate can actually
59
+ reach. A substrate authenticated as a **different** account is **skipped, never used**,
60
+ regardless of tier — including tier 1. A credential is not an identity claim; the
61
+ identity claim is what the provider says when asked.
62
+
63
+ | Vendor | Identity anchor | Probe |
64
+ |---|---|---|
65
+ | Atlassian | `atlassian.cloudId` / `atlassian.site` | `/rest/api/3/myself` email, acli `auth status` site, MCP accessible-resources contains the cloudId |
66
+ | Notion | `notion.workspaceId` (+ `prdDatabaseId` reachability) | `GET /v1/users/me` → `bot.workspace_name`/`workspace_id` |
67
+ | Linear | `linear.workspace` / `linear.teamKey` | `viewer`/`organization` on GraphQL; team list through the MCP |
68
+ | Sentry / PostHog / Jam / Sonar | configured org + project | the substrate's own whoami/org listing |
69
+
70
+ Skipping the check because "the user obviously meant this workspace" is forbidden. Silent
71
+ cross-tenant operations are precisely the hazard this contract exists to prevent.
72
+
73
+ ## Why provider-first (and why it overturns a working default)
74
+
75
+ MCP-first was defensible and is being overturned deliberately, not corrected as an
76
+ oversight. Three reasons outweigh it.
77
+
78
+ **Headless parity.** Cron runs, cloud sessions, CI, and subagent sessions have no
79
+ browser. Under MCP-first an interactive session and a headless session resolve through
80
+ *different* substrates and can therefore fail differently — and the failure surfaces only
81
+ in the environment nobody is watching. Provider-first makes the primary path the same one
82
+ everywhere, with MCP as the enhancement rather than the default.
83
+
84
+ **Tenant safety — the generalized Atlassian write rule.** Substrates differ in *where
85
+ their target comes from*:
86
+
87
+ - **Per-invocation-bound.** The target is part of the call. A cloudId-scoped REST URL
88
+ (`https://api.atlassian.com/ex/jira/<CLOUDID>/…`) or a workspace-scoped API token
89
+ carries its tenant in the request itself, so nothing outside the call can redirect it.
90
+ - **Ambient-bound.** The target comes from machine-global or session-global state a skill
91
+ does not own: acli's single active account, an MCP's browser OAuth session bound to
92
+ whatever account the human last used. Any other process — or the human — can change it
93
+ between the check and the call. That is a **TOCTOU** window, and a successful
94
+ pre-flight `auth status` does not close it.
95
+
96
+ Prefer the per-invocation-bound substrate. This is exactly why Atlassian JIRA *writes*
97
+ were already forced onto the cloudId-scoped curl adapter; the hazard is not specific to
98
+ Atlassian and not specific to writes. A misrouted write is loud and often reversible; a
99
+ **read through the wrong tenant silently returns wrong data**, which then propagates into
100
+ tickets, PRDs, and verification claims — harder to detect and harder to unwind. Reads get
101
+ the same ordering as writes.
102
+
103
+ **Determinism.** A token path either has its bootstrap or does not, and says so. An MCP's
104
+ readiness depends on session state a skill cannot inspect reliably — the same server
105
+ registers under different prefixes depending on install path, and its data tools register
106
+ only after OAuth completes.
107
+
108
+ ## MCP stays a first-class fallback
109
+
110
+ This is a **re-ordering, not a removal.** The strongest argument for MCP-first — that an
111
+ already-authenticated MCP is zero-setup and identity-verified — is preserved by keeping
112
+ MCP as a genuine, fully supported tier rather than deleting it:
113
+
114
+ - Every access skill keeps its MCP adapters in the dispatch table.
115
+ - An operation with no tier 1 adapter routes to MCP **as the normal path**, not as an
116
+ error.
117
+ - A project with no credentials provider is fully functional on MCP alone.
118
+ - MCP failure messages stay actionable (how to enable and authenticate the plugin).
119
+
120
+ Removing an MCP adapter is a separate decision requiring its own justification. Do not
121
+ treat this contract as license to delete one.
122
+
123
+ ## Guarded fallback for ambient-bound substrates
124
+
125
+ When the ladder does fall back to an ambient-bound substrate for a **mutating**
126
+ operation, the fallback is guarded — never the normal path:
127
+
128
+ 1. Switch to the configured profile and assert the active identity matches config
129
+ immediately before the write.
130
+ 2. Execute the write.
131
+ 3. Re-read the affected object(s) immediately afterward.
132
+ 4. Perform a **post-write tenant assertion** on the response — the tenant is proven from
133
+ the response (self URL host, cloudId in the path, or response metadata), not assumed
134
+ from the pre-flight check.
135
+ 5. On mismatch: stop, report a cross-tenant hazard, and best-effort **roll back** the
136
+ write when a safe reversal exists (delete the created object, remove the created
137
+ comment/link, revert a reversible field edit). Never continue as if it succeeded.
138
+
139
+ A successful pre-flight switch is not sufficient for tenant safety — another process can
140
+ mutate global state between the check and the write.
141
+
142
+ ## Consequences to expect
143
+
144
+ - **A stale or wrong token now fails identity-match instead of silently succeeding
145
+ through an authenticated MCP.** That is intended: it is the exact class of bug this
146
+ contract exists to surface. Fix the credential (`/lisa:setup:<vendor>`); do not
147
+ re-order the ladder to route around it.
148
+ - Headless and interactive sessions take the same primary path, so a credential problem
149
+ reproduces on a laptop instead of only at 3am in cron.
150
+ - The ordering is **not configurable per project**. A knob would let a project
151
+ reintroduce the headless divergence this contract removes. Revisit only with a concrete
152
+ need and a new decision record.
153
+
154
+ ## Adding or editing an access skill
155
+
156
+ 1. Cite this rule by name; do not restate the ordering.
157
+ 2. Document the tier 1 credential and the `lisa-secrets-access` resolution path.
158
+ 3. Document the identity anchor and its probe, and state that mismatch means skip.
159
+ 4. Keep MCP adapters and name the operations for which MCP is the only substrate.
160
+ 5. Make the terminal failure name the exact credential and remediation command.
161
+
162
+ Single-substrate access skills are conformant when their one substrate is
163
+ provider-credential-authenticated (`lisa-sonarcloud-access`: the official SonarQube MCP
164
+ authenticates headlessly from `SONARQUBE_CLI_TOKEN`, so it *is* the tier 1 substrate and
165
+ needs no separate REST tier). Reserve a multi-tier ladder for vendors whose MCP is
166
+ browser-OAuth or keychain-bound and therefore dead headless.
@@ -4,24 +4,35 @@ Every Lisa skill or rule that consumes an external integration MUST route throug
4
4
  the integration's `*-access` skill instead of calling that vendor's MCP tools or
5
5
  REST API directly.
6
6
 
7
- The access skill owns substrate resolution:
7
+ The access skill owns substrate resolution. **The ordering is not this rule's to
8
+ define** — it is the single shared contract in `credential-substrate-precedence`,
9
+ cited identically by every `*-access` skill:
8
10
 
9
- 1. MCP, when the tool is available and already authenticated to the configured
10
- workspace/account.
11
- 2. Token/REST substrate, only when the documented env var is present.
12
- 3. Loud failure naming the exact env var to set.
11
+ 1. **Configured-provider token/CLI substrate** the path fed by
12
+ `lisa-secrets-access` — when its bootstrap credential is present AND the
13
+ resolved substrate identity-matches the configured tenant/workspace/account.
14
+ 2. **Interactive MCP**, as a first-class fallback, when the provider path is
15
+ genuinely unavailable (no bootstrap, no adapter for the operation, provider
16
+ outage).
17
+ 3. Loud failure naming the exact credential to set.
13
18
 
14
- Do not blind-retry a failed or absent MCP. Fall back only after checking the
15
- documented env var for that vendor, and never silently no-op when neither tier is
16
- available.
19
+ Identity-match verification is mandatory on **every** substrate, in both
20
+ directions; one authenticated as a different tenant is skipped, never used. See the
21
+ `credential-substrate-precedence` rule for the rationale (headless parity, tenant
22
+ safety, determinism), the guarded-fallback protocol, and what "genuinely
23
+ unavailable" means.
24
+
25
+ Do not blind-retry a failed or absent substrate, and never silently no-op when no
26
+ tier is available.
17
27
 
18
28
  Some MCPs authenticate headlessly from an env token and need no separate REST
19
- tier — the MCP **is** the headless substrate on both developer machines and cloud
20
- routines. The official SonarQube MCP is one such case (`SONARQUBE_CLI_TOKEN`
29
+ tier — such an MCP **is** the configured-provider substrate on both developer
30
+ machines and cloud routines, so a single-substrate access skill is conformant. The
31
+ official SonarQube MCP is one such case (`SONARQUBE_CLI_TOKEN`
21
32
  [+ `SONARQUBE_CLI_ORG`/`SONARQUBE_CLI_SERVER`]): `lisa-sonarcloud-access` resolves it as a
22
- single substrate with no hand-rolled REST fallback. Reserve the two-tier
23
- MCP-then-REST shape for vendors whose MCP is browser-OAuth or keychain-bound and
24
- therefore dead headless.
33
+ single substrate with no hand-rolled REST fallback. Reserve the multi-tier ladder
34
+ for vendors whose MCP is browser-OAuth or keychain-bound and therefore dead
35
+ headless.
25
36
 
26
37
  ## Access Skills
27
38
 
@@ -60,7 +71,8 @@ When editing any skill listed in the matrix:
60
71
  delegate to the matching access skill.
61
72
  - Keep operation names coarse and vendor-native. Add new operation rows to the
62
73
  access skill instead of embedding REST details in the consumer.
63
- - Preserve existing MCP behavior as the first tier where Claude/Codex can expose
64
- the MCP, but make headless token fallback explicit and gated by the env var.
74
+ - Put the documented token/CLI substrate first and keep the MCP as an explicit,
75
+ fully supported fallback tier `credential-substrate-precedence`. Preserving
76
+ the MCP adapters is required; re-ordering them is not the same as removing them.
65
77
  - If a vendor has no documented token substrate, keep the MCP-only behavior and
66
78
  fail with a clear "no documented headless substrate" message.