opencode-lisa 0.3.0 → 0.3.2
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 +14 -12
- package/bin/cli.js +146 -183
- package/dist/index.js +21 -19
- package/package.json +1 -12
- package/assets/skills/lisa/SKILL.md +0 -841
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
An intelligent epic workflow plugin for [OpenCode](https://opencode.ai). Like the Ralph Wiggum pattern, but smarter.
|
|
6
6
|
|
|
7
|
-
**Latest version: 0.
|
|
7
|
+
**Latest version: 0.3.0** - Simplified one-command installation!
|
|
8
8
|
|
|
9
9
|
## Why Lisa?
|
|
10
10
|
|
|
@@ -25,31 +25,33 @@ The **Ralph Wiggum pattern** is a simple bash loop that keeps feeding prompts to
|
|
|
25
25
|
|
|
26
26
|
## Install
|
|
27
27
|
|
|
28
|
+
One command to install Lisa in your project:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npx opencode-lisa --opencode
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Or with Bun:
|
|
35
|
+
|
|
28
36
|
```bash
|
|
29
|
-
|
|
30
|
-
npx opencode-lisa init
|
|
37
|
+
bunx opencode-lisa --opencode
|
|
31
38
|
```
|
|
32
39
|
|
|
33
|
-
This will
|
|
34
|
-
- Install command and skill files to `.opencode/`
|
|
35
|
-
- Add the plugin to your `opencode.json`
|
|
36
|
-
- Set up Lisa for use in your project
|
|
40
|
+
This creates an `opencode.json` file with Lisa configured. The plugin will be automatically downloaded by OpenCode when you start it.
|
|
37
41
|
|
|
38
42
|
Requires [OpenCode](https://opencode.ai) 1.0+.
|
|
39
43
|
|
|
40
44
|
### Global Installation
|
|
41
45
|
|
|
42
|
-
To
|
|
46
|
+
To use Lisa in all your projects, add to your global OpenCode config:
|
|
43
47
|
|
|
44
48
|
```bash
|
|
45
|
-
|
|
46
|
-
npx opencode-lisa init --global
|
|
49
|
+
# Create or edit ~/.config/opencode/opencode.json
|
|
47
50
|
```
|
|
48
51
|
|
|
49
|
-
Add to your global `~/.config/opencode/opencode.json`:
|
|
50
|
-
|
|
51
52
|
```json
|
|
52
53
|
{
|
|
54
|
+
"$schema": "https://opencode.ai/config.json",
|
|
53
55
|
"plugin": ["opencode-lisa"]
|
|
54
56
|
}
|
|
55
57
|
```
|
package/bin/cli.js
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import { existsSync,
|
|
3
|
+
import { existsSync, readFileSync, writeFileSync, unlinkSync, rmSync, copyFileSync, mkdirSync, statSync } from 'fs';
|
|
4
4
|
import { join, dirname } from 'path';
|
|
5
5
|
import { fileURLToPath } from 'url';
|
|
6
|
-
import { createInterface } from 'readline';
|
|
7
6
|
|
|
8
7
|
const __filename = fileURLToPath(import.meta.url);
|
|
9
8
|
const __dirname = dirname(__filename);
|
|
10
|
-
const ASSETS_DIR = join(__dirname, '..', 'assets');
|
|
11
9
|
|
|
12
|
-
|
|
10
|
+
const PLUGIN_NAME = 'opencode-lisa';
|
|
11
|
+
|
|
13
12
|
const colors = {
|
|
14
13
|
green: (s) => `\x1b[32m${s}\x1b[0m`,
|
|
15
14
|
yellow: (s) => `\x1b[33m${s}\x1b[0m`,
|
|
@@ -18,232 +17,196 @@ const colors = {
|
|
|
18
17
|
dim: (s) => `\x1b[2m${s}\x1b[0m`,
|
|
19
18
|
};
|
|
20
19
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
output: process.stdout,
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
return new Promise((resolve) => {
|
|
28
|
-
rl.question(question, (answer) => {
|
|
29
|
-
rl.close();
|
|
30
|
-
resolve(answer.toLowerCase().trim());
|
|
31
|
-
});
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
async function confirmOverwrite(filePath, force) {
|
|
36
|
-
if (!existsSync(filePath)) return true;
|
|
37
|
-
if (force) return true;
|
|
20
|
+
function printHelp() {
|
|
21
|
+
console.log(`
|
|
22
|
+
${colors.cyan('Lisa - Intelligent Epic Workflow Plugin')}
|
|
38
23
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
);
|
|
42
|
-
return answer === 'y' || answer === 'yes';
|
|
43
|
-
}
|
|
24
|
+
Usage:
|
|
25
|
+
npx ${PLUGIN_NAME} --opencode
|
|
44
26
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
mkdirSync(dir, { recursive: true });
|
|
49
|
-
}
|
|
50
|
-
}
|
|
27
|
+
Options:
|
|
28
|
+
--opencode Install Lisa for OpenCode in current directory
|
|
29
|
+
--help, -h Show this help message
|
|
51
30
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const srcPath = join(ASSETS_DIR, srcRelative);
|
|
55
|
-
|
|
56
|
-
if (!existsSync(srcPath)) {
|
|
57
|
-
console.error(colors.red(`Error: Source file not found: ${srcPath}`));
|
|
58
|
-
process.exit(1);
|
|
59
|
-
}
|
|
31
|
+
Example:
|
|
32
|
+
npx ${PLUGIN_NAME} --opencode
|
|
60
33
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
return false;
|
|
65
|
-
}
|
|
34
|
+
After installation, run ${colors.cyan('opencode')} and type ${colors.cyan('/lisa help')} to get started!
|
|
35
|
+
`);
|
|
36
|
+
}
|
|
66
37
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
38
|
+
async function checkOpenCodeInstalled() {
|
|
39
|
+
try {
|
|
40
|
+
// Check if opencode command exists
|
|
41
|
+
const { execSync } = await import('child_process');
|
|
42
|
+
execSync('which opencode', { stdio: 'ignore' });
|
|
70
43
|
return true;
|
|
71
|
-
}
|
|
44
|
+
} catch {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
72
47
|
}
|
|
73
48
|
|
|
74
|
-
function
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
if (answer !== 'y' && answer !== 'yes') {
|
|
91
|
-
console.log(colors.dim(` Skipped: opencode.json update`));
|
|
92
|
-
return false;
|
|
49
|
+
function cleanupOldInstalls(targetDir) {
|
|
50
|
+
// Remove old file-based installations from previous versions
|
|
51
|
+
const oldPaths = [
|
|
52
|
+
join(targetDir, '.opencode', 'skills', 'lisa'),
|
|
53
|
+
join(targetDir, '.opencode', 'skill', 'lisa'), // old singular path
|
|
54
|
+
join(targetDir, '.opencode', 'command', 'lisa.md'), // old singular path
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
for (const oldPath of oldPaths) {
|
|
58
|
+
try {
|
|
59
|
+
if (existsSync(oldPath)) {
|
|
60
|
+
const stat = statSync(oldPath);
|
|
61
|
+
if (stat.isDirectory()) {
|
|
62
|
+
rmSync(oldPath, { recursive: true, force: true });
|
|
63
|
+
} else {
|
|
64
|
+
unlinkSync(oldPath);
|
|
93
65
|
}
|
|
94
|
-
|
|
66
|
+
console.log(colors.dim(` Cleaned up old install: ${oldPath}`));
|
|
95
67
|
}
|
|
68
|
+
} catch {
|
|
69
|
+
// Ignore errors during cleanup
|
|
96
70
|
}
|
|
97
|
-
|
|
98
|
-
// Ensure plugin array exists
|
|
99
|
-
if (!config.plugin) {
|
|
100
|
-
config.plugin = [];
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// Check if already has the plugin
|
|
104
|
-
if (config.plugin.includes('opencode-lisa')) {
|
|
105
|
-
console.log(colors.dim(` Already configured: opencode-lisa in plugins`));
|
|
106
|
-
return false;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// Add the plugin
|
|
110
|
-
config.plugin.push('opencode-lisa');
|
|
111
|
-
|
|
112
|
-
// Add schema if not present
|
|
113
|
-
if (!config.$schema) {
|
|
114
|
-
config.$schema = 'https://opencode.ai/config.json';
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
ensureDir(configPath);
|
|
118
|
-
writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n');
|
|
119
|
-
|
|
120
|
-
if (existed) {
|
|
121
|
-
console.log(colors.green(` Updated: opencode.json (added opencode-lisa to plugins)`));
|
|
122
|
-
} else {
|
|
123
|
-
console.log(colors.green(` Created: opencode.json`));
|
|
124
|
-
}
|
|
125
|
-
return true;
|
|
126
|
-
};
|
|
71
|
+
}
|
|
127
72
|
}
|
|
128
73
|
|
|
129
|
-
|
|
130
|
-
|
|
74
|
+
function installCommandFile(targetDir) {
|
|
75
|
+
// Source: command file in the npm package
|
|
76
|
+
const sourcePath = join(__dirname, '..', 'assets', 'commands', 'lisa.md');
|
|
77
|
+
|
|
78
|
+
// Destination: where OpenCode looks for slash commands
|
|
79
|
+
const destPath = join(targetDir, '.opencode', 'commands', 'lisa.md');
|
|
80
|
+
|
|
81
|
+
// Verify source file exists
|
|
82
|
+
if (!existsSync(sourcePath)) {
|
|
83
|
+
throw new Error(`Source command file not found: ${sourcePath}`);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Create directory if needed
|
|
87
|
+
const destDir = dirname(destPath);
|
|
88
|
+
if (!existsSync(destDir)) {
|
|
89
|
+
mkdirSync(destDir, { recursive: true });
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Copy file (overwrite if exists to ensure latest version)
|
|
93
|
+
copyFileSync(sourcePath, destPath);
|
|
94
|
+
console.log(colors.green(` Created: ${destPath}`));
|
|
95
|
+
}
|
|
131
96
|
|
|
97
|
+
async function install(targetDir) {
|
|
132
98
|
console.log('');
|
|
133
99
|
console.log(colors.cyan('Lisa - Intelligent Epic Workflow Plugin'));
|
|
134
|
-
console.log(colors.dim('Installing command and skill files...'));
|
|
135
100
|
console.log('');
|
|
136
101
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
'commands/lisa.md',
|
|
150
|
-
join(targetDir, '.opencode', 'commands', 'lisa.md'),
|
|
151
|
-
force
|
|
152
|
-
),
|
|
153
|
-
},
|
|
154
|
-
];
|
|
102
|
+
// Check if OpenCode is installed
|
|
103
|
+
const isOpenCodeInstalled = checkOpenCodeInstalled();
|
|
104
|
+
if (!isOpenCodeInstalled) {
|
|
105
|
+
console.log(colors.red('Error: OpenCode is not installed or not in PATH.'));
|
|
106
|
+
console.log('');
|
|
107
|
+
console.log('Please install OpenCode first:');
|
|
108
|
+
console.log(` ${colors.cyan('brew install opencode')} (macOS)`);
|
|
109
|
+
console.log(` ${colors.cyan('npm install -g @opencode-ai/cli')} (other platforms)`);
|
|
110
|
+
console.log('');
|
|
111
|
+
console.log('Then run this installer again.');
|
|
112
|
+
process.exit(1);
|
|
113
|
+
}
|
|
155
114
|
|
|
156
|
-
//
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
115
|
+
// Cleanup old file-based installs
|
|
116
|
+
cleanupOldInstalls(targetDir);
|
|
117
|
+
|
|
118
|
+
// Install command file for slash command autocomplete
|
|
119
|
+
try {
|
|
120
|
+
installCommandFile(targetDir);
|
|
121
|
+
} catch (err) {
|
|
122
|
+
console.log(colors.red(`Error: Failed to install command file.`));
|
|
123
|
+
console.log(colors.dim(` ${err.message}`));
|
|
124
|
+
console.log('');
|
|
125
|
+
console.log('Lisa cannot be installed without the command file.');
|
|
126
|
+
console.log('Please report this issue at https://github.com/fractalswift/lisa-simpson/issues');
|
|
127
|
+
process.exit(1);
|
|
162
128
|
}
|
|
163
129
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
130
|
+
// Update or create opencode.json
|
|
131
|
+
const configPath = join(targetDir, 'opencode.json');
|
|
132
|
+
let config = {};
|
|
133
|
+
let configExisted = false;
|
|
134
|
+
|
|
135
|
+
if (existsSync(configPath)) {
|
|
136
|
+
configExisted = true;
|
|
137
|
+
try {
|
|
138
|
+
const content = readFileSync(configPath, 'utf-8');
|
|
139
|
+
config = JSON.parse(content);
|
|
140
|
+
} catch (e) {
|
|
141
|
+
console.log(colors.red(`Error: ${configPath} exists but is not valid JSON.`));
|
|
142
|
+
console.log(colors.dim(` ${e.message}`));
|
|
143
|
+
process.exit(1);
|
|
144
|
+
}
|
|
168
145
|
}
|
|
169
146
|
|
|
170
|
-
|
|
147
|
+
// Ensure plugin array exists
|
|
148
|
+
if (!config.plugin) {
|
|
149
|
+
config.plugin = [];
|
|
150
|
+
}
|
|
171
151
|
|
|
172
|
-
if
|
|
173
|
-
|
|
174
|
-
console.log(
|
|
175
|
-
console.log('Lisa is now installed. You can use:');
|
|
152
|
+
// Check if already installed
|
|
153
|
+
if (config.plugin.includes(PLUGIN_NAME)) {
|
|
154
|
+
console.log(colors.yellow(`Lisa is already configured in this project.`));
|
|
176
155
|
console.log('');
|
|
177
|
-
console.log(`
|
|
178
|
-
console.log(` ${colors.cyan('/lisa help')} - Show available Lisa commands`);
|
|
179
|
-
console.log(` ${colors.cyan('/lisa list')} - List all your epics`);
|
|
156
|
+
console.log(`Run ${colors.cyan('opencode')} and type ${colors.cyan('/lisa help')} to get started!`);
|
|
180
157
|
console.log('');
|
|
181
|
-
|
|
182
|
-
} else {
|
|
183
|
-
console.log(colors.dim('Nothing to do - everything is already set up.'));
|
|
158
|
+
return;
|
|
184
159
|
}
|
|
185
160
|
|
|
186
|
-
|
|
187
|
-
|
|
161
|
+
// Add the plugin
|
|
162
|
+
config.plugin.push(PLUGIN_NAME);
|
|
188
163
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
Like Ralph Wiggum, but smarter. Lisa plans before she acts.
|
|
194
|
-
|
|
195
|
-
Usage:
|
|
196
|
-
npx opencode-lisa init [options]
|
|
164
|
+
// Add schema if not present
|
|
165
|
+
if (!config.$schema) {
|
|
166
|
+
config.$schema = 'https://opencode.ai/config.json';
|
|
167
|
+
}
|
|
197
168
|
|
|
198
|
-
|
|
199
|
-
|
|
169
|
+
// Write config
|
|
170
|
+
writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n');
|
|
200
171
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
Examples:
|
|
207
|
-
npx opencode-lisa init
|
|
208
|
-
npx opencode-lisa init --force
|
|
209
|
-
npx opencode-lisa init --global
|
|
172
|
+
if (configExisted) {
|
|
173
|
+
console.log(colors.green(` Updated: ${configPath} (added ${PLUGIN_NAME} to plugins)`));
|
|
174
|
+
} else {
|
|
175
|
+
console.log(colors.green(` Created: ${configPath}`));
|
|
176
|
+
}
|
|
210
177
|
|
|
211
|
-
|
|
212
|
-
|
|
178
|
+
console.log('');
|
|
179
|
+
console.log(colors.green('Done!'));
|
|
180
|
+
console.log('');
|
|
181
|
+
console.log('Lisa is now installed and will be auto-downloaded by OpenCode.');
|
|
182
|
+
console.log('');
|
|
183
|
+
console.log('Next steps:');
|
|
184
|
+
console.log(` 1. Run ${colors.cyan('opencode')} to start OpenCode`);
|
|
185
|
+
console.log(` 2. Type ${colors.cyan('/lisa help')} to see available commands`);
|
|
186
|
+
console.log(` 3. Type ${colors.cyan('/lisa <epic-name>}')} to create your first epic`);
|
|
187
|
+
console.log('');
|
|
213
188
|
}
|
|
214
189
|
|
|
215
190
|
async function main() {
|
|
216
191
|
const args = process.argv.slice(2);
|
|
217
192
|
|
|
218
193
|
// Parse flags
|
|
219
|
-
const
|
|
220
|
-
const isGlobal = args.includes('--global') || args.includes('-g');
|
|
194
|
+
const opencodeFlag = args.includes('--opencode');
|
|
221
195
|
const help = args.includes('--help') || args.includes('-h');
|
|
222
|
-
|
|
223
|
-
// Get command (first non-flag argument)
|
|
224
|
-
const command = args.find((arg) => !arg.startsWith('-'));
|
|
225
196
|
|
|
226
|
-
if (help ||
|
|
197
|
+
if (help || args.length === 0) {
|
|
227
198
|
printHelp();
|
|
228
199
|
process.exit(0);
|
|
229
200
|
}
|
|
230
201
|
|
|
231
|
-
if (
|
|
232
|
-
console.
|
|
233
|
-
console.
|
|
202
|
+
if (!opencodeFlag) {
|
|
203
|
+
console.log(colors.red(`Unknown flag: ${args.find(a => a.startsWith('--')) || args[0]}`));
|
|
204
|
+
console.log(`Run ${colors.cyan(`npx ${PLUGIN_NAME} --help`)} for usage.`);
|
|
234
205
|
process.exit(1);
|
|
235
206
|
}
|
|
236
207
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
if (isGlobal) {
|
|
240
|
-
const home = process.env.HOME || process.env.USERPROFILE;
|
|
241
|
-
targetDir = join(home, '.config', 'opencode');
|
|
242
|
-
} else {
|
|
243
|
-
targetDir = process.cwd();
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
await init(targetDir, { force, global: isGlobal });
|
|
208
|
+
const targetDir = process.cwd();
|
|
209
|
+
await install(targetDir);
|
|
247
210
|
}
|
|
248
211
|
|
|
249
212
|
main().catch((err) => {
|
package/dist/index.js
CHANGED
|
@@ -12390,31 +12390,33 @@ The input format is: \`<epic-name> [mode]\`
|
|
|
12390
12390
|
|
|
12391
12391
|
### If no arguments or \`help\`:
|
|
12392
12392
|
|
|
12393
|
-
If the user runs \`/lisa\` with no arguments, or \`/lisa help\`,
|
|
12393
|
+
If the user runs \`/lisa\` with no arguments, or \`/lisa help\`, IMMEDIATELY output EXACTLY this text (verbatim, no modifications, no tool calls):
|
|
12394
12394
|
|
|
12395
|
-
|
|
12396
|
-
Lisa - Intelligent Epic Workflow
|
|
12395
|
+
---
|
|
12397
12396
|
|
|
12398
|
-
|
|
12397
|
+
**Lisa - Intelligent Epic Workflow**
|
|
12399
12398
|
|
|
12400
|
-
|
|
12401
|
-
/lisa <name> - Continue or create an epic (interactive)
|
|
12402
|
-
/lisa <name> spec - Create/view the spec only
|
|
12403
|
-
/lisa <name> status - Show detailed epic status
|
|
12404
|
-
/lisa <name> yolo - Auto-execute mode (no confirmations)
|
|
12405
|
-
/lisa config view - View current configuration
|
|
12406
|
-
/lisa config init - Initialize config with defaults
|
|
12407
|
-
/lisa config reset - Reset config to defaults
|
|
12399
|
+
**Available Commands:**
|
|
12408
12400
|
|
|
12409
|
-
|
|
12410
|
-
|
|
12411
|
-
|
|
12412
|
-
|
|
12401
|
+
\`/lisa list\` - List all epics and their status
|
|
12402
|
+
\`/lisa <name>\` - Continue or create an epic (interactive)
|
|
12403
|
+
\`/lisa <name> spec\` - Create/view the spec only
|
|
12404
|
+
\`/lisa <name> status\` - Show detailed epic status
|
|
12405
|
+
\`/lisa <name> yolo\` - Auto-execute mode (no confirmations)
|
|
12406
|
+
\`/lisa config view\` - View current configuration
|
|
12407
|
+
\`/lisa config init\` - Initialize config with defaults
|
|
12408
|
+
\`/lisa config reset\` - Reset config to defaults
|
|
12413
12409
|
|
|
12414
|
-
|
|
12415
|
-
|
|
12410
|
+
**Examples:**
|
|
12411
|
+
- \`/lisa list\` - See all your epics
|
|
12412
|
+
- \`/lisa auth-system\` - Start or continue the auth-system epic
|
|
12413
|
+
- \`/lisa auth-system yolo\` - Run auth-system in full auto mode
|
|
12414
|
+
|
|
12415
|
+
**Get started:** \`/lisa <epic-name>\`
|
|
12416
|
+
|
|
12417
|
+
---
|
|
12416
12418
|
|
|
12417
|
-
**
|
|
12419
|
+
**CRITICAL: Output the above help text EXACTLY as shown. Do not add explanations, do not call tools, do not be creative. Just show the menu and stop.**
|
|
12418
12420
|
|
|
12419
12421
|
### Otherwise, parse the arguments:
|
|
12420
12422
|
|
package/package.json
CHANGED
|
@@ -1,17 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-lisa",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "Lisa - intelligent epic workflow plugin for OpenCode. Like Ralph Wiggum, but smarter.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"bin": {
|
|
8
8
|
"opencode-lisa": "./bin/cli.js"
|
|
9
9
|
},
|
|
10
|
-
"exports": {
|
|
11
|
-
".": {
|
|
12
|
-
"import": "./dist/index.js"
|
|
13
|
-
}
|
|
14
|
-
},
|
|
15
10
|
"files": [
|
|
16
11
|
"dist",
|
|
17
12
|
"bin",
|
|
@@ -45,14 +40,8 @@
|
|
|
45
40
|
"engines": {
|
|
46
41
|
"node": ">=18.0.0"
|
|
47
42
|
},
|
|
48
|
-
"peerDependencies": {
|
|
49
|
-
"@opencode-ai/plugin": ">=1.0.0"
|
|
50
|
-
},
|
|
51
43
|
"devDependencies": {
|
|
52
44
|
"@opencode-ai/plugin": "^1.1.25",
|
|
53
45
|
"typescript": "^5.0.0"
|
|
54
|
-
},
|
|
55
|
-
"dependencies": {
|
|
56
|
-
"opencode-lisa": "^0.2.1"
|
|
57
46
|
}
|
|
58
47
|
}
|
|
@@ -1,841 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: lisa
|
|
3
|
-
description: Lisa - intelligent epic workflow with spec, research, plan, and execute phases. Smarter than Ralph.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Lisa - Intelligent Epic Workflow
|
|
7
|
-
|
|
8
|
-
A structured approach to implementing large features by breaking them into phases: spec, research, plan, and execute.
|
|
9
|
-
|
|
10
|
-
Like the Ralph Wiggum pattern, but smarter. Lisa plans before she acts.
|
|
11
|
-
|
|
12
|
-
## Working Directory
|
|
13
|
-
|
|
14
|
-
Epics are stored in `.lisa/epics/` relative to **where you run `opencode`**.
|
|
15
|
-
|
|
16
|
-
Run opencode from your project root and epics will be at `your-project/.lisa/epics/`.
|
|
17
|
-
|
|
18
|
-
**Example structure:**
|
|
19
|
-
```
|
|
20
|
-
my-project/ <- run `opencode` from here
|
|
21
|
-
├── .lisa/
|
|
22
|
-
│ ├── config.jsonc
|
|
23
|
-
│ ├── .gitignore
|
|
24
|
-
│ └── epics/
|
|
25
|
-
│ └── my-feature/
|
|
26
|
-
│ ├── .state
|
|
27
|
-
│ ├── spec.md
|
|
28
|
-
│ └── tasks/
|
|
29
|
-
├── src/
|
|
30
|
-
└── package.json
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
---
|
|
34
|
-
|
|
35
|
-
## Parse Arguments
|
|
36
|
-
|
|
37
|
-
The input format is: `<epic-name> [mode]`
|
|
38
|
-
|
|
39
|
-
### If no arguments or `help`:
|
|
40
|
-
|
|
41
|
-
If the user runs `/lisa` with no arguments, or `/lisa help`, immediately respond with this help menu (no tool calls needed):
|
|
42
|
-
|
|
43
|
-
```
|
|
44
|
-
Lisa - Intelligent Epic Workflow
|
|
45
|
-
|
|
46
|
-
Available Commands:
|
|
47
|
-
|
|
48
|
-
/lisa list - List all epics and their status
|
|
49
|
-
/lisa <name> - Continue or create an epic (interactive)
|
|
50
|
-
/lisa <name> spec - Create/view the spec only
|
|
51
|
-
/lisa <name> status - Show detailed epic status
|
|
52
|
-
/lisa <name> yolo - Auto-execute mode (no confirmations)
|
|
53
|
-
/lisa config view - View current configuration
|
|
54
|
-
/lisa config init - Initialize config with defaults
|
|
55
|
-
/lisa config reset - Reset config to defaults
|
|
56
|
-
|
|
57
|
-
Examples:
|
|
58
|
-
/lisa list - See all your epics
|
|
59
|
-
/lisa auth-system - Start or continue the auth-system epic
|
|
60
|
-
/lisa auth-system yolo - Run auth-system in full auto mode
|
|
61
|
-
|
|
62
|
-
Get started: /lisa <epic-name>
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
**Stop here. Do not call any tools or do anything else.**
|
|
66
|
-
|
|
67
|
-
### Otherwise, parse the arguments:
|
|
68
|
-
|
|
69
|
-
**Modes:**
|
|
70
|
-
- `list` → List all epics
|
|
71
|
-
- `config <action>` → Config management (view/init/reset)
|
|
72
|
-
- `<name>` (no mode) → Default mode with checkpoints
|
|
73
|
-
- `<name> spec` → Just create/view spec
|
|
74
|
-
- `<name> yolo` → Full auto, no checkpoints
|
|
75
|
-
- `<name> status` → Show status
|
|
76
|
-
|
|
77
|
-
**Examples:**
|
|
78
|
-
- `list` → list all epics
|
|
79
|
-
- `config view` → show config
|
|
80
|
-
- `my-feature` → default mode
|
|
81
|
-
- `my-feature spec` → spec only
|
|
82
|
-
- `my-feature yolo` → full auto
|
|
83
|
-
- `my-feature status` → show status
|
|
84
|
-
|
|
85
|
-
---
|
|
86
|
-
|
|
87
|
-
## Mode: config
|
|
88
|
-
|
|
89
|
-
Handle config subcommands using the `lisa_config` tool:
|
|
90
|
-
|
|
91
|
-
- `config view` → Call `lisa_config(action: "view")` and display the result
|
|
92
|
-
- `config init` → Call `lisa_config(action: "init")` and confirm creation
|
|
93
|
-
- `config reset` → Call `lisa_config(action: "reset")` and confirm reset
|
|
94
|
-
|
|
95
|
-
After the tool returns, display the result in a user-friendly format.
|
|
96
|
-
|
|
97
|
-
---
|
|
98
|
-
|
|
99
|
-
## Mode: list
|
|
100
|
-
|
|
101
|
-
**Use the `list_epics` tool** to quickly get all epics and their status.
|
|
102
|
-
|
|
103
|
-
Display the results in a formatted list showing:
|
|
104
|
-
- Epic name
|
|
105
|
-
- Current phase (spec/research/plan/execute/complete)
|
|
106
|
-
- Task progress (X/Y done) if in execute phase
|
|
107
|
-
- Whether yolo mode is active
|
|
108
|
-
|
|
109
|
-
**If no epics found:**
|
|
110
|
-
> "No epics found. Start one with `/lisa <name>`"
|
|
111
|
-
|
|
112
|
-
---
|
|
113
|
-
|
|
114
|
-
## Mode: status
|
|
115
|
-
|
|
116
|
-
**Use the `get_epic_status` tool** to quickly get detailed status.
|
|
117
|
-
|
|
118
|
-
Display the results showing:
|
|
119
|
-
- Current phase
|
|
120
|
-
- Which artifacts exist (spec.md, research.md, plan.md)
|
|
121
|
-
- Task breakdown: done, in-progress, pending, blocked
|
|
122
|
-
- Yolo mode status (if active)
|
|
123
|
-
- Suggested next action
|
|
124
|
-
|
|
125
|
-
**If epic doesn't exist:**
|
|
126
|
-
> "Epic '<name>' not found. Start it with `/lisa <name>`"
|
|
127
|
-
|
|
128
|
-
---
|
|
129
|
-
|
|
130
|
-
## Mode: spec
|
|
131
|
-
|
|
132
|
-
Interactive spec creation only. Does NOT continue to research/plan/execute.
|
|
133
|
-
|
|
134
|
-
### If spec already exists:
|
|
135
|
-
|
|
136
|
-
Read and display the existing spec, then:
|
|
137
|
-
|
|
138
|
-
> "Spec already exists at `.lisa/epics/<name>/spec.md`. You can:
|
|
139
|
-
> - Edit it directly in your editor
|
|
140
|
-
> - Delete it and run `/lisa <name> spec` again to start over
|
|
141
|
-
> - Run `/lisa <name>` to continue with research and planning"
|
|
142
|
-
|
|
143
|
-
### If no spec exists:
|
|
144
|
-
|
|
145
|
-
Have an interactive conversation to define the spec. Cover:
|
|
146
|
-
|
|
147
|
-
1. **Goal** - What are we trying to achieve? Why?
|
|
148
|
-
2. **Scope** - What's included? What's explicitly out of scope?
|
|
149
|
-
3. **Acceptance Criteria** - How do we know when it's done?
|
|
150
|
-
4. **Technical Constraints** - Any specific technologies, patterns, or limitations?
|
|
151
|
-
|
|
152
|
-
Be conversational. Ask clarifying questions. Push back if scope is too large or vague.
|
|
153
|
-
|
|
154
|
-
**Keep it concise** - aim for 20-50 lines. Focus on "what" and "why", not "how".
|
|
155
|
-
|
|
156
|
-
### When conversation is complete:
|
|
157
|
-
|
|
158
|
-
Summarize the spec and ask:
|
|
159
|
-
|
|
160
|
-
> "Here's the spec:
|
|
161
|
-
>
|
|
162
|
-
> [formatted spec]
|
|
163
|
-
>
|
|
164
|
-
> Ready to save to `.lisa/epics/<name>/spec.md`?"
|
|
165
|
-
|
|
166
|
-
On confirmation, create the directory and save:
|
|
167
|
-
|
|
168
|
-
```
|
|
169
|
-
.lisa/epics/<name>/
|
|
170
|
-
spec.md
|
|
171
|
-
.state
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
**spec.md format:**
|
|
175
|
-
```markdown
|
|
176
|
-
# Epic: <name>
|
|
177
|
-
|
|
178
|
-
## Goal
|
|
179
|
-
[What we're building and why - 1-2 sentences]
|
|
180
|
-
|
|
181
|
-
## Scope
|
|
182
|
-
- [What's included]
|
|
183
|
-
- [What's included]
|
|
184
|
-
|
|
185
|
-
### Out of Scope
|
|
186
|
-
- [What we're NOT doing]
|
|
187
|
-
|
|
188
|
-
## Acceptance Criteria
|
|
189
|
-
- [ ] [Measurable criterion]
|
|
190
|
-
- [ ] [Measurable criterion]
|
|
191
|
-
|
|
192
|
-
## Technical Constraints
|
|
193
|
-
- [Any constraints, or "None"]
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
**.state format (JSON):**
|
|
197
|
-
```json
|
|
198
|
-
{
|
|
199
|
-
"name": "<name>",
|
|
200
|
-
"currentPhase": "spec",
|
|
201
|
-
"specComplete": true,
|
|
202
|
-
"researchComplete": false,
|
|
203
|
-
"planComplete": false,
|
|
204
|
-
"executeComplete": false,
|
|
205
|
-
"lastUpdated": "<timestamp>"
|
|
206
|
-
}
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
After saving:
|
|
210
|
-
> "Spec saved to `.lisa/epics/<name>/spec.md`
|
|
211
|
-
>
|
|
212
|
-
> Next steps:
|
|
213
|
-
> - Run `/lisa <name>` to continue with research and planning
|
|
214
|
-
> - Run `/lisa <name> yolo` for full auto execution"
|
|
215
|
-
|
|
216
|
-
---
|
|
217
|
-
|
|
218
|
-
## Mode: default (with checkpoints)
|
|
219
|
-
|
|
220
|
-
This is the main interactive mode. It guides you through each phase with approval checkpoints.
|
|
221
|
-
|
|
222
|
-
### Step 1: Ensure spec exists
|
|
223
|
-
|
|
224
|
-
**If no spec:**
|
|
225
|
-
Run the spec conversation (same as spec mode). After saving, continue to step 2.
|
|
226
|
-
|
|
227
|
-
**If spec exists:**
|
|
228
|
-
Read and briefly summarize it, then continue to step 2.
|
|
229
|
-
|
|
230
|
-
### Step 2: Research phase
|
|
231
|
-
|
|
232
|
-
**If research.md already exists:**
|
|
233
|
-
> "Research already complete. Proceeding to planning..."
|
|
234
|
-
Skip to step 3.
|
|
235
|
-
|
|
236
|
-
**If research not done:**
|
|
237
|
-
> "Ready to start research? I'll explore the codebase to understand what's needed for this epic."
|
|
238
|
-
|
|
239
|
-
Wait for confirmation. On "yes" or similar:
|
|
240
|
-
|
|
241
|
-
1. Read spec.md
|
|
242
|
-
2. Explore the codebase using available tools (LSP, grep, glob, file reads)
|
|
243
|
-
3. Document findings
|
|
244
|
-
4. Save to `.lisa/epics/<name>/research.md`
|
|
245
|
-
5. Update .state
|
|
246
|
-
|
|
247
|
-
**research.md format:**
|
|
248
|
-
```markdown
|
|
249
|
-
# Research: <name>
|
|
250
|
-
|
|
251
|
-
## Overview
|
|
252
|
-
[1-2 sentence summary of findings]
|
|
253
|
-
|
|
254
|
-
## Relevant Files
|
|
255
|
-
- `path/to/file.ts` - [why it's relevant]
|
|
256
|
-
- `path/to/file.ts` - [why it's relevant]
|
|
257
|
-
|
|
258
|
-
## Existing Patterns
|
|
259
|
-
[How similar things are done in this codebase]
|
|
260
|
-
|
|
261
|
-
## Dependencies
|
|
262
|
-
[External packages or internal modules needed]
|
|
263
|
-
|
|
264
|
-
## Technical Findings
|
|
265
|
-
[Key discoveries that affect implementation]
|
|
266
|
-
|
|
267
|
-
## Recommendations
|
|
268
|
-
[Suggested approach based on findings]
|
|
269
|
-
```
|
|
270
|
-
|
|
271
|
-
After saving:
|
|
272
|
-
> "Research complete and saved. Found X relevant files. Key insight: [one line summary]"
|
|
273
|
-
|
|
274
|
-
### Step 3: Plan phase
|
|
275
|
-
|
|
276
|
-
**If plan.md already exists:**
|
|
277
|
-
> "Plan already complete with X tasks. Proceeding to execution..."
|
|
278
|
-
Skip to step 4.
|
|
279
|
-
|
|
280
|
-
**If plan not done:**
|
|
281
|
-
> "Ready to create the implementation plan?"
|
|
282
|
-
|
|
283
|
-
Wait for confirmation. On "yes" or similar:
|
|
284
|
-
|
|
285
|
-
1. Read spec.md and research.md
|
|
286
|
-
2. Break down into discrete tasks (aim for 1-5 files per task, ~30 min of work each)
|
|
287
|
-
3. Define dependencies between tasks
|
|
288
|
-
4. Save plan.md and individual task files
|
|
289
|
-
5. Update .state
|
|
290
|
-
|
|
291
|
-
**plan.md format:**
|
|
292
|
-
```markdown
|
|
293
|
-
# Plan: <name>
|
|
294
|
-
|
|
295
|
-
## Overview
|
|
296
|
-
[1-2 sentence summary of approach]
|
|
297
|
-
|
|
298
|
-
## Tasks
|
|
299
|
-
|
|
300
|
-
1. [Task name] - tasks/01-[slug].md
|
|
301
|
-
2. [Task name] - tasks/02-[slug].md
|
|
302
|
-
3. [Task name] - tasks/03-[slug].md
|
|
303
|
-
|
|
304
|
-
## Dependencies
|
|
305
|
-
|
|
306
|
-
- 01: []
|
|
307
|
-
- 02: [01]
|
|
308
|
-
- 03: [01]
|
|
309
|
-
- 04: [02, 03]
|
|
310
|
-
|
|
311
|
-
## Risks
|
|
312
|
-
- [Risk and mitigation, or "None identified"]
|
|
313
|
-
```
|
|
314
|
-
|
|
315
|
-
**Task file format (tasks/XX-slug.md):**
|
|
316
|
-
```markdown
|
|
317
|
-
# Task X: [Name]
|
|
318
|
-
|
|
319
|
-
## Status: pending
|
|
320
|
-
|
|
321
|
-
## Goal
|
|
322
|
-
[What this task accomplishes - 1-2 sentences]
|
|
323
|
-
|
|
324
|
-
## Files
|
|
325
|
-
- path/to/file1.ts
|
|
326
|
-
- path/to/file2.ts
|
|
327
|
-
|
|
328
|
-
## Steps
|
|
329
|
-
1. [Concrete step]
|
|
330
|
-
2. [Concrete step]
|
|
331
|
-
3. [Concrete step]
|
|
332
|
-
|
|
333
|
-
## Done When
|
|
334
|
-
- [ ] [Testable criterion]
|
|
335
|
-
- [ ] [Testable criterion]
|
|
336
|
-
```
|
|
337
|
-
|
|
338
|
-
After saving:
|
|
339
|
-
> "Plan created with X tasks:
|
|
340
|
-
> 1. [task 1 name]
|
|
341
|
-
> 2. [task 2 name]
|
|
342
|
-
> ...
|
|
343
|
-
>
|
|
344
|
-
> Saved to `.lisa/epics/<name>/plan.md`"
|
|
345
|
-
|
|
346
|
-
### Step 4: Execute phase
|
|
347
|
-
|
|
348
|
-
**Use `get_available_tasks` tool** to quickly see what's ready to run.
|
|
349
|
-
|
|
350
|
-
**If all tasks done (available and blocked both empty):**
|
|
351
|
-
> "All tasks complete! Epic finished."
|
|
352
|
-
Stop.
|
|
353
|
-
|
|
354
|
-
**If tasks remain:**
|
|
355
|
-
Show task summary from the tool output and ask:
|
|
356
|
-
> "Ready to execute? X tasks remaining:
|
|
357
|
-
> - Available now: [from available list]
|
|
358
|
-
> - Blocked by dependencies: [from blocked list]"
|
|
359
|
-
|
|
360
|
-
Wait for confirmation. On "yes" or similar:
|
|
361
|
-
|
|
362
|
-
**Execute tasks using `build_task_context` + Task tool:**
|
|
363
|
-
|
|
364
|
-
Tasks with satisfied dependencies can be executed in **parallel** (the `available` list from `get_available_tasks` shows all tasks that are ready). Tasks whose dependencies aren't met yet are in the `blocked` list and must wait.
|
|
365
|
-
|
|
366
|
-
For each task in the `available` list:
|
|
367
|
-
1. Call `build_task_context(epicName, taskId)` to get the prompt
|
|
368
|
-
2. Call the Task tool with the prompt to spawn a sub-agent
|
|
369
|
-
3. After sub-agent(s) complete, call `get_available_tasks` again to refresh the list
|
|
370
|
-
4. If a task isn't done, retry up to 3 times, then mark blocked
|
|
371
|
-
5. Repeat until all tasks done
|
|
372
|
-
|
|
373
|
-
**Note:** If executing in parallel, each sub-agent gets the same context snapshot. Their reports will be available for subsequent tasks.
|
|
374
|
-
|
|
375
|
-
**On task failure (after 3 attempts):**
|
|
376
|
-
- Mark task as `blocked` in the task file
|
|
377
|
-
- Add `## Blocked Reason: [why]`
|
|
378
|
-
- Continue with other available tasks
|
|
379
|
-
|
|
380
|
-
**On all tasks complete:**
|
|
381
|
-
> "Epic complete! All X tasks finished.
|
|
382
|
-
>
|
|
383
|
-
> Summary of changes:
|
|
384
|
-
> - [file]: [what changed]
|
|
385
|
-
> - [file]: [what changed]"
|
|
386
|
-
|
|
387
|
-
---
|
|
388
|
-
|
|
389
|
-
## Mode: yolo (full auto)
|
|
390
|
-
|
|
391
|
-
Full automatic execution with no checkpoints. Requires spec to exist.
|
|
392
|
-
|
|
393
|
-
**IMPORTANT:** In yolo mode, the Lisa plugin monitors for session idle events and automatically continues execution until all tasks are complete. You don't need to worry about session limits - just keep working and the plugin handles continuation.
|
|
394
|
-
|
|
395
|
-
### YOLO MODE RULES - READ CAREFULLY
|
|
396
|
-
|
|
397
|
-
When in yolo mode, you MUST follow these rules strictly:
|
|
398
|
-
|
|
399
|
-
1. **NEVER stop to summarize progress** - Don't say "I've completed X, Y tasks remain". Just keep working.
|
|
400
|
-
|
|
401
|
-
2. **NEVER ask for confirmation** - Don't say "Ready to continue?" or "Should I proceed?". Just proceed.
|
|
402
|
-
|
|
403
|
-
3. **NEVER explain what you're about to do** - Don't narrate. Execute.
|
|
404
|
-
|
|
405
|
-
4. **ALWAYS execute the next task immediately** - After one task completes, immediately call `get_available_tasks` and start the next one.
|
|
406
|
-
|
|
407
|
-
5. **ONLY stop when truly done** - You stop ONLY when:
|
|
408
|
-
- All tasks have `## Status: done`, OR
|
|
409
|
-
- All remaining tasks are `## Status: blocked`
|
|
410
|
-
|
|
411
|
-
6. **Treat each response as a work session** - Your goal is to make maximum progress before your response ends. Execute as many tasks as possible.
|
|
412
|
-
|
|
413
|
-
**Why these rules matter:** Yolo mode is for autonomous, unattended execution. The user has walked away. Every time you stop to summarize or ask a question, you break the automation and waste the user's time.
|
|
414
|
-
|
|
415
|
-
**If you're unsure, keep working.** It's better to complete an extra task than to stop and ask.
|
|
416
|
-
|
|
417
|
-
### If no spec exists:
|
|
418
|
-
|
|
419
|
-
> "No spec found at `.lisa/epics/<name>/spec.md`.
|
|
420
|
-
>
|
|
421
|
-
> Create one first:
|
|
422
|
-
> - Interactively: `/lisa <name> spec`
|
|
423
|
-
> - Manually: Create `.lisa/epics/<name>/spec.md`"
|
|
424
|
-
|
|
425
|
-
Stop. Do not proceed.
|
|
426
|
-
|
|
427
|
-
### If spec exists:
|
|
428
|
-
|
|
429
|
-
**Step 1: Activate yolo mode in .state**
|
|
430
|
-
|
|
431
|
-
Read the current `.lisa/epics/<name>/.state` file and add the `yolo` configuration:
|
|
432
|
-
|
|
433
|
-
```json
|
|
434
|
-
{
|
|
435
|
-
"name": "<name>",
|
|
436
|
-
"currentPhase": "...",
|
|
437
|
-
"specComplete": true,
|
|
438
|
-
"researchComplete": false,
|
|
439
|
-
"planComplete": false,
|
|
440
|
-
"executeComplete": false,
|
|
441
|
-
"lastUpdated": "<timestamp>",
|
|
442
|
-
"yolo": {
|
|
443
|
-
"active": true,
|
|
444
|
-
"iteration": 1,
|
|
445
|
-
"maxIterations": 100,
|
|
446
|
-
"startedAt": "<current ISO timestamp>"
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
```
|
|
450
|
-
|
|
451
|
-
This tells the Lisa plugin to automatically continue the session when you finish responding.
|
|
452
|
-
|
|
453
|
-
**Step 2: Run all phases without asking for confirmation:**
|
|
454
|
-
|
|
455
|
-
1. **Research** (if not done) - explore codebase, save research.md
|
|
456
|
-
2. **Plan** (if not done) - create plan.md and task files
|
|
457
|
-
3. **Execute** - use `get_available_tasks` + `build_task_context` + Task tool
|
|
458
|
-
|
|
459
|
-
**Execute tasks using `build_task_context` + Task tool:**
|
|
460
|
-
|
|
461
|
-
Tasks with satisfied dependencies can be executed in **parallel** if desired.
|
|
462
|
-
|
|
463
|
-
1. Call `get_available_tasks(epicName)` to get the list of ready tasks
|
|
464
|
-
2. For each task in the `available` list (can parallelize):
|
|
465
|
-
- Call `build_task_context(epicName, taskId)` to get the prompt
|
|
466
|
-
- Call the Task tool with the prompt to spawn a sub-agent
|
|
467
|
-
3. After sub-agent(s) complete, call `get_available_tasks` again to refresh
|
|
468
|
-
4. If a task isn't done, retry up to 3 times, then mark blocked
|
|
469
|
-
5. Repeat until all tasks done or all blocked
|
|
470
|
-
|
|
471
|
-
The plugin will automatically continue the session if context fills up.
|
|
472
|
-
|
|
473
|
-
**REMEMBER THE YOLO RULES:** Don't stop to summarize. Don't ask questions. Just keep executing tasks until they're all done or blocked.
|
|
474
|
-
|
|
475
|
-
**On all tasks complete:**
|
|
476
|
-
- Update .state: set `executeComplete: true` and `yolo.active: false`
|
|
477
|
-
> "Epic complete! All X tasks finished."
|
|
478
|
-
|
|
479
|
-
**On task blocked (after 3 attempts):**
|
|
480
|
-
- Mark as blocked in the task file, continue with others
|
|
481
|
-
- If all remaining tasks blocked:
|
|
482
|
-
- Update .state: set `yolo.active: false`
|
|
483
|
-
- Report which tasks are blocked and why
|
|
484
|
-
|
|
485
|
-
---
|
|
486
|
-
|
|
487
|
-
## Shared: Task Execution Logic
|
|
488
|
-
|
|
489
|
-
**IMPORTANT: Use the `build_task_context` tool + Task tool for each task.**
|
|
490
|
-
|
|
491
|
-
This pattern ensures each task runs with fresh context in a sub-agent:
|
|
492
|
-
- Fresh context for each task (no accumulated cruft)
|
|
493
|
-
- Proper handoff between tasks via reports
|
|
494
|
-
- Consistent execution pattern
|
|
495
|
-
|
|
496
|
-
### Execution Flow (Orchestrator)
|
|
497
|
-
|
|
498
|
-
As the orchestrator, you manage the overall flow:
|
|
499
|
-
|
|
500
|
-
1. **Read plan.md** to understand task order and dependencies
|
|
501
|
-
2. **For each available task** (dependencies satisfied, not blocked):
|
|
502
|
-
|
|
503
|
-
**Step A: Build context**
|
|
504
|
-
```
|
|
505
|
-
Call build_task_context with:
|
|
506
|
-
- epicName: the epic name
|
|
507
|
-
- taskId: the task number (e.g., "01", "02")
|
|
508
|
-
```
|
|
509
|
-
This returns a `prompt` field with the full context.
|
|
510
|
-
|
|
511
|
-
**Step B: Execute with sub-agent**
|
|
512
|
-
```
|
|
513
|
-
Call the Task tool with:
|
|
514
|
-
- description: "Execute task {taskId} of epic {epicName}"
|
|
515
|
-
- prompt: [the prompt returned from build_task_context]
|
|
516
|
-
```
|
|
517
|
-
|
|
518
|
-
3. **After sub-agent completes**, check the task file:
|
|
519
|
-
- If `## Status: done` → Move to next task
|
|
520
|
-
- If not done → Retry (up to 3 times) or mark blocked
|
|
521
|
-
4. **Repeat** until all tasks done or all remaining tasks blocked
|
|
522
|
-
|
|
523
|
-
### What the Sub-Agent Does
|
|
524
|
-
|
|
525
|
-
The sub-agent (spawned via Task tool) receives full context and:
|
|
526
|
-
|
|
527
|
-
1. **Reads the context**: spec, research, plan, all previous task files with reports
|
|
528
|
-
2. **Executes the task steps**
|
|
529
|
-
3. **Updates the task file**:
|
|
530
|
-
- Changes `## Status: pending` to `## Status: done`
|
|
531
|
-
- Adds a `## Report` section (see format below)
|
|
532
|
-
4. **May update future tasks** if the plan needs changes
|
|
533
|
-
5. **Confirms completion** when done
|
|
534
|
-
|
|
535
|
-
### Task File Format (with Report)
|
|
536
|
-
|
|
537
|
-
After completion, a task file should look like:
|
|
538
|
-
|
|
539
|
-
```markdown
|
|
540
|
-
# Task 01: [Name]
|
|
541
|
-
|
|
542
|
-
## Status: done
|
|
543
|
-
|
|
544
|
-
## Goal
|
|
545
|
-
[What this task accomplishes]
|
|
546
|
-
|
|
547
|
-
## Files
|
|
548
|
-
- path/to/file1.ts
|
|
549
|
-
- path/to/file2.ts
|
|
550
|
-
|
|
551
|
-
## Steps
|
|
552
|
-
1. [Concrete step]
|
|
553
|
-
2. [Concrete step]
|
|
554
|
-
|
|
555
|
-
## Done When
|
|
556
|
-
- [x] [Criterion - now checked]
|
|
557
|
-
- [x] [Criterion - now checked]
|
|
558
|
-
|
|
559
|
-
## Report
|
|
560
|
-
|
|
561
|
-
### What Was Done
|
|
562
|
-
- Created X component
|
|
563
|
-
- Added Y functionality
|
|
564
|
-
- Configured Z
|
|
565
|
-
|
|
566
|
-
### Decisions Made
|
|
567
|
-
- Chose approach A over B because [reason]
|
|
568
|
-
- Used library X for [reason]
|
|
569
|
-
|
|
570
|
-
### Issues / Notes for Next Task
|
|
571
|
-
- The API returns data in format X, next task should handle this
|
|
572
|
-
- Found that Y needs to be done differently than planned
|
|
573
|
-
|
|
574
|
-
### Files Changed
|
|
575
|
-
- src/components/Foo.tsx (new)
|
|
576
|
-
- src/hooks/useBar.ts (modified)
|
|
577
|
-
- package.json (added dependency)
|
|
578
|
-
```
|
|
579
|
-
|
|
580
|
-
### Handling Failures
|
|
581
|
-
|
|
582
|
-
When `execute_epic_task` returns `status: "failed"`:
|
|
583
|
-
|
|
584
|
-
1. **Check the summary** for what went wrong
|
|
585
|
-
2. **Decide**:
|
|
586
|
-
- Retry (up to 3 times) if it seems like a transient issue
|
|
587
|
-
- Mark as blocked if fundamentally broken
|
|
588
|
-
- Revise the plan if the approach is wrong
|
|
589
|
-
|
|
590
|
-
To mark as blocked:
|
|
591
|
-
```markdown
|
|
592
|
-
## Status: blocked
|
|
593
|
-
|
|
594
|
-
## Blocked Reason
|
|
595
|
-
[Explanation of why this task cannot proceed]
|
|
596
|
-
```
|
|
597
|
-
|
|
598
|
-
### On discovering the plan needs changes:
|
|
599
|
-
|
|
600
|
-
If during execution you realize:
|
|
601
|
-
- A task's approach is fundamentally wrong (not just a bug to fix)
|
|
602
|
-
- Tasks are missing that should have been included
|
|
603
|
-
- Dependencies are incorrect
|
|
604
|
-
- The order should change
|
|
605
|
-
- New information invalidates earlier assumptions
|
|
606
|
-
|
|
607
|
-
**You may update the plan. The plan is a living document, not a rigid contract.**
|
|
608
|
-
|
|
609
|
-
1. **Update the affected task file(s)** in `tasks/`:
|
|
610
|
-
- Revise steps if the approach needs changing
|
|
611
|
-
- Update "Files" if different files are involved
|
|
612
|
-
- Update "Done When" if criteria need adjusting
|
|
613
|
-
|
|
614
|
-
2. **Update `plan.md`** if:
|
|
615
|
-
- Adding new tasks (create new task files too)
|
|
616
|
-
- Removing tasks (mark as `## Status: cancelled` with reason)
|
|
617
|
-
- Changing dependencies
|
|
618
|
-
|
|
619
|
-
3. **Document the change** in the task file:
|
|
620
|
-
```markdown
|
|
621
|
-
## Plan Revision
|
|
622
|
-
- Changed: [what changed]
|
|
623
|
-
- Reason: [why the original approach didn't work]
|
|
624
|
-
- Timestamp: [now]
|
|
625
|
-
```
|
|
626
|
-
|
|
627
|
-
4. **Continue execution** with the revised plan
|
|
628
|
-
|
|
629
|
-
**Key principle:** Do NOT keep retrying a broken approach. If something fundamentally doesn't work, adapt the plan. It's better to revise and succeed than to stubbornly fail.
|
|
630
|
-
|
|
631
|
-
---
|
|
632
|
-
|
|
633
|
-
## Shared: Parsing Dependencies
|
|
634
|
-
|
|
635
|
-
The plan.md Dependencies section looks like:
|
|
636
|
-
```markdown
|
|
637
|
-
## Dependencies
|
|
638
|
-
- 01: []
|
|
639
|
-
- 02: [01]
|
|
640
|
-
- 03: [01, 02]
|
|
641
|
-
```
|
|
642
|
-
|
|
643
|
-
A task is **available** when:
|
|
644
|
-
1. Status is `pending` (or `in-progress` with progress notes)
|
|
645
|
-
2. All tasks in its dependency list have status `done`
|
|
646
|
-
|
|
647
|
-
A task is **blocked** when:
|
|
648
|
-
1. Status is `blocked`, OR
|
|
649
|
-
2. Any dependency is not `done` and not expected to complete
|
|
650
|
-
|
|
651
|
-
---
|
|
652
|
-
|
|
653
|
-
## State File (.state)
|
|
654
|
-
|
|
655
|
-
Track epic progress in `.lisa/epics/<name>/.state`:
|
|
656
|
-
|
|
657
|
-
```json
|
|
658
|
-
{
|
|
659
|
-
"name": "<name>",
|
|
660
|
-
"currentPhase": "execute",
|
|
661
|
-
"specComplete": true,
|
|
662
|
-
"researchComplete": true,
|
|
663
|
-
"planComplete": true,
|
|
664
|
-
"executeComplete": false,
|
|
665
|
-
"lastUpdated": "2026-01-16T10:00:00Z"
|
|
666
|
-
}
|
|
667
|
-
```
|
|
668
|
-
|
|
669
|
-
**With yolo mode active:**
|
|
670
|
-
```json
|
|
671
|
-
{
|
|
672
|
-
"name": "<name>",
|
|
673
|
-
"currentPhase": "execute",
|
|
674
|
-
"specComplete": true,
|
|
675
|
-
"researchComplete": true,
|
|
676
|
-
"planComplete": true,
|
|
677
|
-
"executeComplete": false,
|
|
678
|
-
"lastUpdated": "2026-01-16T10:00:00Z",
|
|
679
|
-
"yolo": {
|
|
680
|
-
"active": true,
|
|
681
|
-
"iteration": 1,
|
|
682
|
-
"maxIterations": 100,
|
|
683
|
-
"startedAt": "2026-01-16T10:00:00Z"
|
|
684
|
-
}
|
|
685
|
-
}
|
|
686
|
-
```
|
|
687
|
-
|
|
688
|
-
**Yolo fields:**
|
|
689
|
-
- `active`: Set to `true` when yolo mode starts, `false` when complete or stopped
|
|
690
|
-
- `iteration`: Current iteration count (plugin increments this on each continuation)
|
|
691
|
-
- `maxIterations`: Safety limit. Use the value from config (`yolo.defaultMaxIterations`). Set to 0 for unlimited.
|
|
692
|
-
- `startedAt`: ISO timestamp when yolo mode was activated
|
|
693
|
-
|
|
694
|
-
Update this file after each phase completes. The Lisa plugin reads this file to determine whether to auto-continue.
|
|
695
|
-
|
|
696
|
-
---
|
|
697
|
-
|
|
698
|
-
## Configuration
|
|
699
|
-
|
|
700
|
-
Lisa settings are stored in `.lisa/config.jsonc`. The config is automatically created with safe defaults when you first create an epic.
|
|
701
|
-
|
|
702
|
-
**Config locations (merged in order):**
|
|
703
|
-
1. `~/.config/lisa/config.jsonc` - Global user defaults
|
|
704
|
-
2. `.lisa/config.jsonc` - Project settings (commit this)
|
|
705
|
-
3. `.lisa/config.local.jsonc` - Personal overrides (gitignored)
|
|
706
|
-
|
|
707
|
-
**Use the `get_lisa_config` tool** to read current config settings.
|
|
708
|
-
|
|
709
|
-
**Use the `lisa_config` tool** to view or manage config:
|
|
710
|
-
- `lisa_config(action: "view")` - Show current config and sources
|
|
711
|
-
- `lisa_config(action: "init")` - Create config if it doesn't exist
|
|
712
|
-
- `lisa_config(action: "reset")` - Reset config to defaults
|
|
713
|
-
|
|
714
|
-
### Config Schema
|
|
715
|
-
|
|
716
|
-
```jsonc
|
|
717
|
-
{
|
|
718
|
-
"execution": {
|
|
719
|
-
"maxRetries": 3 // Retries for failed tasks before marking blocked
|
|
720
|
-
},
|
|
721
|
-
"git": {
|
|
722
|
-
"completionMode": "none", // "pr" | "commit" | "none"
|
|
723
|
-
"branchPrefix": "epic/", // Branch naming prefix
|
|
724
|
-
"autoPush": true // Auto-push when completionMode is "pr"
|
|
725
|
-
},
|
|
726
|
-
"yolo": {
|
|
727
|
-
"defaultMaxIterations": 100 // Default max iterations (0 = unlimited)
|
|
728
|
-
}
|
|
729
|
-
}
|
|
730
|
-
```
|
|
731
|
-
|
|
732
|
-
### Completion Modes
|
|
733
|
-
|
|
734
|
-
The `git.completionMode` setting controls what happens when an epic completes:
|
|
735
|
-
|
|
736
|
-
- **`"none"`** (default, safest): No git operations. You manage git entirely.
|
|
737
|
-
- **`"commit"`**: Create a branch and commits, but don't push. You handle push/PR.
|
|
738
|
-
- **`"pr"`**: Create branch, commits, push, and open a PR via `gh` CLI.
|
|
739
|
-
|
|
740
|
-
---
|
|
741
|
-
|
|
742
|
-
## Epic Completion
|
|
743
|
-
|
|
744
|
-
When all tasks are done and the epic is complete, follow this completion flow based on the config:
|
|
745
|
-
|
|
746
|
-
### Step 1: Check config
|
|
747
|
-
|
|
748
|
-
Call `get_lisa_config()` to read the current `git.completionMode`.
|
|
749
|
-
|
|
750
|
-
### Step 2: Execute completion based on mode
|
|
751
|
-
|
|
752
|
-
**If `git.completionMode` is `"none"`:**
|
|
753
|
-
- Update `.state` with `executeComplete: true`
|
|
754
|
-
- Report completion to user:
|
|
755
|
-
> "Epic complete! All X tasks finished.
|
|
756
|
-
>
|
|
757
|
-
> Changes have been made but not committed. You can review and commit them manually."
|
|
758
|
-
|
|
759
|
-
**If `git.completionMode` is `"commit"`:**
|
|
760
|
-
1. Create a new branch if not already on one:
|
|
761
|
-
```bash
|
|
762
|
-
git checkout -b {branchPrefix}{epicName}
|
|
763
|
-
```
|
|
764
|
-
2. Stage and commit all changes:
|
|
765
|
-
```bash
|
|
766
|
-
git add -A
|
|
767
|
-
git commit -m "feat: {epic goal summary}"
|
|
768
|
-
```
|
|
769
|
-
3. Update `.state` with `executeComplete: true`
|
|
770
|
-
4. Report completion:
|
|
771
|
-
> "Epic complete! All X tasks finished.
|
|
772
|
-
>
|
|
773
|
-
> Changes committed to branch `{branchPrefix}{epicName}`.
|
|
774
|
-
> Push and create a PR when ready:
|
|
775
|
-
> ```
|
|
776
|
-
> git push -u origin {branchPrefix}{epicName}
|
|
777
|
-
> gh pr create
|
|
778
|
-
> ```"
|
|
779
|
-
|
|
780
|
-
**If `git.completionMode` is `"pr"`:**
|
|
781
|
-
1. Create a new branch if not already on one:
|
|
782
|
-
```bash
|
|
783
|
-
git checkout -b {branchPrefix}{epicName}
|
|
784
|
-
```
|
|
785
|
-
2. Stage and commit all changes:
|
|
786
|
-
```bash
|
|
787
|
-
git add -A
|
|
788
|
-
git commit -m "feat: {epic goal summary}"
|
|
789
|
-
```
|
|
790
|
-
3. Check if `gh` CLI is available:
|
|
791
|
-
```bash
|
|
792
|
-
which gh
|
|
793
|
-
```
|
|
794
|
-
4. **If `gh` is available and `autoPush` is true:**
|
|
795
|
-
```bash
|
|
796
|
-
git push -u origin {branchPrefix}{epicName}
|
|
797
|
-
gh pr create --title "{epic goal}" --body "## Summary\n\n{epic description}\n\n## Tasks Completed\n\n{task list}"
|
|
798
|
-
```
|
|
799
|
-
Report:
|
|
800
|
-
> "Epic complete! All X tasks finished.
|
|
801
|
-
>
|
|
802
|
-
> PR created: {PR URL}"
|
|
803
|
-
|
|
804
|
-
5. **If `gh` is NOT available:**
|
|
805
|
-
Report:
|
|
806
|
-
> "Epic complete! All X tasks finished.
|
|
807
|
-
>
|
|
808
|
-
> Changes committed to branch `{branchPrefix}{epicName}`.
|
|
809
|
-
>
|
|
810
|
-
> Note: GitHub CLI (`gh`) not found. Install it to enable automatic PR creation:
|
|
811
|
-
> - macOS: `brew install gh`
|
|
812
|
-
> - Then: `gh auth login`
|
|
813
|
-
>
|
|
814
|
-
> To create a PR manually:
|
|
815
|
-
> ```
|
|
816
|
-
> git push -u origin {branchPrefix}{epicName}
|
|
817
|
-
> gh pr create
|
|
818
|
-
> ```"
|
|
819
|
-
|
|
820
|
-
### Commit Message Format
|
|
821
|
-
|
|
822
|
-
Use conventional commits format for the commit message:
|
|
823
|
-
- `feat: {epic goal}` for new features
|
|
824
|
-
- `fix: {epic goal}` for bug fixes
|
|
825
|
-
- `refactor: {epic goal}` for refactoring
|
|
826
|
-
|
|
827
|
-
Include a brief body with the tasks completed if helpful.
|
|
828
|
-
|
|
829
|
-
---
|
|
830
|
-
|
|
831
|
-
## First Epic Setup
|
|
832
|
-
|
|
833
|
-
When creating the first epic in a project (when `.lisa/` doesn't exist):
|
|
834
|
-
|
|
835
|
-
1. Create `.lisa/` directory
|
|
836
|
-
2. Create `.lisa/config.jsonc` with default settings
|
|
837
|
-
3. Create `.lisa/.gitignore` containing `config.local.jsonc`
|
|
838
|
-
4. Create `.lisa/epics/` directory
|
|
839
|
-
5. Create the epic directory `.lisa/epics/{epicName}/`
|
|
840
|
-
|
|
841
|
-
This ensures config is always present with safe defaults.
|