@tarcisiopgs/lisa 1.33.3 → 1.35.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 +37 -5
- package/dist/{chunk-UDQRHMVH.js → chunk-6SNT7TND.js} +20 -4
- package/dist/{chunk-5724FKM6.js → chunk-6VIN5PMW.js} +127 -33
- package/dist/{chunk-2EQI6U5O.js → chunk-BWND35E5.js} +409 -25
- package/dist/{chunk-PPRXJHPW.js → chunk-V44FTYWZ.js} +7 -1
- package/dist/index.js +83 -36
- package/dist/{kanban-MKRXRMTL.js → kanban-CRHTDRBU.js} +13 -3
- package/dist/{loop-ZPYCRA6I.js → loop-N5D27JQX.js} +3 -3
- package/dist/{tui-bridge-ZLL4U7W3.js → tui-bridge-LQDYRWHY.js} +4 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -28,7 +28,7 @@ lisa # start the agent loop
|
|
|
28
28
|
## How It Works
|
|
29
29
|
|
|
30
30
|
```
|
|
31
|
-
Plan → Create issues → Fetch → Implement → Push → Open PR → Update board → Next
|
|
31
|
+
Plan → Create issues → Fetch → Implement → Push → Open PR → CI Monitor → Review Monitor → Update board → Next
|
|
32
32
|
```
|
|
33
33
|
|
|
34
34
|
Lisa starts and shows a Kanban board. If the queue is empty, press `n` to plan — describe a goal and the AI brainstorms with you (asking clarifying questions), presents its understanding for your confirmation, then decomposes the goal into atomic issues created directly in your tracker. You can review, edit, reorder, delete, or regenerate the plan with feedback before approving. Press `r` to start processing. Lisa picks the highest-priority labeled issue, moves it to "In Progress", sends a structured prompt to the AI agent, and monitors execution. The agent works in an isolated git worktree, implements the change, runs tests, and commits. Lisa pushes, opens a PR, moves the ticket to "In Review", and picks up the next one.
|
|
@@ -47,11 +47,16 @@ If something fails — pre-push hooks, quota limits, stuck processes — Lisa ha
|
|
|
47
47
|
- **Model fallback** — chain models; transient errors (429, quota, timeout) auto-switch to the next
|
|
48
48
|
- **Real-time TUI** — Kanban board with live provider output, plan mode, merge PRs with `m`
|
|
49
49
|
- **CI monitoring** — polls CI after PR creation, re-invokes the agent to fix failures automatically
|
|
50
|
+
- **Review monitoring** — polls PR reviews after CI, auto-addresses reviewer feedback (GitHub)
|
|
51
|
+
- **Reaction engine** — configurable actions for CI failures, review changes, stuck agents
|
|
52
|
+
- **Session state tracking** — real-time visibility into agent pipeline phase (implementing → validating → CI → review)
|
|
53
|
+
- **Smart activity detection** — reads agent session logs to prevent false stuck kills during analysis phases
|
|
50
54
|
- **Progress comments** — posts real-time status updates on issues as Lisa works through stages
|
|
51
55
|
- **Context enrichment** — greps for issue-related files and surfaces them in the agent prompt
|
|
52
56
|
- **PR reviewers & assignees** — auto-request reviews and assign PRs via config; `self` keyword resolves to the authenticated user
|
|
53
57
|
- **Self-healing** — orphan recovery on startup, push failure retry, stuck process detection
|
|
54
58
|
- **Guardrails** — past failures are injected into future prompts to avoid repeating mistakes
|
|
59
|
+
- **Lineage context** — plan-decomposed issues get sibling task awareness, preventing duplicate work in concurrent mode
|
|
55
60
|
- **Project context** — auto-generates `.lisa/context.md` with your stack, conventions, and constraints
|
|
56
61
|
|
|
57
62
|
## Providers
|
|
@@ -109,6 +114,7 @@ lisa config --set loop.cooldown=5 # set nested config values
|
|
|
109
114
|
lisa doctor # diagnose setup issues (config, provider, env, git)
|
|
110
115
|
lisa context refresh # regenerate project context
|
|
111
116
|
lisa feedback --pr URL # inject PR review feedback into guardrails
|
|
117
|
+
lisa sessions # list active session states (supports --json)
|
|
112
118
|
```
|
|
113
119
|
|
|
114
120
|
Append `--json` to any command for machine-readable output. Use `--verbose` / `--quiet` to control log verbosity.
|
|
@@ -252,6 +258,31 @@ ci_monitor:
|
|
|
252
258
|
poll_timeout: 600 # max seconds to wait for CI
|
|
253
259
|
block_on_failure: false # revert issue if CI never passes
|
|
254
260
|
|
|
261
|
+
# Post-PR review monitoring (GitHub only)
|
|
262
|
+
review_monitor:
|
|
263
|
+
enabled: true
|
|
264
|
+
max_retries: 2 # fix attempts on review changes (default: 2)
|
|
265
|
+
poll_interval: 60 # seconds between review checks (default: 60)
|
|
266
|
+
poll_timeout: 3600 # max seconds to wait for review (default: 3600)
|
|
267
|
+
|
|
268
|
+
# Configurable reactions (override defaults)
|
|
269
|
+
reactions:
|
|
270
|
+
ci_failed:
|
|
271
|
+
action: reinvoke # reinvoke | notify | skip
|
|
272
|
+
max_retries: 3
|
|
273
|
+
escalate_after: 30m
|
|
274
|
+
changes_requested:
|
|
275
|
+
action: reinvoke
|
|
276
|
+
max_retries: 2
|
|
277
|
+
escalate_after: 1h
|
|
278
|
+
approved:
|
|
279
|
+
action: notify
|
|
280
|
+
agent_stuck:
|
|
281
|
+
action: notify
|
|
282
|
+
validation_failed:
|
|
283
|
+
action: reinvoke
|
|
284
|
+
max_retries: 2
|
|
285
|
+
|
|
255
286
|
progress_comments:
|
|
256
287
|
enabled: true # post real-time status on issues
|
|
257
288
|
|
|
@@ -275,7 +306,7 @@ hooks:
|
|
|
275
306
|
After the agent implements an issue, Lisa runs a multi-stage validation pipeline before creating a PR:
|
|
276
307
|
|
|
277
308
|
```
|
|
278
|
-
Agent implements → Proof of Work (lint/test/typecheck) → Spec Compliance → PR
|
|
309
|
+
Agent implements → Proof of Work (lint/test/typecheck) → Spec Compliance → PR → CI Monitor → Review Monitor
|
|
279
310
|
```
|
|
280
311
|
|
|
281
312
|
**Proof of Work** runs configured shell commands (lint, typecheck, test). If any fail, the agent is re-invoked with the error output to fix the issue.
|
|
@@ -318,9 +349,10 @@ The real-time Kanban board shows issue progress, streams provider output, and de
|
|
|
318
349
|
| Key | Action | Key | Action |
|
|
319
350
|
|-----|--------|-----|--------|
|
|
320
351
|
| `←` `→` | Switch columns | `k` | Kill current issue |
|
|
321
|
-
| `↑` `↓` | Navigate cards | `
|
|
322
|
-
| `↵` | Open detail view | `
|
|
323
|
-
| `p` | Pause / resume | `
|
|
352
|
+
| `↑` `↓` | Navigate cards | `s` | Skip current issue |
|
|
353
|
+
| `↵` | Open detail view | `n` | Open plan mode |
|
|
354
|
+
| `p` | Pause / resume | `r` | Run (from idle) |
|
|
355
|
+
| `m` | Merge PR (opens detail + triggers merge) | `q` | Quit |
|
|
324
356
|
|
|
325
357
|
**Detail view**
|
|
326
358
|
|
|
@@ -3,15 +3,16 @@ import {
|
|
|
3
3
|
buildContextMdBlock,
|
|
4
4
|
readContext,
|
|
5
5
|
resolveModels,
|
|
6
|
-
runWithFallback
|
|
7
|
-
|
|
6
|
+
runWithFallback,
|
|
7
|
+
saveLineage
|
|
8
|
+
} from "./chunk-6VIN5PMW.js";
|
|
8
9
|
import {
|
|
9
10
|
error,
|
|
10
11
|
log,
|
|
11
12
|
normalizeLabels,
|
|
12
13
|
ok,
|
|
13
14
|
warn
|
|
14
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-V44FTYWZ.js";
|
|
15
16
|
|
|
16
17
|
// src/cli/error.ts
|
|
17
18
|
var CliError = class extends Error {
|
|
@@ -163,7 +164,7 @@ function ensureAcceptanceCriteria(description, criteria) {
|
|
|
163
164
|
|
|
164
165
|
${checklist}`;
|
|
165
166
|
}
|
|
166
|
-
async function createPlanIssues(source, config, plan) {
|
|
167
|
+
async function createPlanIssues(source, config, plan, workspace) {
|
|
167
168
|
if (!source.createIssue) {
|
|
168
169
|
throw new Error(`Source "${source.name}" does not support createIssue`);
|
|
169
170
|
}
|
|
@@ -219,6 +220,21 @@ _Depends on: ${depRefs}_`;
|
|
|
219
220
|
);
|
|
220
221
|
}
|
|
221
222
|
}
|
|
223
|
+
if (createdIds.length > 1 && workspace) {
|
|
224
|
+
const lineage = {
|
|
225
|
+
planId: plan.createdAt,
|
|
226
|
+
goal: plan.goal,
|
|
227
|
+
issues: sorted.map((issue, idx) => ({
|
|
228
|
+
id: createdIds[idx] ?? `unknown-${idx}`,
|
|
229
|
+
title: issue.title,
|
|
230
|
+
order: issue.order
|
|
231
|
+
}))
|
|
232
|
+
};
|
|
233
|
+
try {
|
|
234
|
+
saveLineage(workspace, lineage);
|
|
235
|
+
} catch {
|
|
236
|
+
}
|
|
237
|
+
}
|
|
222
238
|
return createdIds;
|
|
223
239
|
}
|
|
224
240
|
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
normalizeLabels,
|
|
12
12
|
ok,
|
|
13
13
|
warn
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-V44FTYWZ.js";
|
|
15
15
|
import {
|
|
16
16
|
appendEntry,
|
|
17
17
|
buildGuardrailsSection,
|
|
@@ -1180,7 +1180,8 @@ function buildPrompt(opts) {
|
|
|
1180
1180
|
step,
|
|
1181
1181
|
previousResults = [],
|
|
1182
1182
|
isLastStep = false,
|
|
1183
|
-
relevantFiles
|
|
1183
|
+
relevantFiles,
|
|
1184
|
+
lineageBlock
|
|
1184
1185
|
} = opts;
|
|
1185
1186
|
let manifestPath = opts.manifestPath;
|
|
1186
1187
|
if (!manifestPath && variant === "branch" && config) {
|
|
@@ -1194,6 +1195,7 @@ function buildPrompt(opts) {
|
|
|
1194
1195
|
const depBlock = issue.dependency ? buildDependencyContext(issue.dependency) : "";
|
|
1195
1196
|
const specWarningBlock = buildSpecWarningBlock(issue.specWarning);
|
|
1196
1197
|
const contextMdBlock = buildContextMdBlock(repoContextMd ?? null);
|
|
1198
|
+
const dodBlock = buildDefinitionOfDone(issue.description ?? "");
|
|
1197
1199
|
const relevantFilesBlock = relevantFiles ?? "";
|
|
1198
1200
|
const prBase = issue.dependency ? issue.dependency.branch : baseBranch;
|
|
1199
1201
|
const prCreateBlock = buildPrCreateInstruction(platform2, prBase);
|
|
@@ -1266,10 +1268,7 @@ ${repoEntries}
|
|
|
1266
1268
|
- Verify each acceptance criteria (if present)
|
|
1267
1269
|
- Respect any stack or technical constraints (if present)
|
|
1268
1270
|
${testBlock}${hookBlock}
|
|
1269
|
-
4.
|
|
1270
|
-
- Check \`package.json\` (or equivalent) for lint, typecheck, check, or test scripts.
|
|
1271
|
-
- Run whichever validation scripts exist (e.g., \`npm run lint\`, \`npm run typecheck\`).
|
|
1272
|
-
- Fix any errors before proceeding.
|
|
1271
|
+
4. ${buildValidateStep(testRunner ?? null, pm)}
|
|
1273
1272
|
${readmeBlock}
|
|
1274
1273
|
**CRITICAL \u2014 Do NOT stop here. The following steps (commit, push, PR, manifest) are MANDATORY. Skipping them means the task has FAILED.**
|
|
1275
1274
|
|
|
@@ -1305,10 +1304,7 @@ ${readmeBlock}
|
|
|
1305
1304
|
- Follow the implementation instructions exactly
|
|
1306
1305
|
- Verify each acceptance criteria relevant to your scope
|
|
1307
1306
|
${testBlock}${hookBlock}
|
|
1308
|
-
2.
|
|
1309
|
-
- Check \`package.json\` (or equivalent) for lint, typecheck, check, or test scripts.
|
|
1310
|
-
- Run whichever validation scripts exist (e.g., \`npm run lint\`, \`npm run typecheck\`).
|
|
1311
|
-
- Fix any errors before proceeding.
|
|
1307
|
+
2. ${buildValidateStep(testRunner ?? null, pm)}
|
|
1312
1308
|
${readmeBlock}
|
|
1313
1309
|
**CRITICAL \u2014 Do NOT stop here. The following steps (commit, push, PR, manifest) are MANDATORY. Skipping them means the task has FAILED.**
|
|
1314
1310
|
|
|
@@ -1341,10 +1337,7 @@ ${trackerStep}
|
|
|
1341
1337
|
- Verify each acceptance criteria (if present)
|
|
1342
1338
|
- Respect any stack or technical constraints (if present)
|
|
1343
1339
|
${testBlock}${hookBlock}
|
|
1344
|
-
2.
|
|
1345
|
-
- Check \`package.json\` (or equivalent) for lint, typecheck, check, or test scripts.
|
|
1346
|
-
- Run whichever validation scripts exist (e.g., \`npm run lint\`, \`npm run typecheck\`).
|
|
1347
|
-
- Fix any errors before proceeding.
|
|
1340
|
+
2. ${buildValidateStep(testRunner ?? null, pm)}
|
|
1348
1341
|
${readmeBlock}
|
|
1349
1342
|
**CRITICAL \u2014 Do NOT stop here. The following steps (commit, push, PR, manifest) are MANDATORY. Skipping them means the task has FAILED.**
|
|
1350
1343
|
|
|
@@ -1384,6 +1377,7 @@ ${branchRenameInstruction}
|
|
|
1384
1377
|
rulesSection = buildRulesSection(projectContext?.environment);
|
|
1385
1378
|
}
|
|
1386
1379
|
const taskHint = buildTaskTypeHint(issue.title);
|
|
1380
|
+
const lineageSection = lineageBlock ?? "";
|
|
1387
1381
|
return `${preamble}${taskHint}
|
|
1388
1382
|
${workContext}${contextBlock ? `
|
|
1389
1383
|
${contextBlock}
|
|
@@ -1391,6 +1385,8 @@ ${contextBlock}
|
|
|
1391
1385
|
${relevantFilesBlock}
|
|
1392
1386
|
` : ""}${depBlock ? `
|
|
1393
1387
|
${depBlock}
|
|
1388
|
+
` : ""}${lineageSection ? `
|
|
1389
|
+
${lineageSection}
|
|
1394
1390
|
` : ""}
|
|
1395
1391
|
## Issue
|
|
1396
1392
|
|
|
@@ -1401,7 +1397,7 @@ ${depBlock}
|
|
|
1401
1397
|
### Description
|
|
1402
1398
|
|
|
1403
1399
|
${issue.description}
|
|
1404
|
-
${specWarningBlock}${scopeSection}${GUARDRAILS_PLACEHOLDER}
|
|
1400
|
+
${specWarningBlock}${dodBlock}${scopeSection}${GUARDRAILS_PLACEHOLDER}
|
|
1405
1401
|
${instructions}
|
|
1406
1402
|
|
|
1407
1403
|
${rulesSection}
|
|
@@ -1415,7 +1411,7 @@ Before finishing, verify ALL of the following are true:
|
|
|
1415
1411
|
- [ ] Manifest file is written with \`prUrl\` field
|
|
1416
1412
|
If ANY item is unchecked, go back and complete it. Do NOT finish with incomplete steps.`;
|
|
1417
1413
|
}
|
|
1418
|
-
function buildImplementPrompt(issue, config, testRunner, pm, projectContext, cwd, manifestPath, repoContextMd, relevantFiles) {
|
|
1414
|
+
function buildImplementPrompt(issue, config, testRunner, pm, projectContext, cwd, manifestPath, repoContextMd, relevantFiles, lineageBlock) {
|
|
1419
1415
|
const workspace = resolve(config.workspace);
|
|
1420
1416
|
const resolvedManifestPath = manifestPath ?? getManifestPath(workspace);
|
|
1421
1417
|
if (config.workflow === "worktree") {
|
|
@@ -1430,7 +1426,8 @@ function buildImplementPrompt(issue, config, testRunner, pm, projectContext, cwd
|
|
|
1430
1426
|
cwd,
|
|
1431
1427
|
platform: config.platform,
|
|
1432
1428
|
repoContextMd,
|
|
1433
|
-
relevantFiles
|
|
1429
|
+
relevantFiles,
|
|
1430
|
+
lineageBlock
|
|
1434
1431
|
});
|
|
1435
1432
|
}
|
|
1436
1433
|
return buildPrompt({
|
|
@@ -1445,7 +1442,8 @@ function buildImplementPrompt(issue, config, testRunner, pm, projectContext, cwd
|
|
|
1445
1442
|
platform: config.platform,
|
|
1446
1443
|
repoContextMd,
|
|
1447
1444
|
config,
|
|
1448
|
-
relevantFiles
|
|
1445
|
+
relevantFiles,
|
|
1446
|
+
lineageBlock
|
|
1449
1447
|
});
|
|
1450
1448
|
}
|
|
1451
1449
|
function buildNativeWorktreePrompt(issue, repoPath, testRunner, pm, baseBranch, projectContext, manifestPath, platform2 = "cli", repoContextMd, relevantFiles) {
|
|
@@ -1484,12 +1482,26 @@ function buildTestInstructions(testRunner, pm = "npm") {
|
|
|
1484
1482
|
if (!testRunner) return "";
|
|
1485
1483
|
const testCmd = pm === "bun" ? "bun run test" : `${pm} run test`;
|
|
1486
1484
|
return `
|
|
1487
|
-
**MANDATORY \u2014
|
|
1488
|
-
This project uses **${testRunner}
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1485
|
+
**MANDATORY \u2014 Test-Driven Development (TDD):**
|
|
1486
|
+
This project uses **${testRunner}**. Follow the RED \u2192 GREEN \u2192 REFACTOR cycle strictly:
|
|
1487
|
+
1. **RED**: Write the failing tests first \u2014 before writing any implementation code.
|
|
1488
|
+
Run \`${testCmd}\` and confirm the new tests fail. If they pass immediately, the tests are wrong.
|
|
1489
|
+
2. **GREEN**: Write the minimum implementation to make the tests pass.
|
|
1490
|
+
Run \`${testCmd}\` \u2014 all tests must pass before continuing.
|
|
1491
|
+
3. **REFACTOR**: Clean up the code without breaking tests. Run \`${testCmd}\` one final time to confirm.
|
|
1492
|
+
- Cover the main functionality, edge cases, and error scenarios.
|
|
1493
|
+
- Do NOT write implementation before tests. The PR will be blocked if tests are missing or written after the fact.
|
|
1494
|
+
`;
|
|
1495
|
+
}
|
|
1496
|
+
function buildDefinitionOfDone(description) {
|
|
1497
|
+
const criteria = description.split("\n").map((l) => l.trim()).filter((l) => /^- \[ \]/.test(l));
|
|
1498
|
+
if (criteria.length === 0) return "";
|
|
1499
|
+
return `
|
|
1500
|
+
## Definition of Done
|
|
1501
|
+
|
|
1502
|
+
Verify each item before finishing:
|
|
1503
|
+
|
|
1504
|
+
${criteria.join("\n")}
|
|
1493
1505
|
`;
|
|
1494
1506
|
}
|
|
1495
1507
|
function buildSpecWarningBlock(warning) {
|
|
@@ -1525,6 +1537,14 @@ function buildEnvironmentDependencyRule(env) {
|
|
|
1525
1537
|
}
|
|
1526
1538
|
return "";
|
|
1527
1539
|
}
|
|
1540
|
+
function buildValidateStep(testRunner, pm = "npm") {
|
|
1541
|
+
const testCmd = pm === "bun" ? "bun run test" : `${pm} run test`;
|
|
1542
|
+
const testLine = testRunner ? ` - Run \`${testCmd}\` \u2014 ALL tests must pass (final gate after the TDD cycle).
|
|
1543
|
+
` : "";
|
|
1544
|
+
return `**Validate**: Confirm all quality gates before committing:
|
|
1545
|
+
${testLine} - Run lint/typecheck scripts if available (e.g., \`npm run lint\`, \`npm run typecheck\`).
|
|
1546
|
+
- Fix every error. Do NOT commit with failing tests or lint errors.`;
|
|
1547
|
+
}
|
|
1528
1548
|
function buildPreCommitHookInstructions() {
|
|
1529
1549
|
return `
|
|
1530
1550
|
**Pre-commit hooks:**
|
|
@@ -1731,7 +1751,7 @@ If ANY item is unchecked, go back and complete it. Do NOT finish with incomplete
|
|
|
1731
1751
|
// src/providers/aider.ts
|
|
1732
1752
|
import { mkdtempSync as mkdtempSync2, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
1733
1753
|
import { tmpdir as tmpdir2 } from "os";
|
|
1734
|
-
import { join as
|
|
1754
|
+
import { join as join5 } from "path";
|
|
1735
1755
|
|
|
1736
1756
|
// src/providers/output-buffer.ts
|
|
1737
1757
|
import { appendFileSync } from "fs";
|
|
@@ -1791,7 +1811,7 @@ var OutputBuffer = class {
|
|
|
1791
1811
|
import { execFile as execFile2, spawn as spawn3 } from "child_process";
|
|
1792
1812
|
import { mkdtempSync, rmSync, writeFileSync } from "fs";
|
|
1793
1813
|
import { tmpdir } from "os";
|
|
1794
|
-
import { join as
|
|
1814
|
+
import { join as join4 } from "path";
|
|
1795
1815
|
import { promisify as promisify2 } from "util";
|
|
1796
1816
|
|
|
1797
1817
|
// src/session/overseer.ts
|
|
@@ -1833,6 +1853,13 @@ function createSessionTimeout(proc, timeoutSeconds) {
|
|
|
1833
1853
|
};
|
|
1834
1854
|
}
|
|
1835
1855
|
|
|
1856
|
+
// src/session/activity.ts
|
|
1857
|
+
import { closeSync, openSync, readdirSync as readdirSync2, readSync, statSync as statSync2 } from "fs";
|
|
1858
|
+
import { homedir } from "os";
|
|
1859
|
+
import { join as join3 } from "path";
|
|
1860
|
+
var TAIL_BYTES = 128 * 1024;
|
|
1861
|
+
var DEFAULT_IDLE_THRESHOLD_MS = 5 * 60 * 1e3;
|
|
1862
|
+
|
|
1836
1863
|
// src/session/overseer.ts
|
|
1837
1864
|
var execFileAsync = promisify(execFile);
|
|
1838
1865
|
var STUCK_MESSAGE = "\n[lisa-overseer] Provider killed: no git changes detected within the stuck threshold. Eligible for fallback.\n";
|
|
@@ -2052,8 +2079,8 @@ async function isCommandAvailable(command, args = ["--version"]) {
|
|
|
2052
2079
|
}
|
|
2053
2080
|
async function runProviderProcess(config, prompt, opts) {
|
|
2054
2081
|
const start = Date.now();
|
|
2055
|
-
const tmpDir = mkdtempSync(
|
|
2056
|
-
const promptFile =
|
|
2082
|
+
const tmpDir = mkdtempSync(join4(tmpdir(), "lisa-"));
|
|
2083
|
+
const promptFile = join4(tmpDir, "prompt.md");
|
|
2057
2084
|
writeFileSync(promptFile, prompt, { encoding: "utf-8", mode: 384 });
|
|
2058
2085
|
try {
|
|
2059
2086
|
const promptCatExpr = `"$(cat '${escapeShellPath(promptFile)}')"`;
|
|
@@ -2180,8 +2207,8 @@ var AiderProvider = class {
|
|
|
2180
2207
|
try {
|
|
2181
2208
|
if (opts.model) validateShellArg(opts.model, "model");
|
|
2182
2209
|
const modelFlag = opts.model ? `--model ${opts.model}` : "";
|
|
2183
|
-
const aiderTmpDir = mkdtempSync2(
|
|
2184
|
-
const aiderPromptFile =
|
|
2210
|
+
const aiderTmpDir = mkdtempSync2(join5(tmpdir2(), "lisa-aider-"));
|
|
2211
|
+
const aiderPromptFile = join5(aiderTmpDir, "prompt.md");
|
|
2185
2212
|
writeFileSync2(aiderPromptFile, prompt, { encoding: "utf-8", mode: 384 });
|
|
2186
2213
|
const config = {
|
|
2187
2214
|
name: "aider",
|
|
@@ -4310,9 +4337,9 @@ function resolveModels(config) {
|
|
|
4310
4337
|
|
|
4311
4338
|
// src/session/context-manager.ts
|
|
4312
4339
|
import { existsSync as existsSync3, mkdirSync, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
4313
|
-
import { join as
|
|
4340
|
+
import { join as join6 } from "path";
|
|
4314
4341
|
function getContextPath(dir) {
|
|
4315
|
-
return
|
|
4342
|
+
return join6(dir, ".lisa", "context.md");
|
|
4316
4343
|
}
|
|
4317
4344
|
function contextExists(dir) {
|
|
4318
4345
|
return existsSync3(getContextPath(dir));
|
|
@@ -4327,6 +4354,70 @@ function readContext(dir) {
|
|
|
4327
4354
|
}
|
|
4328
4355
|
}
|
|
4329
4356
|
|
|
4357
|
+
// src/plan/lineage.ts
|
|
4358
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync2, readdirSync as readdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "fs";
|
|
4359
|
+
import { join as join7 } from "path";
|
|
4360
|
+
function lineageDir(workspace) {
|
|
4361
|
+
return join7(workspace, ".lisa", "lineage");
|
|
4362
|
+
}
|
|
4363
|
+
function sanitizePlanId(planId) {
|
|
4364
|
+
return planId.replace(/[^a-zA-Z0-9_\-.]/g, "_");
|
|
4365
|
+
}
|
|
4366
|
+
function lineagePath(workspace, planId) {
|
|
4367
|
+
return join7(lineageDir(workspace), `${sanitizePlanId(planId)}.json`);
|
|
4368
|
+
}
|
|
4369
|
+
function saveLineage(workspace, lineage) {
|
|
4370
|
+
const dir = lineageDir(workspace);
|
|
4371
|
+
if (!existsSync4(dir)) {
|
|
4372
|
+
mkdirSync2(dir, { recursive: true });
|
|
4373
|
+
}
|
|
4374
|
+
const path = lineagePath(workspace, lineage.planId);
|
|
4375
|
+
writeFileSync4(path, JSON.stringify(lineage, null, " "), "utf-8");
|
|
4376
|
+
}
|
|
4377
|
+
function loadLineageForIssue(workspace, issueId) {
|
|
4378
|
+
const dir = lineageDir(workspace);
|
|
4379
|
+
if (!existsSync4(dir)) return null;
|
|
4380
|
+
let files;
|
|
4381
|
+
try {
|
|
4382
|
+
files = readdirSync3(dir).filter((f) => f.endsWith(".json"));
|
|
4383
|
+
} catch {
|
|
4384
|
+
return null;
|
|
4385
|
+
}
|
|
4386
|
+
for (const file of files) {
|
|
4387
|
+
try {
|
|
4388
|
+
const raw = readFileSync4(join7(dir, file), "utf-8");
|
|
4389
|
+
const lineage = JSON.parse(raw);
|
|
4390
|
+
if (lineage.issues.some((issue) => issue.id === issueId)) {
|
|
4391
|
+
return lineage;
|
|
4392
|
+
}
|
|
4393
|
+
} catch {
|
|
4394
|
+
}
|
|
4395
|
+
}
|
|
4396
|
+
return null;
|
|
4397
|
+
}
|
|
4398
|
+
function buildLineagePromptBlock(lineage, currentIssueId) {
|
|
4399
|
+
if (lineage.issues.length <= 1) return "";
|
|
4400
|
+
const sorted = [...lineage.issues].sort((a, b) => a.order - b.order);
|
|
4401
|
+
const taskList = sorted.map((issue, idx) => {
|
|
4402
|
+
const marker = issue.id === currentIssueId ? " <-- (this task)" : "";
|
|
4403
|
+
return ` ${idx + 1}. [${issue.id}] ${issue.title}${marker}`;
|
|
4404
|
+
}).join("\n");
|
|
4405
|
+
const siblings = sorted.filter((issue) => issue.id !== currentIssueId).map((issue) => `- [${issue.id}] ${issue.title}`).join("\n");
|
|
4406
|
+
return `## Task Hierarchy
|
|
4407
|
+
|
|
4408
|
+
**Goal:** ${lineage.goal}
|
|
4409
|
+
|
|
4410
|
+
This task is part of a decomposed plan with ${lineage.issues.length} subtasks:
|
|
4411
|
+
|
|
4412
|
+
${taskList}
|
|
4413
|
+
|
|
4414
|
+
## Parallel Work
|
|
4415
|
+
|
|
4416
|
+
The following sibling tasks may be running concurrently. Do NOT duplicate their work:
|
|
4417
|
+
|
|
4418
|
+
${siblings}`;
|
|
4419
|
+
}
|
|
4420
|
+
|
|
4330
4421
|
export {
|
|
4331
4422
|
analyzeProject,
|
|
4332
4423
|
runValidationCommands,
|
|
@@ -4359,5 +4450,8 @@ export {
|
|
|
4359
4450
|
contextExists,
|
|
4360
4451
|
readContext,
|
|
4361
4452
|
WATCH_POLL_INTERVAL_MS,
|
|
4362
|
-
resolveModels
|
|
4453
|
+
resolveModels,
|
|
4454
|
+
saveLineage,
|
|
4455
|
+
loadLineageForIssue,
|
|
4456
|
+
buildLineagePromptBlock
|
|
4363
4457
|
};
|