@tarcisiopgs/lisa 1.29.0 → 1.30.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 CHANGED
@@ -44,7 +44,10 @@ If something fails — pre-push hooks, quota limits, stuck processes — Lisa ha
44
44
  - **Concurrent execution** — process multiple issues in parallel, each in its own worktree
45
45
  - **Multi-repo** — plans across repos, creates one PR per repo in the correct order
46
46
  - **Model fallback** — chain models; transient errors (429, quota, timeout) auto-switch to the next
47
- - **Real-time TUI** — Kanban board with live provider output, plan mode, PR merge detection
47
+ - **Real-time TUI** — Kanban board with live provider output, plan mode, merge PRs with `m`
48
+ - **CI monitoring** — polls CI after PR creation, re-invokes the agent to fix failures automatically
49
+ - **Progress comments** — posts real-time status updates on issues as Lisa works through stages
50
+ - **Context enrichment** — greps for issue-related files and surfaces them in the agent prompt
48
51
  - **Self-healing** — orphan recovery on startup, push failure retry, stuck process detection
49
52
  - **Guardrails** — past failures are injected into future prompts to avoid repeating mistakes
50
53
  - **Project context** — auto-generates `.lisa/context.md` with your stack, conventions, and constraints
@@ -231,6 +234,16 @@ proof_of_work:
231
234
 
232
235
  validation:
233
236
  require_acceptance_criteria: true
237
+
238
+ ci_monitor:
239
+ enabled: true
240
+ max_retries: 3 # fix attempts on CI failure
241
+ poll_interval: 30 # seconds between CI status checks
242
+ poll_timeout: 600 # max seconds to wait for CI
243
+ block_on_failure: false # revert issue if CI never passes
244
+
245
+ progress_comments:
246
+ enabled: true # post real-time status on issues
234
247
  ```
235
248
 
236
249
  </details>
@@ -274,6 +287,7 @@ The real-time Kanban board shows issue progress, streams provider output, and de
274
287
  |-----|--------|
275
288
  | `↑` `↓` | Scroll output log |
276
289
  | `o` | Open PR in browser |
290
+ | `m` | Merge PR (warns if CI not passed) |
277
291
  | `Esc` | Back to board |
278
292
 
279
293
  **Plan mode**
@@ -4,14 +4,14 @@ import {
4
4
  readContext,
5
5
  resolveModels,
6
6
  runWithFallback
7
- } from "./chunk-YURAUUDI.js";
7
+ } from "./chunk-IMIDFVMI.js";
8
8
  import {
9
9
  error,
10
10
  log,
11
11
  normalizeLabels,
12
12
  ok,
13
13
  warn
14
- } from "./chunk-5N4BWHIT.js";
14
+ } from "./chunk-66TB6NMR.js";
15
15
 
16
16
  // src/cli/error.ts
17
17
  var CliError = class extends Error {
@@ -425,6 +425,18 @@ var GitHubIssuesSource = class {
425
425
  } catch {
426
426
  }
427
427
  }
428
+ async createComment(issueId, body) {
429
+ const ref = parseGitHubIssueNumber(issueId);
430
+ const result = await api().post(
431
+ `/repos/${ref.owner}/${ref.repo}/issues/${ref.number}/comments`,
432
+ { body }
433
+ );
434
+ return String(result.id);
435
+ }
436
+ async updateComment(issueId, commentId, body) {
437
+ const ref = parseGitHubIssueNumber(issueId);
438
+ await api().patch(`/repos/${ref.owner}/${ref.repo}/issues/comments/${commentId}`, { body });
439
+ }
428
440
  async createIssue(opts, config) {
429
441
  const { owner, repo } = parseOwnerRepo(config.scope);
430
442
  const labels = Array.isArray(opts.label) ? opts.label : [opts.label];
@@ -652,6 +664,20 @@ var GitLabIssuesSource = class {
652
664
  labels: filtered.join(",")
653
665
  });
654
666
  }
667
+ async createComment(issueId, body) {
668
+ const { project, iid } = splitIssueId(issueId);
669
+ const encodedProject = parseGitLabProject(project);
670
+ const note = await api2().post(
671
+ `/projects/${encodedProject}/issues/${iid}/notes`,
672
+ { body }
673
+ );
674
+ return String(note.id);
675
+ }
676
+ async updateComment(issueId, commentId, body) {
677
+ const { project, iid } = splitIssueId(issueId);
678
+ const encodedProject = parseGitLabProject(project);
679
+ await api2().put(`/projects/${encodedProject}/issues/${iid}/notes/${commentId}`, { body });
680
+ }
655
681
  async createIssue(opts, config) {
656
682
  const encodedProject = parseGitLabProject(config.scope);
657
683
  const labels = Array.isArray(opts.label) ? opts.label : [opts.label];
@@ -694,7 +720,7 @@ function parseGitLabIssueRef(input) {
694
720
  }
695
721
 
696
722
  // src/ui/state.ts
697
- var MERGE_POLL_INTERVAL_MS = 6e4;
723
+ var MERGE_POLL_INTERVAL_MS = 5e3;
698
724
  var activePolls = /* @__PURE__ */ new Map();
699
725
  async function checkPrMergedByUrl(prUrl) {
700
726
  if (prUrl.includes("github.com")) {
@@ -108,15 +108,9 @@ async function appendPrBody(prUrl, content) {
108
108
  }
109
109
  }
110
110
 
111
- // src/errors.ts
112
- function formatError(err) {
113
- return err instanceof Error ? err.message : String(err);
114
- }
115
-
116
111
  export {
117
112
  stripProviderAttribution,
118
113
  isGhCliAvailable,
119
114
  appendPrAttribution,
120
- appendPrBody,
121
- formatError
115
+ appendPrBody
122
116
  };
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/errors.ts
4
+ function formatError(err) {
5
+ return err instanceof Error ? err.message : String(err);
6
+ }
7
+
8
+ export {
9
+ formatError
10
+ };
@@ -11,7 +11,7 @@ import {
11
11
  normalizeLabels,
12
12
  ok,
13
13
  warn
14
- } from "./chunk-5N4BWHIT.js";
14
+ } from "./chunk-66TB6NMR.js";
15
15
  import {
16
16
  appendEntry,
17
17
  buildGuardrailsSection,
@@ -25,9 +25,11 @@ import {
25
25
  import {
26
26
  appendPrAttribution,
27
27
  appendPrBody,
28
- formatError,
29
28
  stripProviderAttribution
30
- } from "./chunk-NMQ6YMBH.js";
29
+ } from "./chunk-72DVXSHO.js";
30
+ import {
31
+ formatError
32
+ } from "./chunk-7JT7DTSS.js";
31
33
 
32
34
  // src/providers/aider.ts
33
35
  import { mkdtempSync as mkdtempSync2, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "fs";
@@ -2024,6 +2026,14 @@ var PlaneSource = class {
2024
2026
  { labels: updatedLabels }
2025
2027
  );
2026
2028
  }
2029
+ async createComment(issueId, body) {
2030
+ const { workspaceSlug, projectId, issueId: planeIssueId } = parseIssueId(issueId);
2031
+ const result = await planePost(
2032
+ `/workspaces/${workspaceSlug}/projects/${projectId}/work-items/${planeIssueId}/comments/`,
2033
+ { comment_html: `<p>${escapeHtml(body)}</p>` }
2034
+ );
2035
+ return result.id;
2036
+ }
2027
2037
  async createIssue(opts, config) {
2028
2038
  const workspaceSlug = config.scope;
2029
2039
  const projectId = await resolveProjectId(workspaceSlug, config.project);
@@ -2317,6 +2327,13 @@ var ShortcutSource = class {
2317
2327
  labels: labelNames
2318
2328
  });
2319
2329
  }
2330
+ async createComment(issueId, body) {
2331
+ const storyId = parseShortcutIdentifier(issueId);
2332
+ const result = await shortcutPost(`/api/v3/stories/${storyId}/comments`, {
2333
+ text: body
2334
+ });
2335
+ return String(result.id);
2336
+ }
2320
2337
  async createIssue(opts, _config) {
2321
2338
  const stateId = await resolveWorkflowStateId(opts.status);
2322
2339
  const labelNames = Array.isArray(opts.label) ? opts.label : [opts.label];
@@ -3379,7 +3396,8 @@ function buildPrompt(opts) {
3379
3396
  config,
3380
3397
  step,
3381
3398
  previousResults = [],
3382
- isLastStep = false
3399
+ isLastStep = false,
3400
+ relevantFiles
3383
3401
  } = opts;
3384
3402
  let manifestPath = opts.manifestPath;
3385
3403
  if (!manifestPath && variant === "branch" && config) {
@@ -3393,6 +3411,7 @@ function buildPrompt(opts) {
3393
3411
  const depBlock = issue.dependency ? buildDependencyContext(issue.dependency) : "";
3394
3412
  const specWarningBlock = buildSpecWarningBlock(issue.specWarning);
3395
3413
  const contextMdBlock = buildContextMdBlock(repoContextMd ?? null);
3414
+ const relevantFilesBlock = relevantFiles ?? "";
3396
3415
  const prBase = issue.dependency ? issue.dependency.branch : baseBranch;
3397
3416
  const prCreateBlock = buildPrCreateInstruction(platform2, prBase);
3398
3417
  const manifestLocation = manifestPath ? `\`${manifestPath}\`` : "`.lisa/manifests/default.json` in the **current directory**";
@@ -3594,7 +3613,9 @@ ${workContext}
3594
3613
  ${issue.description}
3595
3614
  ${specWarningBlock}${contextBlock ? `
3596
3615
  ${contextBlock}
3597
- ` : ""}${contextMdBlock}${depBlock ? `
3616
+ ` : ""}${contextMdBlock}${relevantFilesBlock ? `
3617
+ ${relevantFilesBlock}
3618
+ ` : ""}${depBlock ? `
3598
3619
  ${depBlock}
3599
3620
  ` : ""}${scopeSection}
3600
3621
  ${instructions}
@@ -3610,7 +3631,7 @@ Before finishing, verify ALL of the following are true:
3610
3631
  - [ ] Manifest file is written with \`prUrl\` field
3611
3632
  If ANY item is unchecked, go back and complete it. Do NOT finish with incomplete steps.`;
3612
3633
  }
3613
- function buildImplementPrompt(issue, config, testRunner, pm, projectContext, cwd, manifestPath, repoContextMd) {
3634
+ function buildImplementPrompt(issue, config, testRunner, pm, projectContext, cwd, manifestPath, repoContextMd, relevantFiles) {
3614
3635
  const workspace = resolve(config.workspace);
3615
3636
  const resolvedManifestPath = manifestPath ?? getManifestPath(workspace);
3616
3637
  if (config.workflow === "worktree") {
@@ -3624,7 +3645,8 @@ function buildImplementPrompt(issue, config, testRunner, pm, projectContext, cwd
3624
3645
  manifestPath: resolvedManifestPath,
3625
3646
  cwd,
3626
3647
  platform: config.platform,
3627
- repoContextMd
3648
+ repoContextMd,
3649
+ relevantFiles
3628
3650
  });
3629
3651
  }
3630
3652
  return buildPrompt({
@@ -3638,10 +3660,11 @@ function buildImplementPrompt(issue, config, testRunner, pm, projectContext, cwd
3638
3660
  cwd,
3639
3661
  platform: config.platform,
3640
3662
  repoContextMd,
3641
- config
3663
+ config,
3664
+ relevantFiles
3642
3665
  });
3643
3666
  }
3644
- function buildNativeWorktreePrompt(issue, repoPath, testRunner, pm, baseBranch, projectContext, manifestPath, platform2 = "cli", repoContextMd) {
3667
+ function buildNativeWorktreePrompt(issue, repoPath, testRunner, pm, baseBranch, projectContext, manifestPath, platform2 = "cli", repoContextMd, relevantFiles) {
3645
3668
  return buildPrompt({
3646
3669
  issue,
3647
3670
  variant: "native-worktree",
@@ -3652,7 +3675,8 @@ function buildNativeWorktreePrompt(issue, repoPath, testRunner, pm, baseBranch,
3652
3675
  manifestPath,
3653
3676
  cwd: repoPath,
3654
3677
  platform: platform2,
3655
- repoContextMd
3678
+ repoContextMd,
3679
+ relevantFiles
3656
3680
  });
3657
3681
  }
3658
3682
  function buildScopedImplementPrompt(issue, step, previousResults, testRunner, pm, isLastStep = false, baseBranch, projectContext, manifestPath, cwd, platform2 = "cli", repoContextMd) {
@@ -1,8 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- formatError,
4
3
  isGhCliAvailable
5
- } from "./chunk-NMQ6YMBH.js";
4
+ } from "./chunk-72DVXSHO.js";
5
+ import {
6
+ formatError
7
+ } from "./chunk-7JT7DTSS.js";
6
8
 
7
9
  // src/cli/detection.ts
8
10
  import { execSync } from "child_process";