@sjawhar/pi-legion-envoy 0.1.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.
- package/README.md +95 -0
- package/dist/envoy.js +31138 -0
- package/dist/skills/AGENTS.md +37 -0
- package/dist/skills/envoy/SKILL.md +396 -0
- package/dist/skills/github/SKILL.md +203 -0
- package/dist/skills/legion-architect/SKILL.md +199 -0
- package/dist/skills/legion-controller/SKILL.md +136 -0
- package/dist/skills/legion-oracle/SKILL.md +63 -0
- package/dist/skills/legion-retro/SKILL.md +87 -0
- package/dist/skills/legion-worker/SKILL.md +175 -0
- package/dist/skills/legion-worker/references/config.md +259 -0
- package/dist/skills/legion-worker/references/knowledge-injection.md +98 -0
- package/dist/skills/legion-worker/resources/strategies/cleanup-deletion.md +22 -0
- package/dist/skills/legion-worker/resources/strategies/systematic-rename.md +19 -0
- package/dist/skills/linear/SKILL.md +76 -0
- package/package.json +36 -0
|
@@ -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
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sjawhar/pi-legion-envoy",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"omp": {
|
|
6
|
+
"extensions": [
|
|
7
|
+
"dist/envoy.js"
|
|
8
|
+
]
|
|
9
|
+
},
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "https://github.com/sjawhar/legion"
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "bun build extensions/envoy.ts extensions/legion.ts --outdir dist --target bun --format esm --external @oh-my-pi/pi-coding-agent",
|
|
19
|
+
"prepack": "./scripts/prepack.sh",
|
|
20
|
+
"postpack": "rm -rf dist/skills",
|
|
21
|
+
"typecheck": "bunx tsc --noEmit",
|
|
22
|
+
"test": "bun test",
|
|
23
|
+
"lint": "bunx biome lint extensions/ src/"
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@biomejs/biome": "^2.3.14",
|
|
27
|
+
"@legion/contracts": "0.10.0",
|
|
28
|
+
"@legion/envoy-client": "0.1.0",
|
|
29
|
+
"@legion/workspace": "0.1.0",
|
|
30
|
+
"@toon-format/toon": "^4.1.1",
|
|
31
|
+
"@types/bun": "latest",
|
|
32
|
+
"nats": "^2.29.2",
|
|
33
|
+
"typescript": "^5.3.0",
|
|
34
|
+
"zod": "^4.1.8"
|
|
35
|
+
}
|
|
36
|
+
}
|