@codyswann/lisa 4.27.2 → 4.27.3

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 (124) hide show
  1. package/dist/core/nightly-e2e-guard-behavior-certificate.js +2 -2
  2. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  3. package/dist/core/upstream-evidence-manifest.js +21 -11
  4. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  5. package/package.json +3 -3
  6. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  7. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  8. package/plugins/lisa/.codex-plugin/skills/lisa-linear-access/SKILL.md +84 -1
  9. package/plugins/lisa/.codex-plugin/skills/lisa-linear-build-intake/SKILL.md +3 -3
  10. package/plugins/lisa/.codex-plugin/skills/lisa-linear-claim/SKILL.md +2 -2
  11. package/plugins/lisa/.codex-plugin/skills/lisa-linear-evidence/SKILL.md +4 -4
  12. package/plugins/lisa/.codex-plugin/skills/lisa-linear-sync/SKILL.md +5 -2
  13. package/plugins/lisa/.codex-plugin/skills/lisa-linear-write-issue/SKILL.md +5 -5
  14. package/plugins/lisa/.codex-plugin/skills/lisa-repair-intake/SKILL.md +3 -2
  15. package/plugins/lisa/.codex-plugin/skills/lisa-setup-linear/SKILL.md +11 -1
  16. package/plugins/lisa/.codex-plugin/skills/lisa-validate-tracker-mapping/SKILL.md +3 -1
  17. package/plugins/lisa/agents/linear-agent.md +12 -12
  18. package/plugins/lisa/agents/linear-build-intake.md +1 -1
  19. package/plugins/lisa/scripts/linear-state-write-target.mjs +362 -0
  20. package/plugins/lisa/skills/lisa-linear-access/SKILL.md +84 -1
  21. package/plugins/lisa/skills/lisa-linear-build-intake/SKILL.md +3 -3
  22. package/plugins/lisa/skills/lisa-linear-claim/SKILL.md +2 -2
  23. package/plugins/lisa/skills/lisa-linear-evidence/SKILL.md +5 -5
  24. package/plugins/lisa/skills/lisa-linear-sync/SKILL.md +5 -2
  25. package/plugins/lisa/skills/lisa-linear-write-issue/SKILL.md +5 -5
  26. package/plugins/lisa/skills/lisa-repair-intake/SKILL.md +3 -2
  27. package/plugins/lisa/skills/lisa-setup-linear/SKILL.md +11 -1
  28. package/plugins/lisa/skills/lisa-validate-tracker-mapping/SKILL.md +3 -1
  29. package/plugins/lisa-agy/agents/linear-agent.md +12 -12
  30. package/plugins/lisa-agy/agents/linear-build-intake.md +1 -1
  31. package/plugins/lisa-agy/plugin.json +1 -1
  32. package/plugins/lisa-agy/scripts/linear-state-write-target.mjs +362 -0
  33. package/plugins/lisa-agy/skills/lisa-linear-access/SKILL.md +84 -1
  34. package/plugins/lisa-agy/skills/lisa-linear-build-intake/SKILL.md +3 -3
  35. package/plugins/lisa-agy/skills/lisa-linear-claim/SKILL.md +2 -2
  36. package/plugins/lisa-agy/skills/lisa-linear-evidence/SKILL.md +5 -5
  37. package/plugins/lisa-agy/skills/lisa-linear-sync/SKILL.md +5 -2
  38. package/plugins/lisa-agy/skills/lisa-linear-write-issue/SKILL.md +5 -5
  39. package/plugins/lisa-agy/skills/lisa-repair-intake/SKILL.md +3 -2
  40. package/plugins/lisa-agy/skills/lisa-setup-linear/SKILL.md +11 -1
  41. package/plugins/lisa-agy/skills/lisa-validate-tracker-mapping/SKILL.md +3 -1
  42. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  43. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  44. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  45. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  46. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  47. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  48. package/plugins/lisa-copilot/agents/linear-agent.agent.md +12 -12
  49. package/plugins/lisa-copilot/agents/linear-build-intake.agent.md +1 -1
  50. package/plugins/lisa-copilot/scripts/linear-state-write-target.mjs +362 -0
  51. package/plugins/lisa-copilot/skills/lisa-linear-access/SKILL.md +84 -1
  52. package/plugins/lisa-copilot/skills/lisa-linear-build-intake/SKILL.md +3 -3
  53. package/plugins/lisa-copilot/skills/lisa-linear-claim/SKILL.md +2 -2
  54. package/plugins/lisa-copilot/skills/lisa-linear-evidence/SKILL.md +5 -5
  55. package/plugins/lisa-copilot/skills/lisa-linear-sync/SKILL.md +5 -2
  56. package/plugins/lisa-copilot/skills/lisa-linear-write-issue/SKILL.md +5 -5
  57. package/plugins/lisa-copilot/skills/lisa-repair-intake/SKILL.md +3 -2
  58. package/plugins/lisa-copilot/skills/lisa-setup-linear/SKILL.md +11 -1
  59. package/plugins/lisa-copilot/skills/lisa-validate-tracker-mapping/SKILL.md +3 -1
  60. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  61. package/plugins/lisa-cursor/agents/linear-agent.md +12 -12
  62. package/plugins/lisa-cursor/agents/linear-build-intake.md +1 -1
  63. package/plugins/lisa-cursor/scripts/linear-state-write-target.mjs +362 -0
  64. package/plugins/lisa-cursor/skills/lisa-linear-access/SKILL.md +84 -1
  65. package/plugins/lisa-cursor/skills/lisa-linear-build-intake/SKILL.md +3 -3
  66. package/plugins/lisa-cursor/skills/lisa-linear-claim/SKILL.md +2 -2
  67. package/plugins/lisa-cursor/skills/lisa-linear-evidence/SKILL.md +5 -5
  68. package/plugins/lisa-cursor/skills/lisa-linear-sync/SKILL.md +5 -2
  69. package/plugins/lisa-cursor/skills/lisa-linear-write-issue/SKILL.md +5 -5
  70. package/plugins/lisa-cursor/skills/lisa-repair-intake/SKILL.md +3 -2
  71. package/plugins/lisa-cursor/skills/lisa-setup-linear/SKILL.md +11 -1
  72. package/plugins/lisa-cursor/skills/lisa-validate-tracker-mapping/SKILL.md +3 -1
  73. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  74. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  75. package/plugins/lisa-expo-agy/plugin.json +1 -1
  76. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  77. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  78. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  79. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  80. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  81. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  82. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  83. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  84. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  85. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  86. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  87. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  88. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  89. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  90. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  91. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  92. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  93. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  94. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  95. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  96. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  97. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  98. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  99. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  100. package/plugins/lisa-rails-agy/plugin.json +1 -1
  101. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  102. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  103. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  104. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  105. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  106. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  107. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  108. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  109. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  110. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  111. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  112. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  113. package/plugins/src/base/agents/linear-agent.md +12 -12
  114. package/plugins/src/base/agents/linear-build-intake.md +1 -1
  115. package/plugins/src/base/scripts/linear-state-write-target.mjs +362 -0
  116. package/plugins/src/base/skills/lisa-linear-access/SKILL.md +84 -1
  117. package/plugins/src/base/skills/lisa-linear-build-intake/SKILL.md +3 -3
  118. package/plugins/src/base/skills/lisa-linear-claim/SKILL.md +2 -2
  119. package/plugins/src/base/skills/lisa-linear-evidence/SKILL.md +5 -5
  120. package/plugins/src/base/skills/lisa-linear-sync/SKILL.md +5 -2
  121. package/plugins/src/base/skills/lisa-linear-write-issue/SKILL.md +5 -5
  122. package/plugins/src/base/skills/lisa-repair-intake/SKILL.md +3 -2
  123. package/plugins/src/base/skills/lisa-setup-linear/SKILL.md +11 -1
  124. package/plugins/src/base/skills/lisa-validate-tracker-mapping/SKILL.md +3 -1
@@ -1,12 +1,12 @@
1
1
  ---
2
2
  name: lisa-linear-evidence
3
- description: "Uploads text evidence to the GitHub `pr-assets` release, updates the PR description, posts a comment on the originating Linear Issue with code blocks, and transitions the Issue from the configured `claimed` label to the configured `review` label. Reusable by any skill that captures evidence and generates evidence/comment.txt + evidence/code-blocks.md. Linear counterpart of lisa-jira-evidence and lisa-github-evidence."
3
+ description: "Uploads text evidence to the GitHub `pr-assets` release, updates the PR description, posts a comment on the originating Linear Issue with code blocks, and transitions the Issue from the configured `claimed` workflow state to the configured `review` workflow state. Reusable by any skill that captures evidence and generates evidence/comment.txt + evidence/code-blocks.md. Linear counterpart of lisa-jira-evidence and lisa-github-evidence."
4
4
  allowed-tools: ["Bash", "Skill"]
5
5
  ---
6
6
 
7
7
  # Linear Evidence: $ARGUMENTS
8
8
 
9
- Post verification evidence to a Linear Issue and transition it from the configured `claimed` build label to the configured `review` build label. This skill is the destination of the `lisa-tracker-evidence` shim when `tracker = "linear"`.
9
+ Post verification evidence to a Linear Issue and transition it from the configured `claimed` workflow **state** to the configured `review` workflow **state**. Linear's build lane is state-driven, not label-driven — `linear.labels.build.{ready,claimed,review,done}` is inert and nothing reads it (see `lisa-validate-tracker-mapping`). This skill is the destination of the `lisa-tracker-evidence` shim when `tracker = "linear"`.
10
10
 
11
11
  `$ARGUMENTS` is the Linear Issue identifier (e.g. `ENG-123`) and the path to the evidence directory. Caller passes both: `<IDENTIFIER> <evidence-dir>`.
12
12
 
@@ -104,15 +104,15 @@ Linear comments support markdown including `<details>` collapsibles, fenced code
104
104
 
105
105
  **If `$REVIEW` is empty, skip this phase entirely** — post the evidence comment and leave the Issue in `$CLAIMED`. Report it plainly (`No linear.workflow.review configured; leaving <ID> in its current (claimed) state`) so the skip is visible rather than silent. This is a supported configuration, not a failure.
106
106
 
107
- When `$REVIEW` is non-empty, update labels via `lisa-linear-access operation: save-issue` to remove `$CLAIMED` and add `$REVIEW`. Resolve label IDs first via `lisa-linear-access operation: list-issue-labels` (create the label via `create_issue_label` if it doesn't exist on the team).
107
+ When `$REVIEW` is non-empty, invoke `lisa-linear-access operation: save-issue lifecycle_role: review`. That is the whole transition: the Linear build lane is the native workflow **state**, so there is no accompanying label move — do not remove a `claimed` label or add a `review` one, and do not create either. Those keys are inert.
108
108
 
109
- The native Linear `state` field is updated to `$REVIEW` **only when the resolver returned it from config**. Never resolve the state by searching the team for something review-shaped: on a board with more than one review-ish state that picks by position, not by intent, and the states most likely to be found that way are the human-only ones a project deliberately kept out of its config.
109
+ The access layer resolves `$REVIEW`'s exact configured state itself and dispatches that ID; this skill never hands it one. Never resolve the state by searching the team for something review-shaped: on a board with more than one review-ish state that picks by position, not by intent, and the states most likely to be found that way are the human-only ones a project deliberately kept out of its config. The access layer refuses such a write outright — an unbound optional `review` is a refusal there, not a guess.
110
110
 
111
111
  ## Phase 6 — Report
112
112
 
113
113
  Return:
114
114
 
115
- - Linear Issue URL with new label state
115
+ - Linear Issue URL with its new workflow state
116
116
  - PR URL (if updated)
117
117
  - List of uploaded evidence file URLs
118
118
 
@@ -122,7 +122,7 @@ Run it whenever the resolved env is **intermediate** (below the production termi
122
122
 
123
123
  1. Resolve the merged PR's base branch to its env via `.lisa.config.json` `deploy.branches` (`config-resolution`). If it maps to the production/terminal `done`, this phase is a **no-op** — native completion is correct there.
124
124
  2. **Uniform / single-environment no-op.** When the project's env-keyed `done` map is uniform — every environment resolves to the same `Done`, as in this repo (`production: main` only) — dev-merge == terminal, so native completion is correct. Do nothing. Only a **non-uniform** env→`done` map (distinct `On Dev`/`On Stg`/`Done` rungs) can desync.
125
- 3. Otherwise (non-uniform map, resolved env intermediate): re-read the Issue's `state`. If it sits in a `completed`-typed state while the derived role is a lower env rung, **re-open** the native state by moving it back to the correct env rung (via `lisa-linear-access operation: save-issue`) and post a short `[lisa-linear-sync]` reconciliation comment **naming the likely cause** — a live `merge → Done` git automation, or a magic word in the PR body. This applies the `leaf-only-lifecycle` "Terminal native closure" rule — closure fires **only** at the production terminal `done`. Cite the rule by slug; do not restate it.
125
+ 3. Otherwise (non-uniform map, resolved env intermediate): re-read the Issue's `state`. If it sits in a `completed`-typed state while the derived role is a lower env rung, **re-open** the native state by moving it back to the correct env rung (via `lisa-linear-access operation: save-issue lifecycle_role: done env: <resolved-rung>` — the backstop names the role and the rung like every other lifecycle write; it never re-derives a state ID itself) and post a short `[lisa-linear-sync]` reconciliation comment **naming the likely cause** — a live `merge → Done` git automation, or a magic word in the PR body. This applies the `leaf-only-lifecycle` "Terminal native closure" rule — closure fires **only** at the production terminal `done`. Cite the rule by slug; do not restate it.
126
126
  4. **Safe default.** If the true terminal cannot be resolved (ambiguous env or unresolvable `done` map), do not change the `state` — post a `[lisa-linear-sync]` reconciliation-suggestion comment and leave it untouched, mirroring the Phase 5 safe default.
127
127
 
128
128
  ## Phase 5 — Parent Status Rollup (`--rollup`)
@@ -148,7 +148,10 @@ When the caller passes `--rollup`, this skill **derives a parent/container's wor
148
148
 
149
149
  **Single-environment collapse (this repo).** The env rungs resolve via the env-keyed `done` logic in `config-resolution`. In this repo `deploy.branches` declares only `production: main`, so `done` collapses to the single `Done` state, the only env rung is production, and the lifecycle is `ready → claimed → done` with **no** dev/staging promotion hops and no configured `review` rung; the rollup never resolves a dev or staging `done`. Multi-environment projects keep the env-keyed map and roll a parent up to the intermediate env states.
150
150
 
151
- **Apply the derived state** via `lisa-linear-access operation: save-issue` (Project or Issue), setting the parent's `stateId` to the derived role. Post an idempotent rollup comment naming the derived state and the child tally. Because the terminal `done` state is itself typed `completed`, a parent rolled to terminal is natively closed by the same write — there is no second closure step. **Safe default:** if the derived terminal cannot be resolved (ambiguous required-set or unresolvable env `done`), do not guess — post the derived suggestion as a comment and leave the parent's state untouched.
151
+ **Apply the derived state**, naming the derived role — the access layer resolves the configured state for that role and dispatches it. This skill never computes a `stateId` of its own; a role the project never bound is refused there rather than approximated here.
152
+
153
+ - **Issue parent** → `lisa-linear-access operation: save-issue lifecycle_role: <derived role> [env: <key>]`. An Issue's lane IS a team workflow state, so this is the guarded write.
154
+ - **Project parent** → `lisa-linear-access operation: save-project`. A Linear Project has no team workflow state — it carries its own coarse project status — so there is no `stateId` and no `lifecycle_role` to declare. Map the derived role onto the Project's own status and say in the rollup comment which role produced it. Do not send `lifecycle_role` here; the workflow-state guard governs Issues and has nothing to resolve for a Project. Post an idempotent rollup comment naming the derived state and the child tally. Because the terminal `done` state is itself typed `completed`, a parent rolled to terminal is natively closed by the same write — there is no second closure step. **Safe default:** if the derived terminal cannot be resolved (ambiguous required-set or unresolvable env `done`), do not guess — post the derived suggestion as a comment and leave the parent's state untouched.
152
155
 
153
156
  ## Rules
154
157
 
@@ -31,7 +31,7 @@ Linear's data model maps Epic / Story / Sub-task to **different entity types**.
31
31
  | `Bug` | **Issue** | `lisa-linear-access operation: save-issue` | `projectId` if part of an Epic; else top-level |
32
32
  | `Spike` | **Issue** | `lisa-linear-access operation: save-issue` | `projectId` if part of an Epic; else top-level |
33
33
 
34
- The build lifecycle uses native **workflow states** (`Ready`, `In Progress`, `In Review`, `Blocked`, `On Dev`, `On Stg`, `Done`), resolved per role from `linear.workflow` — see "Why Linear uses states, not labels" in `config-resolution`. A new **leaf** work unit is created in the configured `ready` state only on explicit `build_ready: true`; omitted or `false` leaves it in the team's default backlog state, and a container is never put in `ready` at all (see the Build-ready control input below).
34
+ The build lifecycle uses native **workflow states** (`Ready`, `In Progress`, `Blocked`, `On Dev`, `On Stg`, `Done`, plus an optional review state a project may bind), resolved per role from `linear.workflow` — see "Why Linear uses states, not labels" in `config-resolution`. A new **leaf** work unit is created in the configured `ready` state only on explicit `build_ready: true`; omitted or `false` leaves it in the team's default backlog state, and a container is never put in `ready` at all (see the Build-ready control input below).
35
35
 
36
36
  ## Phase 1 — Resolve Intent
37
37
 
@@ -271,7 +271,7 @@ For Bug / Task / Sub-task, ensure the summary is prefixed with `[<repo-name>]`.
271
271
 
272
272
  - **Omitted** → **not build-ready**: the leaf is left in the team's default backlog state. Ready is an explicit claim, never a vendor default. **This is a breaking change** — Linear previously created a leaf directly in the `ready` state on omission, so a caller that relied on that must now pass `build_ready: true`.
273
273
  - **`build_ready: false`** → create the leaf **without** the `ready` state, leaving it in the team's default backlog state so it waits for a human to review and promote it into the queue.
274
- - **`build_ready: true`** → transition the **leaf** to the resolved `ready` state (`.linear.workflow.ready`) so `lisa-intake` / `lisa-linear-build-intake` auto-picks it up. Best-effort: if the state cannot be resolved or the transition is rejected, do not fail the write — leave the Issue in its default state and record the reason.
274
+ - **`build_ready: true`** → declare `lifecycle_role: ready` so the access layer resolves `.linear.workflow.ready` and places the leaf there, and `lisa-intake` / `lisa-linear-build-intake` auto-picks it up. Best-effort **for the lane, never for the guard**: an access-layer refusal (`ready` unbound, absent from the team, ambiguous) is fail-closed and is never worked around here — surface its message verbatim, do not fail the write, leave the Issue in its default state and record the reason. The Issue is still created; what is refused is the unproven lane placement, which is the safe half to lose.
275
275
 
276
276
  **A filing with neither is an incomplete handoff.** A leaf that is not build-ready must carry an explicit `human_gate: "<why a human must judge this first>"`; nothing in the ready lane means nothing ever claims it. When `human_gate` is supplied, stamp the hold on the Issue so it is auditable — a visible line plus the verbatim marker:
277
277
 
@@ -306,7 +306,7 @@ If the validator reports `PASS`, continue to Phase 6.
306
306
 
307
307
  ### CREATE — Story / Task / Bug / Spike / Improvement (Issue with projectId)
308
308
 
309
- 1. Resolve any required Issue labels (`type:<Kind>`, `repo:<name>`, `component:<name>`, `prd-intake-feedback` only if this is a sentinel issue) via `lisa-linear-access operation: list-issue-labels` (create via `lisa-linear-access operation: create-issue-label` if missing). Separately resolve the `ready` **state** id via `lisa-linear-access operation: list-workflow-states`, and set it as `stateId` only for a **leaf** work unit and only when `build_ready` is not `false` — omit it for a container, and for a `build_ready: false` leaf which then waits in the default backlog state for a human to promote it.
309
+ 1. Resolve any required Issue labels (`type:<Kind>`, `repo:<name>`, `component:<name>`, `prd-intake-feedback` only if this is a sentinel issue) via `lisa-linear-access operation: list-issue-labels` (create via `lisa-linear-access operation: create-issue-label` if missing). Separately, place a **leaf** work unit in the `ready` lane by passing `lifecycle_role: ready` on the create call below — and only on **explicit `build_ready: true`**, per the Build-ready control input below. Omit the role for a container, and for a leaf whose `build_ready` is `false` or omitted, which then waits in the team's default backlog state for a human to promote it. Ready is an explicit claim, never an omission's default. Never resolve a state ID here and pass it as `stateId`: the access layer resolves the configured `ready` state itself and refuses anything else.
310
310
  2. Call `lisa-linear-access operation: save-issue` with: `team` (teamId), `title` (summary), `description` (markdown), `projectId` (the Epic Project), `priority` (0–4), `estimate`, `labelIds`, `assignee` if known.
311
311
  3. Capture the returned identifier (e.g. `ENG-123`) — Phase 4 sub-tasks need it as `parentId`.
312
312
  4. Add relationships from Phase 4b via `save_issue` (relations field) or paired relation calls.
@@ -314,8 +314,8 @@ If the validator reports `PASS`, continue to Phase 6.
314
314
 
315
315
  ### CREATE — Sub-task (Issue with parentId)
316
316
 
317
- 1. Resolve labels as above.
318
- 2. Call `lisa-linear-access operation: save-issue` with: `team` (teamId), `title` (`[<repo>] <summary>` prefix is mandatory), `description` (markdown), `parentId` (the Story Issue ID), `projectId` (inherit from parent), `priority`, `estimate`, `labelIds`.
317
+ 1. Resolve labels as above. A Sub-task is a **leaf**, so the same ready-lane rule applies: pass `lifecycle_role: ready` on the create call below only on explicit `build_ready: true`, and omit it otherwise. Never resolve a state ID here.
318
+ 2. Call `lisa-linear-access operation: save-issue` with: `team` (teamId), `title` (`[<repo>] <summary>` prefix is mandatory), `description` (markdown), `parentId` (the Story Issue ID), `projectId` (inherit from parent), `priority`, `estimate`, `labelIds`, plus `lifecycle_role: ready` when `build_ready` is explicitly `true`.
319
319
  3. Capture identifier.
320
320
  4. Add relationships via Phase 4b.
321
321
 
@@ -729,8 +729,9 @@ node "${CLAUDE_PLUGIN_ROOT}/scripts/rollup-blocker-classification.mjs" \
729
729
 
730
730
  3. **If the derived state differs from the parent's current state, apply it** via the vendor's
731
731
  lifecycle write: a JIRA transition; a GitHub label swap in the item's own lifecycle namespace;
732
- or a Linear `save-issue` update that writes the resolved workflow `stateId`, never a lifecycle
733
- label. For GitHub, resolve the lane before writing: PRD parents use the configured `prd.*`
732
+ or a Linear `save-issue lifecycle_role: <derived role> [env: <key>]` update, which resolves the
733
+ configured workflow state in the access layer and writes that — never a lifecycle label, and
734
+ never a state ID this skill picked. For GitHub, resolve the lane before writing: PRD parents use the configured `prd.*`
734
735
  roles, while build tickets use the configured build roles. Keep exactly one lifecycle label in
735
736
  that selected namespace and never substitute or overlap the other namespace. When applying any
736
737
  of these writes, remove conflicting stale lifecycle roles — **including a stale `ready`** the
@@ -243,12 +243,22 @@ Enumerate the team's states with `lisa-linear-access operation: list-workflow-st
243
243
  |------|---------------|--------|--------------------------|
244
244
  | `ready` | `Ready` | `unstarted` | **no — must be created or mapped** |
245
245
  | `claimed` | `In Progress` | `started` | yes |
246
- | `review` | `In Review` | `started` | yes |
246
+ | `review` | **none — optional, never seeded** | `started` | n/a |
247
247
  | `blocked` | `Blocked` | `unstarted` | **no — must be created or mapped** |
248
248
  | `done.dev` | `On Dev` | `started` | **no — must be created or mapped** |
249
249
  | `done.staging` | `On Stg` | `started` | **no — must be created or mapped** |
250
250
  | `done.production` | `Done` | `completed` | yes |
251
251
 
252
+ **`review` is OPTIONAL and this setup NEVER binds it unprompted.** It has no
253
+ default state, so there is nothing to resolve unless the user asks for a review
254
+ hold; leaving `linear.workflow.review` absent is a supported configuration
255
+ meaning the project runs no agent review step, and lifecycle skills skip that
256
+ transition entirely (`config-resolution` R1). Writing a binding a project did
257
+ not ask for is how agent-owned work reaches a human-only review lane — the
258
+ stock `In Review` state a team happens to ship is not evidence the project
259
+ wants one. Offer it only on an explicit request, and resolve it through the
260
+ same four-rung cascade as any other role.
261
+
252
262
  **The env rungs are deliberately `started`, not `completed`.** `On Dev` and `On Stg` mean "merged and deployed *that far*" — work that is emphatically not finished. Typing them `completed` would make Linear treat them as closed: they would leave the active board, stop counting in cycles, and re-create the exact premature-closure problem this model exists to fix. Only `done.production` is `completed`.
253
263
 
254
264
  **Position them between `In Review` and `Done`** so the board reads left-to-right in real lifecycle order. A team that orders its board differently can pass its own `position`.
@@ -71,7 +71,9 @@ Resolve the **effective** role → name mapping using the same defaults `/lisa:i
71
71
  - **Missing / empty tracker**: report `UNRESOLVABLE` with setup guidance (`/lisa:setup:jira`, `/lisa:setup:github`, or `/lisa:setup:linear`). Do not default to JIRA.
72
72
  - **JIRA build workflow** (`jira.workflow`): `ready`, `claimed`, optional `review`, `blocked`, and each `done.<env>` (`dev` / `staging` / `production`). Defaults: `Ready`, `In Progress`, `Code Review`, `Blocked`, `{dev: "On Dev", staging: "On Stg", production: "Done"}`.
73
73
  - **GitHub build/prd labels** (`github.labels.build`, `github.labels.prd`): each configured label string.
74
- - **Linear build workflow** (`linear.workflow`): `ready`, `claimed`, `review`, `blocked`, and each `done.<env>` — native workflow **states**, the Linear analogue of `jira.workflow`, not of `github.labels`. Defaults: `Ready`, `In Progress`, `In Review`, `Blocked`, `{dev: "On Dev", staging: "On Stg", production: "Done"}`.
74
+ - **Linear build workflow** (`linear.workflow`): `ready`, `claimed`, `blocked`, and each `done.<env>` are required; `review` is optional — native workflow **states**, the Linear analogue of `jira.workflow`, not of `github.labels`. Defaults: `Ready`, `In Progress`, `Blocked`, `{dev: "On Dev", staging: "On Stg", production: "Done"}`. **`review` has no default**: an absent `review` is a valid configuration meaning the project skips that transition, not drift to report.
75
+
76
+ Report a **missing required binding as invalid** rather than auditing the default in its place. The defaults above are what `/lisa:setup:linear` and `lisa sync` write INTO a config; they are not a resolution tier, and the write path has none — `lisa-linear-access` refuses a state write whose role resolves to nothing. Validating an unbound `ready`/`claimed`/`blocked`/`done` against `Ready`/`In Progress`/`Blocked`/`Done` would pass a config whose every lifecycle write later refuses, which is the shape of a green check on a broken project.
75
77
  - **Linear labels** (`linear.labels`): the `prd.*` map plus the one surviving build-lane key, the `human_needed` marker (`linear.labels.build.human_needed`). A config that predates the state model may still carry `ready` / `claimed` / `blocked` / `done` under `linear.labels.build`; those are **inert** — nothing reads them. Do not audit them against the live label set, and do not report them as drift. Report them once as a migration note pointing at `/lisa:setup:linear`, which removes them.
76
78
  - **Notion PRD values** (`notion.values`): each configured select-option value, validated against the `notion.statusProperty` property's options.
77
79
  - **Confluence PRD parents** (`confluence.parents`): each configured parent page id, validated by existence.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "4.27.2",
3
+ "version": "4.27.3",
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": "4.27.2",
3
+ "version": "4.27.3",
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": "4.27.2",
3
+ "version": "4.27.3",
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": "4.27.2",
3
+ "version": "4.27.3",
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": "4.27.2",
3
+ "version": "4.27.3",
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": "4.27.2",
3
+ "version": "4.27.3",
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": "4.27.2",
3
+ "version": "4.27.3",
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": "4.27.2",
3
+ "version": "4.27.3",
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": "4.27.2",
3
+ "version": "4.27.3",
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": "4.27.2",
3
+ "version": "4.27.3",
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": "4.27.2",
3
+ "version": "4.27.3",
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": "4.27.2",
3
+ "version": "4.27.3",
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": "4.27.2",
3
+ "version": "4.27.3",
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": "4.27.2",
3
+ "version": "4.27.3",
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": "4.27.2",
3
+ "version": "4.27.3",
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": "4.27.2",
3
+ "version": "4.27.3",
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": "4.27.2",
3
+ "version": "4.27.3",
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": "4.27.2",
3
+ "version": "4.27.3",
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": "4.27.2",
3
+ "version": "4.27.3",
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": "4.27.2",
3
+ "version": "4.27.3",
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-phaser",
3
- "version": "4.27.2",
3
+ "version": "4.27.3",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-phaser",
3
- "version": "4.27.2",
3
+ "version": "4.27.3",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-phaser",
3
- "version": "4.27.2",
3
+ "version": "4.27.3",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-phaser",
3
- "version": "4.27.2",
3
+ "version": "4.27.3",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-phaser",
3
- "version": "4.27.2",
3
+ "version": "4.27.3",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "4.27.2",
3
+ "version": "4.27.3",
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": "4.27.2",
3
+ "version": "4.27.3",
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": "4.27.2",
3
+ "version": "4.27.3",
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": "4.27.2",
3
+ "version": "4.27.3",
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": "4.27.2",
3
+ "version": "4.27.3",
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": "4.27.2",
3
+ "version": "4.27.3",
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": "4.27.2",
3
+ "version": "4.27.3",
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": "4.27.2",
3
+ "version": "4.27.3",
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": "4.27.2",
3
+ "version": "4.27.3",
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": "4.27.2",
3
+ "version": "4.27.3",
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": "4.27.2",
3
+ "version": "4.27.3",
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": "4.27.2",
3
+ "version": "4.27.3",
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": "4.27.2",
3
+ "version": "4.27.3",
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": "4.27.2",
3
+ "version": "4.27.3",
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": "4.27.2",
3
+ "version": "4.27.3",
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"