@codyswann/lisa 2.151.0 → 2.152.1

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 (65) hide show
  1. package/dist/core/lisa.d.ts.map +1 -1
  2. package/dist/core/lisa.js +23 -11
  3. package/dist/core/lisa.js.map +1 -1
  4. package/dist/opencode/hooks-installer.d.ts +54 -0
  5. package/dist/opencode/hooks-installer.d.ts.map +1 -0
  6. package/dist/opencode/hooks-installer.js +300 -0
  7. package/dist/opencode/hooks-installer.js.map +1 -0
  8. package/dist/opencode/plugin-templates/lisa-block-migration-edits.ts +44 -0
  9. package/dist/opencode/plugin-templates/lisa-block-suppress-directives.ts +57 -0
  10. package/dist/opencode/plugin-templates/lisa-lint-on-edit.ts +53 -0
  11. package/dist/opencode/plugin-templates/lisa-rubocop-on-edit.ts +54 -0
  12. package/dist/opencode/plugin-templates/lisa-session-bootstrap.ts +76 -0
  13. package/dist/opencode/plugin-templates/lisa-sg-scan-on-edit.ts +50 -0
  14. package/package.json +2 -2
  15. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  16. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  17. package/plugins/lisa/skills/repair-intake/SKILL.md +57 -21
  18. package/plugins/lisa-agy/plugin.json +1 -1
  19. package/plugins/lisa-agy/skills/repair-intake/SKILL.md +57 -21
  20. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  21. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  22. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  23. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  24. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  25. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  26. package/plugins/lisa-copilot/skills/repair-intake/SKILL.md +57 -21
  27. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  28. package/plugins/lisa-cursor/skills/repair-intake/SKILL.md +57 -21
  29. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  30. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  31. package/plugins/lisa-expo-agy/plugin.json +1 -1
  32. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  33. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  34. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  35. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  36. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  37. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  38. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  39. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  40. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  41. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  42. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  43. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  44. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  45. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  46. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  47. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  48. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  49. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  50. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  51. package/plugins/lisa-rails-agy/plugin.json +1 -1
  52. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  53. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  54. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  55. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  56. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  57. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  58. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  59. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  60. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  61. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  62. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  63. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  64. package/plugins/src/base/skills/repair-intake/SKILL.md +57 -21
  65. package/scripts/copy-opencode-plugin-templates.mjs +29 -0
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.151.0",
3
+ "version": "2.152.1",
4
4
  "description": "Expo and React Native-specific skills, agents, rules, and MCP servers.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.151.0",
3
+ "version": "2.152.1",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.151.0",
3
+ "version": "2.152.1",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.151.0",
3
+ "version": "2.152.1",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.151.0",
3
+ "version": "2.152.1",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.151.0",
3
+ "version": "2.152.1",
4
4
  "description": "Harper/Fabric-specific Lisa rules for TypeScript component apps.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.151.0",
3
+ "version": "2.152.1",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.151.0",
3
+ "version": "2.152.1",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.151.0",
3
+ "version": "2.152.1",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.151.0",
3
+ "version": "2.152.1",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.151.0",
3
+ "version": "2.152.1",
4
4
  "description": "NestJS-specific skills and migration write-protection hooks.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.151.0",
3
+ "version": "2.152.1",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.151.0",
3
+ "version": "2.152.1",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.151.0",
3
+ "version": "2.152.1",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "2.151.0",
3
+ "version": "2.152.1",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "2.151.0",
3
+ "version": "2.152.1",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, across Claude and Codex.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "2.151.0",
3
+ "version": "2.152.1",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "2.151.0",
3
+ "version": "2.152.1",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "2.151.0",
3
+ "version": "2.152.1",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.151.0",
3
+ "version": "2.152.1",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.151.0",
3
+ "version": "2.152.1",
4
4
  "description": "Ruby on Rails-specific skills and hooks for RuboCop and ast-grep scanning on edit.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.151.0",
3
+ "version": "2.152.1",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.151.0",
3
+ "version": "2.152.1",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.151.0",
3
+ "version": "2.152.1",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.151.0",
3
+ "version": "2.152.1",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.151.0",
3
+ "version": "2.152.1",
4
4
  "description": "TypeScript-specific hooks for formatting, linting, and ast-grep scanning on edit.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.151.0",
3
+ "version": "2.152.1",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.151.0",
3
+ "version": "2.152.1",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.151.0",
3
+ "version": "2.152.1",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.151.0",
3
+ "version": "2.152.1",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.151.0",
3
+ "version": "2.152.1",
4
4
  "description": "Distributable LLM Wiki kernel — ingest, query, lint, and maintain a git-native markdown knowledge base across Claude and Codex.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.151.0",
3
+ "version": "2.152.1",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.151.0",
3
+ "version": "2.152.1",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.151.0",
3
+ "version": "2.152.1",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -229,6 +229,18 @@ An in-progress item (build `claimed`, PRD `in_review`) is **stalled** only if it
229
229
  observable activity newer than the `stale_after` threshold. `blocked` items are NOT gated on
230
230
  staleness — their repairability is judged on current blocker/answer state, not elapsed time.
231
231
 
232
+ A build `claimed` leaf whose linked PR has **already merged** (`state == MERGED`) is likewise NOT
233
+ gated on staleness. A merged PR is a settled terminal state, not in-flight work: the only thing
234
+ missing is the env transition build-intake never applied (its merge gate left the item `claimed`
235
+ because the merge landed after its agent returned). The recovery is judged on PR merge state, not
236
+ elapsed time — and crucially **post-merge activity does not defer it**. A freshly-merged PR keeps
237
+ producing activity that the signal below would otherwise read as keep-alive (a queued/in-progress
238
+ release or deploy check-run, a post-merge CodeRabbit summary comment), so gating merged-PR recovery
239
+ on staleness strands a *completed* leaf in `claimed` for as long as that activity keeps the clock
240
+ warm — exactly the failure that leaves a shipped Sub-task showing `status:in-progress` for a day
241
+ while its parents roll up against it. Recover it regardless of recent activity (Build `claimed`
242
+ decision tree step 0, and the dedicated high-confidence ordering bucket).
243
+
232
244
  ### Threshold resolution
233
245
 
234
246
  1. `$ARGUMENTS` `stale_after=<dur>` (one-off override) — always wins. Parse `Nh` / `Nm` / `Nd` /
@@ -263,6 +275,12 @@ keep-alive activity: it does not reset the staleness clock. The clock runs from
263
275
  progress event, so a PR that has been sitting failed/conflicted/awaiting-changes for longer than
264
276
  `stale_after` counts as stalled and is diagnosed below.
265
277
 
278
+ A **merged** linked PR is the same kind of non-keep-alive signal, in the other direction: the work
279
+ is settled and complete, so its post-merge check-runs and summary comments must NOT count as
280
+ keep-alive either. A build `claimed` leaf with a merged PR is recovered regardless of the staleness
281
+ clock (see the Staleness model note above and the dedicated ordering bucket); it is never recorded
282
+ `active` and skipped on the strength of post-merge activity.
283
+
266
284
  If a provider cannot expose any reliable timestamp, do **not** auto-resume its in-progress
267
285
  items unless the caller passed `stale_after=0`. (Dependency-cleared `blocked` repair still
268
286
  proceeds — it is judged on blocker state, not time.)
@@ -276,17 +294,24 @@ recorded under Errors. Do not stop after the first write; the cap is the batch b
276
294
 
277
295
  ### Build `claimed` (stalled in-progress) → diagnose blocker, else resume in place
278
296
 
279
- After the staleness gate passes, **first diagnose why it stalled** by inspecting the item's PRs and
280
- deploys (see "Stuck-cause diagnosis" below). A stalled build usually stalled for a concrete external
281
- reason, and re-dispatching the agent at it will not fix a PR that cannot merge or a deploy that
282
- failed it just churns.
297
+ **First check for an already-merged PR this check is NOT gated on staleness.** Read the item's
298
+ linked PR state before applying the staleness gate (see "Stuck-cause diagnosis" step 1–2 for
299
+ discovery). If `state == MERGED`, recover it immediately via step 0's merged-PR arm regardless of
300
+ elapsed time or recent post-merge activity (per the Staleness model's merged-PR exemption): a merged
301
+ PR is a completed leaf, and deferring it behind the staleness clock is what strands shipped work in
302
+ `claimed`.
303
+
304
+ Only if the PR is **not** merged does the staleness gate apply. Once it passes, **diagnose why it
305
+ stalled** by inspecting the item's PRs and deploys (see "Stuck-cause diagnosis" below). A stalled
306
+ build usually stalled for a concrete external reason, and re-dispatching the agent at it will not fix
307
+ a PR that cannot merge or a deploy that failed — it just churns.
283
308
 
284
309
  0. **Diagnose PR & deploy state.** Run "Stuck-cause diagnosis" below. It resolves, in order:
285
- - **PR already merged** → the build effectively completed; the vendor build-intake's merge gate
286
- left the item `claimed` because the merge landed after its agent returned. Do **not** re-dispatch
287
- or file anything — apply the scanner's post-agent env-resolved `claimed → done` transition
288
- directly (step 2 below, env-resolved), and record it. This is the recovery arm for build-intake
289
- leaving merged-but-unadvanced items in `claimed`.
310
+ - **PR already merged** (checked first, staleness-exempt) → the build effectively completed; the
311
+ vendor build-intake's merge gate left the item `claimed` because the merge landed after its agent
312
+ returned. Do **not** re-dispatch or file anything — apply the scanner's post-agent env-resolved
313
+ `claimed → done` transition directly (step 2 below, env-resolved), and record it. This is the
314
+ recovery arm for build-intake leaving merged-but-unadvanced items in `claimed`.
290
315
  - **PR only behind its base (a needed rebase)** → mechanically resolvable, **not** a human blocker.
291
316
  Re-sync the branch in place so the already-enabled auto-merge can land (see diagnosis step 3).
292
317
  Keep the item `claimed`; a later cycle confirms the merge and transitions. Do **not** file a fix
@@ -328,10 +353,15 @@ Run this for every stalled `claimed` build item **before** considering an agent
328
353
  goal is to distinguish "work died mid-flight, just resume it" from "work is blocked on a concrete
329
354
  external state that resuming the agent cannot fix."
330
355
 
331
- **1. Find the associated PR(s) and deploy(s).** From the item's linked PRs (GitHub: remote/dev
332
- links and `gh pr list --search <issue-ref>`; JIRA: dev-status / remote links; Linear: attachments
333
- and git-branch links) and the deploy(s) for the resulting merge (the env-keyed `deploy.branches`
334
- mapping from `config-resolution`). Read each PR with the vendor's native state, e.g. GitHub
356
+ **1. Find the associated PR(s) and deploy(s).** From the item's linked PRs (GitHub: prefer the
357
+ native dev-link surface — `gh issue view <n> --json closedByPullRequestsReferences` which lists
358
+ merged PRs that closed the issue, then `gh pr list --search <issue-ref> --state all`; JIRA:
359
+ dev-status / remote links; Linear: attachments and git-branch links) and the deploy(s) for the
360
+ resulting merge (the env-keyed `deploy.branches` mapping from `config-resolution`). The `--state all`
361
+ is load-bearing: `gh pr list --search` defaults to `--state open`, so a **merged** (closed) PR is
362
+ invisible on that surface — the exact state this recovery path exists to catch. A merged PR linked
363
+ only via search (no `Closes #` / native dev link) would otherwise never be discovered, and the leaf
364
+ would never recover. Read each PR with the vendor's native state, e.g. GitHub
335
365
  `gh pr view <n> --json state,mergedAt,mergeable,mergeStateStatus,reviewDecision,statusCheckRollup,comments,reviews`.
336
366
 
337
367
  **2. PR already merged → recover, don't re-dispatch.** If `state == MERGED`, the build is effectively
@@ -852,18 +882,24 @@ It MUST NOT:
852
882
  for the detected lifecycle(s), up to `max_candidates`, via the Access layer reads.
853
883
  3. **Order deterministically**, highest repair-confidence first:
854
884
  1. terminal-labeled items that only need native close / complete / resolve,
855
- 2. GitHub parents (PRDs missing native links for generated top-level work, or build Epic/Story
885
+ 2. build `claimed` leaves whose linked PR is **already merged** apply the env-resolved
886
+ `claimed → done` close-out (staleness-exempt; no re-dispatch). This MUST run before any rollup
887
+ bucket: a merged-PR leaf is a settled terminal state, and recovering it first means its parent
888
+ rolls up to its true derived state in the **same** cycle. If this ran after rollup (or last,
889
+ among generic stalled items), the parent would be reconciled against a not-yet-closed child and
890
+ the shipped leaf would linger another cron pass — the failure this ordering exists to prevent,
891
+ 3. GitHub parents (PRDs missing native links for generated top-level work, or build Epic/Story
856
892
  containers missing native links for prose/hierarchy children) needing structure-only repair,
857
- 3. rollup parents/PRDs whose child sets are all terminal (close-out),
858
- 4. rollup parents whose children have advanced to an intermediate env, or stale-`ready`
893
+ 4. rollup parents/PRDs whose child sets are all terminal (close-out),
894
+ 5. rollup parents whose children have advanced to an intermediate env, or stale-`ready`
859
895
  containers, that need their derived state applied (status-only reconciliation, no native
860
896
  close),
861
- 5. `blocked` items whose dependencies are now **cleared** (safe, high-value, one-cycle wins),
862
- 6. `blocked` items whose **validation / quality-gate self-block now re-validates PASS** —
897
+ 6. `blocked` items whose dependencies are now **cleared** (safe, high-value, one-cycle wins),
898
+ 7. `blocked` items whose **validation / quality-gate self-block now re-validates PASS** —
863
899
  a human filled in the missing sections (Class B; equally safe and high-value),
864
- 7. `blocked` items with **new clarifying answers**,
865
- 8. GitHub missing-official-label normalization candidates,
866
- 9. **stalled** in-progress items, oldest activity first.
900
+ 8. `blocked` items with **new clarifying answers**,
901
+ 9. GitHub missing-official-label normalization candidates,
902
+ 10. **stalled** in-progress items (PR not merged), oldest activity first.
867
903
  4. **Walk the ordered list**, evaluating each candidate (terminal close-out, rollup child tally,
868
904
  staleness, dependency, answer checks), and repair **every** candidate that is actionable inside
869
905
  the `max_candidates` cap. Continue after successful writes and after per-item errors.
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Copy OpenCode plugin templates next to the compiled OpenCode hooks installer.
4
+ *
5
+ * `src/opencode/plugin-templates/*.ts` are NOT app source — they run under
6
+ * OpenCode's Bun runtime inside a host project's `.opencode/plugin/`, so they
7
+ * are excluded from this repo's tsconfig (tsc never emits them). The installer
8
+ * (`dist/opencode/hooks-installer.js`) copies them verbatim into a host project
9
+ * at install time, resolving them from `dist/opencode/plugin-templates/`. This
10
+ * step puts the source `.ts` files there. Mirrors `copy-codex-scripts.mjs`.
11
+ */
12
+ import fs from "node:fs";
13
+ import path from "node:path";
14
+
15
+ const repoRoot = path.resolve(import.meta.dirname, "..");
16
+ const sourceDir = path.join(repoRoot, "src", "opencode", "plugin-templates");
17
+ const destDir = path.join(repoRoot, "dist", "opencode", "plugin-templates");
18
+
19
+ fs.rmSync(destDir, { recursive: true, force: true });
20
+ fs.mkdirSync(destDir, { recursive: true });
21
+
22
+ for (const entry of fs.readdirSync(sourceDir, { withFileTypes: true })) {
23
+ if (!entry.isFile() || !entry.name.endsWith(".ts")) {
24
+ continue;
25
+ }
26
+ const sourcePath = path.join(sourceDir, entry.name);
27
+ const destPath = path.join(destDir, entry.name);
28
+ fs.copyFileSync(sourcePath, destPath);
29
+ }