@bojackduy/opencode-loopd 1.3.0 → 1.4.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.
Files changed (3) hide show
  1. package/dist/server.js +47 -7
  2. package/dist/tui.js +379 -239
  3. package/package.json +1 -1
package/dist/server.js CHANGED
@@ -1118,6 +1118,7 @@ function createLoopEngine(options) {
1118
1118
  import { randomUUID as randomUUID4 } from "crypto";
1119
1119
  init_state_repository();
1120
1120
  import * as path2 from "path";
1121
+ import { promises as fs2 } from "fs";
1121
1122
 
1122
1123
  // src/server/worker-session.ts
1123
1124
  function createWorkerManager(host) {
@@ -1125,7 +1126,8 @@ function createWorkerManager(host) {
1125
1126
  async createWorker(goal) {
1126
1127
  const workerSessionID = await host.createWorker({
1127
1128
  parentID: goal.ownerSessionID,
1128
- title: `loopd: ${goal.name}`
1129
+ title: `loopd: ${goal.name}`,
1130
+ agent: goal.config.agent
1129
1131
  });
1130
1132
  return {
1131
1133
  goalID: goal.id,
@@ -1197,10 +1199,25 @@ function buildContinuationSteering(goal, runtime, context) {
1197
1199
  }
1198
1200
  }
1199
1201
  parts.push(...outputLocationBlock());
1202
+ if (context?.verification) {
1203
+ const v = context.verification;
1204
+ parts.push(``, `## VERIFICATION (deterministic pre-screen)`);
1205
+ if (v.checksPassed !== undefined) {
1206
+ if (v.checksPassed)
1207
+ parts.push(`- checks: all passed`);
1208
+ else if (v.failedChecks?.length)
1209
+ parts.push(`- checks FAILED: ${v.failedChecks.join(", ")} \u2014 fix before claiming completion`);
1210
+ else
1211
+ parts.push(`- checks: not yet run`);
1212
+ }
1213
+ if (v.artifactSummary)
1214
+ parts.push(`- artifacts: ${v.artifactSummary}`);
1215
+ }
1216
+ parts.push(``, `## COMPLETION AUDIT \u2014 you ARE the evaluator`, `Before deciding the goal is achieved, treat completion as unproven:`, `1. Derive concrete requirements from the objective and any referenced files/plans/specs/issues. Preserve original scope; do not redefine success.`, `2. For _every_ explicit requirement, numbered item, named artifact, command, test, gate, invariant, deliverable \u2192 identify authoritative evidence: files, command output, test results, PR state, rendered artifacts, runtime behavior.`, `3. Judge each per-requirement: proves | contradicts | incomplete | too weak/indirect | missing \u2014 matching scope narrowly (narrow check \u2260 broad claim).`, `4. Treat tests/manifests/verifiers as evidence only after confirming they cover the relevant requirement. Treat uncertain/indirect as NOT achieved.`, `5. Only call complete_goal when _every_ requirement's current-state evidence proves it and no required work remains. If any requirement is missing/incomplete/weak \u2192 keep working, do not call complete_goal.`);
1200
1217
  if (context?.forceFinish) {
1201
- parts.push(``, `## FINAL REPORT REQUIRED \u2014 STOPPING SOON`, `The system requires you to wrap up now. Do NOT start new work.`, `Call complete_goal NOW with:`, `- summary: a specific semantic summary of what was accomplished (files changed, results, key findings)`, `- evidence: concrete proof (commands run, files created, checks passed)`, `If you cannot complete, call block_goal with the reason.`);
1218
+ parts.push(``, `## FINAL REPORT REQUIRED \u2014 STOPPING SOON`, `The system requires you to wrap up now. Do NOT start new work.`, `Call complete_goal NOW with:`, `- summary: a specific semantic summary of what was accomplished (files changed, results, key findings)`, `- evidence: concrete proof (commands run, files created, checks passed)`, `If you cannot complete truthfully, call block_goal with the reason \u2014 do not fabricate evidence.`);
1202
1219
  } else {
1203
- parts.push(``, `## INSTRUCTIONS`, `1. Inspect current workspace state \u2014 read files, check what exists. Do NOT redo completed work.`, `2. Continue concrete progress toward the objective.`, `3. After completing a batch, call report_goal_progress with what you did and what's next.`, `4. Verify completion requirement-by-requirement before calling complete_goal.`, `5. Call block_goal only if the same blocker persists across 3+ consecutive turns.`, `6. Use the built-in question tool only for genuinely risky ambiguity.`);
1220
+ parts.push(``, `## INSTRUCTIONS`, `1. Inspect current workspace state \u2014 read files, check what exists. Do NOT redo completed work.`, `2. Continue concrete progress toward the objective.`, `3. After completing a batch, call report_goal_progress with what you did and what's next.`, `4. Use the built-in question tool only for genuinely risky ambiguity.`);
1204
1221
  }
1205
1222
  }
1206
1223
  if (context?.inboxMessages && context.inboxMessages.length > 0) {
@@ -1365,11 +1382,28 @@ function createGoalService(host) {
1365
1382
  } catch {
1366
1383
  transcriptTail = [];
1367
1384
  }
1385
+ let verification;
1386
+ try {
1387
+ const artifactDir = goal.config.artifactDir;
1388
+ if (artifactDir) {
1389
+ try {
1390
+ const files = await fs2.readdir(artifactDir);
1391
+ verification = { artifactSummary: files.length ? `${files.length} file(s): ${files.slice(0, 8).join(", ")}` : "no artifacts yet" };
1392
+ } catch {
1393
+ verification = { artifactSummary: "no artifacts yet" };
1394
+ }
1395
+ }
1396
+ if (goal.config.checks?.length) {
1397
+ const c = `checks configured: ${goal.config.checks.length} \u2014 run them before claiming completion`;
1398
+ verification = { ...verification || {}, failedChecks: [c], checksPassed: undefined };
1399
+ }
1400
+ } catch {}
1368
1401
  const context = {
1369
1402
  inboxMessages: inboxMessages.length > 0 ? inboxMessages : undefined,
1370
1403
  progressHistory: progressHistory.length > 0 ? progressHistory : undefined,
1371
1404
  transcriptTail: transcriptTail && transcriptTail.length > 0 ? transcriptTail : undefined,
1372
- forceFinish: opts?.forceFinish || undefined
1405
+ forceFinish: opts?.forceFinish || undefined,
1406
+ verification
1373
1407
  };
1374
1408
  await workers.continueWorker(session, goal, runtime, context);
1375
1409
  }
@@ -1551,9 +1585,12 @@ function createGoalService(host) {
1551
1585
  // src/server/host-adapter.ts
1552
1586
  function createRealHost(client, directory) {
1553
1587
  return {
1554
- async createWorker({ parentID, title }) {
1588
+ async createWorker({ parentID, title, agent }) {
1555
1589
  try {
1556
- const result = await withTimeout(client.session.create({ body: { parentID, title } }), 1e4, "OpenCode session.create");
1590
+ const body = { parentID, title };
1591
+ if (agent)
1592
+ body.agent = agent;
1593
+ const result = await withTimeout(client.session.create({ body }), 1e4, "OpenCode session.create");
1557
1594
  const data = result?.data;
1558
1595
  if (result?.error || !data?.id) {
1559
1596
  const detail = describeError(result?.error || "response contained no session ID");
@@ -1688,7 +1725,8 @@ function goalTools(dir, goalService, hostSessionID) {
1688
1725
  maxNoProgress: tool.schema.number().optional().describe("Block after N turns without progress."),
1689
1726
  maxFailures: tool.schema.number().optional().describe("Block after N consecutive failures."),
1690
1727
  compactEvery: tool.schema.number().optional().describe("Compact the worker session every N turns."),
1691
- timeoutMs: tool.schema.number().optional().describe("Per-turn timeout in ms.")
1728
+ timeoutMs: tool.schema.number().optional().describe("Per-turn timeout in ms."),
1729
+ agent: tool.schema.string().optional().describe('Agent to run the worker as (e.g. "dumb-agent", "build"). Defaults to primary agent.')
1692
1730
  },
1693
1731
  execute: async (args, context) => {
1694
1732
  const sessionID = context?.sessionID || hostSessionID;
@@ -1718,6 +1756,8 @@ function goalTools(dir, goalService, hostSessionID) {
1718
1756
  config.compactEvery = args.compactEvery;
1719
1757
  if (args.timeoutMs !== undefined)
1720
1758
  config.timeoutMs = args.timeoutMs;
1759
+ if (args.agent !== undefined)
1760
+ config.agent = args.agent;
1721
1761
  try {
1722
1762
  const { goal, worker } = await goalService.start(dir, {
1723
1763
  name: args.name,
package/dist/tui.js CHANGED
@@ -248,8 +248,8 @@ function tokenize(input) {
248
248
  }
249
249
  function commandHelp() {
250
250
  return [
251
- "Modes: : insert \u2192 send/commands, Ctrl+N \u2192 normal, ? toggle help, Shift+B bug report",
252
- "Nav: j/k move \u2502 g/G top/bottom \u2502 o open child \u2502 p/r/R/x pause/resume/retry/clear \u2502 L logs \u2502 q close",
251
+ "Modes: : insert \u2192 send/commands | Ctrl+N \u2192 normal | ? toggle help | Shift+B bug report",
252
+ "Nav: j/k move | g/G top/bottom | o open child | p/r/R/x pause/resume/retry/clear | L logs | q close",
253
253
  "Commands (insert mode, : prefix):",
254
254
  " :send <message> Send instruction to selected goal",
255
255
  " :open Open child session (same as o)",
@@ -912,19 +912,22 @@ function LoopDashboard(props) {
912
912
  _$insertNode(_el$25, _el$26);
913
913
  _$setProp(_el$25, "flexDirection", "row");
914
914
  _$setProp(_el$25, "alignItems", "center");
915
- _$setProp(_el$25, "border", true);
916
915
  _$setProp(_el$25, "paddingLeft", 1);
917
916
  _$setProp(_el$25, "paddingRight", 1);
918
917
  _$setProp(_el$25, "flexShrink", 0);
919
918
  _$spread(_el$25, _$mergeProps({
920
- get borderColor() {
919
+ get backgroundColor() {
921
920
  return theme().error;
922
921
  }
923
922
  }, {
924
- onClick: handleBugReport
923
+ onMouseDown: handleBugReport
925
924
  }), true);
926
925
  _$insertNode(_el$26, _el$27);
927
- _$insertNode(_el$27, _$createTextNode(`Bug`));
926
+ _$insertNode(_el$27, _$createTextNode(`Bug Report`));
927
+ _$setProp(_el$27, "style", {
928
+ fg: "white",
929
+ bold: true
930
+ });
928
931
  _$insertNode(_el$29, _el$34);
929
932
  _$setProp(_el$29, "flexDirection", "column");
930
933
  _$setProp(_el$29, "flexGrow", 1);
@@ -956,17 +959,140 @@ function LoopDashboard(props) {
956
959
  `);
957
960
  },
958
961
  children: (line) => {
959
- const isHeader = line.startsWith("Modes:") || line.startsWith("Nav:") || line.startsWith("Commands");
960
- const isCmd = line.trim().startsWith(":");
962
+ if (line.startsWith("Modes:") || line.startsWith("Nav:")) {
963
+ const label = line.startsWith("Modes:") ? "Modes:" : "Nav:";
964
+ const rest = line.slice(label.length).trim();
965
+ const segments = rest.split(" | ");
966
+ return [`
967
+ `, (() => {
968
+ var _el$45 = _$createElement("span");
969
+ _$insert(_el$45, label);
970
+ _$effect((_$p) => _$setProp(_el$45, "style", {
971
+ fg: theme().primary,
972
+ bold: true
973
+ }, _$p));
974
+ return _el$45;
975
+ })(), (() => {
976
+ var _el$46 = _$createElement("span");
977
+ _$insertNode(_el$46, _$createTextNode(` `));
978
+ _$effect((_$p) => _$setProp(_el$46, "style", {
979
+ fg: theme().textMuted
980
+ }, _$p));
981
+ return _el$46;
982
+ })(), _$createComponent(For, {
983
+ each: segments,
984
+ children: (seg, idx) => {
985
+ const hasArrow = seg.includes("\u2192");
986
+ if (hasArrow) {
987
+ const [k2, d2] = seg.split("\u2192").map((s) => s.trim());
988
+ return [_$memo(() => _$memo(() => idx() > 0)() && (() => {
989
+ var _el$52 = _$createElement("span");
990
+ _$insertNode(_el$52, _$createTextNode(` | `));
991
+ _$effect((_$p) => _$setProp(_el$52, "style", {
992
+ fg: theme().textMuted
993
+ }, _$p));
994
+ return _el$52;
995
+ })()), (() => {
996
+ var _el$48 = _$createElement("span");
997
+ _$insert(_el$48, k2);
998
+ _$effect((_$p) => _$setProp(_el$48, "style", {
999
+ fg: theme().warning,
1000
+ bold: true
1001
+ }, _$p));
1002
+ return _el$48;
1003
+ })(), (() => {
1004
+ var _el$49 = _$createElement("span");
1005
+ _$insertNode(_el$49, _$createTextNode(` \u2192 `));
1006
+ _$effect((_$p) => _$setProp(_el$49, "style", {
1007
+ fg: theme().textMuted
1008
+ }, _$p));
1009
+ return _el$49;
1010
+ })(), (() => {
1011
+ var _el$51 = _$createElement("span");
1012
+ _$insert(_el$51, d2);
1013
+ _$effect((_$p) => _$setProp(_el$51, "style", {
1014
+ fg: theme().text
1015
+ }, _$p));
1016
+ return _el$51;
1017
+ })()];
1018
+ }
1019
+ const sp = seg.indexOf(" ");
1020
+ const k = sp > 0 ? seg.slice(0, sp) : seg;
1021
+ const d = sp > 0 ? seg.slice(sp + 1) : "";
1022
+ return [_$memo(() => _$memo(() => idx() > 0)() && (() => {
1023
+ var _el$55 = _$createElement("span");
1024
+ _$insertNode(_el$55, _$createTextNode(` | `));
1025
+ _$effect((_$p) => _$setProp(_el$55, "style", {
1026
+ fg: theme().textMuted
1027
+ }, _$p));
1028
+ return _el$55;
1029
+ })()), (() => {
1030
+ var _el$54 = _$createElement("span");
1031
+ _$insert(_el$54, k);
1032
+ _$effect((_$p) => _$setProp(_el$54, "style", {
1033
+ fg: theme().warning,
1034
+ bold: true
1035
+ }, _$p));
1036
+ return _el$54;
1037
+ })(), d && (() => {
1038
+ var _el$57 = _$createElement("span"), _el$58 = _$createTextNode(` `);
1039
+ _$insertNode(_el$57, _el$58);
1040
+ _$insert(_el$57, d, null);
1041
+ _$effect((_$p) => _$setProp(_el$57, "style", {
1042
+ fg: theme().text
1043
+ }, _$p));
1044
+ return _el$57;
1045
+ })()];
1046
+ }
1047
+ })];
1048
+ }
1049
+ if (line.trim().startsWith(":")) {
1050
+ const m = line.match(/^(\s*)(:\S+(?:\s+\S+)*?)\s{2,}(.*)$/);
1051
+ const indent = m?.[1] ?? line.match(/^\s*/)?.[0] ?? "";
1052
+ const key = m?.[2] ?? line.trim().split(/\s{2,}/)[0] ?? line.trim();
1053
+ const desc = m?.[3] ?? line.split(/\s{2,}/)[1] ?? "";
1054
+ return [`
1055
+ `, (() => {
1056
+ var _el$59 = _$createElement("span");
1057
+ _$insert(_el$59, indent);
1058
+ _$effect((_$p) => _$setProp(_el$59, "style", {
1059
+ fg: theme().textMuted
1060
+ }, _$p));
1061
+ return _el$59;
1062
+ })(), (() => {
1063
+ var _el$60 = _$createElement("span");
1064
+ _$insert(_el$60, key);
1065
+ _$effect((_$p) => _$setProp(_el$60, "style", {
1066
+ fg: theme().warning,
1067
+ bold: true
1068
+ }, _$p));
1069
+ return _el$60;
1070
+ })(), desc && [(() => {
1071
+ var _el$61 = _$createElement("span");
1072
+ _$insertNode(_el$61, _$createTextNode(` `));
1073
+ _$effect((_$p) => _$setProp(_el$61, "style", {
1074
+ fg: theme().textMuted
1075
+ }, _$p));
1076
+ return _el$61;
1077
+ })(), (() => {
1078
+ var _el$63 = _$createElement("span");
1079
+ _$insert(_el$63, desc);
1080
+ _$effect((_$p) => _$setProp(_el$63, "style", {
1081
+ fg: theme().textMuted
1082
+ }, _$p));
1083
+ return _el$63;
1084
+ })()]];
1085
+ }
1086
+ const isHeader = line.startsWith("Commands");
961
1087
  return [`
962
1088
  `, (() => {
963
- var _el$45 = _$createElement("span");
964
- _$insert(_el$45, line);
965
- _$effect((_$p) => _$setProp(_el$45, "style", {
966
- fg: isHeader ? theme().primary : isCmd ? theme().warning : theme().text,
1089
+ var _el$64 = _$createElement("span");
1090
+ _$insert(_el$64, line);
1091
+ _$effect((_$p) => _$setProp(_el$64, "style", {
1092
+ fg: isHeader ? theme().primary : theme().textMuted,
967
1093
  bold: isHeader
968
1094
  }, _$p));
969
- return _el$45;
1095
+ return _el$64;
970
1096
  })()];
971
1097
  }
972
1098
  }), null);
@@ -985,63 +1111,63 @@ function LoopDashboard(props) {
985
1111
  },
986
1112
  get fallback() {
987
1113
  return (() => {
988
- var _el$46 = _$createElement("box"), _el$47 = _$createElement("text"), _el$48 = _$createElement("span"), _el$50 = _$createElement("span"), _el$52 = _$createElement("span"), _el$54 = _$createElement("text"), _el$55 = _$createElement("span"), _el$57 = _$createElement("span"), _el$59 = _$createElement("span"), _el$61 = _$createElement("span"), _el$63 = _$createElement("span"), _el$65 = _$createElement("span"), _el$67 = _$createElement("span");
989
- _$insertNode(_el$46, _el$47);
990
- _$insertNode(_el$46, _el$54);
991
- _$setProp(_el$46, "flexDirection", "column");
992
- _$setProp(_el$46, "gap", 1);
993
- _$insertNode(_el$47, _el$48);
994
- _$insertNode(_el$47, _el$50);
995
- _$insertNode(_el$47, _el$52);
996
- _$insertNode(_el$48, _$createTextNode(`No active goals.`));
997
- _$insertNode(_el$50, _$createTextNode(` /goal`));
998
- _$insertNode(_el$52, _$createTextNode(` in parent chat to create one.`));
999
- _$insertNode(_el$54, _el$55);
1000
- _$insertNode(_el$54, _el$57);
1001
- _$insertNode(_el$54, _el$59);
1002
- _$insertNode(_el$54, _el$61);
1003
- _$insertNode(_el$54, _el$63);
1004
- _$insertNode(_el$54, _el$65);
1005
- _$insertNode(_el$54, _el$67);
1006
- _$insertNode(_el$55, _$createTextNode(`Tip: `));
1007
- _$insertNode(_el$57, _$createTextNode(`:send`));
1008
- _$insertNode(_el$59, _$createTextNode(` to steer the worker \xB7 `));
1009
- _$insertNode(_el$61, _$createTextNode(`o`));
1010
- _$insertNode(_el$63, _$createTextNode(` to open child \xB7 `));
1011
- _$insertNode(_el$65, _$createTextNode(`:force`));
1012
- _$insertNode(_el$67, _$createTextNode(` to complete manually.`));
1114
+ var _el$65 = _$createElement("box"), _el$66 = _$createElement("text"), _el$67 = _$createElement("span"), _el$69 = _$createElement("span"), _el$71 = _$createElement("span"), _el$73 = _$createElement("text"), _el$74 = _$createElement("span"), _el$76 = _$createElement("span"), _el$78 = _$createElement("span"), _el$80 = _$createElement("span"), _el$82 = _$createElement("span"), _el$84 = _$createElement("span"), _el$86 = _$createElement("span");
1115
+ _$insertNode(_el$65, _el$66);
1116
+ _$insertNode(_el$65, _el$73);
1117
+ _$setProp(_el$65, "flexDirection", "column");
1118
+ _$setProp(_el$65, "gap", 1);
1119
+ _$insertNode(_el$66, _el$67);
1120
+ _$insertNode(_el$66, _el$69);
1121
+ _$insertNode(_el$66, _el$71);
1122
+ _$insertNode(_el$67, _$createTextNode(`No active goals.`));
1123
+ _$insertNode(_el$69, _$createTextNode(` /goal`));
1124
+ _$insertNode(_el$71, _$createTextNode(` in parent chat to create one.`));
1125
+ _$insertNode(_el$73, _el$74);
1126
+ _$insertNode(_el$73, _el$76);
1127
+ _$insertNode(_el$73, _el$78);
1128
+ _$insertNode(_el$73, _el$80);
1129
+ _$insertNode(_el$73, _el$82);
1130
+ _$insertNode(_el$73, _el$84);
1131
+ _$insertNode(_el$73, _el$86);
1132
+ _$insertNode(_el$74, _$createTextNode(`Tip: `));
1133
+ _$insertNode(_el$76, _$createTextNode(`:send`));
1134
+ _$insertNode(_el$78, _$createTextNode(` to steer the worker \xB7 `));
1135
+ _$insertNode(_el$80, _$createTextNode(`o`));
1136
+ _$insertNode(_el$82, _$createTextNode(` to open child \xB7 `));
1137
+ _$insertNode(_el$84, _$createTextNode(`:force`));
1138
+ _$insertNode(_el$86, _$createTextNode(` to complete manually.`));
1013
1139
  _$effect((_p$) => {
1014
- var _v$22 = {
1140
+ var _v$21 = {
1015
1141
  fg: theme().textMuted
1016
- }, _v$23 = {
1142
+ }, _v$22 = {
1017
1143
  fg: theme().accent
1144
+ }, _v$23 = {
1145
+ fg: theme().textMuted
1018
1146
  }, _v$24 = {
1019
1147
  fg: theme().textMuted
1020
1148
  }, _v$25 = {
1021
- fg: theme().textMuted
1022
- }, _v$26 = {
1023
1149
  fg: theme().warning
1024
- }, _v$27 = {
1150
+ }, _v$26 = {
1025
1151
  fg: theme().textMuted
1026
- }, _v$28 = {
1152
+ }, _v$27 = {
1027
1153
  fg: theme().warning
1028
- }, _v$29 = {
1154
+ }, _v$28 = {
1029
1155
  fg: theme().textMuted
1030
- }, _v$30 = {
1156
+ }, _v$29 = {
1031
1157
  fg: theme().warning
1032
- }, _v$31 = {
1158
+ }, _v$30 = {
1033
1159
  fg: theme().textMuted
1034
1160
  };
1035
- _v$22 !== _p$.e && (_p$.e = _$setProp(_el$48, "style", _v$22, _p$.e));
1036
- _v$23 !== _p$.t && (_p$.t = _$setProp(_el$50, "style", _v$23, _p$.t));
1037
- _v$24 !== _p$.a && (_p$.a = _$setProp(_el$52, "style", _v$24, _p$.a));
1038
- _v$25 !== _p$.o && (_p$.o = _$setProp(_el$55, "style", _v$25, _p$.o));
1039
- _v$26 !== _p$.i && (_p$.i = _$setProp(_el$57, "style", _v$26, _p$.i));
1040
- _v$27 !== _p$.n && (_p$.n = _$setProp(_el$59, "style", _v$27, _p$.n));
1041
- _v$28 !== _p$.s && (_p$.s = _$setProp(_el$61, "style", _v$28, _p$.s));
1042
- _v$29 !== _p$.h && (_p$.h = _$setProp(_el$63, "style", _v$29, _p$.h));
1043
- _v$30 !== _p$.r && (_p$.r = _$setProp(_el$65, "style", _v$30, _p$.r));
1044
- _v$31 !== _p$.d && (_p$.d = _$setProp(_el$67, "style", _v$31, _p$.d));
1161
+ _v$21 !== _p$.e && (_p$.e = _$setProp(_el$67, "style", _v$21, _p$.e));
1162
+ _v$22 !== _p$.t && (_p$.t = _$setProp(_el$69, "style", _v$22, _p$.t));
1163
+ _v$23 !== _p$.a && (_p$.a = _$setProp(_el$71, "style", _v$23, _p$.a));
1164
+ _v$24 !== _p$.o && (_p$.o = _$setProp(_el$74, "style", _v$24, _p$.o));
1165
+ _v$25 !== _p$.i && (_p$.i = _$setProp(_el$76, "style", _v$25, _p$.i));
1166
+ _v$26 !== _p$.n && (_p$.n = _$setProp(_el$78, "style", _v$26, _p$.n));
1167
+ _v$27 !== _p$.s && (_p$.s = _$setProp(_el$80, "style", _v$27, _p$.s));
1168
+ _v$28 !== _p$.h && (_p$.h = _$setProp(_el$82, "style", _v$28, _p$.h));
1169
+ _v$29 !== _p$.r && (_p$.r = _$setProp(_el$84, "style", _v$29, _p$.r));
1170
+ _v$30 !== _p$.d && (_p$.d = _$setProp(_el$86, "style", _v$30, _p$.d));
1045
1171
  return _p$;
1046
1172
  }, {
1047
1173
  e: undefined,
@@ -1055,7 +1181,7 @@ function LoopDashboard(props) {
1055
1181
  r: undefined,
1056
1182
  d: undefined
1057
1183
  });
1058
- return _el$46;
1184
+ return _el$65;
1059
1185
  })();
1060
1186
  },
1061
1187
  get children() {
@@ -1078,102 +1204,102 @@ function LoopDashboard(props) {
1078
1204
  return phaseColor(runtime().phase || "idle", theme());
1079
1205
  };
1080
1206
  return (() => {
1081
- var _el$69 = _$createElement("box"), _el$70 = _$createElement("text"), _el$71 = _$createElement("span"), _el$72 = _$createElement("span"), _el$74 = _$createElement("span");
1082
- _$insertNode(_el$69, _el$70);
1083
- _$setProp(_el$69, "flexDirection", "row");
1084
- _$setProp(_el$69, "paddingLeft", 1);
1085
- _$setProp(_el$69, "paddingRight", 1);
1086
- _$insertNode(_el$70, _el$71);
1087
- _$insertNode(_el$70, _el$72);
1088
- _$insertNode(_el$70, _el$74);
1089
- _$insert(_el$71, (() => {
1207
+ var _el$88 = _$createElement("box"), _el$89 = _$createElement("text"), _el$90 = _$createElement("span"), _el$91 = _$createElement("span"), _el$93 = _$createElement("span");
1208
+ _$insertNode(_el$88, _el$89);
1209
+ _$setProp(_el$88, "flexDirection", "row");
1210
+ _$setProp(_el$88, "paddingLeft", 1);
1211
+ _$setProp(_el$88, "paddingRight", 1);
1212
+ _$insertNode(_el$89, _el$90);
1213
+ _$insertNode(_el$89, _el$91);
1214
+ _$insertNode(_el$89, _el$93);
1215
+ _$insert(_el$90, (() => {
1090
1216
  var _c$2 = _$memo(() => !!isActive());
1091
1217
  return () => _c$2() ? `\u25B6 ${statusIcon(goal.status)} ${goal.name}` : ` ${statusIcon(goal.status)} ${goal.name}`;
1092
1218
  })());
1093
- _$insertNode(_el$72, _$createTextNode(` \u2502 `));
1094
- _$insert(_el$74, () => goal.status.toUpperCase());
1095
- _$insert(_el$70, (() => {
1219
+ _$insertNode(_el$91, _$createTextNode(` \u2502 `));
1220
+ _$insert(_el$93, () => goal.status.toUpperCase());
1221
+ _$insert(_el$89, (() => {
1096
1222
  var _c$3 = _$memo(() => !!runtime());
1097
1223
  return () => _c$3() && [(() => {
1098
- var _el$75 = _$createElement("span");
1099
- _$insertNode(_el$75, _$createTextNode(` \u2502 `));
1100
- _$effect((_$p) => _$setProp(_el$75, "style", {
1224
+ var _el$94 = _$createElement("span");
1225
+ _$insertNode(_el$94, _$createTextNode(` \u2502 `));
1226
+ _$effect((_$p) => _$setProp(_el$94, "style", {
1101
1227
  fg: theme().textMuted
1102
1228
  }, _$p));
1103
- return _el$75;
1229
+ return _el$94;
1104
1230
  })(), (() => {
1105
- var _el$77 = _$createElement("span"), _el$78 = _$createTextNode(` `);
1106
- _$insertNode(_el$77, _el$78);
1107
- _$insert(_el$77, (() => {
1231
+ var _el$96 = _$createElement("span"), _el$97 = _$createTextNode(` `);
1232
+ _$insertNode(_el$96, _el$97);
1233
+ _$insert(_el$96, (() => {
1108
1234
  var _c$6 = _$memo(() => runtime().phase === "running");
1109
1235
  return () => _c$6() ? runningFrame() : phaseIcon(runtime().phase);
1110
- })(), _el$78);
1111
- _$insert(_el$77, () => runtime().phase.toUpperCase(), null);
1112
- _$effect((_$p) => _$setProp(_el$77, "style", {
1236
+ })(), _el$97);
1237
+ _$insert(_el$96, () => runtime().phase.toUpperCase(), null);
1238
+ _$effect((_$p) => _$setProp(_el$96, "style", {
1113
1239
  fg: turnColor(),
1114
1240
  bold: runtime().phase === "running"
1115
1241
  }, _$p));
1116
- return _el$77;
1242
+ return _el$96;
1117
1243
  })(), (() => {
1118
- var _el$79 = _$createElement("span"), _el$80 = _$createTextNode(` `);
1119
- _$insertNode(_el$79, _el$80);
1120
- _$insert(_el$79, () => runtime().turnCount, null);
1121
- _$insert(_el$79, maxTurns ? `/${maxTurns}` : "", null);
1122
- _$effect((_$p) => _$setProp(_el$79, "style", {
1244
+ var _el$98 = _$createElement("span"), _el$99 = _$createTextNode(` `);
1245
+ _$insertNode(_el$98, _el$99);
1246
+ _$insert(_el$98, () => runtime().turnCount, null);
1247
+ _$insert(_el$98, maxTurns ? `/${maxTurns}` : "", null);
1248
+ _$effect((_$p) => _$setProp(_el$98, "style", {
1123
1249
  fg: turnColor()
1124
1250
  }, _$p));
1125
- return _el$79;
1251
+ return _el$98;
1126
1252
  })(), (() => {
1127
- var _el$81 = _$createElement("span"), _el$82 = _$createTextNode(` `);
1128
- _$insertNode(_el$81, _el$82);
1129
- _$insert(_el$81, () => ageLabel(runtime().lastProgressAt || runtime().lastRunAt, clock()), null);
1130
- _$effect((_$p) => _$setProp(_el$81, "style", {
1253
+ var _el$100 = _$createElement("span"), _el$101 = _$createTextNode(` `);
1254
+ _$insertNode(_el$100, _el$101);
1255
+ _$insert(_el$100, () => ageLabel(runtime().lastProgressAt || runtime().lastRunAt, clock()), null);
1256
+ _$effect((_$p) => _$setProp(_el$100, "style", {
1131
1257
  fg: theme().textMuted
1132
1258
  }, _$p));
1133
- return _el$81;
1259
+ return _el$100;
1134
1260
  })()];
1135
1261
  })(), null);
1136
- _$insert(_el$70, (() => {
1262
+ _$insert(_el$89, (() => {
1137
1263
  var _c$4 = _$memo(() => !!(runtime() && runtime().consecutiveFailures > 0));
1138
1264
  return () => _c$4() && (() => {
1139
- var _el$83 = _$createElement("span"), _el$84 = _$createTextNode(` \u2502 \u26A0 `), _el$85 = _$createTextNode(` fail`);
1140
- _$insertNode(_el$83, _el$84);
1141
- _$insertNode(_el$83, _el$85);
1142
- _$insert(_el$83, () => runtime().consecutiveFailures, _el$85);
1143
- _$effect((_$p) => _$setProp(_el$83, "style", {
1265
+ var _el$102 = _$createElement("span"), _el$103 = _$createTextNode(` \u2502 \u26A0 `), _el$104 = _$createTextNode(` fail`);
1266
+ _$insertNode(_el$102, _el$103);
1267
+ _$insertNode(_el$102, _el$104);
1268
+ _$insert(_el$102, () => runtime().consecutiveFailures, _el$104);
1269
+ _$effect((_$p) => _$setProp(_el$102, "style", {
1144
1270
  fg: theme().error,
1145
1271
  bold: true
1146
1272
  }, _$p));
1147
- return _el$83;
1273
+ return _el$102;
1148
1274
  })();
1149
1275
  })(), null);
1150
- _$insert(_el$70, (() => {
1276
+ _$insert(_el$89, (() => {
1151
1277
  var _c$5 = _$memo(() => !!(runtime() && (runtime().noProgressCount || 0) > 0));
1152
1278
  return () => _c$5() && (() => {
1153
- var _el$86 = _$createElement("span"), _el$87 = _$createTextNode(` \u2502 `), _el$88 = _$createTextNode(` no-progress`);
1154
- _$insertNode(_el$86, _el$87);
1155
- _$insertNode(_el$86, _el$88);
1156
- _$insert(_el$86, () => runtime().noProgressCount, _el$88);
1157
- _$effect((_$p) => _$setProp(_el$86, "style", {
1279
+ var _el$105 = _$createElement("span"), _el$106 = _$createTextNode(` \u2502 `), _el$107 = _$createTextNode(` no-progress`);
1280
+ _$insertNode(_el$105, _el$106);
1281
+ _$insertNode(_el$105, _el$107);
1282
+ _$insert(_el$105, () => runtime().noProgressCount, _el$107);
1283
+ _$effect((_$p) => _$setProp(_el$105, "style", {
1158
1284
  fg: theme().warning
1159
1285
  }, _$p));
1160
- return _el$86;
1286
+ return _el$105;
1161
1287
  })();
1162
1288
  })(), null);
1163
1289
  _$effect((_p$) => {
1164
- var _v$32 = isActive() ? theme().backgroundElement : undefined, _v$33 = {
1290
+ var _v$31 = isActive() ? theme().backgroundElement : undefined, _v$32 = {
1165
1291
  fg: statusColor(goal.status, theme()),
1166
1292
  bold: isActive()
1167
- }, _v$34 = {
1293
+ }, _v$33 = {
1168
1294
  fg: theme().textMuted
1169
- }, _v$35 = {
1295
+ }, _v$34 = {
1170
1296
  fg: statusColor(goal.status, theme()),
1171
1297
  bold: true
1172
1298
  };
1173
- _v$32 !== _p$.e && (_p$.e = _$setProp(_el$69, "backgroundColor", _v$32, _p$.e));
1174
- _v$33 !== _p$.t && (_p$.t = _$setProp(_el$71, "style", _v$33, _p$.t));
1175
- _v$34 !== _p$.a && (_p$.a = _$setProp(_el$72, "style", _v$34, _p$.a));
1176
- _v$35 !== _p$.o && (_p$.o = _$setProp(_el$74, "style", _v$35, _p$.o));
1299
+ _v$31 !== _p$.e && (_p$.e = _$setProp(_el$88, "backgroundColor", _v$31, _p$.e));
1300
+ _v$32 !== _p$.t && (_p$.t = _$setProp(_el$90, "style", _v$32, _p$.t));
1301
+ _v$33 !== _p$.a && (_p$.a = _$setProp(_el$91, "style", _v$33, _p$.a));
1302
+ _v$34 !== _p$.o && (_p$.o = _$setProp(_el$93, "style", _v$34, _p$.o));
1177
1303
  return _p$;
1178
1304
  }, {
1179
1305
  e: undefined,
@@ -1181,7 +1307,7 @@ function LoopDashboard(props) {
1181
1307
  a: undefined,
1182
1308
  o: undefined
1183
1309
  });
1184
- return _el$69;
1310
+ return _el$88;
1185
1311
  })();
1186
1312
  }
1187
1313
  });
@@ -1194,159 +1320,178 @@ function LoopDashboard(props) {
1194
1320
  children: (goal) => {
1195
1321
  const rt = () => state()?.runtimes.find((r) => r.goalID === goal().id);
1196
1322
  return (() => {
1197
- var _el$89 = _$createElement("box"), _el$90 = _$createElement("text"), _el$91 = _$createElement("span"), _el$92 = _$createTextNode(` `), _el$93 = _$createElement("span"), _el$94 = _$createTextNode(` `), _el$95 = _$createTextNode(`
1198
- `), _el$96 = _$createElement("span");
1199
- _$insertNode(_el$89, _el$90);
1200
- _$setProp(_el$89, "flexDirection", "column");
1201
- _$setProp(_el$89, "border", true);
1202
- _$setProp(_el$89, "padding", 1);
1203
- _$setProp(_el$89, "flexShrink", 0);
1204
- _$setProp(_el$89, "maxHeight", 10);
1205
- _$insertNode(_el$90, _el$91);
1206
- _$insertNode(_el$90, _el$93);
1207
- _$insertNode(_el$90, _el$95);
1208
- _$insertNode(_el$90, _el$96);
1209
- _$insertNode(_el$91, _el$92);
1210
- _$insert(_el$91, () => statusIcon(goal().status), _el$92);
1211
- _$insert(_el$91, () => goal().name, null);
1212
- _$insertNode(_el$93, _el$94);
1213
- _$insert(_el$93, () => goal().status.toUpperCase(), null);
1214
- _$insert(_el$90, (() => {
1323
+ var _el$108 = _$createElement("box"), _el$109 = _$createElement("text"), _el$110 = _$createElement("span"), _el$111 = _$createTextNode(` `), _el$112 = _$createElement("span"), _el$113 = _$createTextNode(` `), _el$114 = _$createTextNode(`
1324
+ `), _el$115 = _$createElement("span");
1325
+ _$insertNode(_el$108, _el$109);
1326
+ _$setProp(_el$108, "flexDirection", "column");
1327
+ _$setProp(_el$108, "border", true);
1328
+ _$setProp(_el$108, "padding", 1);
1329
+ _$setProp(_el$108, "flexShrink", 0);
1330
+ _$setProp(_el$108, "maxHeight", 10);
1331
+ _$insertNode(_el$109, _el$110);
1332
+ _$insertNode(_el$109, _el$112);
1333
+ _$insertNode(_el$109, _el$114);
1334
+ _$insertNode(_el$109, _el$115);
1335
+ _$insertNode(_el$110, _el$111);
1336
+ _$insert(_el$110, () => statusIcon(goal().status), _el$111);
1337
+ _$insert(_el$110, () => goal().name, null);
1338
+ _$insertNode(_el$112, _el$113);
1339
+ _$insert(_el$112, () => goal().status.toUpperCase(), null);
1340
+ _$insert(_el$109, (() => {
1215
1341
  var _c$7 = _$memo(() => !!rt());
1216
1342
  return () => _c$7() && [(() => {
1217
- var _el$97 = _$createElement("span");
1218
- _$insertNode(_el$97, _$createTextNode(` \u2502 `));
1219
- _$effect((_$p) => _$setProp(_el$97, "style", {
1343
+ var _el$116 = _$createElement("span");
1344
+ _$insertNode(_el$116, _$createTextNode(` \u2502 `));
1345
+ _$effect((_$p) => _$setProp(_el$116, "style", {
1220
1346
  fg: theme().textMuted
1221
1347
  }, _$p));
1222
- return _el$97;
1348
+ return _el$116;
1223
1349
  })(), (() => {
1224
- var _el$99 = _$createElement("span"), _el$100 = _$createTextNode(` `);
1225
- _$insertNode(_el$99, _el$100);
1226
- _$insert(_el$99, () => phaseIcon(rt().phase), _el$100);
1227
- _$insert(_el$99, () => rt().phase, null);
1228
- _$effect((_$p) => _$setProp(_el$99, "style", {
1350
+ var _el$118 = _$createElement("span"), _el$119 = _$createTextNode(` `);
1351
+ _$insertNode(_el$118, _el$119);
1352
+ _$insert(_el$118, () => phaseIcon(rt().phase), _el$119);
1353
+ _$insert(_el$118, () => rt().phase, null);
1354
+ _$effect((_$p) => _$setProp(_el$118, "style", {
1229
1355
  fg: phaseColor(rt().phase, theme()),
1230
1356
  bold: true
1231
1357
  }, _$p));
1232
- return _el$99;
1358
+ return _el$118;
1233
1359
  })(), (() => {
1234
- var _el$101 = _$createElement("span"), _el$102 = _$createTextNode(` turn `);
1235
- _$insertNode(_el$101, _el$102);
1236
- _$insert(_el$101, () => rt().turnCount, null);
1237
- _$effect((_$p) => _$setProp(_el$101, "style", {
1360
+ var _el$120 = _$createElement("span"), _el$121 = _$createTextNode(` turn `);
1361
+ _$insertNode(_el$120, _el$121);
1362
+ _$insert(_el$120, () => rt().turnCount, null);
1363
+ _$effect((_$p) => _$setProp(_el$120, "style", {
1238
1364
  fg: theme().textMuted
1239
1365
  }, _$p));
1240
- return _el$101;
1366
+ return _el$120;
1241
1367
  })()];
1242
- })(), _el$95);
1243
- _$insert(_el$96, () => goal().objective.slice(0, 160));
1244
- _$insert(_el$90, (() => {
1368
+ })(), _el$114);
1369
+ _$insert(_el$115, () => goal().objective.slice(0, 160));
1370
+ _$insert(_el$109, (() => {
1245
1371
  var _c$8 = _$memo(() => !!goal().lastProgress);
1246
1372
  return () => _c$8() && [(() => {
1247
- var _el$103 = _$createElement("span"), _el$104 = _$createTextNode(`
1373
+ var _el$122 = _$createElement("span"), _el$123 = _$createTextNode(`
1248
1374
  \u2714 `);
1249
- _$insertNode(_el$103, _el$104);
1250
- _$effect((_$p) => _$setProp(_el$103, "style", {
1375
+ _$insertNode(_el$122, _el$123);
1376
+ _$effect((_$p) => _$setProp(_el$122, "style", {
1251
1377
  fg: theme().success
1252
1378
  }, _$p));
1253
- return _el$103;
1379
+ return _el$122;
1254
1380
  })(), (() => {
1255
- var _el$106 = _$createElement("span");
1256
- _$insert(_el$106, () => goal().lastProgress.summary.slice(0, 100));
1257
- _$effect((_$p) => _$setProp(_el$106, "style", {
1381
+ var _el$125 = _$createElement("span");
1382
+ _$insert(_el$125, () => goal().lastProgress.summary.slice(0, 100));
1383
+ _$effect((_$p) => _$setProp(_el$125, "style", {
1258
1384
  fg: theme().text
1259
1385
  }, _$p));
1260
- return _el$106;
1386
+ return _el$125;
1261
1387
  })(), (() => {
1262
- var _el$107 = _$createElement("span"), _el$108 = _$createTextNode(` \u2192 `);
1263
- _$insertNode(_el$107, _el$108);
1264
- _$insert(_el$107, () => goal().lastProgress.next?.slice(0, 60) || "", null);
1265
- _$effect((_$p) => _$setProp(_el$107, "style", {
1388
+ var _el$126 = _$createElement("span"), _el$127 = _$createTextNode(` \u2192 `);
1389
+ _$insertNode(_el$126, _el$127);
1390
+ _$insert(_el$126, () => goal().lastProgress.next?.slice(0, 60) || "", null);
1391
+ _$effect((_$p) => _$setProp(_el$126, "style", {
1266
1392
  fg: theme().textMuted
1267
1393
  }, _$p));
1268
- return _el$107;
1394
+ return _el$126;
1269
1395
  })()];
1270
1396
  })(), null);
1271
- _$insert(_el$90, (() => {
1397
+ _$insert(_el$109, (() => {
1272
1398
  var _c$9 = _$memo(() => !!goal().blocker);
1273
1399
  return () => _c$9() && [(() => {
1274
- var _el$109 = _$createElement("span"), _el$110 = _$createTextNode(`
1400
+ var _el$128 = _$createElement("span"), _el$129 = _$createTextNode(`
1275
1401
  \u2716 blocked: `);
1276
- _$insertNode(_el$109, _el$110);
1277
- _$effect((_$p) => _$setProp(_el$109, "style", {
1402
+ _$insertNode(_el$128, _el$129);
1403
+ _$effect((_$p) => _$setProp(_el$128, "style", {
1278
1404
  fg: theme().error,
1279
1405
  bold: true
1280
1406
  }, _$p));
1281
- return _el$109;
1407
+ return _el$128;
1282
1408
  })(), (() => {
1283
- var _el$112 = _$createElement("span");
1284
- _$insert(_el$112, () => goal().blocker.reason.slice(0, 140));
1285
- _$effect((_$p) => _$setProp(_el$112, "style", {
1409
+ var _el$131 = _$createElement("span");
1410
+ _$insert(_el$131, () => goal().blocker.reason.slice(0, 140));
1411
+ _$effect((_$p) => _$setProp(_el$131, "style", {
1286
1412
  fg: theme().error
1287
1413
  }, _$p));
1288
- return _el$112;
1414
+ return _el$131;
1289
1415
  })(), (() => {
1290
- var _el$113 = _$createElement("span"), _el$114 = _$createTextNode(` \u2014 `);
1291
- _$insertNode(_el$113, _el$114);
1292
- _$insert(_el$113, () => goal().blocker.needed.slice(0, 60), null);
1293
- _$effect((_$p) => _$setProp(_el$113, "style", {
1416
+ var _el$132 = _$createElement("span"), _el$133 = _$createTextNode(` \u2014 `);
1417
+ _$insertNode(_el$132, _el$133);
1418
+ _$insert(_el$132, () => goal().blocker.needed.slice(0, 60), null);
1419
+ _$effect((_$p) => _$setProp(_el$132, "style", {
1294
1420
  fg: theme().textMuted
1295
1421
  }, _$p));
1296
- return _el$113;
1422
+ return _el$132;
1297
1423
  })()];
1298
1424
  })(), null);
1299
- _$insert(_el$90, (() => {
1425
+ _$insert(_el$109, (() => {
1300
1426
  var _c$0 = _$memo(() => !!goal().config.artifactDir);
1301
1427
  return () => _c$0() && [(() => {
1302
- var _el$115 = _$createElement("span"), _el$116 = _$createTextNode(`
1428
+ var _el$134 = _$createElement("span"), _el$135 = _$createTextNode(`
1303
1429
  \uD83D\uDCC1 `);
1304
- _$insertNode(_el$115, _el$116);
1305
- _$effect((_$p) => _$setProp(_el$115, "style", {
1430
+ _$insertNode(_el$134, _el$135);
1431
+ _$effect((_$p) => _$setProp(_el$134, "style", {
1306
1432
  fg: theme().accent
1307
1433
  }, _$p));
1308
- return _el$115;
1434
+ return _el$134;
1309
1435
  })(), (() => {
1310
- var _el$118 = _$createElement("span");
1311
- _$insert(_el$118, () => String(goal().config.artifactDir).replace(String(props.directory), "."));
1312
- _$effect((_$p) => _$setProp(_el$118, "style", {
1436
+ var _el$137 = _$createElement("span");
1437
+ _$insert(_el$137, () => String(goal().config.artifactDir).replace(String(props.directory), "."));
1438
+ _$effect((_$p) => _$setProp(_el$137, "style", {
1313
1439
  fg: theme().textMuted
1314
1440
  }, _$p));
1315
- return _el$118;
1441
+ return _el$137;
1316
1442
  })()];
1317
1443
  })(), null);
1318
- _$insert(_el$90, (() => {
1319
- var _c$1 = _$memo(() => !!rt()?.lastError);
1320
- return () => _c$1() && [(() => {
1321
- var _el$119 = _$createElement("span"), _el$120 = _$createTextNode(`
1444
+ _$insert(_el$109, (() => {
1445
+ var _c$1 = _$memo(() => (goal().config.checks?.length ?? 0) > 0);
1446
+ return () => _c$1() ? [(() => {
1447
+ var _el$138 = _$createElement("span"), _el$139 = _$createTextNode(`
1448
+ \u25A3 checks: `);
1449
+ _$insertNode(_el$138, _el$139);
1450
+ _$effect((_$p) => _$setProp(_el$138, "style", {
1451
+ fg: theme().warning
1452
+ }, _$p));
1453
+ return _el$138;
1454
+ })(), (() => {
1455
+ var _el$141 = _$createElement("span");
1456
+ _$insert(_el$141, () => goal().config.checks.join(", ").slice(0, 100));
1457
+ _$effect((_$p) => _$setProp(_el$141, "style", {
1458
+ fg: theme().textMuted
1459
+ }, _$p));
1460
+ return _el$141;
1461
+ })()] : null;
1462
+ })(), null);
1463
+ _$insert(_el$109, (() => {
1464
+ var _c$10 = _$memo(() => !!rt()?.lastError);
1465
+ return () => _c$10() && [(() => {
1466
+ var _el$142 = _$createElement("span"), _el$143 = _$createTextNode(`
1322
1467
  \u26A0 `);
1323
- _$insertNode(_el$119, _el$120);
1324
- _$effect((_$p) => _$setProp(_el$119, "style", {
1468
+ _$insertNode(_el$142, _el$143);
1469
+ _$effect((_$p) => _$setProp(_el$142, "style", {
1325
1470
  fg: theme().error
1326
1471
  }, _$p));
1327
- return _el$119;
1472
+ return _el$142;
1328
1473
  })(), (() => {
1329
- var _el$122 = _$createElement("span");
1330
- _$insert(_el$122, () => rt().lastError.slice(0, 120));
1331
- _$effect((_$p) => _$setProp(_el$122, "style", {
1474
+ var _el$145 = _$createElement("span");
1475
+ _$insert(_el$145, () => rt().lastError.slice(0, 120));
1476
+ _$effect((_$p) => _$setProp(_el$145, "style", {
1332
1477
  fg: theme().error
1333
1478
  }, _$p));
1334
- return _el$122;
1479
+ return _el$145;
1335
1480
  })()];
1336
1481
  })(), null);
1337
1482
  _$effect((_p$) => {
1338
- var _v$36 = borderColorForStatus(goal().status, theme()), _v$37 = {
1483
+ var _v$35 = borderColorForStatus(goal().status, theme()), _v$36 = {
1339
1484
  fg: statusColor(goal().status, theme()),
1340
1485
  bold: true
1341
- }, _v$38 = {
1486
+ }, _v$37 = {
1342
1487
  fg: statusColor(goal().status, theme())
1343
- }, _v$39 = {
1488
+ }, _v$38 = {
1344
1489
  fg: theme().text
1345
1490
  };
1346
- _v$36 !== _p$.e && (_p$.e = _$setProp(_el$89, "borderColor", _v$36, _p$.e));
1347
- _v$37 !== _p$.t && (_p$.t = _$setProp(_el$91, "style", _v$37, _p$.t));
1348
- _v$38 !== _p$.a && (_p$.a = _$setProp(_el$93, "style", _v$38, _p$.a));
1349
- _v$39 !== _p$.o && (_p$.o = _$setProp(_el$96, "style", _v$39, _p$.o));
1491
+ _v$35 !== _p$.e && (_p$.e = _$setProp(_el$108, "borderColor", _v$35, _p$.e));
1492
+ _v$36 !== _p$.t && (_p$.t = _$setProp(_el$110, "style", _v$36, _p$.t));
1493
+ _v$37 !== _p$.a && (_p$.a = _$setProp(_el$112, "style", _v$37, _p$.a));
1494
+ _v$38 !== _p$.o && (_p$.o = _$setProp(_el$115, "style", _v$38, _p$.o));
1350
1495
  return _p$;
1351
1496
  }, {
1352
1497
  e: undefined,
@@ -1354,7 +1499,7 @@ function LoopDashboard(props) {
1354
1499
  a: undefined,
1355
1500
  o: undefined
1356
1501
  });
1357
- return _el$89;
1502
+ return _el$108;
1358
1503
  })();
1359
1504
  }
1360
1505
  }), null);
@@ -1380,39 +1525,39 @@ function LoopDashboard(props) {
1380
1525
  return events().slice(-10);
1381
1526
  },
1382
1527
  children: (ev) => (() => {
1383
- var _el$123 = _$createElement("text"), _el$124 = _$createElement("span"), _el$125 = _$createElement("span"), _el$126 = _$createTextNode(` `);
1384
- _$insertNode(_el$123, _el$124);
1385
- _$insertNode(_el$123, _el$125);
1386
- _$insert(_el$124, () => String(ev.type));
1387
- _$insertNode(_el$125, _el$126);
1388
- _$insert(_el$125, () => ev.goalID?.slice(0, 8), null);
1389
- _$insert(_el$123, (() => {
1390
- var _c$10 = _$memo(() => !!ev.summary);
1391
- return () => _c$10() && (() => {
1392
- var _el$127 = _$createElement("span"), _el$128 = _$createTextNode(` \u2014 `);
1393
- _$insertNode(_el$127, _el$128);
1394
- _$insert(_el$127, () => String(ev.summary).slice(0, 60), null);
1395
- _$effect((_$p) => _$setProp(_el$127, "style", {
1528
+ var _el$146 = _$createElement("text"), _el$147 = _$createElement("span"), _el$148 = _$createElement("span"), _el$149 = _$createTextNode(` `);
1529
+ _$insertNode(_el$146, _el$147);
1530
+ _$insertNode(_el$146, _el$148);
1531
+ _$insert(_el$147, () => String(ev.type));
1532
+ _$insertNode(_el$148, _el$149);
1533
+ _$insert(_el$148, () => ev.goalID?.slice(0, 8), null);
1534
+ _$insert(_el$146, (() => {
1535
+ var _c$11 = _$memo(() => !!ev.summary);
1536
+ return () => _c$11() && (() => {
1537
+ var _el$150 = _$createElement("span"), _el$151 = _$createTextNode(` \u2014 `);
1538
+ _$insertNode(_el$150, _el$151);
1539
+ _$insert(_el$150, () => String(ev.summary).slice(0, 60), null);
1540
+ _$effect((_$p) => _$setProp(_el$150, "style", {
1396
1541
  fg: theme().text
1397
1542
  }, _$p));
1398
- return _el$127;
1543
+ return _el$150;
1399
1544
  })();
1400
1545
  })(), null);
1401
1546
  _$effect((_p$) => {
1402
- var _v$40 = {
1547
+ var _v$39 = {
1403
1548
  fg: eventColor(String(ev.type), theme()),
1404
1549
  bold: true
1405
- }, _v$41 = {
1550
+ }, _v$40 = {
1406
1551
  fg: theme().textMuted
1407
1552
  };
1408
- _v$40 !== _p$.e && (_p$.e = _$setProp(_el$124, "style", _v$40, _p$.e));
1409
- _v$41 !== _p$.t && (_p$.t = _$setProp(_el$125, "style", _v$41, _p$.t));
1553
+ _v$39 !== _p$.e && (_p$.e = _$setProp(_el$147, "style", _v$39, _p$.e));
1554
+ _v$40 !== _p$.t && (_p$.t = _$setProp(_el$148, "style", _v$40, _p$.t));
1410
1555
  return _p$;
1411
1556
  }, {
1412
1557
  e: undefined,
1413
1558
  t: undefined
1414
1559
  });
1415
- return _el$123;
1560
+ return _el$146;
1416
1561
  })()
1417
1562
  }), null);
1418
1563
  _$effect((_p$) => {
@@ -1508,14 +1653,11 @@ function LoopDashboard(props) {
1508
1653
  bold: true
1509
1654
  }, _v$13 = {
1510
1655
  fg: theme().textMuted
1511
- }, _v$14 = {
1512
- fg: theme().error,
1513
- bold: true
1514
- }, _v$15 = mode() === "insert" ? theme().warning : theme().border, _v$16 = {
1656
+ }, _v$14 = mode() === "insert" ? theme().warning : theme().border, _v$15 = {
1515
1657
  fg: mode() === "insert" ? theme().warning : theme().success,
1516
1658
  bold: true,
1517
1659
  bg: mode() === "insert" ? theme().backgroundElement : undefined
1518
- }, _v$17 = mode() === "insert" ? ":send hello or :force done --evidence proof or :open (Ctrl+N: normal)" : statusText() || "Press : to send/command \xB7 ? help \xB7 o open child \xB7 q close", _v$18 = theme().textMuted, _v$19 = theme().primary, _v$20 = theme().text, _v$21 = theme().background;
1660
+ }, _v$16 = mode() === "insert" ? ":send hello or :force done --evidence proof or :open (Ctrl+N: normal)" : statusText() || "Press : to send/command \xB7 ? help \xB7 o open child \xB7 q close", _v$17 = theme().textMuted, _v$18 = theme().primary, _v$19 = theme().text, _v$20 = theme().background;
1519
1661
  _v$4 !== _p$.e && (_p$.e = _$setProp(_el$2, "borderColor", _v$4, _p$.e));
1520
1662
  _v$5 !== _p$.t && (_p$.t = _$setProp(_el$5, "style", _v$5, _p$.t));
1521
1663
  _v$6 !== _p$.a && (_p$.a = _$setProp(_el$7, "style", _v$6, _p$.a));
@@ -1528,14 +1670,13 @@ function LoopDashboard(props) {
1528
1670
  _v$11 !== _p$.d && (_p$.d = _$setProp(_el$20, "style", _v$11, _p$.d));
1529
1671
  _v$12 !== _p$.l && (_p$.l = _$setProp(_el$22, "style", _v$12, _p$.l));
1530
1672
  _v$13 !== _p$.u && (_p$.u = _$setProp(_el$23, "style", _v$13, _p$.u));
1531
- _v$14 !== _p$.c && (_p$.c = _$setProp(_el$27, "style", _v$14, _p$.c));
1532
- _v$15 !== _p$.w && (_p$.w = _$setProp(_el$41, "borderColor", _v$15, _p$.w));
1533
- _v$16 !== _p$.m && (_p$.m = _$setProp(_el$43, "style", _v$16, _p$.m));
1534
- _v$17 !== _p$.f && (_p$.f = _$setProp(_el$44, "placeholder", _v$17, _p$.f));
1535
- _v$18 !== _p$.y && (_p$.y = _$setProp(_el$44, "placeholderColor", _v$18, _p$.y));
1536
- _v$19 !== _p$.g && (_p$.g = _$setProp(_el$44, "cursorColor", _v$19, _p$.g));
1537
- _v$20 !== _p$.p && (_p$.p = _$setProp(_el$44, "focusedTextColor", _v$20, _p$.p));
1538
- _v$21 !== _p$.b && (_p$.b = _$setProp(_el$44, "focusedBackgroundColor", _v$21, _p$.b));
1673
+ _v$14 !== _p$.c && (_p$.c = _$setProp(_el$41, "borderColor", _v$14, _p$.c));
1674
+ _v$15 !== _p$.w && (_p$.w = _$setProp(_el$43, "style", _v$15, _p$.w));
1675
+ _v$16 !== _p$.m && (_p$.m = _$setProp(_el$44, "placeholder", _v$16, _p$.m));
1676
+ _v$17 !== _p$.f && (_p$.f = _$setProp(_el$44, "placeholderColor", _v$17, _p$.f));
1677
+ _v$18 !== _p$.y && (_p$.y = _$setProp(_el$44, "cursorColor", _v$18, _p$.y));
1678
+ _v$19 !== _p$.g && (_p$.g = _$setProp(_el$44, "focusedTextColor", _v$19, _p$.g));
1679
+ _v$20 !== _p$.p && (_p$.p = _$setProp(_el$44, "focusedBackgroundColor", _v$20, _p$.p));
1539
1680
  return _p$;
1540
1681
  }, {
1541
1682
  e: undefined,
@@ -1556,8 +1697,7 @@ function LoopDashboard(props) {
1556
1697
  f: undefined,
1557
1698
  y: undefined,
1558
1699
  g: undefined,
1559
- p: undefined,
1560
- b: undefined
1700
+ p: undefined
1561
1701
  });
1562
1702
  return _el$;
1563
1703
  })();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
3
  "name": "@bojackduy/opencode-loopd",
4
- "version": "1.3.0",
4
+ "version": "1.4.0",
5
5
  "description": "Codex-inspired background goal engine for OpenCode — autonomous subagents, engine-driven loop, child worker sessions and modal TUI dashboard. Like Claude Code loop for OpenCode.",
6
6
  "type": "module",
7
7
  "license": "AGPL-3.0-only",