@tarcisiopgs/lisa 1.26.2 → 1.27.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
@@ -91,10 +91,13 @@ lisa run --issue INT-42 # process a specific issue
91
91
  lisa run --limit 5 # stop after 5 issues
92
92
  lisa init # create .lisa/config.yaml interactively
93
93
  lisa status # show session stats
94
+ lisa doctor # diagnose setup issues (config, provider, env, git)
94
95
  lisa context refresh # regenerate project context
95
96
  lisa feedback --pr URL # inject PR review feedback into guardrails
96
97
  ```
97
98
 
99
+ Append `--json` to any command for machine-readable output. Use `--verbose` / `--quiet` to control log verbosity.
100
+
98
101
  ## Configuration
99
102
 
100
103
  Config lives in `.lisa/config.yaml`. Run `lisa init` to create it interactively.
@@ -235,15 +238,24 @@ Acceptance criteria:
235
238
 
236
239
  ## TUI
237
240
 
238
- The real-time Kanban board shows issue progress, streams provider output, and detects PR merges.
241
+ The real-time Kanban board shows issue progress, streams provider output, and detects PR merges. The sidebar legend updates contextually — only the shortcuts active in the current view are shown.
242
+
243
+ **Board view**
239
244
 
240
245
  | Key | Action | Key | Action |
241
246
  |-----|--------|-----|--------|
242
247
  | `←` `→` | Switch columns | `p` | Pause / resume provider |
243
- | `↑` `↓` | Navigate cards | `k` | Kill current issue |
244
- | `↵` | Open detail view | `s` | Skip current issue |
245
- | `Esc` | Back to board | `o` | Open PR in browser |
246
- | `q` | Quit | | |
248
+ | `1` `2` `3` | Jump to column | `k` | Kill current issue |
249
+ | `↑` `↓` | Navigate cards | `s` | Skip current issue |
250
+ | `↵` | Open detail view | `q` | Quit |
251
+
252
+ **Detail view**
253
+
254
+ | Key | Action |
255
+ |-----|--------|
256
+ | `↑` `↓` | Scroll output log |
257
+ | `o` | Open PR in browser |
258
+ | `Esc` | Back to board |
247
259
 
248
260
  ## License
249
261
 
@@ -81,7 +81,7 @@ ${newEntryText}`;
81
81
 
82
82
  ${rotated.join("\n\n")}`;
83
83
  }
84
- writeFileSync(path, content, "utf-8");
84
+ writeFileSync(path, content, { encoding: "utf-8", mode: 384 });
85
85
  }
86
86
  function appendRawEntry(dir, entryText) {
87
87
  writeLock = writeLock.then(() => appendRawEntrySync(dir, entryText)).catch(() => {
@@ -108,7 +108,7 @@ ${entryText}`;
108
108
 
109
109
  ${rotated.join("\n\n")}`;
110
110
  }
111
- writeFileSync(path, content, "utf-8");
111
+ writeFileSync(path, content, { encoding: "utf-8", mode: 384 });
112
112
  }
113
113
  function formatEntry(entry) {
114
114
  return [
@@ -2,11 +2,16 @@
2
2
 
3
3
  // src/cli/detection.ts
4
4
  import { execSync } from "child_process";
5
- import { existsSync, readdirSync, readFileSync } from "fs";
5
+ import { existsSync, readdirSync, readFileSync, rmSync } from "fs";
6
6
  import { tmpdir } from "os";
7
7
  import { join, resolve as resolvePath } from "path";
8
8
  import * as clack from "@clack/prompts";
9
9
 
10
+ // src/errors.ts
11
+ function formatError(err) {
12
+ return err instanceof Error ? err.message : String(err);
13
+ }
14
+
10
15
  // src/git/github.ts
11
16
  import { execa } from "execa";
12
17
 
@@ -99,6 +104,15 @@ async function appendPrAttribution(prUrl, providerUsed) {
99
104
  } catch {
100
105
  }
101
106
  }
107
+ async function appendPrBody(prUrl, content) {
108
+ try {
109
+ const { stdout: bodyJson } = await execa("gh", ["pr", "view", prUrl, "--json", "body"]);
110
+ const { body } = JSON.parse(bodyJson);
111
+ const newBody = (body ?? "") + content;
112
+ await execa("gh", ["pr", "edit", prUrl, "--body", newBody]);
113
+ } catch {
114
+ }
115
+ }
102
116
 
103
117
  // src/cli/detection.ts
104
118
  function getVersion() {
@@ -112,7 +126,7 @@ function getVersion() {
112
126
  }
113
127
  var CURSOR_FREE_PLAN_ERROR = "Free plans can only use Auto";
114
128
  async function isCursorFreePlan() {
115
- const { mkdtempSync, unlinkSync, writeFileSync } = await import("fs");
129
+ const { mkdtempSync, writeFileSync } = await import("fs");
116
130
  const tmpDir = mkdtempSync(join(tmpdir(), "lisa-cursor-check-"));
117
131
  const promptFile = join(tmpDir, "prompt.txt");
118
132
  writeFileSync(promptFile, "test", "utf-8");
@@ -133,15 +147,11 @@ async function isCursorFreePlan() {
133
147
  });
134
148
  return output.includes(CURSOR_FREE_PLAN_ERROR);
135
149
  } catch (err) {
136
- const errorOutput = err instanceof Error ? err.message : String(err);
150
+ const errorOutput = formatError(err);
137
151
  return errorOutput.includes(CURSOR_FREE_PLAN_ERROR);
138
152
  } finally {
139
153
  try {
140
- unlinkSync(promptFile);
141
- } catch {
142
- }
143
- try {
144
- execSync(`rm -rf ${tmpDir}`, { stdio: "ignore" });
154
+ rmSync(tmpDir, { recursive: true, force: true });
145
155
  } catch {
146
156
  }
147
157
  }
@@ -346,6 +356,8 @@ export {
346
356
  stripProviderAttribution,
347
357
  isGhCliAvailable,
348
358
  appendPrAttribution,
359
+ appendPrBody,
360
+ formatError,
349
361
  getVersion,
350
362
  isCursorFreePlan,
351
363
  fetchCursorModels,