@codyswann/lisa 4.74.9 → 4.75.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 (799) hide show
  1. package/.claude-plugin/marketplace.json +60 -0
  2. package/dist/core/lisa-skill-sources.d.ts +3 -3
  3. package/dist/core/lisa-skill-sources.d.ts.map +1 -1
  4. package/dist/core/lisa-skill-sources.js +3 -2
  5. package/dist/core/lisa-skill-sources.js.map +1 -1
  6. package/dist/core/nightly-e2e-guard-behavior-certificate.js +2 -2
  7. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  8. package/dist/core/upstream-evidence-manifest.js +730 -5
  9. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  10. package/package.json +4 -4
  11. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  12. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  13. package/plugins/lisa-agy/plugin.json +1 -1
  14. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  15. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  16. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  17. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  18. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  19. package/plugins/lisa-cdk-devin/.claude-plugin/plugin.json +11 -0
  20. package/plugins/lisa-cdk-devin/.devin-plugin/plugin.json +8 -0
  21. package/plugins/lisa-cdk-devin/skills/setup-aws-accounts/SKILL.md +292 -0
  22. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  23. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  24. package/plugins/lisa-devin/.claude-plugin/plugin.json +8 -0
  25. package/plugins/lisa-devin/.devin-plugin/plugin.json +8 -0
  26. package/plugins/lisa-devin/.mcp.json +8 -0
  27. package/plugins/lisa-devin/agents/architecture-specialist.md +32 -0
  28. package/plugins/lisa-devin/agents/bug-fixer.md +43 -0
  29. package/plugins/lisa-devin/agents/builder.md +44 -0
  30. package/plugins/lisa-devin/agents/confluence-prd-intake.md +65 -0
  31. package/plugins/lisa-devin/agents/debug-specialist.md +34 -0
  32. package/plugins/lisa-devin/agents/eval-specialist.md +33 -0
  33. package/plugins/lisa-devin/agents/git-history-analyzer.md +183 -0
  34. package/plugins/lisa-devin/agents/github-agent.md +155 -0
  35. package/plugins/lisa-devin/agents/github-build-intake.md +64 -0
  36. package/plugins/lisa-devin/agents/github-prd-intake.md +66 -0
  37. package/plugins/lisa-devin/agents/jira-agent.md +135 -0
  38. package/plugins/lisa-devin/agents/jira-build-intake.md +64 -0
  39. package/plugins/lisa-devin/agents/learner.md +85 -0
  40. package/plugins/lisa-devin/agents/learning-judge.md +119 -0
  41. package/plugins/lisa-devin/agents/learnings-synthesizer.md +155 -0
  42. package/plugins/lisa-devin/agents/linear-agent.md +138 -0
  43. package/plugins/lisa-devin/agents/linear-build-intake.md +64 -0
  44. package/plugins/lisa-devin/agents/linear-prd-intake.md +66 -0
  45. package/plugins/lisa-devin/agents/notion-prd-intake.md +63 -0
  46. package/plugins/lisa-devin/agents/performance-specialist.md +26 -0
  47. package/plugins/lisa-devin/agents/pr-mining-specialist.md +85 -0
  48. package/plugins/lisa-devin/agents/product-specialist.md +30 -0
  49. package/plugins/lisa-devin/agents/quality-specialist.md +30 -0
  50. package/plugins/lisa-devin/agents/security-specialist.md +43 -0
  51. package/plugins/lisa-devin/agents/skill-evaluator.md +205 -0
  52. package/plugins/lisa-devin/agents/spec-conformance-specialist.md +56 -0
  53. package/plugins/lisa-devin/agents/test-specialist.md +32 -0
  54. package/plugins/lisa-devin/agents/tracker-mining-specialist.md +85 -0
  55. package/plugins/lisa-devin/agents/verification-specialist.md +145 -0
  56. package/plugins/lisa-devin/hooks/auto-update.mjs +824 -0
  57. package/plugins/lisa-devin/hooks/auto-update.sh +31 -0
  58. package/plugins/lisa-devin/hooks/block-blind-automerge.sh +1242 -0
  59. package/plugins/lisa-devin/hooks/block-direct-issue-create.sh +2603 -0
  60. package/plugins/lisa-devin/hooks/block-host-name-leak.mjs +412 -0
  61. package/plugins/lisa-devin/hooks/block-host-name-leak.sh +61 -0
  62. package/plugins/lisa-devin/hooks/block-instruction-file-edits.sh +207 -0
  63. package/plugins/lisa-devin/hooks/block-managed-file-edits.sh +1175 -0
  64. package/plugins/lisa-devin/hooks/block-no-verify.sh +2288 -0
  65. package/plugins/lisa-devin/hooks/block-shell-json-parsing.sh +263 -0
  66. package/plugins/lisa-devin/hooks/cleanup-stale-worktrees.sh +122 -0
  67. package/plugins/lisa-devin/hooks/devin-tool-name-shim.sh +30 -0
  68. package/plugins/lisa-devin/hooks/discharge-work-item-gates.sh +90 -0
  69. package/plugins/lisa-devin/hooks/enforce-verification-gate.sh +506 -0
  70. package/plugins/lisa-devin/hooks/enforcement-vintage-npm.mjs +320 -0
  71. package/plugins/lisa-devin/hooks/enforcement-vintage.mjs +472 -0
  72. package/plugins/lisa-devin/hooks/enforcement-vintage.sh +48 -0
  73. package/plugins/lisa-devin/hooks/failure-signature-index.mjs +717 -0
  74. package/plugins/lisa-devin/hooks/failure-signature-index.sh +26 -0
  75. package/plugins/lisa-devin/hooks/guard-dedupe.bash +374 -0
  76. package/plugins/lisa-devin/hooks/inject-resolved-config.mjs +903 -0
  77. package/plugins/lisa-devin/hooks/inject-resolved-config.sh +107 -0
  78. package/plugins/lisa-devin/hooks/inject-rules.sh +49 -0
  79. package/plugins/lisa-devin/hooks/install-pkgs.sh +84 -0
  80. package/plugins/lisa-devin/hooks/operational-hazards.mjs +736 -0
  81. package/plugins/lisa-devin/hooks/operational-hazards.sh +28 -0
  82. package/plugins/lisa-devin/hooks/parity-safety-net-heredoc.py +1004 -0
  83. package/plugins/lisa-devin/hooks/parity-safety-net.sh +3275 -0
  84. package/plugins/lisa-devin/hooks/secrets-preflight.sh +72 -0
  85. package/plugins/lisa-devin/hooks/setup-jira-cli.sh +205 -0
  86. package/plugins/lisa-devin/hooks/shell-write-nudge.sh +86 -0
  87. package/plugins/lisa-devin/hooks/sonar-secrets.sh +205 -0
  88. package/plugins/lisa-devin/hooks/threshold-ratchet-compare.mjs +518 -0
  89. package/plugins/lisa-devin/hooks/threshold-ratchet-families.mjs +543 -0
  90. package/plugins/lisa-devin/hooks/threshold-ratchet.mjs +568 -0
  91. package/plugins/lisa-devin/hooks/threshold-ratchet.sh +22 -0
  92. package/plugins/lisa-devin/hooks/withdrawn-rulings.mjs +600 -0
  93. package/plugins/lisa-devin/hooks/withdrawn-rulings.sh +24 -0
  94. package/plugins/lisa-devin/hooks/worktree-binding-guard.mjs +1383 -0
  95. package/plugins/lisa-devin/hooks/worktree-binding-guard.sh +79 -0
  96. package/plugins/lisa-devin/hooks.json +247 -0
  97. package/plugins/lisa-devin/rules/eager/00-rule-index.md +82 -0
  98. package/plugins/lisa-devin/rules/eager/base-rules.md +85 -0
  99. package/plugins/lisa-devin/rules/eager/coding-philosophy.md +27 -0
  100. package/plugins/lisa-devin/rules/eager/config-resolution.md +37 -0
  101. package/plugins/lisa-devin/rules/eager/do-it-now.md +11 -0
  102. package/plugins/lisa-devin/rules/eager/empirical-inquiry.md +24 -0
  103. package/plugins/lisa-devin/rules/eager/falsifiable-checks.md +48 -0
  104. package/plugins/lisa-devin/rules/eager/history-audit.md +27 -0
  105. package/plugins/lisa-devin/rules/eager/integration-access-layer.md +19 -0
  106. package/plugins/lisa-devin/rules/eager/intent-routing.md +18 -0
  107. package/plugins/lisa-devin/rules/eager/learnings-ladder.md +18 -0
  108. package/plugins/lisa-devin/rules/eager/local-ci-first.md +15 -0
  109. package/plugins/lisa-devin/rules/eager/measurement-integrity.md +18 -0
  110. package/plugins/lisa-devin/rules/eager/never-name-a-downstream-project.md +9 -0
  111. package/plugins/lisa-devin/rules/eager/not-blocked-just-waiting.md +13 -0
  112. package/plugins/lisa-devin/rules/eager/operational-hazards.md +50 -0
  113. package/plugins/lisa-devin/rules/eager/report-actionability.md +26 -0
  114. package/plugins/lisa-devin/rules/eager/security-audit-handling.md +40 -0
  115. package/plugins/lisa-devin/rules/eager/session-status-updates.md +20 -0
  116. package/plugins/lisa-devin/rules/eager/settled-decisions.md +75 -0
  117. package/plugins/lisa-devin/rules/eager/stale-state-claims.md +26 -0
  118. package/plugins/lisa-devin/rules/eager/tool-access-gate.md +23 -0
  119. package/plugins/lisa-devin/rules/eager/tracked-work.md +9 -0
  120. package/plugins/lisa-devin/rules/eager/upstream-to-lisa.md +14 -0
  121. package/plugins/lisa-devin/rules/eager/verification.md +33 -0
  122. package/plugins/lisa-devin/rules/eager/wiki-knowledge-source.md +13 -0
  123. package/plugins/lisa-devin/rules/eager/withdrawn-rulings.md +102 -0
  124. package/plugins/lisa-devin/rules/reference/automation-runbook-contract.md +355 -0
  125. package/plugins/lisa-devin/rules/reference/base-rules.md +136 -0
  126. package/plugins/lisa-devin/rules/reference/bdd-e2e-coverage.md +301 -0
  127. package/plugins/lisa-devin/rules/reference/blocker-containment.md +165 -0
  128. package/plugins/lisa-devin/rules/reference/claim-archaeology.md +184 -0
  129. package/plugins/lisa-devin/rules/reference/claim-evidence-mapping.md +362 -0
  130. package/plugins/lisa-devin/rules/reference/claim-time-guards.md +135 -0
  131. package/plugins/lisa-devin/rules/reference/coding-philosophy.md +428 -0
  132. package/plugins/lisa-devin/rules/reference/config-resolution.md +1225 -0
  133. package/plugins/lisa-devin/rules/reference/control-reachability.md +166 -0
  134. package/plugins/lisa-devin/rules/reference/convergent-review.md +145 -0
  135. package/plugins/lisa-devin/rules/reference/credential-substrate-precedence.md +249 -0
  136. package/plugins/lisa-devin/rules/reference/dependency-decision-records.md +177 -0
  137. package/plugins/lisa-devin/rules/reference/dependency-internalization-kit.md +244 -0
  138. package/plugins/lisa-devin/rules/reference/dependency-trust-classes.md +291 -0
  139. package/plugins/lisa-devin/rules/reference/deployed-state-readback.md +142 -0
  140. package/plugins/lisa-devin/rules/reference/derived-branch-plan.md +214 -0
  141. package/plugins/lisa-devin/rules/reference/design-source-of-truth.md +260 -0
  142. package/plugins/lisa-devin/rules/reference/design-value-binding.md +311 -0
  143. package/plugins/lisa-devin/rules/reference/do-it-now.md +19 -0
  144. package/plugins/lisa-devin/rules/reference/documentation-source-paths.md +31 -0
  145. package/plugins/lisa-devin/rules/reference/empirical-inquiry.md +28 -0
  146. package/plugins/lisa-devin/rules/reference/factory-model.md +111 -0
  147. package/plugins/lisa-devin/rules/reference/falsifiable-checks.md +275 -0
  148. package/plugins/lisa-devin/rules/reference/history-audit.md +42 -0
  149. package/plugins/lisa-devin/rules/reference/integration-access-layer.md +89 -0
  150. package/plugins/lisa-devin/rules/reference/intent-routing.md +428 -0
  151. package/plugins/lisa-devin/rules/reference/leaf-only-lifecycle.md +227 -0
  152. package/plugins/lisa-devin/rules/reference/learnings-ladder.md +41 -0
  153. package/plugins/lisa-devin/rules/reference/local-ci-first.md +34 -0
  154. package/plugins/lisa-devin/rules/reference/measurement-integrity.md +119 -0
  155. package/plugins/lisa-devin/rules/reference/never-name-a-downstream-project.md +37 -0
  156. package/plugins/lisa-devin/rules/reference/not-blocked-just-waiting.md +41 -0
  157. package/plugins/lisa-devin/rules/reference/observability-audit.md +146 -0
  158. package/plugins/lisa-devin/rules/reference/operational-hazards.md +115 -0
  159. package/plugins/lisa-devin/rules/reference/prd-definition-of-ready.md +118 -0
  160. package/plugins/lisa-devin/rules/reference/prd-lifecycle-rollup.md +192 -0
  161. package/plugins/lisa-devin/rules/reference/pre-flight-autofill.md +250 -0
  162. package/plugins/lisa-devin/rules/reference/project-learnings.md +159 -0
  163. package/plugins/lisa-devin/rules/reference/promotion-contract.md +148 -0
  164. package/plugins/lisa-devin/rules/reference/readiness-rubric.md +242 -0
  165. package/plugins/lisa-devin/rules/reference/ready-role-filing.md +212 -0
  166. package/plugins/lisa-devin/rules/reference/rejection-detection.md +308 -0
  167. package/plugins/lisa-devin/rules/reference/repo-scope-split.md +119 -0
  168. package/plugins/lisa-devin/rules/reference/report-actionability.md +61 -0
  169. package/plugins/lisa-devin/rules/reference/reset-seed-coverage.md +286 -0
  170. package/plugins/lisa-devin/rules/reference/security-audit-handling.md +55 -0
  171. package/plugins/lisa-devin/rules/reference/session-status-updates.md +111 -0
  172. package/plugins/lisa-devin/rules/reference/settled-decisions.md +39 -0
  173. package/plugins/lisa-devin/rules/reference/stale-state-claims.md +88 -0
  174. package/plugins/lisa-devin/rules/reference/tool-access-gate.md +114 -0
  175. package/plugins/lisa-devin/rules/reference/tracked-work.md +49 -0
  176. package/plugins/lisa-devin/rules/reference/upstream-to-lisa.md +26 -0
  177. package/plugins/lisa-devin/rules/reference/usage-accounting.md +261 -0
  178. package/plugins/lisa-devin/rules/reference/verification.md +278 -0
  179. package/plugins/lisa-devin/rules/reference/wiki-knowledge-source.md +37 -0
  180. package/plugins/lisa-devin/rules/reference/withdrawn-rulings.md +148 -0
  181. package/plugins/lisa-devin/rules/reference/work-item-definition-of-ready.md +177 -0
  182. package/plugins/lisa-devin/rules/reference/work-item-trailer-definition.md +129 -0
  183. package/plugins/lisa-devin/scripts/automation-run-record.mjs +678 -0
  184. package/plugins/lisa-devin/scripts/automation-status-claude-adapter.mjs +804 -0
  185. package/plugins/lisa-devin/scripts/automation-status-codex-adapter.mjs +1081 -0
  186. package/plugins/lisa-devin/scripts/automation-status-contract-drift.mjs +392 -0
  187. package/plugins/lisa-devin/scripts/automation-status-expected-fleet.mjs +508 -0
  188. package/plugins/lisa-devin/scripts/automation-status-report.mjs +200 -0
  189. package/plugins/lisa-devin/scripts/automation-status-run-history.mjs +216 -0
  190. package/plugins/lisa-devin/scripts/automation-status-unrecorded-runs.mjs +127 -0
  191. package/plugins/lisa-devin/scripts/blocker-edge-resolution.mjs +150 -0
  192. package/plugins/lisa-devin/scripts/cross-pollinate.mjs +763 -0
  193. package/plugins/lisa-devin/scripts/design-bindings-probe.mjs +713 -0
  194. package/plugins/lisa-devin/scripts/design-intake-gate.mjs +470 -0
  195. package/plugins/lisa-devin/scripts/design-source-gate.mjs +610 -0
  196. package/plugins/lisa-devin/scripts/design-variable-ids.mjs +567 -0
  197. package/plugins/lisa-devin/scripts/doctor-report.mjs +635 -0
  198. package/plugins/lisa-devin/scripts/install-remote-agent-aws.mjs +443 -0
  199. package/plugins/lisa-devin/scripts/intake-blocker-reprobe.mjs +1065 -0
  200. package/plugins/lisa-devin/scripts/intake-prework-denominator.mjs +249 -0
  201. package/plugins/lisa-devin/scripts/lifecycle-label-trust.mjs +593 -0
  202. package/plugins/lisa-devin/scripts/linear-state-write-target.mjs +362 -0
  203. package/plugins/lisa-devin/scripts/plugin-sync-explain.mjs +654 -0
  204. package/plugins/lisa-devin/scripts/pr-arming-sweep.mjs +561 -0
  205. package/plugins/lisa-devin/scripts/project-ideation-idempotency-harness.mjs +338 -0
  206. package/plugins/lisa-devin/scripts/qa-signal-lifecycle.mjs +523 -0
  207. package/plugins/lisa-devin/scripts/queue-contract-resolution.mjs +583 -0
  208. package/plugins/lisa-devin/scripts/queue-health-classification.mjs +157 -0
  209. package/plugins/lisa-devin/scripts/queue-status-build-readers.mjs +561 -0
  210. package/plugins/lisa-devin/scripts/queue-status-prd-readers.mjs +452 -0
  211. package/plugins/lisa-devin/scripts/remote-agent-aws-setup.sh +677 -0
  212. package/plugins/lisa-devin/scripts/repo-scope-vocabulary-audit.mjs +458 -0
  213. package/plugins/lisa-devin/scripts/resolve-lifecycle-role.mjs +347 -0
  214. package/plugins/lisa-devin/scripts/rollup-blocker-classification.mjs +616 -0
  215. package/plugins/lisa-devin/scripts/scoping-label-audit.mjs +474 -0
  216. package/plugins/lisa-devin/skills/lisa-acceptance-criteria/SKILL.md +73 -0
  217. package/plugins/lisa-devin/skills/lisa-agent-design-best-practices/SKILL.md +242 -0
  218. package/plugins/lisa-devin/skills/lisa-agent-ready/SKILL.md +271 -0
  219. package/plugins/lisa-devin/skills/lisa-analyze-claude-remote/SKILL.md +434 -0
  220. package/plugins/lisa-devin/skills/lisa-atlassian-access/SKILL.md +469 -0
  221. package/plugins/lisa-devin/skills/lisa-atlassian-access/scripts/markdown-to-adf.mjs +236 -0
  222. package/plugins/lisa-devin/skills/lisa-attribute-failure/SKILL.md +142 -0
  223. package/plugins/lisa-devin/skills/lisa-automation-status/SKILL.md +149 -0
  224. package/plugins/lisa-devin/skills/lisa-bug-triage/SKILL.md +23 -0
  225. package/plugins/lisa-devin/skills/lisa-capability-drift/SKILL.md +71 -0
  226. package/plugins/lisa-devin/skills/lisa-codebase-research/SKILL.md +87 -0
  227. package/plugins/lisa-devin/skills/lisa-codify-verification/SKILL.md +213 -0
  228. package/plugins/lisa-devin/skills/lisa-confluence-prd-intake/SKILL.md +417 -0
  229. package/plugins/lisa-devin/skills/lisa-confluence-to-tracker/SKILL.md +469 -0
  230. package/plugins/lisa-devin/skills/lisa-confluence-write-prd/SKILL.md +111 -0
  231. package/plugins/lisa-devin/skills/lisa-cross-pollinate/SKILL.md +175 -0
  232. package/plugins/lisa-devin/skills/lisa-debrief/SKILL.md +96 -0
  233. package/plugins/lisa-devin/skills/lisa-debrief-apply/SKILL.md +106 -0
  234. package/plugins/lisa-devin/skills/lisa-delivery-effectiveness/SKILL.md +62 -0
  235. package/plugins/lisa-devin/skills/lisa-design-intake/SKILL.md +198 -0
  236. package/plugins/lisa-devin/skills/lisa-detect-tooling/SKILL.md +110 -0
  237. package/plugins/lisa-devin/skills/lisa-detect-tooling/scripts/commands.mjs +479 -0
  238. package/plugins/lisa-devin/skills/lisa-detect-tooling/scripts/detect-tooling.mjs +658 -0
  239. package/plugins/lisa-devin/skills/lisa-doctor/SKILL.md +743 -0
  240. package/plugins/lisa-devin/skills/lisa-drive-pr-to-merge/SKILL.md +1587 -0
  241. package/plugins/lisa-devin/skills/lisa-epic-triage/SKILL.md +28 -0
  242. package/plugins/lisa-devin/skills/lisa-evaluation-suite/SKILL.md +63 -0
  243. package/plugins/lisa-devin/skills/lisa-exploratory-qa/SKILL.md +185 -0
  244. package/plugins/lisa-devin/skills/lisa-fix-linter-error/SKILL.md +45 -0
  245. package/plugins/lisa-devin/skills/lisa-generate-claude-remote-build-script/SKILL.md +235 -0
  246. package/plugins/lisa-devin/skills/lisa-git-commit/SKILL.md +53 -0
  247. package/plugins/lisa-devin/skills/lisa-git-prune/SKILL.md +35 -0
  248. package/plugins/lisa-devin/skills/lisa-git-submit-pr/SKILL.md +170 -0
  249. package/plugins/lisa-devin/skills/lisa-github-add-journey/SKILL.md +118 -0
  250. package/plugins/lisa-devin/skills/lisa-github-build-intake/SKILL.md +745 -0
  251. package/plugins/lisa-devin/skills/lisa-github-claim/SKILL.md +27 -0
  252. package/plugins/lisa-devin/skills/lisa-github-create/SKILL.md +105 -0
  253. package/plugins/lisa-devin/skills/lisa-github-evidence/SKILL.md +120 -0
  254. package/plugins/lisa-devin/skills/lisa-github-journey/SKILL.md +134 -0
  255. package/plugins/lisa-devin/skills/lisa-github-prd-intake/SKILL.md +424 -0
  256. package/plugins/lisa-devin/skills/lisa-github-project-v2/SKILL.md +227 -0
  257. package/plugins/lisa-devin/skills/lisa-github-read-issue/SKILL.md +305 -0
  258. package/plugins/lisa-devin/skills/lisa-github-sync/SKILL.md +201 -0
  259. package/plugins/lisa-devin/skills/lisa-github-to-tracker/SKILL.md +456 -0
  260. package/plugins/lisa-devin/skills/lisa-github-validate-issue/SKILL.md +598 -0
  261. package/plugins/lisa-devin/skills/lisa-github-verify/SKILL.md +60 -0
  262. package/plugins/lisa-devin/skills/lisa-github-write-issue/SKILL.md +531 -0
  263. package/plugins/lisa-devin/skills/lisa-github-write-prd/SKILL.md +156 -0
  264. package/plugins/lisa-devin/skills/lisa-health/SKILL.md +142 -0
  265. package/plugins/lisa-devin/skills/lisa-health-drift-cron/SKILL.md +80 -0
  266. package/plugins/lisa-devin/skills/lisa-implement/SKILL.md +372 -0
  267. package/plugins/lisa-devin/skills/lisa-improve-code-complexity/SKILL.md +44 -0
  268. package/plugins/lisa-devin/skills/lisa-improve-harness/SKILL.md +487 -0
  269. package/plugins/lisa-devin/skills/lisa-improve-max-lines/SKILL.md +45 -0
  270. package/plugins/lisa-devin/skills/lisa-improve-max-lines-per-function/SKILL.md +46 -0
  271. package/plugins/lisa-devin/skills/lisa-improve-test-coverage/SKILL.md +47 -0
  272. package/plugins/lisa-devin/skills/lisa-improve-tests/SKILL.md +50 -0
  273. package/plugins/lisa-devin/skills/lisa-intake/SKILL.md +208 -0
  274. package/plugins/lisa-devin/skills/lisa-intake-explain/SKILL.md +279 -0
  275. package/plugins/lisa-devin/skills/lisa-jam-access/SKILL.md +128 -0
  276. package/plugins/lisa-devin/skills/lisa-jira-add-journey/SKILL.md +139 -0
  277. package/plugins/lisa-devin/skills/lisa-jira-build-intake/SKILL.md +556 -0
  278. package/plugins/lisa-devin/skills/lisa-jira-claim/SKILL.md +27 -0
  279. package/plugins/lisa-devin/skills/lisa-jira-create/SKILL.md +157 -0
  280. package/plugins/lisa-devin/skills/lisa-jira-evidence/SKILL.md +106 -0
  281. package/plugins/lisa-devin/skills/lisa-jira-evidence/scripts/post-evidence.sh +262 -0
  282. package/plugins/lisa-devin/skills/lisa-jira-journey/SKILL.md +168 -0
  283. package/plugins/lisa-devin/skills/lisa-jira-journey/scripts/generate-templates.py +239 -0
  284. package/plugins/lisa-devin/skills/lisa-jira-journey/scripts/parse-plan.py +570 -0
  285. package/plugins/lisa-devin/skills/lisa-jira-read-ticket/SKILL.md +199 -0
  286. package/plugins/lisa-devin/skills/lisa-jira-read-ticket/scripts/download-attachment.sh +211 -0
  287. package/plugins/lisa-devin/skills/lisa-jira-sync/SKILL.md +117 -0
  288. package/plugins/lisa-devin/skills/lisa-jira-validate-ticket/SKILL.md +525 -0
  289. package/plugins/lisa-devin/skills/lisa-jira-verify/SKILL.md +61 -0
  290. package/plugins/lisa-devin/skills/lisa-jira-write-ticket/SKILL.md +440 -0
  291. package/plugins/lisa-devin/skills/lisa-jsdoc-best-practices/SKILL.md +491 -0
  292. package/plugins/lisa-devin/skills/lisa-kane-browser/SKILL.md +80 -0
  293. package/plugins/lisa-devin/skills/lisa-learnings-audit/SKILL.md +490 -0
  294. package/plugins/lisa-devin/skills/lisa-linear-access/SKILL.md +483 -0
  295. package/plugins/lisa-devin/skills/lisa-linear-add-journey/SKILL.md +109 -0
  296. package/plugins/lisa-devin/skills/lisa-linear-build-intake/SKILL.md +548 -0
  297. package/plugins/lisa-devin/skills/lisa-linear-claim/SKILL.md +28 -0
  298. package/plugins/lisa-devin/skills/lisa-linear-create/SKILL.md +150 -0
  299. package/plugins/lisa-devin/skills/lisa-linear-evidence/SKILL.md +124 -0
  300. package/plugins/lisa-devin/skills/lisa-linear-journey/SKILL.md +147 -0
  301. package/plugins/lisa-devin/skills/lisa-linear-prd-intake/SKILL.md +411 -0
  302. package/plugins/lisa-devin/skills/lisa-linear-read-issue/SKILL.md +201 -0
  303. package/plugins/lisa-devin/skills/lisa-linear-sync/SKILL.md +164 -0
  304. package/plugins/lisa-devin/skills/lisa-linear-to-tracker/SKILL.md +454 -0
  305. package/plugins/lisa-devin/skills/lisa-linear-validate-issue/SKILL.md +504 -0
  306. package/plugins/lisa-devin/skills/lisa-linear-verify/SKILL.md +65 -0
  307. package/plugins/lisa-devin/skills/lisa-linear-write-issue/SKILL.md +448 -0
  308. package/plugins/lisa-devin/skills/lisa-linear-write-prd/SKILL.md +98 -0
  309. package/plugins/lisa-devin/skills/lisa-monitor/SKILL.md +224 -0
  310. package/plugins/lisa-devin/skills/lisa-nightly-add-test-coverage/SKILL.md +40 -0
  311. package/plugins/lisa-devin/skills/lisa-nightly-improve-tests/SKILL.md +29 -0
  312. package/plugins/lisa-devin/skills/lisa-nightly-lower-code-complexity/SKILL.md +42 -0
  313. package/plugins/lisa-devin/skills/lisa-notion-access/SKILL.md +301 -0
  314. package/plugins/lisa-devin/skills/lisa-notion-prd-intake/SKILL.md +360 -0
  315. package/plugins/lisa-devin/skills/lisa-notion-to-tracker/SKILL.md +467 -0
  316. package/plugins/lisa-devin/skills/lisa-notion-write-prd/SKILL.md +111 -0
  317. package/plugins/lisa-devin/skills/lisa-parity-code-review/SKILL.md +83 -0
  318. package/plugins/lisa-devin/skills/lisa-parity-code-simplifier/SKILL.md +76 -0
  319. package/plugins/lisa-devin/skills/lisa-parity-coderabbit/SKILL.md +87 -0
  320. package/plugins/lisa-devin/skills/lisa-parity-sentry-sdk-setup/SKILL.md +375 -0
  321. package/plugins/lisa-devin/skills/lisa-parity-sentry-seer/SKILL.md +168 -0
  322. package/plugins/lisa-devin/skills/lisa-parity-skill-creator/SKILL.md +155 -0
  323. package/plugins/lisa-devin/skills/lisa-performance-review/SKILL.md +94 -0
  324. package/plugins/lisa-devin/skills/lisa-persist-learning/SKILL.md +247 -0
  325. package/plugins/lisa-devin/skills/lisa-plan/SKILL.md +64 -0
  326. package/plugins/lisa-devin/skills/lisa-plugin-sync-explain/SKILL.md +53 -0
  327. package/plugins/lisa-devin/skills/lisa-posthog-access/SKILL.md +140 -0
  328. package/plugins/lisa-devin/skills/lisa-prd-backlink/SKILL.md +274 -0
  329. package/plugins/lisa-devin/skills/lisa-prd-source-write/SKILL.md +104 -0
  330. package/plugins/lisa-devin/skills/lisa-prd-ticket-coverage/SKILL.md +187 -0
  331. package/plugins/lisa-devin/skills/lisa-product-walkthrough/SKILL.md +106 -0
  332. package/plugins/lisa-devin/skills/lisa-project-ideation/SKILL.md +417 -0
  333. package/plugins/lisa-devin/skills/lisa-project-ideation/examples/evidence-card-format.md +21 -0
  334. package/plugins/lisa-devin/skills/lisa-project-ideation/examples/host-project-only.md +22 -0
  335. package/plugins/lisa-devin/skills/lisa-project-ideation/examples/idempotency-verification-harness.md +57 -0
  336. package/plugins/lisa-devin/skills/lisa-project-ideation/examples/public-external-inspiration.md +22 -0
  337. package/plugins/lisa-devin/skills/lisa-project-ideation/examples/unavailable-data-rejection.md +22 -0
  338. package/plugins/lisa-devin/skills/lisa-pull-request-review/SKILL.md +132 -0
  339. package/plugins/lisa-devin/skills/lisa-quality-review/SKILL.md +63 -0
  340. package/plugins/lisa-devin/skills/lisa-queue-status/SKILL.md +215 -0
  341. package/plugins/lisa-devin/skills/lisa-remote-dispatch/SKILL.md +109 -0
  342. package/plugins/lisa-devin/skills/lisa-remote-dispatch/scripts/dispatch.mjs +535 -0
  343. package/plugins/lisa-devin/skills/lisa-repair-intake/SKILL.md +1621 -0
  344. package/plugins/lisa-devin/skills/lisa-reproduce-bug/SKILL.md +75 -0
  345. package/plugins/lisa-devin/skills/lisa-research/SKILL.md +92 -0
  346. package/plugins/lisa-devin/skills/lisa-review-implementation/SKILL.md +209 -0
  347. package/plugins/lisa-devin/skills/lisa-review-local/SKILL.md +141 -0
  348. package/plugins/lisa-devin/skills/lisa-rework-triage/SKILL.md +206 -0
  349. package/plugins/lisa-devin/skills/lisa-root-cause-analysis/SKILL.md +135 -0
  350. package/plugins/lisa-devin/skills/lisa-secrets-access/SKILL.md +430 -0
  351. package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/aws-bootstrap.mjs +433 -0
  352. package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/bootstrap-store.mjs +288 -0
  353. package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/doctor-secrets.mjs +273 -0
  354. package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/envfile.mjs +80 -0
  355. package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/inspect-vault.mjs +142 -0
  356. package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +1085 -0
  357. package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/note-format.mjs +179 -0
  358. package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/owner.mjs +96 -0
  359. package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/preflight-secrets.mjs +342 -0
  360. package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/prompt-secret.mjs +79 -0
  361. package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/providers.mjs +805 -0
  362. package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/publish-aws-bootstrap.mjs +680 -0
  363. package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/read-secret-note.mjs +105 -0
  364. package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/resolve-expo-token.mjs +90 -0
  365. package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/resolve-secret.mjs +285 -0
  366. package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/rotate-secret.mjs +297 -0
  367. package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/routing-floor.mjs +153 -0
  368. package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/surfaces.mjs +480 -0
  369. package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/sync-secret-to-ci.mjs +510 -0
  370. package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/tools-from-notes.mjs +63 -0
  371. package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/validate-config.mjs +550 -0
  372. package/plugins/lisa-devin/skills/lisa-security-review/SKILL.md +124 -0
  373. package/plugins/lisa-devin/skills/lisa-security-zap-scan/SKILL.md +53 -0
  374. package/plugins/lisa-devin/skills/lisa-sentry-access/SKILL.md +140 -0
  375. package/plugins/lisa-devin/skills/lisa-setup-atlassian/SKILL.md +407 -0
  376. package/plugins/lisa-devin/skills/lisa-setup-automations/SKILL.md +430 -0
  377. package/plugins/lisa-devin/skills/lisa-setup-automations/scripts/generate-workflow.mjs +288 -0
  378. package/plugins/lisa-devin/skills/lisa-setup-confluence/SKILL.md +254 -0
  379. package/plugins/lisa-devin/skills/lisa-setup-github/SKILL.md +319 -0
  380. package/plugins/lisa-devin/skills/lisa-setup-github-repo/SKILL.md +128 -0
  381. package/plugins/lisa-devin/skills/lisa-setup-jira/SKILL.md +198 -0
  382. package/plugins/lisa-devin/skills/lisa-setup-kane/SKILL.md +96 -0
  383. package/plugins/lisa-devin/skills/lisa-setup-linear/SKILL.md +375 -0
  384. package/plugins/lisa-devin/skills/lisa-setup-local-env/SKILL.md +95 -0
  385. package/plugins/lisa-devin/skills/lisa-setup-local-env/scripts/local-env.mjs +196 -0
  386. package/plugins/lisa-devin/skills/lisa-setup-notion/SKILL.md +376 -0
  387. package/plugins/lisa-devin/skills/lisa-setup-remote-aws/SKILL.md +149 -0
  388. package/plugins/lisa-devin/skills/lisa-setup-remote-env/SKILL.md +382 -0
  389. package/plugins/lisa-devin/skills/lisa-setup-remote-env/assets/materialized-env-authority.mjs +262 -0
  390. package/plugins/lisa-devin/skills/lisa-setup-remote-env/assets/session-start.sh +87 -0
  391. package/plugins/lisa-devin/skills/lisa-setup-remote-env/assets/setup.sh +216 -0
  392. package/plugins/lisa-devin/skills/lisa-setup-remote-env/scripts/environment.mjs +227 -0
  393. package/plugins/lisa-devin/skills/lisa-setup-remote-env/scripts/preflight-tools.mjs +378 -0
  394. package/plugins/lisa-devin/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +1632 -0
  395. package/plugins/lisa-devin/skills/lisa-setup-remote-env/scripts/tool-floor.mjs +94 -0
  396. package/plugins/lisa-devin/skills/lisa-setup-remote-env/scripts/toolchain.mjs +448 -0
  397. package/plugins/lisa-devin/skills/lisa-setup-remote-env/scripts/verify-remote-env.mjs +250 -0
  398. package/plugins/lisa-devin/skills/lisa-setup-sonar/SKILL.md +153 -0
  399. package/plugins/lisa-devin/skills/lisa-setup-workstation/SKILL.md +143 -0
  400. package/plugins/lisa-devin/skills/lisa-setup-workstation/scripts/bounded-child.mjs +168 -0
  401. package/plugins/lisa-devin/skills/lisa-setup-workstation/scripts/catalogue.mjs +293 -0
  402. package/plugins/lisa-devin/skills/lisa-setup-workstation/scripts/cli.mjs +333 -0
  403. package/plugins/lisa-devin/skills/lisa-setup-workstation/scripts/workstation.mjs +511 -0
  404. package/plugins/lisa-devin/skills/lisa-sonarcloud-access/SKILL.md +202 -0
  405. package/plugins/lisa-devin/skills/lisa-spec-conformance/SKILL.md +205 -0
  406. package/plugins/lisa-devin/skills/lisa-starter-sync/SKILL.md +35 -0
  407. package/plugins/lisa-devin/skills/lisa-sync-down/SKILL.md +209 -0
  408. package/plugins/lisa-devin/skills/lisa-task-decomposition/SKILL.md +195 -0
  409. package/plugins/lisa-devin/skills/lisa-task-triage/SKILL.md +23 -0
  410. package/plugins/lisa-devin/skills/lisa-tdd-implementation/SKILL.md +91 -0
  411. package/plugins/lisa-devin/skills/lisa-tear-down-automations/SKILL.md +85 -0
  412. package/plugins/lisa-devin/skills/lisa-test-strategy/SKILL.md +66 -0
  413. package/plugins/lisa-devin/skills/lisa-ticket-triage/SKILL.md +214 -0
  414. package/plugins/lisa-devin/skills/lisa-track/SKILL.md +129 -0
  415. package/plugins/lisa-devin/skills/lisa-tracker-add-journey/SKILL.md +28 -0
  416. package/plugins/lisa-devin/skills/lisa-tracker-build-intake/SKILL.md +134 -0
  417. package/plugins/lisa-devin/skills/lisa-tracker-claim/SKILL.md +35 -0
  418. package/plugins/lisa-devin/skills/lisa-tracker-create/SKILL.md +28 -0
  419. package/plugins/lisa-devin/skills/lisa-tracker-evidence/SKILL.md +63 -0
  420. package/plugins/lisa-devin/skills/lisa-tracker-journey/SKILL.md +27 -0
  421. package/plugins/lisa-devin/skills/lisa-tracker-read/SKILL.md +28 -0
  422. package/plugins/lisa-devin/skills/lisa-tracker-source-artifacts/SKILL.md +111 -0
  423. package/plugins/lisa-devin/skills/lisa-tracker-sync/SKILL.md +150 -0
  424. package/plugins/lisa-devin/skills/lisa-tracker-validate/SKILL.md +37 -0
  425. package/plugins/lisa-devin/skills/lisa-tracker-verify/SKILL.md +29 -0
  426. package/plugins/lisa-devin/skills/lisa-tracker-write/SKILL.md +55 -0
  427. package/plugins/lisa-devin/skills/lisa-usage-accounting/SKILL.md +205 -0
  428. package/plugins/lisa-devin/skills/lisa-usage-accounting/references/effectiveness.md +63 -0
  429. package/plugins/lisa-devin/skills/lisa-use-the-product/SKILL.md +86 -0
  430. package/plugins/lisa-devin/skills/lisa-validate-tracker-mapping/SKILL.md +467 -0
  431. package/plugins/lisa-devin/skills/lisa-verification-lifecycle/SKILL.md +384 -0
  432. package/plugins/lisa-devin/skills/lisa-verify/SKILL.md +55 -0
  433. package/plugins/lisa-devin/skills/lisa-verify-prd/SKILL.md +394 -0
  434. package/plugins/lisa-devin/skills/lisa-verify-workflow-change/SKILL.md +154 -0
  435. package/plugins/lisa-devin/skills/lisa-wiki-install/SKILL.md +101 -0
  436. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  437. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  438. package/plugins/lisa-expo-agy/plugin.json +1 -1
  439. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  440. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  441. package/plugins/lisa-expo-devin/.claude-plugin/plugin.json +11 -0
  442. package/plugins/lisa-expo-devin/.devin-plugin/plugin.json +8 -0
  443. package/plugins/lisa-expo-devin/.mcp.json +8 -0
  444. package/plugins/lisa-expo-devin/THIRD-PARTY-NOTICES.md +84 -0
  445. package/plugins/lisa-expo-devin/agents/ops-specialist.md +124 -0
  446. package/plugins/lisa-expo-devin/hooks/devin-tool-name-shim.sh +30 -0
  447. package/plugins/lisa-expo-devin/hooks/register-maestro-mcp.sh +84 -0
  448. package/plugins/lisa-expo-devin/hooks.json +14 -0
  449. package/plugins/lisa-expo-devin/skills/add-app-clip/SKILL.md +280 -0
  450. package/plugins/lisa-expo-devin/skills/add-app-clip/references/native-module.md +96 -0
  451. package/plugins/lisa-expo-devin/skills/apollo-client/SKILL.md +238 -0
  452. package/plugins/lisa-expo-devin/skills/apollo-client/references/mutation-patterns.md +360 -0
  453. package/plugins/lisa-expo-devin/skills/atomic-design-gluestack/SKILL.md +369 -0
  454. package/plugins/lisa-expo-devin/skills/atomic-design-gluestack/references/atomic-levels.md +417 -0
  455. package/plugins/lisa-expo-devin/skills/atomic-design-gluestack/references/folder-structure.md +257 -0
  456. package/plugins/lisa-expo-devin/skills/atomic-design-gluestack/references/gluestack-mapping.md +233 -0
  457. package/plugins/lisa-expo-devin/skills/atomic-design-gluestack/scripts/test_validate_atomic_structure.py +240 -0
  458. package/plugins/lisa-expo-devin/skills/atomic-design-gluestack/scripts/validate_atomic_structure.py +438 -0
  459. package/plugins/lisa-expo-devin/skills/building-native-ui/SKILL.md +321 -0
  460. package/plugins/lisa-expo-devin/skills/building-native-ui/references/animations.md +220 -0
  461. package/plugins/lisa-expo-devin/skills/building-native-ui/references/controls.md +272 -0
  462. package/plugins/lisa-expo-devin/skills/building-native-ui/references/form-sheet.md +253 -0
  463. package/plugins/lisa-expo-devin/skills/building-native-ui/references/gradients.md +106 -0
  464. package/plugins/lisa-expo-devin/skills/building-native-ui/references/icons.md +213 -0
  465. package/plugins/lisa-expo-devin/skills/building-native-ui/references/media.md +198 -0
  466. package/plugins/lisa-expo-devin/skills/building-native-ui/references/route-structure.md +229 -0
  467. package/plugins/lisa-expo-devin/skills/building-native-ui/references/search.md +248 -0
  468. package/plugins/lisa-expo-devin/skills/building-native-ui/references/storage.md +121 -0
  469. package/plugins/lisa-expo-devin/skills/building-native-ui/references/tabs.md +433 -0
  470. package/plugins/lisa-expo-devin/skills/building-native-ui/references/toolbar-and-headers.md +284 -0
  471. package/plugins/lisa-expo-devin/skills/building-native-ui/references/visual-effects.md +197 -0
  472. package/plugins/lisa-expo-devin/skills/building-native-ui/references/webgpu-three.md +605 -0
  473. package/plugins/lisa-expo-devin/skills/building-native-ui/references/zoom-transitions.md +158 -0
  474. package/plugins/lisa-expo-devin/skills/container-view-pattern/SKILL.md +355 -0
  475. package/plugins/lisa-expo-devin/skills/container-view-pattern/references/examples.md +749 -0
  476. package/plugins/lisa-expo-devin/skills/container-view-pattern/references/patterns.md +318 -0
  477. package/plugins/lisa-expo-devin/skills/container-view-pattern/scripts/create_component.py +200 -0
  478. package/plugins/lisa-expo-devin/skills/container-view-pattern/scripts/validate_component.py +332 -0
  479. package/plugins/lisa-expo-devin/skills/cross-platform-compatibility/SKILL.md +268 -0
  480. package/plugins/lisa-expo-devin/skills/cross-platform-compatibility/references/common-issues.md +619 -0
  481. package/plugins/lisa-expo-devin/skills/cross-platform-compatibility/references/file-extensions.md +340 -0
  482. package/plugins/lisa-expo-devin/skills/cross-platform-compatibility/references/platform-api.md +276 -0
  483. package/plugins/lisa-expo-devin/skills/cross-platform-compatibility/scripts/validate_cross_platform.py +416 -0
  484. package/plugins/lisa-expo-devin/skills/directory-structure/SKILL.md +214 -0
  485. package/plugins/lisa-expo-devin/skills/directory-structure/scripts/validate_structure.py +454 -0
  486. package/plugins/lisa-expo-devin/skills/e2e-coverage-gaps/SKILL.md +117 -0
  487. package/plugins/lisa-expo-devin/skills/eas-update-insights/SKILL.md +228 -0
  488. package/plugins/lisa-expo-devin/skills/eas-update-insights/references/channel-insights-schema.md +47 -0
  489. package/plugins/lisa-expo-devin/skills/eas-update-insights/references/update-insights-schema.md +69 -0
  490. package/plugins/lisa-expo-devin/skills/expo-api-routes/SKILL.md +369 -0
  491. package/plugins/lisa-expo-devin/skills/expo-brownfield/SKILL.md +54 -0
  492. package/plugins/lisa-expo-devin/skills/expo-brownfield/references/brownfield-integrated.md +526 -0
  493. package/plugins/lisa-expo-devin/skills/expo-brownfield/references/brownfield-isolated.md +402 -0
  494. package/plugins/lisa-expo-devin/skills/expo-brownfield/references/comparison.md +63 -0
  495. package/plugins/lisa-expo-devin/skills/expo-brownfield/references/troubleshooting.md +88 -0
  496. package/plugins/lisa-expo-devin/skills/expo-cicd-workflows/SKILL.md +92 -0
  497. package/plugins/lisa-expo-devin/skills/expo-cicd-workflows/scripts/fetch.js +113 -0
  498. package/plugins/lisa-expo-devin/skills/expo-cicd-workflows/scripts/package.json +11 -0
  499. package/plugins/lisa-expo-devin/skills/expo-cicd-workflows/scripts/validate.js +85 -0
  500. package/plugins/lisa-expo-devin/skills/expo-deployment/SKILL.md +193 -0
  501. package/plugins/lisa-expo-devin/skills/expo-deployment/references/app-store-metadata.md +479 -0
  502. package/plugins/lisa-expo-devin/skills/expo-deployment/references/ios-app-store.md +355 -0
  503. package/plugins/lisa-expo-devin/skills/expo-deployment/references/play-store.md +264 -0
  504. package/plugins/lisa-expo-devin/skills/expo-deployment/references/testflight.md +58 -0
  505. package/plugins/lisa-expo-devin/skills/expo-deployment/references/workflows.md +200 -0
  506. package/plugins/lisa-expo-devin/skills/expo-dev-client/SKILL.md +164 -0
  507. package/plugins/lisa-expo-devin/skills/expo-env-config/SKILL.md +309 -0
  508. package/plugins/lisa-expo-devin/skills/expo-env-config/references/validation-patterns.md +417 -0
  509. package/plugins/lisa-expo-devin/skills/expo-module/SKILL.md +141 -0
  510. package/plugins/lisa-expo-devin/skills/expo-module/references/config-plugin.md +90 -0
  511. package/plugins/lisa-expo-devin/skills/expo-module/references/create-expo-module.md +206 -0
  512. package/plugins/lisa-expo-devin/skills/expo-module/references/lifecycle.md +127 -0
  513. package/plugins/lisa-expo-devin/skills/expo-module/references/module-config.md +48 -0
  514. package/plugins/lisa-expo-devin/skills/expo-module/references/native-module.md +286 -0
  515. package/plugins/lisa-expo-devin/skills/expo-module/references/native-view.md +171 -0
  516. package/plugins/lisa-expo-devin/skills/expo-router-best-practices/SKILL.md +432 -0
  517. package/plugins/lisa-expo-devin/skills/expo-router-best-practices/references/official-docs.md +290 -0
  518. package/plugins/lisa-expo-devin/skills/expo-router-best-practices/references/static-export-verification.md +54 -0
  519. package/plugins/lisa-expo-devin/skills/expo-router-best-practices/scripts/generate-route.py +171 -0
  520. package/plugins/lisa-expo-devin/skills/expo-tailwind-setup/SKILL.md +487 -0
  521. package/plugins/lisa-expo-devin/skills/expo-ui-jetpack-compose/SKILL.md +40 -0
  522. package/plugins/lisa-expo-devin/skills/expo-ui-swift-ui/SKILL.md +39 -0
  523. package/plugins/lisa-expo-devin/skills/gluestack-nativewind/SKILL.md +419 -0
  524. package/plugins/lisa-expo-devin/skills/gluestack-nativewind/references/color-tokens.md +343 -0
  525. package/plugins/lisa-expo-devin/skills/gluestack-nativewind/references/component-mapping.md +307 -0
  526. package/plugins/lisa-expo-devin/skills/gluestack-nativewind/references/spacing-scale.md +300 -0
  527. package/plugins/lisa-expo-devin/skills/gluestack-nativewind/scripts/test_validate_styling.py +240 -0
  528. package/plugins/lisa-expo-devin/skills/gluestack-nativewind/scripts/validate_styling.py +424 -0
  529. package/plugins/lisa-expo-devin/skills/jira-add-journey/SKILL.md +140 -0
  530. package/plugins/lisa-expo-devin/skills/jira-create/SKILL.md +161 -0
  531. package/plugins/lisa-expo-devin/skills/jira-evidence/SKILL.md +84 -0
  532. package/plugins/lisa-expo-devin/skills/jira-evidence/scripts/post-evidence.sh +262 -0
  533. package/plugins/lisa-expo-devin/skills/jira-journey/SKILL.md +196 -0
  534. package/plugins/lisa-expo-devin/skills/jira-journey/scripts/generate-templates.py +281 -0
  535. package/plugins/lisa-expo-devin/skills/jira-journey/scripts/parse-plan.py +400 -0
  536. package/plugins/lisa-expo-devin/skills/jira-verify/SKILL.md +27 -0
  537. package/plugins/lisa-expo-devin/skills/local-state/SKILL.md +362 -0
  538. package/plugins/lisa-expo-devin/skills/local-state/references/async-storage.md +505 -0
  539. package/plugins/lisa-expo-devin/skills/local-state/references/persistence-patterns.md +711 -0
  540. package/plugins/lisa-expo-devin/skills/local-state/references/reactive-variables.md +446 -0
  541. package/plugins/lisa-expo-devin/skills/maestro-mcp-setup/SKILL.md +144 -0
  542. package/plugins/lisa-expo-devin/skills/native-data-fetching/SKILL.md +507 -0
  543. package/plugins/lisa-expo-devin/skills/native-data-fetching/references/expo-router-loaders.md +344 -0
  544. package/plugins/lisa-expo-devin/skills/ops-browser-uat/SKILL.md +124 -0
  545. package/plugins/lisa-expo-devin/skills/ops-check-logs/SKILL.md +217 -0
  546. package/plugins/lisa-expo-devin/skills/ops-db-ops/SKILL.md +214 -0
  547. package/plugins/lisa-expo-devin/skills/ops-deploy/SKILL.md +123 -0
  548. package/plugins/lisa-expo-devin/skills/ops-monitor-errors/SKILL.md +99 -0
  549. package/plugins/lisa-expo-devin/skills/ops-performance/SKILL.md +165 -0
  550. package/plugins/lisa-expo-devin/skills/ops-run-local/SKILL.md +169 -0
  551. package/plugins/lisa-expo-devin/skills/ops-verify-health/SKILL.md +101 -0
  552. package/plugins/lisa-expo-devin/skills/owasp-zap/SKILL.md +61 -0
  553. package/plugins/lisa-expo-devin/skills/play-store-access/SKILL.md +226 -0
  554. package/plugins/lisa-expo-devin/skills/playwright-ci-debugging/SKILL.md +140 -0
  555. package/plugins/lisa-expo-devin/skills/playwright-selectors/SKILL.md +496 -0
  556. package/plugins/lisa-expo-devin/skills/reduce-complexity/SKILL.md +251 -0
  557. package/plugins/lisa-expo-devin/skills/reduce-complexity/references/extraction-strategies.md +456 -0
  558. package/plugins/lisa-expo-devin/skills/reduce-complexity/references/refactoring-patterns.md +557 -0
  559. package/plugins/lisa-expo-devin/skills/testing-library/SKILL.md +314 -0
  560. package/plugins/lisa-expo-devin/skills/testing-library/references/async-patterns.md +420 -0
  561. package/plugins/lisa-expo-devin/skills/testing-library/references/expo-router-testing.md +556 -0
  562. package/plugins/lisa-expo-devin/skills/testing-library/references/mocking-patterns.md +612 -0
  563. package/plugins/lisa-expo-devin/skills/testing-library/references/query-priority.md +291 -0
  564. package/plugins/lisa-expo-devin/skills/upgrading-expo/SKILL.md +134 -0
  565. package/plugins/lisa-expo-devin/skills/upgrading-expo/references/expo-av-to-audio.md +132 -0
  566. package/plugins/lisa-expo-devin/skills/upgrading-expo/references/expo-av-to-video.md +160 -0
  567. package/plugins/lisa-expo-devin/skills/upgrading-expo/references/native-tabs.md +124 -0
  568. package/plugins/lisa-expo-devin/skills/upgrading-expo/references/new-architecture.md +79 -0
  569. package/plugins/lisa-expo-devin/skills/upgrading-expo/references/react-19.md +79 -0
  570. package/plugins/lisa-expo-devin/skills/upgrading-expo/references/react-compiler.md +59 -0
  571. package/plugins/lisa-expo-devin/skills/upgrading-expo/references/react-navigation-to-expo-router.md +61 -0
  572. package/plugins/lisa-expo-devin/skills/use-dom/SKILL.md +417 -0
  573. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  574. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  575. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  576. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  577. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  578. package/plugins/lisa-harper-fabric-devin/.claude-plugin/plugin.json +11 -0
  579. package/plugins/lisa-harper-fabric-devin/.devin-plugin/plugin.json +8 -0
  580. package/plugins/lisa-harper-fabric-devin/generated-artifact-globs.txt +5 -0
  581. package/plugins/lisa-harper-fabric-devin/hooks/block-generated-artifact-edits.sh +141 -0
  582. package/plugins/lisa-harper-fabric-devin/hooks/devin-tool-name-shim.sh +30 -0
  583. package/plugins/lisa-harper-fabric-devin/hooks/enforce-config-extensions.mjs +196 -0
  584. package/plugins/lisa-harper-fabric-devin/hooks/enforce-config-extensions.sh +46 -0
  585. package/plugins/lisa-harper-fabric-devin/hooks/inject-rules.sh +27 -0
  586. package/plugins/lisa-harper-fabric-devin/hooks.json +36 -0
  587. package/plugins/lisa-harper-fabric-devin/rules/eager/harper-fabric.md +31 -0
  588. package/plugins/lisa-harper-fabric-devin/rules/reference/harper-fabric.md +52 -0
  589. package/plugins/lisa-harper-fabric-devin/skills/e2e-coverage-gaps/SKILL.md +117 -0
  590. package/plugins/lisa-harper-fabric-devin/skills/harper-auth/SKILL.md +368 -0
  591. package/plugins/lisa-harper-fabric-devin/skills/harper-build-and-deploy/SKILL.md +198 -0
  592. package/plugins/lisa-harper-fabric-devin/skills/harper-caching/SKILL.md +265 -0
  593. package/plugins/lisa-harper-fabric-devin/skills/harper-component-model/SKILL.md +87 -0
  594. package/plugins/lisa-harper-fabric-devin/skills/harper-config-yaml/SKILL.md +283 -0
  595. package/plugins/lisa-harper-fabric-devin/skills/harper-operations/SKILL.md +239 -0
  596. package/plugins/lisa-harper-fabric-devin/skills/harper-realtime/SKILL.md +187 -0
  597. package/plugins/lisa-harper-fabric-devin/skills/harper-resources/SKILL.md +142 -0
  598. package/plugins/lisa-harper-fabric-devin/skills/harper-rest-queries/SKILL.md +403 -0
  599. package/plugins/lisa-harper-fabric-devin/skills/harper-schema-graphql/SKILL.md +123 -0
  600. package/plugins/lisa-harper-fabric-devin/skills/harper-testing/SKILL.md +254 -0
  601. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  602. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  603. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  604. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  605. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  606. package/plugins/lisa-nestjs-devin/.claude-plugin/plugin.json +11 -0
  607. package/plugins/lisa-nestjs-devin/.devin-plugin/plugin.json +8 -0
  608. package/plugins/lisa-nestjs-devin/hooks/block-migration-edits.sh +125 -0
  609. package/plugins/lisa-nestjs-devin/hooks/devin-tool-name-shim.sh +30 -0
  610. package/plugins/lisa-nestjs-devin/hooks/lisa-edit-gate.sh +152 -0
  611. package/plugins/lisa-nestjs-devin/hooks.json +15 -0
  612. package/plugins/lisa-nestjs-devin/skills/nestjs-graphql/SKILL.md +176 -0
  613. package/plugins/lisa-nestjs-devin/skills/nestjs-graphql/references/advanced-features.md +527 -0
  614. package/plugins/lisa-nestjs-devin/skills/nestjs-graphql/references/project-patterns.md +531 -0
  615. package/plugins/lisa-nestjs-devin/skills/nestjs-graphql/references/quick-start.md +257 -0
  616. package/plugins/lisa-nestjs-devin/skills/nestjs-graphql/references/resolvers-mutations.md +413 -0
  617. package/plugins/lisa-nestjs-devin/skills/nestjs-graphql/references/types-scalars.md +513 -0
  618. package/plugins/lisa-nestjs-devin/skills/nestjs-rules/SKILL.md +560 -0
  619. package/plugins/lisa-nestjs-devin/skills/typeorm-patterns/SKILL.md +275 -0
  620. package/plugins/lisa-nestjs-devin/skills/typeorm-patterns/references/configuration-patterns.md +487 -0
  621. package/plugins/lisa-nestjs-devin/skills/typeorm-patterns/references/entity-patterns.md +450 -0
  622. package/plugins/lisa-nestjs-devin/skills/typeorm-patterns/references/observability-patterns.md +536 -0
  623. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  624. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  625. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  626. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  627. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  628. package/plugins/lisa-openclaw-devin/.claude-plugin/plugin.json +8 -0
  629. package/plugins/lisa-openclaw-devin/.devin-plugin/plugin.json +8 -0
  630. package/plugins/lisa-openclaw-devin/skills/lisa-openclaw-connect-repo-topic/SKILL.md +163 -0
  631. package/plugins/lisa-openclaw-devin/skills/lisa-openclaw-connect-repo-topic/references/repo-topic-config.md +185 -0
  632. package/plugins/lisa-openclaw-devin/skills/lisa-openclaw-connect-staff/SKILL.md +175 -0
  633. package/plugins/lisa-openclaw-devin/skills/lisa-openclaw-connect-staff/references/platform-routing.md +123 -0
  634. package/plugins/lisa-openclaw-devin/skills/lisa-openclaw-connect-staff/references/prompts.md +78 -0
  635. package/plugins/lisa-openclaw-devin/skills/lisa-openclaw-setup/SKILL.md +141 -0
  636. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  637. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  638. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  639. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  640. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  641. package/plugins/lisa-phaser-devin/.claude-plugin/plugin.json +11 -0
  642. package/plugins/lisa-phaser-devin/.devin-plugin/plugin.json +8 -0
  643. package/plugins/lisa-phaser-devin/agents/accessibility-advocate.md +55 -0
  644. package/plugins/lisa-phaser-devin/agents/art-director.md +90 -0
  645. package/plugins/lisa-phaser-devin/agents/audio-director.md +65 -0
  646. package/plugins/lisa-phaser-devin/agents/combat-designer.md +61 -0
  647. package/plugins/lisa-phaser-devin/agents/economy-designer.md +59 -0
  648. package/plugins/lisa-phaser-devin/agents/game-designer.md +62 -0
  649. package/plugins/lisa-phaser-devin/agents/game-feel-specialist.md +56 -0
  650. package/plugins/lisa-phaser-devin/agents/level-designer.md +59 -0
  651. package/plugins/lisa-phaser-devin/agents/localization-manager.md +61 -0
  652. package/plugins/lisa-phaser-devin/agents/marketing-strategist.md +59 -0
  653. package/plugins/lisa-phaser-devin/agents/monetization-designer.md +59 -0
  654. package/plugins/lisa-phaser-devin/agents/narrative-designer.md +56 -0
  655. package/plugins/lisa-phaser-devin/agents/onboarding-advocate.md +59 -0
  656. package/plugins/lisa-phaser-devin/agents/player-advocate.md +57 -0
  657. package/plugins/lisa-phaser-devin/agents/producer.md +61 -0
  658. package/plugins/lisa-phaser-devin/agents/product-analyst.md +62 -0
  659. package/plugins/lisa-phaser-devin/agents/publisher.md +59 -0
  660. package/plugins/lisa-phaser-devin/agents/qa-playtester.md +57 -0
  661. package/plugins/lisa-phaser-devin/agents/target-player.md +52 -0
  662. package/plugins/lisa-phaser-devin/agents/ux-ui-designer.md +60 -0
  663. package/plugins/lisa-phaser-devin/hooks/devin-tool-name-shim.sh +30 -0
  664. package/plugins/lisa-phaser-devin/hooks/inject-rules.sh +27 -0
  665. package/plugins/lisa-phaser-devin/hooks.json +14 -0
  666. package/plugins/lisa-phaser-devin/rules/eager/phaser.md +44 -0
  667. package/plugins/lisa-phaser-devin/rules/reference/phaser.md +184 -0
  668. package/plugins/lisa-phaser-devin/skills/phaser-accessibility/SKILL.md +135 -0
  669. package/plugins/lisa-phaser-devin/skills/phaser-asset-pipeline/SKILL.md +222 -0
  670. package/plugins/lisa-phaser-devin/skills/phaser-asset-sourcing/SKILL.md +151 -0
  671. package/plugins/lisa-phaser-devin/skills/phaser-build-deploy/SKILL.md +153 -0
  672. package/plugins/lisa-phaser-devin/skills/phaser-i18n/SKILL.md +122 -0
  673. package/plugins/lisa-phaser-devin/skills/phaser-project-structure/SKILL.md +89 -0
  674. package/plugins/lisa-phaser-devin/skills/phaser-services/SKILL.md +208 -0
  675. package/plugins/lisa-phaser-devin/skills/phaser-testing/SKILL.md +192 -0
  676. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  677. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  678. package/plugins/lisa-rails-agy/plugin.json +1 -1
  679. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  680. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  681. package/plugins/lisa-rails-devin/.claude-plugin/plugin.json +11 -0
  682. package/plugins/lisa-rails-devin/.devin-plugin/plugin.json +8 -0
  683. package/plugins/lisa-rails-devin/agents/ops-specialist.md +226 -0
  684. package/plugins/lisa-rails-devin/hooks/devin-tool-name-shim.sh +30 -0
  685. package/plugins/lisa-rails-devin/hooks/inject-rules.sh +40 -0
  686. package/plugins/lisa-rails-devin/hooks/lisa-edit-gate.sh +152 -0
  687. package/plugins/lisa-rails-devin/hooks/rubocop-on-edit.sh +101 -0
  688. package/plugins/lisa-rails-devin/hooks/sg-scan-on-edit.sh +97 -0
  689. package/plugins/lisa-rails-devin/hooks.json +29 -0
  690. package/plugins/lisa-rails-devin/rules/eager/rails-conventions.md +23 -0
  691. package/plugins/lisa-rails-devin/rules/reference/rails-conventions.md +176 -0
  692. package/plugins/lisa-rails-devin/skills/action-controller-best-practices/SKILL.md +374 -0
  693. package/plugins/lisa-rails-devin/skills/action-view-best-practices/SKILL.md +335 -0
  694. package/plugins/lisa-rails-devin/skills/active-record-model-best-practices/SKILL.md +166 -0
  695. package/plugins/lisa-rails-devin/skills/e2e-coverage-gaps/SKILL.md +117 -0
  696. package/plugins/lisa-rails-devin/skills/fix-linter-error/SKILL.md +45 -0
  697. package/plugins/lisa-rails-devin/skills/improve-code-complexity/SKILL.md +51 -0
  698. package/plugins/lisa-rails-devin/skills/improve-max-lines/SKILL.md +46 -0
  699. package/plugins/lisa-rails-devin/skills/improve-max-lines-per-function/SKILL.md +46 -0
  700. package/plugins/lisa-rails-devin/skills/improve-test-coverage/SKILL.md +48 -0
  701. package/plugins/lisa-rails-devin/skills/jira-add-journey/SKILL.md +79 -0
  702. package/plugins/lisa-rails-devin/skills/jira-create/SKILL.md +100 -0
  703. package/plugins/lisa-rails-devin/skills/jira-evidence/SKILL.md +76 -0
  704. package/plugins/lisa-rails-devin/skills/jira-evidence/scripts/post-evidence.sh +262 -0
  705. package/plugins/lisa-rails-devin/skills/jira-journey/SKILL.md +65 -0
  706. package/plugins/lisa-rails-devin/skills/jira-verify/SKILL.md +26 -0
  707. package/plugins/lisa-rails-devin/skills/ops-check-logs/SKILL.md +191 -0
  708. package/plugins/lisa-rails-devin/skills/ops-deploy/SKILL.md +153 -0
  709. package/plugins/lisa-rails-devin/skills/ops-run-local/SKILL.md +169 -0
  710. package/plugins/lisa-rails-devin/skills/ops-verify-jobs/SKILL.md +157 -0
  711. package/plugins/lisa-rails-devin/skills/ops-verify-telemetry/SKILL.md +226 -0
  712. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  713. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  714. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  715. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  716. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  717. package/plugins/lisa-typescript-devin/.claude-plugin/plugin.json +11 -0
  718. package/plugins/lisa-typescript-devin/.devin-plugin/plugin.json +8 -0
  719. package/plugins/lisa-typescript-devin/hooks/block-suppress-directives.sh +141 -0
  720. package/plugins/lisa-typescript-devin/hooks/devin-tool-name-shim.sh +30 -0
  721. package/plugins/lisa-typescript-devin/hooks/format-on-edit.sh +102 -0
  722. package/plugins/lisa-typescript-devin/hooks/lint-on-edit.sh +117 -0
  723. package/plugins/lisa-typescript-devin/hooks/lisa-edit-gate.sh +152 -0
  724. package/plugins/lisa-typescript-devin/hooks/sg-scan-on-edit.sh +94 -0
  725. package/plugins/lisa-typescript-devin/hooks.json +34 -0
  726. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  727. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  728. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  729. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  730. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  731. package/plugins/lisa-wiki-devin/.claude-plugin/plugin.json +8 -0
  732. package/plugins/lisa-wiki-devin/.devin-plugin/plugin.json +8 -0
  733. package/plugins/lisa-wiki-devin/ci/lisa-wiki-validate.yml +33 -0
  734. package/plugins/lisa-wiki-devin/schema/lisa-wiki-config.schema.json +162 -0
  735. package/plugins/lisa-wiki-devin/schema/wiki-structure.schema.json +51 -0
  736. package/plugins/lisa-wiki-devin/scripts/_wiki-lib.mjs +204 -0
  737. package/plugins/lisa-wiki-devin/scripts/diff-guard.mjs +117 -0
  738. package/plugins/lisa-wiki-devin/scripts/ensure-gitignore.mjs +131 -0
  739. package/plugins/lisa-wiki-devin/scripts/ensure-wiki.mjs +268 -0
  740. package/plugins/lisa-wiki-devin/scripts/ingest-git.mjs +198 -0
  741. package/plugins/lisa-wiki-devin/scripts/ingest-memory.mjs +135 -0
  742. package/plugins/lisa-wiki-devin/scripts/ingest-roles.mjs +95 -0
  743. package/plugins/lisa-wiki-devin/scripts/ingest_slack_channel.py +361 -0
  744. package/plugins/lisa-wiki-devin/scripts/lib/bounded-child.mjs +159 -0
  745. package/plugins/lisa-wiki-devin/scripts/lint-wiki.mjs +513 -0
  746. package/plugins/lisa-wiki-devin/scripts/mcp-doctor.mjs +72 -0
  747. package/plugins/lisa-wiki-devin/scripts/render-contract.mjs +107 -0
  748. package/plugins/lisa-wiki-devin/scripts/rewrite-refs.mjs +144 -0
  749. package/plugins/lisa-wiki-devin/scripts/slack_oauth_user.py +179 -0
  750. package/plugins/lisa-wiki-devin/scripts/validate-config.mjs +321 -0
  751. package/plugins/lisa-wiki-devin/scripts/verify-migration.mjs +203 -0
  752. package/plugins/lisa-wiki-devin/scripts/verify-wiki-safety.mjs +126 -0
  753. package/plugins/lisa-wiki-devin/scripts/wiki-safety.mjs +378 -0
  754. package/plugins/lisa-wiki-devin/scripts/wiki-status.mjs +345 -0
  755. package/plugins/lisa-wiki-devin/skills/lisa-wiki-add-ingest/SKILL.md +34 -0
  756. package/plugins/lisa-wiki-devin/skills/lisa-wiki-add-role/SKILL.md +35 -0
  757. package/plugins/lisa-wiki-devin/skills/lisa-wiki-connector-confluence/SKILL.md +25 -0
  758. package/plugins/lisa-wiki-devin/skills/lisa-wiki-connector-docs/SKILL.md +30 -0
  759. package/plugins/lisa-wiki-devin/skills/lisa-wiki-connector-git/SKILL.md +25 -0
  760. package/plugins/lisa-wiki-devin/skills/lisa-wiki-connector-jira/SKILL.md +28 -0
  761. package/plugins/lisa-wiki-devin/skills/lisa-wiki-connector-memory/SKILL.md +28 -0
  762. package/plugins/lisa-wiki-devin/skills/lisa-wiki-connector-notion/SKILL.md +25 -0
  763. package/plugins/lisa-wiki-devin/skills/lisa-wiki-connector-roles/SKILL.md +22 -0
  764. package/plugins/lisa-wiki-devin/skills/lisa-wiki-connector-slack/SKILL.md +30 -0
  765. package/plugins/lisa-wiki-devin/skills/lisa-wiki-connector-web/SKILL.md +23 -0
  766. package/plugins/lisa-wiki-devin/skills/lisa-wiki-doctor/SKILL.md +47 -0
  767. package/plugins/lisa-wiki-devin/skills/lisa-wiki-ingest/SKILL.md +106 -0
  768. package/plugins/lisa-wiki-devin/skills/lisa-wiki-lint/SKILL.md +32 -0
  769. package/plugins/lisa-wiki-devin/skills/lisa-wiki-migrate/SKILL.md +43 -0
  770. package/plugins/lisa-wiki-devin/skills/lisa-wiki-onboard-me/SKILL.md +33 -0
  771. package/plugins/lisa-wiki-devin/skills/lisa-wiki-query/SKILL.md +40 -0
  772. package/plugins/lisa-wiki-devin/skills/lisa-wiki-setup/SKILL.md +75 -0
  773. package/plugins/lisa-wiki-devin/skills/lisa-wiki-setup-automations/SKILL.md +83 -0
  774. package/plugins/lisa-wiki-devin/skills/lisa-wiki-status/SKILL.md +47 -0
  775. package/plugins/lisa-wiki-devin/skills/lisa-wiki-tear-down-automations/SKILL.md +34 -0
  776. package/plugins/lisa-wiki-devin/skills/lisa-wiki-usage/SKILL.md +50 -0
  777. package/plugins/lisa-wiki-devin/templates/agents/role-agent.claude.md +16 -0
  778. package/plugins/lisa-wiki-devin/templates/agents/role-agent.codex.toml +15 -0
  779. package/plugins/lisa-wiki-devin/templates/index.md +17 -0
  780. package/plugins/lisa-wiki-devin/templates/llm-wiki-contract.md +72 -0
  781. package/plugins/lisa-wiki-devin/templates/log.md +8 -0
  782. package/plugins/lisa-wiki-devin/templates/page-types/architecture.md +18 -0
  783. package/plugins/lisa-wiki-devin/templates/page-types/concept.md +18 -0
  784. package/plugins/lisa-wiki-devin/templates/page-types/decision.md +18 -0
  785. package/plugins/lisa-wiki-devin/templates/page-types/entity.md +19 -0
  786. package/plugins/lisa-wiki-devin/templates/page-types/open-question.md +18 -0
  787. package/plugins/lisa-wiki-devin/templates/page-types/playbook.md +18 -0
  788. package/plugins/lisa-wiki-devin/templates/page-types/project.md +19 -0
  789. package/plugins/lisa-wiki-devin/templates/page-types/requirement.md +19 -0
  790. package/plugins/lisa-wiki-devin/templates/page-types/staff.md +26 -0
  791. package/plugins/lisa-wiki-devin/templates/start-here.md +24 -0
  792. package/plugins/lisa-wiki-devin/templates/state-readme.md +20 -0
  793. package/plugins/lisa-wiki-devin/templates/wrapper-gitignore.txt +19 -0
  794. package/scripts/build-plugins.sh +2 -2
  795. package/scripts/deployed-guard-advice.mjs +1 -0
  796. package/scripts/generate-devin-plugin-artifacts.mjs +263 -0
  797. package/scripts/lib/hook-registration-audit.mjs +3 -1
  798. package/scripts/lib/per-agent-hook-filter.mjs +174 -5
  799. package/scripts/lib/plugin-rule-citations.mjs +2 -2
@@ -0,0 +1,1065 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Blocker re-probe gate for pre-work build-intake candidates.
4
+ *
5
+ * A blocker is a claim with a timestamp, not a fact. It is written once, and it
6
+ * decays the moment its condition goes true — a dependency lands on trunk, a
7
+ * CVE gets patched, a package publishes. Nothing in the old intake loop ever
8
+ * re-read one, so a discharged blocker held its item out of the queue forever.
9
+ *
10
+ * This module decides, per candidate, whether intake may select it. It never
11
+ * probes anything itself: the caller runs the probe and hands back the result,
12
+ * which keeps the decision auditable and testable apart from the network.
13
+ */
14
+
15
+ import { isPreWorkLaneType } from "./intake-prework-denominator.mjs";
16
+
17
+ /** Marker a writer stamps on an item a human deliberately parked. */
18
+ export const HUMAN_GATE_MARKER = "[lisa-human-gate]";
19
+
20
+ /** Default label naming a block only a human can clear. */
21
+ export const DEFAULT_HUMAN_NEEDED_LABEL = "human-needed";
22
+
23
+ /**
24
+ * @param {unknown} labels
25
+ * @returns {readonly string[]}
26
+ */
27
+ function normalizeLabels(labels) {
28
+ return (Array.isArray(labels) ? labels : [])
29
+ .map(label =>
30
+ typeof label === "string"
31
+ ? label
32
+ : typeof label?.name === "string"
33
+ ? label.name
34
+ : ""
35
+ )
36
+ .map(label => label.trim().toLowerCase())
37
+ .filter(label => label.length > 0);
38
+ }
39
+
40
+ /**
41
+ * Decoration a declaration may sit behind, and nothing more.
42
+ *
43
+ * Whitespace, blockquote arrows, list bullets or numbers, emphasis, a comment
44
+ * hash, and an opening HTML comment. `#` is there on EVIDENCE rather than
45
+ * taste: a shell script declares a hold as `# <marker> reason=…` — a bare
46
+ * marker behind a SHELL comment, with no HTML comment anywhere — and that form
47
+ * is in this repository's own guard fixtures. A single character class plus two
48
+ * optional groups —
49
+ * deliberately not a nested-quantifier pattern, because this runs over
50
+ * untrusted work-item bodies and `sonarjs/slow-regex` is right about that
51
+ * shape.
52
+ */
53
+ const LEADING_DECORATION =
54
+ /^[ \t>*_+#-]*(?:\d+[.)][ \t]*)?(?:<!--[ \t]*)?[ \t]*/u;
55
+
56
+ /**
57
+ * Decode one stored Markdown escape layer without changing the provider record.
58
+ * Linear escapes marker brackets and punctuation in reason keys. A single pass
59
+ * keeps literal backslash pairs intact instead of recursively inventing markers.
60
+ * Callers doing bookkeeping-marker searches use this same projection; hold and
61
+ * release parsers receive original bodies and apply it after excluding code.
62
+ * @param {unknown} body - Original provider text
63
+ * @returns {string} One-pass Markdown punctuation projection
64
+ */
65
+ export function normalizeProviderMarkdown(body) {
66
+ return String(body ?? "").replace(
67
+ /\\([\u0021-\u002f\u003a-\u0040\u005b-\u0060\u007b-\u007e])/gu,
68
+ "$1"
69
+ );
70
+ }
71
+
72
+ /**
73
+ * The body with fenced blocks and inline code spans removed.
74
+ *
75
+ * Documentation of a declaration is not a declaration, and a fenced example is
76
+ * how the declaration form gets written ABOUT. The same move
77
+ * `pr-arming-sweep.mjs` makes for the auto-merge-off marker
78
+ * (CodySwannGT/lisa#3986), and the same one `block-direct-issue-create.sh`
79
+ * makes when it strips heredoc bodies before tokenising argv.
80
+ * @param {unknown} body - The raw item body
81
+ * @returns {string} The body with quoted and code regions blanked out
82
+ */
83
+ function declarativeText(body) {
84
+ const withoutCode = String(body ?? "")
85
+ .replace(/```[\s\S]*?```/gu, "")
86
+ .replace(/`[^`\n]*`/gu, "");
87
+ return normalizeProviderMarkdown(withoutCode);
88
+ }
89
+
90
+ /**
91
+ * Whether an HTML comment on this line carries the given marker.
92
+ *
93
+ * The second declaration form, and it is not a concession: an HTML comment is
94
+ * invisible when the body is rendered, so nobody writes one to TALK about the
95
+ * marker — a quotation has to be visible to be a quotation. Prose about the
96
+ * marker is written in sentences, code spans and fenced examples, all of which
97
+ * this rule already excludes.
98
+ *
99
+ * Scanned rather than pattern-matched. A regular expression with two lazy
100
+ * `[^\n]*?` runs around a literal is the ambiguous shape this module avoids
101
+ * elsewhere, and an indexOf walk is both linear and easier to be sure about.
102
+ * @param {string} line - One line of the body
103
+ * @param {string} marker - The literal marker to look for
104
+ * @returns {boolean} True when a comment on this line contains the marker
105
+ */
106
+ function commentCarriesMarker(line, marker) {
107
+ const segments = line.split("<!--");
108
+ for (let index = 1; index < segments.length; index += 1) {
109
+ const close = segments[index].indexOf("-->");
110
+ const inside =
111
+ close === -1 ? segments[index] : segments[index].slice(0, close);
112
+ if (inside.includes(marker)) return true;
113
+ }
114
+ return false;
115
+ }
116
+
117
+ /**
118
+ * Whether one line DECLARES a hold rather than mentioning one.
119
+ *
120
+ * Two accepted forms, and the corpus says they cost nothing to combine:
121
+ * measured over this repository's 42 matching bodies, line-leading alone and
122
+ * line-leading-or-comment hold the SAME 29. The comment branch exists because
123
+ * the filing guard reads inputs that are not markdown documents — a one-line
124
+ * `--body` string and a shell script — where a declaration legitimately sits
125
+ * after other text on its line.
126
+ * @param {string} line - One line of the body
127
+ * @param {string} [marker] - The declaration marker to test for
128
+ * @returns {boolean} True when the line declares with that marker
129
+ */
130
+ function declaresOnLine(line, marker = HUMAN_GATE_MARKER) {
131
+ if (line.replace(LEADING_DECORATION, "").startsWith(marker)) {
132
+ return true;
133
+ }
134
+ return commentCarriesMarker(line, marker);
135
+ }
136
+
137
+ /**
138
+ * Count what a body says about the hold marker, split by what it MEANS.
139
+ *
140
+ * ## Why the substring test had to go
141
+ *
142
+ * `isHumanGated` asked one question — does the body contain the marker
143
+ * anywhere — and that form was deliberate, documented, and correct when it was
144
+ * written: *"it is a marker with no other meaning, so its presence IS the
145
+ * declaration."* The premise expired. The marker acquired a second meaning —
146
+ * **being discussed** — the moment the feature became something people file
147
+ * tickets about, so a sentence quoting it, a Gherkin line naming it, and a
148
+ * ticket about it all read as declared holds (CodySwannGT/lisa#3815).
149
+ *
150
+ * The consequence is not one skipped cycle. `planHumanGateReconciliation`
151
+ * removes the ready role and applies the human-needed label, so a false
152
+ * positive rewrites the item's own metadata and every later sweep agrees with
153
+ * the first. And the affected population GROWS with the documentation: 38
154
+ * matching bodies measured 2026-09-04, 42 on 2026-09-05.
155
+ *
156
+ * ## The rule
157
+ *
158
+ * A declaration is POSITIONAL — the marker leads its line, behind at most
159
+ * blockquote, list, emphasis or opening-comment decoration — evaluated after
160
+ * code regions are removed. Measured over this repository's 42 matching bodies:
161
+ * this holds 29 of them and correctly releases the two live ready-lane items
162
+ * that only discussed the marker.
163
+ *
164
+ * The stricter HTML-comment-only rule was measured and REJECTED: it holds only
165
+ * 18, dropping declarations that carry `human-needed` today. Losing a real hold
166
+ * is the unsafe direction and would need a retrofit of the tracker.
167
+ *
168
+ * ## Why it counts rather than answering yes or no
169
+ *
170
+ * A heuristic that silently drops candidates is indistinguishable from one that
171
+ * found none. Every occurrence this rule declines to honour is counted and
172
+ * reported, so "the rule demoted 33 mentions" is a fact an operator can read
173
+ * rather than an absence they must infer.
174
+ * @param {unknown} body - The item body
175
+ * @returns {{ total: number, declared: number, demoted: number }} Occurrences,
176
+ * those that declare a hold, and those demoted to mentions
177
+ */
178
+ export function humanGateMentions(body) {
179
+ const raw = String(body ?? "");
180
+ const total =
181
+ normalizeProviderMarkdown(raw).split(HUMAN_GATE_MARKER).length - 1;
182
+ const declared = declarativeText(raw)
183
+ .split("\n")
184
+ .filter(line => declaresOnLine(line)).length;
185
+ return { total, declared, demoted: total - declared };
186
+ }
187
+
188
+ /**
189
+ * Whether a body declares a hold, as opposed to discussing one.
190
+ * @param {unknown} body - The item body
191
+ * @returns {boolean} True when at least one line declares a hold
192
+ */
193
+ export function bodyDeclaresHold(body) {
194
+ return humanGateMentions(body).declared > 0;
195
+ }
196
+
197
+ /**
198
+ * Marker a comment carries to DISCHARGE a hold.
199
+ *
200
+ * ## Why a comment and not the body
201
+ *
202
+ * The hold lives in the description, and the only description write this plugin
203
+ * has is a whole-body replacement — re-read everything, change one line, write
204
+ * it all back. On an item carrying acceptance criteria, a validation journey
205
+ * and a managed usage section, "delete one HTML comment" is therefore "rewrite
206
+ * the record and hope nothing was dropped". A release procedure whose only
207
+ * implementation risks destroying what it releases is not a release procedure:
208
+ * the rational move is always to leave the hold, so holds only accumulate
209
+ * (CodySwannGT/lisa#3852).
210
+ *
211
+ * A comment is append-only. It cannot drop a section it never held, and the
212
+ * same reader that reads the hold reads the discharge.
213
+ *
214
+ * ## Why it is not a superstring of the hold marker
215
+ *
216
+ * `HUMAN_GATE_MARKER` closes with `]`, so `[lisa-human-gate-release]` does not
217
+ * contain it. That is load-bearing rather than incidental: a release record
218
+ * that matched the hold test would declare a fresh hold every time one was
219
+ * lifted, which is the same trap `NORMALIZATION_HOLD_NOTE_MARKER` documents.
220
+ */
221
+ export const HUMAN_GATE_RELEASE_MARKER = "[lisa-human-gate-release]";
222
+
223
+ /** Structured key a hold and its release both name, so they pair up. */
224
+ const REASON_KEY = "reason=";
225
+
226
+ /**
227
+ * The comparable form of a hold reason.
228
+ *
229
+ * Case and internal whitespace drift between the hand that writes the hold and
230
+ * the hand that writes the release; the identity of the question does not.
231
+ * @param {unknown} value - A raw reason string
232
+ * @returns {string} Its comparable form, empty when there is none
233
+ */
234
+ function normalizeReason(value) {
235
+ return String(value ?? "")
236
+ .replace(/\s+/gu, " ")
237
+ .trim()
238
+ .toLowerCase();
239
+ }
240
+
241
+ /**
242
+ * The reason a declaring line names, or the empty key when it names none.
243
+ *
244
+ * A keyless declaration is not a defect to be rejected — markers in the wild
245
+ * carry no `reason=` at all, which is why the hold test is not keyed on one.
246
+ * The empty string is a real key here: a keyless hold is discharged by a
247
+ * keyless release and by nothing else, so the two surfaces stay symmetric
248
+ * whether or not a reason was ever written.
249
+ * @param {string} line - A line already known to declare
250
+ * @param {string} marker - The declaration marker it carries
251
+ * @returns {string} The normalized reason key
252
+ */
253
+ function reasonOnLine(line, marker) {
254
+ const at = line.indexOf(marker);
255
+ if (at === -1) return "";
256
+ const tail = line.slice(at + marker.length).split("-->")[0];
257
+ const key = tail.indexOf(REASON_KEY);
258
+ if (key === -1) return "";
259
+ return normalizeReason(tail.slice(key + REASON_KEY.length));
260
+ }
261
+
262
+ /**
263
+ * The reason keys of every hold a body DECLARES, deduplicated.
264
+ *
265
+ * Reuses the precision rule rather than restating it, so a body that merely
266
+ * discusses the marker yields no holds here for the same reason it reads as
267
+ * unheld in {@link bodyDeclaresHold}.
268
+ * @param {unknown} body - The item body
269
+ * @returns {string[]} One key per declared hold
270
+ */
271
+ export function humanGateHolds(body) {
272
+ const keys = declarativeText(body)
273
+ .split("\n")
274
+ .filter(line => declaresOnLine(line))
275
+ .map(line => reasonOnLine(line, HUMAN_GATE_MARKER));
276
+ return [...new Set(keys)];
277
+ }
278
+
279
+ /**
280
+ * Normalize stable provider IDs without case folding or trusting display names.
281
+ * @param {unknown} value - Provider actor ID
282
+ * @returns {string} Stable comparison key, or empty when invalid
283
+ */
284
+ function stableActorId(value) {
285
+ if (typeof value === "string") return value.trim();
286
+ return Number.isSafeInteger(value) && value > 0 ? String(value) : "";
287
+ }
288
+
289
+ /**
290
+ * Recognize explicit provider bot metadata even for an allowlisted identity.
291
+ * @param {unknown} actor - Provider or normalized author metadata
292
+ * @returns {boolean} Whether the metadata identifies automation
293
+ */
294
+ function isKnownBot(actor) {
295
+ if (!actor || typeof actor !== "object") return false;
296
+ const kinds = [
297
+ actor.type,
298
+ actor.__typename,
299
+ actor.accountType,
300
+ actor.authorType,
301
+ ];
302
+ return (
303
+ actor.botActor != null ||
304
+ actor.isBot === true ||
305
+ actor.bot === true ||
306
+ kinds.some(kind => /^(?:bot|app)$/i.test(String(kind ?? "").trim()))
307
+ );
308
+ }
309
+
310
+ /**
311
+ * Require authenticated provider identity and separately supplied human trust.
312
+ * Adapters may normalize the ID to authorId, but must preserve bot metadata.
313
+ * Names, body text and self-asserted authorization flags never confer trust.
314
+ * @param {unknown} comment - Structured provider comment
315
+ * @param {ReadonlySet<string>} trustedIds - Explicitly trusted human actor IDs
316
+ * @returns {boolean} Whether the comment may discharge a human hold
317
+ */
318
+ function isTrustedHumanComment(comment, trustedIds) {
319
+ if (!comment || typeof comment !== "object" || Array.isArray(comment))
320
+ return false;
321
+ if ([comment, comment.user, comment.author].some(isKnownBot)) return false;
322
+ const id = stableActorId(
323
+ comment.authorId ??
324
+ comment.user?.id ??
325
+ comment.author?.id ??
326
+ comment.author?.accountId
327
+ );
328
+ return id.length > 0 && trustedIds.has(id);
329
+ }
330
+
331
+ /**
332
+ * The reason keys released by explicitly trusted human authors, deduplicated.
333
+ *
334
+ * Comments must retain authenticated provider authorship: normalized authorId,
335
+ * user.id, author.id or author.accountId. The caller supplies trusted human IDs
336
+ * independently of comment content. Raw strings, missing IDs, known bots and
337
+ * an absent or empty allowlist fail closed and cannot discharge a hold.
338
+ * @param {unknown} comments - Structured comments, any order
339
+ * @param {unknown} trustedHumanActorIds - Explicit trusted human provider IDs
340
+ * @returns {string[]} One key per authorized recorded release
341
+ */
342
+ export function humanGateReleases(comments, trustedHumanActorIds = []) {
343
+ const trustedIds = new Set(
344
+ (Array.isArray(trustedHumanActorIds) ? trustedHumanActorIds : [])
345
+ .map(stableActorId)
346
+ .filter(Boolean)
347
+ );
348
+ const bodies = (Array.isArray(comments) ? comments : [])
349
+ .filter(entry => isTrustedHumanComment(entry, trustedIds))
350
+ .map(entry => entry.body ?? "");
351
+ const keys = bodies.flatMap(body =>
352
+ declarativeText(body)
353
+ .split("\n")
354
+ .filter(line => declaresOnLine(line, HUMAN_GATE_RELEASE_MARKER))
355
+ .map(line => reasonOnLine(line, HUMAN_GATE_RELEASE_MARKER))
356
+ );
357
+ return [...new Set(keys)];
358
+ }
359
+
360
+ /**
361
+ * Whether every hold on this item has a release recorded against it.
362
+ *
363
+ * Matching is per-reason on purpose. A blanket "any release clears everything"
364
+ * rule would make a hold declared AFTER a release be born discharged, which is
365
+ * the unsafe direction — the one this fix must not introduce while correcting
366
+ * the safe one. An item with no declared body hold is discharged only by a
367
+ * keyless release, which is the form that pairs with a label-only hold.
368
+ * @param {{ body?: unknown, comments?: unknown, trustedHumanActorIds?: unknown }} input - The item's surfaces
369
+ * @returns {boolean} True when nothing is left outstanding
370
+ */
371
+ export function humanGateDischarged(input = {}) {
372
+ const released = new Set(
373
+ humanGateReleases(input.comments, input.trustedHumanActorIds)
374
+ );
375
+ const holds = humanGateHolds(input.body);
376
+ if (holds.length === 0) return released.has("");
377
+ return holds.every(reason => released.has(reason));
378
+ }
379
+
380
+ /**
381
+ * The full held-ness verdict for an item, on every surface that carries a hold.
382
+ *
383
+ * Split out of {@link isHumanGated} because the release path needs to know more
384
+ * than yes-or-no: whether a hold existed at all, which reasons are still
385
+ * outstanding, and whether the durable label needs removing. A caller that only
386
+ * wants the boolean still gets exactly the boolean.
387
+ *
388
+ * The label is treated as a MIRROR of a declared body hold, never as a second
389
+ * independent hold, because that is how it is written: the vendor writers stamp
390
+ * both surfaces for one hold, and `planHumanGateReconciliation` adds the label
391
+ * to an item already carrying the marker. Counting it separately would leave
392
+ * every mirrored hold permanently outstanding under a keyed release — the exact
393
+ * defect this function exists to end, one layer down. Only when the body
394
+ * declares nothing does the label stand as a hold in its own right, and then it
395
+ * is a keyless one.
396
+ *
397
+ * Fails CLOSED on an unreadable discharge: with no comments supplied there are
398
+ * no releases, so a held item stays held. Holding a gate that may be stale
399
+ * beats releasing one that is not, and every caller that never passes comments
400
+ * keeps its current behaviour by construction.
401
+ * @param {{ labels?: unknown, body?: unknown, comments?: unknown, trustedHumanActorIds?: unknown, humanNeededLabel?: unknown }} input - Candidate surfaces
402
+ * @returns {{ held: boolean, reason: string, declared: number, outstanding: string[], released: string[], labelPresent: boolean }} Held-ness verdict
403
+ */
404
+ export function humanGateVerdict(input = {}) {
405
+ const configured = String(
406
+ input.humanNeededLabel ?? DEFAULT_HUMAN_NEEDED_LABEL
407
+ )
408
+ .trim()
409
+ .toLowerCase();
410
+ const labelPresent =
411
+ configured.length > 0 && normalizeLabels(input.labels).includes(configured);
412
+ const released = humanGateReleases(
413
+ input.comments,
414
+ input.trustedHumanActorIds
415
+ );
416
+ const releasedSet = new Set(released);
417
+ const holds = humanGateHolds(input.body);
418
+ const outstanding = holds.filter(reason => !releasedSet.has(reason));
419
+ const base = {
420
+ declared: holds.length,
421
+ released,
422
+ labelPresent,
423
+ };
424
+
425
+ if (outstanding.length > 0) {
426
+ return { held: true, reason: "hold-outstanding", outstanding, ...base };
427
+ }
428
+ if (holds.length > 0) {
429
+ return { held: false, reason: "hold-released", outstanding: [], ...base };
430
+ }
431
+ if (labelPresent) {
432
+ return releasedSet.has("")
433
+ ? { held: false, reason: "hold-released", outstanding: [], ...base }
434
+ : { held: true, reason: "hold-outstanding", outstanding: [""], ...base };
435
+ }
436
+
437
+ return { held: false, reason: "no-hold", outstanding: [], ...base };
438
+ }
439
+
440
+ /**
441
+ * Whether an item is held for a person, on either surface.
442
+ *
443
+ * Exported deliberately, and it is the ONLY answer to that question anywhere in
444
+ * the intake machinery. Every selection and promotion path calls this rather
445
+ * than inspecting labels itself, because the label surface alone is a partial
446
+ * answer: the vendor writers stamp the body marker on a deliberate hold, so an
447
+ * item held exactly as the filing contract instructs carries no label at all.
448
+ * A path that read labels alone judged such an item unheld and promoted it —
449
+ * which is #3805, and is why this is a shared function rather than a shared
450
+ * convention.
451
+ *
452
+ * It is also the only place a hold ENDS, which is why the release lives behind
453
+ * the same call rather than beside it: a reader that could see the hold but not
454
+ * its discharge is how the gate became one-way in the first place. Pass the
455
+ * item's structured comments and trustedHumanActorIds to honor an authorized
456
+ * release; omit either and the item stays held.
457
+ * @param {{ labels?: unknown, body?: unknown, comments?: unknown, trustedHumanActorIds?: unknown, humanNeededLabel?: unknown }} input - Candidate surfaces
458
+ * @returns {boolean} True when a person is holding this item
459
+ */
460
+ export function isHumanGated(input) {
461
+ return humanGateVerdict(input).held;
462
+ }
463
+
464
+ /**
465
+ * @param {unknown} value
466
+ * @returns {string}
467
+ */
468
+ function trimmedString(value) {
469
+ return typeof value === "string" ? value.trim() : "";
470
+ }
471
+
472
+ /**
473
+ * @param {{ discharged?: unknown, evidence?: unknown }} probe
474
+ * @returns {{ selectable: boolean, reason: string, evidence: string }}
475
+ */
476
+ function judgeProbe(probe) {
477
+ const evidence = trimmedString(probe.evidence);
478
+
479
+ if (probe.discharged !== true) {
480
+ return {
481
+ selectable: false,
482
+ reason: "blocker-holds",
483
+ evidence,
484
+ };
485
+ }
486
+ if (evidence.length === 0) {
487
+ return {
488
+ selectable: false,
489
+ reason: "blocker-discharge-unevidenced",
490
+ evidence,
491
+ };
492
+ }
493
+
494
+ return { selectable: true, reason: "blocker-discharged", evidence };
495
+ }
496
+
497
+ /**
498
+ * Decide whether a pre-work item may be selected as a build candidate.
499
+ *
500
+ * Order is load-bearing. The human gate is checked before anything else, so no
501
+ * probe result — however conclusive — can promote an item a human parked.
502
+ *
503
+ * @param {{
504
+ * laneType?: unknown
505
+ * labels?: unknown
506
+ * body?: unknown
507
+ * comments?: unknown
508
+ * trustedHumanActorIds?: unknown
509
+ * humanNeededLabel?: unknown
510
+ * statedBlocker?: unknown
511
+ * probe?: { discharged?: unknown, evidence?: unknown } | null
512
+ * }} input
513
+ * @returns {{ selectable: boolean, reason: string, humanGated: boolean, evidence: string }}
514
+ */
515
+ export function classifyPreWorkCandidate(input = {}) {
516
+ if (isHumanGated(input)) {
517
+ return {
518
+ selectable: false,
519
+ reason: "human-gate",
520
+ humanGated: true,
521
+ evidence: "",
522
+ };
523
+ }
524
+ if (!isPreWorkLaneType(input.laneType)) {
525
+ return {
526
+ selectable: false,
527
+ reason: "not-pre-work",
528
+ humanGated: false,
529
+ evidence: "",
530
+ };
531
+ }
532
+ if (trimmedString(input.statedBlocker).length === 0) {
533
+ return {
534
+ selectable: true,
535
+ reason: "no-blocker",
536
+ humanGated: false,
537
+ evidence: "",
538
+ };
539
+ }
540
+ if (!input.probe || typeof input.probe !== "object") {
541
+ return {
542
+ selectable: false,
543
+ reason: "blocker-unprobed",
544
+ humanGated: false,
545
+ evidence: "",
546
+ };
547
+ }
548
+
549
+ return { ...judgeProbe(input.probe), humanGated: false };
550
+ }
551
+
552
+ /** Plain-English wording for each verdict, for the note left on the item. */
553
+ const REASON_COPY = Object.freeze({
554
+ "human-gate": "A person parked this one on purpose, so intake left it alone.",
555
+ "not-pre-work": "This item is not sitting in a not-yet-started lane.",
556
+ "no-blocker": "No blocker was written on this item, so it is buildable.",
557
+ "blocker-unprobed":
558
+ "This item states a blocker that was not re-checked this cycle, so it stays put.",
559
+ "blocker-holds":
560
+ "The blocker was re-checked and still holds, so it stays put.",
561
+ "blocker-discharge-unevidenced":
562
+ "The blocker looked clear but no proof was recorded, so it stays put.",
563
+ "blocker-discharged":
564
+ "The blocker was re-checked and no longer applies, so this item is buildable again.",
565
+ });
566
+
567
+ /**
568
+ * Render the re-probe result to leave on the item, so the next cycle reads the
569
+ * answer instead of deriving it again.
570
+ *
571
+ * @param {{
572
+ * statedBlocker?: unknown
573
+ * checkedAt?: string | Date
574
+ * }} candidate
575
+ * @param {{ reason: string, evidence?: string }} verdict
576
+ * @returns {string}
577
+ */
578
+ export function formatReprobeNote(candidate = {}, verdict) {
579
+ const checkedAt =
580
+ candidate.checkedAt instanceof Date
581
+ ? candidate.checkedAt.toISOString()
582
+ : trimmedString(candidate.checkedAt) || new Date().toISOString();
583
+ const lines = [
584
+ "**Blocker re-check**",
585
+ "",
586
+ `- What has to be true: ${trimmedString(candidate.statedBlocker) || "(none written on this item)"}`,
587
+ `- What we found: ${REASON_COPY[verdict.reason] ?? verdict.reason}`,
588
+ ];
589
+ const evidence = trimmedString(verdict.evidence);
590
+ if (evidence.length > 0) {
591
+ lines.push(`- Proof: ${evidence}`);
592
+ }
593
+ lines.push(`- Checked at: ${checkedAt}`);
594
+
595
+ return lines.join("\n");
596
+ }
597
+
598
+ /**
599
+ * Marker on the note this module leaves, so a later cycle recognises its own
600
+ * work instead of commenting again.
601
+ */
602
+ export const HUMAN_GATE_NOTE_MARKER = "<!-- [lisa-human-gate-reconciled] -->";
603
+
604
+ /**
605
+ * Decide whether a candidate ALREADY IN THE READY LANE may be claimed.
606
+ *
607
+ * `classifyPreWorkCandidate` was the only caller of the human-gate test, and it
608
+ * runs on candidates outside the ready lane. An item that reached the ready
609
+ * lane was therefore claimed with the gate never consulted — the check was
610
+ * correct and simply unreachable from the path that matters.
611
+ *
612
+ * This shares `isHumanGated` with the pre-work classifier deliberately. Two
613
+ * copies of a substring test drift, and a drifted gate fails silently: it stops
614
+ * matching, and nothing reports that it stopped.
615
+ *
616
+ * The test stays a plain literal-substring match and is NOT keyed on `reason=`.
617
+ * Markers in the wild carry no `reason=` at all and sit anywhere in the body, so
618
+ * a parser keyed on the structured field would miss those while appearing to
619
+ * work on every item that happens to have one — reproducing this defect one
620
+ * layer down.
621
+ * @param {{ labels?: unknown, body?: unknown, comments?: unknown, trustedHumanActorIds?: unknown, humanNeededLabel?: unknown }} input - Candidate surfaces
622
+ * @returns {{ claimable: boolean, reason: string, humanGated: boolean }} Claim verdict
623
+ */
624
+ export function classifyReadyCandidate(input = {}) {
625
+ if (isHumanGated(input)) {
626
+ return { claimable: false, reason: "human-gate", humanGated: true };
627
+ }
628
+ return { claimable: true, reason: "ready-eligible", humanGated: false };
629
+ }
630
+
631
+ /**
632
+ * Plan the state repair for a ready-lane item that is held for a person.
633
+ *
634
+ * Skipping such an item is not enough. `lisa-repair-intake` sweeps items that
635
+ * are NOT in the ready role and excludes gated ones outright, so a ready AND
636
+ * gated item falls outside its filter twice over. Skipping alone would leave it
637
+ * re-evaluated and re-rejected every cycle forever, seen by nothing — trading a
638
+ * loud failure for a silent one.
639
+ *
640
+ * So the lane is reconciled to match the hold: the item leaves the pickup queue
641
+ * and gains the human-needed marker. That is the same repair the leaf-only gate
642
+ * already performs for a ready item that must not be dispatched.
643
+ *
644
+ * Idempotent by state rather than by memory: an item already out of the queue
645
+ * and already marked needs nothing, so asking twice yields no second mutation.
646
+ * @param {{
647
+ * labels?: unknown
648
+ * body?: unknown
649
+ * comments?: unknown
650
+ * trustedHumanActorIds?: unknown
651
+ * humanNeededLabel?: unknown
652
+ * readyLabel?: unknown
653
+ * alreadyNotified?: unknown
654
+ * }} input - Candidate surfaces plus the configured lane and marker labels
655
+ * @returns {{ gated: boolean, reason: string, actions: { removeReadyRole: boolean, addHumanNeededLabel: boolean, comment: boolean } }} Repair plan
656
+ */
657
+ export function planHumanGateReconciliation(input = {}) {
658
+ const idle = Object.freeze({
659
+ removeReadyRole: false,
660
+ addHumanNeededLabel: false,
661
+ comment: false,
662
+ });
663
+ if (!isHumanGated(input)) {
664
+ return { gated: false, reason: "not-gated", actions: idle };
665
+ }
666
+
667
+ const labels = normalizeLabels(input.labels);
668
+ const needed = String(input.humanNeededLabel ?? DEFAULT_HUMAN_NEEDED_LABEL)
669
+ .trim()
670
+ .toLowerCase();
671
+ const ready = String(input.readyLabel ?? "")
672
+ .trim()
673
+ .toLowerCase();
674
+ const inReadyLane = ready.length > 0 && labels.includes(ready);
675
+ const marked = needed.length > 0 && labels.includes(needed);
676
+ const actions = {
677
+ removeReadyRole: inReadyLane,
678
+ addHumanNeededLabel: needed.length > 0 && !marked,
679
+ comment:
680
+ input.alreadyNotified !== true &&
681
+ (inReadyLane || (needed.length > 0 && !marked)),
682
+ };
683
+ const changed =
684
+ actions.removeReadyRole || actions.addHumanNeededLabel || actions.comment;
685
+
686
+ return {
687
+ gated: true,
688
+ reason: changed ? "reconcile" : "already-reconciled",
689
+ actions,
690
+ };
691
+ }
692
+
693
+ /**
694
+ * Marker on the note the release path leaves, so a later cycle recognises its
695
+ * own work instead of commenting again.
696
+ *
697
+ * A superstring of neither declaration marker, for the reason
698
+ * {@link HUMAN_GATE_RELEASE_MARKER} gives: a note ABOUT a release must not read
699
+ * as a release, or the note announcing one item's discharge would discharge
700
+ * every item it names.
701
+ */
702
+ export const HUMAN_GATE_RELEASE_NOTE_MARKER =
703
+ "<!-- [lisa-human-gate-released] -->";
704
+
705
+ /**
706
+ * The one sentence every hold note gives an operator to END the hold.
707
+ *
708
+ * One constant, two notes, because the instruction IS the release path as far
709
+ * as the person reading it is concerned. Two copies of it drift, and a drifted
710
+ * instruction sends someone to a mechanism that no longer exists — which is
711
+ * worse than the prose it replaced, since that at least described something
712
+ * real. It names a comment because the alternative it replaces — "remove the
713
+ * hold note from the description" — asks for a whole-body rewrite the tooling
714
+ * has no safe way to perform.
715
+ */
716
+ const RESUME_INSTRUCTION = [
717
+ "- To resume it: leave a comment on this item that starts with ",
718
+ HUMAN_GATE_RELEASE_MARKER,
719
+ " and repeats the reason the hold in the description names. The next sweep ",
720
+ "puts it back in the queue on its own. Nothing else has to change — do not ",
721
+ "edit the description, and do not move it by hand.",
722
+ ].join("");
723
+
724
+ /**
725
+ * Plan the state repair for an item whose hold has been discharged.
726
+ *
727
+ * The exact inverse of {@link planHumanGateReconciliation}, and deliberately
728
+ * the same shape: that one takes the ready role away and adds the marker label,
729
+ * this one takes the marker label away and puts the ready role back. A state
730
+ * change with no inverse is the defect class this pair exists to close
731
+ * (`state-changes-without-inverses`), and an inverse that is merely *possible*
732
+ * is not one — it has to sit on a path something actually runs, which is why
733
+ * this is a planner the intake sweeps call rather than an instruction to an
734
+ * operator.
735
+ *
736
+ * Two refusals are load-bearing:
737
+ *
738
+ * - **A still-held item plans nothing.** Every outstanding reason holds the
739
+ * whole item, so an item whose second hold has not been answered is not
740
+ * half-released.
741
+ * - **An item that was never held plans nothing.** Without that, this would be
742
+ * a path that adds the build-ready role to arbitrary items — a promotion
743
+ * mechanism wearing a release mechanism's name.
744
+ *
745
+ * The ready role is restored only when the item carries none of the configured
746
+ * lifecycle labels, mirroring {@link planLabelNormalization}. An item that was
747
+ * held and has since reached a terminal lane must not be dragged back to the
748
+ * queue by its own release.
749
+ *
750
+ * Idempotent by state rather than by memory: an item already unmarked and
751
+ * already back in the queue needs nothing, so asking twice yields no second
752
+ * mutation.
753
+ * @param {{
754
+ * labels?: unknown
755
+ * body?: unknown
756
+ * comments?: unknown
757
+ * trustedHumanActorIds?: unknown
758
+ * humanNeededLabel?: unknown
759
+ * readyLabel?: unknown
760
+ * lifecycleLabels?: unknown
761
+ * alreadyNotified?: unknown
762
+ * }} input - Candidate surfaces plus the configured lane vocabulary
763
+ * @returns {{ released: boolean, reason: string, discharged: string[], actions: { removeHumanNeededLabel: boolean, addReadyLabel: string | null, comment: boolean } }} Release plan
764
+ */
765
+ export function planHumanGateRelease(input = {}) {
766
+ const idle = Object.freeze({
767
+ removeHumanNeededLabel: false,
768
+ addReadyLabel: null,
769
+ comment: false,
770
+ });
771
+ const verdict = humanGateVerdict(input);
772
+ if (verdict.held) {
773
+ return {
774
+ released: false,
775
+ reason: "hold-outstanding",
776
+ discharged: [],
777
+ actions: idle,
778
+ };
779
+ }
780
+ if (verdict.declared === 0 && !verdict.labelPresent) {
781
+ return {
782
+ released: false,
783
+ reason: "no-hold",
784
+ discharged: [],
785
+ actions: idle,
786
+ };
787
+ }
788
+
789
+ const needed = String(input.humanNeededLabel ?? DEFAULT_HUMAN_NEEDED_LABEL)
790
+ .trim()
791
+ .toLowerCase();
792
+ // The marker label is excluded from the lane test on both sides. It is one of
793
+ // the configured lifecycle labels AND it is the label this plan removes, so
794
+ // counting it would let the hold's own marker prove the item is already in a
795
+ // lane and veto the restoration — the release would clear the flag and leave
796
+ // the item in no queue at all, which is the original defect with one fewer
797
+ // symptom.
798
+ const labels = normalizeLabels(input.labels).filter(name => name !== needed);
799
+ const lifecycle = normalizeLabels(input.lifecycleLabels).filter(
800
+ name => name !== needed
801
+ );
802
+ const ready = trimmedString(input.readyLabel);
803
+ const inLifecycle = lifecycle.some(name => labels.includes(name));
804
+ const addReadyLabel =
805
+ ready.length > 0 && !inLifecycle && !labels.includes(ready.toLowerCase())
806
+ ? ready
807
+ : null;
808
+ const actions = {
809
+ removeHumanNeededLabel: verdict.labelPresent,
810
+ addReadyLabel,
811
+ comment:
812
+ input.alreadyNotified !== true &&
813
+ (verdict.labelPresent || addReadyLabel !== null),
814
+ };
815
+ const changed =
816
+ actions.removeHumanNeededLabel || addReadyLabel !== null || actions.comment;
817
+
818
+ return {
819
+ released: true,
820
+ reason: changed ? "release" : "already-released",
821
+ discharged: verdict.released,
822
+ actions,
823
+ };
824
+ }
825
+
826
+ /**
827
+ * Render the discharge record a person or a skill leaves to END a hold.
828
+ *
829
+ * Generated rather than retyped, because the release names the hold it ends by
830
+ * its reason and a mistyped reason discharges nothing while looking like it
831
+ * did. The reason is echoed verbatim from the hold, so the pairing is visible
832
+ * to a reader as well as to the matcher.
833
+ * @param {{ reason?: unknown, decidedBy?: unknown, decision?: unknown }} discharge - What was decided, and by whom
834
+ * @returns {string} Comment body carrying the release marker
835
+ */
836
+ export function formatHumanGateRelease(discharge = {}) {
837
+ const reason = trimmedString(discharge.reason);
838
+ const declaration =
839
+ reason.length > 0
840
+ ? `${HUMAN_GATE_RELEASE_MARKER} ${REASON_KEY}${reason}`
841
+ : HUMAN_GATE_RELEASE_MARKER;
842
+ const lines = [declaration, "", "**The hold on this item is lifted.**", ""];
843
+ lines.push(
844
+ `- What was being asked: ${reason.length > 0 ? reason : "(the hold named no reason)"}`
845
+ );
846
+ const decision = trimmedString(discharge.decision);
847
+ if (decision.length > 0) lines.push(`- What was decided: ${decision}`);
848
+ const decidedBy = trimmedString(discharge.decidedBy);
849
+ if (decidedBy.length > 0) lines.push(`- Decided by: ${decidedBy}`);
850
+ lines.push(
851
+ "- What happens next: this item goes back into the queue that agents build from."
852
+ );
853
+
854
+ return lines.join("\n");
855
+ }
856
+
857
+ /**
858
+ * Render the notice for an item this sweep released.
859
+ *
860
+ * Distinct from {@link formatHumanGateNote} for the same reason
861
+ * {@link formatNormalizationHoldNote} is: the two report opposite events, and
862
+ * reusing one to report the other tells an operator the wrong thing happened.
863
+ * @returns {string} Comment body, carrying the marker that keeps a re-run quiet
864
+ */
865
+ export function formatHumanGateReleaseNote() {
866
+ return [
867
+ "**Back in the queue: the hold was answered**",
868
+ "",
869
+ "- What was found: this item was being held for a person, and the " +
870
+ "decision it was waiting for has since been recorded on it.",
871
+ "- What changed: the hold flag has been taken off and the item has been " +
872
+ "put back into the queue that agents build from.",
873
+ "- Nothing was rewritten: the description is exactly as it was, hold note " +
874
+ "and all, so the history of why it was held stays readable.",
875
+ "",
876
+ HUMAN_GATE_RELEASE_NOTE_MARKER,
877
+ ].join("\n");
878
+ }
879
+
880
+ /**
881
+ * Marker on the note the normalization sweep leaves, so a later cycle
882
+ * recognises its own work instead of commenting again.
883
+ *
884
+ * Deliberately NOT the hold marker and deliberately not a superstring of it:
885
+ * `HUMAN_GATE_MARKER` closes with `]`, so neither this nor
886
+ * `HUMAN_GATE_NOTE_MARKER` matches it. A note that read as a hold declaration
887
+ * would make every reported item look held to the next body-reading sweep,
888
+ * including items the report merely names.
889
+ */
890
+ export const NORMALIZATION_HOLD_NOTE_MARKER =
891
+ "<!-- [lisa-human-gate-normalization-held] -->";
892
+
893
+ /**
894
+ * Decide whether an item carrying NO configured lifecycle label may be
895
+ * normalized into a ready lane.
896
+ *
897
+ * This is the promotion path, and it was keyed on labels alone. The configured
898
+ * `human_needed` label is one of the lifecycle labels whose *absence* the sweep
899
+ * enumerates on, so an item held only by the body marker was a member of the
900
+ * swept population by definition and got the build-ready label applied to it.
901
+ * The `[lisa-human-gate]` exclusion existed, in a different and read-only sweep
902
+ * further down the same contract: the one sweep that writes was the one that
903
+ * could not see the marker.
904
+ *
905
+ * Order is load-bearing for the same reason it is in `classifyPreWorkCandidate`:
906
+ * the hold is checked before lane membership and before any classification, so
907
+ * nothing downstream — however confident — can promote an item a person parked.
908
+ *
909
+ * On a match this plans NO write of its own. `planHumanGateReconciliation`
910
+ * turns a match into durable state, so a false positive there latches and every
911
+ * later cycle agrees with the first. The gate test is a plain substring match
912
+ * whose imprecision is tracked separately, so this path refuses and reports
913
+ * read-only instead — the same treatment the ungated-filing sweep already gives
914
+ * a hold it finds.
915
+ * @param {{
916
+ * labels?: unknown
917
+ * body?: unknown
918
+ * comments?: unknown
919
+ * trustedHumanActorIds?: unknown
920
+ * humanNeededLabel?: unknown
921
+ * lifecycleLabels?: unknown
922
+ * readyLabel?: unknown
923
+ * }} input - Candidate surfaces plus the configured lifecycle vocabulary
924
+ * @returns {{ normalize: boolean, reason: string, humanGated: boolean, actions: { addReadyLabel: string | null, reportHold: boolean } }} Normalization plan
925
+ */
926
+ export function planLabelNormalization(input = {}) {
927
+ const idle = Object.freeze({ addReadyLabel: null, reportHold: false });
928
+ if (isHumanGated(input)) {
929
+ return {
930
+ normalize: false,
931
+ reason: "human-gate",
932
+ humanGated: true,
933
+ actions: Object.freeze({ addReadyLabel: null, reportHold: true }),
934
+ };
935
+ }
936
+
937
+ const labels = normalizeLabels(input.labels);
938
+ if (normalizeLabels(input.lifecycleLabels).some(l => labels.includes(l))) {
939
+ return {
940
+ normalize: false,
941
+ reason: "already-in-lifecycle",
942
+ humanGated: false,
943
+ actions: idle,
944
+ };
945
+ }
946
+
947
+ const ready = trimmedString(input.readyLabel);
948
+ if (ready.length === 0) {
949
+ return {
950
+ normalize: false,
951
+ reason: "no-ready-label",
952
+ humanGated: false,
953
+ actions: idle,
954
+ };
955
+ }
956
+
957
+ return {
958
+ normalize: true,
959
+ reason: "normalize",
960
+ humanGated: false,
961
+ actions: Object.freeze({ addReadyLabel: ready, reportHold: false }),
962
+ };
963
+ }
964
+
965
+ /**
966
+ * Render the notice for an item the normalization sweep left alone.
967
+ *
968
+ * Distinct from `formatHumanGateNote` because the two say opposite things
969
+ * about what happened: that one reports a lane that WAS changed, this one
970
+ * reports a promotion that was declined and nothing else. Reusing it would tell
971
+ * an operator their item had been moved when it had not.
972
+ * @returns {string} Comment body, carrying the marker that keeps a re-run quiet
973
+ */
974
+ export function formatNormalizationHoldNote() {
975
+ return [
976
+ "**Left alone: a person is holding this**",
977
+ "",
978
+ "- What was found: the description says a person is holding this one, so " +
979
+ "it was not put into the queue that agents work from.",
980
+ "- What changed: nothing at all. It was left exactly as it is, and " +
981
+ "nothing will pick it up on its own.",
982
+ RESUME_INSTRUCTION,
983
+ "",
984
+ NORMALIZATION_HOLD_NOTE_MARKER,
985
+ ].join("\n");
986
+ }
987
+
988
+ /**
989
+ * Render the hold notice for a reader who does not know this subsystem.
990
+ *
991
+ * Written for a non-technical operator on purpose — that is who stands at this
992
+ * gate. It names what was found, what changed, and how to undo it, and uses no
993
+ * skill name, label syntax, or phase number, none of which a reader can act on.
994
+ * @returns {string} Comment body, carrying the marker that keeps a re-run quiet
995
+ */
996
+ export function formatHumanGateNote() {
997
+ return [
998
+ "**On hold for a person**",
999
+ "",
1000
+ "- What was found: this item is marked as held for a person, but it was " +
1001
+ "also sitting in the queue that agents build from — so it would have " +
1002
+ "been picked up and built anyway.",
1003
+ "- What changed: it has been taken out of that queue and flagged as " +
1004
+ "needing a person, so nothing will build it automatically.",
1005
+ RESUME_INSTRUCTION,
1006
+ "",
1007
+ HUMAN_GATE_NOTE_MARKER,
1008
+ ].join("\n");
1009
+ }
1010
+
1011
+ /**
1012
+ * Render the cycle-summary line naming what was held.
1013
+ *
1014
+ * A lane mutation nobody can see afterwards is the same class of problem as the
1015
+ * one this fixes, so the run says what it moved — and it keeps "nothing was
1016
+ * eligible" distinguishable from "something eligible was held".
1017
+ * @param {readonly unknown[]} held - Item references held this cycle
1018
+ * @returns {string} One summary line
1019
+ */
1020
+ /**
1021
+ * Render the cycle-summary line naming what the precision rule DEMOTED.
1022
+ *
1023
+ * The counterpart of {@link summarizeHumanGateHolds}, and it exists for the
1024
+ * same reason: a mutation nobody can see afterwards is the problem this whole
1025
+ * area keeps having. A rule that quietly declines to honour half the marker
1026
+ * occurrences it sees reads exactly like a rule that saw none, so the count is
1027
+ * printed even when it is zero — measured across this repository's matching
1028
+ * bodies, 33 of 62 occurrences are mentions rather than declarations.
1029
+ * @param {unknown} demoted - How many occurrences were mentions, not declarations
1030
+ * @returns {string} One summary line
1031
+ */
1032
+ export function summarizeHumanGateMentions(demoted = 0) {
1033
+ const count = Number.isFinite(Number(demoted))
1034
+ ? Math.trunc(Number(demoted))
1035
+ : 0;
1036
+ const shown = count > 0 ? String(count) : "none";
1037
+ return `Marker mentions demoted (not declarations): ${shown}.`;
1038
+ }
1039
+
1040
+ export function summarizeHumanGateHolds(held = []) {
1041
+ const names = (Array.isArray(held) ? held : [])
1042
+ .map(item => trimmedString(item))
1043
+ .filter(name => name.length > 0);
1044
+ if (names.length === 0) return "Held for a person: none.";
1045
+ return `Held for a person (${String(names.length)}): ${names.join(", ")}.`;
1046
+ }
1047
+
1048
+ /**
1049
+ * Render the cycle-summary line naming what was RELEASED.
1050
+ *
1051
+ * The counterpart of {@link summarizeHumanGateHolds}, printed even when it is
1052
+ * zero. Without it a release path that has stopped working is indistinguishable
1053
+ * from a cycle where nothing needed releasing — which is exactly how the
1054
+ * missing inverse went unnoticed for as long as it did, and a fix that cannot
1055
+ * be observed to fire is a fix nobody can tell has regressed.
1056
+ * @param {readonly unknown[]} released - Item references released this cycle
1057
+ * @returns {string} One summary line
1058
+ */
1059
+ export function summarizeHumanGateReleases(released = []) {
1060
+ const names = (Array.isArray(released) ? released : [])
1061
+ .map(item => trimmedString(item))
1062
+ .filter(name => name.length > 0);
1063
+ if (names.length === 0) return "Released back to the queue: none.";
1064
+ return `Released back to the queue (${String(names.length)}): ${names.join(", ")}.`;
1065
+ }