@sjawhar/opencode-legion-envoy 0.6.1 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,177 @@
1
+ ---
2
+ name: legion-worker
3
+ description: Use when dispatched as an architect, plan, implement, test, or review phase worker in a Legion issue workspace.
4
+ ---
5
+
6
+ # Legion Phase Worker
7
+
8
+ You are one phase in a shared issue workspace, not a dispatcher or pipeline coordinator. The
9
+ architect owns the tree; phases use the same jj workspace sequentially. Complete the phase
10
+ assigned in the prompt, return its structured output to the architect, and leave the durable
11
+ copy that the next phase can trust.
12
+
13
+ ## Identity, scope, and role
14
+
15
+ The dispatch supplies the issue, phase, daemon-minted role token, workspace, and task
16
+ `outputSchema`. At startup, claim that role with `envoy_role_set`; never construct a role
17
+ token from an issue name. A claim survives parking, and a revived or re-created worker claims
18
+ its own role again.
19
+
20
+ Read the current issue and its acceptance criteria before changing the workspace. Work only
21
+ on this phase's artifact. You may use ordinary scouts, reviewers, and oracle subagents for
22
+ phase work; never spawn legion-role workers. Escalate a product, scope, cross-phase, or
23
+ lifecycle decision to the owning architect through hub, with the verified facts and the
24
+ decision needed. For a durable question that needs Sami directly, you may use the raw
25
+ `dispatch` MCP tool yourself; replies return to your own session.
26
+
27
+ ## Workspace and handoff precedence
28
+
29
+ The `workspace` attribute in your `<legion-spawn>` block is the authoritative issue
30
+ workspace. Before reading repository files or handoffs, you **MUST** bind to that exact
31
+ path with:
32
+
33
+ ```bash
34
+ cd -- "<workspace>" && jj -R "<workspace>" status
35
+ ```
36
+
37
+ Never rely on the inherited cwd. Every later repository shell command **MUST** begin
38
+ `cd -- "<workspace>" &&`; every jj command **MUST** use `-R "<workspace>"`; and native
39
+ filesystem tool paths **MUST** be absolute under that workspace. Do not create an isolated
40
+ worktree, change the workspace topology, or mix another issue's work into it. Concurrent
41
+ issues have disjoint workspaces; phases for this issue are sequential.
42
+
43
+ On every start, and especially after revival or re-creation, read the issue and then the
44
+ committed predecessor handoffs in lifecycle order from `<workspace>/.legion/`:
45
+
46
+ 1. `architect.json`
47
+ 2. `plan.json`
48
+ 3. `implement.json`
49
+ 4. `test.json`
50
+ 5. `review.json`
51
+
52
+ Read only files that precede the assigned phase. The live path returns JSON matching the task
53
+ `outputSchema` directly to the architect. The durable path uses the **same schema** in
54
+ `<workspace>/.legion/<phase>.json`. If a committed handoff conflicts with memory or a prior
55
+ transcript, the committed file wins: it is the copy that survived.
56
+
57
+ ## jj Safety Rules
58
+
59
+ - **Always `jj -R "<workspace>" new` to create isolated commits.** Never
60
+ `jj -R "<workspace>" edit @-` to go back to a parent — this changes what `@` points to
61
+ and makes `jj abandon` dangerous.
62
+ - **Never `jj -R "<workspace>" abandon`.** If a mistake would require abandoning work,
63
+ stop and send the owning architect the `jj -R "<workspace>" log` evidence.
64
+ - **Before pushing, check ancestry:** `jj -R "<workspace>" log -r 'ancestors(@, 5)'` —
65
+ verify only your issue's commits are in the chain, not unrelated work.
66
+
67
+ **Shared operation safety:** Never run `jj op restore` in a Legion workspace. It rewrites the
68
+ shared operation log. If a mistake reaches that point, stop and send the owning architect the
69
+ `jj -R "<workspace>" log` evidence; recover only through the approved, path-scoped workflow.
70
+
71
+ ## Phase work
72
+
73
+ Follow the repository's normal engineering workflow and the assigned issue's acceptance criteria.
74
+ The dispatch output schema defines the phase artifact and completion evidence. Do not replace
75
+ architect-owned decomposition, gate discipline, scheduling, or human communication with labels
76
+ or a local status model.
77
+
78
+ Commit attribution is automatic: the Legion extension exports a `JJ_CONFIG` overlay at root
79
+ bootstrap, so every jj commit made in the session family carries an `Omp-Session: <root-session-id>`
80
+ trailer with no action from you. Do not add attribution trailers by hand.
81
+
82
+ The jj configuration already supplies the phase worker's plus-addressed author and committer
83
+ identity. Do not override Git identity configuration. The worker session receives the
84
+ credential capability it needs; invoke GitHub through the credential helper:
85
+
86
+ ```bash
87
+ legion gh -- <gh args…>
88
+ ```
89
+
90
+ ## GitHub comment attribution
91
+
92
+ Append this exact structured footer to **every** GitHub issue comment, pull-request comment,
93
+ and review that this phase posts. It preserves session provenance on the artifact itself so
94
+ work stays attributable to the session that produced it:
95
+
96
+ ```html
97
+ <!-- legion: {"session":"<session-id>","phase":"<phase>"} -->
98
+ ```
99
+
100
+ For example:
101
+
102
+ ```bash
103
+ legion gh -- issue comment <issue-number> \
104
+ --body $'Verification complete.\n\n<!-- legion: {"session":"<session-id>","phase":"<phase>"} -->' \
105
+ --repo <owner>/<repo>
106
+ ```
107
+
108
+ ## Implementer push and pull request
109
+
110
+ Only the implementer creates the issue bookmark, pushes it, and opens the pull request. After
111
+ its implementation commit and verification, it uses this exact branch name and push procedure:
112
+
113
+ ```bash
114
+ cd -- "<workspace>" && \
115
+ jj -R "<workspace>" bookmark set legion/issue-<n> && \
116
+ jj -R "<workspace>" git push --bookmark legion/issue-<n> --allow-new
117
+ ```
118
+
119
+ The provisioned issue workspace configures `credential.helper` with the daemon's absolute
120
+ credential command, so `jj -R "<workspace>" git push` authenticates transparently through the
121
+ same session capability. Never handle a token.
122
+
123
+ Then create the pull request with the `github` tool's `pr_create` operation. The credential
124
+ helper and `legion gh` provide the GitHub identity; never export, fetch, or replace a token.
125
+ Other phases advance the existing branch rather than creating a replacement bookmark or PR.
126
+
127
+ ## Completion gate: handoff write, verification, and persistence
128
+
129
+ The durable handoff uses the phase-specific fields from the task's `outputSchema` only.
130
+ `--data` must not include `schemaVersion`, `phase`, or `completed`: the CLI generates that
131
+ envelope. Return the **full** schema through the task's structured output, including the
132
+ generated envelope fields.
133
+
134
+ Write the phase-specific handoff:
135
+
136
+ ```bash
137
+ cd -- "<workspace>" && \
138
+ legion handoff write --phase <p> --data '<JSON object of phase-specific fields only>'
139
+ ```
140
+
141
+ Then verify the durable artifact exists:
142
+
143
+ ```bash
144
+ test -f "<workspace>/.legion/<phase>.json"
145
+ ```
146
+
147
+ Then commit that exact handoff file onto the issue branch:
148
+
149
+ ```bash
150
+ cd -- "<workspace>" && \
151
+ jj -R "<workspace>" split -m "<phase>: record handoff" .legion/<phase>.json
152
+ ```
153
+
154
+ If the issue bookmark exists locally, advance it and push it with the provisioned credential
155
+ helper. `--allow-new` also publishes the locally provisioned bookmark on its first push:
156
+
157
+ ```bash
158
+ cd -- "<workspace>" && \
159
+ jj -R "<workspace>" bookmark set legion/issue-<n> && \
160
+ jj -R "<workspace>" git push --bookmark legion/issue-<n> --allow-new
161
+ ```
162
+
163
+ Do not report phase completion until the write, existence check, and handoff commit succeed;
164
+ when an issue branch exists, its push is also required. This is the committed copy the next
165
+ phase reads after revival. The reviewer later removes `.legion/` as its final commit; phase
166
+ workers do not remove it.
167
+
168
+ ## Completion and escalation
169
+
170
+ Return the same schema as the durable handoff through the task's structured output. Do not add
171
+ pipeline labels, run a controller loop, or notify a controller with an invented completion
172
+ protocol. A direct worker delivery belongs to its role; overseers receive only derived
173
+ verdicts.
174
+
175
+ When blocked on lifecycle, scope, or cross-phase matters, send the owning architect a concise
176
+ hub message: issue, phase, verified observation, what you tried, and the decision required.
177
+ Reach for `dispatch` yourself only for a standalone human question outside that coordination.
@@ -0,0 +1,259 @@
1
+ # Repository Configuration (.legion/config.yml)
2
+
3
+ Workers load repository-specific configuration from `.legion/config.yml` at the workspace root. This file allows teams to customize Legion behavior per repository without modifying workflows.
4
+
5
+ ## Schema Overview
6
+
7
+ The config file is YAML with the following top-level sections:
8
+
9
+ ```yaml
10
+ merge:
11
+ require_smoke_test: boolean
12
+ require_reporter_approval: boolean
13
+ auto_merge_allowed: boolean
14
+
15
+ testing:
16
+ require_specific_task: boolean
17
+ require_taiga_evidence: boolean
18
+
19
+ notifications:
20
+ slack_channel: string
21
+ ping_reporter_on_pr: boolean
22
+
23
+ skills:
24
+ required:
25
+ - skill_name_1
26
+ - skill_name_2
27
+
28
+ phases:
29
+ architect:
30
+ # Phase-specific overrides (same keys as top-level)
31
+ plan:
32
+ # Phase-specific overrides
33
+ implement:
34
+ # Phase-specific overrides
35
+ test:
36
+ # Phase-specific overrides
37
+ review:
38
+ # Phase-specific overrides
39
+ ```
40
+
41
+ ## Field Reference
42
+
43
+ ### merge
44
+
45
+ Controls merge behavior and approval gates.
46
+
47
+ | Field | Type | Default | Description |
48
+ |-------|------|---------|-------------|
49
+ | `require_smoke_test` | boolean | `false` | If `true`, merge workflow requires evidence of smoke testing before auto-merge |
50
+ | `require_reporter_approval` | boolean | `false` | If `true`, merge workflow requires explicit reporter approval before merging |
51
+ | `auto_merge_allowed` | boolean | `false` | If `true`, merge workflow may auto-merge PRs that pass all gates |
52
+
53
+ ### testing
54
+
55
+ Controls test requirements and evidence gates.
56
+
57
+ | Field | Type | Default | Description |
58
+ |-------|------|---------|-------------|
59
+ | `require_specific_task` | boolean | `false` | If `true`, test workflow requires evidence of specific task testing (not just unit tests) |
60
+ | `require_taiga_evidence` | boolean | `false` | If `true`, test workflow requires Taiga evidence (e.g., screenshots, logs) attached to the issue |
61
+
62
+ ### notifications
63
+
64
+ Controls notifications and pings.
65
+
66
+ | Field | Type | Default | Description |
67
+ |-------|------|---------|-------------|
68
+ | `slack_channel` | string | `null` | Slack channel ID (e.g., `#eng-legion`) where implementation status updates are posted. If set and `slack-bot` skill is available, implement workflow posts PR URL and CI state |
69
+ | `ping_reporter_on_pr` | boolean | `false` | If `true`, notify the issue reporter when a PR is created |
70
+
71
+ ### skills
72
+
73
+ Specifies skills that should be invoked for all phases.
74
+
75
+ | Field | Type | Default | Description |
76
+ |-------|------|---------|-------------|
77
+ | `required` | string[] | `[]` | List of skill names to invoke in addition to plan handoff `requiredSkills` and independently discovered skills. Additive with other skill sources |
78
+
79
+ ### phases
80
+
81
+ Phase-specific overrides. Each phase (`architect`, `plan`, `implement`, `test`, `review`) can override any top-level key.
82
+
83
+ **Merge behavior:** Phase-specific values override top-level values. For example:
84
+
85
+ ```yaml
86
+ merge:
87
+ require_reporter_approval: false
88
+
89
+ phases:
90
+ implement:
91
+ merge:
92
+ require_reporter_approval: true # Override for implement phase only
93
+ ```
94
+
95
+ ## Recognized Keys
96
+
97
+ Workers recognize the following keys (case-sensitive):
98
+
99
+ - `merge.require_smoke_test`
100
+ - `merge.require_reporter_approval`
101
+ - `merge.auto_merge_allowed`
102
+ - `testing.require_specific_task`
103
+ - `testing.require_taiga_evidence`
104
+ - `notifications.slack_channel`
105
+ - `notifications.ping_reporter_on_pr`
106
+ - `skills.required`
107
+ - `phases.<mode>.*` (any of the above keys under a phase)
108
+
109
+ Unknown keys are silently ignored. Malformed YAML causes the config to be skipped (fallback to defaults).
110
+
111
+ ## Worker Behavior
112
+
113
+ ### Loading
114
+
115
+ Each workflow loads config at startup:
116
+
117
+ ```bash
118
+ if [ -f .legion/config.yml ]; then cat .legion/config.yml; fi
119
+ ```
120
+
121
+ If the file is missing or malformed, workers proceed with defaults (no error).
122
+
123
+ ### Parsing
124
+
125
+ Workers parse recognized keys and echo them for auditability:
126
+
127
+ ```
128
+ Repo config constraints from .legion/config.yml:
129
+ - merge.require_reporter_approval: true
130
+ - testing.require_specific_task: true
131
+ - skills.required: [test-driven-development, verification-before-completion]
132
+ ```
133
+
134
+ ### Application
135
+
136
+ Config values are applied to shape workflow behavior:
137
+
138
+ - **Plan phase:** Config constraints inform the plan preamble (e.g., "reporter approval required before merge")
139
+ - **Implement phase:** Config-required skills are invoked additively with plan handoff skills
140
+ - **Test phase:** Config gates (e.g., `require_specific_task`) are enforced
141
+ - **Review phase:** Config-required skills are invoked additively
142
+ - **Merge phase:** Config gates (e.g., `require_reporter_approval`) are enforced
143
+
144
+ ## Example Configuration
145
+
146
+ ### Minimal (all defaults)
147
+
148
+ ```yaml
149
+ # Empty file or omitted entirely
150
+ # All defaults apply
151
+ ```
152
+
153
+ ### Strict Testing
154
+
155
+ ```yaml
156
+ testing:
157
+ require_specific_task: true
158
+ require_taiga_evidence: true
159
+
160
+ skills:
161
+ required:
162
+ - test-driven-development
163
+ - verification-before-completion
164
+ ```
165
+
166
+ ### Slack Notifications + Approval Gate
167
+
168
+ ```yaml
169
+ notifications:
170
+ slack_channel: "#eng-legion"
171
+ ping_reporter_on_pr: true
172
+
173
+ merge:
174
+ require_reporter_approval: true
175
+ require_smoke_test: true
176
+ ```
177
+
178
+ ### Phase-Specific Overrides
179
+
180
+ ```yaml
181
+ # Default: no approval required
182
+ merge:
183
+ require_reporter_approval: false
184
+
185
+ # But for implement phase, require approval
186
+ phases:
187
+ implement:
188
+ merge:
189
+ require_reporter_approval: true
190
+
191
+ # And require specific task testing only in test phase
192
+ phases:
193
+ test:
194
+ testing:
195
+ require_specific_task: true
196
+ ```
197
+
198
+ ### Full Example
199
+
200
+ ```yaml
201
+ merge:
202
+ require_smoke_test: true
203
+ require_reporter_approval: false
204
+ auto_merge_allowed: false
205
+
206
+ testing:
207
+ require_specific_task: true
208
+ require_taiga_evidence: false
209
+
210
+ notifications:
211
+ slack_channel: "#eng-legion"
212
+ ping_reporter_on_pr: true
213
+
214
+ skills:
215
+ required:
216
+ - test-driven-development
217
+ - verification-before-completion
218
+
219
+ phases:
220
+ plan:
221
+ skills:
222
+ required:
223
+ - brainstorming
224
+ implement:
225
+ merge:
226
+ require_reporter_approval: true
227
+ test:
228
+ testing:
229
+ require_taiga_evidence: true
230
+ ```
231
+
232
+ ## Defaults
233
+
234
+ If a key is not specified in `.legion/config.yml`, the following defaults apply:
235
+
236
+ ```yaml
237
+ merge:
238
+ require_smoke_test: false
239
+ require_reporter_approval: false
240
+ auto_merge_allowed: false
241
+
242
+ testing:
243
+ require_specific_task: false
244
+ require_taiga_evidence: false
245
+
246
+ notifications:
247
+ slack_channel: null
248
+ ping_reporter_on_pr: false
249
+
250
+ skills:
251
+ required: []
252
+ ```
253
+
254
+ ## Notes
255
+
256
+ - **Additive skills:** Config-required skills are additive with plan handoff `requiredSkills` and independently discovered skills. All sources are combined.
257
+ - **Phase overrides:** Phase-specific values completely override top-level values for that phase. Partial overrides are not merged.
258
+ - **Missing file:** If `.legion/config.yml` is missing or malformed, workers proceed with defaults (no error).
259
+ - **Auditability:** Workers echo recognized keys and effective values at the start of each phase for transparency.
@@ -0,0 +1,98 @@
1
+ # Knowledge Injection Algorithm
2
+
3
+ Canonical algorithm for injecting relevant learnings from `docs/solutions/` before phase-specific work begins. All worker workflows reference this file for the injection procedure; each workflow specifies its own keyword sources.
4
+
5
+ ## Overview
6
+
7
+ Before starting main work, each phase checks the learnings index for applicable prior knowledge. This surfaces patterns, pitfalls, and institutional knowledge that previous workers documented.
8
+
9
+ **Injection must never block work.** If any step fails (missing index, invalid JSON, missing files, empty handoff data), skip silently and proceed with the phase's main work.
10
+
11
+ ## Algorithm
12
+
13
+ ### 1. Read the Index
14
+
15
+ Assemble the index by reading all per-entry JSON files in `docs/solutions/.index/`:
16
+
17
+ ```bash
18
+ # Read and merge all entry files in .index/ directory
19
+ for f in docs/solutions/.index/*.json; do
20
+ [ -f "$f" ] && cat "$f"
21
+ done
22
+ ```
23
+
24
+ Each file has the format `{ "version": 1, "entries": { "key": ["learning-path", ...] } }`. Merge all `entries` maps together, deduplicating learning paths per key.
25
+
26
+ If the `.index/` directory doesn't exist or contains no valid JSON files, skip injection entirely — proceed to the phase's main work.
27
+
28
+ ### 2. Extract Keywords
29
+
30
+ Collect keywords from the phase-specific sources (defined in each workflow file). The extraction algorithm:
31
+
32
+ 1. **Collect raw text** from the specified keyword sources (see the calling workflow's keyword source table)
33
+ 2. **Tokenize**: split on whitespace, `/`, `-`, `_`, and camelCase boundaries
34
+ 3. **Normalize**: lowercase all tokens
35
+ 4. **Filter**: remove tokens < 3 chars and common stopwords (the, and, for, with, this, that, from, into, when, will, should, would, could, also, been, have, each, etc.)
36
+ 5. **Deduplicate** tokens
37
+ 6. **Extract full path segments**: e.g., `packages/daemon/src/state` — keep as-is for path matching in addition to individual tokens
38
+
39
+ Also look for references to:
40
+ - Source path segments (e.g., `packages/daemon/src/state/`, `serve-manager`)
41
+ - Module names (e.g., "daemon", "controller", "worker", "state")
42
+ - Component names (e.g., "serve-manager", "decision", "fetch")
43
+ - Feature areas (e.g., "skills", "linear", "github", "review", "retro")
44
+ - Integration concerns (e.g., "PR", "labels", "MCP")
45
+ - Domain concepts and error keywords from the context
46
+
47
+ ### 3. Match Keywords Against Index
48
+
49
+ Use two matching modes against the keys in `.index`:
50
+
51
+ - **Path matching**: For each key that does NOT start with `tag:`, check if any extracted keyword appears as a substring of the key (case-insensitive). Collect all matched learning file paths.
52
+ - **Tag matching**: For each key that starts with `tag:`, extract the tag name (e.g., `tag:race-condition` → `race-condition`). Check if any extracted keyword matches the tag name (case-insensitive). Collect matched learning file paths.
53
+
54
+ ### 4. Deduplicate and Rank
55
+
56
+ - Remove duplicates (same file matched via multiple keys)
57
+ - **Status filter**: For each candidate, read its YAML front matter `status` field. Exclude any file with `status: superseded`. If the file doesn't exist or has no front matter, include it (graceful degradation).
58
+ - **Primary rank: tag overlap** — For each remaining candidate, read its `tags` front matter field. Count how many of its tags appear in the extracted keywords (case-insensitive). Higher overlap = higher rank.
59
+ - **Secondary rank: key specificity** — Learnings matched via longer/more-specific keys rank higher (e.g., a match on `packages/daemon/src/state` outranks a match on `packages/daemon`)
60
+ - **Tertiary rank: match count** — Number of distinct key matches (more matches = more relevant)
61
+ - **Cap at 3 learnings maximum**
62
+
63
+ ### 5. Read Matched Learnings
64
+
65
+ For each matched learning file (from `docs/solutions/<path>`):
66
+
67
+ 1. Read YAML front matter: extract `title` and `tags` fields
68
+ 2. Skip past front matter (`---` blocks) and headings, take the first paragraph of prose (typically the Problem or Overview section)
69
+ 3. Prepend structured header: `[{title} | tags: {comma-separated tags}]`
70
+ 4. Truncate entire output (header + prose) to **350 characters**
71
+
72
+ **If a matched file doesn't exist on disk:** Skip that entry silently (stale index entry from a file rename). Do not error.
73
+
74
+ ### 6. Output Injected Learnings
75
+
76
+ Output the injected learnings visibly in the session before proceeding with the phase's main work:
77
+
78
+ ```
79
+ ## Relevant Learnings (from docs/solutions/)
80
+
81
+ 1. [docs/solutions/<path>]: [{title} | tags: {tag1}, {tag2}] <prose excerpt> (350 chars max total)
82
+ 2. [docs/solutions/<path>]: [{title} | tags: {tag1}, {tag2}] <prose excerpt>
83
+ 3. [docs/solutions/<path>]: [{title} | tags: {tag1}, {tag2}] <prose excerpt>
84
+
85
+ (Review these for patterns and pitfalls relevant to this phase's work.)
86
+ ```
87
+
88
+ **If no matches found:** Output "No relevant learnings found." and proceed. Do NOT add an empty section.
89
+
90
+ **Canonical identifiers:** All references to learnings use their `docs/solutions/` relative file path (e.g., `daemon/controller-lifecycle-separation.md`). These paths are the stable IDs used for injection, handoff tracking, and future aggregation. Never use titles or truncated text as identifiers.
91
+
92
+ ## Fallback Behavior
93
+
94
+ When a keyword source is unavailable (missing handoff data, empty fields, missing phase data), silently fall back to the next available source as defined in the calling workflow's fallback rules. Never error on missing data.
95
+
96
+ ## Integration with Handoffs
97
+
98
+ If the phase writes handoff data, include a `learningsInjected` field listing the `docs/solutions/` relative paths of all injected learnings. This enables downstream phases to see what knowledge was available and supports future aggregation.
@@ -0,0 +1,22 @@
1
+ # Strategy: Cleanup & Deletion PRs
2
+
3
+ When deleting deprecated code, stale docs, or consolidating references.
4
+
5
+ ## When deleting a CLI command, check all four:
6
+
7
+ 1. Implementation file(s)
8
+ 2. `package.json` / `pyproject.toml` script entry
9
+ 3. All project documentation references (AGENTS.md or equivalent — check command tables AND section headings)
10
+ 4. Wrapper scripts or CI jobs that invoke it
11
+
12
+ ## project doc headings are documentation too
13
+
14
+ When updating a command reference, grep for the section heading and update it in the same commit. Headings that reference specific paths (`## Foo (meta/bar/)`) go stale when paths change.
15
+
16
+ ## Deletion PRs should be almost entirely deletions
17
+
18
+ Resist opportunistic refactors. If the diff has significant additions, the scope has crept. The value of a cleanup PR is its tight, reviewable scope.
19
+
20
+ ## Complete the deletion chain
21
+
22
+ If a feature has implementation + CLI wrapper + package.json entry + docs, remove all of them together. Partial deletion leaves broken references.
@@ -0,0 +1,19 @@
1
+ # Strategy: Systematic Rename
2
+
3
+ When a repo, package, or URL is renamed across a codebase.
4
+
5
+ ## Checklist
6
+
7
+ 1. **Scope by file type** — grep all text-bearing extensions, not just the obvious ones:
8
+ - Source code (`.ts`, `.js`, `.py`, `.sh`) — functional, must update
9
+ - CI/CD configs (`.yml`, `.yaml`) — functional, must update
10
+ - Documentation (`.md`) — correctness, should update
11
+ - Config files (`.json`, `.toml`) — check but may be immutable
12
+
13
+ 2. **Classify matches as mutable vs immutable** — historical records (transcripts, test snapshots, progress logs) must NOT be modified. Changing them falsifies history.
14
+
15
+ 3. **Check comments for semantic context** — a comment mentioning the old name may still be correct in intent. Update the name but preserve the reasoning.
16
+
17
+ 4. **Verify with grep before AND after** — capture pre-edit state as a baseline for comparison.
18
+
19
+ 5. **Use `jj diff --git`** for verification — plain `jj diff` without color concatenates old/new text confusingly (e.g., `old-nameNEW-name` without color codes).
@@ -0,0 +1,76 @@
1
+ ---
2
+ name: linear
3
+ description: Manage Linear issues. Use when working with tasks, tickets, bugs, or Linear.
4
+ mcp:
5
+ linear:
6
+ command: npx
7
+ args: ["-y", "github:obra/streamlinear"]
8
+ env:
9
+ LINEAR_API_TOKEN: ${LINEAR_API_TOKEN}
10
+ ---
11
+
12
+ # Linear (Stream Linear)
13
+
14
+ Single-tool MCP with action dispatch. All operations go through `linear_linear`.
15
+
16
+ ## Actions
17
+
18
+ ### Search Issues
19
+
20
+ ```
21
+ linear_linear(action="search") # Your active issues
22
+ linear_linear(action="search", query="auth bug") # Text search
23
+ linear_linear(action="search", query={state: "In Progress"}) # Filter
24
+ linear_linear(action="search", query={team: "ENG", assignee: "me"})
25
+ ```
26
+
27
+ ### Get Issue Details
28
+
29
+ ```
30
+ linear_linear(action="get", id="ABC-123") # By short ID
31
+ linear_linear(action="get", id="https://linear.app/...") # By URL
32
+ ```
33
+
34
+ Returns: title, description, status, labels, comments, attachments.
35
+
36
+ ### Update Issue
37
+
38
+ ```
39
+ linear_linear(action="update", id="ABC-123", state="Done")
40
+ linear_linear(action="update", id="ABC-123", priority=1)
41
+ linear_linear(action="update", id="ABC-123", assignee="me")
42
+ linear_linear(action="update", id="ABC-123", labels=["legion-backlog", "existing-label"])
43
+ ```
44
+
45
+ **Labels array replaces all labels.** Fetch current labels first, then append.
46
+
47
+ ### Comment on Issue
48
+
49
+ ```
50
+ linear_linear(action="comment", id="ABC-123", body="Fixed in commit abc123")
51
+ ```
52
+
53
+ ### Create Issue
54
+
55
+ ```
56
+ linear_linear(action="create", title="Bug: Login fails", team="ENG")
57
+ linear_linear(action="create", title="Bug", team="ENG", body="Details", priority=2)
58
+ ```
59
+
60
+ ### Raw GraphQL
61
+
62
+ ```
63
+ linear_linear(action="graphql", graphql="query { viewer { name } }")
64
+ ```
65
+
66
+ ### Help
67
+
68
+ ```
69
+ linear_linear(action="help")
70
+ ```
71
+
72
+ ## Reference
73
+
74
+ - Priority: 0=None, 1=Urgent, 2=High, 3=Medium, 4=Low
75
+ - State matching is fuzzy: "done" → "Done", "in prog" → "In Progress"
76
+ - IDs accept: `ABC-123`, Linear URLs, or UUIDs