@tarcisiopgs/lisa 1.38.4 → 1.39.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.
@@ -19,10 +19,10 @@ import {
19
19
  readContext,
20
20
  resolveModels,
21
21
  runWithFallback
22
- } from "./chunk-246P5Z5G.js";
22
+ } from "./chunk-YTUZFCU2.js";
23
23
  import {
24
24
  kanbanEmitter
25
- } from "./chunk-LR2GREZS.js";
25
+ } from "./chunk-SOV2YONG.js";
26
26
  import {
27
27
  appendPlatformAttribution,
28
28
  appendPlatformProofOfWork,
@@ -1188,6 +1188,27 @@ function emptyCommitFailure(result) {
1188
1188
  ]
1189
1189
  });
1190
1190
  }
1191
+ async function pullBaseBranch(config) {
1192
+ const workspace = resolve3(config.workspace);
1193
+ const baseBranch = config.base_branch;
1194
+ const repoPaths = [workspace];
1195
+ if (config.repos.length > 0) {
1196
+ for (const repo of config.repos) {
1197
+ repoPaths.push(resolve3(workspace, repo.path));
1198
+ }
1199
+ }
1200
+ for (const repoPath of repoPaths) {
1201
+ try {
1202
+ await execa("git", ["pull", "--ff-only", "origin", baseBranch], {
1203
+ cwd: repoPath,
1204
+ reject: true,
1205
+ timeout: 3e4
1206
+ });
1207
+ } catch (err) {
1208
+ warn(`Failed to pull ${baseBranch} in ${repoPath}: ${formatError(err)}`);
1209
+ }
1210
+ }
1211
+ }
1191
1212
  function appendSessionLog(logFile, result) {
1192
1213
  try {
1193
1214
  appendFileSync(
@@ -2092,6 +2113,7 @@ async function monitorCi(branch, config, issue, models, cwd, logFile, workspace,
2092
2113
  let retriesLeft = maxRetries;
2093
2114
  while (true) {
2094
2115
  startSpinner(`${issue.id} \u2014 waiting for CI...`);
2116
+ kanbanEmitter.emit("issue:ci-status", issue.id, "pending");
2095
2117
  const startTime = Date.now();
2096
2118
  let lastRun = null;
2097
2119
  while (Date.now() - startTime < pollTimeout) {
@@ -2103,10 +2125,12 @@ async function monitorCi(branch, config, issue, models, cwd, logFile, workspace,
2103
2125
  }
2104
2126
  if (lastRun.status === "success") {
2105
2127
  stopSpinner();
2128
+ kanbanEmitter.emit("issue:ci-status", issue.id, "passing");
2106
2129
  ok(`CI passed: ${lastRun.name}`);
2107
2130
  return { passed: true, skipped: false, attempts: maxRetries - retriesLeft };
2108
2131
  }
2109
2132
  if (lastRun.status === "failure") {
2133
+ kanbanEmitter.emit("issue:ci-status", issue.id, "failing");
2110
2134
  break;
2111
2135
  }
2112
2136
  await sleep2(pollInterval);
@@ -2656,7 +2680,11 @@ function cleanupManifest(cwd, issueId) {
2656
2680
  function readManifestFile(filePath) {
2657
2681
  if (!existsSync6(filePath)) return null;
2658
2682
  try {
2659
- return JSON.parse(readFileSync6(filePath, "utf-8").trim());
2683
+ const parsed = JSON.parse(readFileSync6(filePath, "utf-8").trim());
2684
+ if (Array.isArray(parsed)) {
2685
+ return parsed.find((m) => m.prUrl) ?? null;
2686
+ }
2687
+ return parsed;
2660
2688
  } catch {
2661
2689
  return null;
2662
2690
  }
@@ -3505,6 +3533,7 @@ async function runConcurrentLoop(config, source, models, workspace, opts) {
3505
3533
  kanbanEmitter.emit("issue:started", issue.id);
3506
3534
  await moveToInProgress(issue, source, config);
3507
3535
  activeCleanups.set(issue.id, { previousStatus, source, sourceConfig: config.source_config });
3536
+ await pullBaseBranch(config);
3508
3537
  let sessionResult;
3509
3538
  try {
3510
3539
  sessionResult = await runWorktreeSession(
@@ -4145,6 +4174,7 @@ async function runSequentialLoop(config, source, models, workspace, opts) {
4145
4174
  kanbanEmitter.emit("issue:started", issue.id);
4146
4175
  await moveToInProgress(issue, source, config);
4147
4176
  activeCleanups.set(issue.id, { previousStatus, source, sourceConfig: config.source_config });
4177
+ await pullBaseBranch(config);
4148
4178
  let sessionResult;
4149
4179
  try {
4150
4180
  sessionResult = config.workflow === "worktree" ? await runWorktreeSession(config, issue, logFile, session, models, source) : await runBranchSession(config, issue, logFile, session, models, source);
@@ -5,10 +5,10 @@ import {
5
5
  resolveModels,
6
6
  runWithFallback,
7
7
  saveLineage
8
- } from "./chunk-246P5Z5G.js";
8
+ } from "./chunk-YTUZFCU2.js";
9
9
  import {
10
10
  normalizeLabels
11
- } from "./chunk-LR2GREZS.js";
11
+ } from "./chunk-SOV2YONG.js";
12
12
  import {
13
13
  error,
14
14
  log,
@@ -891,6 +891,9 @@ function useKanbanState(bellEnabled, initialCards = []) {
891
891
  const onSubstatus = (issueId, substatus) => {
892
892
  setCards((prev) => prev.map((c) => c.id === issueId ? { ...c, substatus } : c));
893
893
  };
894
+ const onCiStatus = (issueId, ciStatus) => {
895
+ setCards((prev) => prev.map((c) => c.id === issueId ? { ...c, ciStatus } : c));
896
+ };
894
897
  const onReviewersUpdated = (issueId, reviewers) => {
895
898
  setCards((prev) => prev.map((c) => c.id === issueId ? { ...c, reviewers } : c));
896
899
  };
@@ -947,6 +950,7 @@ function useKanbanState(bellEnabled, initialCards = []) {
947
950
  kanbanEmitter.on("provider:resumed", onProviderResumed);
948
951
  kanbanEmitter.on("issue:log-file", onLogFile);
949
952
  kanbanEmitter.on("issue:substatus", onSubstatus);
953
+ kanbanEmitter.on("issue:ci-status", onCiStatus);
950
954
  kanbanEmitter.on("issue:reviewers-updated", onReviewersUpdated);
951
955
  kanbanEmitter.on("issue:available-reviewers", onAvailableReviewers);
952
956
  kanbanEmitter.on("issue:output", onOutput);
@@ -995,6 +999,7 @@ function useKanbanState(bellEnabled, initialCards = []) {
995
999
  kanbanEmitter.off("provider:resumed", onProviderResumed);
996
1000
  kanbanEmitter.off("issue:log-file", onLogFile);
997
1001
  kanbanEmitter.off("issue:substatus", onSubstatus);
1002
+ kanbanEmitter.off("issue:ci-status", onCiStatus);
998
1003
  kanbanEmitter.off("issue:reviewers-updated", onReviewersUpdated);
999
1004
  kanbanEmitter.off("issue:available-reviewers", onAvailableReviewers);
1000
1005
  kanbanEmitter.off("issue:output", onOutput);
@@ -6,7 +6,7 @@ import {
6
6
  createApiClient,
7
7
  kanbanEmitter,
8
8
  normalizeLabels
9
- } from "./chunk-LR2GREZS.js";
9
+ } from "./chunk-SOV2YONG.js";
10
10
  import {
11
11
  buildPrCreateInstruction
12
12
  } from "./chunk-ZOVVFU7B.js";
@@ -500,7 +500,8 @@ function buildValidateStep(testRunner, pm = "npm") {
500
500
  ` : "";
501
501
  return `**Validate**: Confirm all quality gates before committing:
502
502
  ${testLine} - Run lint/typecheck scripts if available (e.g., \`npm run lint\`, \`npm run typecheck\`).
503
- - Fix every error. Do NOT commit with failing tests or lint errors.`;
503
+ - Fix every error. Do NOT commit with failing tests or lint errors.
504
+ - Run the **full** test suite, not just the files you changed \u2014 your changes may break existing tests that import or mock the same modules.`;
504
505
  }
505
506
  function buildPreCommitHookInstructions() {
506
507
  return `
package/dist/index.js CHANGED
@@ -14,7 +14,7 @@ import {
14
14
  runLoop,
15
15
  saveConfig,
16
16
  validateConfig
17
- } from "./chunk-UA22HIYE.js";
17
+ } from "./chunk-5O3ECNWK.js";
18
18
  import {
19
19
  CliError,
20
20
  buildExecutionWaves,
@@ -24,7 +24,7 @@ import {
24
24
  parseStructuredOutput,
25
25
  runPlanWizard,
26
26
  savePlan
27
- } from "./chunk-BKKDHLUA.js";
27
+ } from "./chunk-RZ53EOAY.js";
28
28
  import {
29
29
  buildContextMdBlock,
30
30
  createProvider,
@@ -34,10 +34,10 @@ import {
34
34
  readContext,
35
35
  resolveModels,
36
36
  runWithFallback
37
- } from "./chunk-246P5Z5G.js";
37
+ } from "./chunk-YTUZFCU2.js";
38
38
  import {
39
39
  kanbanEmitter
40
- } from "./chunk-LR2GREZS.js";
40
+ } from "./chunk-SOV2YONG.js";
41
41
  import {
42
42
  isProofOfWorkEnabled,
43
43
  isSpecComplianceEnabled,
@@ -1850,7 +1850,7 @@ async function reviewAndCreate(plan2, planPath, opts) {
1850
1850
  log("Run `lisa run` when ready.");
1851
1851
  return;
1852
1852
  }
1853
- const { runLoop: runLoop2 } = await import("./loop-CHG2SZUB.js");
1853
+ const { runLoop: runLoop2 } = await import("./loop-OLYIVX3B.js");
1854
1854
  const waves = buildExecutionWaves(plan2.issues);
1855
1855
  const maxWaveSize = Math.max(...waves.map((w) => w.length));
1856
1856
  await runLoop2(config2, {
@@ -1945,6 +1945,7 @@ function resolveCard(card) {
1945
1945
  finishedAt: card.finishedAt ?? Date.now(),
1946
1946
  prUrls: card.prUrls,
1947
1947
  merged: card.merged,
1948
+ ciStatus: card.ciStatus,
1948
1949
  logFile: card.logFile,
1949
1950
  outputLog: card.outputLogTail.join("\n")
1950
1951
  };
@@ -1971,6 +1972,7 @@ function resolveCard(card) {
1971
1972
  skipped: card.skipped,
1972
1973
  killed: card.killed,
1973
1974
  merged: card.merged,
1975
+ ciStatus: card.ciStatus,
1974
1976
  logFile: card.logFile,
1975
1977
  outputLog: card.outputLogTail.join("\n")
1976
1978
  };
@@ -2055,6 +2057,10 @@ var KanbanPersistence = class {
2055
2057
  this.updateCard(issueId, { substatus });
2056
2058
  this.scheduleFlush();
2057
2059
  });
2060
+ on("issue:ci-status", (issueId, ciStatus) => {
2061
+ this.updateCard(issueId, { ciStatus });
2062
+ this.scheduleFlush();
2063
+ });
2058
2064
  on("issue:reconcile-remove", (issueId) => {
2059
2065
  this.removeCard(issueId);
2060
2066
  this.scheduleFlush();
@@ -2220,7 +2226,7 @@ async function executeRun(args) {
2220
2226
  if (isTTY) {
2221
2227
  const { render } = await import("ink");
2222
2228
  const { createElement } = await import("react");
2223
- const { KanbanApp } = await import("./kanban-6WPOGFK5.js");
2229
+ const { KanbanApp } = await import("./kanban-XCQ6QNOL.js");
2224
2230
  const demoConfig = {
2225
2231
  provider: "claude",
2226
2232
  source: "linear",
@@ -2320,7 +2326,7 @@ Add them to your ${shell} and run: source ${shell}`));
2320
2326
  const initialCards = persistence.load();
2321
2327
  persistedCards = initialCards;
2322
2328
  persistence.start();
2323
- const { registerPlanBridge } = await import("./tui-bridge-HNJ5ADCJ.js");
2329
+ const { registerPlanBridge } = await import("./tui-bridge-GGH36LIH.js");
2324
2330
  const cleanupPlan = registerPlanBridge(merged);
2325
2331
  onBeforeExit = () => {
2326
2332
  persistence.stop();
@@ -2328,7 +2334,7 @@ Add them to your ${shell} and run: source ${shell}`));
2328
2334
  };
2329
2335
  const { render } = await import("ink");
2330
2336
  const { createElement } = await import("react");
2331
- const { KanbanApp } = await import("./kanban-6WPOGFK5.js");
2337
+ const { KanbanApp } = await import("./kanban-XCQ6QNOL.js");
2332
2338
  render(createElement(KanbanApp, { config: merged, initialCards }), { exitOnCtrlC: false });
2333
2339
  }
2334
2340
  await runLoop(merged, {
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  kanbanEmitter,
4
4
  useKanbanState
5
- } from "./chunk-LR2GREZS.js";
5
+ } from "./chunk-SOV2YONG.js";
6
6
  import {
7
7
  resetTitle,
8
8
  startSpinner,
@@ -141,7 +141,10 @@ function Card({
141
141
  "\u2714 ",
142
142
  formatElapsed(card.finishedAt - card.startedAt)
143
143
  ] }),
144
- card.prUrls.length > 0 && /* @__PURE__ */ jsx(Text, { color: card.merged ? "magenta" : "yellow", dimColor: true, children: card.merged ? "PR\u2714" : "PR" })
144
+ card.prUrls.length > 0 && /* @__PURE__ */ jsxs(Text, { color: card.merged ? "magenta" : "yellow", dimColor: true, children: [
145
+ card.merged ? "PR\u2714" : "PR",
146
+ card.ciStatus === "pending" ? "\u23F3" : card.ciStatus === "passing" ? "\u2714" : card.ciStatus === "failing" ? "\u2716" : ""
147
+ ] })
145
148
  ] }) : card.killed ? /* @__PURE__ */ jsx(Text, { color: "red", children: "KILLED" }) : card.skipped ? /* @__PURE__ */ jsx(Text, { color: "gray", children: "SKIPPED" }) : card.hasError && !card.killed && !card.skipped ? /* @__PURE__ */ jsx(Text, { color: "red", children: "FAILED" }) : (
146
149
  // Empty row for backlog and done-without-timing — maintains CARD_HEIGHT
147
150
  /* @__PURE__ */ jsx(Text, { children: " ".repeat(cardWidth) })
@@ -530,7 +533,8 @@ function IssueDetail({
530
533
  const hasPrMeta = card.prUrls.length > 0 && (cardReviewers.length > 0 || assignees?.length);
531
534
  const prMetaRow = hasPrMeta ? 1 : 0;
532
535
  const pickerRows = showReviewerPicker ? Math.min((card.availableReviewers ?? []).length + 2, 12) : 0;
533
- const headerOverhead = 6 + prCount + logFileRow + prMetaRow + pickerRows;
536
+ const ciRow = card.ciStatus ? 1 : 0;
537
+ const headerOverhead = 6 + prCount + logFileRow + ciRow + prMetaRow + pickerRows;
534
538
  const bodyRows = Math.max(1, terminalRows - headerOverhead);
535
539
  const lines = useMemo(() => processOutputLines(card.outputLog), [card.outputLog]);
536
540
  const startLine = Math.max(0, lines.length - bodyRows - logScrollOffset);
@@ -595,6 +599,16 @@ function IssueDetail({
595
599
  /* @__PURE__ */ jsx4(Text4, { color: "yellow", dimColor: true, children: card.prUrls.length === 1 ? "PR: " : `PR ${i + 1}: ` }),
596
600
  /* @__PURE__ */ jsx4(Text4, { color: "yellow", wrap: "truncate", children: hyperlink(url, truncateLine(url, maxLineWidth - 5)) })
597
601
  ] }, url)),
602
+ card.ciStatus && /* @__PURE__ */ jsxs4(Box4, { marginTop: 0, children: [
603
+ /* @__PURE__ */ jsx4(Text4, { color: "gray", dimColor: true, children: "CI: " }),
604
+ /* @__PURE__ */ jsx4(
605
+ Text4,
606
+ {
607
+ color: card.ciStatus === "passing" ? "green" : card.ciStatus === "failing" ? "red" : "yellow",
608
+ children: card.ciStatus === "passing" ? "\u2714 passing" : card.ciStatus === "failing" ? "\u2716 failing" : "\u23F3 pending"
609
+ }
610
+ )
611
+ ] }),
598
612
  hasPrMeta && /* @__PURE__ */ jsxs4(Box4, { marginTop: 0, flexDirection: "row", children: [
599
613
  cardReviewers.length > 0 ? /* @__PURE__ */ jsxs4(Fragment2, { children: [
600
614
  /* @__PURE__ */ jsx4(Text4, { color: "cyan", dimColor: true, children: "REVIEWERS: " }),
@@ -4,11 +4,11 @@ import {
4
4
  cleanupEventListeners,
5
5
  runDemoLoop,
6
6
  runLoop
7
- } from "./chunk-UA22HIYE.js";
7
+ } from "./chunk-5O3ECNWK.js";
8
8
  import {
9
9
  WATCH_POLL_INTERVAL_MS
10
- } from "./chunk-246P5Z5G.js";
11
- import "./chunk-LR2GREZS.js";
10
+ } from "./chunk-YTUZFCU2.js";
11
+ import "./chunk-SOV2YONG.js";
12
12
  import "./chunk-ZOVVFU7B.js";
13
13
  import "./chunk-3EOEDL3T.js";
14
14
  import "./chunk-7OCDGYDM.js";
@@ -6,15 +6,15 @@ import {
6
6
  markdownToIssue,
7
7
  parseStructuredOutput,
8
8
  savePlan
9
- } from "./chunk-BKKDHLUA.js";
9
+ } from "./chunk-RZ53EOAY.js";
10
10
  import {
11
11
  createSource,
12
12
  resolveModels,
13
13
  runWithFallback
14
- } from "./chunk-246P5Z5G.js";
14
+ } from "./chunk-YTUZFCU2.js";
15
15
  import {
16
16
  kanbanEmitter
17
- } from "./chunk-LR2GREZS.js";
17
+ } from "./chunk-SOV2YONG.js";
18
18
  import "./chunk-ZOVVFU7B.js";
19
19
  import "./chunk-3EOEDL3T.js";
20
20
  import "./chunk-7OCDGYDM.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tarcisiopgs/lisa",
3
- "version": "1.38.4",
3
+ "version": "1.39.0",
4
4
  "description": "Autonomous issue resolver",
5
5
  "keywords": [
6
6
  "loop",