@tarcisiopgs/lisa 1.20.2 → 1.21.1

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.
@@ -28,21 +28,15 @@ function getGuardrailsPath(cwd) {
28
28
  return join(getCacheDir(cwd), "guardrails.md");
29
29
  }
30
30
  function getManifestPath(cwd, issueId) {
31
- if (issueId) {
32
- const safe = issueId.replace(/[^a-zA-Z0-9_-]/g, "_");
33
- return join(getCacheDir(cwd), `manifest-${safe}.json`);
34
- }
35
- return join(getCacheDir(cwd), "manifest.json");
31
+ const safe = issueId ? issueId.replace(/[^a-zA-Z0-9_-]/g, "_") : "default";
32
+ return join(cwd, ".lisa", "manifests", `${safe}.json`);
36
33
  }
37
34
  function getPrCachePath(cwd) {
38
35
  return join(getCacheDir(cwd), "pr-cache.json");
39
36
  }
40
37
  function getPlanPath(cwd, issueId) {
41
- if (issueId) {
42
- const safe = issueId.replace(/[^a-zA-Z0-9_-]/g, "_");
43
- return join(getCacheDir(cwd), `plan-${safe}.json`);
44
- }
45
- return join(getCacheDir(cwd), "plan.json");
38
+ const safe = issueId ? issueId.replace(/[^a-zA-Z0-9_-]/g, "_") : "default";
39
+ return join(cwd, ".lisa", "plans", `${safe}.json`);
46
40
  }
47
41
  function getKanbanStatePath(cwd) {
48
42
  return join(getCacheDir(cwd), "kanban-state.json");
@@ -777,6 +777,9 @@ function useKanbanState(bellEnabled, initialCards = []) {
777
777
  (prev) => prev.map((c) => c.id === issueId ? { ...c, outputLog: c.outputLog + text } : c)
778
778
  );
779
779
  };
780
+ const onReconcileRemove = (issueId) => {
781
+ setCards((prev) => prev.filter((c) => c.id !== issueId));
782
+ };
780
783
  kanbanEmitter.on("issue:queued", onQueued);
781
784
  kanbanEmitter.on("issue:started", onStarted);
782
785
  kanbanEmitter.on("issue:done", onDone);
@@ -784,6 +787,7 @@ function useKanbanState(bellEnabled, initialCards = []) {
784
787
  kanbanEmitter.on("issue:reverted", onReverted);
785
788
  kanbanEmitter.on("issue:skipped", onSkipped);
786
789
  kanbanEmitter.on("issue:killed", onKilled);
790
+ kanbanEmitter.on("issue:reconcile-remove", onReconcileRemove);
787
791
  kanbanEmitter.on("provider:paused", onProviderPaused);
788
792
  kanbanEmitter.on("provider:resumed", onProviderResumed);
789
793
  kanbanEmitter.on("issue:log-file", onLogFile);
@@ -814,6 +818,7 @@ function useKanbanState(bellEnabled, initialCards = []) {
814
818
  kanbanEmitter.off("issue:reverted", onReverted);
815
819
  kanbanEmitter.off("issue:skipped", onSkipped);
816
820
  kanbanEmitter.off("issue:killed", onKilled);
821
+ kanbanEmitter.off("issue:reconcile-remove", onReconcileRemove);
817
822
  kanbanEmitter.off("provider:paused", onProviderPaused);
818
823
  kanbanEmitter.off("provider:resumed", onProviderResumed);
819
824
  kanbanEmitter.off("issue:log-file", onLogFile);
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  getGuardrailsPath
4
- } from "./chunk-EK5XS7CB.js";
4
+ } from "./chunk-7OCDGYDM.js";
5
5
 
6
6
  // src/session/guardrails.ts
7
7
  import { copyFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
@@ -10,8 +10,8 @@ import {
10
10
  guardrailsPath,
11
11
  migrateGuardrails,
12
12
  readGuardrails
13
- } from "./chunk-N35HZN5O.js";
14
- import "./chunk-EK5XS7CB.js";
13
+ } from "./chunk-ZAYL7SJN.js";
14
+ import "./chunk-7OCDGYDM.js";
15
15
  export {
16
16
  appendEntry,
17
17
  appendEntrySync,
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  extractContext,
7
7
  extractErrorType,
8
8
  migrateGuardrails
9
- } from "./chunk-N35HZN5O.js";
9
+ } from "./chunk-ZAYL7SJN.js";
10
10
  import {
11
11
  ensureCacheDir,
12
12
  getKanbanStatePath,
@@ -15,7 +15,7 @@ import {
15
15
  getPlanPath,
16
16
  getPrCachePath,
17
17
  rotateLogFiles
18
- } from "./chunk-EK5XS7CB.js";
18
+ } from "./chunk-7OCDGYDM.js";
19
19
  import {
20
20
  appendPrAttribution,
21
21
  detectDefaultBranch,
@@ -47,7 +47,7 @@ import {
47
47
  setOutputMode,
48
48
  updateNotice,
49
49
  warn
50
- } from "./chunk-HDOVPYNL.js";
50
+ } from "./chunk-XE35VI6S.js";
51
51
  import {
52
52
  notify,
53
53
  resetTitle,
@@ -406,7 +406,7 @@ import { promisify } from "util";
406
406
  var execFileAsync = promisify(execFile);
407
407
  var STUCK_MESSAGE = "\n[lisa-overseer] Provider killed: no git changes detected within the stuck threshold. Eligible for fallback.\n";
408
408
  var STALL_MESSAGE = "\n[lisa-stall] Provider killed: no output received within the stall timeout. Eligible for fallback.\n";
409
- var DEFAULT_OUTPUT_STALL_TIMEOUT = 120;
409
+ var DEFAULT_OUTPUT_STALL_TIMEOUT = 300;
410
410
  function createOutputStallDetector(proc, timeoutSeconds) {
411
411
  const timeout = timeoutSeconds ?? DEFAULT_OUTPUT_STALL_TIMEOUT;
412
412
  if (timeout <= 0) {
@@ -2456,8 +2456,8 @@ var feedback = defineCommand3({
2456
2456
  },
2457
2457
  async run({ args }) {
2458
2458
  const { fetchPrFeedback: fetchPrFeedback2, formatPrFeedbackEntry: formatPrFeedbackEntry2 } = await import("./pr-feedback-DGHNP3E7.js");
2459
- const { appendRawEntrySync } = await import("./guardrails-OAO4CAIT.js");
2460
- const { ensureCacheDir: ensureCacheDir2 } = await import("./paths-ZRUQ4GIN.js");
2459
+ const { appendRawEntrySync } = await import("./guardrails-EMOWZNS7.js");
2460
+ const { ensureCacheDir: ensureCacheDir2 } = await import("./paths-JE4IML2C.js");
2461
2461
  const prUrl = args.pr;
2462
2462
  const issueId = args.issue ?? "unknown";
2463
2463
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
@@ -3863,7 +3863,7 @@ import { defineCommand as defineCommand6 } from "citty";
3863
3863
  import pc5 from "picocolors";
3864
3864
 
3865
3865
  // src/loop/index.ts
3866
- import { join as join18, resolve as resolve14 } from "path";
3866
+ import { join as join17, resolve as resolve14 } from "path";
3867
3867
 
3868
3868
  // src/loop/concurrent.ts
3869
3869
  import { resolve as resolve11 } from "path";
@@ -4281,7 +4281,7 @@ function logAttemptHistory(result) {
4281
4281
 
4282
4282
  // src/loop/worktree-session.ts
4283
4283
  import { appendFileSync as appendFileSync11 } from "fs";
4284
- import { join as join16, resolve as resolve10 } from "path";
4284
+ import { resolve as resolve10 } from "path";
4285
4285
  import { execa as execa5 } from "execa";
4286
4286
 
4287
4287
  // src/context.ts
@@ -4988,7 +4988,7 @@ function buildWorktreePrompt(issue2, testRunner, pm, baseBranch, projectContext,
4988
4988
  const specWarningBlock = buildSpecWarningBlock(issue2.specWarning);
4989
4989
  const contextMdBlock = buildContextMdBlock(repoContextMd ?? null);
4990
4990
  const prBase = issue2.dependency ? issue2.dependency.branch : baseBranch;
4991
- const manifestLocation = manifestPath ? `\`${manifestPath}\`` : "`.lisa-manifest.json` in the **current directory**";
4991
+ const manifestLocation = manifestPath ? `\`${manifestPath}\`` : "`.lisa/manifests/default.json` in the **current directory**";
4992
4992
  const prCreateBlock = buildPrCreateInstruction(platform2, prBase);
4993
4993
  return `You are an autonomous implementation agent. Your job is to implement an issue end-to-end: code, push, PR, and tracker update.
4994
4994
  Do NOT use interactive skills, ask clarifying questions, or wait for user input. You are running unattended. If the issue is too ambiguous to implement, you MUST STOP and provide a clear explanation.
@@ -5139,7 +5139,7 @@ function buildNativeWorktreePrompt(issue2, repoPath, testRunner, pm, baseBranch,
5139
5139
  const specWarningBlock = buildSpecWarningBlock(issue2.specWarning);
5140
5140
  const contextMdBlock = buildContextMdBlock(repoContextMd ?? null);
5141
5141
  const prBase = issue2.dependency ? issue2.dependency.branch : baseBranch;
5142
- const manifestLocation = manifestPath ? `\`${manifestPath}\`` : "`.lisa-manifest.json` in the **current directory**";
5142
+ const manifestLocation = manifestPath ? `\`${manifestPath}\`` : "`.lisa/manifests/default.json` in the **current directory**";
5143
5143
  const prCreateBlock = buildPrCreateInstruction(platform2, prBase);
5144
5144
  return `You are an autonomous implementation agent. Your job is to implement an issue end-to-end: code, push, PR, and tracker update.
5145
5145
  Do NOT use interactive skills, ask clarifying questions, or wait for user input. You are running unattended. If the issue is too ambiguous to implement, you MUST STOP and provide a clear explanation.
@@ -5333,7 +5333,7 @@ ${readmeBlock}
5333
5333
 
5334
5334
  5. ${buildPrCreateInstruction(platform2, prBase)}
5335
5335
  ${trackerStep}
5336
- 7. **Write manifest**: Create ${manifestPath ? `\`${manifestPath}\`` : "`.lisa-manifest.json` in the **current directory**"} with JSON:
5336
+ 7. **Write manifest**: Create ${manifestPath ? `\`${manifestPath}\`` : "`.lisa/manifests/default.json` in the **current directory**"} with JSON:
5337
5337
  \`\`\`json
5338
5338
  {"branch": "<final English branch name>", "prUrl": "<pull request URL>"}
5339
5339
  \`\`\`
@@ -5709,7 +5709,7 @@ function readPlanFile(filePath) {
5709
5709
 
5710
5710
  // src/loop/multi-repo-session.ts
5711
5711
  import { appendFileSync as appendFileSync10, unlinkSync as unlinkSync2 } from "fs";
5712
- import { join as join15, resolve as resolve9 } from "path";
5712
+ import { resolve as resolve9 } from "path";
5713
5713
  async function runWorktreeMultiRepoSession(config2, issue2, logFile, session, models) {
5714
5714
  const workspace = resolve9(config2.workspace);
5715
5715
  const planPath = getPlanPath(workspace, issue2.id);
@@ -5874,7 +5874,7 @@ async function runMultiRepoStep(config2, issue2, step, previousResults, logFile,
5874
5874
  const lifecycleMode = config2.lifecycle?.mode ?? "skip";
5875
5875
  resolveInfraStatus(lifecycleMode, { success: lifecycleSuccess });
5876
5876
  const workspace = resolve9(config2.workspace);
5877
- const manifestPath = join15(worktreePath, ".lisa-manifest.json");
5877
+ const manifestPath = getManifestPath(worktreePath, issue2.id);
5878
5878
  const prompt = buildScopedImplementPrompt(
5879
5879
  issue2,
5880
5880
  step,
@@ -6174,7 +6174,7 @@ async function runManualWorktreeSession(config2, issue2, logFile, session, model
6174
6174
  lifecycleEnv = started.env;
6175
6175
  }
6176
6176
  const workspace = resolve10(config2.workspace);
6177
- const manifestPath = join16(worktreePath, ".lisa-manifest.json");
6177
+ const manifestPath = getManifestPath(worktreePath, issue2.id);
6178
6178
  const prompt = buildImplementPrompt(
6179
6179
  issue2,
6180
6180
  config2,
@@ -6532,10 +6532,10 @@ async function getChangedFiles(repoPath, baseBranch, dependencyBranch) {
6532
6532
 
6533
6533
  // src/loop/branch-session.ts
6534
6534
  import { appendFileSync as appendFileSync12, unlinkSync as unlinkSync3 } from "fs";
6535
- import { join as join17, resolve as resolve12 } from "path";
6535
+ import { resolve as resolve12 } from "path";
6536
6536
  async function runBranchSession(config2, issue2, logFile, session, models) {
6537
6537
  const workspace = resolve12(config2.workspace);
6538
- const manifestPath = join17(workspace, ".lisa-manifest.json");
6538
+ const manifestPath = getManifestPath(workspace, issue2.id);
6539
6539
  try {
6540
6540
  unlinkSync3(manifestPath);
6541
6541
  } catch {
@@ -7029,7 +7029,7 @@ async function runLoop(config2, opts) {
7029
7029
  migrateGuardrails(workspace);
7030
7030
  rotateLogFiles(workspace);
7031
7031
  if (!opts.dryRun) {
7032
- const contextLogFile = join18(workspace, ".lisa", "context-generation.log");
7032
+ const contextLogFile = join17(workspace, ".lisa", "context-generation.log");
7033
7033
  ensureWorkspaceContext(config2, models, workspace, contextLogFile).catch((err) => {
7034
7034
  warn(
7035
7035
  `Background context generation failed: ${err instanceof Error ? err.message : String(err)}`
@@ -7045,6 +7045,17 @@ async function runLoop(config2, opts) {
7045
7045
  if (kanbanEmitter.listenerCount("issue:queued") > 0) {
7046
7046
  try {
7047
7047
  const allIssues = await source.listIssues(config2.source_config);
7048
+ const activeIssueIds = new Set(allIssues.map((i) => i.id));
7049
+ if (opts.initialCards) {
7050
+ for (const card of opts.initialCards) {
7051
+ if (card.column === "backlog" && (card.hasError || card.skipped || card.killed)) {
7052
+ if (!activeIssueIds.has(card.id)) {
7053
+ kanbanEmitter.emit("issue:reconcile-remove", card.id);
7054
+ log(`Reconciled ${card.id}: no longer in source queue \u2014 removed from kanban`);
7055
+ }
7056
+ }
7057
+ }
7058
+ }
7048
7059
  for (const issue2 of allIssues) {
7049
7060
  kanbanEmitter.emit("issue:queued", issue2);
7050
7061
  }
@@ -7180,6 +7191,10 @@ var KanbanPersistence = class {
7180
7191
  this.updateCard(issueId, { column: "backlog", startedAt: void 0, killed: true });
7181
7192
  this.scheduleFlush();
7182
7193
  });
7194
+ on("issue:reconcile-remove", (issueId) => {
7195
+ this.removeCard(issueId);
7196
+ this.scheduleFlush();
7197
+ });
7183
7198
  on("issue:log-file", (issueId, logFile) => {
7184
7199
  this.updateCard(issueId, { logFile });
7185
7200
  this.scheduleFlush();
@@ -7213,6 +7228,9 @@ var KanbanPersistence = class {
7213
7228
  if (!existsSync9(dir)) mkdirSync4(dir, { recursive: true });
7214
7229
  writeFileSync12(this.statePath, JSON.stringify(this.state));
7215
7230
  }
7231
+ removeCard(id) {
7232
+ this.state.cards = this.state.cards.filter((c) => c.id !== id);
7233
+ }
7216
7234
  upsertCard(id, title) {
7217
7235
  if (!this.state.cards.some((c) => c.id === id)) {
7218
7236
  this.state.cards.push({ id, title, column: "backlog", prUrls: [], outputLogTail: [] });
@@ -7297,7 +7315,7 @@ var run = defineCommand6({
7297
7315
  if (isTTY) {
7298
7316
  const { render } = await import("ink");
7299
7317
  const { createElement } = await import("react");
7300
- const { KanbanApp } = await import("./kanban-TOKVY5AS.js");
7318
+ const { KanbanApp } = await import("./kanban-VOOYRIWF.js");
7301
7319
  const demoConfig = {
7302
7320
  provider: "claude",
7303
7321
  source: "linear",
@@ -7370,15 +7388,17 @@ Add them to your ${shell} and run: source ${shell}`));
7370
7388
  merged.workflow = "worktree";
7371
7389
  }
7372
7390
  let onBeforeExit;
7391
+ let persistedCards;
7373
7392
  if (isTTY) {
7374
7393
  const workspace = resolve15(merged.workspace);
7375
7394
  const persistence = createKanbanPersistence(workspace);
7376
7395
  const initialCards = persistence.load();
7396
+ persistedCards = initialCards;
7377
7397
  persistence.start();
7378
7398
  onBeforeExit = () => persistence.stop();
7379
7399
  const { render } = await import("ink");
7380
7400
  const { createElement } = await import("react");
7381
- const { KanbanApp } = await import("./kanban-TOKVY5AS.js");
7401
+ const { KanbanApp } = await import("./kanban-VOOYRIWF.js");
7382
7402
  render(createElement(KanbanApp, { config: merged, initialCards }), { exitOnCtrlC: false });
7383
7403
  }
7384
7404
  await runLoop(merged, {
@@ -7388,7 +7408,8 @@ Add them to your ${shell} and run: source ${shell}`));
7388
7408
  dryRun: args["dry-run"],
7389
7409
  issueId: args.issue,
7390
7410
  concurrency,
7391
- onBeforeExit
7411
+ onBeforeExit,
7412
+ initialCards: persistedCards
7392
7413
  });
7393
7414
  }
7394
7415
  });
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  kanbanEmitter,
4
4
  useKanbanState
5
- } from "./chunk-HDOVPYNL.js";
5
+ } from "./chunk-XE35VI6S.js";
6
6
  import {
7
7
  resetTitle,
8
8
  startSpinner,
@@ -10,7 +10,7 @@ import {
10
10
  getPrCachePath,
11
11
  projectHash,
12
12
  rotateLogFiles
13
- } from "./chunk-EK5XS7CB.js";
13
+ } from "./chunk-7OCDGYDM.js";
14
14
  export {
15
15
  ensureCacheDir,
16
16
  getCacheDir,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tarcisiopgs/lisa",
3
- "version": "1.20.2",
3
+ "version": "1.21.1",
4
4
  "description": "Autonomous issue resolver",
5
5
  "keywords": [
6
6
  "loop",