@codyswann/lisa 4.27.2 → 4.27.4
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.
- package/cdk/create-only/.github/workflows/ci.yml +79 -4
- package/dist/core/nightly-e2e-guard-behavior-certificate.js +2 -2
- package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
- package/dist/core/upstream-evidence-manifest.js +24 -12
- package/dist/core/upstream-evidence-manifest.js.map +1 -1
- package/package.json +3 -3
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-linear-access/SKILL.md +84 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-linear-build-intake/SKILL.md +3 -3
- package/plugins/lisa/.codex-plugin/skills/lisa-linear-claim/SKILL.md +2 -2
- package/plugins/lisa/.codex-plugin/skills/lisa-linear-evidence/SKILL.md +4 -4
- package/plugins/lisa/.codex-plugin/skills/lisa-linear-sync/SKILL.md +5 -2
- package/plugins/lisa/.codex-plugin/skills/lisa-linear-write-issue/SKILL.md +5 -5
- package/plugins/lisa/.codex-plugin/skills/lisa-repair-intake/SKILL.md +3 -2
- package/plugins/lisa/.codex-plugin/skills/lisa-setup-linear/SKILL.md +11 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-validate-tracker-mapping/SKILL.md +3 -1
- package/plugins/lisa/agents/linear-agent.md +12 -12
- package/plugins/lisa/agents/linear-build-intake.md +1 -1
- package/plugins/lisa/scripts/linear-state-write-target.mjs +362 -0
- package/plugins/lisa/skills/lisa-linear-access/SKILL.md +84 -1
- package/plugins/lisa/skills/lisa-linear-build-intake/SKILL.md +3 -3
- package/plugins/lisa/skills/lisa-linear-claim/SKILL.md +2 -2
- package/plugins/lisa/skills/lisa-linear-evidence/SKILL.md +5 -5
- package/plugins/lisa/skills/lisa-linear-sync/SKILL.md +5 -2
- package/plugins/lisa/skills/lisa-linear-write-issue/SKILL.md +5 -5
- package/plugins/lisa/skills/lisa-repair-intake/SKILL.md +3 -2
- package/plugins/lisa/skills/lisa-setup-linear/SKILL.md +11 -1
- package/plugins/lisa/skills/lisa-validate-tracker-mapping/SKILL.md +3 -1
- package/plugins/lisa-agy/agents/linear-agent.md +12 -12
- package/plugins/lisa-agy/agents/linear-build-intake.md +1 -1
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-agy/scripts/linear-state-write-target.mjs +362 -0
- package/plugins/lisa-agy/skills/lisa-linear-access/SKILL.md +84 -1
- package/plugins/lisa-agy/skills/lisa-linear-build-intake/SKILL.md +3 -3
- package/plugins/lisa-agy/skills/lisa-linear-claim/SKILL.md +2 -2
- package/plugins/lisa-agy/skills/lisa-linear-evidence/SKILL.md +5 -5
- package/plugins/lisa-agy/skills/lisa-linear-sync/SKILL.md +5 -2
- package/plugins/lisa-agy/skills/lisa-linear-write-issue/SKILL.md +5 -5
- package/plugins/lisa-agy/skills/lisa-repair-intake/SKILL.md +3 -2
- package/plugins/lisa-agy/skills/lisa-setup-linear/SKILL.md +11 -1
- package/plugins/lisa-agy/skills/lisa-validate-tracker-mapping/SKILL.md +3 -1
- package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-agy/plugin.json +1 -1
- package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/agents/linear-agent.agent.md +12 -12
- package/plugins/lisa-copilot/agents/linear-build-intake.agent.md +1 -1
- package/plugins/lisa-copilot/scripts/linear-state-write-target.mjs +362 -0
- package/plugins/lisa-copilot/skills/lisa-linear-access/SKILL.md +84 -1
- package/plugins/lisa-copilot/skills/lisa-linear-build-intake/SKILL.md +3 -3
- package/plugins/lisa-copilot/skills/lisa-linear-claim/SKILL.md +2 -2
- package/plugins/lisa-copilot/skills/lisa-linear-evidence/SKILL.md +5 -5
- package/plugins/lisa-copilot/skills/lisa-linear-sync/SKILL.md +5 -2
- package/plugins/lisa-copilot/skills/lisa-linear-write-issue/SKILL.md +5 -5
- package/plugins/lisa-copilot/skills/lisa-repair-intake/SKILL.md +3 -2
- package/plugins/lisa-copilot/skills/lisa-setup-linear/SKILL.md +11 -1
- package/plugins/lisa-copilot/skills/lisa-validate-tracker-mapping/SKILL.md +3 -1
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/agents/linear-agent.md +12 -12
- package/plugins/lisa-cursor/agents/linear-build-intake.md +1 -1
- package/plugins/lisa-cursor/scripts/linear-state-write-target.mjs +362 -0
- package/plugins/lisa-cursor/skills/lisa-linear-access/SKILL.md +84 -1
- package/plugins/lisa-cursor/skills/lisa-linear-build-intake/SKILL.md +3 -3
- package/plugins/lisa-cursor/skills/lisa-linear-claim/SKILL.md +2 -2
- package/plugins/lisa-cursor/skills/lisa-linear-evidence/SKILL.md +5 -5
- package/plugins/lisa-cursor/skills/lisa-linear-sync/SKILL.md +5 -2
- package/plugins/lisa-cursor/skills/lisa-linear-write-issue/SKILL.md +5 -5
- package/plugins/lisa-cursor/skills/lisa-repair-intake/SKILL.md +3 -2
- package/plugins/lisa-cursor/skills/lisa-setup-linear/SKILL.md +11 -1
- package/plugins/lisa-cursor/skills/lisa-validate-tracker-mapping/SKILL.md +3 -1
- package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-agy/plugin.json +1 -1
- package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-agy/plugin.json +1 -1
- package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-agy/plugin.json +1 -1
- package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-agy/plugin.json +1 -1
- package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-agy/plugin.json +1 -1
- package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-agy/plugin.json +1 -1
- package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-agy/plugin.json +1 -1
- package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/src/base/agents/linear-agent.md +12 -12
- package/plugins/src/base/agents/linear-build-intake.md +1 -1
- package/plugins/src/base/scripts/linear-state-write-target.mjs +362 -0
- package/plugins/src/base/skills/lisa-linear-access/SKILL.md +84 -1
- package/plugins/src/base/skills/lisa-linear-build-intake/SKILL.md +3 -3
- package/plugins/src/base/skills/lisa-linear-claim/SKILL.md +2 -2
- package/plugins/src/base/skills/lisa-linear-evidence/SKILL.md +5 -5
- package/plugins/src/base/skills/lisa-linear-sync/SKILL.md +5 -2
- package/plugins/src/base/skills/lisa-linear-write-issue/SKILL.md +5 -5
- package/plugins/src/base/skills/lisa-repair-intake/SKILL.md +3 -2
- package/plugins/src/base/skills/lisa-setup-linear/SKILL.md +11 -1
- 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`
|
|
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`
|
|
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,
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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`, `
|
|
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`** →
|
|
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
|
|
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
|
|
733
|
-
|
|
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` |
|
|
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`, `
|
|
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.
|
|
@@ -47,11 +47,11 @@ Use the `linear-verify` skill to check the item against organizational standards
|
|
|
47
47
|
|
|
48
48
|
**Gating behavior — this is the one place auto-transitioning is allowed:**
|
|
49
49
|
|
|
50
|
-
Resolve build-lifecycle STATES from `.lisa.config.json` `linear.workflow.*`
|
|
50
|
+
Resolve build-lifecycle STATES from `.lisa.config.json` `linear.workflow.*` through `scripts/resolve-lifecycle-role.mjs` (`--vendor linear`). `ready`, `claimed`, `blocked` and `done` are REQUIRED and have no built-in default — an unset one is a setup defect to report. `review` is OPTIONAL and deliberately has **no** default: an unset `review` means the project runs no agent review step and the transition is skipped, never substituted (`config-resolution` R1). Resolve the `human_needed` marker label from `linear.labels.build.human_needed` (default `human-needed`) — the one surviving build-lane label key.
|
|
51
51
|
|
|
52
52
|
If `linear-verify` returns `FAIL` on any of the above, do NOT continue to build. **Draft the missing spec content first, then block for confirmation** — never bounce a raw "go write all this" checklist back to the creator:
|
|
53
53
|
1. **Best-effort autofill (before blocking).** Run `pre-flight-autofill` for every work item. Preserve a human bare configured key or `Confirmed: <env>`; automation writes `Inferred: <env> — evidence: <title|body|reproduction|hostname>`, `Assumption: <env> — remote default branch <branch>` for a unique reverse-map, or `Assumption: remote default branch <branch>` otherwise. Human confirmation replaces the annotation with the bare key or `Confirmed: <env>`. For a legacy bare value, use managed draft markers and current ticket content only; provider edit history is not required. A marker proves automation and requires re-annotation; otherwise unknown provenance plus conflicting evidence stops for confirmation. Resolve one exact `deploy.branches` key from the human-authored title, body, and reproduction steps or URL hostname; exclude the complete `Target Backend Environment` section and other machine-authored metadata/draft blocks so annotations cannot become evidence. A reported bug environment is an example, not a restriction. Evidence supersedes only `Assumption:`. Normalize `prod` ↔ `production` only when exactly one is configured; no other aliases exist. Conflicts stop; never infer from arbitrary branch text, URL paths/query strings, or substrings. Write through `linear-write-issue`, never overwrite human prose, then re-run `linear-verify`.
|
|
54
|
-
2.
|
|
54
|
+
2. Move the Issue to the configured `blocked` **state** via `lisa-linear-access operation: save-issue lifecycle_role: blocked` (the access layer resolves the configured state itself; never hand it a state ID), and add the configured `human_needed` marker **label** in the same or a following metadata update. (Create either label via `create_issue_label` if needed.) Even after the agent drafted what it could, a pre-flight gate failure bounces the item back to its creator because it still needs a human to **confirm the drafted assumptions** or supply something no agent can invent — real missing credentials, access, or an irreducible product/scoping decision — so the marker tells a human scanning the board which blocked items are waiting on them. The marker is additive to `blocked`, not a replacement. (See the `config-resolution` rule's "Build markers" for when the marker applies and when it must NOT.)
|
|
55
55
|
3. Reassign the item to the **Issue creator** (the human who filed it — Linear's `creator` field).
|
|
56
56
|
4. Post the **confirmation comment** from the `pre-flight-autofill` rule via `lisa-linear-access operation: save-comment`, **not** a bare remediation checklist: disclose it is a Claude draft, give one line per drafted section naming the key assumption made, list any remaining human-only item as a specific question with a recommended default, and close with *"review the drafted sections, correct anything wrong, then flip back to Ready and it builds — or reply with corrections."* Prefix with `[{repo}]`.
|
|
57
57
|
5. Stop. Do not run triage, do not delegate to a flow, do not start work.
|
|
@@ -116,23 +116,23 @@ Use the `linear-evidence` skill to:
|
|
|
116
116
|
|
|
117
117
|
### 8. Suggest Status Transition
|
|
118
118
|
|
|
119
|
-
Based on the milestone,
|
|
119
|
+
Based on the milestone, name the lifecycle role the item has reached. This agent does not perform these transitions itself — the owning flow does (`linear-evidence` for `review`, `linear-build-intake` for `claimed` and `done`) — so this section is a suggestion surface, not a write surface. Role names are resolved from `.lisa.config.json` `linear.workflow.*`; there is no default column, because a role this project did not bind has no name to print:
|
|
120
120
|
|
|
121
|
-
| Milestone |
|
|
122
|
-
|
|
123
|
-
| Plan created | `claimed` | `
|
|
124
|
-
| PR ready | `review` | `
|
|
125
|
-
| PR merged | `done` (env-aware; build-intake performs if dispatched via that flow) | env-keyed variant per `linear.workflow.done` |
|
|
121
|
+
| Milestone | Lifecycle role | Configured state |
|
|
122
|
+
|-----------|----------------|------------------|
|
|
123
|
+
| Plan created | `claimed` | `linear.workflow.claimed` (required) |
|
|
124
|
+
| PR ready | `review` | `linear.workflow.review` — **optional**; unset means skip the step |
|
|
125
|
+
| PR merged | `done` (env-aware; build-intake performs it if dispatched via that flow) | env-keyed variant per `linear.workflow.done` |
|
|
126
126
|
|
|
127
|
-
Note: `done` may be a string or an env-keyed map (`{ dev, staging, production }`). When
|
|
127
|
+
Note: `done` may be a string or an env-keyed map (`{ dev, staging, production }`). When naming the PR-merged transition, the env is implied by the PR's base branch via `deploy.branches` — surface the resolved state name; do not perform the transition here.
|
|
128
128
|
|
|
129
|
-
The
|
|
129
|
+
The native workflow **state** is the canonical build lane on Linear (`linear.labels.build.{ready,claimed,review,done}` is inert and nothing reads it). Suggesting a role never authorizes writing it: every state write goes through `lisa-linear-access` with a declared `lifecycle_role`, which resolves the target from config rather than trusting a supplied ID.
|
|
130
130
|
|
|
131
131
|
## Rules
|
|
132
132
|
|
|
133
|
-
-
|
|
133
|
+
- **This agent** never transitions the native Linear `state`, with one explicit exception: when `linear-verify` returns `FAIL` for the pre-flight gate (Step 2), run the `pre-flight-autofill` draft-then-block procedure (draft the authorable missing sections into the description as labeled assumptions), then move the Issue to the configured `blocked` state via `lisa-linear-access operation: save-issue lifecycle_role: blocked`, add the configured `human_needed` marker label (`linear.labels.build.human_needed`, default `human-needed`), and reassign to the creator with a confirmation comment. Every other transition is a suggestion this agent surfaces and the owning lifecycle flow performs — it is not a claim that the lane is label-driven. It is not: on Linear the lane is the state.
|
|
134
134
|
- Always read the full item graph via `linear-read-issue` before determining intent — don't rely on type labels alone.
|
|
135
|
-
- Never create or materially edit an item by calling MCP write tools directly — always delegate to `linear-write-issue` so relationships, Gherkin criteria, and metadata gates are enforced. Two explicit exceptions are permitted: (1) the Step 2 pre-flight failure path (when `linear-verify` returns `FAIL`) may call `lisa-linear-access operation: save-issue` and `lisa-linear-access operation: save-comment` directly to
|
|
135
|
+
- Never create or materially edit an item by calling MCP write tools directly — always delegate to `linear-write-issue` so relationships, Gherkin criteria, and metadata gates are enforced. Two explicit exceptions are permitted: (1) the Step 2 pre-flight failure path (when `linear-verify` returns `FAIL`) may call `lisa-linear-access operation: save-issue lifecycle_role: blocked` and `lisa-linear-access operation: save-comment` directly to move the Issue to the configured `blocked` state, add the configured `human_needed` marker label, and reassign to the creator — this narrow exception is already granted by the rule above; (2) the Step 3 triage path may call `lisa-linear-access operation: save-comment` to post triage findings and `lisa-linear-access operation: save-issue` to add the `claude-triaged-{repo}` label — these are lightweight metadata updates that do not create or materially edit ticket content and therefore do not need to route through `linear-write-issue`.
|
|
136
136
|
- If sign-in credentials are in the item, extract and pass them to the flow. If the item touches an authenticated surface and credentials are missing, that is a Step 2 failure — block and reassign rather than guessing.
|
|
137
137
|
- If the item has a Validation Journey section, pass it to the verifier agent. The Validation Journey's local-verification step must point at the target backend environment named in the description.
|
|
138
138
|
- The environment handoff for every work item uses the same durable grammar: human bare configured key or `Confirmed: <env>`; automated `Inferred: <env> — evidence: <title|body|reproduction|hostname>`, `Assumption: <env> — remote default branch <branch>` for a unique reverse-map, or `Assumption: remote default branch <branch>` otherwise. Human confirmation replaces an automated annotation with the bare key or `Confirmed: <env>`. For legacy bare values, managed draft markers and current ticket content decide provenance; provider edit history is not required. A marker proves automation; otherwise unknown provenance plus conflicting evidence stops for confirmation. Human-confirmed wins, then validated `Inferred:`; otherwise one exact `deploy.branches` key from the human-authored title, body, and reproduction steps or URL hostname drives the implementation base branch. Exclude the complete `Target Backend Environment` section and other machine-authored metadata/draft blocks so annotations cannot become evidence. Evidence supersedes only `Assumption:`. Normalize `prod` ↔ `production` only when exactly one is configured; no other aliases exist. Conflicts stop. Never infer from arbitrary branch text, URL paths/query strings, or substrings. With no signal, use the remote default and record the applicable assumption without blocking on a non-unique reverse-map. Require any selected mapping and remote branch. A reported bug environment is an example of the all-work-type rule. Non-integration fixes still require the linked forward cherry-pick.
|
|
@@ -17,7 +17,7 @@ skills:
|
|
|
17
17
|
|
|
18
18
|
You are a Linear build-intake agent. Your single job is to run one cycle against a Linear team — find Issues in the configured `ready` workflow STATE, dispatch each through the build flow, transition successful builds to the configured (env-aware) `done` state — then report what happened.
|
|
19
19
|
|
|
20
|
-
Build-lifecycle role names (`ready`, `claimed`, `review`, `blocked`, `done`) are resolved from `.lisa.config.json` `linear.workflow.*` by the `linear-build-intake` skill, and name native **workflow states**, not labels. Defaults: `Ready`, `In Progress`, `
|
|
20
|
+
Build-lifecycle role names (`ready`, `claimed`, `review`, `blocked`, `done`) are resolved from `.lisa.config.json` `linear.workflow.*` by the `linear-build-intake` skill, and name native **workflow states**, not labels. Defaults: `Ready`, `In Progress`, `Blocked`, env-keyed `{ dev: "On Dev", staging: "On Stg", production: "Done" }`. **`review` has no default and is never seeded** — it is optional, and an unset `review` means the project runs no agent review step, so the transition is skipped rather than aimed at a review-shaped state nobody configured. `ready` is a DEDICATED state, never the team default (`Todo`) — mapping it to the default makes every untouched backlog item claimable.
|
|
21
21
|
|
|
22
22
|
## Confirmation policy
|
|
23
23
|
|